mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 01:13:45 +00:00
pass env in TxStart
This commit is contained in:
parent
619ac2948c
commit
54171ee4a8
18 changed files with 97 additions and 94 deletions
|
|
@ -112,7 +112,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) {
|
||||||
var receipt *types.Receipt
|
var receipt *types.Receipt
|
||||||
if evm.Config.Tracer != nil {
|
if evm.Config.Tracer != nil {
|
||||||
evm.Config.Tracer.CaptureTxStart(tx)
|
evm.Config.Tracer.CaptureTxStart(evm, tx)
|
||||||
defer func() {
|
defer func() {
|
||||||
evm.Config.Tracer.CaptureTxEnd(receipt)
|
evm.Config.Tracer.CaptureTxEnd(receipt)
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
// Calling a non existing account, don't do anything, but ping the tracer
|
// Calling a non existing account, don't do anything, but ping the tracer
|
||||||
if debug {
|
if debug {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
||||||
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
|
evm.Config.Tracer.CaptureEnd(ret, 0, nil)
|
||||||
} else {
|
} else {
|
||||||
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
|
||||||
|
|
@ -208,7 +208,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
// Capture the tracer start/end events in debug mode
|
// Capture the tracer start/end events in debug mode
|
||||||
if debug {
|
if debug {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value)
|
evm.Config.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
||||||
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
defer func(startGas uint64) { // Lazy evaluation of the parameters
|
||||||
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
|
evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
|
||||||
}(gas)
|
}(gas)
|
||||||
|
|
@ -456,7 +456,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||||
|
|
||||||
if evm.Config.Tracer != nil {
|
if evm.Config.Tracer != nil {
|
||||||
if evm.depth == 0 {
|
if evm.depth == 0 {
|
||||||
evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value)
|
evm.Config.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value)
|
||||||
} else {
|
} else {
|
||||||
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
|
evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,10 @@ import (
|
||||||
// if you need to retain them beyond the current call.
|
// if you need to retain them beyond the current call.
|
||||||
type EVMLogger interface {
|
type EVMLogger interface {
|
||||||
// Transaction level
|
// Transaction level
|
||||||
CaptureTxStart(tx *types.Transaction)
|
CaptureTxStart(evm *EVM, tx *types.Transaction)
|
||||||
CaptureTxEnd(receipt *types.Receipt)
|
CaptureTxEnd(receipt *types.Receipt)
|
||||||
// Top call frame
|
// Top call frame
|
||||||
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureEnd(output []byte, gasUsed uint64, err error)
|
CaptureEnd(output []byte, gasUsed uint64, err error)
|
||||||
// Rest of call frames
|
// Rest of call frames
|
||||||
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
vmConf.Tracer.CaptureTxStart(tx)
|
vmConf.Tracer.CaptureTxStart(vmenv, tx)
|
||||||
vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit))
|
||||||
vmConf.Tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
|
vmConf.Tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
|
||||||
if writer != nil {
|
if writer != nil {
|
||||||
|
|
@ -973,7 +973,7 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
|
||||||
|
|
||||||
// Call Prepare to clear out the statedb access list
|
// Call Prepare to clear out the statedb access list
|
||||||
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
||||||
tracer.CaptureTxStart(tx)
|
tracer.CaptureTxStart(vmenv, tx)
|
||||||
res, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit))
|
res, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
tracer.CaptureTxStart(tx)
|
tracer.CaptureTxStart(evm, tx)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to execute transaction: %v", err)
|
t.Fatalf("failed to execute transaction: %v", err)
|
||||||
|
|
@ -266,17 +266,13 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
||||||
|
|
||||||
func TestInternals(t *testing.T) {
|
func TestInternals(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
config = params.AllEthashProtocolChanges
|
config = params.MainnetChainConfig
|
||||||
to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
|
to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
|
||||||
originHex = "0x71562b71999873db5b286df957af199ec94617f7"
|
originHex = "0x71562b71999873db5b286df957af199ec94617f7"
|
||||||
origin = common.HexToAddress(originHex)
|
origin = common.HexToAddress(originHex)
|
||||||
signer = types.LatestSigner(config)
|
signer = types.LatestSigner(config)
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
txContext = vm.TxContext{
|
context = vm.BlockContext{
|
||||||
Origin: origin,
|
|
||||||
GasPrice: big.NewInt(1),
|
|
||||||
}
|
|
||||||
context = vm.BlockContext{
|
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
Coinbase: common.Address{},
|
Coinbase: common.Address{},
|
||||||
|
|
@ -284,6 +280,7 @@ func TestInternals(t *testing.T) {
|
||||||
Time: 5,
|
Time: 5,
|
||||||
Difficulty: big.NewInt(0x30000),
|
Difficulty: big.NewInt(0x30000),
|
||||||
GasLimit: uint64(6000000),
|
GasLimit: uint64(6000000),
|
||||||
|
BaseFee: new(big.Int),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer {
|
mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer {
|
||||||
|
|
@ -349,7 +346,7 @@ func TestInternals(t *testing.T) {
|
||||||
byte(vm.LOG0),
|
byte(vm.LOG0),
|
||||||
},
|
},
|
||||||
tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)),
|
tracer: mkTracer("prestateTracer", json.RawMessage(`{ "withLog": true }`)),
|
||||||
want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52640350"}}`, originHex),
|
want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex),
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||||
|
|
@ -362,21 +359,25 @@ func TestInternals(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, false)
|
}, false)
|
||||||
statedb.SetLogger(tc.tracer)
|
statedb.SetLogger(tc.tracer)
|
||||||
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
|
|
||||||
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
|
||||||
To: &to,
|
To: &to,
|
||||||
Value: big.NewInt(0),
|
Value: big.NewInt(0),
|
||||||
Gas: 50000,
|
Gas: 50000,
|
||||||
GasPrice: big.NewInt(0),
|
GasPrice: new(big.Int),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err)
|
t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err)
|
||||||
}
|
}
|
||||||
|
txContext := vm.TxContext{
|
||||||
|
Origin: origin,
|
||||||
|
GasPrice: tx.GasPrice(),
|
||||||
|
}
|
||||||
|
evm := vm.NewEVM(context, txContext, statedb, config, vm.Config{Tracer: tc.tracer})
|
||||||
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
t.Fatalf("test %v: failed to create message: %v", tc.name, err)
|
||||||
}
|
}
|
||||||
tc.tracer.CaptureTxStart(tx)
|
tc.tracer.CaptureTxStart(evm, tx)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
|
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
tracer.CaptureTxStart(tx)
|
tracer.CaptureTxStart(evm, tx)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to execute transaction: %v", err)
|
return fmt.Errorf("failed to execute transaction: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
}
|
}
|
||||||
tracer.CaptureTxStart(tx)
|
tracer.CaptureTxStart(evm, tx)
|
||||||
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to execute transaction: %v", err)
|
t.Fatalf("failed to execute transaction: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ type jsTracer struct {
|
||||||
activePrecompiles []common.Address // List of active precompiles at current block
|
activePrecompiles []common.Address // List of active precompiles at current block
|
||||||
traceStep bool // True if tracer object exposes a `step()` method
|
traceStep bool // True if tracer object exposes a `step()` method
|
||||||
traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods
|
traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods
|
||||||
gasLimit uint64 // Amount of gas bought for the whole tx
|
|
||||||
err error // Any error that should stop tracing
|
err error // Any error that should stop tracing
|
||||||
obj *goja.Object // Trace object
|
obj *goja.Object // Trace object
|
||||||
|
|
||||||
|
|
@ -215,8 +214,17 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracer
|
||||||
|
|
||||||
// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
|
// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
|
||||||
// transaction processing.
|
// transaction processing.
|
||||||
func (t *jsTracer) CaptureTxStart(tx *types.Transaction) {
|
func (t *jsTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
t.gasLimit = tx.Gas()
|
t.env = env
|
||||||
|
// Need statedb access for db object
|
||||||
|
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
|
||||||
|
t.dbValue = db.setupObject()
|
||||||
|
// Update list of precompiles based on current block
|
||||||
|
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
|
||||||
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
|
t.ctx["block"] = t.vm.ToValue(t.env.Context.BlockNumber.Uint64())
|
||||||
|
t.ctx["gasPrice"] = t.vm.ToValue(t.env.TxContext.GasPrice)
|
||||||
|
t.ctx["gas"] = t.vm.ToValue(tx.Gas())
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureTxEnd implements the Tracer interface and is invoked at the end of
|
// CaptureTxEnd implements the Tracer interface and is invoked at the end of
|
||||||
|
|
@ -226,10 +234,7 @@ func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the Tracer interface to initialize the tracing operation.
|
// CaptureStart implements the Tracer interface to initialize the tracing operation.
|
||||||
func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *jsTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
t.env = env
|
|
||||||
db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
|
|
||||||
t.dbValue = db.setupObject()
|
|
||||||
if create {
|
if create {
|
||||||
t.ctx["type"] = t.vm.ToValue("CREATE")
|
t.ctx["type"] = t.vm.ToValue("CREATE")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -238,18 +243,12 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
|
||||||
t.ctx["from"] = t.vm.ToValue(from.Bytes())
|
t.ctx["from"] = t.vm.ToValue(from.Bytes())
|
||||||
t.ctx["to"] = t.vm.ToValue(to.Bytes())
|
t.ctx["to"] = t.vm.ToValue(to.Bytes())
|
||||||
t.ctx["input"] = t.vm.ToValue(input)
|
t.ctx["input"] = t.vm.ToValue(input)
|
||||||
t.ctx["gas"] = t.vm.ToValue(t.gasLimit)
|
|
||||||
t.ctx["gasPrice"] = t.vm.ToValue(env.TxContext.GasPrice)
|
|
||||||
valueBig, err := t.toBig(t.vm, value.String())
|
valueBig, err := t.toBig(t.vm, value.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.err = err
|
t.err = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.ctx["value"] = valueBig
|
t.ctx["value"] = valueBig
|
||||||
t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64())
|
|
||||||
// Update list of precompiles based on current block
|
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
|
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState implements the Tracer interface to trace a single step of VM execution.
|
// CaptureState implements the Tracer interface to trace a single step of VM execution.
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AccessListTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (a *AccessListTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
||||||
|
|
@ -172,7 +172,7 @@ func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureTxStart(tx *types.Transaction) {}
|
func (*AccessListTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt) {}
|
func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,7 @@ func (l *StructLogger) Reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (l *StructLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
l.env = env
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState logs a new structured log message and pushes it out to the environment
|
// CaptureState logs a new structured log message and pushes it out to the environment
|
||||||
|
|
@ -265,7 +264,9 @@ func (l *StructLogger) Stop(err error) {
|
||||||
l.interrupt.Store(true)
|
l.interrupt.Store(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *StructLogger) CaptureTxStart(tx *types.Transaction) {}
|
func (l *StructLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
|
l.env = env
|
||||||
|
}
|
||||||
|
|
||||||
func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt) {
|
func (l *StructLogger) CaptureTxEnd(receipt *types.Receipt) {
|
||||||
l.usedGas = receipt.GasUsed
|
l.usedGas = receipt.GasUsed
|
||||||
|
|
@ -356,8 +357,7 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *mdLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
t.env = env
|
|
||||||
if !create {
|
if !create {
|
||||||
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
|
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
|
||||||
from.String(), to.String(),
|
from.String(), to.String(),
|
||||||
|
|
@ -413,7 +413,7 @@ func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Ad
|
||||||
|
|
||||||
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
func (*mdLogger) CaptureTxStart(tx *types.Transaction) {}
|
func (*mdLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
|
||||||
|
|
||||||
func (*mdLogger) CaptureTxEnd(receipt *types.Receipt) {}
|
func (*mdLogger) CaptureTxEnd(receipt *types.Receipt) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,7 @@ func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (l *JSONLogger) CaptureStart(from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
l.env = env
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||||
|
|
@ -103,7 +102,9 @@ func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureTxStart(tx *types.Transaction) {}
|
func (l *JSONLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
|
l.env = env
|
||||||
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureTxEnd(receipt *types.Receipt) {}
|
func (l *JSONLogger) CaptureTxEnd(receipt *types.Receipt) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
)
|
)
|
||||||
|
|
@ -47,6 +48,7 @@ func init() {
|
||||||
// }
|
// }
|
||||||
type fourByteTracer struct {
|
type fourByteTracer struct {
|
||||||
tracers.NoopTracer
|
tracers.NoopTracer
|
||||||
|
env *vm.EVM
|
||||||
ids map[string]int // ids aggregates the 4byte ids found
|
ids map[string]int // ids aggregates the 4byte ids found
|
||||||
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
||||||
reason error // Textual reason for the interruption
|
reason error // Textual reason for the interruption
|
||||||
|
|
@ -78,13 +80,16 @@ func (t *fourByteTracer) store(id []byte, size int) {
|
||||||
t.ids[key] += 1
|
t.ids[key] += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
func (t *fourByteTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
t.env = env
|
||||||
// Update list of precompiles based on current block
|
// Update list of precompiles based on current block
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
|
rules := t.env.ChainConfig().Rules(t.env.Context.BlockNumber, t.env.Context.Random != nil, t.env.Context.Time)
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
|
}
|
||||||
|
|
||||||
// Save the outer calldata also
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
|
func (t *fourByteTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
|
// Save the outer calldata
|
||||||
if len(input) >= 4 {
|
if len(input) >= 4 {
|
||||||
t.store(input[0:4], len(input)-4)
|
t.store(input[0:4], len(input)-4)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *callTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
toCopy := to
|
toCopy := to
|
||||||
t.callstack[0] = callFrame{
|
t.callstack[0] = callFrame{
|
||||||
Type: vm.CALL,
|
Type: vm.CALL,
|
||||||
|
|
@ -196,7 +196,7 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *callTracer) CaptureTxStart(tx *types.Transaction) {
|
func (t *callTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
t.gasLimit = tx.Gas()
|
t.gasLimit = tx.Gas()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,11 +146,8 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *flatCallTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
t.tracer.CaptureStart(env, from, to, create, input, gas, value)
|
t.tracer.CaptureStart(from, to, create, input, gas, value)
|
||||||
// Update list of precompiles based on current block
|
|
||||||
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
|
|
||||||
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
|
|
@ -203,8 +200,11 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *flatCallTracer) CaptureTxStart(tx *types.Transaction) {
|
func (t *flatCallTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
t.tracer.CaptureTxStart(tx)
|
t.tracer.CaptureTxStart(env, tx)
|
||||||
|
// Update list of precompiles based on current block
|
||||||
|
rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
|
||||||
|
t.activePrecompiles = vm.ActivePrecompiles(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt) {
|
func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt) {
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,9 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, er
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (t *muxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *muxTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
t.CaptureStart(env, from, to, create, input, gas, value)
|
t.CaptureStart(from, to, create, input, gas, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,9 +116,9 @@ func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *muxTracer) CaptureTxStart(tx *types.Transaction) {
|
func (t *muxTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
for _, t := range t.tracers {
|
for _, t := range t.tracers {
|
||||||
t.CaptureTxStart(tx)
|
t.CaptureTxStart(env, tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package native
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
|
@ -61,7 +62,6 @@ type prestateTracer struct {
|
||||||
post state
|
post state
|
||||||
create bool
|
create bool
|
||||||
to common.Address
|
to common.Address
|
||||||
gasLimit uint64 // Amount of gas bought for the whole tx
|
|
||||||
config prestateTracerConfig
|
config prestateTracerConfig
|
||||||
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
interrupt atomic.Bool // Atomic flag to signal execution interruption
|
||||||
reason error // Textual reason for the interruption
|
reason error // Textual reason for the interruption
|
||||||
|
|
@ -90,31 +90,7 @@ func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *prestateTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
t.env = env
|
|
||||||
t.create = create
|
|
||||||
t.to = to
|
|
||||||
|
|
||||||
t.lookupAccount(from)
|
|
||||||
t.lookupAccount(to)
|
|
||||||
t.lookupAccount(env.Context.Coinbase)
|
|
||||||
|
|
||||||
// The recipient balance includes the value transferred.
|
|
||||||
toBal := new(big.Int).Sub(t.pre[to].Balance, value)
|
|
||||||
t.pre[to].Balance = toBal
|
|
||||||
|
|
||||||
// The sender balance is after reducing: value and gasLimit.
|
|
||||||
// We need to re-add them to get the pre-tx balance.
|
|
||||||
fromBal := new(big.Int).Set(t.pre[from].Balance)
|
|
||||||
gasPrice := env.TxContext.GasPrice
|
|
||||||
consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit))
|
|
||||||
fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
|
|
||||||
t.pre[from].Balance = fromBal
|
|
||||||
t.pre[from].Nonce--
|
|
||||||
|
|
||||||
if create && t.config.DiffMode {
|
|
||||||
t.created[to] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
|
|
@ -175,8 +151,29 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *prestateTracer) CaptureTxStart(tx *types.Transaction) {
|
func (t *prestateTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
t.gasLimit = tx.Gas()
|
t.env = env
|
||||||
|
signer := types.MakeSigner(env.ChainConfig(), env.Context.BlockNumber, env.Context.Time)
|
||||||
|
from, err := types.Sender(signer, tx)
|
||||||
|
if err != nil {
|
||||||
|
t.Stop(fmt.Errorf("could not recover sender address: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if tx.To() == nil {
|
||||||
|
t.create = true
|
||||||
|
t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from))
|
||||||
|
} else {
|
||||||
|
t.to = *tx.To()
|
||||||
|
t.create = false
|
||||||
|
}
|
||||||
|
|
||||||
|
t.lookupAccount(from)
|
||||||
|
t.lookupAccount(t.to)
|
||||||
|
t.lookupAccount(env.Context.Coinbase)
|
||||||
|
|
||||||
|
if t.create && t.config.DiffMode {
|
||||||
|
t.created[t.to] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt) {
|
func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt) {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func newNoopTracer(ctx *Context, _ json.RawMessage) (Tracer, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (t *NoopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *NoopTracer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
|
|
@ -69,7 +69,7 @@ func (t *NoopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.
|
||||||
func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*NoopTracer) CaptureTxStart(tx *types.Transaction) {}
|
func (*NoopTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
|
||||||
|
|
||||||
func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt) {}
|
func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ func NewPrinter() *Printer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (p *Printer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (p *Printer) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
fmt.Printf("CaptureStart: from=%v, to=%v, create=%v, input=%v, gas=%v, value=%v\n", from, to, create, input, gas, value)
|
fmt.Printf("CaptureStart: from=%v, to=%v, create=%v, input=%v, gas=%v, value=%v\n", from, to, create, input, gas, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ func (p *Printer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||||
fmt.Printf("CaptureExit: output=%v, gasUsed=%v, err=%v\n", output, gasUsed, err)
|
fmt.Printf("CaptureExit: output=%v, gasUsed=%v, err=%v\n", output, gasUsed, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Printer) CaptureTxStart(tx *types.Transaction) {
|
func (p *Printer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
|
||||||
fmt.Printf("CaptureTxStart: tx=%v\n", tx)
|
fmt.Printf("CaptureTxStart: tx=%v\n", tx)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue