core, eth: fix precompile addresses for tracers (#23097)

* 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
This commit is contained in:
Sina Mahmoodi 2021-06-28 14:13:27 +02:00 committed by GitHub
parent dde6f1e92d
commit 1b5582acf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 6 deletions

View File

@ -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
@ -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 {
@ -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)

View File

@ -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)
@ -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
}
@ -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)
}
}
@ -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")
}
}