mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 15:46:43 +00:00
emit err on tx validation failure
This commit is contained in:
parent
5466fa3133
commit
2faf3dbfd6
20 changed files with 69 additions and 26 deletions
|
|
@ -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++
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue