From bba7177261e56b6b9d2992a0980629d7cef1bb12 Mon Sep 17 00:00:00 2001 From: David Zhou <67666861+Rampex1@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:04:26 -0400 Subject: [PATCH] WIP: Polygon Battlefield Integration (#17) * Flags * DEV: Transaction * Added hooks * Ethash consensus * Fixed all consensus to implement hooks * Calling system hooks * Txs * FIX: System calls in transaction * FIX: System call was duplicated * FIX: Stopped tracing worker * FIX: Updated hooks --- consensus/beacon/consensus.go | 10 +++---- consensus/bor/bor.go | 22 ++++++++------ consensus/bor/bor_test.go | 2 +- consensus/bor/contract/client.go | 4 ++- consensus/bor/genesis.go | 3 +- consensus/bor/genesis_contract_mock.go | 9 +++--- consensus/bor/heimdall/span/spanner.go | 5 ++-- consensus/bor/span.go | 3 +- consensus/bor/span_mock.go | 9 +++--- consensus/bor/statefull/processor.go | 41 ++++++++++++++++++++++++-- consensus/clique/clique.go | 7 +++-- consensus/consensus.go | 5 ++-- consensus/ethash/consensus.go | 6 ++-- core/chain_makers.go | 4 +-- core/parallel_state_processor.go | 6 ++-- core/state_processor.go | 6 ++-- core/state_transition.go | 2 +- core/tracing/hooks.go | 5 ++++ eth/tracers/api.go | 2 +- eth/tracers/firehose.go | 3 ++ miner/worker.go | 9 ++++-- tests/bor/helper.go | 2 +- 22 files changed, 113 insertions(+), 52 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 71793e225f..06aae4a1b9 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -349,9 +349,9 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine and processes withdrawals on top. -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, tracer *tracing.Hooks) { if !beacon.IsPoSHeader(header) { - beacon.ethone.Finalize(chain, header, state, body) + beacon.ethone.Finalize(chain, header, state, body, tracer) return } // Withdrawals processing. @@ -366,9 +366,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, setting the final state and // assembling the block. -func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { +func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, error) { if !beacon.IsPoSHeader(header) { - return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts) + return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts, tracer) } shanghai := chain.Config().IsShanghai(header.Number) @@ -383,7 +383,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea } } // Finalize and assemble the block. - beacon.Finalize(chain, header, state, body) + beacon.Finalize(chain, header, state, body, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(true) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 738fb61bce..2e9d608558 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/core" "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/crypto" "github.com/ethereum/go-ethereum/ethdb" @@ -819,7 +820,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. -func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, tracer *tracing.Hooks) { headerNumber := header.Number.Uint64() if body.Withdrawals != nil || header.WithdrawalsHash != nil { return @@ -837,14 +838,14 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header, start := time.Now() cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span - if err := c.checkAndCommitSpan(state, header, cx); err != nil { + if err := c.checkAndCommitSpan(state, header, cx, tracer); err != nil { log.Error("Error while committing span", "error", err) return } if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(state, header, cx) + stateSyncData, err = c.CommitStates(state, header, cx, tracer) if err != nil { log.Error("Error while committing states", "error", err) return @@ -908,7 +909,7 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { +func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, error) { headerNumber := header.Number.Uint64() if body.Withdrawals != nil || header.WithdrawalsHash != nil { return nil, consensus.ErrUnexpectedWithdrawals @@ -926,14 +927,14 @@ func (c *Bor) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *typ cx := statefull.ChainContext{Chain: chain, Bor: c} // check and commit span - if err = c.checkAndCommitSpan(state, header, cx); err != nil { + if err = c.checkAndCommitSpan(state, header, cx, tracer); err != nil { log.Error("Error while committing span", "error", err) return nil, err } if c.HeimdallClient != nil { // commit states - stateSyncData, err = c.CommitStates(state, header, cx) + stateSyncData, err = c.CommitStates(state, header, cx, tracer) if err != nil { log.Error("Error while committing states", "error", err) return nil, err @@ -1108,6 +1109,7 @@ func (c *Bor) checkAndCommitSpan( state *state.StateDB, header *types.Header, chain core.ChainContext, + tracer *tracing.Hooks, ) error { var ctx = context.Background() headerNumber := header.Number.Uint64() @@ -1118,7 +1120,7 @@ func (c *Bor) checkAndCommitSpan( } 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, tracer) } return nil @@ -1149,6 +1151,7 @@ func (c *Bor) FetchAndCommitSpan( state *state.StateDB, header *types.Header, chain core.ChainContext, + tracer *tracing.Hooks, ) error { var heimdallSpan span.HeimdallSpan @@ -1178,7 +1181,7 @@ func (c *Bor) FetchAndCommitSpan( ) } - return c.spanner.CommitSpan(ctx, heimdallSpan, state, header, chain) + return c.spanner.CommitSpan(ctx, heimdallSpan, state, header, chain, tracer) } // CommitStates commit states @@ -1186,6 +1189,7 @@ func (c *Bor) CommitStates( state *state.StateDB, header *types.Header, chain statefull.ChainContext, + tracer *tracing.Hooks, ) ([]*types.StateSyncData, error) { fetchStart := time.Now() number := header.Number.Uint64() @@ -1264,7 +1268,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/maticnetwork/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, tracer) if err != nil { return nil, err } diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index ed839d3476..065b6559d4 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -77,7 +77,7 @@ func TestGenesisContractChange(t *testing.T) { ParentHash: root, Number: big.NewInt(num), } - b.Finalize(chain, h, statedb, &types.Body{Withdrawals: nil, Transactions: nil, Uncles: nil}) + b.Finalize(chain, h, statedb, &types.Body{Withdrawals: nil, Transactions: nil, Uncles: nil}, nil) // write state to database root, err := statedb.Commit(0, false) diff --git a/consensus/bor/contract/client.go b/consensus/bor/contract/client.go index 1cfc2fd8e9..910eff1d4c 100644 --- a/consensus/bor/contract/client.go +++ b/consensus/bor/contract/client.go @@ -2,6 +2,7 @@ package contract import ( "context" + "github.com/ethereum/go-ethereum/core/tracing" "math" "math/big" "strings" @@ -69,6 +70,7 @@ func (gc *GenesisContractsClient) CommitState( state *state.StateDB, header *types.Header, chCtx statefull.ChainContext, + tracer *tracing.Hooks, ) (uint64, error) { eventRecord := event.BuildEventRecord() @@ -91,7 +93,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, 0, tracer) // 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 9519b18847..7de4f4ab40 100644 --- a/consensus/bor/genesis.go +++ b/consensus/bor/genesis.go @@ -1,6 +1,7 @@ package bor import ( + "github.com/ethereum/go-ethereum/core/tracing" "math/big" "github.com/ethereum/go-ethereum/common" @@ -12,6 +13,6 @@ import ( //go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract type GenesisContract interface { - CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error) + CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext, tracer *tracing.Hooks) (uint64, error) LastStateId(state *state.StateDB, number uint64, hash common.Hash) (*big.Int, error) } diff --git a/consensus/bor/genesis_contract_mock.go b/consensus/bor/genesis_contract_mock.go index 0296cbe905..785a4a1d7b 100644 --- a/consensus/bor/genesis_contract_mock.go +++ b/consensus/bor/genesis_contract_mock.go @@ -13,6 +13,7 @@ import ( 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" + tracing "github.com/ethereum/go-ethereum/core/tracing" gomock "github.com/golang/mock/gomock" ) @@ -40,18 +41,18 @@ func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder { } // CommitState mocks base method. -func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 *state.StateDB, arg2 *types.Header, arg3 statefull.ChainContext) (uint64, error) { +func (m *MockGenesisContract) CommitState(arg0 *clerk.EventRecordWithTime, arg1 *state.StateDB, arg2 *types.Header, arg3 statefull.ChainContext, arg4 *tracing.Hooks) (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/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go index 99c361f044..26841443b4 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/consensus/bor/heimdall/span/spanner.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/core" "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/internal/ethapi" "github.com/ethereum/go-ethereum/log" @@ -287,7 +288,7 @@ func (c *ChainSpanner) GetCurrentValidatorsByHash(ctx context.Context, headerHas const method = "commitSpan" -func (c *ChainSpanner) CommitSpan(ctx context.Context, heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error { +func (c *ChainSpanner) CommitSpan(ctx context.Context, heimdallSpan HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext, tracer *tracing.Hooks) error { // get validators bytes validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) for _, val := range heimdallSpan.ValidatorSet.Validators { @@ -335,7 +336,7 @@ func (c *ChainSpanner) CommitSpan(ctx context.Context, heimdallSpan HeimdallSpan 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, 0, tracer) return err } diff --git a/consensus/bor/span.go b/consensus/bor/span.go index 179f92c79c..bff630b33a 100644 --- a/consensus/bor/span.go +++ b/consensus/bor/span.go @@ -2,6 +2,7 @@ package bor import ( "context" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/bor/heimdall/span" @@ -17,5 +18,5 @@ type Spanner interface { GetCurrentSpan(ctx context.Context, headerHash common.Hash) (*span.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, heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error + CommitSpan(ctx context.Context, heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext, tracer *tracing.Hooks) error } diff --git a/consensus/bor/span_mock.go b/consensus/bor/span_mock.go index 099807161c..f93c815d00 100644 --- a/consensus/bor/span_mock.go +++ b/consensus/bor/span_mock.go @@ -13,6 +13,7 @@ import ( valset "github.com/ethereum/go-ethereum/consensus/bor/valset" core "github.com/ethereum/go-ethereum/core" state "github.com/ethereum/go-ethereum/core/state" + tracing "github.com/ethereum/go-ethereum/core/tracing" types "github.com/ethereum/go-ethereum/core/types" rpc "github.com/ethereum/go-ethereum/rpc" gomock "github.com/golang/mock/gomock" @@ -42,17 +43,17 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder { } // CommitSpan mocks base method. -func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 span.HeimdallSpan, arg2 *state.StateDB, arg3 *types.Header, arg4 core.ChainContext) error { +func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 span.HeimdallSpan, arg2 *state.StateDB, arg3 *types.Header, arg4 core.ChainContext, arg5 *tracing.Hooks) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(error) return ret0 } // CommitSpan indicates an expected call of CommitSpan. -func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4, arg5 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) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4, arg5) } // GetCurrentSpan mocks base method. diff --git a/consensus/bor/statefull/processor.go b/consensus/bor/statefull/processor.go index b2c61b89e7..be80605aaa 100644 --- a/consensus/bor/statefull/processor.go +++ b/consensus/bor/statefull/processor.go @@ -3,6 +3,7 @@ package statefull import ( "bytes" "context" + "github.com/ethereum/go-ethereum/core/tracing" "math" "math/big" @@ -69,15 +70,51 @@ func ApplyMessage( header *types.Header, chainConfig *params.ChainConfig, chainContext core.ChainContext, + spanID int64, + tracer *tracing.Hooks, ) (uint64, error) { + initialGas := msg.Gas() - // Create a new context to be used in the EVM environment blockContext := core.NewEVMBlockContext(header, chainContext, &header.Coinbase) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(blockContext, vm.TxContext{}, state, chainConfig, vm.Config{}) + msgForCtx := core.Message{ + To: msg.To(), + From: msg.From(), + Nonce: msg.Nonce(), + Value: msg.Value(), + GasLimit: msg.Gas(), + GasPrice: msg.GasPrice(), + SkipNonceChecks: false, + SkipFromEOACheck: false, + } + txContext := core.NewEVMTxContext(&msgForCtx) + vmenv := vm.NewEVM(blockContext, txContext, state, chainConfig, vm.Config{Tracer: tracer}) + + tx := types.NewTx(&types.LegacyTx{ + Nonce: msg.Nonce(), + GasPrice: msg.GasPrice(), + Gas: msg.Gas(), + To: msg.To(), + Value: msg.Value(), + Data: msg.Data(), + }) + state.SetTxContext(tx.Hash(), 0) + + // Notify tracers about transaction start (system call is already started at Bor level) + if tracer != nil { + if tracer.OnTxStart != nil { + tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From()) + } + } + + defer func() { + if tracer != nil && tracer.OnTxEnd != nil { + tracer.OnTxEnd(nil, nil) + } + }() // nolint : contextcheck // Apply the transaction to the current state (included in the env) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 824b915e73..8285cc07e5 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -21,6 +21,7 @@ import ( "bytes" "errors" "fmt" + "github.com/ethereum/go-ethereum/core/tracing" "io" "math/big" "math/rand" @@ -619,18 +620,18 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine. There is no post-transaction // consensus rules in clique, do nothing here. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, tracer *tracing.Hooks) { // No block rewards in PoA, so the state remains as is } // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { +func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, error) { if len(body.Withdrawals) > 0 { return nil, errors.New("clique does not support withdrawals") } // Finalize block - c.Finalize(chain, header, state, body) + c.Finalize(chain, header, state, body, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/consensus/consensus.go b/consensus/consensus.go index cd1a01bedf..b72f707d5a 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -18,6 +18,7 @@ package consensus import ( + "github.com/ethereum/go-ethereum/core/tracing" "math/big" "github.com/ethereum/go-ethereum/common" @@ -88,14 +89,14 @@ type Engine interface { // // Note: The state database might be updated to reflect any consensus rules // that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) + Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, tracer *tracing.Hooks) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // rewards or process withdrawals) and assembles the final block. // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). - FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) + FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes // the result into the given channel. diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index a44108c4c7..8246956432 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -503,19 +503,19 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine, accumulating the block and uncle rewards. -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, tracer *tracing.Hooks) { // Accumulate any block and uncle rewards accumulateRewards(chain.Config(), state, header, body.Uncles) } // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. -func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) { +func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, error) { if len(body.Withdrawals) > 0 { return nil, errors.New("ethash does not support withdrawals") } // Finalize block - ethash.Finalize(chain, header, state, body) + ethash.Finalize(chain, header, state, body, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/core/chain_makers.go b/core/chain_makers.go index 803191e1ab..7c8f4ff55f 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -372,7 +372,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests} - block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts) + block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts, nil) if err != nil { panic(err) } @@ -480,7 +480,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine Uncles: b.uncles, Withdrawals: b.withdrawals, } - block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, body, b.receipts) + block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, body, b.receipts, nil) if err != nil { panic(err) } diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go index 5a4903aeae..a8676d4de0 100644 --- a/core/parallel_state_processor.go +++ b/core/parallel_state_processor.go @@ -189,10 +189,10 @@ func (task *ExecutionTask) Settle() { if *task.shouldDelayFeeCal { if task.config.IsLondon(task.blockNumber) { - task.finalStateDB.AddBalance(task.result.BurntContractAddress, cmath.BigIntToUint256Int(task.result.FeeBurnt), tracing.BalanceChangeTransfer) + task.finalStateDB.AddBalance(task.result.BurntContractAddress, cmath.BigIntToUint256Int(task.result.FeeBurnt), tracing.BalanceChangePolygonBurn) } - task.finalStateDB.AddBalance(task.coinbase, cmath.BigIntToUint256Int(task.result.FeeTipped), tracing.BalanceChangeTransfer) + task.finalStateDB.AddBalance(task.coinbase, cmath.BigIntToUint256Int(task.result.FeeTipped), tracing.BalanceIncreaseRewardTransactionFee) output1 := new(big.Int).SetBytes(task.result.SenderInitBalance.Bytes()) output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes()) @@ -404,7 +404,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) - p.engine.Finalize(p.bc, header, statedb, block.Body()) + p.engine.Finalize(p.bc, header, statedb, block.Body(), cfg.Tracer) return &ProcessResult{ Receipts: receipts, diff --git a/core/state_processor.go b/core/state_processor.go index 824554c1b2..7bfd0d40e6 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -111,7 +111,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) - p.hc.engine.Finalize(p.bc, header, statedb, block.Body()) + p.hc.engine.Finalize(p.bc, header, statedb, block.Body(), cfg.Tracer) return &ProcessResult{ Receipts: receipts, @@ -158,11 +158,11 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo statedb.SetMVHashmap(nil) if evm.ChainConfig().IsLondon(blockNumber) { - statedb.AddBalance(result.BurntContractAddress, cmath.BigIntToUint256Int(result.FeeBurnt), tracing.BalanceChangeTransfer) + statedb.AddBalance(result.BurntContractAddress, cmath.BigIntToUint256Int(result.FeeBurnt), tracing.BalanceChangePolygonBurn) } // TODO(raneet10) Double check - statedb.AddBalance(evm.Context.Coinbase, cmath.BigIntToUint256Int(result.FeeTipped), tracing.BalanceChangeTransfer) + statedb.AddBalance(evm.Context.Coinbase, cmath.BigIntToUint256Int(result.FeeTipped), tracing.BalanceIncreaseRewardTransactionFee) output1 := new(big.Int).SetBytes(result.SenderInitBalance.Bytes()) output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes()) diff --git a/core/state_transition.go b/core/state_transition.go index 42b3cf0499..e4462b4e82 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -534,7 +534,7 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio burnAmount = new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee) if !st.noFeeBurnAndTip { - st.state.AddBalance(burntContractAddress, cmath.BigIntToUint256Int(burnAmount), tracing.BalanceChangeTransfer) + st.state.AddBalance(burntContractAddress, cmath.BigIntToUint256Int(burnAmount), tracing.BalanceChangePolygonBurn) } } diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index a7bf63fae8..c1b38e84f6 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -252,6 +252,11 @@ const ( // account within the same tx (captured at end of tx). // Note it doesn't account for a self-destruct which appoints itself as recipient. BalanceDecreaseSelfdestructBurn BalanceChangeReason = 14 + + // Polygon specific balance changes + + // BalanceChangePolygonBurn is ether burned on Polygon by sending it to a designated burn contract. + BalanceChangePolygonBurn BalanceChangeReason = 200 ) //go:generate go run golang.org/x/tools/cmd/stringer@latest -type=GasChangeReason -trimprefix=GasChange -output gen_gas_change_reason_stringer.go diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 6241cc91b8..1e01331694 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -711,7 +711,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config if *config.BorTraceEnabled { 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), 0, nil); 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/eth/tracers/firehose.go b/eth/tracers/firehose.go index e4c76fec5e..ac515c74fa 100644 --- a/eth/tracers/firehose.go +++ b/eth/tracers/firehose.go @@ -2190,6 +2190,9 @@ var balanceChangeReasonToPb = map[tracing.BalanceChangeReason]pbeth.BalanceChang tracing.BalanceIncreaseWithdrawal: pbeth.BalanceChange_REASON_WITHDRAWAL, tracing.BalanceChangeUnspecified: pbeth.BalanceChange_REASON_UNKNOWN, + + // Polygon specific balance change + tracing.BalanceChangePolygonBurn: pbeth.BalanceChange_REASON_BURN, } func balanceChangeReasonFromChain(reason tracing.BalanceChangeReason) pbeth.BalanceChange_Reason { diff --git a/miner/worker.go b/miner/worker.go index 469744b227..01ede3f398 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -890,7 +890,10 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]* ) w.interruptCtx = vm.SetCurrentTxOnContext(w.interruptCtx, tx.Hash()) - receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig(), w.interruptCtx) + config := *w.chain.GetVMConfig() + config.Tracer = nil + + receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, config, w.interruptCtx) if err != nil { env.state.RevertToSnapshot(snap) env.gasPool.SetGas(gp) @@ -1415,7 +1418,7 @@ func (w *worker) generateWork(params *generateParams, witness bool) *newPayloadR } body.Requests = requests } - block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, &body, work.receipts) + block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, &body, work.receipts, nil) if err != nil { return &newPayloadResult{err: err} @@ -1566,7 +1569,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti // Withdrawals are set to nil here, because this is only called in PoW. block, err := w.engine.FinalizeAndAssemble(w.chain, env.header, env.state, &types.Body{ Transactions: env.txs, - }, env.receipts) + }, env.receipts, nil) if err != nil { return err diff --git a/tests/bor/helper.go b/tests/bor/helper.go index 917d9bf520..bd4ed599dc 100644 --- a/tests/bor/helper.go +++ b/tests/bor/helper.go @@ -365,7 +365,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()).Return(&span.Span{0, 0, 0}, nil).AnyTimes() - spanner.EXPECT().CommitSpan(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()).Return(nil).AnyTimes() return spanner }