From e7f6edaa6db06c4aa61dca3ea6241e327fae199e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 6 Aug 2019 00:53:29 -0500 Subject: [PATCH] blockchain: Use standalone module for merkle calcs. This updates blockchain to make use of the optimized merkle root calculation functions in the standalone module. It also deprecates the related exported functions in the blockchain module so they can be removed in the next major version. Finally, the following direct dependencies are updated as required: - github.com/decred/dcrd/blockchain/standalone@v1.0.0 --- blockchain/go.mod | 4 +--- blockchain/go.sum | 12 ++---------- blockchain/merkle.go | 6 ++++++ blockchain/merkle_test.go | 11 ----------- blockchain/validate.go | 15 +++++++-------- 5 files changed, 16 insertions(+), 32 deletions(-) delete mode 100644 blockchain/merkle_test.go diff --git a/blockchain/go.mod b/blockchain/go.mod index 68f43410..8b8d7b34 100644 --- a/blockchain/go.mod +++ b/blockchain/go.mod @@ -5,6 +5,7 @@ go 1.11 require ( github.com/dchest/siphash v1.2.1 // indirect github.com/decred/dcrd/blockchain/stake v1.1.0 + github.com/decred/dcrd/blockchain/standalone v1.0.0 github.com/decred/dcrd/chaincfg v1.5.1 github.com/decred/dcrd/chaincfg/chainhash v1.0.1 github.com/decred/dcrd/database v1.0.3 @@ -15,7 +16,4 @@ require ( github.com/decred/dcrd/txscript v1.1.0 github.com/decred/dcrd/wire v1.2.0 github.com/decred/slog v1.0.0 - github.com/onsi/ginkgo v1.7.0 // indirect - github.com/onsi/gomega v1.4.3 // indirect - gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/blockchain/go.sum b/blockchain/go.sum index 79c33f6d..241db66a 100644 --- a/blockchain/go.sum +++ b/blockchain/go.sum @@ -20,6 +20,8 @@ github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YI github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= github.com/decred/dcrd/blockchain/stake v1.1.0 h1:kCxZdQ2/UfcD+XjE3wlCv0vLKWR9ZFtjbbTTpudb74o= github.com/decred/dcrd/blockchain/stake v1.1.0/go.mod h1:WRuaml4bcyZYza1NT3qizlLcQwMIcAQRENvZVb2t884= +github.com/decred/dcrd/blockchain/standalone v1.0.0 h1:bPkFgSV7/NeZI+ZEGhaOP+XccCUBTIJb3YTf8dMwe8g= +github.com/decred/dcrd/blockchain/standalone v1.0.0/go.mod h1:U5lOleFSi1nL7heSdLgEtuvg0udS1p3cvHxvLJbihfE= github.com/decred/dcrd/chaincfg v1.1.1/go.mod h1:UlGtnp8Xx9YK+etBTybGjoFGoGXSw2bxZQuAnwfKv6I= github.com/decred/dcrd/chaincfg v1.2.0 h1:Vj0xr85wmqOdQDxKLkpP9TqwK1RykqY2eC0fWcCsl0k= github.com/decred/dcrd/chaincfg v1.2.0/go.mod h1:kpoGTMIriKn5hHRSu5b65+Q9LlGUdbQcMzGujac1BVs= @@ -50,7 +52,6 @@ github.com/decred/dcrd/dcrec/secp256k1 v1.0.2 h1:awk7sYJ4pGWmtkiGHFfctztJjHMKGLV github.com/decred/dcrd/dcrec/secp256k1 v1.0.2/go.mod h1:CHTUIVfmDDd0KFVFpNX1pFVCBUegxW387nN0IGwNKR0= github.com/decred/dcrd/dcrutil v1.1.1 h1:zOkGiumN/JkobhAgpG/zfFgUoolGKVGYT5na1hbYUoE= github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhluiNwwY6yBJS4= -github.com/decred/dcrd/dcrutil v1.2.0/go.mod h1:tUNHS2gj7ApeEVS8gb6O+4wJW7w3O2MSRyRdcjW1JxU= github.com/decred/dcrd/dcrutil v1.3.0 h1:LtKIiDnq925yJT/4OpIKKiU9/WaxfD9LfhxrpLSi0Qs= github.com/decred/dcrd/dcrutil v1.3.0/go.mod h1:7fUT70QAarhDwQK62g92uDbbYpjXlXngpy5RBiecufo= github.com/decred/dcrd/gcs v1.0.2 h1:wZjxeC9WPBoRApaAQpBrzvN9NA0iS2KWrTJa9IiDgc8= @@ -79,12 +80,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= golang.org/x/crypto v0.0.0-20180718160520-a2144134853f h1:lRy+hhwk7YT7MsKejxuz0C5Q1gk6p/QoPQYEmKmGFb8= golang.org/x/crypto v0.0.0-20180718160520-a2144134853f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -93,8 +90,6 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180808004115-f9ce57c11b24 h1:mEsFm194MmS9vCwxFy+zwu0EU7ZkxxMD1iH++vmGdUY= golang.org/x/net v0.0.0-20180808004115-f9ce57c11b24/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= @@ -103,7 +98,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTm golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c h1:uHnKXcvx6SNkuwC+nrzxkJ+TpPwZOtumbhWrrOYN5YA= golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e h1:njOxP/wVblhCLIUhjHXf6X+dzTt5OQ3vMQo9mkOIKIo= golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -120,5 +114,3 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/blockchain/merkle.go b/blockchain/merkle.go index 47df1d53..505c4c18 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -30,6 +30,8 @@ func nextPowerOfTwo(n int) int { // HashMerkleBranches takes two hashes, treated as the left and right tree // nodes, and returns the hash of their concatenation. This is a helper // function used to aid in the generation of a merkle tree. +// +// Deprecated: Use standalone.CalcMerkleRoot instead. func HashMerkleBranches(left *chainhash.Hash, right *chainhash.Hash) *chainhash.Hash { // Concatenate the left and right nodes. var hash [chainhash.HashSize * 2]byte @@ -96,6 +98,8 @@ func populateMerkleStore(offset int, merkles []*chainhash.Hash) { // are calculated by concatenating the left node with itself before hashing. // Since this function uses nodes that are pointers to the hashes, empty nodes // will be nil. +// +// Deprecated: Use standalone.CalcTxTreeMerkleRoot instead. func BuildMerkleTreeStore(transactions []*dcrutil.Tx) []*chainhash.Hash { // If there's an empty stake tree, return totally zeroed out merkle tree root // only. @@ -125,6 +129,8 @@ func BuildMerkleTreeStore(transactions []*dcrutil.Tx) []*chainhash.Hash { // BuildMsgTxMerkleTreeStore is identical to BuildMerkleTreeStore but takes a // slice of the wire.MsgTx transaction type instead of the dcrutil.Tx wrapper. // See BuildMerkleTreeStore for more details. +// +// Deprecated: Use standalone.CalcTxTreeMerkleRoot instead. func BuildMsgTxMerkleTreeStore(transactions []*wire.MsgTx) []*chainhash.Hash { // If there's an empty stake tree, return totally zeroed out merkle tree root // only. diff --git a/blockchain/merkle_test.go b/blockchain/merkle_test.go deleted file mode 100644 index b73488ab..00000000 --- a/blockchain/merkle_test.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2013-2014 The btcsuite developers -// Copyright (c) 2015-2018 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package blockchain - -// TODO Make tests for merkle root calculation. Merkle root calculation and -// corruption is already well tested in the blockchain error unit tests and -// reorganization unit tests, but it'd be nice to have a specific test for -// these functions and their error paths. diff --git a/blockchain/validate.go b/blockchain/validate.go index 449dffea..d543878a 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -14,6 +14,7 @@ import ( "time" "github.com/decred/dcrd/blockchain/stake" + "github.com/decred/dcrd/blockchain/standalone" "github.com/decred/dcrd/chaincfg" "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/database" @@ -841,22 +842,20 @@ func checkBlockSanity(block *dcrutil.Block, timeSource MedianTimeSource, flags B // checks. Bitcoind builds the tree here and checks the merkle root // after the following checks, but there is no reason not to check the // merkle root matches here. - merkles := BuildMerkleTreeStore(block.Transactions()) - calculatedMerkleRoot := merkles[len(merkles)-1] - if !header.MerkleRoot.IsEqual(calculatedMerkleRoot) { + wantMerkleRoot := standalone.CalcTxTreeMerkleRoot(msgBlock.Transactions) + if header.MerkleRoot != wantMerkleRoot { str := fmt.Sprintf("block merkle root is invalid - block "+ "header indicates %v, but calculated value is %v", - header.MerkleRoot, calculatedMerkleRoot) + header.MerkleRoot, wantMerkleRoot) return ruleError(ErrBadMerkleRoot, str) } // Build the stake tx tree merkle root too and check it. - merkleStake := BuildMerkleTreeStore(block.STransactions()) - calculatedStakeMerkleRoot := merkleStake[len(merkleStake)-1] - if !header.StakeRoot.IsEqual(calculatedStakeMerkleRoot) { + wantStakeRoot := standalone.CalcTxTreeMerkleRoot(msgBlock.STransactions) + if header.StakeRoot != wantStakeRoot { str := fmt.Sprintf("block stake merkle root is invalid - block"+ " header indicates %v, but calculated value is %v", - header.StakeRoot, calculatedStakeMerkleRoot) + header.StakeRoot, wantStakeRoot) return ruleError(ErrBadMerkleRoot, str) }