Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
452fb28
first working version of new state sync tx
lucca30 Aug 27, 2025
ada4bcc
remove logs
lucca30 Sep 3, 2025
4853b71
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
lucca30 Sep 3, 2025
d57e485
fix lint
lucca30 Sep 3, 2025
a6b395c
fix integration tests
lucca30 Sep 3, 2025
feb65bf
test fixes
lucca30 Sep 4, 2025
030eb31
lint fix
lucca30 Sep 4, 2025
854fabe
fix parallel processor
lucca30 Sep 4, 2025
6f8186c
type improvement and unit tests
lucca30 Sep 4, 2025
55ba461
remove duplicates
lucca30 Sep 4, 2025
340a5bb
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
lucca30 Sep 29, 2025
d634bc1
ignore data test output
lucca30 Oct 6, 2025
f76174b
fixing method calls and fields
lucca30 Oct 6, 2025
7f00fe6
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
lucca30 Oct 6, 2025
b23546e
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
lucca30 Oct 9, 2025
0b556fa
build fix
lucca30 Oct 9, 2025
90b03da
remove bor filter for after hf blocks
lucca30 Oct 9, 2025
15d3a69
sort logs just when necessary
lucca30 Oct 9, 2025
27562ef
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
kamuikatsurgi Oct 15, 2025
d028c82
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
kamuikatsurgi Oct 16, 2025
d56cdc0
ssTxs: fix receiptsHash mismatch (#1829)
kamuikatsurgi Oct 17, 2025
2f5a20d
core(tx): fix Hash method for StateSyncTxType (#1830)
kamuikatsurgi Oct 17, 2025
be7f430
eth: fixes in receipt handling via p2p post HF (#1825)
manav2401 Oct 20, 2025
4b07936
core/types: return nil for chainID() call over state-sync tx
manav2401 Oct 21, 2025
6d6d37f
internal/ethapi: handle bor txs and receipts post HF (#1834)
manav2401 Oct 21, 2025
223f7f9
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
kamuikatsurgi Oct 22, 2025
74627f0
fix: cumulativeGasUsed in insertStateSyncTransactionAndCalculateRecei…
kamuikatsurgi Oct 22, 2025
09b31d5
fix: sort logs and remove duplicate append in Finalize (#1836)
kamuikatsurgi Oct 23, 2025
8960a93
chore: nit (#1838)
kamuikatsurgi Oct 24, 2025
c1fb88e
chore: typos
kamuikatsurgi Oct 24, 2025
64e78d6
fix: lint
kamuikatsurgi Oct 26, 2025
1e3176e
Renaming to Madhugiri HF
lucca30 Oct 27, 2025
af543ae
chore: nits
kamuikatsurgi Oct 27, 2025
097fc2f
(fix): handle pointers to receipt list received via p2p
manav2401 Oct 27, 2025
d1b7dbf
(chore): rename tests with HF name
manav2401 Oct 27, 2025
61d2113
chore: more nits
kamuikatsurgi Oct 27, 2025
bdab391
Merge branch 'lmartins/state-sync-txs-on-block-body' of ssh://github.…
kamuikatsurgi Oct 27, 2025
24302c6
core: add blocktime in bor receipt logs (#1848)
manav2401 Oct 28, 2025
b1ddd41
core/types: derive bloom for bor receipts
manav2401 Oct 28, 2025
00768c5
Merge remote-tracking branch 'origin/develop' into lmartins/state-syn…
kamuikatsurgi Oct 30, 2025
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ profile.cov

tests/spec-tests/

# Test output
eth/tracers/data.csv

# binaries
cmd/abidump/abidump
cmd/abigen/abigen
Expand Down
22 changes: 11 additions & 11 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,15 +409,15 @@ 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)
}
postTrie := state.GetTrie()
if postTrie == nil {
return nil, errors.New("post-state tree is not available")
return nil, nil, errors.New("post-state tree is not available")
}
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
vktPostTrie, okpost := postTrie.(*trie.VerkleTrie)
Expand All @@ -428,7 +428,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 @@ -438,7 +438,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
110 changes: 87 additions & 23 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 @@ -1030,13 +1029,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 @@ -1051,7 +1050,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 @@ -1060,10 +1059,9 @@ 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
}
}

// Get the underlying state for updating consensus time
state := wrappedState.Inner()
state.BorConsensusTime = time.Since(start)
Expand All @@ -1074,12 +1072,60 @@ 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
}

if len(stateSyncData) > 0 && c.config != nil && c.config.IsMadhugiri(header.Number) {
if len(body.Transactions) > 0 {
lastTx := body.Transactions[len(body.Transactions)-1]
if lastTx.Type() == types.StateSyncTxType {
receipts = insertStateSyncTransactionAndCalculateReceipt(lastTx, header, body, wrappedState, receipts)
}
}
} else {
// set state sync
hc := chain.(*core.HeaderChain)
hc.SetStateSync(stateSyncData)
}
return receipts
}

func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transaction, header *types.Header, body *types.Body, state vm.StateDB, receipts []*types.Receipt) []*types.Receipt {
allLogs := state.Logs()
sort.SliceStable(allLogs, func(i, j int) bool {
return allLogs[i].Index < allLogs[j].Index
})
logsFromReceiptCount := countLogsFromReceipts(receipts)
stateSyncLogs := allLogs[logsFromReceiptCount:]

txIndex := uint(len(body.Transactions) - 1)
for _, l := range stateSyncLogs {
l.TxIndex = txIndex
}

var cumulativeGasUsed uint64
if len(receipts) > 0 {
cumulativeGasUsed = receipts[len(receipts)-1].CumulativeGasUsed
}

stateSyncReceipt := &types.Receipt{
// Consensus fields
Type: types.StateSyncTxType,
Status: types.ReceiptStatusSuccessful,
CumulativeGasUsed: cumulativeGasUsed,
Logs: stateSyncLogs,
// Implementation fields
TxHash: stateSyncTx.Hash(),
GasUsed: 0,
// Inclusion information
BlockNumber: header.Number,
TransactionIndex: txIndex,
}

// Set state sync data to blockchain
hc := chain.(*core.HeaderChain)
hc.SetStateSync(stateSyncData)
stateSyncReceipt.Bloom = types.CreateBloom(stateSyncReceipt)
receipts = append(receipts, stateSyncReceipt)

return receipts
}

func decodeGenesisAlloc(i interface{}) (types.GenesisAlloc, error) {
Expand Down Expand Up @@ -1122,13 +1168,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 @@ -1143,7 +1189,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 @@ -1152,14 +1198,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 @@ -1168,15 +1214,23 @@ 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.IsMadhugiri(big.NewInt(int64(headerNumber))) {
stateSyncTx := types.NewTx(&types.StateSyncTx{
StateSyncData: stateSyncData,
})
body.Transactions = append(body.Transactions, stateSyncTx)
receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, 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 @@ -1596,7 +1650,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 @@ -1729,3 +1783,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 @@ -141,7 +141,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
Loading
Loading