From 9851d96c0696a11aa211d6d54b76aa7fa87f7b13 Mon Sep 17 00:00:00 2001 From: snoppy Date: Fri, 29 Mar 2024 10:21:29 +0800 Subject: [PATCH 1/9] chore: fix typos --- btcutil/hdkeychain/README.md | 2 +- mempool/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/btcutil/hdkeychain/README.md b/btcutil/hdkeychain/README.md index 33eba3ce16..2101ed4d81 100644 --- a/btcutil/hdkeychain/README.md +++ b/btcutil/hdkeychain/README.md @@ -17,7 +17,7 @@ report. - Full BIP0032 implementation - Single type for private and public extended keys -- Convenient cryptograpically secure seed generation +- Convenient cryptographically secure seed generation - Simple creation of master nodes - Support for multi-layer derivation - Easy serialization and deserialization for both private and public extended diff --git a/mempool/README.md b/mempool/README.md index 5f1e4a4cd1..85c03993c2 100644 --- a/mempool/README.md +++ b/mempool/README.md @@ -7,7 +7,7 @@ mempool Package mempool provides a policy-enforced pool of unmined bitcoin transactions. -A key responsbility of the bitcoin network is mining user-generated transactions +A key responsibility of the bitcoin network is mining user-generated transactions into blocks. In order to facilitate this, the mining process relies on having a readily-available source of transactions to include in a block that is being solved. From 31647e46ecbac0dfc4b6432bd3d3cc0136193740 Mon Sep 17 00:00:00 2001 From: ffranr Date: Tue, 2 Apr 2024 19:27:10 +0100 Subject: [PATCH 2/9] btcec: add missing doc comments --- btcec/pubkey.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index c4b0680a7a..bff1b24b5f 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -10,6 +10,8 @@ import ( // These constants define the lengths of serialized public keys. const ( + // PubKeyBytesLenCompressed is the bytes length of a serialized compressed + // public key. PubKeyBytesLenCompressed = 33 ) From 665eeb52b19fce48a025afcde01ffdd781672299 Mon Sep 17 00:00:00 2001 From: ffranr Date: Tue, 2 Apr 2024 19:36:47 +0100 Subject: [PATCH 3/9] btcec: add new type `SerializedKey` This commit adds a new type called `SerializedKey`. A serialized type is useful when using public keys as map keys. This is because functionally identical public keys can have different internal representations. These differences would cause the map to treat them as different keys. --- btcec/pubkey.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index bff1b24b5f..2c3a5ccbef 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -51,3 +51,38 @@ type PublicKey = secp.PublicKey func NewPublicKey(x, y *FieldVal) *PublicKey { return secp.NewPublicKey(x, y) } + +// SerializedKey is a type for representing a public key in its compressed +// serialized form. +// +// NOTE: This type is useful when using public keys as keys in maps. +type SerializedKey [PubKeyBytesLenCompressed]byte + +// ToPubKey returns the public key parsed from the serialized key. +func (s SerializedKey) ToPubKey() (*PublicKey, error) { + return ParsePubKey(s[:]) +} + +// SchnorrSerialized returns the Schnorr serialized, x-only 32-byte +// representation of the serialized key. +func (s SerializedKey) SchnorrSerialized() [32]byte { + var serializedSchnorr [32]byte + copy(serializedSchnorr[:], s[1:]) + return serializedSchnorr +} + +// CopyBytes returns a copy of the underlying array as a byte slice. +func (s SerializedKey) CopyBytes() []byte { + c := make([]byte, PubKeyBytesLenCompressed) + copy(c, s[:]) + + return c +} + +// ToSerialized serializes a public key into its compressed form. +func ToSerialized(pubKey *PublicKey) SerializedKey { + var serialized SerializedKey + copy(serialized[:], pubKey.SerializeCompressed()) + + return serialized +} From c9c87951608158a5cb75c37bfa96a60eefcdb6eb Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 8 Apr 2024 17:45:24 +0900 Subject: [PATCH 4/9] blockchain: add Equals method to blockNode Helper function for the added IsAncestor in the follow up commit. Returns true if all the fields (except for parent and ancestor) are equal. --- blockchain/blockindex.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index ca3235f79f..9bfa3348cd 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -135,6 +135,20 @@ func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { return &node } +// Equals compares all the fields of the block node except for the parent and +// ancestor and returns true if they're equal. +func (node *blockNode) Equals(other *blockNode) bool { + return node.hash == other.hash && + node.workSum.Cmp(other.workSum) == 0 && + node.height == other.height && + node.version == other.version && + node.bits == other.bits && + node.nonce == other.nonce && + node.timestamp == other.timestamp && + node.merkleRoot == other.merkleRoot && + node.status == other.status +} + // Header constructs a block header from the node and returns it. // // This function is safe for concurrent access. From bc6396ddfd097f93e2eaf0d1346ab80735eaa169 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 19 Dec 2022 14:57:33 +0900 Subject: [PATCH 5/9] blockchain: Add IsAncestor method to blockNode IsAncestor() provides functionality for testing if a block node is an ancestor of anther block node. --- blockchain/blockindex.go | 22 ++++++ blockchain/chain_test.go | 156 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 9bfa3348cd..5273cb488b 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -274,6 +274,28 @@ func (node *blockNode) RelativeAncestorCtx(distance int32) HeaderCtx { return ancestor } +// IsAncestor returns if the other node is an ancestor of this block node. +func (node *blockNode) IsAncestor(otherNode *blockNode) bool { + // Return early as false if the otherNode is nil. + if otherNode == nil { + return false + } + + ancestor := node.Ancestor(otherNode.height) + if ancestor == nil { + return false + } + + // If the otherNode has the same height as me, then the returned + // ancestor will be me. Return false since I'm not an ancestor of me. + if node.height == ancestor.height { + return false + } + + // Return true if the fetched ancestor is other node. + return ancestor.Equals(otherNode) +} + // RelativeAncestor returns the ancestor block node a relative 'distance' blocks // before this node. This is equivalent to calling Ancestor with the node's // height minus provided distance. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index cd5c761bc4..259a643f3c 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -1155,3 +1155,159 @@ func TestChainTips(t *testing.T) { } } } + +func TestIsAncestor(t *testing.T) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + branch1Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch1Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + + branch2Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch2Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValidateFailed) + chain.index.AddNode(node) + } + + // Is 1 an ancestor of 3? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue := branch0Nodes[2].IsAncestor(branch0Nodes[0]) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. Node %s is an ancestor of node %s but got false", + branch0Nodes[0].hash.String(), branch0Nodes[2].hash.String()) + } + + // Is 1 an ancestor of 2? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch0Nodes[1].IsAncestor(branch0Nodes[0]) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. Node %s is an ancestor of node %s but got false", + branch0Nodes[0].hash.String(), branch0Nodes[1].hash.String()) + } + + // Is the genesis an ancestor of 1? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch0Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch0Nodes[0].hash.String()) + } + + // Is the genesis an ancestor of 1a? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch1Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch1Nodes[0].hash.String()) + } + + // Is the genesis an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch2Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch2Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1a? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse := branch1Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch1Nodes[0].hash.String(), + branch0Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch2Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch2Nodes[0].hash.String(), + branch0Nodes[0].hash.String()) + } + + // Is 1a an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch2Nodes[0].IsAncestor(branch1Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch2Nodes[0].hash.String(), + branch1Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch0Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node is not an ancestor of itself but got true for node %s", + branch0Nodes[0].hash.String()) + } + + // Is the geneis an ancestor of genesis? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = chain.bestChain.Genesis().IsAncestor(chain.bestChain.Genesis()) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node is not an ancestor of itself but got true for node %s", + chain.bestChain.Genesis().hash.String()) + } + + // Is a block from another chain an ancestor of 1b? + fakeChain := newFakeChain(&chaincfg.TestNet3Params) + shouldBeFalse = branch2Nodes[0].IsAncestor(fakeChain.bestChain.Genesis()) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different chain than "+ + "node %s but got true", fakeChain.bestChain.Genesis().hash.String(), + branch2Nodes[0].hash.String()) + } +} From 2f4ff8447d51872bc2704bd31fe3b13bfb9a0143 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Wed, 10 Apr 2024 22:08:30 +0800 Subject: [PATCH 6/9] fix some typos and make OP_DATA_20 explicit in comment (#2080) --- txscript/doc.go | 2 +- txscript/engine.go | 2 +- txscript/script.go | 2 +- txscript/sigvalidate.go | 2 +- txscript/standard.go | 4 ++-- txscript/taproot.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/txscript/doc.go b/txscript/doc.go index d6eddd5a65..957c91947c 100644 --- a/txscript/doc.go +++ b/txscript/doc.go @@ -17,7 +17,7 @@ bitcoin transaction scripts. Bitcoin transaction scripts are written in a stack-base, FORTH-like language. The bitcoin script language consists of a number of opcodes which fall into -several categories such pushing and popping data to and from the stack, +several categories such as pushing and popping data to and from the stack, performing basic and bitwise arithmetic, conditional branching, comparing hashes, and checking cryptographic signatures. Scripts are processed from left to right and intentionally do not provide loops. diff --git a/txscript/engine.go b/txscript/engine.go index 1458728f72..3725845104 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -605,7 +605,7 @@ func (vm *Engine) verifyWitnessProgram(witness wire.TxWitness) error { return scriptError(ErrWitnessProgramWrongLength, errStr) } - // We're attempting to to verify a taproot input, and the witness + // We're attempting to verify a taproot input, and the witness // program data push is of the expected size, so we'll be looking for a // normal key-path spend, or a merkle proof for a tapscript with // execution afterwards. diff --git a/txscript/script.go b/txscript/script.go index 13d6c42711..1448c57e2f 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -178,7 +178,7 @@ func DisasmString(script []byte) (string, error) { // removeOpcodeRaw will return the script after removing any opcodes that match // `opcode`. If the opcode does not appear in script, the original script will // be returned unmodified. Otherwise, a new script will be allocated to contain -// the filtered script. This metehod assumes that the script parses +// the filtered script. This method assumes that the script parses // successfully. // // NOTE: This function is only valid for version 0 scripts. Since the function diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index bda612a4e0..7b56ff6971 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -385,7 +385,7 @@ func (t *taprootSigVerifier) Verify() bool { var _ signatureVerifier = (*taprootSigVerifier)(nil) // baseTapscriptSigVerifier verifies a signature for an input spending a -// tapscript leaf from the prevoous output. +// tapscript leaf from the previous output. type baseTapscriptSigVerifier struct { *taprootSigVerifier diff --git a/txscript/standard.go b/txscript/standard.go index 5ef2ad167f..a25e32df92 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -153,7 +153,7 @@ func isPubKeyScript(script []byte) bool { // is a standard pay-to-pubkey-hash script. It will return nil otherwise. func extractPubKeyHash(script []byte) []byte { // A pay-to-pubkey-hash script is of the form: - // OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG + // OP_DUP OP_HASH160 OP_DATA_20 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG if len(script) == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && @@ -181,7 +181,7 @@ func isPubKeyHashScript(script []byte) bool { // versions. func extractScriptHash(script []byte) []byte { // A pay-to-script-hash script is of the form: - // OP_HASH160 <20-byte scripthash> OP_EQUAL + // OP_HASH160 OP_DATA_20 <20-byte scripthash> OP_EQUAL if len(script) == 23 && script[0] == OP_HASH160 && script[1] == OP_DATA_20 && diff --git a/txscript/taproot.go b/txscript/taproot.go index 3776bf37a3..9e95e0a81f 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -65,7 +65,7 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, // program. rawKey := witnessProgram - // Extract the annex if it exists, so we can compute the proper proper + // Extract the annex if it exists, so we can compute the proper // sighash below. var annex []byte witness := tx.TxIn[inputIndex].Witness From 9f93dc1842557e03387d2856c51c589a494d2737 Mon Sep 17 00:00:00 2001 From: goodfirm <166383463+goodfirm@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:59:42 +0800 Subject: [PATCH 7/9] chore: fix function names in comment (#2163) Signed-off-by: goodfirm --- cmd/addblock/config.go | 2 +- cmd/gencerts/gencerts.go | 2 +- config.go | 2 +- database/ffldb/db.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/addblock/config.go b/cmd/addblock/config.go index ffcc0eca79..d49df0a11d 100644 --- a/cmd/addblock/config.go +++ b/cmd/addblock/config.go @@ -45,7 +45,7 @@ type config struct { TxIndex bool `long:"txindex" description:"Build a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index 328d5ea714..0c91b6fb85 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -90,7 +90,7 @@ func cleanAndExpandPath(path string) string { return filepath.Clean(os.ExpandEnv(path)) } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/config.go b/config.go index f8aad70cf8..a566f79e3d 100644 --- a/config.go +++ b/config.go @@ -384,7 +384,7 @@ func parseCheckpoints(checkpointStrings []string) ([]chaincfg.Checkpoint, error) return checkpoints, nil } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/database/ffldb/db.go b/database/ffldb/db.go index 8fc4d32646..3e96bfc738 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -2071,7 +2071,7 @@ func (db *db) Close() error { return closeErr } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { From 64c9011d727a1e5110f8a867051d96ada1dbcea8 Mon Sep 17 00:00:00 2001 From: youngxhui Date: Wed, 10 Apr 2024 10:00:23 -0700 Subject: [PATCH 8/9] Update developer_resources.md (#2158) fix btcutil link error --- docs/developer_resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer_resources.md b/docs/developer_resources.md index c595c8330e..328e1b225a 100644 --- a/docs/developer_resources.md +++ b/docs/developer_resources.md @@ -28,7 +28,7 @@ * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - Package mempool provides a policy-enforced pool of unmined bitcoin transactions. - * [btcutil](https://github.com/btcsuite/btcd/btcutil) - Provides Bitcoin-specific + * [btcutil](https://github.com/btcsuite/btcd/tree/master/btcutil) - Provides Bitcoin-specific convenience functions and types * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - Provides a generic hash type and associated functions that allows the From 569155bc6a502f45b4a514bc6b9d5f814a980b6c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <5462944+youngjoon-lee@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:37:44 +0300 Subject: [PATCH 9/9] doc: fix config documentation for `AgentWhitelist` (#2140) --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index a566f79e3d..486ce293a3 100644 --- a/config.go +++ b/config.go @@ -101,7 +101,7 @@ type config struct { AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` AddrIndex bool `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"` AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` - AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."` + AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the whitelist, and an empty whitelist will allow all agents that do not fail the blacklist."` BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"`