emit err on tx validation failure

This commit is contained in:
Sina Mahmoodi 2023-07-26 20:07:13 +02:00
parent 5466fa3133
commit 2faf3dbfd6
20 changed files with 69 additions and 26 deletions

View file

@ -191,6 +191,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
gaspool.SetGas(prevGas)
tracer.CaptureTxEnd(nil, err)
continue
}
includedTxs = append(includedTxs, tx)
@ -232,7 +233,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
//receipt.BlockNumber
receipt.TransactionIndex = uint(txIndex)
receipts = append(receipts, receipt)
tracer.CaptureTxEnd(receipt)
tracer.CaptureTxEnd(receipt, nil)
}
txIndex++

View file

@ -108,11 +108,14 @@ 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) {
var receipt *types.Receipt
var (
receipt *types.Receipt
err error
)
if evm.Config.Tracer != nil {
evm.Config.Tracer.CaptureTxStart(evm, tx)
defer func() {
evm.Config.Tracer.CaptureTxEnd(receipt)
evm.Config.Tracer.CaptureTxEnd(receipt, err)
}()
}
// Create a new context to be used in the EVM environment.

View file

@ -31,7 +31,7 @@ import (
type EVMLogger interface {
// Transaction level
CaptureTxStart(evm *EVM, tx *types.Transaction)
CaptureTxEnd(receipt *types.Receipt)
CaptureTxEnd(receipt *types.Receipt, err error)
// Top call frame
CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
CaptureEnd(output []byte, gasUsed uint64, err error)

View file

@ -116,6 +116,9 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
sender = vm.AccountRef(cfg.Origin)
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
)
if cfg.EVMConfig.Tracer != nil {
cfg.EVMConfig.Tracer.CaptureTxStart(vmenv, types.NewTx(&types.LegacyTx{To: &address, Data: input, Value: cfg.Value, Gas: cfg.GasLimit}))
}
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)
@ -149,6 +152,9 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
sender = vm.AccountRef(cfg.Origin)
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
)
if cfg.EVMConfig.Tracer != nil {
cfg.EVMConfig.Tracer.CaptureTxStart(vmenv, types.NewTx(&types.LegacyTx{Data: input, Value: cfg.Value, Gas: cfg.GasLimit}))
}
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)
@ -177,6 +183,9 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
statedb = cfg.State
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
)
if cfg.EVMConfig.Tracer != nil {
cfg.EVMConfig.Tracer.CaptureTxStart(vmenv, types.NewTx(&types.LegacyTx{To: &address, Data: input, Value: cfg.Value, Gas: cfg.GasLimit}))
}
// Execute the preparatory steps for state transition which includes:
// - prepare accessList(post-berlin)
// - reset transient storage(eip 1153)

View file

@ -811,7 +811,7 @@ func TestRuntimeJSTracer(t *testing.T) {
byte(vm.PUSH1), 0,
byte(vm.RETURN),
}
depressedCode := []byte{
suicideCode := []byte{
byte(vm.PUSH1), 0xaa,
byte(vm.SELFDESTRUCT),
}
@ -824,7 +824,7 @@ func TestRuntimeJSTracer(t *testing.T) {
statedb.SetCode(common.HexToAddress("0xcc"), calleeCode)
statedb.SetCode(common.HexToAddress("0xdd"), calleeCode)
statedb.SetCode(common.HexToAddress("0xee"), calleeCode)
statedb.SetCode(common.HexToAddress("0xff"), depressedCode)
statedb.SetCode(common.HexToAddress("0xff"), suicideCode)
tracer, err := tracers.DefaultDirectory.New(jsTracer, new(tracers.Context), nil)
if err != nil {

View file

@ -792,7 +792,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
statedb.SetTxContext(tx.Hash(), i)
vmConf.Tracer.CaptureTxStart(vmenv, tx)
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}, err)
if writer != nil {
writer.Flush()
}
@ -976,10 +976,11 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
tracer.CaptureTxStart(vmenv, tx)
res, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit))
if err != nil {
tracer.CaptureTxEnd(nil, err)
return nil, fmt.Errorf("tracing failed: %w", err)
}
r := &types.Receipt{GasUsed: res.UsedGas}
tracer.CaptureTxEnd(r)
tracer.CaptureTxEnd(r, nil)
return tracer.GetResult()
}

View file

@ -156,7 +156,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected.
res, err := tracer.GetResult()
if err != nil {
@ -382,7 +382,7 @@ func TestInternals(t *testing.T) {
if err != nil {
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
}
tc.tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
tc.tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected
res, err := tc.tracer.GetResult()
if err != nil {

View file

@ -119,7 +119,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
if err != nil {
return fmt.Errorf("failed to execute transaction: %v", err)
}
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the etalon
res, err := tracer.GetResult()

View file

@ -125,7 +125,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas})
tracer.CaptureTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected
res, err := tracer.GetResult()
if err != nil {

View file

@ -229,7 +229,14 @@ func (t *jsTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
// CaptureTxEnd implements the Tracer interface and is invoked at the end of
// transaction processing.
func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt) {
func (t *jsTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
if err != nil {
// Don't override vm error
if _, ok := t.ctx["error"]; !ok {
t.ctx["error"] = t.vm.ToValue(err.Error())
}
return
}
t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed)
}

View file

@ -79,7 +79,7 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
ret, err := env.Interpreter().Run(contract, []byte{}, false)
tracer.CaptureEnd(ret, startGas-contract.Gas, err)
// Rest gas assumes no refund
tracer.CaptureTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas})
tracer.CaptureTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
if err != nil {
return nil, err
}
@ -184,6 +184,8 @@ func TestHaltBetweenSteps(t *testing.T) {
scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
}
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
tracer.CaptureTxStart(env, types.NewTx(&types.LegacyTx{}))
tracer.CaptureStart(common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
timeout := errors.New("stahp")
@ -204,6 +206,8 @@ func TestNoStepExec(t *testing.T) {
if err != nil {
t.Fatal(err)
}
env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
tracer.CaptureTxStart(env, types.NewTx(&types.LegacyTx{}))
tracer.CaptureStart(common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0))
tracer.CaptureEnd(nil, 0, nil)
ret, err := tracer.GetResult()

View file

@ -174,7 +174,7 @@ func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
func (*AccessListTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt) {}
func (*AccessListTracer) CaptureTxEnd(receipt *types.Receipt, err error) {}
func (*AccessListTracer) OnBalanceChange(a common.Address, prev, new *big.Int) {}

View file

@ -269,7 +269,14 @@ 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, err error) {
if err != nil {
// Don't override vm error
if l.err == nil {
l.err = err
}
return
}
l.usedGas = receipt.GasUsed
}
@ -417,7 +424,7 @@ func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
func (*mdLogger) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
func (*mdLogger) CaptureTxEnd(receipt *types.Receipt) {}
func (*mdLogger) CaptureTxEnd(receipt *types.Receipt, err error) {}
func (*mdLogger) OnBalanceChange(a common.Address, prev, new *big.Int) {}

View file

@ -106,7 +106,7 @@ 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, err error) {}
func (*JSONLogger) OnBalanceChange(a common.Address, prev, new *big.Int) {}

View file

@ -200,7 +200,11 @@ func (t *callTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
t.gasLimit = tx.Gas()
}
func (t *callTracer) CaptureTxEnd(receipt *types.Receipt) {
func (t *callTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
// Error happened during tx validation.
if err != nil {
return
}
t.callstack[0].GasUsed = receipt.GasUsed
if t.config.WithLog {
// Logs are not emitted when the call fails

View file

@ -207,8 +207,8 @@ func (t *flatCallTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
t.activePrecompiles = vm.ActivePrecompiles(rules)
}
func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt) {
t.tracer.CaptureTxEnd(receipt)
func (t *flatCallTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
t.tracer.CaptureTxEnd(receipt, err)
}
// GetResult returns an empty json object.

View file

@ -123,9 +123,9 @@ func (t *muxTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
}
}
func (t *muxTracer) CaptureTxEnd(receipt *types.Receipt) {
func (t *muxTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
for _, t := range t.tracers {
t.CaptureTxEnd(receipt)
t.CaptureTxEnd(receipt, err)
}
}

View file

@ -176,10 +176,13 @@ func (t *prestateTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
}
}
func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt) {
func (t *prestateTracer) CaptureTxEnd(receipt *types.Receipt, err error) {
if !t.config.DiffMode {
return
}
if err != nil {
return
}
for addr, state := range t.pre {
// The deleted account's state is pruned from `post` but kept in `pre`

View file

@ -72,7 +72,7 @@ func (t *NoopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
func (*NoopTracer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {}
func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt) {}
func (*NoopTracer) CaptureTxEnd(receipt *types.Receipt, err error) {}
func (*NoopTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason state.BalanceChangeReason) {
}

View file

@ -62,7 +62,11 @@ func (p *Printer) CaptureTxStart(env *vm.EVM, tx *types.Transaction) {
}
func (p *Printer) CaptureTxEnd(receipt *types.Receipt) {
func (p *Printer) CaptureTxEnd(receipt *types.Receipt, err error) {
if err != nil {
fmt.Printf("CaptureTxEnd err: %v\n", err)
return
}
buf, err := json.Marshal(receipt)
if err != nil {
fmt.Printf("err: %v\n", err)