diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index eb5aa58ca8..b4da9b553a 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -326,10 +326,8 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H return nil } -// Finalize implements consensus.Engine, setting the final state on the header +// 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) { - // Finalize is different with Prepare, it can be used in both block generation - // and verification. So determine the consensus rules by header type. if !beacon.IsPoSHeader(header) { beacon.ethone.Finalize(chain, header, state, txs, uncles, nil) return @@ -341,16 +339,12 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. amount = amount.Mul(amount, big.NewInt(params.GWei)) state.AddBalance(w.Address, amount) } - // The block reward is no longer handled here. It's done by the - // external consensus engine. - header.Root = state.IntermediateRoot(true) + // No block reward which is issued by consensus layer instead. } // 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) { - // FinalizeAndAssemble is different with Prepare, it can be used in both block - // generation and verification. So determine the consensus rules by header type. if !beacon.IsPoSHeader(header) { return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) } @@ -367,6 +361,11 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea } // Finalize and assemble the block. beacon.Finalize(chain, header, state, txs, uncles, withdrawals) + + // 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 } diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 4706bbac1c..6c20803b2a 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -565,12 +565,10 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header return nil } -// Finalize implements consensus.Engine, ensuring no uncles are set, nor block -// rewards given. +// 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) { - // No block rewards in PoA, so the state remains as is and uncles are dropped - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - header.UncleHash = types.CalcUncleHash(nil) + // No block rewards in PoA, so the state remains as is } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, @@ -579,11 +577,13 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * if len(withdrawals) > 0 { return nil, errors.New("clique does not support withdrawals") } - // Finalize block c.Finalize(chain, header, state, txs, uncles, nil) - // Assemble and return the final block for sealing + // 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 } diff --git a/consensus/consensus.go b/consensus/consensus.go index 190d5ae12c..a9fd8dd1cf 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -84,16 +84,16 @@ type Engine interface { // rules of a particular engine. The changes are executed inline. Prepare(chain ChainHeaderReader, header *types.Header) error - // Finalize runs any post-transaction state modifications (e.g. block rewards) - // but does not assemble the block. + // Finalize runs any post-transaction state modifications (e.g. block rewards + // or process withdrawals) 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). + // 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) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block - // rewards) and assembles the final 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). diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index da29e16597..c3c06c541c 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -598,12 +598,10 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H return nil } -// Finalize implements consensus.Engine, accumulating the block and uncle rewards, -// setting the final state on the header +// 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) { - // Accumulate any block and uncle rewards and commit the final state root + // Accumulate any block and uncle rewards accumulateRewards(chain.Config(), state, header, uncles) - header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and @@ -612,9 +610,12 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if len(withdrawals) > 0 { return nil, errors.New("ethash does not support withdrawals") } - // Finalize block ethash.Finalize(chain, header, state, txs, uncles, nil) + + // 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 } diff --git a/core/block_validator.go b/core/block_validator.go index 2a8df7c965..bcb228830d 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -90,10 +90,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { return nil } -// ValidateState validates the various changes that happen after a state -// transition, such as amount of used gas, the receipt roots and the state root -// itself. ValidateState returns a database batch if the validation was a success -// otherwise nil and an error is returned. +// ValidateState validates the various changes that happen after a state transition, +// such as amount of used gas, the receipt roots and the state root itself. func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { header := block.Header() if block.GasUsed() != usedGas { diff --git a/core/blockchain.go b/core/blockchain.go index 1fe7d73e00..8fc520e776 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1752,44 +1752,45 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) } // Process block using the parent state as reference point - substart := time.Now() + pstart := time.Now() receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig) if err != nil { bc.reportBlock(block, receipts, err) atomic.StoreUint32(&followupInterrupt, 1) return it.index, err } + ptime := time.Since(pstart) - // Update the metrics touched during block processing - accountReadTimer.Update(statedb.AccountReads) // Account reads are complete, we can mark them - storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete, we can mark them - accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete, we can mark them - storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete, we can mark them - snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete, we can mark them - snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete, we can mark them - triehash := statedb.AccountHashes + statedb.StorageHashes // Save to not double count in validation - trieproc := statedb.SnapshotAccountReads + statedb.AccountReads + statedb.AccountUpdates - trieproc += statedb.SnapshotStorageReads + statedb.StorageReads + statedb.StorageUpdates - - blockExecutionTimer.Update(time.Since(substart) - trieproc - triehash) - - // Validate the state using the default validator - substart = time.Now() + vstart := time.Now() if err := bc.validator.ValidateState(block, statedb, receipts, usedGas); err != nil { bc.reportBlock(block, receipts, err) atomic.StoreUint32(&followupInterrupt, 1) return it.index, err } - proctime := time.Since(start) + vtime := time.Since(vstart) + proctime := time.Since(start) // processing + validation - // Update the metrics touched during block validation - accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete, we can mark them - storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete, we can mark them - blockValidationTimer.Update(time.Since(substart) - (statedb.AccountHashes + statedb.StorageHashes - triehash)) + // Update the metrics touched during block processing and validation + accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing) + storageReadTimer.Update(statedb.StorageReads) // Storage reads are complete(in processing) + snapshotAccountReadTimer.Update(statedb.SnapshotAccountReads) // Account reads are complete(in processing) + snapshotStorageReadTimer.Update(statedb.SnapshotStorageReads) // Storage reads are complete(in processing) + accountUpdateTimer.Update(statedb.AccountUpdates) // Account updates are complete(in validation) + storageUpdateTimer.Update(statedb.StorageUpdates) // Storage updates are complete(in validation) + accountHashTimer.Update(statedb.AccountHashes) // Account hashes are complete(in validation) + storageHashTimer.Update(statedb.StorageHashes) // Storage hashes are complete(in validation) + triehash := statedb.AccountHashes + statedb.StorageHashes // The time spent on tries hashing + trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update + trieRead := statedb.SnapshotAccountReads + statedb.AccountReads // The time spent on account read + trieRead += statedb.SnapshotStorageReads + statedb.StorageReads // The time spent on storage read + blockExecutionTimer.Update(ptime - trieRead) // The time spent on EVM processing + blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation // Write the block to the chain and get the status. - substart = time.Now() - var status WriteStatus + var ( + wstart = time.Now() + status WriteStatus + ) if !setHead { // Don't set the head, only insert the block err = bc.writeBlockWithState(block, receipts, statedb) @@ -1804,9 +1805,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them - triedbCommitTimer.Update(statedb.TrieDBCommits) // Triedb commits are complete, we can mark them + triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them - blockWriteTimer.Update(time.Since(substart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits) + blockWriteTimer.Update(time.Since(wstart) - statedb.AccountCommits - statedb.StorageCommits - statedb.SnapshotCommits - statedb.TrieDBCommits) blockInsertTimer.UpdateSince(start) // Report the import stats before returning the various results