From fe10268b60931139ac7cb6c9a4013aa64ace5fdd Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Tue, 26 Nov 2024 12:07:58 -0500 Subject: [PATCH] tracing: Parlia system transactions live tracing support Push tracing of Parlia system transactions so that live tracers can properly traces those state changes --- consensus/beacon/consensus.go | 10 +-- consensus/clique/clique.go | 7 +- consensus/consensus.go | 5 +- consensus/ethash/consensus.go | 6 +- consensus/parlia/feynmanfork.go | 9 +-- consensus/parlia/parlia.go | 121 ++++++++++++++++++++------------ core/blockchain_test.go | 7 +- core/chain_makers.go | 4 +- core/state_processor.go | 2 +- core/tracing/hooks.go | 49 ++++++++++++- eth/handler_test.go | 7 +- eth/tracers/api.go | 4 +- eth/tracers/logger/logger.go | 12 ++-- eth/tracers/native/call.go | 14 ++-- eth/tracers/native/call_flat.go | 4 +- eth/tracers/native/mux.go | 30 ++++---- eth/tracers/native/noop.go | 28 ++++---- miner/worker.go | 4 +- 18 files changed, 201 insertions(+), 122 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index a4c18c3cf4..50bd06f551 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -359,10 +359,10 @@ func (beacon *Beacon) Delay(_ consensus.ChainReader, _ *types.Header, _ *time.Du } // Finalize implements consensus.Engine, setting the final state on the header -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) error { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64, tracer *tracing.Hooks) error { // Finalize is different with Prepare, it can be used in both block verification. if !beacon.IsPoSHeader(header) { - beacon.ethone.Finalize(chain, header, state, txs, uncles, nil, nil, nil, nil) + beacon.ethone.Finalize(chain, header, state, txs, uncles, nil, nil, nil, nil, tracer) return nil } // Withdrawals processing. @@ -378,10 +378,10 @@ 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, []*types.Receipt, 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, []*types.Receipt, error) { // FinalizeAndAssemble is different with Prepare, it can be used in both block generation. 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, header.Time) if shanghai { @@ -395,7 +395,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea } } // Finalize and assemble the block. - beacon.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil) + beacon.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(true) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index f4386605f3..71c2abf443 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -36,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "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" @@ -587,19 +588,19 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, _ *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, - _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) { + _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64, tracer *tracing.Hooks) (err error) { // No block rewards in PoA, so the state remains as is return } // 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, []*types.Receipt, 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, []*types.Receipt, error) { if len(body.Withdrawals) > 0 { return nil, nil, errors.New("clique does not support withdrawals") } // Finalize block - c.Finalize(chain, header, state, &body.Transactions, body.Uncles, nil, nil, nil, nil) + c.Finalize(chain, header, state, &body.Transactions, body.Uncles, nil, nil, nil, nil, 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 f9d6d6c1fb..43bc23f36c 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "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/params" "github.com/ethereum/go-ethereum/rpc" @@ -113,14 +114,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, txs *[]*types.Transaction, - uncles []*types.Header, withdrawals []*types.Withdrawal, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error + uncles []*types.Header, withdrawals []*types.Withdrawal, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64, tracer *tracing.Hooks) error // 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, []*types.Receipt, error) + FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, 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 092cd11bac..f1cf6413c2 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -509,7 +509,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H // Finalize implements consensus.Engine, accumulating the block and uncle rewards, // setting the final state on the header func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, _ *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, - _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) { + _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64, tracer *tracing.Hooks) (err error) { // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) return @@ -517,12 +517,12 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types. // 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, []*types.Receipt, 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, []*types.Receipt, error) { if len(body.Withdrawals) > 0 { return nil, nil, errors.New("ethash does not support withdrawals") } // Finalize block - ethash.Finalize(chain, header, state, &body.Transactions, body.Uncles, nil, nil, nil, nil) + ethash.Finalize(chain, header, state, &body.Transactions, body.Uncles, nil, nil, nil, nil, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/consensus/parlia/feynmanfork.go b/consensus/parlia/feynmanfork.go index 88d2ae17cc..750e2d883c 100644 --- a/consensus/parlia/feynmanfork.go +++ b/consensus/parlia/feynmanfork.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -30,7 +31,7 @@ func isBreatheBlock(lastBlockTime, blockTime uint64) bool { // initializeFeynmanContract initialize new contracts of Feynman fork func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config, ) error { // method method := "initialize" @@ -53,7 +54,7 @@ func (p *Parlia) initializeFeynmanContract(state *state.StateDB, header *types.H 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) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) if err != nil { return err } @@ -96,7 +97,7 @@ func (h *ValidatorHeap) Pop() interface{} { } func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config, ) error { // 1. get all validators and its voting power blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false) @@ -123,7 +124,7 @@ func (p *Parlia) updateValidatorSetV2(state *state.StateDB, header *types.Header // 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) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) } func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) { diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 9f9665e618..55bf1b290d 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1184,7 +1184,7 @@ func (p *Parlia) verifyTurnLength(chain consensus.ChainHeaderReader, header *typ func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state *state.StateDB, header *types.Header, cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, - usedGas *uint64, mining bool) error { + usedGas *uint64, mining bool, vmConfig vm.Config) error { currentHeight := header.Number.Uint64() epoch := p.config.Epoch chainConfig := chain.Config() @@ -1253,13 +1253,13 @@ 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) + return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining, vmConfig) } // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction, - uncles []*types.Header, _ []*types.Withdrawal, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64) error { + uncles []*types.Header, _ []*types.Withdrawal, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, usedGas *uint64, tracer *tracing.Hooks) error { // warn if not in majority fork number := header.Number.Uint64() snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) @@ -1281,6 +1281,7 @@ 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 { @@ -1292,7 +1293,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade } if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false) + err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) if err != nil { log.Error("init feynman contract failed", "error", err) } @@ -1300,7 +1301,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) + err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) if err != nil { log.Error("init contract failed") } @@ -1321,7 +1322,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) + err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) 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) @@ -1329,13 +1330,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) + err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig) if err != nil { return err } if p.chainConfig.IsPlato(header.Number) { - if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig); err != nil { return err } } @@ -1344,7 +1345,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); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false, vmConfig); err != nil { return err } } @@ -1359,9 +1360,11 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, - body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { + 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) } @@ -1379,14 +1382,14 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * } if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true) + err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) 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) + err := p.initContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) if err != nil { log.Error("init contract failed") } @@ -1410,7 +1413,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) + err = p.slash(spoiledVal, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) 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) @@ -1418,13 +1421,13 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * } } - err := p.distributeIncoming(p.val, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true) + err := p.distributeIncoming(p.val, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig) 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); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig); err != nil { return nil, nil, err } } @@ -1433,7 +1436,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); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, vmConfig); err != nil { return nil, nil, err } } @@ -1816,7 +1819,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 *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { coinbase := header.Coinbase doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) && @@ -1828,7 +1831,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he 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) + err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) if err != nil { return err } @@ -1840,15 +1843,16 @@ func (p *Parlia) distributeIncoming(val common.Address, state *state.StateDB, he if balance.Cmp(common.U2560) <= 0 { return nil } - state.SetBalance(consensus.SystemAddress, common.U2560, tracing.BalanceChangeUnspecified) - state.AddBalance(coinbase, balance, tracing.BalanceChangeUnspecified) + + 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) + return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) } // slash spoiled validators func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { // method method := "slash" @@ -1863,12 +1867,12 @@ func (p *Parlia) slash(spoiledVal common.Address, state *state.StateDB, header * // 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) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) } // init contract func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { // method method := "init" // contracts @@ -1891,7 +1895,7 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain 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) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) if err != nil { return err } @@ -1900,17 +1904,17 @@ func (p *Parlia) initContract(state *state.StateDB, header *types.Header, chain } func (p *Parlia) distributeToSystem(amount *big.Int, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) 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) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) } // distributeToValidator deposits validator reward to validator contract func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address, state *state.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, vmConfig vm.Config) error { // method method := "deposit" @@ -1925,7 +1929,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) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, vmConfig) } // get system message @@ -1949,12 +1953,14 @@ func (p *Parlia) applyTransaction( chainContext core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, -) (err error) { + vmConfig vm.Config, +) (applyErr error) { nonce := state.GetNonce(msg.From()) expectedTx := types.NewTransaction(nonce, *msg.To(), msg.Value(), msg.Gas(), msg.GasPrice(), msg.Data()) expectedHash := p.signer.Hash(expectedTx) if msg.From() == p.val && mining { + var err error expectedTx, err = p.signTxFn(accounts.Account{Address: msg.From()}, expectedTx, p.chainConfig.ChainID) if err != nil { return err @@ -1979,7 +1985,36 @@ func (p *Parlia) applyTransaction( *receivedTxs = (*receivedTxs)[1:] } state.SetTxContext(expectedTx.Hash(), len(*txs)) - gasUsed, err := applyMessage(msg, state, header, p.chainConfig, chainContext) + + // Create a new context to be used in the EVM environment + context := core.NewEVMBlockContext(header, chainContext, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, p.chainConfig, vm.Config{}) + + // 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.OnTxStart != nil { + tracer.OnTxStart(vmenv.GetVMContext(), expectedTx, msg.From()) + } + + if tracer.OnTxEnd != nil { + defer func() { + tracer.OnTxEnd(tracingReceipt, applyErr) + }() + } + if vmConfig.Tracer.OnSystemTxEnd != nil { + defer func() { + vmConfig.Tracer.OnSystemTxEnd() + }() + } + } + + gasUsed, err := applyMessage(msg, vmenv, state, header, p.chainConfig, chainContext) if err != nil { return err } @@ -1991,17 +2026,17 @@ func (p *Parlia) applyTransaction( root = state.IntermediateRoot(p.chainConfig.IsEIP158(header.Number)).Bytes() } *usedGas += gasUsed - receipt := types.NewReceipt(root, false, *usedGas) - receipt.TxHash = expectedTx.Hash() - receipt.GasUsed = gasUsed + tracingReceipt = types.NewReceipt(root, false, *usedGas) + tracingReceipt.TxHash = expectedTx.Hash() + tracingReceipt.GasUsed = gasUsed // Set the receipt logs and create a bloom for filtering - receipt.Logs = state.GetLogs(expectedTx.Hash(), header.Number.Uint64(), header.Hash()) - receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = header.Hash() - receipt.BlockNumber = header.Number - receipt.TransactionIndex = uint(state.TxIndex()) - *receipts = append(*receipts, receipt) + tracingReceipt.Logs = state.GetLogs(expectedTx.Hash(), header.Number.Uint64(), header.Hash()) + tracingReceipt.Bloom = types.CreateBloom(types.Receipts{tracingReceipt}) + tracingReceipt.BlockHash = header.Hash() + tracingReceipt.BlockNumber = header.Number + tracingReceipt.TransactionIndex = uint(state.TxIndex()) + *receipts = append(*receipts, tracingReceipt) return nil } @@ -2158,16 +2193,12 @@ func (m callmsg) Data() []byte { return m.CallMsg.Data } // apply message func applyMessage( msg callmsg, + vmenv *vm.EVM, state *state.StateDB, header *types.Header, chainConfig *params.ChainConfig, chainContext core.ChainContext, ) (uint64, error) { - // Create a new context to be used in the EVM environment - context := core.NewEVMBlockContext(header, chainContext, nil) - // Create a new environment which holds all relevant information - // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(context, vm.TxContext{Origin: msg.From(), GasPrice: big.NewInt(0)}, state, chainConfig, vm.Config{}) // Apply the transaction to the current state (included in the env) if chainConfig.IsCancun(header.Number, header.Time) { rules := vmenv.ChainConfig().Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index adc0dbcdd9..7fb755f795 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -38,6 +38,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "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/crypto" @@ -4275,13 +4276,13 @@ func (c *mockParlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] } func (c *mockParlia) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, _ *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, - _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) { + _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64, tracer *tracing.Hooks) (err error) { return } -func (c *mockParlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { +func (c *mockParlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, error) { // Finalize block - c.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil) + c.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil, 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 27bf4e02b3..2228c1ca35 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -384,7 +384,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) } @@ -499,7 +499,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/state_processor.go b/core/state_processor.go index 1773e9d3c0..42d6056b20 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) - err = p.chain.engine.Finalize(p.chain, header, statedb, &commonTxs, block.Uncles(), block.Withdrawals(), &receipts, &systemTxs, usedGas) + err = p.chain.engine.Finalize(p.chain, header, statedb, &commonTxs, block.Uncles(), block.Withdrawals(), &receipts, &systemTxs, usedGas, cfg.Tracer) if err != nil { return nil, err } diff --git a/core/tracing/hooks.go b/core/tracing/hooks.go index 954d6957ea..8fec2185d0 100644 --- a/core/tracing/hooks.go +++ b/core/tracing/hooks.go @@ -150,9 +150,41 @@ type ( // beacon block root. OnSystemCallEndHook = func() - // OnSystemTxEndHook is called when tracing a system transaction, which does not calculate intrinsic gas during execution. + // OnSystemTxFixIntrinsicGasHook is called when tracing a system transaction, which does not calculate intrinsic gas during execution. // this hook will subtract intrinsic gas from the total gas used. - OnSystemTxEndHook = func(uint64) + OnSystemTxFixIntrinsicGasHook = func(uint64) + + // OnSystemTxStartHook is called when a system transaction is about to be executed within the Parlia consensus + // engine, like before upgrading system contracts, distribution of rewards, and other "chain" related transactions. + // + // This will be called in addition to the `OnTxStart` hook so the flow of event you will receive in your tracer will + // look kike this: + // + // - OnSystemTxStart + // - OnTxStart + // - OnTxEnd + // - OnSystemTxEnd + // + // This event flow enables transactions to be traced correctly with just OnTxStart/End being set but also + // enables special routing of those transactions by having OnSystemTxStart/End defined and keeping a special + // system state to do something different when OnTxEnd is called. + OnSystemTxStartHook func() + + // OnSystemTxEnd is called when a system transaction is about to completed its execution within the Parlia consensus + // engine, like after upgrading system contracts, distribution of rewards, and other "chain" related transactions. + // + // This will be called in addition to the `OnTxStart` hook so the flow of event you will receive in your tracer will + // look kike this: + // + // - OnSystemTxStart + // - OnTxStart + // - OnTxEnd + // - OnSystemTxEnd + // + // This event flow enables transactions to be traced correctly with just OnTxStart/End being set but also + // enables special routing of those transactions by having OnSystemTxStart/End defined and keeping a special + // system state to do something different when OnTxEnd is called. + OnSystemTxEndHook func() /* - State events - @@ -193,7 +225,9 @@ type Hooks struct { OnSystemCallStart OnSystemCallStartHook OnSystemCallEnd OnSystemCallEndHook - OnSystemTxEnd OnSystemTxEndHook + OnSystemTxStart OnSystemTxStartHook + OnSystemTxEnd OnSystemTxEndHook + OnSystemTxFixIntrinsicGas OnSystemTxFixIntrinsicGasHook // State events OnBalanceChange BalanceChangeHook @@ -252,6 +286,15 @@ 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 + + // BSC specific balance changes + + // BalanceDecreaseBSCDistributeReward is a balance change that decreases system address' balance and happens + // when BSC is distributing rewards to validator. + BalanceDecreaseBSCDistributeReward BalanceChangeReason = 210 + // BalanceIncreaseBSCDistributeReward is a balance change that increases the block validator's balance and + // happens when BSC is distributing rewards to validator. + BalanceIncreaseBSCDistributeReward BalanceChangeReason = 211 ) // GasChangeReason is used to indicate the reason for a gas change, useful diff --git a/eth/handler_test.go b/eth/handler_test.go index 060b4a17d0..159841a54f 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/trie" @@ -234,13 +235,13 @@ func (c *mockParlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers [] } func (c *mockParlia) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, _ *[]*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal, - _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64) (err error) { + _ *[]*types.Receipt, _ *[]*types.Transaction, _ *uint64, tracer *tracing.Hooks) (err error) { return } -func (c *mockParlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) { +func (c *mockParlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, error) { // Finalize block - c.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil) + c.Finalize(chain, header, state, &body.Transactions, body.Uncles, body.Withdrawals, nil, nil, nil, tracer) // Assign the final state root to header. header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 8209033f58..e846e851f3 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -1198,8 +1198,8 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor if err != nil { return nil, fmt.Errorf("tracing failed: %w", err) } - if tracer.OnSystemTxEnd != nil { - tracer.OnSystemTxEnd(intrinsicGas) + if tracer.OnSystemTxFixIntrinsicGas != nil { + tracer.OnSystemTxFixIntrinsicGas(intrinsicGas) } return tracer.GetResult() } diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index fc3c2c51fa..3c5baf7473 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -134,11 +134,11 @@ func NewStructLogger(cfg *Config) *StructLogger { func (l *StructLogger) Hooks() *tracing.Hooks { return &tracing.Hooks{ - OnTxStart: l.OnTxStart, - OnTxEnd: l.OnTxEnd, - OnExit: l.OnExit, - OnOpcode: l.OnOpcode, - OnSystemTxEnd: l.OnSystemTxEnd, + OnTxStart: l.OnTxStart, + OnTxEnd: l.OnTxEnd, + OnExit: l.OnExit, + OnOpcode: l.OnOpcode, + OnSystemTxFixIntrinsicGas: l.OnSystemTxFixIntrinsicGas, } } @@ -274,7 +274,7 @@ func (l *StructLogger) OnTxEnd(receipt *types.Receipt, err error) { } } -func (l *StructLogger) OnSystemTxEnd(intrinsicGas uint64) { +func (l *StructLogger) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) { l.usedGas -= intrinsicGas } diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index eef89cbc03..cf016fab5d 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -132,12 +132,12 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, } return &tracers.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.OnTxStart, - OnTxEnd: t.OnTxEnd, - OnEnter: t.OnEnter, - OnExit: t.OnExit, - OnLog: t.OnLog, - OnSystemTxEnd: t.OnSystemTxEnd, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnLog: t.OnLog, + OnSystemTxFixIntrinsicGas: t.OnSystemTxFixIntrinsicGas, }, GetResult: t.GetResult, Stop: t.Stop, @@ -235,7 +235,7 @@ func (t *callTracer) OnTxEnd(receipt *types.Receipt, err error) { } } -func (t *callTracer) OnSystemTxEnd(intrinsicGas uint64) { +func (t *callTracer) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) { t.callstack[0].GasUsed -= intrinsicGas } diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go index e08e3296d7..6dea65aebf 100644 --- a/eth/tracers/native/call_flat.go +++ b/eth/tracers/native/call_flat.go @@ -217,8 +217,8 @@ func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) { t.tracer.OnTxEnd(receipt, err) } -func (t *flatCallTracer) OnSystemTxEnd(intrinsicGas uint64) { - t.tracer.OnSystemTxEnd(intrinsicGas) +func (t *flatCallTracer) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) { + t.tracer.OnSystemTxFixIntrinsicGas(intrinsicGas) } // GetResult returns an empty json object. diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go index 70a0e0f69d..9e4875b747 100644 --- a/eth/tracers/native/mux.go +++ b/eth/tracers/native/mux.go @@ -59,19 +59,19 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, e t := &muxTracer{names: names, tracers: objects} return &tracers.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.OnTxStart, - OnTxEnd: t.OnTxEnd, - OnEnter: t.OnEnter, - OnExit: t.OnExit, - OnOpcode: t.OnOpcode, - OnFault: t.OnFault, - OnGasChange: t.OnGasChange, - OnBalanceChange: t.OnBalanceChange, - OnNonceChange: t.OnNonceChange, - OnCodeChange: t.OnCodeChange, - OnStorageChange: t.OnStorageChange, - OnLog: t.OnLog, - OnSystemTxEnd: t.OnSystemTxEnd, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, + OnGasChange: t.OnGasChange, + OnBalanceChange: t.OnBalanceChange, + OnNonceChange: t.OnNonceChange, + OnCodeChange: t.OnCodeChange, + OnStorageChange: t.OnStorageChange, + OnLog: t.OnLog, + OnSystemTxFixIntrinsicGas: t.OnSystemTxFixIntrinsicGas, }, GetResult: t.GetResult, Stop: t.Stop, @@ -174,9 +174,9 @@ func (t *muxTracer) OnLog(log *types.Log) { } } -func (t *muxTracer) OnSystemTxEnd(intrinsicGas uint64) { +func (t *muxTracer) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) { for _, t := range t.tracers { - t.OnSystemTxEnd(intrinsicGas) + t.OnSystemTxFixIntrinsicGas(intrinsicGas) } } diff --git a/eth/tracers/native/noop.go b/eth/tracers/native/noop.go index 5fd99d4da2..a42670ede9 100644 --- a/eth/tracers/native/noop.go +++ b/eth/tracers/native/noop.go @@ -39,19 +39,19 @@ func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, er t := &noopTracer{} return &tracers.Tracer{ Hooks: &tracing.Hooks{ - OnTxStart: t.OnTxStart, - OnTxEnd: t.OnTxEnd, - OnEnter: t.OnEnter, - OnExit: t.OnExit, - OnOpcode: t.OnOpcode, - OnFault: t.OnFault, - OnGasChange: t.OnGasChange, - OnBalanceChange: t.OnBalanceChange, - OnNonceChange: t.OnNonceChange, - OnCodeChange: t.OnCodeChange, - OnStorageChange: t.OnStorageChange, - OnLog: t.OnLog, - OnSystemTxEnd: t.OnSystemTxEnd, + OnTxStart: t.OnTxStart, + OnTxEnd: t.OnTxEnd, + OnEnter: t.OnEnter, + OnExit: t.OnExit, + OnOpcode: t.OnOpcode, + OnFault: t.OnFault, + OnGasChange: t.OnGasChange, + OnBalanceChange: t.OnBalanceChange, + OnNonceChange: t.OnNonceChange, + OnCodeChange: t.OnCodeChange, + OnStorageChange: t.OnStorageChange, + OnLog: t.OnLog, + OnSystemTxFixIntrinsicGas: t.OnSystemTxFixIntrinsicGas, }, GetResult: t.GetResult, Stop: t.Stop, @@ -89,7 +89,7 @@ func (*noopTracer) OnStorageChange(a common.Address, k, prev, new common.Hash) { func (*noopTracer) OnLog(log *types.Log) {} -func (*noopTracer) OnSystemTxEnd(intrinsicGas uint64) {} +func (*noopTracer) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) {} // GetResult returns an empty json object. func (t *noopTracer) GetResult() (json.RawMessage, error) { diff --git a/miner/worker.go b/miner/worker.go index d193ccca3c..ac76731819 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1166,7 +1166,7 @@ func (w *worker) generateWork(params *generateParams, witness bool) *newPayloadR } body := types.Body{Transactions: work.txs, Withdrawals: params.withdrawals} fees := work.state.GetBalance(consensus.SystemAddress) - block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, &body, work.receipts) + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, &body, work.receipts, nil) if err != nil { return &newPayloadResult{err: err} } @@ -1429,7 +1429,7 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti if env.header.EmptyWithdrawalsHash() { body.Withdrawals = make([]*types.Withdrawal, 0) } - block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(env.header), env.state, &body, env.receipts) + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(env.header), env.state, &body, env.receipts, nil) if err != nil { return err }