Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,9 @@ 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 vm.StateDB, body *types.Body) {
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) []*types.Receipt {
if !beacon.IsPoSHeader(header) {
beacon.ethone.Finalize(chain, header, state, body)
return
return beacon.ethone.Finalize(chain, header, state, body, receipts)
}
// Withdrawals processing.
for _, w := range body.Withdrawals {
Expand All @@ -372,11 +371,12 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
state.AddBalance(w.Address, amount, tracing.BalanceIncreaseWithdrawal)
}
// No block reward which is issued by consensus layer instead.
return receipts
}

// 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, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
if !beacon.IsPoSHeader(header) {
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts)
}
Expand All @@ -389,11 +389,11 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
}
} else {
if len(body.Withdrawals) > 0 {
return nil, errors.New("withdrawals set before Shanghai activation")
return nil, nil, errors.New("withdrawals set before Shanghai activation")
}
}
// Finalize and assemble the block.
beacon.Finalize(chain, header, state, body)
receipts = beacon.Finalize(chain, header, state, body, receipts)

// Assign the final state root to header.
header.Root = state.IntermediateRoot(true)
Expand All @@ -409,11 +409,11 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Open the pre-tree to prove the pre-state against
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
if parent == nil {
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
return nil, nil, fmt.Errorf("nil parent header for block %d", header.Number)
}
preTrie, err := state.Database().OpenTrie(parent.Root)
if err != nil {
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
return nil, nil, fmt.Errorf("error opening pre-state tree root: %w", err)
}
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
Expand All @@ -424,7 +424,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
if len(keys) > 0 {
verkleProof, stateDiff, err := vktPreTrie.Proof(vktPostTrie, keys)
if err != nil {
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
return nil, nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
}
block = block.WithWitness(&types.ExecutionWitness{
StateDiff: stateDiff,
Expand All @@ -434,7 +434,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
}
}

return block, nil
return block, receipts, nil
}

// Seal generates a new sealing request for the given input block and pushes
Expand Down
87 changes: 65 additions & 22 deletions consensus/bor/bor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package bor
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -950,13 +949,13 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e

// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
// rewards given.
func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, wrappedState vm.StateDB, body *types.Body) {
func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, wrappedState vm.StateDB, body *types.Body, receipts []*types.Receipt) []*types.Receipt {
headerNumber := header.Number.Uint64()
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
return
return nil
}
if header.RequestsHash != nil {
return
return nil
}

var (
Expand All @@ -971,7 +970,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
if !c.config.IsRio(header.Number) {
if err := c.checkAndCommitSpan(wrappedState, header, cx); err != nil {
log.Error("Error while committing span", "error", err)
return
return nil
}
}

Expand All @@ -980,7 +979,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
stateSyncData, err = c.CommitStates(wrappedState, header, cx)
if err != nil {
log.Error("Error while committing states", "error", err)
return
return nil
}
}

Expand All @@ -994,12 +993,42 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
// in tracing if it's enabled.
if err = c.changeContractCodeIfNeeded(headerNumber, wrappedState); err != nil {
log.Error("Error changing contract code", "error", err)
return
return nil
}

// Set state sync data to blockchain
hc := chain.(*core.HeaderChain)
hc.SetStateSync(stateSyncData)
if len(stateSyncData) > 0 && c.config != nil && c.config.IsStateSync(big.NewInt(int64(headerNumber))) {
receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncData, header, body, wrappedState, receipts)
} else {
// set state sync
hc := chain.(*core.HeaderChain)
hc.SetStateSync(stateSyncData)
}
return receipts
}

func insertStateSyncTransactionAndCalculateReceipt(stateSyncData []*types.StateSyncData, header *types.Header, body *types.Body, state vm.StateDB, receipts []*types.Receipt) []*types.Receipt {
stateSyncTx := types.NewTx(&types.StateSyncTx{
StateSyncData: stateSyncData,
})
body.Transactions = append(body.Transactions, stateSyncTx)
allLogs := state.Logs()
logsFromReceiptCount := countLogsFromReceipts(receipts)
stateSyncLogs := allLogs[logsFromReceiptCount:]

stateSyncReceipt := &types.Receipt{
Type: types.StateSyncTxType,
PostState: header.Root.Bytes(),
Status: types.ReceiptStatusSuccessful,
CumulativeGasUsed: header.GasUsed,
TxHash: stateSyncTx.Hash(),
Logs: stateSyncLogs,
BlockNumber: header.Number,
TransactionIndex: uint(len(body.Transactions)), // we already appended state sync tx on body
}
stateSyncReceipt.Bloom = types.CreateBloom(stateSyncReceipt)
receipts = append(receipts, stateSyncReceipt)

return receipts
}

func decodeGenesisAlloc(i interface{}) (types.GenesisAlloc, error) {
Expand Down Expand Up @@ -1042,13 +1071,13 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state vm.StateDB)

// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
headerNumber := header.Number.Uint64()
if body.Withdrawals != nil || header.WithdrawalsHash != nil {
return nil, consensus.ErrUnexpectedWithdrawals
return nil, nil, consensus.ErrUnexpectedWithdrawals
}
if header.RequestsHash != nil {
return nil, consensus.ErrUnexpectedRequests
return nil, nil, consensus.ErrUnexpectedRequests
}

var (
Expand All @@ -1063,7 +1092,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
if !c.config.IsRio(header.Number) {
if err = c.checkAndCommitSpan(state, header, cx); err != nil {
log.Error("Error while committing span", "error", err)
return nil, err
return nil, nil, err
}
}

Expand All @@ -1072,14 +1101,14 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
stateSyncData, err = c.CommitStates(state, header, cx)
if err != nil {
log.Error("Error while committing states", "error", err)
return nil, err
return nil, nil, err
}
}
}

if err = c.changeContractCodeIfNeeded(headerNumber, state); err != nil {
log.Error("Error changing contract code", "error", err)
return nil, err
return nil, nil, err
}

// No block rewards in PoA, so the state remains as it is
Expand All @@ -1088,15 +1117,19 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ
// Uncles are dropped
header.UncleHash = types.CalcUncleHash(nil)

if len(stateSyncData) > 0 && c.config != nil && c.config.IsStateSync(big.NewInt(int64(headerNumber))) {
receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncData, header, body, state, receipts)
} else {
// set state sync
bc := chain.(core.BorStateSyncer)
bc.SetStateSync(stateSyncData)
}

// Assemble block
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))

// set state sync
bc := chain.(core.BorStateSyncer)
bc.SetStateSync(stateSyncData)

// return the final block for sealing
return block, nil
return block, receipts, nil
}

// Authorize injects a private key into the consensus engine to mint new blocks
Expand Down Expand Up @@ -1515,7 +1548,7 @@ func (c *Bor) CommitStates(
stateData := types.StateSyncData{
ID: eventRecord.ID,
Contract: eventRecord.Contract,
Data: hex.EncodeToString(eventRecord.Data),
Data: eventRecord.Data,
TxHash: eventRecord.TxHash,
}

Expand Down Expand Up @@ -1648,3 +1681,13 @@ func getUpdatedValidatorSet(oldValidatorSet *valset.ValidatorSet, newVals []*val
func IsSprintStart(number, sprint uint64) bool {
return number%sprint == 0
}

func countLogsFromReceipts(receipts []*types.Receipt) int {
total := 0
for _, receipt := range receipts {
if receipt != nil {
total += len(receipt.Logs)
}
}
return total
}
2 changes: 1 addition & 1 deletion consensus/bor/bor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestGenesisContractChange(t *testing.T) {
ParentHash: root,
Number: big.NewInt(num),
}
b.Finalize(chain.HeaderChain(), h, statedb, &types.Body{Withdrawals: nil, Transactions: nil, Uncles: nil})
b.Finalize(chain.HeaderChain(), h, statedb, &types.Body{Withdrawals: nil, Transactions: nil, Uncles: nil}, nil)

// write state to database
root, err := statedb.Commit(0, false, true)
Expand Down
11 changes: 6 additions & 5 deletions consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -621,24 +621,25 @@ 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 vm.StateDB, body *types.Body) {
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) []*types.Receipt {
// No block rewards in PoA, so the state remains as is
return receipts
}

// 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, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("clique does not support withdrawals")
return nil, nil, errors.New("clique does not support withdrawals")
}
// Finalize block
c.Finalize(chain, header, state, body)
receipts = c.Finalize(chain, header, state, body, receipts)

// 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, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), receipts, nil
}

// Authorize injects a private key into the consensus engine to mint new blocks
Expand Down
4 changes: 2 additions & 2 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,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 vm.StateDB, body *types.Body)
Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) []*types.Receipt

// 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, body *types.Body, receipts []*types.Receipt) (*types.Block, error)
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error)

// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.
Expand Down
11 changes: 6 additions & 5 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,25 +505,26 @@ 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 vm.StateDB, body *types.Body) {
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) []*types.Receipt {
// Accumulate any block and uncle rewards
accumulateRewards(chain.Config(), state, header, body.Uncles)
return receipts
}

// 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, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("ethash does not support withdrawals")
return nil, nil, errors.New("ethash does not support withdrawals")
}
// Finalize block
ethash.Finalize(chain, header, state, body)
ethash.Finalize(chain, header, state, body, receipts)

// 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, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles, Withdrawals: body.Withdrawals}, receipts, trie.NewStackTrie(nil)), nil
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles, Withdrawals: body.Withdrawals}, receipts, trie.NewStackTrie(nil)), receipts, nil
}

// SealHash returns the hash of a block prior to it being sealed.
Expand Down
7 changes: 4 additions & 3 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
return blockLogs[i].Index < blockLogs[j].Index
})

if len(blockLogs) > len(logs) {
// After StateSync HF we dont write bor receipts separately
if !(bc.chainConfig.Bor != nil && bc.chainConfig.Bor.IsStateSync(block.Number())) && len(blockLogs) > len(logs) {
stateSyncLogs = blockLogs[len(logs):] // get state-sync logs from `state.Logs()`

// State sync logs don't have tx index, tx hash and other necessary fields
Expand Down Expand Up @@ -2107,7 +2108,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
if emitHeadEvent {
bc.chainHeadFeed.Send(ChainHeadEvent{Header: block.Header()})
// BOR state sync feed related changes
for _, data := range bc.stateSyncData {
for _, data := range bc.GetStateSync() {
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
}
// BOR
Expand Down Expand Up @@ -2707,7 +2708,7 @@ func (bc *BlockChain) insertChainWithWitnesses(chain types.Blocks, setHead bool,
}

// BOR state sync feed related changes
for _, data := range bc.stateSyncData {
for _, data := range bc.GetStateSync() {
bc.stateSyncFeed.Send(StateSyncEvent{Data: data})
}
// BOR
Expand Down
3 changes: 3 additions & 0 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4191,6 +4191,9 @@ func TestCreateThenDeletePreByzantium(t *testing.T) {
EIP155Block: big.NewInt(10),
EIP158Block: big.NewInt(10),
ByzantiumBlock: big.NewInt(1_700_000),
Bor: &params.BorConfig{
StateSyncBlock: big.NewInt(0),
},
})
}
func TestCreateThenDeletePostByzantium(t *testing.T) {
Expand Down
Loading
Loading