Skip to content

Commit

Permalink
core, eth: fix precompile addresses for tracers (ethereum#23097)
Browse files Browse the repository at this point in the history
* core,eth/tracers: make isPrecompiled dependent on HF

* eth/tracers: use keys when constructing chain config struct

* eth/tracers: dont initialize activePrecompiles with random value
  • Loading branch information
s1na authored Jun 28, 2021
1 parent dde6f1e commit 1b5582a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
15 changes: 13 additions & 2 deletions eth/tracers/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ type Tracer struct {

interrupt uint32 // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption

activePrecompiles []common.Address // Updated on CaptureStart based on given rules
}

// Context contains some contextual infos for a transaction execution that is not
Expand Down Expand Up @@ -414,8 +416,14 @@ func New(code string, ctx *Context) (*Tracer, error) {
return 1
})
tracer.vm.PushGlobalGoFunction("isPrecompiled", func(ctx *duktape.Context) int {
_, ok := vm.PrecompiledContractsIstanbul[common.BytesToAddress(popSlice(ctx))]
ctx.PushBoolean(ok)
addr := common.BytesToAddress(popSlice(ctx))
for _, p := range tracer.activePrecompiles {
if p == addr {
ctx.PushBoolean(true)
return 1
}
}
ctx.PushBoolean(false)
return 1
})
tracer.vm.PushGlobalGoFunction("slice", func(ctx *duktape.Context) int {
Expand Down Expand Up @@ -570,6 +578,9 @@ func (jst *Tracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
// Initialize the context
jst.ctx["block"] = env.Context.BlockNumber.Uint64()
jst.dbWrapper.db = env.StateDB
// Update list of precompiles based on current block
rules := env.ChainConfig().Rules(env.Context.BlockNumber)
jst.activePrecompiles = vm.ActivePrecompiles(rules)

// Compute intrinsic gas
isHomestead := env.ChainConfig().IsHomestead(env.Context.BlockNumber)
Expand Down
39 changes: 35 additions & 4 deletions eth/tracers/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ func testCtx() *vmContext {
return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
}

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})
func runTrace(tracer *Tracer, vmctx *vmContext, chaincfg *params.ChainConfig) (json.RawMessage, error) {
env := vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Debug: true, Tracer: tracer})
var (
startGas uint64 = 10000
value = big.NewInt(0)
Expand All @@ -86,7 +86,7 @@ func TestTracer(t *testing.T) {
ret, err := runTrace(tracer, &vmContext{
blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)},
txCtx: vm.TxContext{GasPrice: big.NewInt(100000)},
})
}, params.TestChainConfig)
if err != nil {
return nil, err.Error() // Stringify to allow comparison without nil checks
}
Expand Down Expand Up @@ -141,7 +141,7 @@ func TestHalt(t *testing.T) {
time.Sleep(1 * time.Second)
tracer.Stop(timeout)
}()
if _, err = runTrace(tracer, testCtx()); err.Error() != "stahp in server-side tracer function 'step'" {
if _, err = runTrace(tracer, testCtx(), params.TestChainConfig); err.Error() != "stahp in server-side tracer function 'step'" {
t.Errorf("Expected timeout error, got %v", err)
}
}
Expand Down Expand Up @@ -205,3 +205,34 @@ func TestNoStepExec(t *testing.T) {
}
}
}

func TestIsPrecompile(t *testing.T) {
chaincfg := &params.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP150Hash: common.Hash{}, EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), LondonBlock: big.NewInt(0), EWASMBlock: nil, CatalystBlock: nil, Ethash: new(params.EthashConfig), Clique: nil}
chaincfg.ByzantiumBlock = big.NewInt(100)
chaincfg.IstanbulBlock = big.NewInt(200)
chaincfg.BerlinBlock = big.NewInt(300)
txCtx := vm.TxContext{GasPrice: big.NewInt(100000)}
tracer, err := New("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", new(Context))
if err != nil {
t.Fatal(err)
}

blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)}
res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
if err != nil {
t.Error(err)
}
if string(res) != "false" {
t.Errorf("Tracer should not consider blake2f as precompile in byzantium")
}

tracer, _ = New("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", new(Context))
blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)}
res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg)
if err != nil {
t.Error(err)
}
if string(res) != "true" {
t.Errorf("Tracer should consider blake2f as precompile in istanbul")
}
}

0 comments on commit 1b5582a

Please sign in to comment.