From 715c9215d1aa15e9bbb6d9fa8e2f1869071d88e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Fri, 6 Feb 2026 09:51:16 +0100 Subject: [PATCH 01/30] Add VM trace support for StateSyncTx tracing - Introduced `vm.Config` to multiple functions for customizable VM tracing. - Added tracer configuration flags (`vmtrace` and `vmtrace.jsonconfig`) to streamline monitoring during blockchain synchronization. - Updated GenesisContract and spanner interfaces for trace integration. - Integrated tracing hooks for StateSyncTx events. --- cmd/cli/main.go | 5 ++ consensus/bor/bor.go | 64 ++++++++++++++++++++++---- consensus/bor/bor_test.go | 2 +- consensus/bor/contract/client.go | 3 +- consensus/bor/genesis.go | 2 +- consensus/bor/heimdall/span/spanner.go | 4 +- consensus/bor/span.go | 2 +- consensus/bor/statefull/processor.go | 7 +-- docs/cli/example_config.toml | 12 +++-- docs/cli/server.md | 4 ++ eth/tracers/api.go | 2 +- internal/cli/server/config.go | 10 ++++ internal/cli/server/flags.go | 14 ++++++ 13 files changed, 106 insertions(+), 25 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 5863276d0b..aa47c53bfc 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -5,6 +5,11 @@ import ( "github.com/ethereum/go-ethereum/internal/cli" "github.com/ethereum/go-ethereum/params" + + // Force-load the tracer engines to trigger registration + _ "github.com/ethereum/go-ethereum/eth/tracers/js" + _ "github.com/ethereum/go-ethereum/eth/tracers/live" + _ "github.com/ethereum/go-ethereum/eth/tracers/native" ) func main() { diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 9e0fc21560..3604cdec39 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1089,14 +1089,40 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, var ( stateSyncData []*types.StateSyncData err error + vmCfg vm.Config ) + if bc, ok := chain.(*core.BlockChain); ok { + vmCfg = *bc.GetVMConfig() + } + if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { start := time.Now() cx := statefull.ChainContext{Chain: chain, Bor: c} + + // Start tracing StateSyncTx (if present in the block body) + var stateSyncTx *types.Transaction + if c.config.IsMadhugiri(header.Number) && len(body.Transactions) > 0 { + lastTx := body.Transactions[len(body.Transactions)-1] + if lastTx.Type() == types.StateSyncTxType { + stateSyncTx = lastTx + hasTracer := vmCfg.Tracer != nil + log.Info("[DEBUG] StateSyncTx found in Finalize", "block", headerNumber, "txHash", lastTx.Hash(), "hasTracer", hasTracer) + if hooks := vmCfg.Tracer; hooks != nil && hooks.OnTxStart != nil { + // todo(milando12): check how much overhead this adds, if it does we can initialize it earlier and pass down to ApplyMessage() + vmenv := vm.NewEVM( + core.NewEVMBlockContext(header, cx, &header.Coinbase), + wrappedState, c.chainConfig, vmCfg, + ) + log.Info("[DEBUG] StateSyncTx OnTxStart", "block", headerNumber, "txHash", stateSyncTx.Hash()) + hooks.OnTxStart(vmenv.GetVMContext(), stateSyncTx, statefull.SystemAddress) + } + } + } + // check and commit span if !c.config.IsRio(header.Number) { - if err := c.checkAndCommitSpan(wrappedState, header, cx); err != nil { + if err := c.checkAndCommitSpan(wrappedState, header, cx, vmCfg); err != nil { log.Error("Error while committing span", "error", err) return nil } @@ -1104,11 +1130,14 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(wrappedState, header, cx) + stateSyncData, err = c.CommitStates(wrappedState, header, cx, vmCfg) if err != nil { log.Error("Error while committing states", "error", err) return nil } + if len(stateSyncData) > 0 { + log.Info("[DEBUG] StateSyncTx CommitStates completed", "block", headerNumber, "eventCount", len(stateSyncData)) + } } // Get the underlying state for updating consensus time state := wrappedState.Inner() @@ -1135,7 +1164,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, return receipts } if lastTx.Type() == types.StateSyncTxType { - receipts = insertStateSyncTransactionAndCalculateReceipt(lastTx, header, body, wrappedState, receipts) + receipts = insertStateSyncTransactionAndCalculateReceipt(lastTx, header, body, wrappedState, receipts, vmCfg) } } } else { @@ -1146,7 +1175,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, return receipts } -func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transaction, header *types.Header, body *types.Body, state vm.StateDB, receipts []*types.Receipt) []*types.Receipt { +func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transaction, header *types.Header, body *types.Body, state vm.StateDB, receipts []*types.Receipt, vmConfig vm.Config) []*types.Receipt { allLogs := state.Logs() sort.SliceStable(allLogs, func(i, j int) bool { return allLogs[i].Index < allLogs[j].Index @@ -1179,6 +1208,13 @@ func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transactio } stateSyncReceipt.Bloom = types.CreateBloom(stateSyncReceipt) + + // End tracing for StateSyncTx + if hooks := vmConfig.Tracer; hooks != nil && hooks.OnTxEnd != nil { + log.Info("[DEBUG] StateSyncTx OnTxEnd", "block", header.Number, "txHash", stateSyncTx.Hash(), "logCount", len(stateSyncLogs), "status", stateSyncReceipt.Status) + hooks.OnTxEnd(stateSyncReceipt, nil) + } + receipts = append(receipts, stateSyncReceipt) return receipts @@ -1235,14 +1271,19 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ var ( stateSyncData []*types.StateSyncData err error + vmCfg vm.Config ) + if bc, ok := chain.(*core.BlockChain); ok { + vmCfg = *bc.GetVMConfig() + } + if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span if !c.config.IsRio(header.Number) { - if err = c.checkAndCommitSpan(state, header, cx); err != nil { + if err = c.checkAndCommitSpan(state, header, cx, vmCfg); err != nil { log.Error("Error while committing span", "error", err) return nil, nil, 0, err } @@ -1250,7 +1291,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(state, header, cx) + stateSyncData, err = c.CommitStates(state, header, cx, vmCfg) if err != nil { log.Error("Error while committing states", "error", err) return nil, nil, 0, err @@ -1276,7 +1317,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ StateSyncData: stateSyncData, }) body.Transactions = append(body.Transactions, stateSyncTx) - receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, state, receipts) + receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, state, receipts, vmCfg) } else { // set state sync bc := chain.(core.BorStateSyncer) @@ -1484,6 +1525,7 @@ func (c *Bor) checkAndCommitSpan( state vm.StateDB, header *types.Header, chain core.ChainContext, + vmCfg vm.Config, ) error { var ctx = context.Background() headerNumber := header.Number.Uint64() @@ -1500,7 +1542,7 @@ func (c *Bor) checkAndCommitSpan( tempState.IntermediateRoot(false) if c.needToCommitSpan(span, headerNumber) { - return c.FetchAndCommitSpan(ctx, span.Id+1, state, header, chain) + return c.FetchAndCommitSpan(ctx, span.Id+1, state, header, chain, vmCfg) } return nil @@ -1539,6 +1581,7 @@ func (c *Bor) FetchAndCommitSpan( state vm.StateDB, header *types.Header, chain core.ChainContext, + vmCfg vm.Config, ) error { var ( minSpan borTypes.Span @@ -1602,7 +1645,7 @@ func (c *Bor) FetchAndCommitSpan( ) } - return c.spanner.CommitSpan(ctx, minSpan, validators, producers, state, header, chain) + return c.spanner.CommitSpan(ctx, minSpan, validators, producers, state, header, chain, vmCfg) } // CommitStates commit states @@ -1610,6 +1653,7 @@ func (c *Bor) CommitStates( state vm.StateDB, header *types.Header, chain statefull.ChainContext, + vmCfg vm.Config, ) ([]*types.StateSyncData, error) { fetchStart := time.Now() number := header.Number.Uint64() @@ -1723,7 +1767,7 @@ func (c *Bor) CommitStates( // we expect that this call MUST emit an event, otherwise we wouldn't make a receipt // if the receiver address is not a contract then we'll skip the most of the execution and emitting an event as well // https://github.com/0xPolygon/genesis-contracts/blob/master/contracts/StateReceiver.sol#L27 - gasUsed, err = c.GenesisContractsClient.CommitState(eventRecord, state, header, chain) + gasUsed, err = c.GenesisContractsClient.CommitState(eventRecord, state, header, chain, vmCfg) if err != nil { return nil, err } diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index d3f6f5be27..5ae0fdca51 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -62,7 +62,7 @@ func (s *fakeSpanner) GetCurrentValidatorsByHash(ctx context.Context, headerHash func (s *fakeSpanner) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context, _ rpc.BlockNumberOrHash, _ uint64) ([]*valset.Validator, error) { return s.vals, nil } -func (s *fakeSpanner) CommitSpan(ctx context.Context, _ borTypes.Span, _ []stakeTypes.MinimalVal, _ []stakeTypes.MinimalVal, _ vm.StateDB, _ *types.Header, _ core.ChainContext) error { +func (s *fakeSpanner) CommitSpan(ctx context.Context, _ borTypes.Span, _ []stakeTypes.MinimalVal, _ []stakeTypes.MinimalVal, _ vm.StateDB, _ *types.Header, _ core.ChainContext, _ vm.Config) error { if s.shouldFailCommit { return errors.New("span commit failed") } diff --git a/consensus/bor/contract/client.go b/consensus/bor/contract/client.go index 1ab8a9a754..c3f87f141c 100644 --- a/consensus/bor/contract/client.go +++ b/consensus/bor/contract/client.go @@ -74,6 +74,7 @@ func (gc *GenesisContractsClient) CommitState( state vm.StateDB, header *types.Header, chCtx statefull.ChainContext, + vmCfg vm.Config, ) (uint64, error) { eventRecord := event.BuildEventRecord() @@ -96,7 +97,7 @@ func (gc *GenesisContractsClient) CommitState( log.Info("→ committing new state", "eventRecord", event.ID) - gasUsed, err := statefull.ApplyMessage(context.Background(), msg, state, header, gc.chainConfig, chCtx) + gasUsed, err := statefull.ApplyMessage(context.Background(), msg, state, header, gc.chainConfig, chCtx, vmCfg) // Logging event log with time and individual gasUsed log.Info("→ committed new state", "eventRecord", event.String(gasUsed)) diff --git a/consensus/bor/genesis.go b/consensus/bor/genesis.go index 31c46ee2be..3d4757df2a 100644 --- a/consensus/bor/genesis.go +++ b/consensus/bor/genesis.go @@ -13,6 +13,6 @@ import ( //go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract type GenesisContract interface { - CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error) + CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext, vmCfg vm.Config) (uint64, error) LastStateId(state *state.StateDB, number uint64, hash common.Hash) (*big.Int, error) } diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go index f63da09638..8569765b97 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/consensus/bor/heimdall/span/spanner.go @@ -291,7 +291,7 @@ func (c *ChainSpanner) GetCurrentValidatorsByHash(ctx context.Context, headerHas const method = "commitSpan" -func (c *ChainSpanner) CommitSpan(ctx context.Context, minimalSpan borTypes.Span, validators, producers []stakeTypes.MinimalVal, state vm.StateDB, header *types.Header, chainContext core.ChainContext) error { +func (c *ChainSpanner) CommitSpan(ctx context.Context, minimalSpan borTypes.Span, validators, producers []stakeTypes.MinimalVal, state vm.StateDB, header *types.Header, chainContext core.ChainContext, vmCfg vm.Config) error { // get validators bytes validatorBytes, err := rlp.EncodeToBytes(validators) if err != nil { @@ -329,7 +329,7 @@ func (c *ChainSpanner) CommitSpan(ctx context.Context, minimalSpan borTypes.Span msg := statefull.GetSystemMessage(c.validatorContractAddress, data) // apply message - _, err = statefull.ApplyMessage(ctx, msg, state, header, c.chainConfig, chainContext) + _, err = statefull.ApplyMessage(ctx, msg, state, header, c.chainConfig, chainContext, vmCfg) return err } diff --git a/consensus/bor/span.go b/consensus/bor/span.go index 06f2673894..3680381c75 100644 --- a/consensus/bor/span.go +++ b/consensus/bor/span.go @@ -20,5 +20,5 @@ type Spanner interface { GetCurrentSpan(ctx context.Context, headerHash common.Hash, state *state.StateDB) (*borTypes.Span, error) GetCurrentValidatorsByHash(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64) ([]*valset.Validator, error) - CommitSpan(ctx context.Context, minimalSpan borTypes.Span, validators, producers []stakeTypes.MinimalVal, state vm.StateDB, header *types.Header, chainContext core.ChainContext) error + CommitSpan(ctx context.Context, minimalSpan borTypes.Span, validators, producers []stakeTypes.MinimalVal, state vm.StateDB, header *types.Header, chainContext core.ChainContext, vmCfg vm.Config) error } diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go index ca84d9057a..e1fb708ded 100644 --- a/consensus/bor/statefull/processor.go +++ b/consensus/bor/statefull/processor.go @@ -17,7 +17,7 @@ import ( "github.com/ethereum/go-ethereum/params" ) -var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") +var SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") type ChainContext struct { Chain consensus.ChainHeaderReader @@ -70,7 +70,7 @@ func (m Callmsg) Data() []byte { return m.CallMsg.Data } func GetSystemMessage(toAddress common.Address, data []byte) Callmsg { return Callmsg{ ethereum.CallMsg{ - From: systemAddress, + From: SystemAddress, Gas: params.MaxTxGas, // should be more than enough for state-sync related syscalls GasPrice: big.NewInt(0), Value: big.NewInt(0), @@ -88,6 +88,7 @@ func ApplyMessage( header *types.Header, chainConfig *params.ChainConfig, chainContext core.ChainContext, + vmConfig vm.Config, ) (uint64, error) { initialGas := msg.Gas() @@ -96,7 +97,7 @@ func ApplyMessage( // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(blockContext, state, chainConfig, vm.Config{}) + vmenv := vm.NewEVM(blockContext, state, chainConfig, vmConfig) // nolint : contextcheck // Apply the transaction to the current state (included in the env) diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml index cf39142ccf..1118254c18 100644 --- a/docs/cli/example_config.toml +++ b/docs/cli/example_config.toml @@ -26,11 +26,13 @@ devfakeauthor = false # Run miner without validator set authorization "32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68" [log] - vmodule = "" # Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) - json = false # Format logs with JSON - backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271") - debug = true # Prepends log messages with call-site location (file and line number) - enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle +vmodule = "" # Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) +json = false # Format logs with JSON +backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271") +debug = true # Prepends log messages with call-site location (file and line number) +enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle +vmtrace = "supply" # Name of a tracer to record internal VM operations during blockchain synchronization (costly) +vmtrace.jsonconfig = '{"path": "output"}' # Tracer configuration (JSON) [p2p] maxpeers = 50 # Maximum number of network peers (network disabled if set to 0) diff --git a/docs/cli/server.md b/docs/cli/server.md index b10194153c..e422a9b29a 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -262,6 +262,10 @@ The ```bor server``` command runs the Bor client. - ```vmodule```: Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) +- ```vmtrace```: Name of a tracer to record internal VM operations during blockchain synchronization (costly) + +- ```vmtrace.jsonconfig```: Tracer configuration (JSON) (default: {}) + ### P2P Options - ```bind```: Network binding address (default: 0.0.0.0) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 4a550f8610..5d37516660 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -723,7 +723,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config if includeStateSyncTx { callmsg := prepareCallMessage(*msg) statedb.SetTxContext(stateSyncHash, i) - if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx)); err != nil { + if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx), vm.Config{}); err != nil { log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", stateSyncHash, "err", err) // We intentionally don't return the error here: if we do, then the RPC server will not // return the roots. Most likely, the caller already knows that a certain transaction fails to diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index cee9219214..55379cdd52 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -164,6 +164,12 @@ type Config struct { // HealthConfig has health check related settings Health *HealthConfig `hcl:"health,block" toml:"health,block"` + + // VMTrace Name of tracer which should record internal VM operations (costly) + VMTrace string `hcl:"vmtrace,optional" toml:"vmtrace,optional"` + + // VMTraceJsonConfig Tracer configuration (JSON) + VMTraceJsonConfig string `hcl:"vmtrace.jsonconfig,optional" toml:"vmtrace.jsonconfig,optional"` } type HistoryConfig struct { @@ -996,6 +1002,8 @@ func DefaultConfig() *Config { LogNoHistory: ethconfig.Defaults.LogNoHistory, StateHistory: params.FullImmutabilityThreshold, }, + VMTrace: "", + VMTraceJsonConfig: "{}", Health: &HealthConfig{ MaxGoRoutineThreshold: 0, WarnGoRoutineThreshold: 0, @@ -1545,6 +1553,8 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* } n.EnableBlockTracking = c.Logging.EnableBlockTracking + n.VMTrace = c.VMTrace + n.VMTraceJsonConfig = c.VMTraceJsonConfig // Blind fork acceptance configs n.DisableBlindForkValidation = c.DisableBlindForkValidation diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index a7ae19265c..df3174d6d4 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -143,6 +143,20 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { Default: c.cliConfig.Logging.Vmodule, Group: "Logging", }) + f.StringFlag(&flagset.StringFlag{ + Name: "vmtrace", + Usage: "Name of a tracer to record internal VM operations during blockchain synchronization (costly)", + Value: &c.cliConfig.VMTrace, + Default: c.cliConfig.VMTrace, + Group: "Logging", + }) + f.StringFlag(&flagset.StringFlag{ + Name: "vmtrace.jsonconfig", + Usage: "Tracer configuration (JSON)", + Value: &c.cliConfig.VMTraceJsonConfig, + Default: c.cliConfig.VMTraceJsonConfig, + Group: "Logging", + }) f.BoolFlag(&flagset.BoolFlag{ Name: "log.json", Usage: "Format logs with JSON", From 7b13a888fade81f2c2c9aec8e36e056608ab0aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Fri, 6 Feb 2026 09:56:54 +0100 Subject: [PATCH 02/30] generate mocks --- consensus/bor/genesis_contract_mock.go | 8 ++++---- consensus/bor/span_mock.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go index 5b80826202..9268adf437 100644 --- a/consensus/bor/genesis_contract_mock.go +++ b/consensus/bor/genesis_contract_mock.go @@ -41,18 +41,18 @@ func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder { } // CommitState mocks base method. -func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 vm.StateDB, arg2 *types.Header, arg3 statefull.ChainContext) (uint64, error) { +func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 vm.StateDB, arg2 *types.Header, arg3 statefull.ChainContext, arg4 vm.Config) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitState", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "CommitState", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // CommitState indicates an expected call of CommitState. -func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1, arg2, arg3, arg4) } // LastStateId mocks base method. diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go index 31e2319ad1..7c32e47c7f 100644 --- a/consensus/bor/span_mock.go +++ b/consensus/bor/span_mock.go @@ -44,17 +44,17 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder { } // CommitSpan mocks base method. -func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 types.Span, arg2, arg3 []types0.MinimalVal, arg4 vm.StateDB, arg5 *types1.Header, arg6 core.ChainContext) error { +func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 types.Span, arg2, arg3 []types0.MinimalVal, arg4 vm.StateDB, arg5 *types1.Header, arg6 core.ChainContext, arg7 vm.Config) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4, arg5, arg6) + ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) ret0, _ := ret[0].(error) return ret0 } // CommitSpan indicates an expected call of CommitSpan. -func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4, arg5, arg6 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4, arg5, arg6) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) } // GetCurrentSpan mocks base method. From 12e21b65d8931a4a930dd7867228e6c973ee3e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Thu, 12 Feb 2026 20:14:00 +0100 Subject: [PATCH 03/30] Remove debug trace logs from StateSyncTx processing Remove the 4 [DEBUG] log lines that were added during development to diagnose StateSyncTx tracing issues. --- consensus/bor/bor.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 3604cdec39..5992f1455e 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1106,15 +1106,12 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, lastTx := body.Transactions[len(body.Transactions)-1] if lastTx.Type() == types.StateSyncTxType { stateSyncTx = lastTx - hasTracer := vmCfg.Tracer != nil - log.Info("[DEBUG] StateSyncTx found in Finalize", "block", headerNumber, "txHash", lastTx.Hash(), "hasTracer", hasTracer) if hooks := vmCfg.Tracer; hooks != nil && hooks.OnTxStart != nil { // todo(milando12): check how much overhead this adds, if it does we can initialize it earlier and pass down to ApplyMessage() vmenv := vm.NewEVM( core.NewEVMBlockContext(header, cx, &header.Coinbase), wrappedState, c.chainConfig, vmCfg, ) - log.Info("[DEBUG] StateSyncTx OnTxStart", "block", headerNumber, "txHash", stateSyncTx.Hash()) hooks.OnTxStart(vmenv.GetVMContext(), stateSyncTx, statefull.SystemAddress) } } @@ -1135,10 +1132,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, log.Error("Error while committing states", "error", err) return nil } - if len(stateSyncData) > 0 { - log.Info("[DEBUG] StateSyncTx CommitStates completed", "block", headerNumber, "eventCount", len(stateSyncData)) } - } // Get the underlying state for updating consensus time state := wrappedState.Inner() state.BorConsensusTime = time.Since(start) @@ -1211,7 +1205,6 @@ func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transactio // End tracing for StateSyncTx if hooks := vmConfig.Tracer; hooks != nil && hooks.OnTxEnd != nil { - log.Info("[DEBUG] StateSyncTx OnTxEnd", "block", header.Number, "txHash", stateSyncTx.Hash(), "logCount", len(stateSyncLogs), "status", stateSyncReceipt.Status) hooks.OnTxEnd(stateSyncReceipt, nil) } From 276a40489da72dd8c8b12deaecde176dbfa751de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Thu, 12 Feb 2026 20:15:49 +0100 Subject: [PATCH 04/30] Propagate VM config through HeaderChain for tracer access When Finalize is called, the chain parameter can be a *core.HeaderChain (not just *core.BlockChain). Without this change, the tracer in vmCfg is nil during finalization, so StateSyncTx tracing hooks never fire. - Add vmConfig field and GetVMConfig() method to HeaderChain - Set hc.vmConfig in NewBlockChain after creating the HeaderChain - Add else-if branch in Finalize and FinalizeAndAssemble to extract VM config from HeaderChain --- consensus/bor/bor.go | 8 ++++++++ core/blockchain.go | 1 + core/headerchain.go | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 5992f1455e..186dab6206 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1094,6 +1094,10 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, if bc, ok := chain.(*core.BlockChain); ok { vmCfg = *bc.GetVMConfig() + } else if hc, ok := chain.(*core.HeaderChain); ok { + if cfg := hc.GetVMConfig(); cfg != nil { + vmCfg = *cfg + } } if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { @@ -1269,6 +1273,10 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ if bc, ok := chain.(*core.BlockChain); ok { vmCfg = *bc.GetVMConfig() + } else if hc, ok := chain.(*core.HeaderChain); ok { + if cfg := hc.GetVMConfig(); cfg != nil { + vmCfg = *cfg + } } if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { diff --git a/core/blockchain.go b/core/blockchain.go index 2863519b74..f51f7e2cba 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -464,6 +464,7 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, if err != nil { return nil, err } + bc.hc.vmConfig = &bc.cfg.VmConfig bc.flushInterval.Store(int64(cfg.TrieTimeLimit)) bc.forker = NewForkChoice(bc, cfg.ShouldPreserve, cfg.Checker) diff --git a/core/headerchain.go b/core/headerchain.go index 08362e4daa..660b464716 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -71,6 +72,7 @@ type HeaderChain struct { procInterrupt func() bool engine consensus.Engine + vmConfig *vm.Config // VM configuration (propagated from BlockChain) stateSyncData []*types.StateSyncData // State sync data } @@ -106,6 +108,11 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c return hc, nil } +// GetVMConfig returns the VM config propagated from BlockChain, or nil if not set. +func (hc *HeaderChain) GetVMConfig() *vm.Config { + return hc.vmConfig +} + // GetBlockNumber retrieves the block number belonging to the given hash // from the cache or database func (hc *HeaderChain) GetBlockNumber(hash common.Hash) (uint64, bool) { From 2b43baf0f1276bece126767c2608792f39f5d27b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Thu, 12 Feb 2026 20:17:39 +0100 Subject: [PATCH 05/30] Pass tracingStateDB to Finalize in state processor The Process function creates a tracingStateDB wrapper for tracing but was passing the unwrapped statedb to Finalize, causing the tracer to miss StateSyncTx state changes. --- core/state_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state_processor.go b/core/state_processor.go index 7bbbd9a245..f6e98306bc 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -155,7 +155,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Finalize the block, applying any consensus engine specific extras (e.g. block rewards), apply // state sync event (if any), and append the receipt. receiptsCountBeforeFinalize := len(receipts) - receipts = p.chain.Engine().Finalize(p.chain, header, statedb, block.Body(), receipts) + receipts = p.chain.Engine().Finalize(p.chain, header, tracingStateDB, block.Body(), receipts) // apply state sync logs if p.chainConfig().Bor != nil && p.chainConfig().Bor.IsMadhugiri(block.Number()) { From afa51c2d0815d1e77d3cd6d9f96358f34eaf085d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Mon, 23 Feb 2026 16:19:33 +0100 Subject: [PATCH 06/30] Add vm.Config parameter to failingGenesisContract's CommitState method Expand the `CommitState` method signature to include the `vm.Config` parameter, enabling proper VM tracing integration and configuration. --- consensus/bor/bor_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index 5ae0fdca51..2260d90881 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -75,7 +75,7 @@ type failingHeimdallClient struct{} // failingGenesisContract simulates GenesisContract failures type failingGenesisContract struct{} -func (f *failingGenesisContract) CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error) { +func (f *failingGenesisContract) CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext, vmCfg vm.Config) (uint64, error) { return 0, errors.New("commit state failed") } From ee7c1221e866abec2ac618a0b003472eedc9f75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Mon, 23 Feb 2026 16:21:17 +0100 Subject: [PATCH 07/30] Refactor StateSyncTx tracing logic to instantiate only if tracing is enabled --- consensus/bor/bor.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 186dab6206..3267f4a563 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1105,18 +1105,16 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, cx := statefull.ChainContext{Chain: chain, Bor: c} // Start tracing StateSyncTx (if present in the block body) - var stateSyncTx *types.Transaction - if c.config.IsMadhugiri(header.Number) && len(body.Transactions) > 0 { - lastTx := body.Transactions[len(body.Transactions)-1] - if lastTx.Type() == types.StateSyncTxType { - stateSyncTx = lastTx - if hooks := vmCfg.Tracer; hooks != nil && hooks.OnTxStart != nil { + if hooks := vmCfg.Tracer; hooks != nil && hooks.OnTxStart != nil { + if c.config.IsMadhugiri(header.Number) && len(body.Transactions) > 0 { + lastTx := body.Transactions[len(body.Transactions)-1] + if lastTx.Type() == types.StateSyncTxType { // todo(milando12): check how much overhead this adds, if it does we can initialize it earlier and pass down to ApplyMessage() vmenv := vm.NewEVM( core.NewEVMBlockContext(header, cx, &header.Coinbase), wrappedState, c.chainConfig, vmCfg, ) - hooks.OnTxStart(vmenv.GetVMContext(), stateSyncTx, statefull.SystemAddress) + hooks.OnTxStart(vmenv.GetVMContext(), lastTx, statefull.SystemAddress) } } } @@ -1136,7 +1134,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, log.Error("Error while committing states", "error", err) return nil } - } + } // Get the underlying state for updating consensus time state := wrappedState.Inner() state.BorConsensusTime = time.Since(start) From f1e065e123757cd589c2c7c24efd2d0559837229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Mon, 23 Feb 2026 16:37:41 +0100 Subject: [PATCH 08/30] Remove unused comment in StateSyncTx tracing initialization logic EVM struct has a comment saying never reuse --- consensus/bor/bor.go | 1 - 1 file changed, 1 deletion(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 3267f4a563..f8c2167ff5 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1109,7 +1109,6 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, if c.config.IsMadhugiri(header.Number) && len(body.Transactions) > 0 { lastTx := body.Transactions[len(body.Transactions)-1] if lastTx.Type() == types.StateSyncTxType { - // todo(milando12): check how much overhead this adds, if it does we can initialize it earlier and pass down to ApplyMessage() vmenv := vm.NewEVM( core.NewEVMBlockContext(header, cx, &header.Coinbase), wrappedState, c.chainConfig, vmCfg, From 9e48c5e5c8ee7727b1a2487764155e2f191803a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Tue, 24 Feb 2026 14:26:50 +0100 Subject: [PATCH 09/30] trigger PR update From 8ddbaad2ace1d3517ffe96fd82d258019a80a981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Tue, 24 Feb 2026 14:28:05 +0100 Subject: [PATCH 10/30] trigger PR update From fbbc5069577a29351f15f2b09e1d7afa3977f2f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Fri, 27 Feb 2026 12:47:38 +0100 Subject: [PATCH 11/30] Add `vm.Config` parameter to methods for improved VM tracing support - Update method signatures to include `vm.Config`, enabling better VM tracing and configuration integration in testing and state processing logic. --- consensus/bor/bor_test.go | 30 +++++++++++++++--------------- tests/bor/bor_test.go | 2 +- tests/bor/helper.go | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index 4ec08c3de4..a3d405c9bc 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -2049,7 +2049,7 @@ func TestInsertStateSyncTransactionAndCalculateReceipt(t *testing.T) { }, } - receipts := insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, mockState, existingReceipts) + receipts := insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, mockState, existingReceipts, vm.Config{}) require.Len(t, receipts, 2) ssReceipt := receipts[1] @@ -2620,7 +2620,7 @@ func TestFetchAndCommitSpan_WithHeimdallClient(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) } @@ -2654,7 +2654,7 @@ func TestFetchAndCommitSpan_ChainIDMismatch(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.Error(t, err) require.Contains(t, err.Error(), "doesn't match") } @@ -2673,7 +2673,7 @@ func TestFetchAndCommitSpan_NilResponse(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.Error(t, err) } @@ -2718,7 +2718,7 @@ func TestCommitStates_WithOverrideSkip(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: genesis.Time + 32} // CommitStates with override that sets records to 0 should skip - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Empty(t, result) } @@ -2750,7 +2750,7 @@ func TestCommitStates_WithIndore(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: genesis.Time + 32} - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Empty(t, result) // no events } @@ -2793,7 +2793,7 @@ func TestCommitStates_WithEvents(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: uint64(now.Unix())} - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Len(t, result, 1) require.Equal(t, uint64(1), result[0].ID) @@ -3169,7 +3169,7 @@ type mockGenesisContractForCommitStatesIndore struct { gasUsed uint64 } -func (m *mockGenesisContractForCommitStatesIndore) CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error) { +func (m *mockGenesisContractForCommitStatesIndore) CommitState(event *clerk.EventRecordWithTime, state vm.StateDB, header *types.Header, chCtx statefull.ChainContext, vmCfg vm.Config) (uint64, error) { return m.gasUsed, nil } @@ -3229,7 +3229,7 @@ func TestCommitStates_WithIndore_EventProcessing(t *testing.T) { Time: uint64(now.Unix()), } - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Len(t, result, 2) // both events should be processed } @@ -3283,7 +3283,7 @@ func TestCommitStates_NonIndore(t *testing.T) { Time: uint64(time.Now().Unix()), } - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Len(t, result, 1) } @@ -3808,7 +3808,7 @@ func TestCommitStates_WithOverrideStateSyncRecords(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) // With OverrideStateSyncRecords truncating to 0, should get empty data require.Empty(t, data) @@ -4068,7 +4068,7 @@ func TestCommitStates_WithOverrideStateSyncRecordsInRange(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) require.Empty(t, data) // truncated to 0 by range override } @@ -4107,7 +4107,7 @@ func TestCommitStates_StateSyncEventsError(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) // error is logged but returns empty data require.Empty(t, data) } @@ -4157,7 +4157,7 @@ func TestCommitStates_EventIdLessThanLastStateId(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) // Event ID=3 should be skipped (3 <= 5), event ID=6 should be processed require.Len(t, data, 1) @@ -4206,7 +4206,7 @@ func TestCommitStates_EventValidationError(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) require.NoError(t, err) // validation error is logged but returned data should be empty require.Empty(t, data) } diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go index a7eac3e37f..85114579b7 100644 --- a/tests/bor/bor_test.go +++ b/tests/bor/bor_test.go @@ -2928,7 +2928,7 @@ func getMockedSpannerWithSpanRotation(t *testing.T, validator1, validator2 commo } spanner.EXPECT().GetCurrentSpan(gomock.Any(), gomock.Any(), gomock.Any()).Return(span1Mock, nil).AnyTimes() - spanner.EXPECT().CommitSpan(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + spanner.EXPECT().CommitSpan(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() return spanner } diff --git a/tests/bor/helper.go b/tests/bor/helper.go index 2f261e999d..9cff5c76b2 100644 --- a/tests/bor/helper.go +++ b/tests/bor/helper.go @@ -495,7 +495,7 @@ func getMockedSpanner(t *testing.T, validators []*valset.Validator) *bor.MockSpa spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return(validators, nil).AnyTimes() spanner.EXPECT().GetCurrentValidatorsByBlockNrOrHash(gomock.Any(), gomock.Any(), gomock.Any()).Return(validators, nil).AnyTimes() spanner.EXPECT().GetCurrentSpan(gomock.Any(), gomock.Any(), gomock.Any()).Return(mockSpan, nil).AnyTimes() - spanner.EXPECT().CommitSpan(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + spanner.EXPECT().CommitSpan(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() return spanner } From 8c27ab38a2dcb15d918cb2503db809c4d1120d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Fri, 27 Feb 2026 13:00:11 +0100 Subject: [PATCH 12/30] trigger PR update From 52a90b40b45d05f2c9252c333ca586b4f8224b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Fri, 27 Feb 2026 14:43:43 +0100 Subject: [PATCH 13/30] Refactor: Extract VM config retrieval logic into `extractVMConfig` helper function - Consolidate duplicate code for retrieving `vm.Config` from `ChainHeaderReader`. - Simplify `Finalize` method by utilizing the new helper. --- consensus/bor/bor.go | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index a00f4cdc70..cd00e129fd 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1123,6 +1123,19 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, w return nil } +// extractVMConfig retrieves the vm.Config from the chain reader, if available. +func extractVMConfig(chain consensus.ChainHeaderReader) vm.Config { + if bc, ok := chain.(*core.BlockChain); ok { + return *bc.GetVMConfig() + } + if hc, ok := chain.(*core.HeaderChain); ok { + if cfg := hc.GetVMConfig(); cfg != nil { + return *cfg + } + } + return vm.Config{} +} + // 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, receipts []*types.Receipt) []*types.Receipt { @@ -1137,16 +1150,9 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, var ( stateSyncData []*types.StateSyncData err error - vmCfg vm.Config ) - if bc, ok := chain.(*core.BlockChain); ok { - vmCfg = *bc.GetVMConfig() - } else if hc, ok := chain.(*core.HeaderChain); ok { - if cfg := hc.GetVMConfig(); cfg != nil { - vmCfg = *cfg - } - } + vmCfg := extractVMConfig(chain) if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { start := time.Now() @@ -1313,16 +1319,9 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ var ( stateSyncData []*types.StateSyncData err error - vmCfg vm.Config ) - if bc, ok := chain.(*core.BlockChain); ok { - vmCfg = *bc.GetVMConfig() - } else if hc, ok := chain.(*core.HeaderChain); ok { - if cfg := hc.GetVMConfig(); cfg != nil { - vmCfg = *cfg - } - } + vmCfg := extractVMConfig(chain) if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} From c2d6e33e2151c5e4b47bd9521abcbacffb7417b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Mon, 2 Mar 2026 09:26:55 +0100 Subject: [PATCH 14/30] eth/tracers: fix supply tracer tests to expect block rewards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state processor now passes the traced (hooked) StateDB to the consensus engine's Finalize method, so live tracers can observe balance changes from block reward distribution. This is the correct behavior — previously, Finalize received the raw StateDB, making block rewards invisible to live tracers like the supply tracer. Update TestSupplyRewards and TestSupplyEip1559Burn to include the expected ethash block reward (2 ETH) in their assertions, matching the new traced output. --- eth/tracers/internal/tracetest/supply_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eth/tracers/internal/tracetest/supply_test.go b/eth/tracers/internal/tracetest/supply_test.go index 7d6325646e..1811c3809b 100644 --- a/eth/tracers/internal/tracetest/supply_test.go +++ b/eth/tracers/internal/tracetest/supply_test.go @@ -142,6 +142,9 @@ func TestSupplyRewards(t *testing.T) { ) expected := supplyInfo{ + Issuance: &supplyInfoIssuance{ + Reward: (*hexutil.Big)(ethash.ConstantinopleBlockReward.ToBig()), + }, Number: 1, Hash: common.HexToHash("0xcbb08370505be503dafedc4e96d139ea27aba3cbc580148568b8a307b3f51052"), ParentHash: common.HexToHash("0xadeda0a83e337b6c073e3f0e9a17531a04009b397a9588c093b628f21b8bc5a3"), @@ -251,6 +254,9 @@ func TestSupplyEip1559Burn(t *testing.T) { head = chain.CurrentBlock() burn = new(big.Int).Mul(big.NewInt(21000), head.BaseFee) expected = supplyInfo{ + Issuance: &supplyInfoIssuance{ + Reward: (*hexutil.Big)(ethash.ConstantinopleBlockReward.ToBig()), + }, Burn: &supplyInfoBurn{ EIP1559: (*hexutil.Big)(burn), }, From bd255d4284c3b9af6df9eac585d0bd8f0a88cb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Do=C5=A1li=C4=87?= Date: Thu, 12 Mar 2026 09:14:05 +0100 Subject: [PATCH 15/30] consensus/bor: use getter for systemAddress instead of exporting variable --- consensus/bor/bor.go | 2 +- consensus/bor/statefull/processor.go | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index f5a0503cf9..518f26bbd9 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1214,7 +1214,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, core.NewEVMBlockContext(header, cx, &header.Coinbase), wrappedState, c.chainConfig, vmCfg, ) - hooks.OnTxStart(vmenv.GetVMContext(), lastTx, statefull.SystemAddress) + hooks.OnTxStart(vmenv.GetVMContext(), lastTx, statefull.GetSystemAddress()) } } } diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go index 3d8d0b308b..98eb7c48ae 100644 --- a/consensus/bor/statefull/processor.go +++ b/consensus/bor/statefull/processor.go @@ -17,7 +17,11 @@ import ( "github.com/ethereum/go-ethereum/params" ) -var SystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") +var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") + +func GetSystemAddress() common.Address { + return systemAddress +} type ChainContext struct { Chain consensus.ChainHeaderReader @@ -70,7 +74,7 @@ func (m Callmsg) Data() []byte { return m.CallMsg.Data } func GetSystemMessage(toAddress common.Address, data []byte) Callmsg { return Callmsg{ ethereum.CallMsg{ - From: SystemAddress, + From: systemAddress, Gas: params.MaxTxGas, // should be more than enough for state-sync related syscalls GasPrice: big.NewInt(0), Value: big.NewInt(0), From 8304f4a6010d1ab13c463f96d7299981ec29df7e Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 00:30:23 +0530 Subject: [PATCH 16/30] refactor state-sync tracing --- consensus/bor/bor.go | 66 +++--------- consensus/bor/bor_test.go | 28 ++--- consensus/bor/genesis_contract_mock.go | 3 +- consensus/bor/span_mock.go | 3 +- consensus/bor/statefull/processor.go | 8 +- core/parallel_state_processor.go | 12 ++- core/state_processor.go | 12 ++- eth/backend.go | 3 + eth/filters/IBackend.go | 141 ++++++++++++++++++++++++- eth/filters/IBatch.go | 3 +- eth/filters/IDatabase.go | 3 +- eth/filters/IIterator.go | 2 +- params/protocol_params.go | 4 + tests/bor/mocks/IHeimdallClient.go | 3 +- 14 files changed, 205 insertions(+), 86 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 518f26bbd9..69ba062a81 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -245,6 +245,7 @@ func BorRLP(header *types.Header, c *params.BorConfig) []byte { type Bor struct { chainConfig *params.ChainConfig // Chain config config *params.BorConfig // Consensus engine configuration parameters for bor consensus + vmConfig vm.Config // VM config (optional) for system transactions db ethdb.Database // Database to store and retrieve snapshot checkpoints recents *ttlcache.Cache[common.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs @@ -327,6 +328,7 @@ func New( c := &Bor{ chainConfig: chainConfig, config: borConfig, + vmConfig: vm.Config{}, db: db, ethAPI: ethAPI, recents: recents, @@ -366,6 +368,10 @@ func New( return c } +func (c *Bor) SetVMConfig(vmCfg vm.Config) { + c.vmConfig = vmCfg +} + // Author implements consensus.Engine, returning the Ethereum address recovered // from the signature in the header's extra-data section. func (c *Bor) Author(header *types.Header) (common.Address, error) { @@ -1170,19 +1176,6 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, w return nil } -// extractVMConfig retrieves the vm.Config from the chain reader, if available. -func extractVMConfig(chain consensus.ChainHeaderReader) vm.Config { - if bc, ok := chain.(*core.BlockChain); ok { - return *bc.GetVMConfig() - } - if hc, ok := chain.(*core.HeaderChain); ok { - if cfg := hc.GetVMConfig(); cfg != nil { - return *cfg - } - } - return vm.Config{} -} - // 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, receipts []*types.Receipt) []*types.Receipt { @@ -1199,29 +1192,13 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, err error ) - vmCfg := extractVMConfig(chain) - if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { start := time.Now() cx := statefull.ChainContext{Chain: chain, Bor: c} - // Start tracing StateSyncTx (if present in the block body) - if hooks := vmCfg.Tracer; hooks != nil && hooks.OnTxStart != nil { - if c.config.IsMadhugiri(header.Number) && len(body.Transactions) > 0 { - lastTx := body.Transactions[len(body.Transactions)-1] - if lastTx.Type() == types.StateSyncTxType { - vmenv := vm.NewEVM( - core.NewEVMBlockContext(header, cx, &header.Coinbase), - wrappedState, c.chainConfig, vmCfg, - ) - hooks.OnTxStart(vmenv.GetVMContext(), lastTx, statefull.GetSystemAddress()) - } - } - } - // check and commit span if !c.config.IsRio(header.Number) { - if err := c.checkAndCommitSpan(wrappedState, header, cx, vmCfg); err != nil { + if err := c.checkAndCommitSpan(wrappedState, header, cx); err != nil { log.Error("Error while committing span", "error", err) return nil } @@ -1229,7 +1206,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(wrappedState, header, cx, vmCfg) + stateSyncData, err = c.CommitStates(wrappedState, header, cx) if err != nil { log.Error("Error while committing states", "error", err) return nil @@ -1260,7 +1237,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, return receipts } if lastTx.Type() == types.StateSyncTxType { - receipts = insertStateSyncTransactionAndCalculateReceipt(lastTx, header, body, wrappedState, receipts, vmCfg) + receipts = insertStateSyncTransactionAndCalculateReceipt(lastTx, header, body, wrappedState, receipts) } } } else { @@ -1271,7 +1248,7 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, return receipts } -func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transaction, header *types.Header, body *types.Body, state vm.StateDB, receipts []*types.Receipt, vmConfig vm.Config) []*types.Receipt { +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 @@ -1304,12 +1281,6 @@ func insertStateSyncTransactionAndCalculateReceipt(stateSyncTx *types.Transactio } stateSyncReceipt.Bloom = types.CreateBloom(stateSyncReceipt) - - // End tracing for StateSyncTx - if hooks := vmConfig.Tracer; hooks != nil && hooks.OnTxEnd != nil { - hooks.OnTxEnd(stateSyncReceipt, nil) - } - receipts = append(receipts, stateSyncReceipt) return receipts @@ -1368,14 +1339,12 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ err error ) - vmCfg := extractVMConfig(chain) - if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span if !c.config.IsRio(header.Number) { - if err = c.checkAndCommitSpan(state, header, cx, vmCfg); err != nil { + if err = c.checkAndCommitSpan(state, header, cx); err != nil { log.Error("Error while committing span", "error", err) return nil, nil, 0, err } @@ -1383,7 +1352,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(state, header, cx, vmCfg) + stateSyncData, err = c.CommitStates(state, header, cx) if err != nil { log.Error("Error while committing states", "error", err) return nil, nil, 0, err @@ -1409,7 +1378,7 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ StateSyncData: stateSyncData, }) body.Transactions = append(body.Transactions, stateSyncTx) - receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, state, receipts, vmCfg) + receipts = insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, state, receipts) } else { // set state sync bc := chain.(core.BorStateSyncer) @@ -1611,7 +1580,6 @@ func (c *Bor) checkAndCommitSpan( state vm.StateDB, header *types.Header, chain core.ChainContext, - vmCfg vm.Config, ) error { var ctx = context.Background() headerNumber := header.Number.Uint64() @@ -1628,7 +1596,7 @@ func (c *Bor) checkAndCommitSpan( tempState.IntermediateRoot(false) if c.needToCommitSpan(span, headerNumber) { - return c.FetchAndCommitSpan(ctx, span.Id+1, state, header, chain, vmCfg) + return c.FetchAndCommitSpan(ctx, span.Id+1, state, header, chain) } return nil @@ -1667,7 +1635,6 @@ func (c *Bor) FetchAndCommitSpan( state vm.StateDB, header *types.Header, chain core.ChainContext, - vmCfg vm.Config, ) error { var ( minSpan borTypes.Span @@ -1731,7 +1698,7 @@ func (c *Bor) FetchAndCommitSpan( ) } - return c.spanner.CommitSpan(ctx, minSpan, validators, producers, state, header, chain, vmCfg) + return c.spanner.CommitSpan(ctx, minSpan, validators, producers, state, header, chain, c.vmConfig) } // CommitStates commit states @@ -1739,7 +1706,6 @@ func (c *Bor) CommitStates( state vm.StateDB, header *types.Header, chain statefull.ChainContext, - vmCfg vm.Config, ) ([]*types.StateSyncData, error) { fetchStart := time.Now() number := header.Number.Uint64() @@ -1853,7 +1819,7 @@ func (c *Bor) CommitStates( // we expect that this call MUST emit an event, otherwise we wouldn't make a receipt // if the receiver address is not a contract then we'll skip the most of the execution and emitting an event as well // https://github.com/0xPolygon/genesis-contracts/blob/master/contracts/StateReceiver.sol#L27 - gasUsed, err = c.GenesisContractsClient.CommitState(eventRecord, state, header, chain, vmCfg) + gasUsed, err = c.GenesisContractsClient.CommitState(eventRecord, state, header, chain, c.vmConfig) if err != nil { return nil, err } diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index 751ca477b5..807a1bbc56 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -2102,7 +2102,7 @@ func TestInsertStateSyncTransactionAndCalculateReceipt(t *testing.T) { }, } - receipts := insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, mockState, existingReceipts, vm.Config{}) + receipts := insertStateSyncTransactionAndCalculateReceipt(stateSyncTx, header, body, mockState, existingReceipts) require.Len(t, receipts, 2) ssReceipt := receipts[1] @@ -2673,7 +2673,7 @@ func TestFetchAndCommitSpan_WithHeimdallClient(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) } @@ -2707,7 +2707,7 @@ func TestFetchAndCommitSpan_ChainIDMismatch(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.Error(t, err) require.Contains(t, err.Error(), "doesn't match") } @@ -2726,7 +2726,7 @@ func TestFetchAndCommitSpan_NilResponse(t *testing.T) { h := &types.Header{Number: big.NewInt(64), ParentHash: genesis.Hash()} - err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + err := b.FetchAndCommitSpan(context.Background(), 1, statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.Error(t, err) } @@ -2771,7 +2771,7 @@ func TestCommitStates_WithOverrideSkip(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: genesis.Time + 32} // CommitStates with override that sets records to 0 should skip - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Empty(t, result) } @@ -2803,7 +2803,7 @@ func TestCommitStates_WithIndore(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: genesis.Time + 32} - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Empty(t, result) // no events } @@ -2846,7 +2846,7 @@ func TestCommitStates_WithEvents(t *testing.T) { h := &types.Header{Number: big.NewInt(16), ParentHash: genesis.Hash(), Time: uint64(now.Unix())} - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Len(t, result, 1) require.Equal(t, uint64(1), result[0].ID) @@ -3282,7 +3282,7 @@ func TestCommitStates_WithIndore_EventProcessing(t *testing.T) { Time: uint64(now.Unix()), } - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Len(t, result, 2) // both events should be processed } @@ -3336,7 +3336,7 @@ func TestCommitStates_NonIndore(t *testing.T) { Time: uint64(time.Now().Unix()), } - result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + result, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Len(t, result, 1) } @@ -3861,7 +3861,7 @@ func TestCommitStates_WithOverrideStateSyncRecords(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) // With OverrideStateSyncRecords truncating to 0, should get empty data require.Empty(t, data) @@ -4121,7 +4121,7 @@ func TestCommitStates_WithOverrideStateSyncRecordsInRange(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) require.Empty(t, data) // truncated to 0 by range override } @@ -4160,7 +4160,7 @@ func TestCommitStates_StateSyncEventsError(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) // error is logged but returns empty data require.Empty(t, data) } @@ -4210,7 +4210,7 @@ func TestCommitStates_EventIdLessThanLastStateId(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) // Event ID=3 should be skipped (3 <= 5), event ID=6 should be processed require.Len(t, data, 1) @@ -4259,7 +4259,7 @@ func TestCommitStates_EventValidationError(t *testing.T) { GasLimit: genesis.GasLimit, } - data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}, vm.Config{}) + data, err := b.CommitStates(statedb, h, statefull.ChainContext{Chain: chain.HeaderChain(), Bor: b}) require.NoError(t, err) // validation error is logged but returned data should be empty require.Empty(t, data) } diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go index 965676148c..685311af1b 100644 --- a/consensus/bor/genesis_contract_mock.go +++ b/consensus/bor/genesis_contract_mock.go @@ -8,14 +8,13 @@ import ( big "math/big" reflect "reflect" - gomock "go.uber.org/mock/gomock" - common "github.com/ethereum/go-ethereum/common" clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" statefull "github.com/ethereum/go-ethereum/consensus/bor/statefull" state "github.com/ethereum/go-ethereum/core/state" types "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" + gomock "github.com/golang/mock/gomock" ) // MockGenesisContract is a mock of GenesisContract interface. diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go index 6417b590d2..12229d1085 100644 --- a/consensus/bor/span_mock.go +++ b/consensus/bor/span_mock.go @@ -8,8 +8,6 @@ import ( context "context" reflect "reflect" - gomock "go.uber.org/mock/gomock" - types "github.com/0xPolygon/heimdall-v2/x/bor/types" types0 "github.com/0xPolygon/heimdall-v2/x/stake/types" common "github.com/ethereum/go-ethereum/common" @@ -19,6 +17,7 @@ import ( types1 "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" rpc "github.com/ethereum/go-ethereum/rpc" + gomock "github.com/golang/mock/gomock" ) // MockSpanner is a mock of Spanner interface. diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go index 98eb7c48ae..c731860846 100644 --- a/consensus/bor/statefull/processor.go +++ b/consensus/bor/statefull/processor.go @@ -17,12 +17,6 @@ import ( "github.com/ethereum/go-ethereum/params" ) -var systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") - -func GetSystemAddress() common.Address { - return systemAddress -} - type ChainContext struct { Chain consensus.ChainHeaderReader Bor consensus.Engine @@ -74,7 +68,7 @@ func (m Callmsg) Data() []byte { return m.CallMsg.Data } func GetSystemMessage(toAddress common.Address, data []byte) Callmsg { return Callmsg{ ethereum.CallMsg{ - From: systemAddress, + From: params.BorSystemAddress, Gas: params.MaxTxGas, // should be more than enough for state-sync related syscalls GasPrice: big.NewInt(0), Value: big.NewInt(0), diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go index 639aa16ad4..0617e02390 100644 --- a/core/parallel_state_processor.go +++ b/core/parallel_state_processor.go @@ -331,7 +331,8 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat ProcessParentBlockHash(block.ParentHash(), vmenv) } // Iterate over and process the individual transactions - for i, tx := range block.Transactions() { + txs := block.Transactions() + for i, tx := range txs { if tx.Type() == types.StateSyncTxType { continue } @@ -421,6 +422,12 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat return nil, err } + if len(txs) > 0 && txs[len(txs)-1].Type() == types.StateSyncTxType { + if hooks := vmenv.Config.Tracer; hooks != nil && hooks.OnTxStart != nil { + hooks.OnTxStart(vmenv.GetVMContext(), txs[len(txs)-1], params.BorSystemAddress) + } + } + // Polygon/bor: EIP-6110, EIP-7002, and EIP-7251 are not supported var requests [][]byte @@ -441,6 +448,9 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat if appliedNewStateSyncReceipt { allLogs = append(allLogs, receipts[len(receipts)-1].Logs...) } + if hooks := vmenv.Config.Tracer; hooks != nil && hooks.OnTxEnd != nil { + hooks.OnTxEnd(receipts[len(receipts)-1], nil) + } } return &ProcessResult{ diff --git a/core/state_processor.go b/core/state_processor.go index ffb6ab3dbb..8e00e0db5f 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -105,7 +105,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Iterate over and process the individual transactions - for i, tx := range block.Transactions() { + txs := block.Transactions() + for i, tx := range txs { // Check if execution should be cancelled or not select { case <-interruptCtx.Done(): @@ -132,6 +133,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs = append(allLogs, receipt.Logs...) } + if len(txs) > 0 && txs[len(txs)-1].Type() == types.StateSyncTxType { + if hooks := evm.Config.Tracer; hooks != nil && hooks.OnTxStart != nil { + hooks.OnTxStart(evm.GetVMContext(), txs[len(txs)-1], params.BorSystemAddress) + } + } + // Polygon/bor: EIP-6110, EIP-7002, and EIP-7251 are not supported // Read requests if Prague is enabled. var requests [][]byte @@ -168,6 +175,9 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if appliedNewStateSyncReceipt { allLogs = append(allLogs, receipts[len(receipts)-1].Logs...) } + if hooks := evm.Config.Tracer; hooks != nil && hooks.OnTxEnd != nil { + hooks.OnTxEnd(receipts[len(receipts)-1], nil) + } } return &ProcessResult{ diff --git a/eth/backend.go b/eth/backend.go index 3705f72514..a5f3903dc8 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -310,6 +310,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { return nil, fmt.Errorf("failed to create tracer %s: %v", config.VMTrace, err) } options.VmConfig.Tracer = t + if borEngine, ok := eth.engine.(*bor.Bor); ok { + borEngine.SetVMConfig(options.VmConfig) + } } checker := whitelist.NewService(chainDb, config.DisableBlindForkValidation, config.MaxBlindForkValidationLimit) diff --git a/eth/filters/IBackend.go b/eth/filters/IBackend.go index 7a0bc7565a..62db435d84 100644 --- a/eth/filters/IBackend.go +++ b/eth/filters/IBackend.go @@ -10,8 +10,6 @@ import ( reflect "reflect" time "time" - gomock "go.uber.org/mock/gomock" - ethereum "github.com/ethereum/go-ethereum" accounts "github.com/ethereum/go-ethereum/accounts" common "github.com/ethereum/go-ethereum/common" @@ -21,12 +19,14 @@ import ( filtermaps "github.com/ethereum/go-ethereum/core/filtermaps" state "github.com/ethereum/go-ethereum/core/state" stateless "github.com/ethereum/go-ethereum/core/stateless" + txpool "github.com/ethereum/go-ethereum/core/txpool" types "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" ethdb "github.com/ethereum/go-ethereum/ethdb" event "github.com/ethereum/go-ethereum/event" params "github.com/ethereum/go-ethereum/params" rpc "github.com/ethereum/go-ethereum/rpc" + gomock "github.com/golang/mock/gomock" ) // MockBackend is a mock of Backend interface. @@ -52,6 +52,34 @@ func (m *MockBackend) EXPECT() *MockBackendMockRecorder { return m.recorder } +// AcceptPreconfTxs mocks base method. +func (m *MockBackend) AcceptPreconfTxs() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AcceptPreconfTxs") + ret0, _ := ret[0].(bool) + return ret0 +} + +// AcceptPreconfTxs indicates an expected call of AcceptPreconfTxs. +func (mr *MockBackendMockRecorder) AcceptPreconfTxs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcceptPreconfTxs", reflect.TypeOf((*MockBackend)(nil).AcceptPreconfTxs)) +} + +// AcceptPrivateTxs mocks base method. +func (m *MockBackend) AcceptPrivateTxs() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AcceptPrivateTxs") + ret0, _ := ret[0].(bool) + return ret0 +} + +// AcceptPrivateTxs indicates an expected call of AcceptPrivateTxs. +func (mr *MockBackendMockRecorder) AcceptPrivateTxs() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AcceptPrivateTxs", reflect.TypeOf((*MockBackend)(nil).AcceptPrivateTxs)) +} + // AccountManager mocks base method. func (m *MockBackend) AccountManager() *accounts.Manager { m.ctrl.T.Helper() @@ -153,6 +181,21 @@ func (mr *MockBackendMockRecorder) ChainDb() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainDb", reflect.TypeOf((*MockBackend)(nil).ChainDb)) } +// CheckPreconfStatus mocks base method. +func (m *MockBackend) CheckPreconfStatus(arg0 common.Hash) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckPreconfStatus", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckPreconfStatus indicates an expected call of CheckPreconfStatus. +func (mr *MockBackendMockRecorder) CheckPreconfStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckPreconfStatus", reflect.TypeOf((*MockBackend)(nil).CheckPreconfStatus), arg0) +} + // CurrentBlock mocks base method. func (m *MockBackend) CurrentBlock() *types.Header { m.ctrl.T.Helper() @@ -756,6 +799,34 @@ func (mr *MockBackendMockRecorder) Pending() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pending", reflect.TypeOf((*MockBackend)(nil).Pending)) } +// PreconfEnabled mocks base method. +func (m *MockBackend) PreconfEnabled() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PreconfEnabled") + ret0, _ := ret[0].(bool) + return ret0 +} + +// PreconfEnabled indicates an expected call of PreconfEnabled. +func (mr *MockBackendMockRecorder) PreconfEnabled() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PreconfEnabled", reflect.TypeOf((*MockBackend)(nil).PreconfEnabled)) +} + +// PrivateTxEnabled mocks base method. +func (m *MockBackend) PrivateTxEnabled() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PrivateTxEnabled") + ret0, _ := ret[0].(bool) + return ret0 +} + +// PrivateTxEnabled indicates an expected call of PrivateTxEnabled. +func (mr *MockBackendMockRecorder) PrivateTxEnabled() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrivateTxEnabled", reflect.TypeOf((*MockBackend)(nil).PrivateTxEnabled)) +} + // ProtocolVersion mocks base method. func (m *MockBackend) ProtocolVersion() uint { m.ctrl.T.Helper() @@ -770,6 +841,18 @@ func (mr *MockBackendMockRecorder) ProtocolVersion() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProtocolVersion", reflect.TypeOf((*MockBackend)(nil).ProtocolVersion)) } +// PurgePrivateTx mocks base method. +func (m *MockBackend) PurgePrivateTx(arg0 common.Hash) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PurgePrivateTx", arg0) +} + +// PurgePrivateTx indicates an expected call of PurgePrivateTx. +func (mr *MockBackendMockRecorder) PurgePrivateTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgePrivateTx", reflect.TypeOf((*MockBackend)(nil).PurgePrivateTx), arg0) +} + // PurgeWhitelistedCheckpoint mocks base method. func (m *MockBackend) PurgeWhitelistedCheckpoint() { m.ctrl.T.Helper() @@ -878,6 +961,18 @@ func (mr *MockBackendMockRecorder) RPCTxSyncMaxTimeout() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RPCTxSyncMaxTimeout", reflect.TypeOf((*MockBackend)(nil).RPCTxSyncMaxTimeout)) } +// RecordPrivateTx mocks base method. +func (m *MockBackend) RecordPrivateTx(arg0 common.Hash) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RecordPrivateTx", arg0) +} + +// RecordPrivateTx indicates an expected call of RecordPrivateTx. +func (mr *MockBackendMockRecorder) RecordPrivateTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPrivateTx", reflect.TypeOf((*MockBackend)(nil).RecordPrivateTx), arg0) +} + // SendTx mocks base method. func (m *MockBackend) SendTx(arg0 context.Context, arg1 *types.Transaction) error { m.ctrl.T.Helper() @@ -980,6 +1075,34 @@ func (mr *MockBackendMockRecorder) SubmitHashrate(arg0, arg1 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitHashrate", reflect.TypeOf((*MockBackend)(nil).SubmitHashrate), arg0, arg1) } +// SubmitPrivateTx mocks base method. +func (m *MockBackend) SubmitPrivateTx(arg0 *types.Transaction) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitPrivateTx", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SubmitPrivateTx indicates an expected call of SubmitPrivateTx. +func (mr *MockBackendMockRecorder) SubmitPrivateTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitPrivateTx", reflect.TypeOf((*MockBackend)(nil).SubmitPrivateTx), arg0) +} + +// SubmitTxForPreconf mocks base method. +func (m *MockBackend) SubmitTxForPreconf(arg0 *types.Transaction) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubmitTxForPreconf", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SubmitTxForPreconf indicates an expected call of SubmitTxForPreconf. +func (mr *MockBackendMockRecorder) SubmitTxForPreconf(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitTxForPreconf", reflect.TypeOf((*MockBackend)(nil).SubmitTxForPreconf), arg0) +} + // SubmitWork mocks base method. func (m *MockBackend) SubmitWork(arg0 types.BlockNonce, arg1, arg2 common.Hash) (bool, error) { m.ctrl.T.Helper() @@ -1180,6 +1303,20 @@ func (mr *MockBackendMockRecorder) TxPoolContentFrom(arg0 interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxPoolContentFrom", reflect.TypeOf((*MockBackend)(nil).TxPoolContentFrom), arg0) } +// TxStatus mocks base method. +func (m *MockBackend) TxStatus(arg0 common.Hash) txpool.TxStatus { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TxStatus", arg0) + ret0, _ := ret[0].(txpool.TxStatus) + return ret0 +} + +// TxStatus indicates an expected call of TxStatus. +func (mr *MockBackendMockRecorder) TxStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxStatus", reflect.TypeOf((*MockBackend)(nil).TxStatus), arg0) +} + // UnprotectedAllowed mocks base method. func (m *MockBackend) UnprotectedAllowed() bool { m.ctrl.T.Helper() diff --git a/eth/filters/IBatch.go b/eth/filters/IBatch.go index 433cda017b..88dbb35ed2 100644 --- a/eth/filters/IBatch.go +++ b/eth/filters/IBatch.go @@ -7,9 +7,8 @@ package filters import ( reflect "reflect" - gomock "go.uber.org/mock/gomock" - ethdb "github.com/ethereum/go-ethereum/ethdb" + gomock "github.com/golang/mock/gomock" ) // MockBatch is a mock of Batch interface. diff --git a/eth/filters/IDatabase.go b/eth/filters/IDatabase.go index 221e4649f2..602a8f1c88 100644 --- a/eth/filters/IDatabase.go +++ b/eth/filters/IDatabase.go @@ -7,9 +7,8 @@ package filters import ( reflect "reflect" - gomock "go.uber.org/mock/gomock" - ethdb "github.com/ethereum/go-ethereum/ethdb" + gomock "github.com/golang/mock/gomock" ) // MockDatabase is a mock of Database interface. diff --git a/eth/filters/IIterator.go b/eth/filters/IIterator.go index 0dbf504414..7aa63b470a 100644 --- a/eth/filters/IIterator.go +++ b/eth/filters/IIterator.go @@ -7,7 +7,7 @@ package filters import ( reflect "reflect" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockIterator is a mock of Iterator interface. diff --git a/params/protocol_params.go b/params/protocol_params.go index 17d9fafae8..494f926f11 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -219,6 +219,10 @@ var ( DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. ) +// BorSystemAddress is used for doing system transactions for processing bor bridge events +// i.e. state-sync events. +var BorSystemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") + // System contracts. var ( // SystemAddress is where the system-transaction is sent from as per EIP-4788 diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go index 3608823bd4..8e5eda68d7 100644 --- a/tests/bor/mocks/IHeimdallClient.go +++ b/tests/bor/mocks/IHeimdallClient.go @@ -8,13 +8,12 @@ import ( context "context" reflect "reflect" - gomock "go.uber.org/mock/gomock" - types "github.com/0xPolygon/heimdall-v2/x/bor/types" coretypes "github.com/cometbft/cometbft/rpc/core/types" clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" checkpoint "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint" milestone "github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone" + gomock "github.com/golang/mock/gomock" ) // MockIHeimdallClient is a mock of IHeimdallClient interface. From 1ac659094c4bac515e9a6715d9c4df4f1ef7cd3f Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:00:10 +0530 Subject: [PATCH 17/30] fix mocks --- consensus/bor/genesis_contract_mock.go | 24 +- consensus/bor/span_mock.go | 40 ++- eth/filters/IBackend.go | 430 +++++++++++++------------ eth/filters/IBatch.go | 40 ++- eth/filters/IDatabase.go | 130 ++++---- eth/filters/IIterator.go | 8 +- tests/bor/mocks/IHeimdallClient.go | 29 +- 7 files changed, 372 insertions(+), 329 deletions(-) diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go index 685311af1b..3bd1b76cf8 100644 --- a/consensus/bor/genesis_contract_mock.go +++ b/consensus/bor/genesis_contract_mock.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: GenesisContract) +// +// Generated by this command: +// +// mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract +// // Package bor is a generated GoMock package. package bor @@ -14,13 +19,14 @@ import ( state "github.com/ethereum/go-ethereum/core/state" types "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockGenesisContract is a mock of GenesisContract interface. type MockGenesisContract struct { ctrl *gomock.Controller recorder *MockGenesisContractMockRecorder + isgomock struct{} } // MockGenesisContractMockRecorder is the mock recorder for MockGenesisContract. @@ -41,31 +47,31 @@ func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder { } // CommitState mocks base method. -func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 vm.StateDB, arg2 *types.Header, arg3 statefull.ChainContext, arg4 vm.Config) (uint64, error) { +func (m *MockGenesisContract) CommitState(event *clerk.EventRecordWithTime, arg1 vm.StateDB, header *types.Header, chCtx statefull.ChainContext, vmCfg vm.Config) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitState", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "CommitState", event, arg1, header, chCtx, vmCfg) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // CommitState indicates an expected call of CommitState. -func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockGenesisContractMockRecorder) CommitState(event, arg1, header, chCtx, vmCfg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), event, arg1, header, chCtx, vmCfg) } // LastStateId mocks base method. -func (m *MockGenesisContract) LastStateId(arg0 *state.StateDB, arg1 uint64, arg2 common.Hash) (*big.Int, error) { +func (m *MockGenesisContract) LastStateId(arg0 *state.StateDB, number uint64, hash common.Hash) (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LastStateId", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "LastStateId", arg0, number, hash) ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } // LastStateId indicates an expected call of LastStateId. -func (mr *MockGenesisContractMockRecorder) LastStateId(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockGenesisContractMockRecorder) LastStateId(arg0, number, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0, number, hash) } diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go index 12229d1085..4e3fde9ef0 100644 --- a/consensus/bor/span_mock.go +++ b/consensus/bor/span_mock.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: Spanner) +// +// Generated by this command: +// +// mockgen -destination=./span_mock.go -package=bor . Spanner +// // Package bor is a generated GoMock package. package bor @@ -17,13 +22,14 @@ import ( types1 "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" rpc "github.com/ethereum/go-ethereum/rpc" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockSpanner is a mock of Spanner interface. type MockSpanner struct { ctrl *gomock.Controller recorder *MockSpannerMockRecorder + isgomock struct{} } // MockSpannerMockRecorder is the mock recorder for MockSpanner. @@ -44,60 +50,60 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder { } // CommitSpan mocks base method. -func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 types.Span, arg2, arg3 []types0.MinimalVal, arg4 vm.StateDB, arg5 *types1.Header, arg6 core.ChainContext, arg7 vm.Config) error { +func (m *MockSpanner) CommitSpan(ctx context.Context, minimalSpan types.Span, validators, producers []types0.MinimalVal, arg4 vm.StateDB, header *types1.Header, chainContext core.ChainContext, vmCfg vm.Config) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) + ret := m.ctrl.Call(m, "CommitSpan", ctx, minimalSpan, validators, producers, arg4, header, chainContext, vmCfg) ret0, _ := ret[0].(error) return ret0 } // CommitSpan indicates an expected call of CommitSpan. -func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) CommitSpan(ctx, minimalSpan, validators, producers, arg4, header, chainContext, vmCfg any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), ctx, minimalSpan, validators, producers, arg4, header, chainContext, vmCfg) } // GetCurrentSpan mocks base method. -func (m *MockSpanner) GetCurrentSpan(arg0 context.Context, arg1 common.Hash, arg2 *state.StateDB) (*types.Span, error) { +func (m *MockSpanner) GetCurrentSpan(ctx context.Context, headerHash common.Hash, arg2 *state.StateDB) (*types.Span, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentSpan", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetCurrentSpan", ctx, headerHash, arg2) ret0, _ := ret[0].(*types.Span) ret1, _ := ret[1].(error) return ret0, ret1 } // GetCurrentSpan indicates an expected call of GetCurrentSpan. -func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) GetCurrentSpan(ctx, headerHash, arg2 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), ctx, headerHash, arg2) } // GetCurrentValidatorsByBlockNrOrHash mocks base method. -func (m *MockSpanner) GetCurrentValidatorsByBlockNrOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash, arg2 uint64) ([]*valset.Validator, error) { +func (m *MockSpanner) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64) ([]*valset.Validator, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentValidatorsByBlockNrOrHash", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetCurrentValidatorsByBlockNrOrHash", ctx, blockNrOrHash, blockNumber) ret0, _ := ret[0].([]*valset.Validator) ret1, _ := ret[1].(error) return ret0, ret1 } // GetCurrentValidatorsByBlockNrOrHash indicates an expected call of GetCurrentValidatorsByBlockNrOrHash. -func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByBlockNrOrHash(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByBlockNrOrHash(ctx, blockNrOrHash, blockNumber any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByBlockNrOrHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByBlockNrOrHash), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByBlockNrOrHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByBlockNrOrHash), ctx, blockNrOrHash, blockNumber) } // GetCurrentValidatorsByHash mocks base method. -func (m *MockSpanner) GetCurrentValidatorsByHash(arg0 context.Context, arg1 common.Hash, arg2 uint64) ([]*valset.Validator, error) { +func (m *MockSpanner) GetCurrentValidatorsByHash(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentValidatorsByHash", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetCurrentValidatorsByHash", ctx, headerHash, blockNumber) ret0, _ := ret[0].([]*valset.Validator) ret1, _ := ret[1].(error) return ret0, ret1 } // GetCurrentValidatorsByHash indicates an expected call of GetCurrentValidatorsByHash. -func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByHash(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByHash(ctx, headerHash, blockNumber any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByHash), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByHash), ctx, headerHash, blockNumber) } diff --git a/eth/filters/IBackend.go b/eth/filters/IBackend.go index 62db435d84..31690bd877 100644 --- a/eth/filters/IBackend.go +++ b/eth/filters/IBackend.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/internal/ethapi (interfaces: Backend) +// +// Generated by this command: +// +// mockgen -destination=../../eth/filters/IBackend.go -package=filters . Backend +// // Package filters is a generated GoMock package. package filters @@ -26,13 +31,14 @@ import ( event "github.com/ethereum/go-ethereum/event" params "github.com/ethereum/go-ethereum/params" rpc "github.com/ethereum/go-ethereum/rpc" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockBackend is a mock of Backend interface. type MockBackend struct { ctrl *gomock.Controller recorder *MockBackendMockRecorder + isgomock struct{} } // MockBackendMockRecorder is the mock recorder for MockBackend. @@ -95,62 +101,62 @@ func (mr *MockBackendMockRecorder) AccountManager() *gomock.Call { } // BlobBaseFee mocks base method. -func (m *MockBackend) BlobBaseFee(arg0 context.Context) *big.Int { +func (m *MockBackend) BlobBaseFee(ctx context.Context) *big.Int { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlobBaseFee", arg0) + ret := m.ctrl.Call(m, "BlobBaseFee", ctx) ret0, _ := ret[0].(*big.Int) return ret0 } // BlobBaseFee indicates an expected call of BlobBaseFee. -func (mr *MockBackendMockRecorder) BlobBaseFee(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) BlobBaseFee(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlobBaseFee", reflect.TypeOf((*MockBackend)(nil).BlobBaseFee), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlobBaseFee", reflect.TypeOf((*MockBackend)(nil).BlobBaseFee), ctx) } // BlockByHash mocks base method. -func (m *MockBackend) BlockByHash(arg0 context.Context, arg1 common.Hash) (*types.Block, error) { +func (m *MockBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockByHash", arg0, arg1) + ret := m.ctrl.Call(m, "BlockByHash", ctx, hash) ret0, _ := ret[0].(*types.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // BlockByHash indicates an expected call of BlockByHash. -func (mr *MockBackendMockRecorder) BlockByHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) BlockByHash(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHash", reflect.TypeOf((*MockBackend)(nil).BlockByHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByHash", reflect.TypeOf((*MockBackend)(nil).BlockByHash), ctx, hash) } // BlockByNumber mocks base method. -func (m *MockBackend) BlockByNumber(arg0 context.Context, arg1 rpc.BlockNumber) (*types.Block, error) { +func (m *MockBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockByNumber", arg0, arg1) + ret := m.ctrl.Call(m, "BlockByNumber", ctx, number) ret0, _ := ret[0].(*types.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // BlockByNumber indicates an expected call of BlockByNumber. -func (mr *MockBackendMockRecorder) BlockByNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) BlockByNumber(ctx, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumber", reflect.TypeOf((*MockBackend)(nil).BlockByNumber), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumber", reflect.TypeOf((*MockBackend)(nil).BlockByNumber), ctx, number) } // BlockByNumberOrHash mocks base method. -func (m *MockBackend) BlockByNumberOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash) (*types.Block, error) { +func (m *MockBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockByNumberOrHash", arg0, arg1) + ret := m.ctrl.Call(m, "BlockByNumberOrHash", ctx, blockNrOrHash) ret0, _ := ret[0].(*types.Block) ret1, _ := ret[1].(error) return ret0, ret1 } // BlockByNumberOrHash indicates an expected call of BlockByNumberOrHash. -func (mr *MockBackendMockRecorder) BlockByNumberOrHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) BlockByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).BlockByNumberOrHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).BlockByNumberOrHash), ctx, blockNrOrHash) } // ChainConfig mocks base method. @@ -182,18 +188,18 @@ func (mr *MockBackendMockRecorder) ChainDb() *gomock.Call { } // CheckPreconfStatus mocks base method. -func (m *MockBackend) CheckPreconfStatus(arg0 common.Hash) (bool, error) { +func (m *MockBackend) CheckPreconfStatus(hash common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CheckPreconfStatus", arg0) + ret := m.ctrl.Call(m, "CheckPreconfStatus", hash) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // CheckPreconfStatus indicates an expected call of CheckPreconfStatus. -func (mr *MockBackendMockRecorder) CheckPreconfStatus(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) CheckPreconfStatus(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckPreconfStatus", reflect.TypeOf((*MockBackend)(nil).CheckPreconfStatus), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckPreconfStatus", reflect.TypeOf((*MockBackend)(nil).CheckPreconfStatus), hash) } // CurrentBlock mocks base method. @@ -296,9 +302,9 @@ func (mr *MockBackendMockRecorder) ExtRPCEnabled() *gomock.Call { } // FeeHistory mocks base method. -func (m *MockBackend) FeeHistory(arg0 context.Context, arg1 uint64, arg2 rpc.BlockNumber, arg3 []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) { +func (m *MockBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FeeHistory", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "FeeHistory", ctx, blockCount, lastBlock, rewardPercentiles) ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].([][]*big.Int) ret2, _ := ret[2].([]*big.Int) @@ -310,60 +316,60 @@ func (m *MockBackend) FeeHistory(arg0 context.Context, arg1 uint64, arg2 rpc.Blo } // FeeHistory indicates an expected call of FeeHistory. -func (mr *MockBackendMockRecorder) FeeHistory(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeHistory", reflect.TypeOf((*MockBackend)(nil).FeeHistory), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FeeHistory", reflect.TypeOf((*MockBackend)(nil).FeeHistory), ctx, blockCount, lastBlock, rewardPercentiles) } // GetBody mocks base method. -func (m *MockBackend) GetBody(arg0 context.Context, arg1 common.Hash, arg2 rpc.BlockNumber) (*types.Body, error) { +func (m *MockBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBody", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetBody", ctx, hash, number) ret0, _ := ret[0].(*types.Body) ret1, _ := ret[1].(error) return ret0, ret1 } // GetBody indicates an expected call of GetBody. -func (mr *MockBackendMockRecorder) GetBody(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetBody(ctx, hash, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBody", reflect.TypeOf((*MockBackend)(nil).GetBody), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBody", reflect.TypeOf((*MockBackend)(nil).GetBody), ctx, hash, number) } // GetBorBlockLogs mocks base method. -func (m *MockBackend) GetBorBlockLogs(arg0 context.Context, arg1 common.Hash) ([]*types.Log, error) { +func (m *MockBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBorBlockLogs", arg0, arg1) + ret := m.ctrl.Call(m, "GetBorBlockLogs", ctx, hash) ret0, _ := ret[0].([]*types.Log) ret1, _ := ret[1].(error) return ret0, ret1 } // GetBorBlockLogs indicates an expected call of GetBorBlockLogs. -func (mr *MockBackendMockRecorder) GetBorBlockLogs(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetBorBlockLogs(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockLogs", reflect.TypeOf((*MockBackend)(nil).GetBorBlockLogs), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockLogs", reflect.TypeOf((*MockBackend)(nil).GetBorBlockLogs), ctx, hash) } // GetBorBlockReceipt mocks base method. -func (m *MockBackend) GetBorBlockReceipt(arg0 context.Context, arg1 common.Hash) (*types.Receipt, error) { +func (m *MockBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBorBlockReceipt", arg0, arg1) + ret := m.ctrl.Call(m, "GetBorBlockReceipt", ctx, hash) ret0, _ := ret[0].(*types.Receipt) ret1, _ := ret[1].(error) return ret0, ret1 } // GetBorBlockReceipt indicates an expected call of GetBorBlockReceipt. -func (mr *MockBackendMockRecorder) GetBorBlockReceipt(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetBorBlockReceipt(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockReceipt", reflect.TypeOf((*MockBackend)(nil).GetBorBlockReceipt), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockReceipt", reflect.TypeOf((*MockBackend)(nil).GetBorBlockReceipt), ctx, hash) } // GetBorBlockTransaction mocks base method. -func (m *MockBackend) GetBorBlockTransaction(arg0 context.Context, arg1 common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { +func (m *MockBackend) GetBorBlockTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBorBlockTransaction", arg0, arg1) + ret := m.ctrl.Call(m, "GetBorBlockTransaction", ctx, txHash) ret0, _ := ret[0].(*types.Transaction) ret1, _ := ret[1].(common.Hash) ret2, _ := ret[2].(uint64) @@ -373,15 +379,15 @@ func (m *MockBackend) GetBorBlockTransaction(arg0 context.Context, arg1 common.H } // GetBorBlockTransaction indicates an expected call of GetBorBlockTransaction. -func (mr *MockBackendMockRecorder) GetBorBlockTransaction(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetBorBlockTransaction(ctx, txHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockTransaction", reflect.TypeOf((*MockBackend)(nil).GetBorBlockTransaction), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockTransaction", reflect.TypeOf((*MockBackend)(nil).GetBorBlockTransaction), ctx, txHash) } // GetBorBlockTransactionWithBlockHash mocks base method. -func (m *MockBackend) GetBorBlockTransactionWithBlockHash(arg0 context.Context, arg1, arg2 common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { +func (m *MockBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBorBlockTransactionWithBlockHash", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetBorBlockTransactionWithBlockHash", ctx, txHash, blockHash) ret0, _ := ret[0].(*types.Transaction) ret1, _ := ret[1].(common.Hash) ret2, _ := ret[2].(uint64) @@ -391,30 +397,30 @@ func (m *MockBackend) GetBorBlockTransactionWithBlockHash(arg0 context.Context, } // GetBorBlockTransactionWithBlockHash indicates an expected call of GetBorBlockTransactionWithBlockHash. -func (mr *MockBackendMockRecorder) GetBorBlockTransactionWithBlockHash(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetBorBlockTransactionWithBlockHash(ctx, txHash, blockHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockTransactionWithBlockHash", reflect.TypeOf((*MockBackend)(nil).GetBorBlockTransactionWithBlockHash), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBorBlockTransactionWithBlockHash", reflect.TypeOf((*MockBackend)(nil).GetBorBlockTransactionWithBlockHash), ctx, txHash, blockHash) } // GetCanonicalReceipt mocks base method. -func (m *MockBackend) GetCanonicalReceipt(arg0 *types.Transaction, arg1 common.Hash, arg2, arg3 uint64) (*types.Receipt, error) { +func (m *MockBackend) GetCanonicalReceipt(tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64) (*types.Receipt, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCanonicalReceipt", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "GetCanonicalReceipt", tx, blockHash, blockNumber, blockIndex) ret0, _ := ret[0].(*types.Receipt) ret1, _ := ret[1].(error) return ret0, ret1 } // GetCanonicalReceipt indicates an expected call of GetCanonicalReceipt. -func (mr *MockBackendMockRecorder) GetCanonicalReceipt(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetCanonicalReceipt(tx, blockHash, blockNumber, blockIndex any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCanonicalReceipt", reflect.TypeOf((*MockBackend)(nil).GetCanonicalReceipt), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCanonicalReceipt", reflect.TypeOf((*MockBackend)(nil).GetCanonicalReceipt), tx, blockHash, blockNumber, blockIndex) } // GetCanonicalTransaction mocks base method. -func (m *MockBackend) GetCanonicalTransaction(arg0 common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { +func (m *MockBackend) GetCanonicalTransaction(txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCanonicalTransaction", arg0) + ret := m.ctrl.Call(m, "GetCanonicalTransaction", txHash) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(*types.Transaction) ret2, _ := ret[2].(common.Hash) @@ -424,82 +430,82 @@ func (m *MockBackend) GetCanonicalTransaction(arg0 common.Hash) (bool, *types.Tr } // GetCanonicalTransaction indicates an expected call of GetCanonicalTransaction. -func (mr *MockBackendMockRecorder) GetCanonicalTransaction(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetCanonicalTransaction(txHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCanonicalTransaction", reflect.TypeOf((*MockBackend)(nil).GetCanonicalTransaction), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCanonicalTransaction", reflect.TypeOf((*MockBackend)(nil).GetCanonicalTransaction), txHash) } // GetEVM mocks base method. -func (m *MockBackend) GetEVM(arg0 context.Context, arg1 *state.StateDB, arg2 *types.Header, arg3 *vm.Config, arg4 *vm.BlockContext) *vm.EVM { +func (m *MockBackend) GetEVM(ctx context.Context, arg1 *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetEVM", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "GetEVM", ctx, arg1, header, vmConfig, blockCtx) ret0, _ := ret[0].(*vm.EVM) return ret0 } // GetEVM indicates an expected call of GetEVM. -func (mr *MockBackendMockRecorder) GetEVM(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetEVM(ctx, arg1, header, vmConfig, blockCtx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEVM", reflect.TypeOf((*MockBackend)(nil).GetEVM), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEVM", reflect.TypeOf((*MockBackend)(nil).GetEVM), ctx, arg1, header, vmConfig, blockCtx) } // GetFinalizedBlockNumber mocks base method. -func (m *MockBackend) GetFinalizedBlockNumber(arg0 context.Context) (uint64, error) { +func (m *MockBackend) GetFinalizedBlockNumber(ctx context.Context) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetFinalizedBlockNumber", arg0) + ret := m.ctrl.Call(m, "GetFinalizedBlockNumber", ctx) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // GetFinalizedBlockNumber indicates an expected call of GetFinalizedBlockNumber. -func (mr *MockBackendMockRecorder) GetFinalizedBlockNumber(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetFinalizedBlockNumber(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFinalizedBlockNumber", reflect.TypeOf((*MockBackend)(nil).GetFinalizedBlockNumber), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFinalizedBlockNumber", reflect.TypeOf((*MockBackend)(nil).GetFinalizedBlockNumber), ctx) } // GetLogs mocks base method. -func (m *MockBackend) GetLogs(arg0 context.Context, arg1 common.Hash, arg2 uint64) ([][]*types.Log, error) { +func (m *MockBackend) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLogs", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetLogs", ctx, blockHash, number) ret0, _ := ret[0].([][]*types.Log) ret1, _ := ret[1].(error) return ret0, ret1 } // GetLogs indicates an expected call of GetLogs. -func (mr *MockBackendMockRecorder) GetLogs(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetLogs(ctx, blockHash, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockBackend)(nil).GetLogs), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockBackend)(nil).GetLogs), ctx, blockHash, number) } // GetPoolNonce mocks base method. -func (m *MockBackend) GetPoolNonce(arg0 context.Context, arg1 common.Address) (uint64, error) { +func (m *MockBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPoolNonce", arg0, arg1) + ret := m.ctrl.Call(m, "GetPoolNonce", ctx, addr) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // GetPoolNonce indicates an expected call of GetPoolNonce. -func (mr *MockBackendMockRecorder) GetPoolNonce(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetPoolNonce(ctx, addr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolNonce", reflect.TypeOf((*MockBackend)(nil).GetPoolNonce), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolNonce", reflect.TypeOf((*MockBackend)(nil).GetPoolNonce), ctx, addr) } // GetPoolTransaction mocks base method. -func (m *MockBackend) GetPoolTransaction(arg0 common.Hash) *types.Transaction { +func (m *MockBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPoolTransaction", arg0) + ret := m.ctrl.Call(m, "GetPoolTransaction", txHash) ret0, _ := ret[0].(*types.Transaction) return ret0 } // GetPoolTransaction indicates an expected call of GetPoolTransaction. -func (mr *MockBackendMockRecorder) GetPoolTransaction(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetPoolTransaction(txHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolTransaction", reflect.TypeOf((*MockBackend)(nil).GetPoolTransaction), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoolTransaction", reflect.TypeOf((*MockBackend)(nil).GetPoolTransaction), txHash) } // GetPoolTransactions mocks base method. @@ -518,76 +524,76 @@ func (mr *MockBackendMockRecorder) GetPoolTransactions() *gomock.Call { } // GetReceipts mocks base method. -func (m *MockBackend) GetReceipts(arg0 context.Context, arg1 common.Hash) (types.Receipts, error) { +func (m *MockBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReceipts", arg0, arg1) + ret := m.ctrl.Call(m, "GetReceipts", ctx, hash) ret0, _ := ret[0].(types.Receipts) ret1, _ := ret[1].(error) return ret0, ret1 } // GetReceipts indicates an expected call of GetReceipts. -func (mr *MockBackendMockRecorder) GetReceipts(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetReceipts(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReceipts", reflect.TypeOf((*MockBackend)(nil).GetReceipts), ctx, hash) } // GetRootHash mocks base method. -func (m *MockBackend) GetRootHash(arg0 context.Context, arg1, arg2 uint64) (string, error) { +func (m *MockBackend) GetRootHash(ctx context.Context, starBlockNr, endBlockNr uint64) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRootHash", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetRootHash", ctx, starBlockNr, endBlockNr) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetRootHash indicates an expected call of GetRootHash. -func (mr *MockBackendMockRecorder) GetRootHash(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetRootHash(ctx, starBlockNr, endBlockNr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootHash", reflect.TypeOf((*MockBackend)(nil).GetRootHash), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootHash", reflect.TypeOf((*MockBackend)(nil).GetRootHash), ctx, starBlockNr, endBlockNr) } // GetTd mocks base method. -func (m *MockBackend) GetTd(arg0 context.Context, arg1 common.Hash) *big.Int { +func (m *MockBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTd", arg0, arg1) + ret := m.ctrl.Call(m, "GetTd", ctx, hash) ret0, _ := ret[0].(*big.Int) return ret0 } // GetTd indicates an expected call of GetTd. -func (mr *MockBackendMockRecorder) GetTd(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetTd(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTd", reflect.TypeOf((*MockBackend)(nil).GetTd), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTd", reflect.TypeOf((*MockBackend)(nil).GetTd), ctx, hash) } // GetTdByNumber mocks base method. -func (m *MockBackend) GetTdByNumber(arg0 context.Context, arg1 rpc.BlockNumber) *big.Int { +func (m *MockBackend) GetTdByNumber(ctx context.Context, blockNr rpc.BlockNumber) *big.Int { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTdByNumber", arg0, arg1) + ret := m.ctrl.Call(m, "GetTdByNumber", ctx, blockNr) ret0, _ := ret[0].(*big.Int) return ret0 } // GetTdByNumber indicates an expected call of GetTdByNumber. -func (mr *MockBackendMockRecorder) GetTdByNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetTdByNumber(ctx, blockNr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTdByNumber", reflect.TypeOf((*MockBackend)(nil).GetTdByNumber), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTdByNumber", reflect.TypeOf((*MockBackend)(nil).GetTdByNumber), ctx, blockNr) } // GetVoteOnHash mocks base method. -func (m *MockBackend) GetVoteOnHash(arg0 context.Context, arg1, arg2 uint64, arg3, arg4 string) (bool, error) { +func (m *MockBackend) GetVoteOnHash(ctx context.Context, startBlockNumber, endBlockNumber uint64, hash, milestoneID string) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetVoteOnHash", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "GetVoteOnHash", ctx, startBlockNumber, endBlockNumber, hash, milestoneID) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // GetVoteOnHash indicates an expected call of GetVoteOnHash. -func (mr *MockBackendMockRecorder) GetVoteOnHash(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetVoteOnHash(ctx, startBlockNumber, endBlockNumber, hash, milestoneID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVoteOnHash", reflect.TypeOf((*MockBackend)(nil).GetVoteOnHash), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVoteOnHash", reflect.TypeOf((*MockBackend)(nil).GetVoteOnHash), ctx, startBlockNumber, endBlockNumber, hash, milestoneID) } // GetWhitelistedCheckpoint mocks base method. @@ -623,18 +629,18 @@ func (mr *MockBackendMockRecorder) GetWhitelistedMilestone() *gomock.Call { } // GetWitnesses mocks base method. -func (m *MockBackend) GetWitnesses(arg0 context.Context, arg1, arg2 uint64) ([]*stateless.Witness, error) { +func (m *MockBackend) GetWitnesses(ctx context.Context, originBlock, totalBlocks uint64) ([]*stateless.Witness, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetWitnesses", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "GetWitnesses", ctx, originBlock, totalBlocks) ret0, _ := ret[0].([]*stateless.Witness) ret1, _ := ret[1].(error) return ret0, ret1 } // GetWitnesses indicates an expected call of GetWitnesses. -func (mr *MockBackendMockRecorder) GetWitnesses(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) GetWitnesses(ctx, originBlock, totalBlocks any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWitnesses", reflect.TypeOf((*MockBackend)(nil).GetWitnesses), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWitnesses", reflect.TypeOf((*MockBackend)(nil).GetWitnesses), ctx, originBlock, totalBlocks) } // GetWork mocks base method. @@ -668,48 +674,48 @@ func (mr *MockBackendMockRecorder) Hashrate() *gomock.Call { } // HeaderByHash mocks base method. -func (m *MockBackend) HeaderByHash(arg0 context.Context, arg1 common.Hash) (*types.Header, error) { +func (m *MockBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeaderByHash", arg0, arg1) + ret := m.ctrl.Call(m, "HeaderByHash", ctx, hash) ret0, _ := ret[0].(*types.Header) ret1, _ := ret[1].(error) return ret0, ret1 } // HeaderByHash indicates an expected call of HeaderByHash. -func (mr *MockBackendMockRecorder) HeaderByHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) HeaderByHash(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHash", reflect.TypeOf((*MockBackend)(nil).HeaderByHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByHash", reflect.TypeOf((*MockBackend)(nil).HeaderByHash), ctx, hash) } // HeaderByNumber mocks base method. -func (m *MockBackend) HeaderByNumber(arg0 context.Context, arg1 rpc.BlockNumber) (*types.Header, error) { +func (m *MockBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeaderByNumber", arg0, arg1) + ret := m.ctrl.Call(m, "HeaderByNumber", ctx, number) ret0, _ := ret[0].(*types.Header) ret1, _ := ret[1].(error) return ret0, ret1 } // HeaderByNumber indicates an expected call of HeaderByNumber. -func (mr *MockBackendMockRecorder) HeaderByNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) HeaderByNumber(ctx, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumber", reflect.TypeOf((*MockBackend)(nil).HeaderByNumber), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumber", reflect.TypeOf((*MockBackend)(nil).HeaderByNumber), ctx, number) } // HeaderByNumberOrHash mocks base method. -func (m *MockBackend) HeaderByNumberOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash) (*types.Header, error) { +func (m *MockBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HeaderByNumberOrHash", arg0, arg1) + ret := m.ctrl.Call(m, "HeaderByNumberOrHash", ctx, blockNrOrHash) ret0, _ := ret[0].(*types.Header) ret1, _ := ret[1].(error) return ret0, ret1 } // HeaderByNumberOrHash indicates an expected call of HeaderByNumberOrHash. -func (mr *MockBackendMockRecorder) HeaderByNumberOrHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) HeaderByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).HeaderByNumberOrHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).HeaderByNumberOrHash), ctx, blockNrOrHash) } // HistoryPruningCutoff mocks base method. @@ -770,10 +776,10 @@ func (mr *MockBackendMockRecorder) NewMatcherBackend() *gomock.Call { } // PeerStats mocks base method. -func (m *MockBackend) PeerStats() interface{} { +func (m *MockBackend) PeerStats() any { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PeerStats") - ret0, _ := ret[0].(interface{}) + ret0, _ := ret[0].(any) return ret0 } @@ -842,15 +848,15 @@ func (mr *MockBackendMockRecorder) ProtocolVersion() *gomock.Call { } // PurgePrivateTx mocks base method. -func (m *MockBackend) PurgePrivateTx(arg0 common.Hash) { +func (m *MockBackend) PurgePrivateTx(hash common.Hash) { m.ctrl.T.Helper() - m.ctrl.Call(m, "PurgePrivateTx", arg0) + m.ctrl.Call(m, "PurgePrivateTx", hash) } // PurgePrivateTx indicates an expected call of PurgePrivateTx. -func (mr *MockBackendMockRecorder) PurgePrivateTx(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) PurgePrivateTx(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgePrivateTx", reflect.TypeOf((*MockBackend)(nil).PurgePrivateTx), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PurgePrivateTx", reflect.TypeOf((*MockBackend)(nil).PurgePrivateTx), hash) } // PurgeWhitelistedCheckpoint mocks base method. @@ -962,47 +968,47 @@ func (mr *MockBackendMockRecorder) RPCTxSyncMaxTimeout() *gomock.Call { } // RecordPrivateTx mocks base method. -func (m *MockBackend) RecordPrivateTx(arg0 common.Hash) { +func (m *MockBackend) RecordPrivateTx(hash common.Hash) { m.ctrl.T.Helper() - m.ctrl.Call(m, "RecordPrivateTx", arg0) + m.ctrl.Call(m, "RecordPrivateTx", hash) } // RecordPrivateTx indicates an expected call of RecordPrivateTx. -func (mr *MockBackendMockRecorder) RecordPrivateTx(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) RecordPrivateTx(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPrivateTx", reflect.TypeOf((*MockBackend)(nil).RecordPrivateTx), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecordPrivateTx", reflect.TypeOf((*MockBackend)(nil).RecordPrivateTx), hash) } // SendTx mocks base method. -func (m *MockBackend) SendTx(arg0 context.Context, arg1 *types.Transaction) error { +func (m *MockBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendTx", arg0, arg1) + ret := m.ctrl.Call(m, "SendTx", ctx, signedTx) ret0, _ := ret[0].(error) return ret0 } // SendTx indicates an expected call of SendTx. -func (mr *MockBackendMockRecorder) SendTx(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SendTx(ctx, signedTx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTx", reflect.TypeOf((*MockBackend)(nil).SendTx), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTx", reflect.TypeOf((*MockBackend)(nil).SendTx), ctx, signedTx) } // SetHead mocks base method. -func (m *MockBackend) SetHead(arg0 uint64) { +func (m *MockBackend) SetHead(number uint64) { m.ctrl.T.Helper() - m.ctrl.Call(m, "SetHead", arg0) + m.ctrl.Call(m, "SetHead", number) } // SetHead indicates an expected call of SetHead. -func (mr *MockBackendMockRecorder) SetHead(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SetHead(number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHead", reflect.TypeOf((*MockBackend)(nil).SetHead), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHead", reflect.TypeOf((*MockBackend)(nil).SetHead), number) } // StateAndHeaderByNumber mocks base method. -func (m *MockBackend) StateAndHeaderByNumber(arg0 context.Context, arg1 rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (m *MockBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StateAndHeaderByNumber", arg0, arg1) + ret := m.ctrl.Call(m, "StateAndHeaderByNumber", ctx, number) ret0, _ := ret[0].(*state.StateDB) ret1, _ := ret[1].(*types.Header) ret2, _ := ret[2].(error) @@ -1010,15 +1016,15 @@ func (m *MockBackend) StateAndHeaderByNumber(arg0 context.Context, arg1 rpc.Bloc } // StateAndHeaderByNumber indicates an expected call of StateAndHeaderByNumber. -func (mr *MockBackendMockRecorder) StateAndHeaderByNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) StateAndHeaderByNumber(ctx, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumber", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumber), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumber", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumber), ctx, number) } // StateAndHeaderByNumberOrHash mocks base method. -func (m *MockBackend) StateAndHeaderByNumberOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { +func (m *MockBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StateAndHeaderByNumberOrHash", arg0, arg1) + ret := m.ctrl.Call(m, "StateAndHeaderByNumberOrHash", ctx, blockNrOrHash) ret0, _ := ret[0].(*state.StateDB) ret1, _ := ret[1].(*types.Header) ret2, _ := ret[2].(error) @@ -1026,9 +1032,9 @@ func (m *MockBackend) StateAndHeaderByNumberOrHash(arg0 context.Context, arg1 rp } // StateAndHeaderByNumberOrHash indicates an expected call of StateAndHeaderByNumberOrHash. -func (mr *MockBackendMockRecorder) StateAndHeaderByNumberOrHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) StateAndHeaderByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumberOrHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateAndHeaderByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).StateAndHeaderByNumberOrHash), ctx, blockNrOrHash) } // Stats mocks base method. @@ -1047,131 +1053,131 @@ func (mr *MockBackendMockRecorder) Stats() *gomock.Call { } // StoreWitness mocks base method. -func (m *MockBackend) StoreWitness(arg0 context.Context, arg1 common.Hash, arg2 *stateless.Witness) error { +func (m *MockBackend) StoreWitness(ctx context.Context, blockHash common.Hash, witness *stateless.Witness) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StoreWitness", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "StoreWitness", ctx, blockHash, witness) ret0, _ := ret[0].(error) return ret0 } // StoreWitness indicates an expected call of StoreWitness. -func (mr *MockBackendMockRecorder) StoreWitness(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) StoreWitness(ctx, blockHash, witness any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreWitness", reflect.TypeOf((*MockBackend)(nil).StoreWitness), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreWitness", reflect.TypeOf((*MockBackend)(nil).StoreWitness), ctx, blockHash, witness) } // SubmitHashrate mocks base method. -func (m *MockBackend) SubmitHashrate(arg0 hexutil.Uint64, arg1 common.Hash) (bool, error) { +func (m *MockBackend) SubmitHashrate(rate hexutil.Uint64, id common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitHashrate", arg0, arg1) + ret := m.ctrl.Call(m, "SubmitHashrate", rate, id) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitHashrate indicates an expected call of SubmitHashrate. -func (mr *MockBackendMockRecorder) SubmitHashrate(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubmitHashrate(rate, id any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitHashrate", reflect.TypeOf((*MockBackend)(nil).SubmitHashrate), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitHashrate", reflect.TypeOf((*MockBackend)(nil).SubmitHashrate), rate, id) } // SubmitPrivateTx mocks base method. -func (m *MockBackend) SubmitPrivateTx(arg0 *types.Transaction) error { +func (m *MockBackend) SubmitPrivateTx(tx *types.Transaction) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitPrivateTx", arg0) + ret := m.ctrl.Call(m, "SubmitPrivateTx", tx) ret0, _ := ret[0].(error) return ret0 } // SubmitPrivateTx indicates an expected call of SubmitPrivateTx. -func (mr *MockBackendMockRecorder) SubmitPrivateTx(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubmitPrivateTx(tx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitPrivateTx", reflect.TypeOf((*MockBackend)(nil).SubmitPrivateTx), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitPrivateTx", reflect.TypeOf((*MockBackend)(nil).SubmitPrivateTx), tx) } // SubmitTxForPreconf mocks base method. -func (m *MockBackend) SubmitTxForPreconf(arg0 *types.Transaction) error { +func (m *MockBackend) SubmitTxForPreconf(tx *types.Transaction) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitTxForPreconf", arg0) + ret := m.ctrl.Call(m, "SubmitTxForPreconf", tx) ret0, _ := ret[0].(error) return ret0 } // SubmitTxForPreconf indicates an expected call of SubmitTxForPreconf. -func (mr *MockBackendMockRecorder) SubmitTxForPreconf(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubmitTxForPreconf(tx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitTxForPreconf", reflect.TypeOf((*MockBackend)(nil).SubmitTxForPreconf), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitTxForPreconf", reflect.TypeOf((*MockBackend)(nil).SubmitTxForPreconf), tx) } // SubmitWork mocks base method. -func (m *MockBackend) SubmitWork(arg0 types.BlockNonce, arg1, arg2 common.Hash) (bool, error) { +func (m *MockBackend) SubmitWork(nonce types.BlockNonce, hash, digest common.Hash) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitWork", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "SubmitWork", nonce, hash, digest) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitWork indicates an expected call of SubmitWork. -func (mr *MockBackendMockRecorder) SubmitWork(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubmitWork(nonce, hash, digest any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitWork", reflect.TypeOf((*MockBackend)(nil).SubmitWork), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitWork", reflect.TypeOf((*MockBackend)(nil).SubmitWork), nonce, hash, digest) } // SubscribeChain2HeadEvent mocks base method. -func (m *MockBackend) SubscribeChain2HeadEvent(arg0 chan<- core.Chain2HeadEvent) event.Subscription { +func (m *MockBackend) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeChain2HeadEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeChain2HeadEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeChain2HeadEvent indicates an expected call of SubscribeChain2HeadEvent. -func (mr *MockBackendMockRecorder) SubscribeChain2HeadEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeChain2HeadEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChain2HeadEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChain2HeadEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChain2HeadEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChain2HeadEvent), ch) } // SubscribeChainEvent mocks base method. -func (m *MockBackend) SubscribeChainEvent(arg0 chan<- core.ChainEvent) event.Subscription { +func (m *MockBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeChainEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeChainEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeChainEvent indicates an expected call of SubscribeChainEvent. -func (mr *MockBackendMockRecorder) SubscribeChainEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeChainEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainEvent), ch) } // SubscribeChainHeadEvent mocks base method. -func (m *MockBackend) SubscribeChainHeadEvent(arg0 chan<- core.ChainHeadEvent) event.Subscription { +func (m *MockBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeChainHeadEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeChainHeadEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeChainHeadEvent indicates an expected call of SubscribeChainHeadEvent. -func (mr *MockBackendMockRecorder) SubscribeChainHeadEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeChainHeadEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainHeadEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainHeadEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeChainHeadEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeChainHeadEvent), ch) } // SubscribeLogsEvent mocks base method. -func (m *MockBackend) SubscribeLogsEvent(arg0 chan<- []*types.Log) event.Subscription { +func (m *MockBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeLogsEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeLogsEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeLogsEvent indicates an expected call of SubscribeLogsEvent. -func (mr *MockBackendMockRecorder) SubscribeLogsEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeLogsEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeLogsEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeLogsEvent), ch) } // SubscribeNewTxsEvent mocks base method. @@ -1183,80 +1189,80 @@ func (m *MockBackend) SubscribeNewTxsEvent(arg0 chan<- core.NewTxsEvent) event.S } // SubscribeNewTxsEvent indicates an expected call of SubscribeNewTxsEvent. -func (mr *MockBackendMockRecorder) SubscribeNewTxsEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeNewTxsEvent(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeNewTxsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeNewTxsEvent), arg0) } // SubscribePendingLogsEvent mocks base method. -func (m *MockBackend) SubscribePendingLogsEvent(arg0 chan<- []*types.Log) event.Subscription { +func (m *MockBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribePendingLogsEvent", arg0) + ret := m.ctrl.Call(m, "SubscribePendingLogsEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribePendingLogsEvent indicates an expected call of SubscribePendingLogsEvent. -func (mr *MockBackendMockRecorder) SubscribePendingLogsEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribePendingLogsEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribePendingLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribePendingLogsEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribePendingLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribePendingLogsEvent), ch) } // SubscribeRemovedLogsEvent mocks base method. -func (m *MockBackend) SubscribeRemovedLogsEvent(arg0 chan<- core.RemovedLogsEvent) event.Subscription { +func (m *MockBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeRemovedLogsEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeRemovedLogsEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeRemovedLogsEvent indicates an expected call of SubscribeRemovedLogsEvent. -func (mr *MockBackendMockRecorder) SubscribeRemovedLogsEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeRemovedLogsEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeRemovedLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeRemovedLogsEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeRemovedLogsEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeRemovedLogsEvent), ch) } // SubscribeStateSyncEvent mocks base method. -func (m *MockBackend) SubscribeStateSyncEvent(arg0 chan<- core.StateSyncEvent) event.Subscription { +func (m *MockBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) event.Subscription { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubscribeStateSyncEvent", arg0) + ret := m.ctrl.Call(m, "SubscribeStateSyncEvent", ch) ret0, _ := ret[0].(event.Subscription) return ret0 } // SubscribeStateSyncEvent indicates an expected call of SubscribeStateSyncEvent. -func (mr *MockBackendMockRecorder) SubscribeStateSyncEvent(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SubscribeStateSyncEvent(ch any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeStateSyncEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeStateSyncEvent), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeStateSyncEvent", reflect.TypeOf((*MockBackend)(nil).SubscribeStateSyncEvent), ch) } // SuggestGasTipCap mocks base method. -func (m *MockBackend) SuggestGasTipCap(arg0 context.Context) (*big.Int, error) { +func (m *MockBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SuggestGasTipCap", arg0) + ret := m.ctrl.Call(m, "SuggestGasTipCap", ctx) ret0, _ := ret[0].(*big.Int) ret1, _ := ret[1].(error) return ret0, ret1 } // SuggestGasTipCap indicates an expected call of SuggestGasTipCap. -func (mr *MockBackendMockRecorder) SuggestGasTipCap(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SuggestGasTipCap(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SuggestGasTipCap", reflect.TypeOf((*MockBackend)(nil).SuggestGasTipCap), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SuggestGasTipCap", reflect.TypeOf((*MockBackend)(nil).SuggestGasTipCap), ctx) } // SyncProgress mocks base method. -func (m *MockBackend) SyncProgress(arg0 context.Context) ethereum.SyncProgress { +func (m *MockBackend) SyncProgress(ctx context.Context) ethereum.SyncProgress { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SyncProgress", arg0) + ret := m.ctrl.Call(m, "SyncProgress", ctx) ret0, _ := ret[0].(ethereum.SyncProgress) return ret0 } // SyncProgress indicates an expected call of SyncProgress. -func (mr *MockBackendMockRecorder) SyncProgress(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) SyncProgress(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncProgress", reflect.TypeOf((*MockBackend)(nil).SyncProgress), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncProgress", reflect.TypeOf((*MockBackend)(nil).SyncProgress), ctx) } // TxIndexDone mocks base method. @@ -1289,32 +1295,32 @@ func (mr *MockBackendMockRecorder) TxPoolContent() *gomock.Call { } // TxPoolContentFrom mocks base method. -func (m *MockBackend) TxPoolContentFrom(arg0 common.Address) ([]*types.Transaction, []*types.Transaction) { +func (m *MockBackend) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TxPoolContentFrom", arg0) + ret := m.ctrl.Call(m, "TxPoolContentFrom", addr) ret0, _ := ret[0].([]*types.Transaction) ret1, _ := ret[1].([]*types.Transaction) return ret0, ret1 } // TxPoolContentFrom indicates an expected call of TxPoolContentFrom. -func (mr *MockBackendMockRecorder) TxPoolContentFrom(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) TxPoolContentFrom(addr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxPoolContentFrom", reflect.TypeOf((*MockBackend)(nil).TxPoolContentFrom), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxPoolContentFrom", reflect.TypeOf((*MockBackend)(nil).TxPoolContentFrom), addr) } // TxStatus mocks base method. -func (m *MockBackend) TxStatus(arg0 common.Hash) txpool.TxStatus { +func (m *MockBackend) TxStatus(hash common.Hash) txpool.TxStatus { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TxStatus", arg0) + ret := m.ctrl.Call(m, "TxStatus", hash) ret0, _ := ret[0].(txpool.TxStatus) return ret0 } // TxStatus indicates an expected call of TxStatus. -func (mr *MockBackendMockRecorder) TxStatus(arg0 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) TxStatus(hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxStatus", reflect.TypeOf((*MockBackend)(nil).TxStatus), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TxStatus", reflect.TypeOf((*MockBackend)(nil).TxStatus), hash) } // UnprotectedAllowed mocks base method. @@ -1332,46 +1338,46 @@ func (mr *MockBackendMockRecorder) UnprotectedAllowed() *gomock.Call { } // WitnessByHash mocks base method. -func (m *MockBackend) WitnessByHash(arg0 context.Context, arg1 common.Hash) (*stateless.Witness, error) { +func (m *MockBackend) WitnessByHash(ctx context.Context, hash common.Hash) (*stateless.Witness, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WitnessByHash", arg0, arg1) + ret := m.ctrl.Call(m, "WitnessByHash", ctx, hash) ret0, _ := ret[0].(*stateless.Witness) ret1, _ := ret[1].(error) return ret0, ret1 } // WitnessByHash indicates an expected call of WitnessByHash. -func (mr *MockBackendMockRecorder) WitnessByHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) WitnessByHash(ctx, hash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByHash", reflect.TypeOf((*MockBackend)(nil).WitnessByHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByHash", reflect.TypeOf((*MockBackend)(nil).WitnessByHash), ctx, hash) } // WitnessByNumber mocks base method. -func (m *MockBackend) WitnessByNumber(arg0 context.Context, arg1 rpc.BlockNumber) (*stateless.Witness, error) { +func (m *MockBackend) WitnessByNumber(ctx context.Context, number rpc.BlockNumber) (*stateless.Witness, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WitnessByNumber", arg0, arg1) + ret := m.ctrl.Call(m, "WitnessByNumber", ctx, number) ret0, _ := ret[0].(*stateless.Witness) ret1, _ := ret[1].(error) return ret0, ret1 } // WitnessByNumber indicates an expected call of WitnessByNumber. -func (mr *MockBackendMockRecorder) WitnessByNumber(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) WitnessByNumber(ctx, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByNumber", reflect.TypeOf((*MockBackend)(nil).WitnessByNumber), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByNumber", reflect.TypeOf((*MockBackend)(nil).WitnessByNumber), ctx, number) } // WitnessByNumberOrHash mocks base method. -func (m *MockBackend) WitnessByNumberOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash) (*stateless.Witness, error) { +func (m *MockBackend) WitnessByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*stateless.Witness, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WitnessByNumberOrHash", arg0, arg1) + ret := m.ctrl.Call(m, "WitnessByNumberOrHash", ctx, blockNrOrHash) ret0, _ := ret[0].(*stateless.Witness) ret1, _ := ret[1].(error) return ret0, ret1 } // WitnessByNumberOrHash indicates an expected call of WitnessByNumberOrHash. -func (mr *MockBackendMockRecorder) WitnessByNumberOrHash(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBackendMockRecorder) WitnessByNumberOrHash(ctx, blockNrOrHash any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).WitnessByNumberOrHash), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WitnessByNumberOrHash", reflect.TypeOf((*MockBackend)(nil).WitnessByNumberOrHash), ctx, blockNrOrHash) } diff --git a/eth/filters/IBatch.go b/eth/filters/IBatch.go index 88dbb35ed2..b2bf9aa3d2 100644 --- a/eth/filters/IBatch.go +++ b/eth/filters/IBatch.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/ethdb (interfaces: Batch) +// +// Generated by this command: +// +// mockgen -destination=../eth/filters/IBatch.go -package=filters . Batch +// // Package filters is a generated GoMock package. package filters @@ -8,13 +13,14 @@ import ( reflect "reflect" ethdb "github.com/ethereum/go-ethereum/ethdb" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockBatch is a mock of Batch interface. type MockBatch struct { ctrl *gomock.Controller recorder *MockBatchMockRecorder + isgomock struct{} } // MockBatchMockRecorder is the mock recorder for MockBatch. @@ -35,59 +41,59 @@ func (m *MockBatch) EXPECT() *MockBatchMockRecorder { } // Delete mocks base method. -func (m *MockBatch) Delete(arg0 []byte) error { +func (m *MockBatch) Delete(key []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0) + ret := m.ctrl.Call(m, "Delete", key) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockBatchMockRecorder) Delete(arg0 interface{}) *gomock.Call { +func (mr *MockBatchMockRecorder) Delete(key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockBatch)(nil).Delete), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockBatch)(nil).Delete), key) } // DeleteRange mocks base method. -func (m *MockBatch) DeleteRange(arg0, arg1 []byte) error { +func (m *MockBatch) DeleteRange(start, end []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteRange", arg0, arg1) + ret := m.ctrl.Call(m, "DeleteRange", start, end) ret0, _ := ret[0].(error) return ret0 } // DeleteRange indicates an expected call of DeleteRange. -func (mr *MockBatchMockRecorder) DeleteRange(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBatchMockRecorder) DeleteRange(start, end any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRange", reflect.TypeOf((*MockBatch)(nil).DeleteRange), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRange", reflect.TypeOf((*MockBatch)(nil).DeleteRange), start, end) } // Put mocks base method. -func (m *MockBatch) Put(arg0, arg1 []byte) error { +func (m *MockBatch) Put(key, value []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Put", arg0, arg1) + ret := m.ctrl.Call(m, "Put", key, value) ret0, _ := ret[0].(error) return ret0 } // Put indicates an expected call of Put. -func (mr *MockBatchMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockBatchMockRecorder) Put(key, value any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockBatch)(nil).Put), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockBatch)(nil).Put), key, value) } // Replay mocks base method. -func (m *MockBatch) Replay(arg0 ethdb.KeyValueWriter) error { +func (m *MockBatch) Replay(w ethdb.KeyValueWriter) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Replay", arg0) + ret := m.ctrl.Call(m, "Replay", w) ret0, _ := ret[0].(error) return ret0 } // Replay indicates an expected call of Replay. -func (mr *MockBatchMockRecorder) Replay(arg0 interface{}) *gomock.Call { +func (mr *MockBatchMockRecorder) Replay(w any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Replay", reflect.TypeOf((*MockBatch)(nil).Replay), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Replay", reflect.TypeOf((*MockBatch)(nil).Replay), w) } // Reset mocks base method. diff --git a/eth/filters/IDatabase.go b/eth/filters/IDatabase.go index 602a8f1c88..82da0237e8 100644 --- a/eth/filters/IDatabase.go +++ b/eth/filters/IDatabase.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/ethdb (interfaces: Database) +// +// Generated by this command: +// +// mockgen -destination=../eth/filters/IDatabase.go -package=filters . Database +// // Package filters is a generated GoMock package. package filters @@ -8,13 +13,14 @@ import ( reflect "reflect" ethdb "github.com/ethereum/go-ethereum/ethdb" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockDatabase is a mock of Database interface. type MockDatabase struct { ctrl *gomock.Controller recorder *MockDatabaseMockRecorder + isgomock struct{} } // MockDatabaseMockRecorder is the mock recorder for MockDatabase. @@ -35,33 +41,33 @@ func (m *MockDatabase) EXPECT() *MockDatabaseMockRecorder { } // Ancient mocks base method. -func (m *MockDatabase) Ancient(arg0 string, arg1 uint64) ([]byte, error) { +func (m *MockDatabase) Ancient(kind string, number uint64) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Ancient", arg0, arg1) + ret := m.ctrl.Call(m, "Ancient", kind, number) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Ancient indicates an expected call of Ancient. -func (mr *MockDatabaseMockRecorder) Ancient(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Ancient(kind, number any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ancient", reflect.TypeOf((*MockDatabase)(nil).Ancient), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ancient", reflect.TypeOf((*MockDatabase)(nil).Ancient), kind, number) } // AncientBytes mocks base method. -func (m *MockDatabase) AncientBytes(arg0 string, arg1, arg2, arg3 uint64) ([]byte, error) { +func (m *MockDatabase) AncientBytes(kind string, id, offset, length uint64) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AncientBytes", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "AncientBytes", kind, id, offset, length) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // AncientBytes indicates an expected call of AncientBytes. -func (mr *MockDatabaseMockRecorder) AncientBytes(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) AncientBytes(kind, id, offset, length any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientBytes", reflect.TypeOf((*MockDatabase)(nil).AncientBytes), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientBytes", reflect.TypeOf((*MockDatabase)(nil).AncientBytes), kind, id, offset, length) } // AncientDatadir mocks base method. @@ -94,33 +100,33 @@ func (mr *MockDatabaseMockRecorder) AncientOffSet() *gomock.Call { } // AncientRange mocks base method. -func (m *MockDatabase) AncientRange(arg0 string, arg1, arg2, arg3 uint64) ([][]byte, error) { +func (m *MockDatabase) AncientRange(kind string, start, count, maxBytes uint64) ([][]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AncientRange", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "AncientRange", kind, start, count, maxBytes) ret0, _ := ret[0].([][]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // AncientRange indicates an expected call of AncientRange. -func (mr *MockDatabaseMockRecorder) AncientRange(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) AncientRange(kind, start, count, maxBytes any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientRange", reflect.TypeOf((*MockDatabase)(nil).AncientRange), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientRange", reflect.TypeOf((*MockDatabase)(nil).AncientRange), kind, start, count, maxBytes) } // AncientSize mocks base method. -func (m *MockDatabase) AncientSize(arg0 string) (uint64, error) { +func (m *MockDatabase) AncientSize(kind string) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AncientSize", arg0) + ret := m.ctrl.Call(m, "AncientSize", kind) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // AncientSize indicates an expected call of AncientSize. -func (mr *MockDatabaseMockRecorder) AncientSize(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) AncientSize(kind any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientSize", reflect.TypeOf((*MockDatabase)(nil).AncientSize), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientSize", reflect.TypeOf((*MockDatabase)(nil).AncientSize), kind) } // Ancients mocks base method. @@ -153,75 +159,75 @@ func (mr *MockDatabaseMockRecorder) Close() *gomock.Call { } // Compact mocks base method. -func (m *MockDatabase) Compact(arg0, arg1 []byte) error { +func (m *MockDatabase) Compact(start, limit []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Compact", arg0, arg1) + ret := m.ctrl.Call(m, "Compact", start, limit) ret0, _ := ret[0].(error) return ret0 } // Compact indicates an expected call of Compact. -func (mr *MockDatabaseMockRecorder) Compact(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Compact(start, limit any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compact", reflect.TypeOf((*MockDatabase)(nil).Compact), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Compact", reflect.TypeOf((*MockDatabase)(nil).Compact), start, limit) } // Delete mocks base method. -func (m *MockDatabase) Delete(arg0 []byte) error { +func (m *MockDatabase) Delete(key []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0) + ret := m.ctrl.Call(m, "Delete", key) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockDatabaseMockRecorder) Delete(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Delete(key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDatabase)(nil).Delete), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDatabase)(nil).Delete), key) } // DeleteRange mocks base method. -func (m *MockDatabase) DeleteRange(arg0, arg1 []byte) error { +func (m *MockDatabase) DeleteRange(start, end []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteRange", arg0, arg1) + ret := m.ctrl.Call(m, "DeleteRange", start, end) ret0, _ := ret[0].(error) return ret0 } // DeleteRange indicates an expected call of DeleteRange. -func (mr *MockDatabaseMockRecorder) DeleteRange(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) DeleteRange(start, end any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRange", reflect.TypeOf((*MockDatabase)(nil).DeleteRange), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRange", reflect.TypeOf((*MockDatabase)(nil).DeleteRange), start, end) } // Get mocks base method. -func (m *MockDatabase) Get(arg0 []byte) ([]byte, error) { +func (m *MockDatabase) Get(key []byte) ([]byte, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", arg0) + ret := m.ctrl.Call(m, "Get", key) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // Get indicates an expected call of Get. -func (mr *MockDatabaseMockRecorder) Get(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Get(key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDatabase)(nil).Get), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockDatabase)(nil).Get), key) } // Has mocks base method. -func (m *MockDatabase) Has(arg0 []byte) (bool, error) { +func (m *MockDatabase) Has(key []byte) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Has", arg0) + ret := m.ctrl.Call(m, "Has", key) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // Has indicates an expected call of Has. -func (mr *MockDatabaseMockRecorder) Has(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Has(key any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockDatabase)(nil).Has), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Has", reflect.TypeOf((*MockDatabase)(nil).Has), key) } // ItemAmountInAncient mocks base method. @@ -249,7 +255,7 @@ func (m *MockDatabase) ModifyAncients(arg0 func(ethdb.AncientWriteOp) error) (in } // ModifyAncients indicates an expected call of ModifyAncients. -func (mr *MockDatabaseMockRecorder) ModifyAncients(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) ModifyAncients(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ModifyAncients", reflect.TypeOf((*MockDatabase)(nil).ModifyAncients), arg0) } @@ -269,59 +275,59 @@ func (mr *MockDatabaseMockRecorder) NewBatch() *gomock.Call { } // NewBatchWithSize mocks base method. -func (m *MockDatabase) NewBatchWithSize(arg0 int) ethdb.Batch { +func (m *MockDatabase) NewBatchWithSize(size int) ethdb.Batch { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewBatchWithSize", arg0) + ret := m.ctrl.Call(m, "NewBatchWithSize", size) ret0, _ := ret[0].(ethdb.Batch) return ret0 } // NewBatchWithSize indicates an expected call of NewBatchWithSize. -func (mr *MockDatabaseMockRecorder) NewBatchWithSize(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) NewBatchWithSize(size any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatchWithSize", reflect.TypeOf((*MockDatabase)(nil).NewBatchWithSize), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatchWithSize", reflect.TypeOf((*MockDatabase)(nil).NewBatchWithSize), size) } // NewIterator mocks base method. -func (m *MockDatabase) NewIterator(arg0, arg1 []byte) ethdb.Iterator { +func (m *MockDatabase) NewIterator(prefix, start []byte) ethdb.Iterator { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewIterator", arg0, arg1) + ret := m.ctrl.Call(m, "NewIterator", prefix, start) ret0, _ := ret[0].(ethdb.Iterator) return ret0 } // NewIterator indicates an expected call of NewIterator. -func (mr *MockDatabaseMockRecorder) NewIterator(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) NewIterator(prefix, start any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewIterator", reflect.TypeOf((*MockDatabase)(nil).NewIterator), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewIterator", reflect.TypeOf((*MockDatabase)(nil).NewIterator), prefix, start) } // Put mocks base method. -func (m *MockDatabase) Put(arg0, arg1 []byte) error { +func (m *MockDatabase) Put(key, value []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Put", arg0, arg1) + ret := m.ctrl.Call(m, "Put", key, value) ret0, _ := ret[0].(error) return ret0 } // Put indicates an expected call of Put. -func (mr *MockDatabaseMockRecorder) Put(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) Put(key, value any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDatabase)(nil).Put), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Put", reflect.TypeOf((*MockDatabase)(nil).Put), key, value) } // ReadAncients mocks base method. -func (m *MockDatabase) ReadAncients(arg0 func(ethdb.AncientReaderOp) error) error { +func (m *MockDatabase) ReadAncients(fn func(ethdb.AncientReaderOp) error) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReadAncients", arg0) + ret := m.ctrl.Call(m, "ReadAncients", fn) ret0, _ := ret[0].(error) return ret0 } // ReadAncients indicates an expected call of ReadAncients. -func (mr *MockDatabaseMockRecorder) ReadAncients(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) ReadAncients(fn any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadAncients", reflect.TypeOf((*MockDatabase)(nil).ReadAncients), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadAncients", reflect.TypeOf((*MockDatabase)(nil).ReadAncients), fn) } // Stat mocks base method. @@ -383,31 +389,31 @@ func (mr *MockDatabaseMockRecorder) Tail() *gomock.Call { } // TruncateHead mocks base method. -func (m *MockDatabase) TruncateHead(arg0 uint64) (uint64, error) { +func (m *MockDatabase) TruncateHead(n uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TruncateHead", arg0) + ret := m.ctrl.Call(m, "TruncateHead", n) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // TruncateHead indicates an expected call of TruncateHead. -func (mr *MockDatabaseMockRecorder) TruncateHead(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) TruncateHead(n any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateHead", reflect.TypeOf((*MockDatabase)(nil).TruncateHead), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateHead", reflect.TypeOf((*MockDatabase)(nil).TruncateHead), n) } // TruncateTail mocks base method. -func (m *MockDatabase) TruncateTail(arg0 uint64) (uint64, error) { +func (m *MockDatabase) TruncateTail(n uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TruncateTail", arg0) + ret := m.ctrl.Call(m, "TruncateTail", n) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // TruncateTail indicates an expected call of TruncateTail. -func (mr *MockDatabaseMockRecorder) TruncateTail(arg0 interface{}) *gomock.Call { +func (mr *MockDatabaseMockRecorder) TruncateTail(n any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateTail", reflect.TypeOf((*MockDatabase)(nil).TruncateTail), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TruncateTail", reflect.TypeOf((*MockDatabase)(nil).TruncateTail), n) } diff --git a/eth/filters/IIterator.go b/eth/filters/IIterator.go index 7aa63b470a..e4e4bdcf22 100644 --- a/eth/filters/IIterator.go +++ b/eth/filters/IIterator.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ethereum/go-ethereum/ethdb (interfaces: Iterator) +// +// Generated by this command: +// +// mockgen -destination=../eth/filters/IIterator.go -package=filters . Iterator +// // Package filters is a generated GoMock package. package filters @@ -7,13 +12,14 @@ package filters import ( reflect "reflect" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockIterator is a mock of Iterator interface. type MockIterator struct { ctrl *gomock.Controller recorder *MockIteratorMockRecorder + isgomock struct{} } // MockIteratorMockRecorder is the mock recorder for MockIterator. diff --git a/tests/bor/mocks/IHeimdallClient.go b/tests/bor/mocks/IHeimdallClient.go index 8e5eda68d7..f6f178f981 100644 --- a/tests/bor/mocks/IHeimdallClient.go +++ b/tests/bor/mocks/IHeimdallClient.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: heimdall.go +// +// Generated by this command: +// +// mockgen -source=heimdall.go -destination=../../tests/bor/mocks/IHeimdallClient.go -package=mocks +// // Package mocks is a generated GoMock package. package mocks @@ -13,13 +18,14 @@ import ( clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk" checkpoint "github.com/ethereum/go-ethereum/consensus/bor/heimdall/checkpoint" milestone "github.com/ethereum/go-ethereum/consensus/bor/heimdall/milestone" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" ) // MockIHeimdallClient is a mock of IHeimdallClient interface. type MockIHeimdallClient struct { ctrl *gomock.Controller recorder *MockIHeimdallClientMockRecorder + isgomock struct{} } // MockIHeimdallClientMockRecorder is the mock recorder for MockIHeimdallClient. @@ -61,7 +67,7 @@ func (m *MockIHeimdallClient) FetchCheckpoint(ctx context.Context, number int64) } // FetchCheckpoint indicates an expected call of FetchCheckpoint. -func (mr *MockIHeimdallClientMockRecorder) FetchCheckpoint(ctx, number interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) FetchCheckpoint(ctx, number any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpoint), ctx, number) } @@ -76,7 +82,7 @@ func (m *MockIHeimdallClient) FetchCheckpointCount(ctx context.Context) (int64, } // FetchCheckpointCount indicates an expected call of FetchCheckpointCount. -func (mr *MockIHeimdallClientMockRecorder) FetchCheckpointCount(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) FetchCheckpointCount(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpointCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpointCount), ctx) } @@ -91,7 +97,7 @@ func (m *MockIHeimdallClient) FetchMilestone(ctx context.Context) (*milestone.Mi } // FetchMilestone indicates an expected call of FetchMilestone. -func (mr *MockIHeimdallClientMockRecorder) FetchMilestone(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) FetchMilestone(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestone), ctx) } @@ -106,7 +112,7 @@ func (m *MockIHeimdallClient) FetchMilestoneCount(ctx context.Context) (int64, e } // FetchMilestoneCount indicates an expected call of FetchMilestoneCount. -func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneCount(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneCount(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestoneCount), ctx) } @@ -121,7 +127,7 @@ func (m *MockIHeimdallClient) FetchStatus(ctx context.Context) (*coretypes.SyncI } // FetchStatus indicates an expected call of FetchStatus. -func (mr *MockIHeimdallClientMockRecorder) FetchStatus(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) FetchStatus(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchStatus", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchStatus), ctx) } @@ -136,7 +142,7 @@ func (m *MockIHeimdallClient) GetLatestSpan(ctx context.Context) (*types.Span, e } // GetLatestSpan indicates an expected call of GetLatestSpan. -func (mr *MockIHeimdallClientMockRecorder) GetLatestSpan(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) GetLatestSpan(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestSpan", reflect.TypeOf((*MockIHeimdallClient)(nil).GetLatestSpan), ctx) } @@ -151,7 +157,7 @@ func (m *MockIHeimdallClient) GetSpan(ctx context.Context, spanID uint64) (*type } // GetSpan indicates an expected call of GetSpan. -func (mr *MockIHeimdallClientMockRecorder) GetSpan(ctx, spanID interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) GetSpan(ctx, spanID any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSpan", reflect.TypeOf((*MockIHeimdallClient)(nil).GetSpan), ctx, spanID) } @@ -166,7 +172,7 @@ func (m *MockIHeimdallClient) StateSyncEvents(ctx context.Context, fromID uint64 } // StateSyncEvents indicates an expected call of StateSyncEvents. -func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(ctx, fromID, to interface{}) *gomock.Call { +func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(ctx, fromID, to any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), ctx, fromID, to) } @@ -175,6 +181,7 @@ func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(ctx, fromID, to inter type MockIHeimdallWSClient struct { ctrl *gomock.Controller recorder *MockIHeimdallWSClientMockRecorder + isgomock struct{} } // MockIHeimdallWSClientMockRecorder is the mock recorder for MockIHeimdallWSClient. @@ -217,7 +224,7 @@ func (m *MockIHeimdallWSClient) SubscribeMilestoneEvents(ctx context.Context) <- } // SubscribeMilestoneEvents indicates an expected call of SubscribeMilestoneEvents. -func (mr *MockIHeimdallWSClientMockRecorder) SubscribeMilestoneEvents(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallWSClientMockRecorder) SubscribeMilestoneEvents(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeMilestoneEvents", reflect.TypeOf((*MockIHeimdallWSClient)(nil).SubscribeMilestoneEvents), ctx) } @@ -231,7 +238,7 @@ func (m *MockIHeimdallWSClient) Unsubscribe(ctx context.Context) error { } // Unsubscribe indicates an expected call of Unsubscribe. -func (mr *MockIHeimdallWSClientMockRecorder) Unsubscribe(ctx interface{}) *gomock.Call { +func (mr *MockIHeimdallWSClientMockRecorder) Unsubscribe(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unsubscribe", reflect.TypeOf((*MockIHeimdallWSClient)(nil).Unsubscribe), ctx) } From ce6db8028c8cfeab4640ca786e256c0b62472d51 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:19:13 +0530 Subject: [PATCH 18/30] update flags, docs and minor refactors --- consensus/bor/bor.go | 1 - core/blockchain.go | 1 - core/headerchain.go | 5 ----- docs/cli/default_config.toml | 2 +- docs/cli/server.md | 8 ++------ internal/cli/server/config.go | 33 ++++++++++++--------------------- internal/cli/server/flags.go | 16 +--------------- 7 files changed, 16 insertions(+), 50 deletions(-) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 05e6919848..d64ea7a237 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1196,7 +1196,6 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, if IsSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { start := time.Now() cx := statefull.ChainContext{Chain: chain, Bor: c} - // check and commit span if !c.config.IsRio(header.Number) { if err := c.checkAndCommitSpan(wrappedState, header, cx); err != nil { diff --git a/core/blockchain.go b/core/blockchain.go index 080a74e252..39d65ba7d3 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -490,7 +490,6 @@ func NewBlockChain(db ethdb.Database, genesis *Genesis, engine consensus.Engine, if err != nil { return nil, err } - bc.hc.vmConfig = &bc.cfg.VmConfig bc.flushInterval.Store(int64(cfg.TrieTimeLimit)) bc.forker = NewForkChoice(bc, cfg.ShouldPreserve, cfg.Checker) diff --git a/core/headerchain.go b/core/headerchain.go index 660b464716..1828e11133 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -108,11 +108,6 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c return hc, nil } -// GetVMConfig returns the VM config propagated from BlockChain, or nil if not set. -func (hc *HeaderChain) GetVMConfig() *vm.Config { - return hc.vmConfig -} - // GetBlockNumber retrieves the block number belonging to the given hash // from the cache or database func (hc *HeaderChain) GetBlockNumber(hash common.Hash) (uint64, bool) { diff --git a/docs/cli/default_config.toml b/docs/cli/default_config.toml index 534b88999d..c81e795853 100644 --- a/docs/cli/default_config.toml +++ b/docs/cli/default_config.toml @@ -3,7 +3,7 @@ identity = "" verbosity = 3 vmdebug = false vmtrace = "" -"vmtrace.jsonconfig" = "" +"vmtrace.jsonconfig" = "{}" "state.size-tracking" = false datadir = "/var/lib/bor" ancient = "" diff --git a/docs/cli/server.md b/docs/cli/server.md index 2de960b4e6..d903f26221 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -110,9 +110,9 @@ The ```bor server``` command runs the Bor client. - ```vmdebug```: Record information useful for VM and contract debugging (default: false) -- ```vmtrace```: Name of tracer which should observe internal VM operations (e.g. 'json') +- ```vmtrace```: Name of a tracer to record internal VM operations during blockchain synchronization (costly) (e.g. 'json') -- ```vmtrace.jsonconfig```: Tracer configuration (JSON) +- ```vmtrace.jsonconfig```: Tracer configuration (JSON) (default: {}) - ```witness.enable```: Enable witness protocol (default: false) @@ -280,10 +280,6 @@ The ```bor server``` command runs the Bor client. - ```vmodule```: Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) -- ```vmtrace```: Name of a tracer to record internal VM operations during blockchain synchronization (costly) - -- ```vmtrace.jsonconfig```: Tracer configuration (JSON) (default: {}) - ### P2P Options - ```bind```: Network binding address (default: 0.0.0.0) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index fa689db360..fb34f62940 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -173,12 +173,6 @@ type Config struct { // Relay has transaction relay related settings Relay *RelayConfig `hcl:"relay,block" toml:"relay,block"` - - // VMTrace Name of tracer which should record internal VM operations (costly) - VMTrace string `hcl:"vmtrace,optional" toml:"vmtrace,optional"` - - // VMTraceJsonConfig Tracer configuration (JSON) - VMTraceJsonConfig string `hcl:"vmtrace.jsonconfig,optional" toml:"vmtrace.jsonconfig,optional"` } type HistoryConfig struct { @@ -811,6 +805,7 @@ type RelayConfig struct { func DefaultConfig() *Config { return &Config{ Chain: "mainnet", + Ethstats: "", Identity: Hostname(), RequiredBlocks: map[string]string{}, Verbosity: 3, @@ -822,6 +817,17 @@ func DefaultConfig() *Config { KeyStoreDir: "", DisableBlindForkValidation: false, MaxBlindForkValidationLimit: whitelist.DefaultMaxForkCorrectnessLimit, + VMTrace: "", + VMTraceJsonConfig: "{}", + BatchRequestLimit: node.DefaultConfig.BatchRequestLimit, + BatchResponseMaxSize: node.DefaultConfig.BatchResponseMaxSize, + RPCReturnDataLimit: 100000, + SyncMode: "full", + GcMode: "full", + StateScheme: "path", + Snapshot: true, + BorLogs: false, + DevFakeAuthor: false, Logging: &LoggingConfig{ Vmodule: "", Json: false, @@ -829,9 +835,6 @@ func DefaultConfig() *Config { Debug: false, EnableBlockTracking: false, }, - BatchRequestLimit: node.DefaultConfig.BatchRequestLimit, - BatchResponseMaxSize: node.DefaultConfig.BatchResponseMaxSize, - RPCReturnDataLimit: 100000, P2P: &P2PConfig{ MaxPeers: 50, MaxPendPeers: 50, @@ -861,12 +864,6 @@ func DefaultConfig() *Config { GRPCAddress: "", WSAddress: "", }, - SyncMode: "full", - GcMode: "full", - StateScheme: "path", - Snapshot: true, - BorLogs: false, - TxPool: &TxPoolConfig{ Locals: []string{}, NoLocals: false, @@ -967,7 +964,6 @@ func DefaultConfig() *Config { VHosts: node.DefaultAuthVhosts, }, }, - Ethstats: "", Telemetry: &TelemetryConfig{ Enabled: false, Expensive: false, @@ -1027,7 +1023,6 @@ func DefaultConfig() *Config { Period: 0, GasLimit: 11500000, }, - DevFakeAuthor: false, Pprof: &PprofConfig{ Enabled: false, Port: 6060, @@ -1056,8 +1051,6 @@ func DefaultConfig() *Config { LogNoHistory: ethconfig.Defaults.LogNoHistory, StateHistory: params.FullImmutabilityThreshold, }, - VMTrace: "", - VMTraceJsonConfig: "{}", Health: &HealthConfig{ MaxGoRoutineThreshold: 0, WarnGoRoutineThreshold: 0, @@ -1686,8 +1679,6 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* } n.EnableBlockTracking = c.Logging.EnableBlockTracking - n.VMTrace = c.VMTrace - n.VMTraceJsonConfig = c.VMTraceJsonConfig // Blind fork acceptance configs n.DisableBlindForkValidation = c.DisableBlindForkValidation diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 288e8f5401..a056b41582 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -47,7 +47,7 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { }) f.StringFlag(&flagset.StringFlag{ Name: "vmtrace", - Usage: "Name of tracer which should observe internal VM operations (e.g. 'json')", + Usage: "Name of a tracer to record internal VM operations during blockchain synchronization (costly) (e.g. 'json')", Value: &c.cliConfig.VMTrace, Default: c.cliConfig.VMTrace, }) @@ -155,20 +155,6 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { Default: c.cliConfig.Logging.Vmodule, Group: "Logging", }) - f.StringFlag(&flagset.StringFlag{ - Name: "vmtrace", - Usage: "Name of a tracer to record internal VM operations during blockchain synchronization (costly)", - Value: &c.cliConfig.VMTrace, - Default: c.cliConfig.VMTrace, - Group: "Logging", - }) - f.StringFlag(&flagset.StringFlag{ - Name: "vmtrace.jsonconfig", - Usage: "Tracer configuration (JSON)", - Value: &c.cliConfig.VMTraceJsonConfig, - Default: c.cliConfig.VMTraceJsonConfig, - Group: "Logging", - }) f.BoolFlag(&flagset.BoolFlag{ Name: "log.json", Usage: "Format logs with JSON", From e28eec537f691a93477a66ab892b30dc9cb7503a Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:20:54 +0530 Subject: [PATCH 19/30] skip force loading tracers in cmd package --- cmd/cli/main.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/cli/main.go b/cmd/cli/main.go index aa47c53bfc..5863276d0b 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -5,11 +5,6 @@ import ( "github.com/ethereum/go-ethereum/internal/cli" "github.com/ethereum/go-ethereum/params" - - // Force-load the tracer engines to trigger registration - _ "github.com/ethereum/go-ethereum/eth/tracers/js" - _ "github.com/ethereum/go-ethereum/eth/tracers/live" - _ "github.com/ethereum/go-ethereum/eth/tracers/native" ) func main() { From cd0d9c7bba6995bd3984ac988af989feb6ee5402 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:21:41 +0530 Subject: [PATCH 20/30] remove vm config from header chain --- core/headerchain.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/headerchain.go b/core/headerchain.go index 1828e11133..08362e4daa 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -72,7 +71,6 @@ type HeaderChain struct { procInterrupt func() bool engine consensus.Engine - vmConfig *vm.Config // VM configuration (propagated from BlockChain) stateSyncData []*types.StateSyncData // State sync data } From 5f16ec64eb1920e58fa83d7eb0da3dafbdbcf4bc Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:23:40 +0530 Subject: [PATCH 21/30] update docs --- docs/cli/example_config.toml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml index 05680c467a..de93bf5b22 100644 --- a/docs/cli/example_config.toml +++ b/docs/cli/example_config.toml @@ -21,6 +21,10 @@ ethstats = "" # Reporting URL of a ethstats service (nodename: witnessprotocol = false # Enables the wit/0 protocol devfakeauthor = false # Run miner without validator set authorization [dev mode] : Use with '--bor.withoutheimdall' (default: false) +# VM tracing +vmtrace = "supply" # Name of a tracer to record internal VM operations during blockchain synchronization (costly) +"vmtrace.jsonconfig" = '{"path": "output"}' # Tracer configuration (JSON) + ["eth.requiredblocks"] # Comma separated block number-to-hash mappings to require for peering (=) (default = empty map) "31000000" = "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e" "32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68" @@ -31,13 +35,11 @@ enable-private-tx = true # Enable private transaction relay bp-rpc-endpoints = [ ] # Comma separated rpc endpoints of all block producers [log] -vmodule = "" # Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) -json = false # Format logs with JSON -backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271") -debug = true # Prepends log messages with call-site location (file and line number) -enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle -vmtrace = "supply" # Name of a tracer to record internal VM operations during blockchain synchronization (costly) -vmtrace.jsonconfig = '{"path": "output"}' # Tracer configuration (JSON) + vmodule = "" # Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4) + json = false # Format logs with JSON + backtrace = "" # Request a stack trace at a specific logging statement (e.g. "block.go:271") + debug = true # Prepends log messages with call-site location (file and line number) + enable-block-tracking = false # Enables additional logging of information collected while tracking block lifecycle [p2p] maxpeers = 50 # Maximum number of network peers (network disabled if set to 0) From 9d1096f2479008ace47e0d96c179ba72e024acb9 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 17 Mar 2026 01:26:39 +0530 Subject: [PATCH 22/30] small refactor --- core/state_processor.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 8e00e0db5f..a0411e5215 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -133,12 +133,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg allLogs = append(allLogs, receipt.Logs...) } - if len(txs) > 0 && txs[len(txs)-1].Type() == types.StateSyncTxType { - if hooks := evm.Config.Tracer; hooks != nil && hooks.OnTxStart != nil { - hooks.OnTxStart(evm.GetVMContext(), txs[len(txs)-1], params.BorSystemAddress) - } - } - // Polygon/bor: EIP-6110, EIP-7002, and EIP-7251 are not supported // Read requests if Prague is enabled. var requests [][]byte @@ -158,6 +152,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } } + // Trace state-sync transaction (if present and if tracer is enabled) + if len(txs) > 0 && txs[len(txs)-1].Type() == types.StateSyncTxType { + if hooks := evm.Config.Tracer; hooks != nil && hooks.OnTxStart != nil { + hooks.OnTxStart(evm.GetVMContext(), txs[len(txs)-1], params.BorSystemAddress) + } + } + // Finalize the block, applying any consensus engine specific extras (e.g. block rewards), apply // state sync event (if any), and append the receipt. receiptsCountBeforeFinalize := len(receipts) From 83b8a8334a51076999d19d7e0197be04be10d58b Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Mar 2026 13:10:41 +0530 Subject: [PATCH 23/30] cmd/keeper: go mod tidy --- cmd/keeper/go.mod | 1 - cmd/keeper/go.sum | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/keeper/go.mod b/cmd/keeper/go.mod index 1da16dd486..768125cbd1 100644 --- a/cmd/keeper/go.mod +++ b/cmd/keeper/go.mod @@ -52,7 +52,6 @@ require ( golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/sys v0.40.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/cmd/keeper/go.sum b/cmd/keeper/go.sum index e67813369a..43778f130f 100644 --- a/cmd/keeper/go.sum +++ b/cmd/keeper/go.sum @@ -165,11 +165,11 @@ golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= From 6f2062c80cacd1d319787c26e152262e8fe053c5 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Mar 2026 13:20:14 +0530 Subject: [PATCH 24/30] eth/tracers: refactor all trace methods for better state-sync handling --- eth/tracers/api.go | 538 +++++++++++++++++++++++++++------------------ eth/tracers/dir.go | 4 + 2 files changed, 330 insertions(+), 212 deletions(-) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index a2e2d55c1e..5e2ae27bed 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -333,17 +333,6 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf // The tracing procedure should be aborted in case the closed signal is received. // nolint:gocognit func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan error) chan *blockTraceResult { - if config == nil { - config = &TraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - BorTx: newBoolPtr(false), - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } - reexec := defaultTraceReexec if config != nil && config.Reexec != nil { reexec = *config.Reexec @@ -351,7 +340,6 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed blocks := int(end.NumberU64() - start.NumberU64()) threads := runtime.NumCPU() - if threads > blocks { threads = blocks } @@ -373,50 +361,28 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed // Fetch and execute the block trace taskCh for task := range taskCh { var ( - signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) - blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) + signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) + blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) + cumulativeGasUsed uint64 ) - // Trace all the transactions contained within - txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, task.block) - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - isMadhugiri := api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(task.block.Number()) - includeStateSyncTx := isMadhugiri || *config.BorTraceEnabled - if stateSyncPresent && !includeStateSyncTx { - txs = txs[:len(txs)-1] - stateSyncPresent = false - } - - for i, tx := range txs { + for i, tx := range task.block.Transactions() { msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) - txHash := tx.Hash() - if stateSyncPresent && i == len(txs)-1 { - txHash = stateSyncHash - } txctx := &Context{ - BlockHash: task.block.Hash(), - BlockNumber: task.block.Number(), - TxIndex: i, - TxHash: txHash, - } - - var res interface{} - - var err error - - // Deep copy config for this transaction to avoid race conditions - txConfig := deepCopyTraceConfig(config) - if stateSyncPresent && i == len(txs)-1 && includeStateSyncTx { - txConfig.BorTx = newBoolPtr(true) + BlockHash: task.block.Hash(), + BlockNumber: task.block.Number(), + TxIndex: i, + TxHash: tx.Hash(), + CumulativeGasUsed: cumulativeGasUsed, + LogIndex: len(task.statedb.Logs()), } - - res, err = api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, &txConfig, nil) + res, gasUsed, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config, nil) if err != nil { - task.results[i] = &txTraceResult{TxHash: txHash, Error: err.Error()} - log.Warn("Tracing failed", "hash", txHash, "block", task.block.NumberU64(), "err", err) - + task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()} + log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) break } - task.results[i] = &txTraceResult{TxHash: txHash, Result: res} + cumulativeGasUsed += gasUsed + task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res} } // Tracing state is used up, queue it for de-referencing. Note the // state is the parent state of trace block, use block.number-1 as @@ -673,17 +639,6 @@ func prepareCallMessage(msg core.Message) statefull.Callmsg { // IntermediateRoots executes a block (bad- or canon- or side-), and returns a list // of intermediate roots: the stateroot after each transaction. func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { - if config == nil { - config = &TraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - BorTx: newBoolPtr(false), - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } - block, _ := api.blockByHash(ctx, hash) if block == nil { // Check in the bad blocks @@ -729,54 +684,37 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config core.ProcessParentBlockHash(block.ParentHash(), evm) } - txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, block) - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - isMadhugiri := chainConfig.Bor != nil && chainConfig.Bor.IsMadhugiri(block.Number()) - includeStateSyncTx := isMadhugiri || *config.BorTraceEnabled - for i, tx := range txs { + for i, tx := range block.Transactions() { if err := ctx.Err(); err != nil { return nil, err } - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - - //nolint:nestif - if stateSyncPresent && i == len(txs)-1 { - if includeStateSyncTx { - callmsg := prepareCallMessage(*msg) - statedb.SetTxContext(stateSyncHash, i) - if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx), vm.Config{}); err != nil { - log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", stateSyncHash, "err", err) - // We intentionally don't return the error here: if we do, then the RPC server will not - // return the roots. Most likely, the caller already knows that a certain transaction fails to - // be included, but still want the intermediate roots that led to that point. - // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be - // executable. - // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. - return roots, nil - } - } else { - break - } + statedb.SetTxContext(tx.Hash(), i) + var err error + // State sync transactions are processed differently than normal transactions + if tx.Type() == types.StateSyncTxType { + // Set tx context so that opcodes like GASPRICE don't panic. + evm.SetTxContext(core.NewEVMTxContext(msg)) + callmsg := prepareCallMessage(*msg) + _, err = statefull.ApplyBorMessage(evm, callmsg) } else { - statedb.SetTxContext(tx.Hash(), i) - if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { - log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) - // We intentionally don't return the error here: if we do, then the RPC server will not - // return the roots. Most likely, the caller already knows that a certain transaction fails to - // be included, but still want the intermediate roots that led to that point. - // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be - // executable. - // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. - return roots, nil - } + _, err = core.ApplyMessage(evm, msg, nil) } + if err != nil { + log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) + // We intentionally don't return the error here: if we do, then the RPC server will not + // return the roots. Most likely, the caller already knows that a certain transaction fails to + // be included, but still want the intermediate roots that led to that point. + // It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be + // executable. + // N.B: This should never happen while tracing canon blocks, only when tracing bad blocks. + return roots, nil + } // calling IntermediateRoot will internally call Finalize on the state // so any modifications are written to the trie roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects)) } - return roots, nil } @@ -792,13 +730,203 @@ func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Has return api.standardTraceBlockToFile(ctx, block, config) } +// traceBlock configures a new tracer according to the provided configuration, and +// executes all the transactions contained within. The return value will be one item +// per transaction, dependent on the requested tracer. +func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { + if block.NumberU64() == 0 { + return nil, errors.New("genesis is not traceable") + } + // Prepare base state + parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) + if err != nil { + return nil, err + } + reexec := defaultTraceReexec + if config != nil && config.Reexec != nil { + reexec = *config.Reexec + } + statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) + if err != nil { + return nil, err + } + defer release() + + blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) + if beaconRoot := block.BeaconRoot(); beaconRoot != nil { + core.ProcessBeaconBlockRoot(*beaconRoot, evm) + } + if api.backend.ChainConfig().IsPrague(block.Number()) { + core.ProcessParentBlockHash(block.ParentHash(), evm) + } + + // JS tracers have high overhead. In this case run a parallel + // process that generates states in one thread and traces txes + // in separate worker threads. + if config != nil && config.Tracer != nil && *config.Tracer != "" { + if isJS := DefaultDirectory.IsJS(*config.Tracer); isJS { + return api.traceBlockParallel(ctx, block, statedb, config) + } + } + + // As state-sync transactions before Madhugiri don't have event data within, we can't replay them. Only + // those post Madhugiri have data to be replayed and are part of block body. If there's a state-sync + // transaction, it should be included in the `block.Transactions()` list below. + // Native tracers have low overhead + var ( + txs = block.Transactions() + blockHash = block.Hash() + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) + results = make([]*txTraceResult, len(txs)) + cumulativeGasUsed uint64 + ) + for i, tx := range txs { + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + txctx := &Context{ + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: i, + TxHash: tx.Hash(), + CumulativeGasUsed: cumulativeGasUsed, + LogIndex: len(statedb.Logs()), + } + res, gasUsed, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config, nil) + if err != nil { + return nil, err + } + cumulativeGasUsed += gasUsed + results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res} + } + return results, nil +} + +// traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread +// runs along and executes txes without tracing enabled to generate their prestate. +// Worker threads take the tasks and the prestate and trace them. +// State-sync transactions (if present) are traced sequentially after all regular transactions +// complete, so that the statedb has the correct accumulated state for log index and cumulative gas. +func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { + var ( + txs = block.Transactions() + isStateSyncPresent bool + blockHash = block.Hash() + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) + results = make([]*txTraceResult, len(txs)) + pend sync.WaitGroup + ) + + threads := runtime.NumCPU() + if threads > len(txs) { + threads = len(txs) + } + if threads == 0 { + threads = 1 + } + jobs := make(chan *txTraceTask, threads) + for th := 0; th < threads; th++ { + pend.Add(1) + go func() { + defer pend.Done() + // Fetch and execute the next transaction trace tasks + for task := range jobs { + msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) + txctx := &Context{ + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: task.index, + TxHash: txs[task.index].Hash(), + } + // Reconstruct the block context for each transaction + // as the GetHash function of BlockContext is not safe for + // concurrent use. + // See: https://github.com/ethereum/go-ethereum/issues/29114 + blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + res, _, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config, nil) + if err != nil { + results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()} + continue + } + results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res} + } + }() + } + + // Feed the transactions into the tracers and return + var failed error + blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) + evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) + + // Track cumulative gas used to populate state-sync receipt at the very end (if it exists) + var cumulativeGasUsed uint64 + +txloop: + for i, tx := range txs { + // Skip process state-sync tx in parallel. + if tx.Type() == types.StateSyncTxType { + isStateSyncPresent = true + continue + } + // Send the trace task over for execution + task := &txTraceTask{statedb: statedb.Copy(), index: i} + select { + case <-ctx.Done(): + failed = ctx.Err() + break txloop + case jobs <- task: + } + + // Generate the next state snapshot fast without tracing + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + statedb.SetTxContext(tx.Hash(), i) + res, err := core.ApplyMessage(evm, msg, nil) + if err != nil { + failed = err + break txloop + } + cumulativeGasUsed += res.UsedGas + // Finalize the state so any modifications are written to the trie + // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect + statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number())) + } + + close(jobs) + pend.Wait() + + // If execution failed in between, abort + if failed != nil { + return nil, failed + } + + if isStateSyncPresent { + tx := txs[len(txs)-1] + msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) + txctx := &Context{ + BlockHash: blockHash, + BlockNumber: block.Number(), + TxIndex: len(txs) - 1, + TxHash: tx.Hash(), + CumulativeGasUsed: cumulativeGasUsed, + LogIndex: len(statedb.Logs()), + } + res, _, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config, nil) + if err != nil { + results[txctx.TxIndex] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()} + } else { + results[txctx.TxIndex] = &txTraceResult{TxHash: tx.Hash(), Result: res} + } + } + + return results, nil +} + // traceBlock configures a new tracer according to the provided configuration, and // executes all the transactions contained within. The return value will be one item // per transaction, dependent on the requested tracer. // We always run parallel execution // One thread runs along and executes txs without tracing enabled to generate their prestate. // Worker threads take the tasks and the prestate and trace them. -func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { +func (api *API) traceBlock2(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { if config == nil { config = &TraceConfig{ BorTraceEnabled: defaultBorTraceEnabled, @@ -900,7 +1028,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // concurrent use. // See: https://github.com/ethereum/go-ethereum/issues/29114 blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - res, err = api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, &txConfig, nil) + res, _, err = api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, &txConfig, nil) if err != nil { results[task.index] = &txTraceResult{TxHash: txHash, Error: err.Error()} continue @@ -965,6 +1093,8 @@ txloop: if stateSyncPresent && i == len(txs)-1 { if *config.BorTraceEnabled { callmsg := prepareCallMessage(*msg) + // Set TxContext so opcodes like GASPRICE don't panic on nil GasPrice. + evm.SetTxContext(core.NewEVMTxContext(msg)) // nolint : contextcheck if _, err := statefull.ApplyBorMessage(evm, callmsg); err != nil { failed = err @@ -1063,18 +1193,9 @@ txloop: // and traces either a full block or an individual transaction. The return value will // be one filename per transaction traced. func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) { - if config == nil { - config = &StdTraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } // If we're tracing a single transaction, make sure it's present if config != nil && config.TxHash != (common.Hash{}) { - if !api.containsTx(ctx, block, config.TxHash) { + if !containsTx(block, config.TxHash) { return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash) } } @@ -1128,15 +1249,6 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block chainConfig, canon = overrideConfig(chainConfig, config.Overrides) } - txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, block) - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - isMadhugiri := api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(block.Number()) - includeStateSyncTx := isMadhugiri || *config.BorTraceEnabled - if stateSyncPresent && !includeStateSyncTx { - txs = txs[:len(txs)-1] - stateSyncPresent = false - } - evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) if beaconRoot := block.BeaconRoot(); beaconRoot != nil { core.ProcessBeaconBlockRoot(*beaconRoot, evm) @@ -1144,12 +1256,20 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block if chainConfig.IsPrague(block.Number()) { core.ProcessParentBlockHash(block.ParentHash(), evm) } - for i, tx := range txs { + for i, tx := range block.Transactions() { // Prepare the transaction for un-traced execution msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - if txHash != (common.Hash{}) && tx.Hash() != txHash && txHash != stateSyncHash { + if txHash != (common.Hash{}) && tx.Hash() != txHash { // Process the tx to update state, but don't trace it. - _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) + var err error + if tx.Type() == types.StateSyncTxType { + // Set tx context so that opcodes like GASPRICE don't panic. + evm.SetTxContext(core.NewEVMTxContext(msg)) + callmsg := prepareCallMessage(*msg) + _, err = statefull.ApplyBorMessage(evm, callmsg) + } else { + _, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) + } if err != nil { return dumps, err } @@ -1180,32 +1300,25 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block }) ) // Execute the transaction and flush any traces to disk - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - //nolint:nestif - if stateSyncPresent && i == len(txs)-1 && includeStateSyncTx { + statedb.SetTxContext(tx.Hash(), i) + // Handle differently for state sync transactions + if tx.Type() == types.StateSyncTxType { + // Set tx context so that opcodes like GASPRICE don't panic. + evm.SetTxContext(core.NewEVMTxContext(msg)) callmsg := prepareCallMessage(*msg) - statedb.SetTxContext(stateSyncHash, i) - _, err = statefull.ApplyBorMessage(evm, callmsg) - - if writer != nil { - _ = writer.Flush() + if tracer.OnTxStart != nil { + tracer.OnTxStart(evm.GetVMContext(), tx, params.BorSystemAddress) } - } else if !(stateSyncPresent && i == len(txs)-1) { - statedb.SetTxContext(tx.Hash(), i) + _, err = statefull.ApplyBorMessage(evm, callmsg) + } else { if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) } - - // nolint : contextcheck - vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) - if tracer.OnTxEnd != nil { - tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err) - } - if writer != nil { - _ = writer.Flush() - } + _, err = core.ApplyMessage(evm, msg, nil) + } + if writer != nil { + _ = writer.Flush() } - if dump != nil { dump.Close() log.Info("Wrote standard trace", "file", dump.Name()) @@ -1229,58 +1342,35 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // containsTx reports whether the transaction with a certain hash // is contained within the specified block. -func (api *API) containsTx(ctx context.Context, block *types.Block, hash common.Hash) bool { - txs, _, stateSyncHash := api.getAllBlockTransactions(ctx, block) - for _, tx := range txs { - if tx.Hash() == hash || stateSyncHash == hash { +func containsTx(block *types.Block, hash common.Hash) bool { + for _, tx := range block.Transactions() { + if tx.Hash() == hash { return true } } - return false } // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) { - if config == nil { - config = &TraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - BorTx: newBoolPtr(false), - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } - found, _, blockHash, blockNumber, index := api.backend.GetCanonicalTransaction(hash) if !found { - // For BorTransaction, there will be no trace available - tx, _, _, _ := rawdb.ReadBorTransaction(api.backend.ChainDb(), hash) - if tx != nil { - return &logger.ExecutionResult{ - StructLogs: make([]json.RawMessage, 0), - }, nil - } else { - // Warn in case tx indexer is not done. - if !api.backend.TxIndexDone() { - return nil, ethapi.NewTxIndexingError() - } - // Only mined txes are supported - return nil, errTxNotFound + // Warn in case tx indexer is not done. + if !api.backend.TxIndexDone() { + return nil, ethapi.NewTxIndexingError() } + // Only mined txes are supported + return nil, errTxNotFound } // It shouldn't happen in practice. if blockNumber == 0 { return nil, errors.New("genesis is not traceable") } - reexec := defaultTraceReexec if config != nil && config.Reexec != nil { reexec = *config.Reexec } - block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash) if err != nil { return nil, err @@ -1289,20 +1379,25 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config * if err != nil { return nil, err } - defer release() - msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee()) - if err != nil { - return nil, err - } txctx := &Context{ BlockHash: blockHash, BlockNumber: block.Number(), TxIndex: int(index), TxHash: hash, + // This field is only used for bor transactions. Use block gas used as state-sync is + // always the last tx. + CumulativeGasUsed: block.GasUsed(), + LogIndex: len(statedb.Logs()), } - return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config, nil) + + msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee()) + if err != nil { + return nil, err + } + res, _, err := api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config, nil) + return res, err } // TraceCall lets you trace a given eth_call. It collects the structured logs @@ -1405,31 +1500,21 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc if config != nil { traceConfig = &config.TraceConfig } - return api.traceTx(ctx, tx, msg, new(Context), blockContext, statedb, traceConfig, precompiles) + res, _, err := api.traceTx(ctx, tx, msg, new(Context), blockContext, statedb, traceConfig, precompiles) + return res, err } // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will -// be tracer dependent. -func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig, precompiles vm.PrecompiledContracts) (interface{}, error) { - if config == nil { - config = &TraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - BorTx: newBoolPtr(false), - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } - +// be tracer dependent. For state-sync transactions, it only supports transactions +// which are post Madhugiri HF. +func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig, precompiles vm.PrecompiledContracts) (interface{}, uint64, error) { var ( tracer *Tracer err error timeout = defaultTraceTimeout usedGas uint64 ) - if config == nil { config = &TraceConfig{} } @@ -1444,7 +1529,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor } else { tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig, api.backend.ChainConfig()) if err != nil { - return nil, err + return nil, 0, err } } tracingStateDB := state.NewHookedState(statedb, tracer.Hooks) @@ -1456,47 +1541,76 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor // Define a meaningful timeout of a single transaction trace if config.Timeout != nil { if timeout, err = time.ParseDuration(*config.Timeout); err != nil { - return nil, err + return nil, 0, err } } - deadlineCtx, cancel := context.WithTimeout(ctx, timeout) - go func() { <-deadlineCtx.Done() - if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) { tracer.Stop(errors.New("execution timeout")) // Stop evm execution. Note cancellation is not necessarily immediate. evm.Cancel() } }() - defer cancel() // Call Prepare to clear out the statedb access list statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - if config.BorTx == nil { - config.BorTx = newBoolPtr(false) - } + // Handle state-sync transactions separately. They're part of block body post Madhugiri so we can replay them + // and gather traces. + if tx.Type() == types.StateSyncTxType && api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(txctx.BlockNumber) { + // We need to do some additional work as ApplyBorMessage directly applies message skipping some steps + // needed for tracing. + + // Set tx context so that opcodes like GASPRICE don't panic. + evm.SetTxContext(core.NewEVMTxContext(message)) - if *config.BorTx { + // Call `OnTxStart` and `OnTxEnd` hooks before and after applying message. callmsg := prepareCallMessage(*message) - // nolint : contextcheck - if _, err := statefull.ApplyBorMessage(evm, callmsg); err != nil { - return nil, fmt.Errorf("tracing failed: %w", err) + if tracer.Hooks.OnTxStart != nil { + tracer.Hooks.OnTxStart(evm.GetVMContext(), tx, params.BorSystemAddress) } - } else { - // Call Prepare to clear out the statedb access list - statedb.SetTxContext(txctx.TxHash, txctx.TxIndex) - _, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, vmctx.Time, tx, &usedGas, evm) + res, err := statefull.ApplyBorMessage(evm, callmsg) if err != nil { - return nil, fmt.Errorf("tracing failed: %w", err) + if tracer.Hooks.OnTxEnd != nil { + tracer.Hooks.OnTxEnd(nil, err) + } + return nil, 0, fmt.Errorf("tracing failed: %w", err) + } + if tracer.Hooks.OnTxEnd != nil { + // Generate a receipt on the fly for tracing. Use LogIndex and CumulativeGasUsed + // from txctx which are populated by the caller based on prior transactions. + allLogs := tracingStateDB.Logs() + stateSyncLogs := allLogs[txctx.LogIndex:] + for _, l := range stateSyncLogs { + l.TxIndex = uint(txctx.TxIndex) + } + receipt := &types.Receipt{ + Type: types.StateSyncTxType, + Status: types.ReceiptStatusSuccessful, + CumulativeGasUsed: txctx.CumulativeGasUsed + res.UsedGas, + Logs: stateSyncLogs, + GasUsed: res.UsedGas, + TxHash: tx.Hash(), + BlockNumber: txctx.BlockNumber, + BlockHash: txctx.BlockHash, + } + tracer.Hooks.OnTxEnd(receipt, nil) } + + result, err := tracer.GetResult() + return result, res.UsedGas, err } - return tracer.GetResult() + // Handle normal transactions + _, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, vmctx.Time, tx, &usedGas, evm) + if err != nil { + return nil, 0, fmt.Errorf("tracing failed: %w", err) + } + result, err := tracer.GetResult() + return result, usedGas, err } // APIs return the collection of RPC services the tracer package offers. diff --git a/eth/tracers/dir.go b/eth/tracers/dir.go index 05c76bceb7..cfb4fec0e0 100644 --- a/eth/tracers/dir.go +++ b/eth/tracers/dir.go @@ -32,6 +32,10 @@ type Context struct { BlockNumber *big.Int // Number of the block the tx is contained within (zero if dangling tx or call) TxIndex int // Index of the transaction within a block (zero if dangling tx or call) TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) + + // Bor specific fields used for state-sync transaction tracing + CumulativeGasUsed uint64 // Cumulative gas used by all prior txs in the block + LogIndex int // Number of logs emitted by all prior txs in the block } // Tracer represents the set of methods that must be exposed by a tracer From cddeedfcc4f503144cc56f2f7379037ecbb69872 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Mar 2026 14:06:02 +0530 Subject: [PATCH 25/30] eth: handle out of bound index --- eth/state_accessor.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eth/state_accessor.go b/eth/state_accessor.go index d7f755c5ab..0fc292df6a 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -265,6 +265,9 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, if txIndex == 0 && len(block.Transactions()) == 0 { return nil, context, statedb, release, nil } + if txIndex >= len(block.Transactions()) { + return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) + } // Recompute transactions up to the target index. signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { From 2a4d48438e1e0ac0526339980439f94e3da0503c Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Mar 2026 14:06:34 +0530 Subject: [PATCH 26/30] eth/tracers: remove TraceBorBlock cli sub-command --- eth/tracers/api.go | 367 ++------------------------------- eth/tracers/api_bor.go | 160 -------------- eth/tracers/api_test.go | 88 -------- internal/cli/server/server.go | 4 - internal/cli/server/service.go | 29 +-- 5 files changed, 16 insertions(+), 632 deletions(-) delete mode 100644 eth/tracers/api_bor.go diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 5e2ae27bed..4f26ecdbcc 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -19,19 +19,15 @@ package tracers import ( "bufio" "context" - "encoding/hex" "encoding/json" "errors" "fmt" "math/big" "os" - "path/filepath" "runtime" "sync" "time" - "github.com/holiman/uint256" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -40,7 +36,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" @@ -74,22 +69,14 @@ const ( // for tracing. The creation of trace state will be paused if the unused // trace states exceed this limit. maximumPendingTraceStates = 128 - - defaultPath = string(".") - - defaultIOFlag = false ) -var defaultBorTraceEnabled = newBoolPtr(false) - var errTxNotFound = errors.New("transaction not found") // StateReleaseFunc is used to deallocate resources held by constructing a // historical state for tracing purposes. type StateReleaseFunc func() -var allowIOTracing = false // Change this to true to enable IO tracing for debugging - // Backend interface provides the common API services (that are provided by // both full and light clients) with access to necessary functions. type Backend interface { @@ -106,9 +93,6 @@ type Backend interface { ChainDb() ethdb.Database StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) - - // Bor related APIs - GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) } // API is the collection of tracing APIs exposed over the private debugging endpoint. @@ -175,38 +159,6 @@ func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber return api.blockByHash(ctx, hash) } -// getAllBlockTransactions returns all blocks transactions including state-sync transaction if present -// along with a flag and it's hash (which is calculated differently than regular transactions) -func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool, common.Hash) { - var ( - txs types.Transactions = block.Transactions() - stateSyncPresent bool - stateSyncHash common.Hash - ) - - isMadhugiri := api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(block.Number()) - if isMadhugiri { - if len(txs) > 0 && txs[len(txs)-1].Type() == types.StateSyncTxType { - stateSyncPresent = true - stateSyncHash = txs[len(txs)-1].Hash() - } - return txs, stateSyncPresent, stateSyncHash - } - - borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64(), api.backend.ChainConfig()) - if borReceipt != nil { - txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash())) - if txHash != (common.Hash{}) { - borTx, _, _, _, _ := api.backend.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash()) - txs = append(txs, borTx) - stateSyncPresent = true - stateSyncHash = txHash - } - } - - return txs, stateSyncPresent, stateSyncHash -} - // TraceConfig holds extra parameters to trace functions. type TraceConfig struct { *logger.Config @@ -217,29 +169,7 @@ type TraceConfig struct { IOFlag *bool // Config specific to given tracer. Note struct logger // config are historically embedded in main object. - TracerConfig json.RawMessage - BorTraceEnabled *bool - BorTx *bool -} - -// deepCopyTraceConfig returns a deep copy of the given TraceConfig so that -// each goroutine can safely mutate its own copy without racing. -func deepCopyTraceConfig(config *TraceConfig) TraceConfig { - cpy := *config - if config.Config != nil { - loggerCfg := *config.Config - cpy.Config = &loggerCfg - } - if config.BorTx != nil { - cpy.BorTx = newBoolPtr(*config.BorTx) - } - if config.BorTraceEnabled != nil { - cpy.BorTraceEnabled = newBoolPtr(*config.BorTraceEnabled) - } - if config.TracerConfig != nil { - cpy.TracerConfig = append(json.RawMessage{}, config.TracerConfig...) - } - return cpy + TracerConfig json.RawMessage } // TraceCallConfig is the config for traceCall API. It holds one more @@ -254,9 +184,8 @@ type TraceCallConfig struct { // StdTraceConfig holds extra parameters to standard-json trace functions. type StdTraceConfig struct { logger.Config - Reexec *uint64 - TxHash common.Hash - BorTraceEnabled *bool + Reexec *uint64 + TxHash common.Hash } // txTraceResult is the result of a single transaction trace. @@ -548,11 +477,6 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed return retCh } -func newBoolPtr(bb bool) *bool { - b := bb - return &b -} - // TraceBlockByNumber returns the structured logs created during the execution of // EVM and returns them as a JSON object. func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) { @@ -698,7 +622,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config callmsg := prepareCallMessage(*msg) _, err = statefull.ApplyBorMessage(evm, callmsg) } else { - _, err = core.ApplyMessage(evm, msg, nil) + _, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) } if err != nil { @@ -879,7 +803,7 @@ txloop: // Generate the next state snapshot fast without tracing msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) - res, err := core.ApplyMessage(evm, msg, nil) + res, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) if err != nil { failed = err break txloop @@ -920,275 +844,6 @@ txloop: return results, nil } -// traceBlock configures a new tracer according to the provided configuration, and -// executes all the transactions contained within. The return value will be one item -// per transaction, dependent on the requested tracer. -// We always run parallel execution -// One thread runs along and executes txs without tracing enabled to generate their prestate. -// Worker threads take the tasks and the prestate and trace them. -func (api *API) traceBlock2(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { - if config == nil { - config = &TraceConfig{ - BorTraceEnabled: defaultBorTraceEnabled, - BorTx: newBoolPtr(false), - } - } - - if config.BorTraceEnabled == nil { - config.BorTraceEnabled = defaultBorTraceEnabled - } - - if block.NumberU64() == 0 { - return nil, errors.New("genesis is not traceable") - } - // Prepare base state - parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) - if err != nil { - return nil, err - } - - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - - path := defaultPath - if config != nil && config.Path != nil { - path = *config.Path - } - - ioflag := defaultIOFlag - if allowIOTracing && config != nil && config.IOFlag != nil { - ioflag = *config.IOFlag - } - - statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, err - } - - defer release() - - // create and add empty mvHashMap in statedb as StateAtBlock does not have mvHashmap in it. - if ioflag { - statedb.AddEmptyMVHashMap() - } - - // Execute all the transaction contained within the block concurrently - var ( - txs, stateSyncPresent, stateSyncHash = api.getAllBlockTransactions(ctx, block) - blockHash = block.Hash() - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - results = make([]*txTraceResult, len(txs)) - pend sync.WaitGroup - ) - - threads := runtime.NumCPU() - if threads > len(txs) { - threads = len(txs) - } - - jobs := make(chan *txTraceTask, threads) - - for th := 0; th < threads; th++ { - pend.Add(1) - - go func() { - defer pend.Done() - // Fetch and execute the next transaction trace tasks - for task := range jobs { - msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) - txHash := txs[task.index].Hash() - if stateSyncPresent && task.index == len(txs)-1 { - txHash = stateSyncHash - } - txctx := &Context{ - BlockHash: blockHash, - BlockNumber: block.Number(), - TxIndex: task.index, - TxHash: txHash, - } - - var res interface{} - - var err error - - // Deep copy config for this transaction to avoid race conditions - txConfig := deepCopyTraceConfig(config) - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - if stateSyncPresent && task.index == len(txs)-1 { - isMadhugiri := api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(block.Number()) - if isMadhugiri || *config.BorTraceEnabled { - txConfig.BorTx = newBoolPtr(true) - } - } - - // Reconstruct the block context for each transaction - // as the GetHash function of BlockContext is not safe for - // concurrent use. - // See: https://github.com/ethereum/go-ethereum/issues/29114 - blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - res, _, err = api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, &txConfig, nil) - if err != nil { - results[task.index] = &txTraceResult{TxHash: txHash, Error: err.Error()} - continue - } - results[task.index] = &txTraceResult{TxHash: txHash, Result: res} - } - }() - } - - var IOdump string - - var RWstruct []state.DumpStruct - - var london bool - - if ioflag { - IOdump = "TransactionIndex, Incarnation, VersionTxIdx, VersionInc, Path, Operation\n" - RWstruct = []state.DumpStruct{} - } - // Feed the transactions into the tracers and return - var failed error - - if ioflag { - london = api.backend.ChainConfig().IsLondon(block.Number()) - } - - blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) - - // Process beacon block root (EIP-4788) and parent block hash (EIP-2935) - // before executing transactions, matching stateAtTransaction behavior. - if beaconRoot := block.BeaconRoot(); beaconRoot != nil { - core.ProcessBeaconBlockRoot(*beaconRoot, evm) - } - if api.backend.ChainConfig().IsPrague(block.Number()) { - core.ProcessParentBlockHash(block.ParentHash(), evm) - } - -txloop: - for i, tx := range txs { - if ioflag { - // copy of statedb - statedb = statedb.Copy() - } - - // Send the trace task over for execution - task := &txTraceTask{statedb: statedb.Copy(), index: i} - select { - case <-ctx.Done(): - failed = ctx.Err() - break txloop - case jobs <- task: - } - - // Generate the next state snapshot fast without tracing - msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - statedb.SetTxContext(tx.Hash(), i) - - // nolint:nestif - if !ioflag { - //nolint:nestif - if stateSyncPresent && i == len(txs)-1 { - if *config.BorTraceEnabled { - callmsg := prepareCallMessage(*msg) - // Set TxContext so opcodes like GASPRICE don't panic on nil GasPrice. - evm.SetTxContext(core.NewEVMTxContext(msg)) - // nolint : contextcheck - if _, err := statefull.ApplyBorMessage(evm, callmsg); err != nil { - failed = err - break txloop - } - } else { - break txloop - } - } else { - // nolint : contextcheck - if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { - failed = err - break txloop - } - // Finalize the state so any modifications are written to the trie - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number())) - } - } else { - coinbaseBalance := big.NewInt(statedb.GetBalance(blockCtx.Coinbase).ToBig().Int64()) - // nolint : contextcheck - result, err := core.ApplyMessageNoFeeBurnOrTip(evm, *msg, new(core.GasPool).AddGas(msg.GasLimit)) - - if err != nil { - failed = err - break - } - - if london { - statedb.AddBalance(result.BurntContractAddress, uint256.NewInt(result.FeeBurnt.Uint64()), tracing.BalanceChangeTransfer) - } - - statedb.AddBalance(blockCtx.Coinbase, uint256.NewInt(result.FeeTipped.Uint64()), tracing.BalanceChangeTransfer) - output1 := new(big.Int).SetBytes(result.SenderInitBalance.Bytes()) - output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes()) - - // Deprecating transfer log and will be removed in future fork. PLEASE DO NOT USE this transfer log going forward. Parameters won't get updated as expected going forward with EIP1559 - // add transfer log - core.AddFeeTransferLog( - statedb, - - msg.From, - blockCtx.Coinbase, - - result.FeeTipped, - result.SenderInitBalance, - coinbaseBalance, - output1.Sub(output1, result.FeeTipped), - output2.Add(output2, result.FeeTipped), - ) - - // Finalize the state so any modifications are written to the trie - // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number())) - statedb.FlushMVWriteSet() - - structRead := statedb.GetReadMapDump() - structWrite := statedb.GetWriteMapDump() - - RWstruct = append(RWstruct, structRead...) - RWstruct = append(RWstruct, structWrite...) - } - } - - if ioflag { - for _, val := range RWstruct { - IOdump += fmt.Sprintf("%v , %v, %v , %v, ", val.TxIdx, val.TxInc, val.VerIdx, val.VerInc) + hex.EncodeToString(val.Path) + ", " + val.Op - } - - // make sure that the file exists and write IOdump - err = os.WriteFile(filepath.Join(path, "data.csv"), []byte(fmt.Sprint(IOdump)), 0600) - if err != nil { - return nil, err - } - } - - close(jobs) - pend.Wait() - - // If execution failed in between, abort - if failed != nil { - return nil, failed - } - - // Include state sync tx if canonical (post-Madhugiri) or BorTraceEnabled (pre-Madhugiri). - isMadhugiri := api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(block.Number()) - includeStateSyncTx := isMadhugiri || *config.BorTraceEnabled - if stateSyncPresent && !includeStateSyncTx { - return results[:len(results)-1], nil - } - - return results, nil -} - // standardTraceBlockToFile configures a new tracer which uses standard JSON output, // and traces either a full block or an individual transaction. The return value will // be one filename per transaction traced. @@ -1302,6 +957,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute the transaction and flush any traces to disk statedb.SetTxContext(tx.Hash(), i) // Handle differently for state sync transactions + var vmResult *core.ExecutionResult if tx.Type() == types.StateSyncTxType { // Set tx context so that opcodes like GASPRICE don't panic. evm.SetTxContext(core.NewEVMTxContext(msg)) @@ -1309,12 +965,19 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), tx, params.BorSystemAddress) } - _, err = statefull.ApplyBorMessage(evm, callmsg) + vmResult, err = statefull.ApplyBorMessage(evm, callmsg) } else { if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) } - _, err = core.ApplyMessage(evm, msg, nil) + vmResult, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) + } + if tracer.OnTxEnd != nil { + var receipt *types.Receipt + if vmResult != nil { + receipt = &types.Receipt{GasUsed: vmResult.UsedGas} + } + tracer.OnTxEnd(receipt, err) } if writer != nil { _ = writer.Flush() diff --git a/eth/tracers/api_bor.go b/eth/tracers/api_bor.go deleted file mode 100644 index d7542f9831..0000000000 --- a/eth/tracers/api_bor.go +++ /dev/null @@ -1,160 +0,0 @@ -package tracers - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/consensus/bor/statefull" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/eth/tracers/logger" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" -) - -type BlockTraceResult struct { - // Trace of each transaction executed - Transactions []*TxTraceResult `json:"transactions,omitempty"` - - // Block that we are executing on the trace - Block interface{} `json:"block"` -} - -type TxTraceResult struct { - // Trace results produced by the tracer - Result interface{} `json:"result,omitempty"` - - // Trace failure produced by the tracer - Error string `json:"error,omitempty"` - - // IntermediateHash of the execution if succeeds - IntermediateHash common.Hash `json:"intermediatehash"` -} - -func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *TraceConfig) (*BlockTraceResult, error) { - if block.NumberU64() == 0 { - return nil, fmt.Errorf("genesis is not traceable") - } - - res := &BlockTraceResult{ - Block: block, - } - - // block object cannot be converted to JSON since much of the fields are non-public - blockFields := ethapi.RPCMarshalBlock(block, true, true, api.backend.ChainConfig(), api.backend.ChainDb()) - - res.Block = blockFields - - parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) - if err != nil { - return nil, err - } - - reexec := defaultTraceReexec - if config != nil && config.Reexec != nil { - reexec = *config.Reexec - } - - // TODO: discuss consequences of setting preferDisk false. - statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) - if err != nil { - return nil, err - } - - defer release() - - // Execute all the transaction contained within the block concurrently - var ( - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) - txs, stateSyncPresent, stateSyncHash = api.getAllBlockTransactions(ctx, block) - deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number()) - ) - - blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) - - traceTxn := func(indx int, tx *types.Transaction, borTx bool, stateSyncHash common.Hash) *TxTraceResult { - message, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) - txHash := tx.Hash() - if borTx { - txHash = stateSyncHash - } - - tracer := logger.NewStructLogger(config.Config) - - // Run the transaction with tracing enabled. - vmenv := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}) - - // Call Prepare to clear out the statedb access list - // Not sure if we need to do this - statedb.SetTxContext(txHash, indx) - - var execRes *core.ExecutionResult - - if borTx { - callmsg := prepareCallMessage(*message) - execRes, err = statefull.ApplyBorMessage(vmenv, callmsg) - } else { - execRes, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit)) - } - - if err != nil { - return &TxTraceResult{ - Error: err.Error(), - } - } - - result := &logger.ExecutionResult{ - Gas: execRes.UsedGas, - Failed: execRes.Failed(), - ReturnValue: execRes.Return(), - StructLogs: tracer.StructLogs(), - } - res := &TxTraceResult{ - Result: result, - IntermediateHash: statedb.IntermediateRoot(deleteEmptyObjects), - } - - return res - } - - for indx, tx := range txs { - if stateSyncPresent && indx == len(txs)-1 { - res.Transactions = append(res.Transactions, traceTxn(indx, tx, true, stateSyncHash)) - } else { - res.Transactions = append(res.Transactions, traceTxn(indx, tx, false, stateSyncHash)) - } - } - - return res, nil -} - -type TraceBlockRequest struct { - Number int64 - Hash string - IsBadBlock bool - Config *TraceConfig -} - -// If you use context as first parameter this function gets exposed automatically on rpc endpoint -func (api *API) TraceBorBlock(req *TraceBlockRequest) (*BlockTraceResult, error) { - ctx := context.Background() - - var blockNumber rpc.BlockNumber - if req.Number == -1 { - blockNumber = rpc.LatestBlockNumber - } else { - blockNumber = rpc.BlockNumber(req.Number) - } - - log.Debug("Tracing Bor Block", "block number", blockNumber) - - block, err := api.blockByNumber(ctx, blockNumber) - if err != nil { - return nil, err - } - - return api.traceBorBlock(ctx, block, req.Config) -} diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 21060124d8..7fdc271ed5 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -712,94 +712,6 @@ type txTraceResultTest struct { Error string `json:"error,omitempty"` // Trace failure produced by the tracer } -func TestIOdump(t *testing.T) { - t.Parallel() - - // Initialize test accounts - accounts := newAccounts(5) - genesis := &core.Genesis{Alloc: types.GenesisAlloc{ - accounts[0].addr: {Balance: big.NewInt(params.Ether)}, - accounts[1].addr: {Balance: big.NewInt(params.Ether)}, - accounts[2].addr: {Balance: big.NewInt(params.Ether)}, - accounts[3].addr: {Balance: big.NewInt(params.Ether)}, - accounts[4].addr: {Balance: big.NewInt(params.Ether)}, - }} - genBlocks := 1 - signer := types.HomesteadSigner{} - api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { - // Transfer from account[0] to account[1], account[1] to account[2], account[2] to account[3], account[3] to account[4], account[4] to account[0] - // value: 1000 wei - // fee: 0 wei - for j := 0; j < 5; j++ { - tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[(j+1)%5].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[j].key) - b.AddTx(tx) - } - })) - - allowIOTracing = true - - ioflag := new(bool) - - *ioflag = true - - var testSuite = []struct { - blockNumber rpc.BlockNumber - config *TraceConfig - want string - expectErr error - }{ - // Trace head block - { - config: &TraceConfig{ - IOFlag: ioflag, - }, - blockNumber: rpc.BlockNumber(genBlocks), - want: `[{"result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}},{"result":{"gas":21000,"failed":false,"returnValue":"0x","structLogs":[]}}]`, - }, - } - - for i, tc := range testSuite { - result, err := api.TraceBlockByNumber(t.Context(), tc.blockNumber, tc.config) - if tc.expectErr != nil { - if err == nil { - t.Errorf("test %d, want error %v", i, tc.expectErr) - continue - } - - if !reflect.DeepEqual(err, tc.expectErr) { - t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err) - } - - continue - } - - // Done As txTraceResult struct was changed during Cancun changes - resArr := make([]*txTraceResultTest, 0) - for _, res := range result { - res := &txTraceResultTest{ - Result: res.Result, - Error: res.Error, - } - resArr = append(resArr, res) - } - - if err != nil { - t.Errorf("test %d, want no error, have %v", i, err) - continue - } - - have, err := json.Marshal(resArr) - if err != nil { - t.Errorf("Error in Marshal: %v", err) - } - - want := tc.want - if string(have) != want { - t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want) - } - } -} - // nolint:typecheck func TestTracingWithOverrides(t *testing.T) { t.Parallel() diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 0a81053713..8b04ca1e13 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -64,9 +64,6 @@ type Server struct { tracer *sdktrace.TracerProvider config *Config - // tracerAPI to trace block executions - tracerAPI *tracers.API - // Bor health service. healthService *health.Health } @@ -247,7 +244,6 @@ func NewServer(config *Config, opts ...serverOption) (*Server, error) { // debug tracing is enabled by default stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend)) - srv.tracerAPI = tracers.NewAPI(srv.backend.APIBackend) // graphql is started from another place if config.JsonRPC.Graphql.Enabled { diff --git a/internal/cli/server/service.go b/internal/cli/server/service.go index a63736e5da..247999fc5c 100644 --- a/internal/cli/server/service.go +++ b/internal/cli/server/service.go @@ -2,7 +2,6 @@ package server import ( "context" - "encoding/json" "errors" "fmt" "math/big" @@ -14,8 +13,6 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/tracers" - "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/internal/cli/server/pprof" "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/ethereum/go-ethereum/p2p" @@ -229,31 +226,7 @@ func headerToProtoHeader(h *types.Header) *proto.Header { } func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_DebugBlockServer) error { - traceReq := &tracers.TraceBlockRequest{ - Number: req.Number, - Config: &tracers.TraceConfig{ - Config: &logger.Config{ - EnableMemory: true, - }, - }, - } - - res, err := s.tracerAPI.TraceBorBlock(traceReq) - if err != nil { - return err - } - - // this is memory heavy - data, err := json.Marshal(res) - if err != nil { - return err - } - - if err := sendStreamDebugFile(stream, map[string]string{}, data); err != nil { - return err - } - - return nil + return errors.New("debug block via gRPC is not supported, use debug_traceBlockByNumber RPC instead") } var bigIntT = reflect.TypeOf(new(big.Int)).Kind() From 711f50045d889bee75f2b981354d47967cf8cb0d Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Thu, 19 Mar 2026 12:32:53 +0530 Subject: [PATCH 27/30] core/types: add tx.GetStateSyncData for state-sync txs --- core/types/transaction.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/types/transaction.go b/core/types/transaction.go index 07cdc5040c..3c198205b5 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -636,6 +636,15 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e return &Transaction{inner: cpy, time: tx.time}, nil } +// GetStateSyncData returns the underlying bridge event data used for state-sync +// transactions. +func (tx *Transaction) GetStateSyncData() []*StateSyncData { + if tx.Type() != StateSyncTxType { + return nil + } + return tx.inner.(*StateSyncTx).StateSyncData +} + // Transactions implements DerivableList for transactions. type Transactions []*Transaction From ec342cdf0c1f9325d4caeb5dfefb13472ee11e6a Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Thu, 19 Mar 2026 13:05:47 +0530 Subject: [PATCH 28/30] correct tracing of state-syncs --- consensus/bor/abi/common.go | 31 +++++++++++++ consensus/bor/contract/client.go | 31 ++----------- consensus/bor/heimdall/span/spanner.go | 12 ++--- consensus/bor/statefull/processor.go | 64 ++++++++++++++++++++++++++ eth/ethconfig/config.go | 3 +- eth/tracers/api.go | 30 ++++-------- 6 files changed, 116 insertions(+), 55 deletions(-) create mode 100644 consensus/bor/abi/common.go diff --git a/consensus/bor/abi/common.go b/consensus/bor/abi/common.go new file mode 100644 index 0000000000..60d82b3b7e --- /dev/null +++ b/consensus/bor/abi/common.go @@ -0,0 +1,31 @@ +package abi + +import ( + "math" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// SystemTxGas is gas limit for system txs/calls (which happen within consensus) +// and should not be limited to the local rpc gas cap or tx gas cap. +var SystemTxGas = (hexutil.Uint64)(math.MaxUint64 / 2) + +var ( + vABI, _ = abi.JSON(strings.NewReader(validatorsetABI)) + sABI, _ = abi.JSON(strings.NewReader(stateReceiverABI)) +) + +func ValidatorSet() abi.ABI { + return vABI +} + +func StateReceiver() abi.ABI { + return sABI +} + +const ( + validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` + stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` +) diff --git a/consensus/bor/contract/client.go b/consensus/bor/contract/client.go index c3f87f141c..ab57a7ad15 100644 --- a/consensus/bor/contract/client.go +++ b/consensus/bor/contract/client.go @@ -2,13 +2,12 @@ package contract import ( "context" - "math" "math/big" - "strings" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + borabi "github.com/ethereum/go-ethereum/consensus/bor/abi" "github.com/ethereum/go-ethereum/consensus/bor/api" "github.com/ethereum/go-ethereum/consensus/bor/clerk" "github.com/ethereum/go-ethereum/consensus/bor/statefull" @@ -22,23 +21,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) -// SystemTxGas is gas limit for system txs/calls (which happen within consensus) -// and should not be limited to the local rpc gas cap or tx gas cap. -var SystemTxGas = (hexutil.Uint64)(math.MaxUint64 / 2) - -var ( - vABI, _ = abi.JSON(strings.NewReader(validatorsetABI)) - sABI, _ = abi.JSON(strings.NewReader(stateReceiverABI)) -) - -func ValidatorSet() abi.ABI { - return vABI -} - -func StateReceiver() abi.ABI { - return sABI -} - type GenesisContractsClient struct { validatorSetABI abi.ABI stateReceiverABI abi.ABI @@ -48,11 +30,6 @@ type GenesisContractsClient struct { ethAPI api.Caller } -const ( - validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` - stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` -) - func NewGenesisContractsClient( chainConfig *params.ChainConfig, validatorContract, @@ -60,8 +37,8 @@ func NewGenesisContractsClient( ethAPI api.Caller, ) *GenesisContractsClient { return &GenesisContractsClient{ - validatorSetABI: ValidatorSet(), - stateReceiverABI: StateReceiver(), + validatorSetABI: borabi.ValidatorSet(), + stateReceiverABI: borabi.StateReceiver(), ValidatorContract: validatorContract, StateReceiverContract: stateReceiverContract, chainConfig: chainConfig, @@ -127,7 +104,7 @@ func (gc *GenesisContractsClient) LastStateId(state *state.StateDB, number uint6 // BOR: Do a 'CallWithState' so that we can fetch the last state ID from a given (incoming) // state instead of local(canonical) chain's state. result, err := gc.ethAPI.CallWithState(context.Background(), ethapi.TransactionArgs{ - Gas: &SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &msgData, }, &rpc.BlockNumberOrHash{BlockNumber: &blockNr, BlockHash: &hash}, state, nil, nil) diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go index 8569765b97..ae1feb6e8a 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/consensus/bor/heimdall/span/spanner.go @@ -11,8 +11,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/bor/abi" + borabi "github.com/ethereum/go-ethereum/consensus/bor/abi" "github.com/ethereum/go-ethereum/consensus/bor/api" - "github.com/ethereum/go-ethereum/consensus/bor/contract" "github.com/ethereum/go-ethereum/consensus/bor/statefull" "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/core" @@ -70,7 +70,7 @@ func (c *ChainSpanner) GetCurrentSpan(ctx context.Context, headerHash common.Has toAddress := c.validatorContractAddress result, err := c.ethAPI.CallWithState(ctx, ethapi.TransactionArgs{ - Gas: &contract.SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &msgData, }, &blockNr, state, nil, nil) @@ -169,7 +169,7 @@ func (c *ChainSpanner) getSpanByBlock(ctx context.Context, blockNrOrHash rpc.Blo spanMsgData := (hexutil.Bytes)(spanData) spanResult, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &contract.SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &spanMsgData, }, &blockNrOrHash, nil, nil) @@ -195,7 +195,7 @@ func (c *ChainSpanner) getProducersBySpanAndIndexMethod(ctx context.Context, blo producerMsgData := (hexutil.Bytes)(producerData) result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &contract.SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &producerMsgData, }, &blockNrOrHash, nil, nil) @@ -221,7 +221,7 @@ func (c *ChainSpanner) getFirstEndBlock(ctx context.Context, blockNrOrHash rpc.B firstEndBlockMsgData := (hexutil.Bytes)(firstEndBlockData) firstEndBlockResult, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &contract.SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &firstEndBlockMsgData, }, &blockNrOrHash, nil, nil) @@ -250,7 +250,7 @@ func (c *ChainSpanner) getBorValidatorsWithoutId(ctx context.Context, blockNrOrH msgData := (hexutil.Bytes)(data) result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{ - Gas: &contract.SystemTxGas, + Gas: &borabi.SystemTxGas, To: &toAddress, Data: &msgData, }, &blockNrOrHash, nil, nil) diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go index c731860846..d5898e0d8b 100644 --- a/consensus/bor/statefull/processor.go +++ b/consensus/bor/statefull/processor.go @@ -3,18 +3,23 @@ package statefull import ( "bytes" "context" + "fmt" "math/big" + "time" "github.com/holiman/uint256" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor/abi" + "github.com/ethereum/go-ethereum/consensus/bor/clerk" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rlp" ) type ChainContext struct { @@ -156,3 +161,62 @@ func ApplyBorMessage(vmenv *vm.EVM, msg Callmsg) (*core.ExecutionResult, error) ReturnData: ret, }, nil } + +// ApplyStateSyncEvents replays all state-sync events from a StateSyncTx against the EVM. This +// method is generally used for tracing. It tries to mimic the exact things which happen when +// a state-sync is processed in a live network (via CommitState). +func ApplyStateSyncEvents(vmenv *vm.EVM, tx *types.Transaction, message *core.Message, stateReceiverContract common.Address) (*core.ExecutionResult, error) { + events := tx.GetStateSyncData() + if len(events) == 0 { + return &core.ExecutionResult{UsedGas: 0, ReturnData: nil}, nil + } + + // Set tx context so that opcodes like GASPRICE don't panic. + vmenv.SetTxContext(core.NewEVMTxContext(message)) + + stateReceiverABI := abi.StateReceiver() + var totalGasUsed uint64 + + const method = "commitState" + now := time.Now().Unix() + + for _, event := range events { + // Convert StateSyncData to EventRecord (matching CommitState's BuildEventRecord) + record := &clerk.EventRecord{ + ID: event.ID, + Contract: event.Contract, + Data: event.Data, + TxHash: event.TxHash, + // Dummy fields, not really needed for execution but required for encoding + LogIndex: 0, + ChainID: "", + } + + recordBytes, err := rlp.EncodeToBytes(record) + if err != nil { + return nil, fmt.Errorf("failed to RLP encode state-sync event %d: %w", event.ID, err) + } + + // ABI-pack commitState(uint256 syncTime, bytes recordBytes) + data, err := stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(now), recordBytes) + if err != nil { + return nil, fmt.Errorf("failed to ABI pack commitState for event %d: %w", event.ID, err) + } + + // Build system message with proper gas and target contract + msg := GetSystemMessage(stateReceiverContract, data) + + // Execute + result, err := ApplyBorMessage(vmenv, msg) + if err != nil { + return nil, fmt.Errorf("state-sync event %d execution failed: %w", event.ID, err) + } + + totalGasUsed += result.UsedGas + } + + return &core.ExecutionResult{ + UsedGas: totalGasUsed, + Err: nil, + }, nil +} diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 4447437e60..ec8cd16807 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -27,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/bor" + borabi "github.com/ethereum/go-ethereum/consensus/bor/abi" "github.com/ethereum/go-ethereum/consensus/bor/contract" "github.com/ethereum/go-ethereum/consensus/bor/heimdall" //nolint:typecheck "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" @@ -339,7 +340,7 @@ func CreateConsensusEngine(chainConfig *params.ChainConfig, ethConfig *Config, d // In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config // Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present. genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, chainConfig.Bor.ValidatorContract, chainConfig.Bor.StateReceiverContract, blockchainAPI) - spanner := span.NewChainSpanner(blockchainAPI, contract.ValidatorSet(), chainConfig, common.HexToAddress(chainConfig.Bor.ValidatorContract)) + spanner := span.NewChainSpanner(blockchainAPI, borabi.ValidatorSet(), chainConfig, common.HexToAddress(chainConfig.Bor.ValidatorContract)) log.Info("Creating consensus engine", "withoutHeimdall", ethConfig.WithoutHeimdall) log.Info("Using custom miner block time", "blockTime", ethConfig.Miner.BlockTime) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 4f26ecdbcc..f189b6655e 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -615,12 +615,10 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) statedb.SetTxContext(tx.Hash(), i) var err error - // State sync transactions are processed differently than normal transactions if tx.Type() == types.StateSyncTxType { - // Set tx context so that opcodes like GASPRICE don't panic. - evm.SetTxContext(core.NewEVMTxContext(msg)) - callmsg := prepareCallMessage(*msg) - _, err = statefull.ApplyBorMessage(evm, callmsg) + // State sync transactions are processed differently than normal transactions + stateReceiverAddress := api.backend.ChainConfig().Bor.StateReceiverContract + _, err = statefull.ApplyStateSyncEvents(evm, tx, msg, common.HexToAddress(stateReceiverAddress)) } else { _, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) } @@ -918,10 +916,8 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Process the tx to update state, but don't trace it. var err error if tx.Type() == types.StateSyncTxType { - // Set tx context so that opcodes like GASPRICE don't panic. - evm.SetTxContext(core.NewEVMTxContext(msg)) - callmsg := prepareCallMessage(*msg) - _, err = statefull.ApplyBorMessage(evm, callmsg) + stateReceiverAddress := api.backend.ChainConfig().Bor.StateReceiverContract + _, err = statefull.ApplyStateSyncEvents(evm, tx, msg, common.HexToAddress(stateReceiverAddress)) } else { _, err = core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)) } @@ -959,13 +955,11 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Handle differently for state sync transactions var vmResult *core.ExecutionResult if tx.Type() == types.StateSyncTxType { - // Set tx context so that opcodes like GASPRICE don't panic. - evm.SetTxContext(core.NewEVMTxContext(msg)) - callmsg := prepareCallMessage(*msg) if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), tx, params.BorSystemAddress) } - vmResult, err = statefull.ApplyBorMessage(evm, callmsg) + stateReceiverAddress := api.backend.ChainConfig().Bor.StateReceiverContract + vmResult, err = statefull.ApplyStateSyncEvents(evm, tx, msg, common.HexToAddress(stateReceiverAddress)) } else { if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) @@ -1224,18 +1218,12 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor // Handle state-sync transactions separately. They're part of block body post Madhugiri so we can replay them // and gather traces. if tx.Type() == types.StateSyncTxType && api.backend.ChainConfig().Bor != nil && api.backend.ChainConfig().Bor.IsMadhugiri(txctx.BlockNumber) { - // We need to do some additional work as ApplyBorMessage directly applies message skipping some steps - // needed for tracing. - - // Set tx context so that opcodes like GASPRICE don't panic. - evm.SetTxContext(core.NewEVMTxContext(message)) - // Call `OnTxStart` and `OnTxEnd` hooks before and after applying message. - callmsg := prepareCallMessage(*message) if tracer.Hooks.OnTxStart != nil { tracer.Hooks.OnTxStart(evm.GetVMContext(), tx, params.BorSystemAddress) } - res, err := statefull.ApplyBorMessage(evm, callmsg) + stateReceiverAddress := api.backend.ChainConfig().Bor.StateReceiverContract + res, err := statefull.ApplyStateSyncEvents(evm, tx, message, common.HexToAddress(stateReceiverAddress)) if err != nil { if tracer.Hooks.OnTxEnd != nil { tracer.Hooks.OnTxEnd(nil, err) From 31e41da48f8c3e8e6d85dc3a114846c6677422d9 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 27 Mar 2026 22:17:24 +0530 Subject: [PATCH 29/30] eth/tracers: add state-sync tracing tests --- eth/tracers/api_statesync_test.go | 907 ++++++++---------------------- 1 file changed, 224 insertions(+), 683 deletions(-) diff --git a/eth/tracers/api_statesync_test.go b/eth/tracers/api_statesync_test.go index 4eac709a34..2a969fadfc 100644 --- a/eth/tracers/api_statesync_test.go +++ b/eth/tracers/api_statesync_test.go @@ -2,11 +2,13 @@ package tracers import ( "context" + "encoding/json" "math/big" "testing" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" @@ -14,6 +16,25 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +var ( + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + + // State receiver address from BorConfig — must match what the tracer reads + stateReceiverAddr = common.HexToAddress("0x0000000000000000000000000000000000001001") + + // Target contract that the state receiver forwards calls to. + // Bytecode: PUSH1(0) PUSH1(0) LOG0 STOP — emits an empty LOG0 on any call. + targetAddr = common.HexToAddress("0x0000000000000000000000000000000000002000") + targetCode = []byte{0x60, 0x00, 0x60, 0x00, 0xa0, 0x00} + + // Production StateReceiver bytecode — leave empty for now, will be populated. + // This contract has full RLP decoding, sequential stateId validation, + // and forwards calls via: call(txGas, receiver, 0, add(data, 0x20), mload(data), 0, 0) + stateReceiverCode = common.FromHex("0x608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a7231582083fbdacb76f32b4112d0f7db9a596937925824798a0026ba0232322390b5263764736f6c634300050b0032") // TODO: replace with production bytecode ) // borTestBackend extends testBackend with Bor-specific configuration for testing @@ -67,7 +88,7 @@ func (b *borTestBackend) BlockByHash(ctx context.Context, hash common.Hash) (*ty } // newBorChainConfig creates a chain config suitable for Bor state sync testing. -func newBorChainConfig(madhugiriBlock *big.Int) *params.ChainConfig { +func newBorChainConfig() *params.ChainConfig { return ¶ms.ChainConfig{ ChainID: big.NewInt(137), HomesteadBlock: big.NewInt(0), @@ -90,61 +111,8 @@ func newBorChainConfig(madhugiriBlock *big.Int) *params.ChainConfig { AhmedabadBlock: big.NewInt(0), BhilaiBlock: big.NewInt(0), RioBlock: big.NewInt(0), - MadhugiriBlock: madhugiriBlock, - MadhugiriProBlock: madhugiriBlock, - DandeliBlock: big.NewInt(0), - Period: map[string]uint64{ - "0": 2, - }, - ProducerDelay: map[string]uint64{ - "0": 2, - }, - Sprint: map[string]uint64{ - "0": 16, - }, - BackupMultiplier: map[string]uint64{ - "0": 2, - }, - ValidatorContract: "0x0000000000000000000000000000000000001000", - StateReceiverContract: "0x0000000000000000000000000000000000001001", - BurntContract: map[string]string{ - "0": "0x000000000000000000000000000000000000dead", - }, - Coinbase: map[string]string{ - "0": "0x0000000000000000000000000000000000000000", - }, - }, - } -} - -// newBorChainConfigForInsertion creates a chain config with Bor settings but without Madhugiri -// for block insertion. This allows transaction execution (which needs BorConfig for burnt contract) -// while avoiding state-sync validation during insertion. -func newBorChainConfigForInsertion() *params.ChainConfig { - return ¶ms.ChainConfig{ - ChainID: big.NewInt(137), - HomesteadBlock: big.NewInt(0), - DAOForkBlock: big.NewInt(0), - DAOForkSupport: true, - EIP150Block: big.NewInt(0), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - BerlinBlock: big.NewInt(0), - LondonBlock: big.NewInt(0), - Bor: ¶ms.BorConfig{ - JaipurBlock: big.NewInt(0), - DelhiBlock: big.NewInt(0), - IndoreBlock: big.NewInt(0), - AhmedabadBlock: big.NewInt(0), - BhilaiBlock: big.NewInt(0), - RioBlock: big.NewInt(0), - MadhugiriBlock: nil, // No Madhugiri - disables state-sync validation - MadhugiriProBlock: nil, + MadhugiriBlock: big.NewInt(0), + MadhugiriProBlock: big.NewInt(0), DandeliBlock: big.NewInt(0), Period: map[string]uint64{ "0": 2, @@ -174,15 +142,14 @@ func newBorChainConfigForInsertion() *params.ChainConfig { // 1. Inserts blocks without Bor validation (to avoid state-sync processing issues) // 2. Exposes a Bor chain config to the tracer API (to test Madhugiri logic) // 3. Allows manual injection of state-sync txs into block bodies after insertion -func newBorTestBackend(t *testing.T, n int, gspec *core.Genesis, madhugiriBlock *big.Int, generator func(i int, b *core.BlockGen)) *borTestBackend { - // Use config without Bor for block insertion - insertionConfig := newBorChainConfigForInsertion() - gspec.Config = insertionConfig +func newBorTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *borTestBackend { + borCfg := newBorChainConfig() + gspec.Config = borCfg backend := &borTestBackend{ testBackend: testBackend{ // Use Bor config for API queries (this is what the tracer API sees) - chainConfig: newBorChainConfig(madhugiriBlock), + chainConfig: borCfg, engine: ethash.NewFaker(), chaindb: rawdb.NewMemoryDatabase(), }, @@ -261,119 +228,20 @@ func createStateSyncTx(id uint64) *types.Transaction { }) } -// TestTraceBlockStateSyncPostMadhugiri verifies that post-Madhugiri blocks -// include state sync transactions in trace results regardless of BorTraceEnabled. -// This is the core fix for the tx count mismatch bug (PIP-74). -func TestTraceBlockStateSyncPostMadhugiri(t *testing.T) { - t.Parallel() +// newStateSyncTestSetup creates a common test setup for state-sync tracing tests. +// It returns the backend, api, stateSyncTx, and the block number where the state-sync tx was injected. +func newStateSyncTestSetup(t *testing.T, n int) (*borTestBackend, *API, uint64) { + t.Helper() - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - // Madhugiri at block 5 - test block 10 which is post-fork - madhugiriBlock := big.NewInt(5) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) - defer backend.chain.Stop() - - // Inject state-sync tx into post-Madhugiri blocks (block 6+) - for i := uint64(6); i <= 10; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } + gspec := &core.Genesis{ + Alloc: types.GenesisAlloc{ + address: {Balance: big.NewInt(params.Ether)}, + stateReceiverAddr: {Code: stateReceiverCode, Balance: big.NewInt(0)}, + targetAddr: {Code: targetCode, Balance: big.NewInt(0)}, + }, } - api := NewAPI(backend) - - // Test post-Madhugiri block (block 10) with BorTraceEnabled=false (default) - t.Run("PostMadhugiri_BorTraceDisabled", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(10)) - if block == nil { - t.Fatal("block 10 not found") - } - - expectedTxCount := len(block.Transactions()) - if expectedTxCount != 2 { - t.Fatalf("expected 2 txs in block (1 regular + 1 state sync), got %d", expectedTxCount) - } - - // Verify last tx is state sync - lastTx := block.Transactions()[expectedTxCount-1] - if lastTx.Type() != types.StateSyncTxType { - t.Fatalf("expected last tx to be StateSyncTxType, got %d", lastTx.Type()) - } - - // Trace with default config (BorTraceEnabled=false) - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(10), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Post-Madhugiri: trace count MUST match block tx count - if len(results) != expectedTxCount { - t.Errorf("tx count mismatch: block has %d txs, trace returned %d results (expected match post-Madhugiri)", - expectedTxCount, len(results)) - } - }) - - // Test post-Madhugiri block with BorTraceEnabled=true - t.Run("PostMadhugiri_BorTraceEnabled", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(10)) - expectedTxCount := len(block.Transactions()) - - borTraceEnabled := true - config := &TraceConfig{BorTraceEnabled: &borTraceEnabled} - - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(10), config) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - if len(results) != expectedTxCount { - t.Errorf("tx count mismatch with BorTraceEnabled=true: block has %d txs, trace returned %d results", - expectedTxCount, len(results)) - } - }) -} - -// TestTraceBlockStateSyncPreMadhugiri verifies legacy behavior is preserved -// for pre-Madhugiri blocks where state sync was not canonical. -func TestTraceBlockStateSyncPreMadhugiri(t *testing.T) { - t.Parallel() - - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - // Madhugiri at block 100 - all test blocks are pre-fork - madhugiriBlock := big.NewInt(100) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { + backend := newBorTestBackend(t, n, gspec, func(i int, b *core.BlockGen) { tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ Nonce: uint64(i), To: &address, @@ -383,568 +251,241 @@ func TestTraceBlockStateSyncPreMadhugiri(t *testing.T) { }), b.Signer(), key) b.AddTx(tx) }) - defer backend.chain.Stop() - - api := NewAPI(backend) - - // Pre-Madhugiri block without state sync tx in body - t.Run("PreMadhugiri_NoStateSyncInBody", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(5)) - if block == nil { - t.Fatal("block 5 not found") - } - - blockTxCount := len(block.Transactions()) - if blockTxCount != 1 { - t.Fatalf("expected 1 tx in pre-Madhugiri block, got %d", blockTxCount) - } - - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(5), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Pre-Madhugiri without state sync: trace count should match block body - if len(results) != blockTxCount { - t.Errorf("expected %d trace results, got %d", blockTxCount, len(results)) - } - }) -} -// TestTraceBlockMadhugiriForkBoundary tests edge cases at the exact fork boundary. -func TestTraceBlockMadhugiriForkBoundary(t *testing.T) { - t.Parallel() - - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, + stateSyncTx := types.NewTx(&types.StateSyncTx{ + StateSyncData: []*types.StateSyncData{ + { + ID: 1, + Contract: targetAddr, + Data: []byte("event-one"), + TxHash: common.HexToHash("0xaaa1"), }, - } - ) - - // Madhugiri at block 5 - madhugiriBlock := big.NewInt(5) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) + { + ID: 2, + Contract: targetAddr, + Data: []byte("event-two"), + TxHash: common.HexToHash("0xaaa2"), + }, + }, }) - defer backend.chain.Stop() - // Inject state-sync tx starting at Madhugiri block (block 5+) - for i := uint64(5); i <= 10; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } - } + stateSyncBlock := uint64(2) + err := backend.injectStateSyncTx(stateSyncBlock, stateSyncTx) + require.NoError(t, err, "failed to inject state-sync tx") api := NewAPI(backend) - - // Test block just before Madhugiri (block 4) - t.Run("BlockBeforeFork", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(4)) - if block == nil { - t.Fatal("block 4 not found") - } - - blockTxCount := len(block.Transactions()) - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(4), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Block 4 is pre-Madhugiri, no state sync in body - if len(results) != blockTxCount { - t.Errorf("block 4 (pre-fork): expected %d results, got %d", blockTxCount, len(results)) - } - }) - - // Test exact Madhugiri fork block (block 5) - t.Run("ExactForkBlock", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(5)) - if block == nil { - t.Fatal("block 5 not found") - } - - blockTxCount := len(block.Transactions()) - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(5), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Block 5 is Madhugiri block - state sync should be included - if len(results) != blockTxCount { - t.Errorf("block 5 (fork block): expected %d results, got %d", blockTxCount, len(results)) - } - }) - - // Test block just after Madhugiri (block 6) - t.Run("BlockAfterFork", func(t *testing.T) { - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(6)) - if block == nil { - t.Fatal("block 6 not found") - } - - blockTxCount := len(block.Transactions()) - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(6), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Block 6 is post-Madhugiri - state sync should be included - if len(results) != blockTxCount { - t.Errorf("block 6 (post-fork): expected %d results, got %d", blockTxCount, len(results)) - } - }) + return backend, api, stateSyncBlock } -// TestTraceBlockByHashStateSyncPostMadhugiri tests TraceBlockByHash endpoint. -func TestTraceBlockByHashStateSyncPostMadhugiri(t *testing.T) { +// TestTraceBlockByNumber_WithStateSyncTx tests end-to-end state-sync tracing using the actual +// StateReceiver contract bytecode and mirrors what happens in actual networks. During the test +// we do the following things: +// +// 1. Deploy StateReceiver at 0x1001 with mainnet bytecode (which has `stateReceive` method). +// 2. A simple "target" contract is deployed at a separate address — it just emits LOG0 on any call. +// 3. A StateSyncTx carries bridge events whose Contract field points to the target is injected. +// 4. During tracing, the bridge events are executed inside EVM which calls the StateReceiver +// contract, which further calls the target contract and generates expected trace. +// 5. We later verify if the trace is correctly generated or not. +func TestTraceBlockByNumber_WithStateSyncTx(t *testing.T) { t.Parallel() - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - madhugiriBlock := big.NewInt(5) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) + backend, api, stateSyncBlock := newStateSyncTestSetup(t, 3) defer backend.chain.Stop() - // Inject state-sync tx into post-Madhugiri blocks - for i := uint64(6); i <= 10; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } - } + // Ensure block body contains transactions + block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(stateSyncBlock)) + require.NotNil(t, block, "block %d not found", stateSyncBlock) + transactions := block.Transactions() + require.Equal(t, 2, len(transactions), "expected %d transactions in block body, got %d", 2, len(transactions)) - api := NewAPI(backend) + // Trace block by number + results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(stateSyncBlock), nil) + require.NoError(t, err, "TraceBlockByNumber failed: %v", err) + require.NotNil(t, results, "TraceBlockByNumber returned nil traces") - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(10)) - if block == nil { - t.Fatal("block 10 not found") + // Validate if the trace is correct or not + require.Equal(t, len(transactions), len(results), "expected %d trace results, got: %d", len(transactions), len(results)) + for i, result := range results { + require.Equal(t, "", result.Error, "expected nil error in trace result %d, got: %s", i, result.Error) + require.Equal(t, transactions[i].Hash(), result.TxHash, "trace result %d tx hash mismatch: got %s, want %s", i, result.TxHash.Hex(), transactions[i].Hash().Hex()) } - expectedTxCount := len(block.Transactions()) - - results, err := api.TraceBlockByHash(context.Background(), block.Hash(), nil) - if err != nil { - t.Fatalf("TraceBlockByHash failed: %v", err) - } - - if len(results) != expectedTxCount { - t.Errorf("TraceBlockByHash: tx count mismatch: block has %d txs, trace returned %d results", - expectedTxCount, len(results)) - } -} - -// TestTraceChainStateSyncPostMadhugiri tests traceChain across fork boundary. -func TestTraceChainStateSyncPostMadhugiri(t *testing.T) { - t.Parallel() - - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - madhugiriBlock := big.NewInt(5) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) - defer backend.chain.Stop() + // Validate the state-sync trace specifically + raw, ok := results[1].Result.(json.RawMessage) + require.True(t, ok, "expected json.RawMessage for state-sync trace result, got %T", results[1].Result) - // Inject state-sync tx into post-Madhugiri blocks - for i := uint64(5); i <= 10; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } + var execResult struct { + Gas uint64 `json:"gas"` + Failed bool `json:"failed"` + StructLogs []json.RawMessage `json:"structLogs"` + ReturnValue string `json:"returnValue"` } + err = json.Unmarshal(raw, &execResult) + require.NoError(t, err, "failed to unmarshal state-sync trace: %v", err) + require.Greater(t, len(execResult.StructLogs), 0, "state-sync trace has no struct logs — EVM code was not executed") - api := NewAPI(backend) - - // Use internal traceChain method (like existing tests do) - from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(4)) - to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(7)) - resCh := api.traceChain(from, to, nil, nil) - - // Verify trace count for each block - nextBlock := uint64(5) // traceChain starts from start+1 - for result := range resCh { - blockNum := uint64(result.Block) - if blockNum != nextBlock { - t.Errorf("unexpected block number: got %d, want %d", blockNum, nextBlock) + // The target contract emits LOG0 for each onStateReceive call. + // With 2 bridge events, we expect 2 LOG0 from the target contract. + var log0Count int + for _, entry := range execResult.StructLogs { + var op struct { + Op string `json:"op"` } - - // Get expected tx count from actual block - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(blockNum)) - if block == nil { - t.Errorf("block %d not found", blockNum) - nextBlock++ - continue + if err := json.Unmarshal(entry, &op); err == nil && op.Op == "LOG0" { + log0Count++ } - - expectedTxCount := len(block.Transactions()) - if len(result.Traces) != expectedTxCount { - t.Errorf("block %d: trace count mismatch: expected %d, got %d", - blockNum, expectedTxCount, len(result.Traces)) - } - - nextBlock++ - } - - // Verify we processed all expected blocks - if nextBlock != 8 { // Should have processed blocks 5, 6, 7 - t.Errorf("did not process all blocks: stopped at %d", nextBlock) } + require.Equal(t, 2, log0Count, "expected 2 LOG0 opcodes (one per bridge event forwarded to target), got %d", log0Count) + t.Logf("state-sync trace: %d struct logs, %d LOG0 opcodes, gas used: %d", len(execResult.StructLogs), log0Count, execResult.Gas) } -// TestIntermediateRootsStateSyncPostMadhugiri tests IntermediateRoots endpoint. -func TestIntermediateRootsStateSyncPostMadhugiri(t *testing.T) { +// TestTraceBlockByHash_WithStateSyncTx tests end-to-end state-sync tracing using the actual +// StateReceiver contract bytecode and mirrors what happens in actual networks. Follows same +// steps as trace by block. +func TestTraceBlockByHash_WithStateSyncTx(t *testing.T) { t.Parallel() - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - madhugiriBlock := big.NewInt(5) - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) + backend, api, stateSyncBlock := newStateSyncTestSetup(t, 3) defer backend.chain.Stop() - // Inject state-sync tx into post-Madhugiri blocks - for i := uint64(6); i <= 10; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } - } - - api := NewAPI(backend) - - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(10)) - if block == nil { - t.Fatal("block 10 not found") - } - - expectedTxCount := len(block.Transactions()) - - roots, err := api.IntermediateRoots(context.Background(), block.Hash(), nil) - if err != nil { - t.Fatalf("IntermediateRoots failed: %v", err) - } - - // Each tx should produce an intermediate root - if len(roots) != expectedTxCount { - t.Errorf("IntermediateRoots: expected %d roots (one per tx), got %d", - expectedTxCount, len(roots)) - } -} - -// TestStateSyncTxTypeDetection verifies correct detection of state sync tx type. -func TestStateSyncTxTypeDetection(t *testing.T) { - t.Parallel() - - stateSyncTx := createStateSyncTx(1) - - if stateSyncTx.Type() != types.StateSyncTxType { - t.Errorf("expected tx type %d (StateSyncTxType), got %d", - types.StateSyncTxType, stateSyncTx.Type()) - } - - // Verify properties of state sync tx - if stateSyncTx.Gas() != 0 { - t.Errorf("state sync tx should have 0 gas, got %d", stateSyncTx.Gas()) - } - if stateSyncTx.GasPrice().Cmp(big.NewInt(0)) != 0 { - t.Errorf("state sync tx should have 0 gas price") - } - if stateSyncTx.Value().Cmp(big.NewInt(0)) != 0 { - t.Errorf("state sync tx should have 0 value") - } -} - -// TestNoMadhugiriFork tests behavior when Madhugiri fork is not configured. -func TestNoMadhugiriFork(t *testing.T) { - t.Parallel() - - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - // nil = no Madhugiri fork - genBlocks := 10 - - backend := newBorTestBackend(t, genBlocks, gspec, nil, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) - defer backend.chain.Stop() + // Ensure block body contains transactions + block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(stateSyncBlock)) + require.NotNil(t, block, "block %d not found", stateSyncBlock) + transactions := block.Transactions() + require.Equal(t, 2, len(transactions), "expected %d transactions in block body, got %d", 2, len(transactions)) - api := NewAPI(backend) + // Trace block by hash + results, err := api.TraceBlockByHash(context.Background(), block.Hash(), nil) + require.NoError(t, err, "TraceBlockByHash failed: %v", err) + require.NotNil(t, results, "TraceBlockByHash returned nil traces") - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(5)) - if block == nil { - t.Fatal("block 5 not found") + // Validate if the trace is correct or not + require.Equal(t, len(transactions), len(results), "expected %d trace results, got: %d", len(transactions), len(results)) + for i, result := range results { + require.Equal(t, "", result.Error, "expected nil error in trace result %d, got: %s", i, result.Error) + require.Equal(t, transactions[i].Hash(), result.TxHash, "trace result %d tx hash mismatch: got %s, want %s", i, result.TxHash.Hex(), transactions[i].Hash().Hex()) } - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(5), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } + // Validate the state-sync trace specifically + raw, ok := results[1].Result.(json.RawMessage) + require.True(t, ok, "expected json.RawMessage for state-sync trace result, got %T", results[1].Result) - // Without Madhugiri fork, trace count should match block body - expectedCount := len(block.Transactions()) - if len(results) != expectedCount { - t.Errorf("without Madhugiri fork: expected %d results, got %d", expectedCount, len(results)) + var execResult struct { + Gas uint64 `json:"gas"` + Failed bool `json:"failed"` + StructLogs []json.RawMessage `json:"structLogs"` + ReturnValue string `json:"returnValue"` } -} - -// TestMadhugiriAtGenesis tests edge case where Madhugiri is active from genesis. -func TestMadhugiriAtGenesis(t *testing.T) { - t.Parallel() + err = json.Unmarshal(raw, &execResult) + require.NoError(t, err, "failed to unmarshal state-sync trace: %v", err) + require.Greater(t, len(execResult.StructLogs), 0, "state-sync trace has no struct logs — EVM code was not executed") - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, + // The target contract emits LOG0 for each onStateReceive call. + // With 2 bridge events, we expect 2 LOG0 from the target contract. + var log0Count int + for _, entry := range execResult.StructLogs { + var op struct { + Op string `json:"op"` } - ) - - // Madhugiri at block 0 = active from genesis - madhugiriBlock := big.NewInt(0) - genBlocks := 5 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - // Use dynamic fee tx with proper fee caps - baseFee := b.BaseFee() - tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasFeeCap: new(big.Int).Mul(baseFee, big.NewInt(2)), - GasTipCap: big.NewInt(1), - }), b.Signer(), key) - b.AddTx(tx) - }) - defer backend.chain.Stop() - - // Inject state-sync tx into all blocks (Madhugiri active from genesis) - for i := uint64(1); i <= 5; i++ { - stateSyncTx := createStateSyncTx(i) - if err := backend.injectStateSyncTx(i, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) + if err := json.Unmarshal(entry, &op); err == nil && op.Op == "LOG0" { + log0Count++ } } - - api := NewAPI(backend) - - // Test block 1 (all blocks are post-Madhugiri) - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(1)) - if block == nil { - t.Fatal("block 1 not found") - } - - expectedTxCount := len(block.Transactions()) - if expectedTxCount != 2 { - t.Fatalf("expected 2 txs, got %d", expectedTxCount) - } - - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(1), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - if len(results) != expectedTxCount { - t.Errorf("Madhugiri from genesis: expected %d results, got %d", expectedTxCount, len(results)) - } + require.Equal(t, 2, log0Count, "expected 2 LOG0 opcodes (one per bridge event forwarded to target), got %d", log0Count) + t.Logf("state-sync trace: %d struct logs, %d LOG0 opcodes, gas used: %d", len(execResult.StructLogs), log0Count, execResult.Gas) } -// TestMultipleStateSyncEvents tests blocks with multiple state sync events bundled. -func TestMultipleStateSyncEvents(t *testing.T) { +// TestTraceChain_WithStateSyncTx tests end-to-end state-sync tracing using the actual +// StateReceiver contract bytecode and mirrors what happens in actual networks. It generates +// traces of range of blocks. +func TestTraceChain_WithStateSyncTx(t *testing.T) { t.Parallel() - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - address = crypto.PubkeyToAddress(key.PublicKey) - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - address: {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - madhugiriBlock := big.NewInt(0) - genBlocks := 5 - - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{ - Nonce: uint64(i), - To: &address, - Value: big.NewInt(1000), - Gas: params.TxGas, - GasPrice: new(big.Int).Mul(b.BaseFee(), big.NewInt(2)), - }), b.Signer(), key) - b.AddTx(tx) - }) + backend, api, stateSyncBlock := newStateSyncTestSetup(t, 3) defer backend.chain.Stop() - // Inject state-sync tx with multiple events into block 3 - stateSyncTx := types.NewTx(&types.StateSyncTx{ - StateSyncData: []*types.StateSyncData{ - {ID: 31, Contract: common.HexToAddress("0x1001"), Data: []byte{0x01}}, - {ID: 32, Contract: common.HexToAddress("0x1001"), Data: []byte{0x02}}, - {ID: 33, Contract: common.HexToAddress("0x1001"), Data: []byte{0x03}}, - }, - }) - if err := backend.injectStateSyncTx(3, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } - - api := NewAPI(backend) - - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(3)) - if block == nil { - t.Fatal("block 3 not found") - } - - // Should have 2 txs: 1 regular + 1 state sync (with 3 events bundled) - expectedTxCount := len(block.Transactions()) - if expectedTxCount != 2 { - t.Fatalf("expected 2 txs, got %d", expectedTxCount) - } - - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(3), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - // Multiple events in one state sync tx = still 1 tx in trace results - if len(results) != expectedTxCount { - t.Errorf("multiple state sync events: expected %d results, got %d", expectedTxCount, len(results)) + // Get the from and to blocks + from, err := backend.BlockByNumber(context.Background(), rpc.BlockNumber(0)) + require.NoError(t, err, "failed to get block: %d, err: %v", 0, err) + to, err := backend.BlockByNumber(context.Background(), rpc.BlockNumber(3)) + require.NoError(t, err, "failed to get block: %d, err: %v", 3, err) + + // Trace full chain (from, to] (i.e. [0, 3]) + results := make(chan *blockTraceResult, 3) + results = api.traceChain(from, to, nil, nil) + require.NoError(t, err, "TraceBlockByNumber failed: %v", err) + require.NotNil(t, results, "TraceBlockByNumber returned nil traces") + + // Validate if the trace is correct or not + for res := range results { + traces := res.Traces + block, err := backend.BlockByNumber(context.Background(), rpc.BlockNumber(uint64(res.Block))) + require.NoError(t, err, "failed to get block: %d, err: %v", res.Block, err) + transactions := block.Transactions() + require.Equal(t, len(transactions), len(traces), "expected %d trace results, got: %d", len(transactions), len(traces)) + for i, result := range traces { + require.Equal(t, "", result.Error, "expected nil error in trace result %d of block: %d, got: %s", i, block.NumberU64(), result.Error) + require.Equal(t, transactions[i].Hash(), result.TxHash, "trace result %d tx hash mismatch of block: %d: got %s, want %s", i, block.NumberU64(), result.TxHash.Hex(), transactions[i].Hash().Hex()) + } + if res.Block == hexutil.Uint64(stateSyncBlock) { + // Validate the state-sync trace specifically + raw, ok := traces[1].Result.(json.RawMessage) + require.True(t, ok, "expected json.RawMessage for state-sync trace result, got %T", traces[1].Result) + + var execResult struct { + Gas uint64 `json:"gas"` + Failed bool `json:"failed"` + StructLogs []json.RawMessage `json:"structLogs"` + ReturnValue string `json:"returnValue"` + } + err = json.Unmarshal(raw, &execResult) + require.NoError(t, err, "failed to unmarshal state-sync trace: %v", err) + require.Greater(t, len(execResult.StructLogs), 0, "state-sync trace has no struct logs — EVM code was not executed") + + // The target contract emits LOG0 for each onStateReceive call. + // With 2 bridge events, we expect 2 LOG0 from the target contract. + var log0Count int + for _, entry := range execResult.StructLogs { + var op struct { + Op string `json:"op"` + } + if err := json.Unmarshal(entry, &op); err == nil && op.Op == "LOG0" { + log0Count++ + } + } + require.Equal(t, 2, log0Count, "expected 2 LOG0 opcodes (one per bridge event forwarded to target), got %d", log0Count) + } } } -// TestEmptyBlockWithStateSyncOnly tests blocks containing only state sync tx. -func TestEmptyBlockWithStateSyncOnly(t *testing.T) { +// TestIntermediateRoots_WithStateSyncTx tests end-to-end state-sync tracing using the actual +// StateReceiver contract bytecode and mirrors what happens in actual networks. Follows same +// steps as trace by block. +func TestIntermediateRoots_WithStateSyncTx(t *testing.T) { t.Parallel() - var ( - key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") - gspec = &core.Genesis{ - Alloc: types.GenesisAlloc{ - crypto.PubkeyToAddress(key.PublicKey): {Balance: big.NewInt(params.Ether)}, - }, - } - ) - - madhugiriBlock := big.NewInt(0) - genBlocks := 5 - - // Generate empty blocks (no regular txs) - backend := newBorTestBackend(t, genBlocks, gspec, madhugiriBlock, func(i int, b *core.BlockGen) { - // No transactions added - }) + backend, api, stateSyncBlock := newStateSyncTestSetup(t, 3) defer backend.chain.Stop() - // Inject state-sync tx into block 3 (which is otherwise empty) - stateSyncTx := createStateSyncTx(3) - if err := backend.injectStateSyncTx(3, stateSyncTx); err != nil { - t.Fatalf("failed to inject state-sync tx: %v", err) - } - - api := NewAPI(backend) - - block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(3)) - if block == nil { - t.Fatal("block 3 not found") - } - - expectedTxCount := len(block.Transactions()) - if expectedTxCount != 1 { - t.Fatalf("expected 1 tx (state-sync only), got %d", expectedTxCount) - } - - results, err := api.TraceBlockByNumber(context.Background(), rpc.BlockNumber(3), nil) - if err != nil { - t.Fatalf("TraceBlockByNumber failed: %v", err) - } - - if len(results) != expectedTxCount { - t.Errorf("block with only state sync: expected %d results, got %d", expectedTxCount, len(results)) + // Ensure block body contains transactions + block, _ := backend.BlockByNumber(context.Background(), rpc.BlockNumber(stateSyncBlock)) + require.NotNil(t, block, "block %d not found", stateSyncBlock) + transactions := block.Transactions() + require.Equal(t, 2, len(transactions), "expected %d transactions in block body, got %d", 2, len(transactions)) + + // Trace block by hash + results, err := api.IntermediateRoots(context.Background(), block.Hash(), nil) + require.NoError(t, err, "IntermediateRoots failed: %v", err) + require.NotNil(t, results, "IntermediateRoots returned nil traces") + + // Validate that correct state roots are returned + expectedStateRoots := []common.Hash{ + common.HexToHash("0x23eda0b1dbe747a8daedaf94b811a393de400047812394476dac190a5e9a8fd4"), + common.HexToHash("0x1b5bcf33b31f2d38b498594a348bc176b9e05b46cba3ed3701ba739c012bc757"), + } + require.Equal(t, 2, len(results), "expected 2 intermediate roots, got: %d", len(results)) + for i, result := range results { + require.Equal(t, expectedStateRoots[i], result, "state root mismatch, index: %d, expected: %v, got: %v", i, expectedStateRoots[i].Hex(), result.Hex()) } } From d8cb4ab6927b540140c0b415d3662992401e3623 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Mon, 30 Mar 2026 21:55:00 +0530 Subject: [PATCH 30/30] fix lint and tests --- eth/tracers/api.go | 16 ---------------- eth/tracers/api_statesync_test.go | 17 +---------------- eth/tracers/api_test.go | 6 ------ internal/cli/server/server.go | 4 ++++ internal/cli/server/service.go | 27 ++++++++++++++++++++++++++- 5 files changed, 31 insertions(+), 39 deletions(-) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index f189b6655e..032fcd1ed3 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -28,7 +28,6 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" @@ -545,21 +544,6 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, return api.standardTraceBlockToFile(ctx, block, config) } -func prepareCallMessage(msg core.Message) statefull.Callmsg { - return statefull.Callmsg{ - CallMsg: ethereum.CallMsg{ - From: msg.From, - To: msg.To, - Gas: msg.GasLimit, - GasPrice: msg.GasPrice, - GasFeeCap: msg.GasFeeCap, - GasTipCap: msg.GasTipCap, - Value: msg.Value, - Data: msg.Data, - AccessList: msg.AccessList, - }} -} - // IntermediateRoots executes a block (bad- or canon- or side-), and returns a list // of intermediate roots: the stateroot after each transaction. func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { diff --git a/eth/tracers/api_statesync_test.go b/eth/tracers/api_statesync_test.go index 2a969fadfc..9bf450bdd4 100644 --- a/eth/tracers/api_statesync_test.go +++ b/eth/tracers/api_statesync_test.go @@ -214,20 +214,6 @@ func (b *borTestBackend) injectStateSyncTx(blockNum uint64, stateSyncTx *types.T return nil } -// createStateSyncTx creates a state sync transaction for testing. -func createStateSyncTx(id uint64) *types.Transaction { - return types.NewTx(&types.StateSyncTx{ - StateSyncData: []*types.StateSyncData{ - { - ID: id, - Contract: common.HexToAddress("0x0000000000000000000000000000000000001001"), - Data: []byte{0x01, 0x02, 0x03}, - TxHash: common.HexToHash("0x0000dead"), - }, - }, - }) -} - // newStateSyncTestSetup creates a common test setup for state-sync tracing tests. // It returns the backend, api, stateSyncTx, and the block number where the state-sync tx was injected. func newStateSyncTestSetup(t *testing.T, n int) (*borTestBackend, *API, uint64) { @@ -412,8 +398,7 @@ func TestTraceChain_WithStateSyncTx(t *testing.T) { require.NoError(t, err, "failed to get block: %d, err: %v", 3, err) // Trace full chain (from, to] (i.e. [0, 3]) - results := make(chan *blockTraceResult, 3) - results = api.traceChain(from, to, nil, nil) + results := api.traceChain(from, to, nil, nil) require.NoError(t, err, "TraceBlockByNumber failed: %v", err) require.NotNil(t, results, "TraceBlockByNumber returned nil traces") diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 7fdc271ed5..aac650ae24 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -706,12 +706,6 @@ func TestTraceBlock(t *testing.T) { } } -// txTraceResult is the result of a single transaction trace. -type txTraceResultTest struct { - Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer - Error string `json:"error,omitempty"` // Trace failure produced by the tracer -} - // nolint:typecheck func TestTracingWithOverrides(t *testing.T) { t.Parallel() diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index 8b04ca1e13..0a81053713 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -64,6 +64,9 @@ type Server struct { tracer *sdktrace.TracerProvider config *Config + // tracerAPI to trace block executions + tracerAPI *tracers.API + // Bor health service. healthService *health.Health } @@ -244,6 +247,7 @@ func NewServer(config *Config, opts ...serverOption) (*Server, error) { // debug tracing is enabled by default stack.RegisterAPIs(tracers.APIs(srv.backend.APIBackend)) + srv.tracerAPI = tracers.NewAPI(srv.backend.APIBackend) // graphql is started from another place if config.JsonRPC.Graphql.Enabled { diff --git a/internal/cli/server/service.go b/internal/cli/server/service.go index 247999fc5c..2814facc40 100644 --- a/internal/cli/server/service.go +++ b/internal/cli/server/service.go @@ -2,6 +2,7 @@ package server import ( "context" + "encoding/json" "errors" "fmt" "math/big" @@ -13,10 +14,13 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/internal/cli/server/pprof" "github.com/ethereum/go-ethereum/internal/cli/server/proto" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/rpc" ) const chunkSize = 1024 * 1024 * 1024 @@ -226,7 +230,28 @@ func headerToProtoHeader(h *types.Header) *proto.Header { } func (s *Server) DebugBlock(req *proto.DebugBlockRequest, stream proto.Bor_DebugBlockServer) error { - return errors.New("debug block via gRPC is not supported, use debug_traceBlockByNumber RPC instead") + config := &tracers.TraceConfig{ + Config: &logger.Config{ + EnableMemory: true, + }, + } + + res, err := s.tracerAPI.TraceBlockByNumber(context.Background(), rpc.BlockNumber(req.Number), config) + if err != nil { + return err + } + + // this is memory heavy + data, err := json.Marshal(res) + if err != nil { + return err + } + + if err := sendStreamDebugFile(stream, map[string]string{}, data); err != nil { + return err + } + + return nil } var bigIntT = reflect.TypeOf(new(big.Int)).Kind()