From 422b30727d999924e90b3cde38df5747f95f2f65 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 18 Mar 2024 12:21:53 +0100 Subject: [PATCH] core: refactor consensus interface --- consensus/beacon/consensus.go | 20 +++++++------- consensus/clique/clique.go | 10 +++---- consensus/consensus.go | 6 ++--- consensus/ethash/consensus.go | 12 ++++----- core/chain_makers.go | 3 ++- core/state_processor.go | 2 +- core/types/block.go | 51 ++++++++++++++++++++++++----------- miner/worker.go | 1 + 8 files changed, 63 insertions(+), 42 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index a350e383a2..9ffed438a8 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -348,13 +348,13 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine and processes withdrawals on top. -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { if !beacon.IsPoSHeader(header) { - beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) + beacon.ethone.Finalize(chain, header, state, body) return } // Withdrawals processing. - for _, w := range withdrawals { + for _, w := range body.Withdrawals { // Convert amount from gwei to wei. amount := new(uint256.Int).SetUint64(w.Amount) amount = amount.Mul(amount, uint256.NewInt(params.GWei)) @@ -365,29 +365,29 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, setting the final state and // assembling the block. -func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { if !beacon.IsPoSHeader(header) { - return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) + return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts) } shanghai := chain.Config().IsShanghai(header.Number, header.Time) if shanghai { // All blocks after Shanghai must include a withdrawals root. - if withdrawals == nil { - withdrawals = make([]*types.Withdrawal, 0) + if body.Withdrawals == nil { + body.Withdrawals = make([]*types.Withdrawal, 0) } } else { - if len(withdrawals) > 0 { + if len(body.Withdrawals) > 0 { return nil, errors.New("withdrawals set before Shanghai activation") } } // Finalize and assemble the block. - beacon.Finalize(chain, header, state, txs, uncles, withdrawals) + beacon.Finalize(chain, header, state, body) // Assign the final state root to header. header.Root = state.IntermediateRoot(true) // Assemble and return the final block. - return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil + return types.NewBlockWithWithdrawals(header, body.Transactions, body.Uncles, receipts, body.Withdrawals, trie.NewStackTrie(nil)), nil } // Seal generates a new sealing request for the given input block and pushes diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 59f0e96ebe..b5727fc666 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -580,24 +580,24 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine. There is no post-transaction // consensus rules in clique, do nothing here. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { // No block rewards in PoA, so the state remains as is } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { - if len(withdrawals) > 0 { +func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { + if len(body.Withdrawals) > 0 { return nil, errors.New("clique does not support withdrawals") } // Finalize block - c.Finalize(chain, header, state, txs, uncles, nil) + c.Finalize(chain, header, state, body) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) // Assemble and return the final block for sealing. - return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil + return types.NewBlock(header, body.Transactions, nil, receipts, trie.NewStackTrie(nil)), nil } // Authorize injects a private key into the consensus engine to mint new blocks diff --git a/consensus/consensus.go b/consensus/consensus.go index 5cc052cb0f..9232f7a2c8 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -88,16 +88,14 @@ type Engine interface { // // Note: The state database might be updated to reflect any consensus rules // that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, withdrawals []*types.Withdrawal) + Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // rewards or process withdrawals) and assembles the final block. // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). - FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, - uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) + FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index c2936fd4b3..5299afa610 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -501,25 +501,25 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { // Accumulate any block and uncle rewards - accumulateRewards(chain.Config(), state, header, uncles) + accumulateRewards(chain.Config(), state, header, body.Uncles) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. -func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { - if len(withdrawals) > 0 { +func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { + if len(body.Withdrawals) > 0 { return nil, errors.New("ethash does not support withdrawals") } // Finalize block - ethash.Finalize(chain, header, state, txs, uncles, nil) + ethash.Finalize(chain, header, state, body) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) // Header seems complete, assemble into a block and return - return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil + return types.NewBlock(header, body.Transactions, body.Uncles, receipts, trie.NewStackTrie(nil)), nil } // SealHash returns the hash of a block prior to it being sealed. diff --git a/core/chain_makers.go b/core/chain_makers.go index 733030fd1c..1c42ab0c9a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -345,7 +345,8 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse gen(i, b) } - block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, b.txs, b.uncles, b.receipts, b.withdrawals) + body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals} + block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts) if err != nil { panic(err) } diff --git a/core/state_processor.go b/core/state_processor.go index 2f18d257b9..9c8beaa7f5 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -99,7 +99,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, errors.New("withdrawals before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles(), withdrawals) + p.engine.Finalize(p.bc, header, statedb, block.Body()) return receipts, allLogs, *usedGas, nil } diff --git a/core/types/block.go b/core/types/block.go index 1a357baa3a..176a247c4a 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -93,6 +93,9 @@ type Header struct { // ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers. ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + + // InclusionListSummaryRoot was added by EIP-7547 and is ignored in legacy headers. + InclusionListSummaryRoot *common.Hash `json:"inclusionListSummaryRoot" rlp:"optional"` } // field type overrides for gencodec @@ -168,9 +171,10 @@ func (h *Header) EmptyReceipts() bool { // Body is a simple (mutable, non-safe) data container for storing and moving // a block's data contents (transactions and uncles) together. type Body struct { - Transactions []*Transaction - Uncles []*Header - Withdrawals []*Withdrawal `rlp:"optional"` + Transactions []*Transaction + Uncles []*Header + Withdrawals []*Withdrawal `rlp:"optional"` + InclusionListSummary []common.Address } // Block represents an Ethereum block. @@ -191,10 +195,11 @@ type Body struct { // - We do not copy body data on access because it does not affect the caches, and also // because it would be too expensive. type Block struct { - header *Header - uncles []*Header - transactions Transactions - withdrawals Withdrawals + header *Header + uncles []*Header + transactions Transactions + withdrawals Withdrawals + inclusionListSummary []common.Address // caches hash atomic.Value @@ -208,10 +213,11 @@ type Block struct { // "external" block encoding. used for eth protocol, etc. type extblock struct { - Header *Header - Txs []*Transaction - Uncles []*Header - Withdrawals []*Withdrawal `rlp:"optional"` + Header *Header + Txs []*Transaction + Uncles []*Header + Withdrawals []*Withdrawal `rlp:"optional"` + InclusionListSummary []common.Address } // NewBlock creates a new block. The input data is copied, changes to header and to the @@ -332,15 +338,16 @@ func (b *Block) EncodeRLP(w io.Writer) error { // Body returns the non-header content of the block. // Note the returned data is not an independent copy. func (b *Block) Body() *Body { - return &Body{b.transactions, b.uncles, b.withdrawals} + return &Body{b.transactions, b.uncles, b.withdrawals, b.inclusionListSummary} } // Accessors for body data. These do not return a copy because the content // of the body slices does not affect the cached hash/size in block. -func (b *Block) Uncles() []*Header { return b.uncles } -func (b *Block) Transactions() Transactions { return b.transactions } -func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } +func (b *Block) Uncles() []*Header { return b.uncles } +func (b *Block) Transactions() Transactions { return b.transactions } +func (b *Block) Withdrawals() Withdrawals { return b.withdrawals } +func (b *Block) InclusionListSummary() []common.Address { return b.inclusionListSummary } func (b *Block) Transaction(hash common.Hash) *Transaction { for _, transaction := range b.transactions { @@ -482,6 +489,20 @@ func (b *Block) WithWithdrawals(withdrawals []*Withdrawal) *Block { return block } +// WithInclusionList returns a copy of the block containing the given inclusionList. +func (b *Block) WithInclusionList(addresses []common.Address) *Block { + block := &Block{ + header: b.header, + transactions: b.transactions, + uncles: b.uncles, + } + if addresses != nil { + block.inclusionListSummary = make([]common.Address, len(addresses)) + copy(block.inclusionListSummary, addresses) + } + return 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() common.Hash { diff --git a/miner/worker.go b/miner/worker.go index 7e038b0f30..dd0d0e23e5 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -453,3 +453,4 @@ func signalToErr(signal int32) error { panic(fmt.Errorf("undefined signal %d", signal)) } } +, b.inclusionListSummary \ No newline at end of file