Skip to content

Commit

Permalink
all: refactor so NewBlock, WithBody take types.Body (#29482)
Browse files Browse the repository at this point in the history
* all: refactor so NewBlock(..) and WithBody(..) take a types.Body

* core: fixup comments, remove txs != receipts panic

* core/types: add empty withdrawls to body if len == 0
  • Loading branch information
lightclient authored Apr 30, 2024
1 parent 5e07054 commit 2e8e35f
Show file tree
Hide file tree
Showing 23 changed files with 81 additions and 76 deletions.
2 changes: 1 addition & 1 deletion beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash,
BlobGasUsed: params.BlobGasUsed,
ParentBeaconRoot: beaconRoot,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: params.Withdrawals})
if block.Hash() != params.BlockHash {
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash())
}
Expand Down
4 changes: 1 addition & 3 deletions beacon/types/exec_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ func convertPayload[T payloadType](payload T, parentRoot *zrntcommon.Root) (*typ
panic("unsupported block type")
}

block := types.NewBlockWithHeader(&header)
block = block.WithBody(transactions, nil)
block = block.WithWithdrawals(withdrawals)
block := types.NewBlockWithHeader(&header).WithBody(types.Body{Transactions: transactions, Withdrawals: withdrawals})
if hash := block.Hash(); hash != expectedHash {
return nil, fmt.Errorf("Sanity check failed, payload hash does not match (expected %x, got %x)", expectedHash, hash)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/internal/t8ntool/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (i *bbInput) ToBlock() *types.Block {
if i.Header.Difficulty != nil {
header.Difficulty = i.Header.Difficulty
}
return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals)
return types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: i.Txs, Uncles: i.Ommers, Withdrawals: i.Withdrawals})
}

// SealBlock seals the given block using the configured engine.
Expand Down
2 changes: 1 addition & 1 deletion consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
header.Root = state.IntermediateRoot(true)

// Assemble and return the final block.
return types.NewBlockWithWithdrawals(header, body.Transactions, body.Uncles, receipts, body.Withdrawals, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
}

// Seal generates a new sealing request for the given input block and pushes
Expand Down
2 changes: 1 addition & 1 deletion consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Assemble and return the final block for sealing.
return types.NewBlock(header, body.Transactions, nil, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
}

// Authorize injects a private key into the consensus engine to mint new blocks
Expand Down
2 changes: 1 addition & 1 deletion consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

// Header seems complete, assemble into a block and return
return types.NewBlock(header, body.Transactions, body.Uncles, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles}, receipts, trie.NewStackTrie(nil)), nil
}

// SealHash returns the hash of a block prior to it being sealed.
Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ func (g *Genesis) ToBlock() *types.Block {
}
}
}
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
}

// Commit writes the block and state of a genesis specification to the database.
Expand Down
14 changes: 11 additions & 3 deletions core/rawdb/accessors_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
if body == nil {
return nil
}
return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles).WithWithdrawals(body.Withdrawals)
return types.NewBlockWithHeader(header).WithBody(*body)
}

// WriteBlock serializes a block into the database, header and body separately.
Expand Down Expand Up @@ -843,7 +843,11 @@ func ReadBadBlock(db ethdb.Reader, hash common.Hash) *types.Block {
}
for _, bad := range badBlocks {
if bad.Header.Hash() == hash {
return types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles).WithWithdrawals(bad.Body.Withdrawals)
block := types.NewBlockWithHeader(bad.Header)
if bad.Body != nil {
block = block.WithBody(*bad.Body)
}
return block
}
}
return nil
Expand All @@ -862,7 +866,11 @@ func ReadAllBadBlocks(db ethdb.Reader) []*types.Block {
}
var blocks []*types.Block
for _, bad := range badBlocks {
blocks = append(blocks, types.NewBlockWithHeader(bad.Header).WithBody(bad.Body.Transactions, bad.Body.Uncles).WithWithdrawals(bad.Body.Withdrawals))
block := types.NewBlockWithHeader(bad.Header)
if bad.Body != nil {
block = block.WithBody(*bad.Body)
}
blocks = append(blocks, block)
}
return blocks
}
Expand Down
2 changes: 1 addition & 1 deletion core/rawdb/accessors_chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ func makeTestBlocks(nblock int, txsPerBlock int) []*types.Block {
Number: big.NewInt(int64(i)),
Extra: []byte("test block"),
}
blocks[i] = types.NewBlockWithHeader(header).WithBody(txs, nil)
blocks[i] = types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
blocks[i].Hash() // pre-cache the block hash
}
return blocks
Expand Down
2 changes: 1 addition & 1 deletion core/rawdb/accessors_indexes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestLookupStorage(t *testing.T) {
tx3 := types.NewTransaction(3, common.BytesToAddress([]byte{0x33}), big.NewInt(333), 3333, big.NewInt(33333), []byte{0x33, 0x33, 0x33})
txs := []*types.Transaction{tx1, tx2, tx3}

block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, txs, nil, nil, newTestHasher())
block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, &types.Body{Transactions: txs}, nil, newTestHasher())

// Check that no transactions entries are in a pristine database
for i, tx := range txs {
Expand Down
8 changes: 4 additions & 4 deletions core/rawdb/chain_iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestChainIterator(t *testing.T) {
var block *types.Block
var txs []*types.Transaction
to := common.BytesToAddress([]byte{0x11})
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher()) // Empty genesis block
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, newTestHasher()) // Empty genesis block
WriteBlock(chainDb, block)
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
for i := uint64(1); i <= 10; i++ {
Expand All @@ -60,7 +60,7 @@ func TestChainIterator(t *testing.T) {
})
}
txs = append(txs, tx)
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher())
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, &types.Body{Transactions: types.Transactions{tx}}, nil, newTestHasher())
WriteBlock(chainDb, block)
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
}
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestIndexTransactions(t *testing.T) {
to := common.BytesToAddress([]byte{0x11})

// Write empty genesis block
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newTestHasher())
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, newTestHasher())
WriteBlock(chainDb, block)
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())

Expand All @@ -138,7 +138,7 @@ func TestIndexTransactions(t *testing.T) {
})
}
txs = append(txs, tx)
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newTestHasher())
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, &types.Body{Transactions: types.Transactions{tx}}, nil, newTestHasher())
WriteBlock(chainDb, block)
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
}
Expand Down
5 changes: 3 additions & 2 deletions core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,10 +417,11 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
header.ParentBeaconRoot = &beaconRoot
}
// Assemble and return the final block for sealing
body := &types.Body{Transactions: txs}
if config.IsShanghai(header.Number, header.Time) {
return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil))
body.Withdrawals = []*types.Withdrawal{}
}
return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil))
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
}

var (
Expand Down
2 changes: 1 addition & 1 deletion core/txpool/legacypool/legacypool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (bc *testBlockChain) CurrentBlock() *types.Header {
}

func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
}

func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
Expand Down
68 changes: 26 additions & 42 deletions core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"io"
"math/big"
"reflect"
"slices"
"sync/atomic"
"time"

Expand Down Expand Up @@ -217,13 +218,19 @@ type extblock struct {
// NewBlock creates a new block. The input data is copied, changes to header and to the
// field values will not affect the block.
//
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs, uncles
// and receipts.
func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, hasher TrieHasher) *Block {
b := &Block{header: CopyHeader(header)}
// The body elements and the receipts are used to recompute and overwrite the
// relevant portions of the header.
func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block {
if body == nil {
body = &Body{}
}
var (
b = NewBlockWithHeader(header)
txs = body.Transactions
uncles = body.Uncles
withdrawals = body.Withdrawals
)

// TODO: panic if len(txs) != len(receipts)
if len(txs) == 0 {
b.header.TxHash = EmptyTxsHash
} else {
Expand All @@ -249,27 +256,18 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
}
}

return b
}

// NewBlockWithWithdrawals creates a new block with withdrawals. The input data is copied,
// changes to header and to the field values will not affect the block.
//
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header are ignored and set to
// values derived from the given txs, uncles and receipts.
func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt, withdrawals []*Withdrawal, hasher TrieHasher) *Block {
b := NewBlock(header, txs, uncles, receipts, hasher)

if withdrawals == nil {
b.header.WithdrawalsHash = nil
} else if len(withdrawals) == 0 {
b.header.WithdrawalsHash = &EmptyWithdrawalsHash
b.withdrawals = Withdrawals{}
} else {
h := DeriveSha(Withdrawals(withdrawals), hasher)
b.header.WithdrawalsHash = &h
hash := DeriveSha(Withdrawals(withdrawals), hasher)
b.header.WithdrawalsHash = &hash
b.withdrawals = slices.Clone(withdrawals)
}

return b.WithWithdrawals(withdrawals)
return b
}

// CopyHeader creates a deep copy of a block header.
Expand Down Expand Up @@ -453,31 +451,17 @@ func (b *Block) WithSeal(header *Header) *Block {
}
}

// WithBody returns a copy of the block with the given transaction and uncle contents.
func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block {
block := &Block{
header: b.header,
transactions: make([]*Transaction, len(transactions)),
uncles: make([]*Header, len(uncles)),
withdrawals: b.withdrawals,
}
copy(block.transactions, transactions)
for i := range uncles {
block.uncles[i] = CopyHeader(uncles[i])
}
return block
}

// WithWithdrawals returns a copy of the block containing the given withdrawals.
func (b *Block) WithWithdrawals(withdrawals []*Withdrawal) *Block {
// WithBody returns a new block with the original header and a deep copy of the
// provided body.
func (b *Block) WithBody(body Body) *Block {
block := &Block{
header: b.header,
transactions: b.transactions,
uncles: b.uncles,
transactions: slices.Clone(body.Transactions),
uncles: make([]*Header, len(body.Uncles)),
withdrawals: slices.Clone(body.Withdrawals),
}
if withdrawals != nil {
block.withdrawals = make([]*Withdrawal, len(withdrawals))
copy(block.withdrawals, withdrawals)
for i := range body.Uncles {
block.uncles[i] = CopyHeader(body.Uncles[i])
}
return block
}
Expand Down
2 changes: 1 addition & 1 deletion core/types/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func makeBenchBlock() *Block {
Extra: []byte("benchmark uncle"),
}
}
return NewBlock(header, txs, uncles, receipts, blocktest.NewHasher())
return NewBlock(header, &Body{Transactions: txs, Uncles: uncles}, receipts, blocktest.NewHasher())
}

func TestRlpDecodeParentHash(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions eth/catalyst/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
Extra: data.ExtraData,
MixDigest: data.Random,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
data.BlockHash = block.Hash()
return data
}
Expand Down Expand Up @@ -935,7 +935,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
Extra: data.ExtraData,
MixDigest: data.Random,
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
data.BlockHash = block.Hash()
// Send the new payload
resp2, err := api.NewPayloadV1(data)
Expand Down Expand Up @@ -1554,7 +1554,7 @@ func TestBlockToPayloadWithBlobs(t *testing.T) {
},
}

block := types.NewBlock(&header, txs, nil, nil, trie.NewStackTrie(nil))
block := types.NewBlock(&header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
envelope := engine.BlockToExecutableData(block, nil, sidecars)
var want int
for _, tx := range txs {
Expand Down
6 changes: 3 additions & 3 deletions eth/downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -1504,7 +1504,7 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error {
)
blocks := make([]*types.Block, len(results))
for i, result := range results {
blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.body())
}
// Downloaded blocks are always regarded as trusted after the
// transition. Because the downloaded chain is guided by the
Expand Down Expand Up @@ -1726,7 +1726,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
blocks := make([]*types.Block, len(results))
receipts := make([]types.Receipts, len(results))
for i, result := range results {
blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.body())
receipts[i] = result.Receipts
}
if index, err := d.blockchain.InsertReceiptChain(blocks, receipts, d.ancientLimit); err != nil {
Expand All @@ -1737,7 +1737,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
}

func (d *Downloader) commitPivotBlock(result *fetchResult) error {
block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
block := types.NewBlockWithHeader(result.Header).WithBody(result.body())
log.Debug("Committing snap sync pivot as new head", "number", block.Number(), "hash", block.Hash())

// Commit the pivot block as the new head, will require full sync from here on
Expand Down
9 changes: 9 additions & 0 deletions eth/downloader/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ func newFetchResult(header *types.Header, fastSync bool) *fetchResult {
return item
}

// body returns a representation of the fetch result as a types.Body object.
func (f *fetchResult) body() types.Body {
return types.Body{
Transactions: f.Transactions,
Uncles: f.Uncles,
Withdrawals: f.Withdrawals,
}
}

// SetBodyDone flags the body as finished.
func (f *fetchResult) SetBodyDone() {
if v := f.pending.Load(); (v & (1 << bodyType)) != 0 {
Expand Down
7 changes: 6 additions & 1 deletion ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,12 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
}
txs[i] = tx.tx
}
return types.NewBlockWithHeader(head).WithBody(txs, uncles).WithWithdrawals(body.Withdrawals), nil
return types.NewBlockWithHeader(head).WithBody(
types.Body{
Transactions: txs,
Uncles: uncles,
Withdrawals: body.Withdrawals,
}), nil
}

// HeaderByHash returns the block header with the given hash.
Expand Down
2 changes: 1 addition & 1 deletion internal/era/era.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (e *Era) GetBlockByNumber(num uint64) (*types.Block, error) {
if err := rlp.Decode(r, &body); err != nil {
return nil, err
}
return types.NewBlockWithHeader(&header).WithBody(body.Transactions, body.Uncles), nil
return types.NewBlockWithHeader(&header).WithBody(body), nil
}

// Accumulator reads the accumulator entry in the Era1 file.
Expand Down
2 changes: 1 addition & 1 deletion internal/era/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (it *Iterator) Block() (*types.Block, error) {
if err := rlp.Decode(it.inner.Body, &body); err != nil {
return nil, err
}
return types.NewBlockWithHeader(&header).WithBody(body.Transactions, body.Uncles), nil
return types.NewBlockWithHeader(&header).WithBody(body), nil
}

// Receipts returns the receipts for the iterator's current position.
Expand Down
Loading

0 comments on commit 2e8e35f

Please sign in to comment.