diff --git a/eth/tracers/tracer.go b/eth/tracers/tracer.go index dfe855f86977..c9f00d7371ed 100644 --- a/eth/tracers/tracer.go +++ b/eth/tracers/tracer.go @@ -549,7 +549,6 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost // Initialize the context if it wasn't done yet if !jst.inited { jst.ctx["block"] = env.Context.BlockNumber.Uint64() - // Compute intrinsic gas isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber) isIstanbul := env.ChainConfig().IsIstanbul(env.Context.BlockNumber) @@ -562,7 +561,6 @@ func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost return err } jst.ctx["intrinsicGas"] = intrinsicGas - jst.inited = true } // If tracing was interrupted, set the error and stop diff --git a/eth/tracers/tracer_test.go b/eth/tracers/tracer_test.go index 80926c1a7b29..f28e14864bd1 100644 --- a/eth/tracers/tracer_test.go +++ b/eth/tracers/tracer_test.go @@ -17,7 +17,6 @@ package tracers import ( - "bytes" "encoding/json" "errors" "math/big" @@ -61,9 +60,9 @@ func testCtx() *vmContext { func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) { env := vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) - var( + var ( startGas uint64 = 10000 - value = big.NewInt(0) + value = big.NewInt(0) ) contract := vm.NewContract(account{}, account{}, value, startGas) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} @@ -77,87 +76,50 @@ func runTrace(tracer *Tracer, vmctx *vmContext) (json.RawMessage, error) { return tracer.GetResult() } -// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory access -func TestRegressionPanicSlice(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - if _, err = runTrace(tracer, vmctx); err != nil { - t.Fatal(err) - } -} - -// TestRegressionPanicSlice tests that we don't panic on bad arguments to stack peeks -func TestRegressionPanicPeek(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - if _, err = runTrace(tracer, vmctx); err != nil { - t.Fatal(err) - } -} - -// TestRegressionPanicSlice tests that we don't panic on bad arguments to memory getUint -func TestRegressionPanicGetUint(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - if _, err = runTrace(tracer, vmctx); err != nil { - t.Fatal(err) - } -} - -func TestTracing(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - - ret, err := runTrace(tracer, vmctx) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(ret, []byte("3")) { - t.Errorf("Expected return value to be 3, got %s", string(ret)) - } -} - -func TestStack(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - - ret, err := runTrace(tracer, vmctx) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(ret, []byte("[0,1,2]")) { - t.Errorf("Expected return value to be [0,1,2], got %s", string(ret)) - } -} - -func TestOpcodes(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - - ret, err := runTrace(tracer, vmctx) - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(ret, []byte("[\"PUSH1\",\"PUSH1\",\"STOP\"]")) { - t.Errorf("Expected return value to be [\"PUSH1\",\"PUSH1\",\"STOP\"], got %s", string(ret)) +func TestTracer(t *testing.T) { + execTracer := func(code string) []byte { + t.Helper() + ctx := &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} + tracer, err := New(code, ctx.txCtx) + if err != nil { + t.Fatal(err) + } + ret, err := runTrace(tracer, ctx) + if err != nil { + t.Fatal(err) + } + return ret + } + for i, tt := range []struct { + code string + want string + }{ + { // tests that we don't panic on bad arguments to memory access + code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}", + want: `[{},{},{}]`, + }, { // tests that we don't panic on bad arguments to stack peeks + code: "{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}", + want: `["0","0","0"]`, + }, { // tests that we don't panic on bad arguments to memory getUint + code: "{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}", + want: `["0","0","0"]`, + }, { // tests some general counting + code: "{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}", + want: `3`, + }, { // tests that depth is reported correctly + code: "{depths: [], step: function(log) { this.depths.push(log.stack.length()); }, fault: function() {}, result: function() { return this.depths; }}", + want: `[0,1,2]`, + }, { // tests to-string of opcodes + code: "{opcodes: [], step: function(log) { this.opcodes.push(log.op.toString()); }, fault: function() {}, result: function() { return this.opcodes; }}", + want: `["PUSH1","PUSH1","STOP"]`, + }, { // tests intrinsic gas + code: "{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}", + want: `"100000.6.21000"`, + }, + } { + if have := execTracer(tt.code); tt.want != string(have) { + t.Errorf("testcase %d: expected return value to be %s got %s\n\tcode: %v", i, tt.want, string(have), tt.code) + } } } @@ -187,9 +149,6 @@ func TestHaltBetweenSteps(t *testing.T) { if err != nil { t.Fatal(err) } - // Needed for intrinsic gas computation - tracer.ctx["input"] = []byte{} - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0) @@ -202,19 +161,3 @@ func TestHaltBetweenSteps(t *testing.T) { t.Errorf("Expected timeout error, got %v", err) } } - -func TestIntrinsicGas(t *testing.T) { - vmctx := testCtx() - tracer, err := New("{depths: [], step: function() {}, fault: function() {}, result: function(ctx) { return ctx.gasPrice+'.'+ctx.gasUsed+'.'+ctx.intrinsicGas; }}", vmctx.txCtx) - if err != nil { - t.Fatal(err) - } - - ret, err := runTrace(tracer, vmctx) - if err != nil { - t.Fatal(err) - } - if have, want := ret, []byte(`"100000.6.21000"`); !bytes.Equal(have, want) { - t.Errorf("Expected return value to be %s got %s", string(want), string(have)) - } -}