diff --git a/pkg/core/block/block.go b/pkg/core/block/block.go index 9c53ca4bd..d06e44575 100644 --- a/pkg/core/block/block.go +++ b/pkg/core/block/block.go @@ -46,8 +46,8 @@ func (b *Block) Header() *Header { } } -// computeMerkleTree computes Merkle tree based on actual block's data. -func (b *Block) computeMerkleTree() util.Uint256 { +// ComputeMerkleRoot computes Merkle tree root hash based on actual block's data. +func (b *Block) ComputeMerkleRoot() util.Uint256 { hashes := make([]util.Uint256, len(b.Transactions)+1) hashes[0] = b.ConsensusData.Hash() for i, tx := range b.Transactions { @@ -59,27 +59,7 @@ func (b *Block) computeMerkleTree() util.Uint256 { // RebuildMerkleRoot rebuilds the merkleroot of the block. func (b *Block) RebuildMerkleRoot() { - b.MerkleRoot = b.computeMerkleTree() -} - -// Verify verifies the integrity of the block. -func (b *Block) Verify() error { - if b.Transactions != nil { - hashes := map[util.Uint256]bool{} - for _, tx := range b.Transactions { - if !hashes[tx.Hash()] { - hashes[tx.Hash()] = true - } else { - return errors.New("transaction duplication is not allowed") - } - } - } - - merkle := b.computeMerkleTree() - if !b.MerkleRoot.Equals(merkle) { - return errors.New("MerkleRoot mismatch") - } - return nil + b.MerkleRoot = b.ComputeMerkleRoot() } // NewBlockFromTrimmedBytes returns a new block from trimmed data. @@ -173,7 +153,6 @@ func (b *Block) DecodeBinary(br *io.BinReader) { if br.Err != nil { return } - br.Err = b.Verify() } // EncodeBinary encodes the block to the given BinWriter, implementing diff --git a/pkg/core/block/block_test.go b/pkg/core/block/block_test.go index 3e9c37317..02df2403e 100644 --- a/pkg/core/block/block_test.go +++ b/pkg/core/block/block_test.go @@ -108,17 +108,6 @@ func TestHashBlockEqualsHashHeader(t *testing.T) { assert.Equal(t, block.Hash(), block.Header().Hash()) } -func TestBlockVerify(t *testing.T) { - block := newDumbBlock() - assert.NotNil(t, block.Verify()) - block.RebuildMerkleRoot() - assert.Nil(t, block.Verify()) - - block.Transactions = []*transaction.Transaction{} - block.RebuildMerkleRoot() - assert.Nil(t, block.Verify()) -} - func TestBinBlockDecodeEncode(t *testing.T) { // transaction taken from mainnet: 2000000 rawtx := "0000000005440c786a66aaebf472aacb1d1db19d5b494c6a9226ea91bf5cf0e63a6605138cde5064efb81bc6539620b9e6d6d7c74f97d415b922c4fb4bb1833ce6a97a9d61f962fb7301000065f000005d12ac6c589d59f92e82d8bf60659cb716ffc1f101fd4a010c4011ff5d2138cf546d112ef712ee8a15277f7b6f1d5d2564b97497ac155782e6089cd3005dc9de81a8b22bb2f1c3a2edbac55e01581cb27980fdedf3a8bc57fa470c40657253c374a48da773fc653591f282a63a60695f29ab6c86300020ed505a019e5563e1be493efa71bdde37b16b4ec3f5f6dc2d2a2550151b020176b4dbe7afe40c403efdc559cb6bff135fd79138267db897c6fded01e3a0f15c0fb1c337359935d65e7ac49239f020951a74a96e11e73d225c9789953ffec40d5f7c9a84707b1d9a0c402804f24ab8034fa41223977ba48883eb94951184e31e5739872daf4f65461de3196ebf333f6d7dc4aff0b7b2143793179415f50a715484aba4e33b97dc636e150c40ed6b2ffeaef97eef746815ad16f5b8aed743892e93f7216bb744eb5c2f4cad91ae291919b61cd9a8d50fe85630d5e010c49a01ed687727c3ae5a7e17d4da213afdfd00150c2103009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a20c21030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba0c210214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff010c2103408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a2594778060c2102a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b0c2102ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd0c2102f889ecd43c5126ff1932d75fa87dea34fc95325fb724db93c8f79fe32cc3f180170b41138defaf0202c1353ed4e94d0cbc00be80024f7673890000000000261c130000000000e404210001f813c2cc8e18bbe4b3b87f8ef9105b50bb93918e01005d0300743ba40b0000000c14aa07cc3f2193a973904a09a6e60b87f1f96273970c14f813c2cc8e18bbe4b3b87f8ef9105b50bb93918e13c00c087472616e736665720c14bcaf41d684c7d4ad6ee0d99da9707b9d1f0c8e6641627d5b523801420c402360bbf64b9644c25f066dbd406454b07ab9f56e8e25d92d90c96c598f6c29d97eabdcf226f3575481662cfcdd064ee410978e5fae3f09a2f83129ba9cd82641290c2103caf763f91d3691cba5b5df3eb13e668fdace0295b37e2e259fd0fb152d354f900b4195440d78" @@ -157,6 +146,9 @@ func TestBinBlockDecodeEncode(t *testing.T) { assert.NoError(t, err) assert.Equal(t, rawtx, hex.EncodeToString(data)) + // update hidden hash value. + _ = b.ConsensusData.Hash() + testserdes.MarshalUnmarshalJSON(t, b, New(netmode.TestNet)) } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 14e0b6aaa..71744e935 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -423,9 +423,9 @@ func (bc *Blockchain) AddBlock(block *block.Block) error { } } if bc.config.VerifyBlocks { - err := block.Verify() - if err != nil { - return fmt.Errorf("block %s is invalid: %w", block.Hash().StringLE(), err) + merkle := block.ComputeMerkleRoot() + if !block.MerkleRoot.Equals(merkle) { + return errors.New("invalid block: MerkleRoot mismatch") } mp = mempool.New(len(block.Transactions)) for _, tx := range block.Transactions { diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index 5845b3065..f8cb2f87f 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -161,7 +161,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, serverResponse: b1Verbose, result: func(c *Client) interface{} { - return getResultBlock1() + res := getResultBlock1() + // update hidden hash value. + _ = res.Block.ConsensusData.Hash() + return res }, }, { @@ -190,7 +193,10 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ }, serverResponse: b1Verbose, result: func(c *Client) interface{} { - return getResultBlock1() + res := getResultBlock1() + // update hidden hash value. + _ = res.Block.ConsensusData.Hash() + return res }, }, },