From 09acca6e69a4c5867cc2c75222fddb402da06c3c Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Tue, 7 Jan 2025 10:07:07 -0500 Subject: [PATCH] tracing: pass `*tracing.Hooks` around instead of `vm.Config` Passing `*tracing.Hooks` makes the intent clearer and ensure the `applyTransaction` controls the creationg of the `vm.Config`. --- consensus/parlia/feynmanfork.go | 9 +++-- consensus/parlia/parlia.go | 66 ++++++++++++++++----------------- consensus/parlia/parlia_test.go | 4 +- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/consensus/parlia/feynmanfork.go b/consensus/parlia/feynmanfork.go index 8a824f74e0..48bdf0ace9 100644 --- a/consensus/parlia/feynmanfork.go +++ b/consensus/parlia/feynmanfork.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/systemcontracts" + "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/internal/ethapi" @@ -30,7 +31,7 @@ func isBreatheBlock(lastBlockTime, blockTime uint64) bool { // initializeFeynmanContract initialize new contracts of Feynman fork func (p *Parlia) initializeFeynmanContract(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks, ) error { // method method := "initialize" @@ -53,7 +54,7 @@ func (p *Parlia) initializeFeynmanContract(state vm.StateDB, header *types.Heade msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0) // apply message log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c) - err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) if err != nil { return err } @@ -96,7 +97,7 @@ func (h *ValidatorHeap) Pop() interface{} { } func (p *Parlia) updateValidatorSetV2(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks, ) error { // 1. get all validators and its voting power blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false) @@ -123,7 +124,7 @@ func (p *Parlia) updateValidatorSetV2(state vm.StateDB, header *types.Header, ch // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) } func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) { diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index bcf7fffe24..bb4f13e2f6 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1186,7 +1186,7 @@ func (p *Parlia) verifyTurnLength(chain consensus.ChainHeaderReader, header *typ func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state vm.StateDB, header *types.Header, cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, - usedGas *uint64, mining bool, vmConfig vm.Config) error { + usedGas *uint64, mining bool, tracer *tracing.Hooks) error { currentHeight := header.Number.Uint64() epoch := p.config.Epoch chainConfig := chain.Config() @@ -1255,7 +1255,7 @@ func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, sta return err } msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0) - return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining, vmConfig) + return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining, tracer) } // Finalize implements consensus.Engine, ensuring no uncles are set, nor block @@ -1283,7 +1283,6 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade } cx := chainContext{Chain: chain, parlia: p} - vmConfig := vm.Config{Tracer: tracer} parent := chain.GetHeaderByHash(header.ParentHash) if parent == nil { @@ -1293,7 +1292,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade systemcontracts.TryUpdateBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false) if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) + err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) if err != nil { log.Error("init feynman contract failed", "error", err) } @@ -1301,7 +1300,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // No block rewards in PoA, so the state remains as is and uncles are dropped if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) + err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) if err != nil { log.Error("init contract failed") } @@ -1322,7 +1321,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade if !signedRecently { log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) - err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) + err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "err", err) @@ -1330,13 +1329,13 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade } } val := header.Coinbase - err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) + err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) if err != nil { return err } if p.chainConfig.IsPlato(header.Number) { - if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer); err != nil { return err } } @@ -1345,7 +1344,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) { // we should avoid update validators in the Feynman upgrade block if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer); err != nil { return err } } @@ -1363,7 +1362,6 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped cx := chainContext{Chain: chain, parlia: p} - vmConfig := vm.Config{Tracer: tracer} if body.Transactions == nil { body.Transactions = make([]*types.Transaction, 0) @@ -1380,14 +1378,14 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * systemcontracts.TryUpdateBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false) if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) + err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) if err != nil { log.Error("init feynman contract failed", "error", err) } } if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) + err := p.initContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) if err != nil { log.Error("init contract failed") } @@ -1411,7 +1409,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * } } if !signedRecently { - err = p.slash(spoiledVal, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) + err = p.slash(spoiledVal, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) if err != nil { // it is possible that slash validator failed because of the slash channel is disabled. log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) @@ -1419,13 +1417,13 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * } } - err := p.distributeIncoming(p.val, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) + err := p.distributeIncoming(p.val, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) if err != nil { return nil, nil, err } if p.chainConfig.IsPlato(header.Number) { - if err := p.distributeFinalityReward(chain, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer); err != nil { return nil, nil, err } } @@ -1434,7 +1432,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) { // we should avoid update validators in the Feynman upgrade block if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - if err := p.updateValidatorSetV2(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer); err != nil { return nil, nil, err } } @@ -1817,7 +1815,7 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int) // distributeIncoming distributes system incoming of the block func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { coinbase := header.Coinbase doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) && @@ -1829,7 +1827,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header if rewards.Cmp(common.U2560) > 0 { state.SetBalance(consensus.SystemAddress, balance.Sub(balance, rewards), tracing.BalanceChangeUnspecified) state.AddBalance(coinbase, rewards, tracing.BalanceChangeUnspecified) - err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) if err != nil { return err } @@ -1845,12 +1843,12 @@ func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header state.SetBalance(consensus.SystemAddress, common.U2560, tracing.BalanceDecreaseBSCDistributeReward) state.AddBalance(coinbase, balance, tracing.BalanceIncreaseBSCDistributeReward) log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance) - return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) } // slash spoiled validators func (p *Parlia) slash(spoiledVal common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { // method method := "slash" @@ -1865,12 +1863,12 @@ func (p *Parlia) slash(spoiledVal common.Address, state vm.StateDB, header *type // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SlashContract), data, common.Big0) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) } // init contract func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { // method method := "init" // contracts @@ -1893,7 +1891,7 @@ func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0) // apply message log.Trace("init contract", "block hash", header.Hash(), "contract", c) - err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) if err != nil { return err } @@ -1902,17 +1900,17 @@ func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core } func (p *Parlia) distributeToSystem(amount *big.Int, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SystemRewardContract), nil, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) } // distributeToValidator deposits validator reward to validator contract func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { // method method := "deposit" @@ -1927,7 +1925,7 @@ func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) } // get system message @@ -1949,7 +1947,7 @@ func (p *Parlia) applyTransaction( chainContext core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, - vmConfig vm.Config, + tracer *tracing.Hooks, ) (applyErr error) { nonce := state.GetNonce(msg.From) expectedTx := types.NewTransaction(nonce, *msg.To, msg.Value, msg.GasLimit, msg.GasPrice, msg.Data) @@ -1986,14 +1984,14 @@ func (p *Parlia) applyTransaction( context := core.NewEVMBlockContext(header, chainContext, nil) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - evm := vm.NewEVM(context, state, p.chainConfig, vmConfig) + evm := vm.NewEVM(context, state, p.chainConfig, vm.Config{Tracer: tracer}) evm.SetTxContext(core.NewEVMTxContext(msg)) // Tracing receipt will be set if there is no error and will be used to trace the transaction var tracingReceipt *types.Receipt - if tracer := vmConfig.Tracer; tracer != nil { - if vmConfig.Tracer.OnSystemTxStart != nil { - vmConfig.Tracer.OnSystemTxStart() + if tracer != nil { + if tracer.OnSystemTxStart != nil { + tracer.OnSystemTxStart() } if tracer.OnTxStart != nil { tracer.OnTxStart(evm.GetVMContext(), expectedTx, msg.From) @@ -2001,9 +1999,9 @@ func (p *Parlia) applyTransaction( // Defers are last in first out, so OnTxEnd will run before OnSystemTxEnd in this transaction, // which is what we want. - if vmConfig.Tracer.OnSystemTxEnd != nil { + if tracer.OnSystemTxEnd != nil { defer func() { - vmConfig.Tracer.OnSystemTxEnd() + tracer.OnSystemTxEnd() }() } if tracer.OnTxEnd != nil { diff --git a/consensus/parlia/parlia_test.go b/consensus/parlia/parlia_test.go index 8b6309e903..d32cdda892 100644 --- a/consensus/parlia/parlia_test.go +++ b/consensus/parlia/parlia_test.go @@ -703,9 +703,7 @@ func TestParlia_applyTransactionTracing(t *testing.T) { hooks := recording.hooks() cx := chainContext{Chain: chain, parlia: engine} - applyErr := engine.applyTransaction(msg, state.NewHookedState(stateDB, hooks), bs[0].Header(), cx, &txs, &receipts, &receivedTxs, &usedGas, false, vm.Config{ - Tracer: hooks, - }) + applyErr := engine.applyTransaction(msg, state.NewHookedState(stateDB, hooks), bs[0].Header(), cx, &txs, &receipts, &receivedTxs, &usedGas, false, hooks) if applyErr != nil { t.Fatalf("failed to apply system contract transaction: %v", applyErr) }