From 1502825c9528c0af07ffa03f39fe7f68ac3d2ca9 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:25:48 +0200 Subject: [PATCH] Move atomic hash from Block to Header (#12462) Cherry pick #11513 into `release/2.61` Co-authored-by: Alex Sharov --- cmd/devnet/blocks/waiter.go | 4 +- consensus/aura/aura.go | 2 +- consensus/clique/clique.go | 9 +-- consensus/clique/verifier.go | 2 +- consensus/consensus.go | 3 - consensus/merge/merge.go | 4 +- core/chain_makers.go | 15 +++-- core/types/block.go | 63 +++++++++++++------ core/types/block_test.go | 4 +- core/vm/runtime/runtime_test.go | 3 +- eth/stagedsync/stage_mining_finish.go | 2 +- go.mod | 1 + go.sum | 2 + polygon/bor/bor.go | 16 ++--- .../statedb_insert_chain_transaction_test.go | 54 ++++++++-------- turbo/execution/eth1/eth1_utils/grpc_test.go | 7 ++- .../stages/headerdownload/header_algo_test.go | 13 ++-- 17 files changed, 108 insertions(+), 96 deletions(-) diff --git a/cmd/devnet/blocks/waiter.go b/cmd/devnet/blocks/waiter.go index 05b4280ba1a..0c1119faadb 100644 --- a/cmd/devnet/blocks/waiter.go +++ b/cmd/devnet/blocks/waiter.go @@ -104,7 +104,7 @@ func BlockWaiter(ctx context.Context, handler BlockHandler) (Waiter, context.Can var err error - headers := make(chan types.Header) + headers := make(chan *types.Header) waiter.headersSub, err = node.Subscribe(ctx, requests.Methods.ETHNewHeads, headers) if err != nil { @@ -117,7 +117,7 @@ func BlockWaiter(ctx context.Context, handler BlockHandler) (Waiter, context.Can return wait{waiter}, cancel } -func (c *blockWaiter) receive(ctx context.Context, node devnet.Node, headers chan types.Header) { +func (c *blockWaiter) receive(ctx context.Context, node devnet.Node, headers chan *types.Header) { blockMap := map[libcommon.Hash]*requests.Block{} defer close(c.result) diff --git a/consensus/aura/aura.go b/consensus/aura/aura.go index b27b1740ffb..2da332fc9c3 100644 --- a/consensus/aura/aura.go +++ b/consensus/aura/aura.go @@ -846,7 +846,7 @@ func (c *AuRa) FinalizeAndAssemble(config *chain.Config, header *types.Header, s } // Assemble and return the final block for sealing - return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals, requests), outTxs, outReceipts, nil + return types.NewBlockForAsembling(header, outTxs, uncles, outReceipts, withdrawals, requests), outTxs, outReceipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 7c9a91c88ee..060d267c932 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -67,7 +67,7 @@ var ( NonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer nonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer. - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. + emptyUncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. DiffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures @@ -381,8 +381,6 @@ func (c *Clique) Finalize(config *chain.Config, header *types.Header, state *sta txs types.Transactions, uncles []*types.Header, r types.Receipts, withdrawals []*types.Withdrawal, requests types.Requests, chain consensus.ChainReader, syscall consensus.SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, types.Requests, error) { - // No block rewards in PoA, so the state remains as is and uncles are dropped - header.UncleHash = types.CalcUncleHash(nil) return txs, r, nil, nil } @@ -391,11 +389,8 @@ func (c *Clique) Finalize(config *chain.Config, header *types.Header, state *sta func (c *Clique) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Header, state *state.IntraBlockState, txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests types.Requests, chain consensus.ChainReader, syscall consensus.SystemCall, call consensus.Call, logger log.Logger, ) (*types.Block, types.Transactions, types.Receipts, error) { - // No block rewards in PoA, so the state remains as is and uncles are dropped - header.UncleHash = types.CalcUncleHash(nil) - // Assemble and return the final block for sealing - return types.NewBlock(header, txs, nil, receipts, withdrawals, requests), txs, receipts, nil + return types.NewBlockForAsembling(header, txs, nil, receipts, withdrawals, requests), txs, receipts, nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/clique/verifier.go b/consensus/clique/verifier.go index 2c8686a70ce..ceeb52f98a3 100644 --- a/consensus/clique/verifier.go +++ b/consensus/clique/verifier.go @@ -67,7 +67,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H return errInvalidMixDigest } // Ensure that the block doesn't contain any uncles which are meaningless in PoA - if header.UncleHash != uncleHash { + if header.UncleHash != emptyUncleHash { return errInvalidUncleHash } // Ensure that the block's difficulty is meaningful (may not be correct at this point) diff --git a/consensus/consensus.go b/consensus/consensus.go index a2b9176acc5..e3600e39ed3 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -156,9 +156,6 @@ type EngineWriter interface { // Finalize runs any post-transaction state modifications (e.g. block rewards) // but does not assemble the block. - // - // Note: The block header and state database might be updated to reflect any - // consensus rules that happen at finalization (e.g. block rewards). Finalize(config *chain.Config, header *types.Header, state *state.IntraBlockState, txs types.Transactions, uncles []*types.Header, receipts types.Receipts, withdrawals []*types.Withdrawal, requests types.Requests, chain ChainReader, syscall SystemCall, logger log.Logger, ) (types.Transactions, types.Receipts, types.Requests, error) diff --git a/consensus/merge/merge.go b/consensus/merge/merge.go index 97f1697c2cf..c09624755d1 100644 --- a/consensus/merge/merge.go +++ b/consensus/merge/merge.go @@ -214,7 +214,7 @@ func (s *Merge) FinalizeAndAssemble(config *chain.Config, header *types.Header, rs = make(types.Requests, 0) } } - return types.NewBlock(header, outTxs, uncles, outReceipts, withdrawals, rs), outTxs, outReceipts, nil + return types.NewBlockForAsembling(header, outTxs, uncles, outReceipts, withdrawals, rs), outTxs, outReceipts, nil } func (s *Merge) SealHash(header *types.Header) (hash libcommon.Hash) { @@ -307,7 +307,7 @@ func (s *Merge) verifyHeader(chain consensus.ChainHeaderReader, header, parent * } func (s *Merge) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - if !misc.IsPoSHeader(block.Header()) { + if !misc.IsPoSHeader(block.HeaderNoCopy()) { return s.eth1Engine.Seal(chain, block, results, stop) } return nil diff --git a/core/chain_makers.go b/core/chain_makers.go index e8e502e2cc3..2de165ef70e 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -391,7 +391,7 @@ func GenerateChain(config *chain.Config, parent *types.Block, engine consensus.E return nil, nil, fmt.Errorf("call to CalcTrieRoot: %w", err) } // Recreating block to make sure Root makes it into the header - block := types.NewBlock(b.header, b.txs, b.uncles, b.receipts, nil /* withdrawals */, nil /*requests*/) + block := types.NewBlockForAsembling(b.header, b.txs, b.uncles, b.receipts, nil /* withdrawals */, nil /*requests*/) return block, b.receipts, nil } return nil, nil, fmt.Errorf("no engine to generate blocks") @@ -578,13 +578,12 @@ func CalcHashRootForTests(tx kv.RwTx, header *types.Header, histV4 bool) (hashRo } func MakeEmptyHeader(parent *types.Header, chainConfig *chain.Config, timestamp uint64, targetGasLimit *uint64) *types.Header { - header := &types.Header{ - Root: parent.Root, - ParentHash: parent.Hash(), - Number: new(big.Int).Add(parent.Number, libcommon.Big1), - Difficulty: libcommon.Big0, - Time: timestamp, - } + header := types.NewEmptyHeaderForAssembling() + header.Root = parent.Root + header.ParentHash = parent.Hash() + header.Number = new(big.Int).Add(parent.Number, libcommon.Big1) + header.Difficulty = libcommon.Big0 + header.Time = timestamp parentGasLimit := parent.GasLimit // Set baseFee and GasLimit if we are on an EIP-1559 chain diff --git a/core/types/block.go b/core/types/block.go index 766094bd50f..b7de7f3b614 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -111,6 +111,19 @@ type Header struct { Verkle bool VerkleProof []byte VerkleKeyVals []verkle.KeyValuePair + + // by default all headers are immutable + // but assembling/mining may use `NewEmptyHeaderForAssembling` to create temporary mutable Header object + // then pass it to `block.WithSeal(header)` - to produce new block with immutable `Header` + mutable bool + hash atomic.Pointer[libcommon.Hash] +} + +// NewEmptyHeaderForAssembling - returns mutable header object - for assembling/sealing/etc... +// when sealing done - `block.WithSeal(header)` called - which producing new block with immutable `Header` +// by default all headers are immutable +func NewEmptyHeaderForAssembling() *Header { + return &Header{mutable: true} } func (h *Header) EncodingSize() int { @@ -564,8 +577,17 @@ type headerMarshaling struct { // Hash returns the block hash of the header, which is simply the keccak256 hash of its // RLP encoding. -func (h *Header) Hash() libcommon.Hash { - return rlpHash(h) +func (h *Header) Hash() (hash libcommon.Hash) { + if !h.mutable { + if hash := h.hash.Load(); hash != nil { + return *hash + } + } + hash = rlpHash(h) + if !h.mutable { + h.hash.Store(&hash) + } + return hash } var headerSize = common.StorageSize(reflect.TypeOf(Header{}).Size()) @@ -681,7 +703,6 @@ type Block struct { requests Requests // caches - hash atomic.Pointer[libcommon.Hash] size atomic.Uint64 } @@ -1055,14 +1076,22 @@ func NewBlock(header *Header, txs []Transaction, uncles []*Header, receipts []*R } } + b.header.mutable = false //Force immutability of block and header. Use `NewBlockForAsembling` if you need mutable block + return b +} + +// NewBlockForAsembling - creating new block - which allow mutation of fileds. Use it for block-assembly +func NewBlockForAsembling(header *Header, txs []Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal, requests Requests) *Block { + b := NewBlock(header, txs, uncles, receipts, withdrawals, requests) + b.header.mutable = true return b } // NewBlockFromStorage like NewBlock but used to create Block object when read it from DB // in this case no reason to copy parts, or re-calculate headers fields - they are all stored in DB func NewBlockFromStorage(hash libcommon.Hash, header *Header, txs []Transaction, uncles []*Header, withdrawals []*Withdrawal, requests Requests) *Block { + header.hash.Store(&hash) b := &Block{header: header, transactions: txs, uncles: uncles, withdrawals: withdrawals, requests: requests} - b.hash.Store(&hash) return b } @@ -1088,7 +1117,7 @@ func NewBlockFromNetwork(header *Header, body *Body) *Block { // CopyHeader creates a deep copy of a block header to prevent side effects from // modifying a header variable. func CopyHeader(h *Header) *Header { - cpy := *h + cpy := *h //nolint if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) } @@ -1127,6 +1156,11 @@ func CopyHeader(h *Header) *Header { cpy.RequestsHash = new(libcommon.Hash) cpy.RequestsHash.SetBytes(h.RequestsHash.Bytes()) } + cpy.mutable = h.mutable + if hash := h.hash.Load(); hash != nil { + hashCopy := *hash + cpy.hash.Store(&hashCopy) + } return &cpy } @@ -1454,10 +1488,6 @@ func (b *Block) Copy() *Block { withdrawals: withdrawals, requests: requests, } - if h := b.hash.Load(); h != nil { - hashCopy := *h - newB.hash.Store(&hashCopy) - } szCopy := b.size.Load() newB.size.Store(szCopy) return newB @@ -1466,10 +1496,10 @@ func (b *Block) Copy() *Block { // WithSeal returns a new block with the data from b but the header replaced with // the sealed one. func (b *Block) WithSeal(header *Header) *Block { - cpy := *header - + headerCopy := CopyHeader(header) + headerCopy.mutable = false return &Block{ - header: &cpy, + header: headerCopy, transactions: b.transactions, uncles: b.uncles, withdrawals: b.withdrawals, @@ -1479,14 +1509,7 @@ func (b *Block) WithSeal(header *Header) *Block { // Hash returns the keccak256 hash of b's header. // The hash is computed on the first call and cached thereafter. -func (b *Block) Hash() libcommon.Hash { - if hash := b.hash.Load(); hash != nil { - return *hash - } - h := b.header.Hash() - b.hash.Store(&h) - return h -} +func (b *Block) Hash() libcommon.Hash { return b.header.Hash() } type Blocks []*Block diff --git a/core/types/block_test.go b/core/types/block_test.go index 7d7ac4a4da3..2990cd8c255 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -24,6 +24,7 @@ import ( "reflect" "testing" + "github.com/go-test/deep" "github.com/holiman/uint256" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" @@ -473,7 +474,8 @@ func TestAuRaHeaderEncoding(t *testing.T) { var decoded Header require.NoError(t, rlp.DecodeBytes(encoded, &decoded)) - assert.Equal(t, header, decoded) + deep.CompareUnexportedFields = true + require.Nil(t, deep.Equal(&header, &decoded)) } func TestWithdrawalsEncoding(t *testing.T) { diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 83ebbf4dd11..29812de17c2 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -233,7 +233,7 @@ func BenchmarkEVM_CREATE2_1200(bench *testing.B) { } func fakeHeader(n uint64, parentHash libcommon.Hash) *types.Header { - header := types.Header{ + return &types.Header{ Coinbase: libcommon.HexToAddress("0x00000000000000000000000000000000deadbeef"), Number: big.NewInt(int64(n)), ParentHash: parentHash, @@ -243,7 +243,6 @@ func fakeHeader(n uint64, parentHash libcommon.Hash) *types.Header { Difficulty: big.NewInt(0), GasLimit: 100000, } - return &header } // FakeChainHeaderReader implements consensus.ChainHeaderReader interface diff --git a/eth/stagedsync/stage_mining_finish.go b/eth/stagedsync/stage_mining_finish.go index 408a7990e71..f57576d40ed 100644 --- a/eth/stagedsync/stage_mining_finish.go +++ b/eth/stagedsync/stage_mining_finish.go @@ -52,7 +52,7 @@ func SpawnMiningFinishStage(s *StageState, tx kv.RwTx, cfg MiningFinishCfg, quit // continue //} - block := types.NewBlock(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals, current.Requests) + block := types.NewBlockForAsembling(current.Header, current.Txs, current.Uncles, current.Receipts, current.Withdrawals, current.Requests) blockWithReceipts := &types.BlockWithReceipts{Block: block, Receipts: current.Receipts} *current = MiningBlock{} // hack to clean global data diff --git a/go.mod b/go.mod index fbf72f2a78f..f611f020ddd 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( github.com/gfx-labs/sse v0.0.0-20231226060816-f747e26a9baa github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/cors v1.2.1 + github.com/go-test/deep v1.1.1 github.com/goccy/go-json v0.9.11 github.com/gofrs/flock v0.8.1 github.com/golang-jwt/jwt/v4 v4.5.0 diff --git a/go.sum b/go.sum index aaf158f99e0..566ae3ad893 100644 --- a/go.sum +++ b/go.sum @@ -335,6 +335,8 @@ github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 1423690eb4b..d0e653d31ef 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -68,7 +68,7 @@ var ( "0": 64, } // Default number of blocks after which to checkpoint and reset the pending votes - uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. + emptyUncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. // diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures // diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures @@ -545,7 +545,7 @@ func ValidateHeaderUnusedFields(header *types.Header) error { } // Ensure that the block doesn't contain any uncles which are meaningless in PoA - if header.UncleHash != uncleHash { + if header.UncleHash != emptyUncleHash { return errInvalidUncleHash } @@ -1018,10 +1018,6 @@ func (c *Bor) Finalize(config *chain.Config, header *types.Header, state *state. return nil, types.Receipts{}, nil, err } - // No block rewards in PoA, so the state remains as is and uncles are dropped - // header.Root = state.IntermediateRoot(chain.Config().IsSpuriousDragon(header.Number.Uint64())) - header.UncleHash = types.CalcUncleHash(nil) - // Set state sync data to blockchain // bc := chain.(*core.BlockChain) // bc.SetStateSync(stateSyncData) @@ -1088,12 +1084,8 @@ func (c *Bor) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Heade return nil, nil, types.Receipts{}, err } - // No block rewards in PoA, so the state remains as is and uncles are dropped - // header.Root = state.IntermediateRoot(chain.Config().IsSpuriousDragon(header.Number)) - header.UncleHash = types.CalcUncleHash(nil) - // Assemble block - block := types.NewBlock(header, txs, nil, receipts, withdrawals, requests) + block := types.NewBlockForAsembling(header, txs, nil, receipts, withdrawals, requests) // set state sync // bc := chain.(*core.BlockChain) @@ -1123,7 +1115,7 @@ func (c *Bor) Authorize(currentSigner libcommon.Address, signFn SignerFn) { // Seal implements consensus.Engine, attempting to create a sealed block using // the local signing credentials. func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { - header := block.Header() + header := block.HeaderNoCopy() // Sealing the genesis block is not supported number := header.Number.Uint64() diff --git a/tests/statedb_insert_chain_transaction_test.go b/tests/statedb_insert_chain_transaction_test.go index 12896e2dbf8..ed9411dca9b 100644 --- a/tests/statedb_insert_chain_transaction_test.go +++ b/tests/statedb_insert_chain_transaction_test.go @@ -45,15 +45,15 @@ func TestInsertIncorrectStateRootDifferentAccounts(t *testing.T) { } // BLOCK 1 - incorrectHeader := *chain.Headers[0] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[0]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root if chain.Headers[0].Root == incorrectHeader.Root { t.Fatal("roots are the same") } - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") } @@ -112,15 +112,15 @@ func TestInsertIncorrectStateRootSameAccount(t *testing.T) { t.Fatal(err) } // BLOCK 1 - incorrectHeader := *chain.Headers[0] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[0]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root if chain.Headers[0].Root == incorrectHeader.Root { t.Fatal("roots are the same") } - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") } @@ -178,11 +178,11 @@ func TestInsertIncorrectStateRootSameAccountSameAmount(t *testing.T) { } // BLOCK 1 - incorrectHeader := *chain.Headers[0] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[0]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") } @@ -240,11 +240,11 @@ func TestInsertIncorrectStateRootAllFundsRoot(t *testing.T) { } // BLOCK 1 - incorrectHeader := *chain.Headers[0] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[0]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") } @@ -302,10 +302,10 @@ func TestInsertIncorrectStateRootAllFunds(t *testing.T) { } // BLOCK 1 - incorrectHeader := *chain.Headers[0] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[0]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[0].Transactions(), chain.Blocks[0].Uncles(), chain.Receipts[0], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -383,10 +383,10 @@ func TestAccountDeployIncorrectRoot(t *testing.T) { }) require.NoError(t, err) - incorrectHeader := *chain.Headers[1] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[1]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[0].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[1].Transactions(), chain.Blocks[1].Uncles(), chain.Receipts[1], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[1].Transactions(), chain.Blocks[1].Uncles(), chain.Receipts[1], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} // BLOCK 2 - INCORRECT if err = m.InsertChain(incorrectChain); err == nil { @@ -490,10 +490,10 @@ func TestAccountCreateIncorrectRoot(t *testing.T) { require.NoError(t, err) // BLOCK 3 - INCORRECT - incorrectHeader := *chain.Headers[2] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[2]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[2].Transactions(), chain.Blocks[2].Uncles(), chain.Receipts[2], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[2].Transactions(), chain.Blocks[2].Uncles(), chain.Receipts[2], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -579,10 +579,10 @@ func TestAccountUpdateIncorrectRoot(t *testing.T) { } // BLOCK 4 - INCORRECT - incorrectHeader := *chain.Headers[3] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[3]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") @@ -667,10 +667,10 @@ func TestAccountDeleteIncorrectRoot(t *testing.T) { } // BLOCK 4 - INCORRECT - incorrectHeader := *chain.Headers[3] // Copy header, not just pointer + incorrectHeader := types.CopyHeader(chain.Headers[3]) // Copy header, not just pointer incorrectHeader.Root = chain.Headers[1].Root - incorrectBlock := types.NewBlock(&incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) - incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{&incorrectHeader}, TopBlock: incorrectBlock} + incorrectBlock := types.NewBlock(incorrectHeader, chain.Blocks[3].Transactions(), chain.Blocks[3].Uncles(), chain.Receipts[3], nil, nil) + incorrectChain := &core.ChainPack{Blocks: []*types.Block{incorrectBlock}, Headers: []*types.Header{incorrectHeader}, TopBlock: incorrectBlock} if err = m.InsertChain(incorrectChain); err == nil { t.Fatal("should fail") } diff --git a/turbo/execution/eth1/eth1_utils/grpc_test.go b/turbo/execution/eth1/eth1_utils/grpc_test.go index 3c593337c34..ce8b5110086 100644 --- a/turbo/execution/eth1/eth1_utils/grpc_test.go +++ b/turbo/execution/eth1/eth1_utils/grpc_test.go @@ -3,6 +3,7 @@ package eth1_utils import ( "testing" + "github.com/go-test/deep" "github.com/holiman/uint256" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/common/math" @@ -79,7 +80,9 @@ func TestBlockRpcConversion(t *testing.T) { if err != nil { panic(err) } - require.Equal(testBlock.Header(), roundTripHeader) + + deep.CompareUnexportedFields = true + require.Nil(deep.Equal(testBlock.HeaderNoCopy(), roundTripHeader)) // body conversions rpcBlock := ConvertBlockToRPC(testBlock) @@ -91,7 +94,7 @@ func TestBlockRpcConversion(t *testing.T) { require.Greater(len(testBlockRaw.Transactions), 0) require.Greater(len(testBlockRaw.Uncles), 0) require.Greater(len(testBlockRaw.Withdrawals), 0) - require.Equal(testBlockRaw, roundTripBody) // validates txns, uncles, and withdrawals + require.Nil(deep.Equal(testBlockRaw, roundTripBody)) } func TestBigIntConversion(t *testing.T) { diff --git a/turbo/stages/headerdownload/header_algo_test.go b/turbo/stages/headerdownload/header_algo_test.go index 59a8fd3e9fd..7a83b452bac 100644 --- a/turbo/stages/headerdownload/header_algo_test.go +++ b/turbo/stages/headerdownload/header_algo_test.go @@ -72,7 +72,7 @@ func TestSideChainInsert(t *testing.T) { testCases := []struct { name string - chain []types.Header + chain []*types.Header expectedHash common.Hash expectedDiff int64 }{ @@ -88,9 +88,8 @@ func TestSideChainInsert(t *testing.T) { for _, tc := range testCases { tc := tc for i, h := range tc.chain { - h := h - data, _ := rlp.EncodeToBytes(&h) - if _, err = hi.FeedHeaderPoW(tx, br, &h, data, h.Hash(), uint64(i+1)); err != nil { + data, _ := rlp.EncodeToBytes(h) + if _, err = hi.FeedHeaderPoW(tx, br, h, data, h.Hash(), uint64(i+1)); err != nil { t.Errorf("feed empty header for %s, err: %v", tc.name, err) } } @@ -104,14 +103,14 @@ func TestSideChainInsert(t *testing.T) { } } -func createTestChain(length int64, parent common.Hash, diff int64, extra []byte) []types.Header { +func createTestChain(length int64, parent common.Hash, diff int64, extra []byte) []*types.Header { var ( i int64 - headers []types.Header + headers []*types.Header ) for i = 0; i < length; i++ { - h := types.Header{ + h := &types.Header{ Number: big.NewInt(i + 1), Difficulty: big.NewInt(diff), ParentHash: parent,