Skip to content

Commit 48d1bf0

Browse files
authored
consensus: improve consensus engine definition (#26871)
Makes clear the distinction between Finalize and FinalizedAndAssemble: - In Finalize function, a series of state operations are applied according to consensus rules. The statedb is mutated and the root hash can be checked and compared afterwards. This function should be used in block processing(receive afrom network and apply it locally) but not block generation. - In FinalizeAndAssemble function, after applying state mutations, the block is also to be assembled with the latest state root computed, updating the header. This function should be used in block generation only.
1 parent bba2a1b commit 48d1bf0

File tree

6 files changed

+54
-55
lines changed

6 files changed

+54
-55
lines changed

consensus/beacon/consensus.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,10 +326,8 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
326326
return nil
327327
}
328328

329-
// Finalize implements consensus.Engine, setting the final state on the header
329+
// Finalize implements consensus.Engine and processes withdrawals on top.
330330
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
331-
// Finalize is different with Prepare, it can be used in both block generation
332-
// and verification. So determine the consensus rules by header type.
333331
if !beacon.IsPoSHeader(header) {
334332
beacon.ethone.Finalize(chain, header, state, txs, uncles, nil)
335333
return
@@ -341,16 +339,12 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
341339
amount = amount.Mul(amount, big.NewInt(params.GWei))
342340
state.AddBalance(w.Address, amount)
343341
}
344-
// The block reward is no longer handled here. It's done by the
345-
// external consensus engine.
346-
header.Root = state.IntermediateRoot(true)
342+
// No block reward which is issued by consensus layer instead.
347343
}
348344

349345
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
350346
// assembling the block.
351347
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) {
352-
// FinalizeAndAssemble is different with Prepare, it can be used in both block
353-
// generation and verification. So determine the consensus rules by header type.
354348
if !beacon.IsPoSHeader(header) {
355349
return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil)
356350
}
@@ -367,6 +361,11 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
367361
}
368362
// Finalize and assemble the block.
369363
beacon.Finalize(chain, header, state, txs, uncles, withdrawals)
364+
365+
// Assign the final state root to header.
366+
header.Root = state.IntermediateRoot(true)
367+
368+
// Assemble and return the final block.
370369
return types.NewBlockWithWithdrawals(header, txs, uncles, receipts, withdrawals, trie.NewStackTrie(nil)), nil
371370
}
372371

consensus/clique/clique.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -565,12 +565,10 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
565565
return nil
566566
}
567567

568-
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
569-
// rewards given.
568+
// Finalize implements consensus.Engine. There is no post-transaction
569+
// consensus rules in clique, do nothing here.
570570
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
571-
// No block rewards in PoA, so the state remains as is and uncles are dropped
572-
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
573-
header.UncleHash = types.CalcUncleHash(nil)
571+
// No block rewards in PoA, so the state remains as is
574572
}
575573

576574
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
@@ -579,11 +577,13 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
579577
if len(withdrawals) > 0 {
580578
return nil, errors.New("clique does not support withdrawals")
581579
}
582-
583580
// Finalize block
584581
c.Finalize(chain, header, state, txs, uncles, nil)
585582

586-
// Assemble and return the final block for sealing
583+
// Assign the final state root to header.
584+
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
585+
586+
// Assemble and return the final block for sealing.
587587
return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)), nil
588588
}
589589

consensus/consensus.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,16 @@ type Engine interface {
8484
// rules of a particular engine. The changes are executed inline.
8585
Prepare(chain ChainHeaderReader, header *types.Header) error
8686

87-
// Finalize runs any post-transaction state modifications (e.g. block rewards)
88-
// but does not assemble the block.
87+
// Finalize runs any post-transaction state modifications (e.g. block rewards
88+
// or process withdrawals) but does not assemble the block.
8989
//
90-
// Note: The block header and state database might be updated to reflect any
91-
// consensus rules that happen at finalization (e.g. block rewards).
90+
// Note: The state database might be updated to reflect any consensus rules
91+
// that happen at finalization (e.g. block rewards).
9292
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
9393
uncles []*types.Header, withdrawals []*types.Withdrawal)
9494

9595
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
96-
// rewards) and assembles the final block.
96+
// rewards or process withdrawals) and assembles the final block.
9797
//
9898
// Note: The block header and state database might be updated to reflect any
9999
// consensus rules that happen at finalization (e.g. block rewards).

consensus/ethash/consensus.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -598,12 +598,10 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
598598
return nil
599599
}
600600

601-
// Finalize implements consensus.Engine, accumulating the block and uncle rewards,
602-
// setting the final state on the header
601+
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
603602
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) {
604-
// Accumulate any block and uncle rewards and commit the final state root
603+
// Accumulate any block and uncle rewards
605604
accumulateRewards(chain.Config(), state, header, uncles)
606-
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
607605
}
608606

609607
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
@@ -612,9 +610,12 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
612610
if len(withdrawals) > 0 {
613611
return nil, errors.New("ethash does not support withdrawals")
614612
}
615-
616613
// Finalize block
617614
ethash.Finalize(chain, header, state, txs, uncles, nil)
615+
616+
// Assign the final state root to header.
617+
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
618+
618619
// Header seems complete, assemble into a block and return
619620
return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil
620621
}

core/block_validator.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
9090
return nil
9191
}
9292

93-
// ValidateState validates the various changes that happen after a state
94-
// transition, such as amount of used gas, the receipt roots and the state root
95-
// itself. ValidateState returns a database batch if the validation was a success
96-
// otherwise nil and an error is returned.
93+
// ValidateState validates the various changes that happen after a state transition,
94+
// such as amount of used gas, the receipt roots and the state root itself.
9795
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
9896
header := block.Header()
9997
if block.GasUsed() != usedGas {

core/blockchain.go

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,44 +1752,45 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
17521752
}
17531753

17541754
// Process block using the parent state as reference point
1755-
substart := time.Now()
1755+
pstart := time.Now()
17561756
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig)
17571757
if err != nil {
17581758
bc.reportBlock(block, receipts, err)
17591759
atomic.StoreUint32(&followupInterrupt, 1)
17601760
return it.index, err
17611761
}
1762+
ptime := time.Since(pstart)
17621763

1763-
// Update the metrics touched during block processing
1764-
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete, we can mark them
1765-
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete, we can mark them
1766-
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete, we can mark them
1767-
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete, we can mark them
1768-
snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete, we can mark them
1769-
snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete, we can mark them
1770-
triehash := statedb.AccountHashes + statedb.StorageHashes // Save to not double count in validation
1771-
trieproc := statedb.SnapshotAccountReads + statedb.AccountReads + statedb.AccountUpdates
1772-
trieproc += statedb.SnapshotStorageReads + statedb.StorageReads + statedb.StorageUpdates
1773-
1774-
blockExecutionTimer.Update(time.Since(substart) - trieproc - triehash)
1775-
1776-
// Validate the state using the default validator
1777-
substart = time.Now()
1764+
vstart := time.Now()
17781765
if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil {
17791766
bc.reportBlock(block, receipts, err)
17801767
atomic.StoreUint32(&followupInterrupt, 1)
17811768
return it.index, err
17821769
}
1783-
proctime := time.Since(start)
1784-
1785-
// Update the metrics touched during block validation
1786-
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete, we can mark them
1787-
storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete, we can mark them
1788-
blockValidationTimer.Update(time.Since(substart) - (statedb.AccountHashes + statedb.StorageHashes - triehash))
1770+
vtime := time.Since(vstart)
1771+
proctime := time.Since(start) // processing + validation
1772+
1773+
// Update the metrics touched during block processing and validation
1774+
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
1775+
storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing)
1776+
snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing)
1777+
snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing)
1778+
accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation)
1779+
storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation)
1780+
accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation)
1781+
storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete(in validation)
1782+
triehash := statedb.AccountHashes + statedb.StorageHashes // The time spent on tries hashing
1783+
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
1784+
trieRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read
1785+
trieRead += statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read
1786+
blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing
1787+
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
17891788

17901789
// Write the block to the chain and get the status.
1791-
substart = time.Now()
1792-
var status WriteStatus
1790+
var (
1791+
wstart = time.Now()
1792+
status WriteStatus
1793+
)
17931794
if !setHead {
17941795
// Don't set the head, only insert the block
17951796
err = bc.writeBlockWithState(block, receipts, statedb)
@@ -1804,9 +1805,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
18041805
accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them
18051806
storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them
18061807
snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them
1807-
triedbCommitTimer.Update(statedb.TrieDBCommits) // Triedb commits are complete, we can mark them
1808+
triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them
18081809

1809-
blockWriteTimer.Update(time.Since(substart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits)
1810+
blockWriteTimer.Update(time.Since(wstart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits)
18101811
blockInsertTimer.UpdateSince(start)
18111812

18121813
// Report the import stats before returning the various results

0 commit comments

Comments
 (0)