Skip to content

Commit

Permalink
tracing: pass *tracing.Hooks around instead of vm.Config (#2846)
Browse files Browse the repository at this point in the history
Passing `*tracing.Hooks` makes the intent clearer and ensure the `applyTransaction`
controls the creationg of the `vm.Config`.
  • Loading branch information
maoueh authored Jan 9, 2025
1 parent 849d89d commit b912401
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 41 deletions.
9 changes: 5 additions & 4 deletions consensus/parlia/feynmanfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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
}
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down
66 changes: 32 additions & 34 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -1293,15 +1292,15 @@ 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)
}
}

// 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")
}
Expand All @@ -1322,21 +1321,21 @@ 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)
}
}
}
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
}
}
Expand All @@ -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
}
}
Expand All @@ -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)
Expand All @@ -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")
}
Expand All @@ -1411,21 +1409,21 @@ 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)
}
}
}

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
}
}
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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) &&
Expand All @@ -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
}
Expand All @@ -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"

Expand All @@ -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
Expand All @@ -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
}
Expand All @@ -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"

Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -1986,24 +1984,24 @@ 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)
}

// 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 {
Expand Down
4 changes: 1 addition & 3 deletions consensus/parlia/parlia_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down

0 comments on commit b912401

Please sign in to comment.