core,eth: implement tx-level hooks for tracers (#24510)

* core,eth: add empty tx logger hooks

* core,eth: add initial and remaining gas to tx hooks

* store tx gasLimit in js tracer

* use gasLimit to compute intrinsic cost for js tracer

* re-use rules in transitiondb

* rm logs

* rm logs

* Mv some fields from Start to TxStart

* simplify sender lookup in prestate tracer

* mv env to TxStart

* Revert "mv env to TxStart"

This reverts commit 656939634b9aff19f55a1cd167345faf8b1ec310.

* Revert "simplify sender lookup in prestate tracer"

This reverts commit ab65bce48007cab99e68232e7aac2fe008338d50.

* Revert "Mv some fields from Start to TxStart"

This reverts commit aa50d3d9b2559addc80df966111ef5fb5d0c1b6b.

* fix intrinsic gas for prestate tracer

* add comments

* refactor

* fix test case

* simplify consumedGas calc in prestate tracer
This commit is contained in:
Sina Mahmoodi
2022-03-31 11:51:44 +02:00
committed by GitHub
parent da16d089c0
commit 3fd16af5a9
11 changed files with 83 additions and 40 deletions

View File

@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
tracers2 "github.com/ethereum/go-ethereum/eth/tracers"
@ -419,6 +418,7 @@ type jsTracer struct {
activePrecompiles []common.Address // Updated on CaptureStart based on given rules
traceSteps bool // When true, will invoke step() on each opcode
traceCallFrames bool // When true, will invoke enter() and exit() js funcs
gasLimit uint64 // Amount of gas bought for the whole tx
}
// New instantiates a new tracer instance. code specifies a Javascript snippet,
@ -679,7 +679,18 @@ func wrapError(context string, err error) error {
return fmt.Errorf("%v in server-side tracer function '%v'", err, context)
}
// CaptureStart implements the Tracer interface to initialize the tracing operation.
// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
// transaction processing.
func (jst *jsTracer) CaptureTxStart(gasLimit uint64) {
jst.gasLimit = gasLimit
}
// CaptureTxStart implements the Tracer interface and is invoked at the end of
// transaction processing.
func (*jsTracer) CaptureTxEnd(restGas uint64) {}
// CaptureStart implements the Tracer interface and is invoked before executing the
// top-level call frame of a transaction.
func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
jst.env = env
jst.ctx["type"] = "CALL"
@ -700,14 +711,8 @@ func (jst *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Ad
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil)
jst.activePrecompiles = vm.ActivePrecompiles(rules)
// Compute intrinsic gas
isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber)
intrinsicGas, err := core.IntrinsicGas(input, nil, jst.ctx["type"] == "CREATE", isHomestead, isIstanbul)
if err != nil {
return
}
jst.ctx["intrinsicGas"] = intrinsicGas
// Intrinsic costs are the only things reduced from initial gas to this point
jst.ctx["intrinsicGas"] = jst.gasLimit - gas
}
// CaptureState implements the Tracer interface to trace a single step of VM execution.
@ -760,7 +765,7 @@ func (jst *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, sco
}
}
// CaptureEnd is called after the call finishes to finalize the tracing.
// CaptureEnd is called after the top-level call finishes.
func (jst *jsTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {
jst.ctx["output"] = output
jst.ctx["time"] = t.String()

View File

@ -62,15 +62,19 @@ func testCtx() *vmContext {
func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
var (
env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
gasLimit uint64 = 31000
startGas uint64 = 10000
value = big.NewInt(0)
contract = vm.NewContract(account{}, account{}, value, startGas)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
tracer.CaptureTxStart(gasLimit)
tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
ret, err := env.Interpreter().Run(contract, []byte{}, false)
tracer.CaptureEnd(ret, startGas-contract.Gas, 1, err)
// Rest gas assumes no refund
tracer.CaptureTxEnd(startGas - contract.Gas)
if err != nil {
return nil, err
}