eth/tracers: fix create2-flaw in prestate_tracer

This commit is contained in:
Martin Holst Swende 2018-12-21 17:05:38 +01:00
parent 2b46018eb6
commit 13d76348bc
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 98 additions and 14 deletions

File diff suppressed because one or more lines are too long

View file

@ -91,7 +91,8 @@
// stack: salt, size, offset, endowment // stack: salt, size, offset, endowment
var offset = log.stack.peek(1).valueOf() var offset = log.stack.peek(1).valueOf()
var size = log.stack.peek(2).valueOf() var size = log.stack.peek(2).valueOf()
this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, size)), db); var end = offset + size
this.lookupAccount(toContract2(from, log.stack.peek(3).toString(16), log.memory.slice(offset, end)), db);
break; break;
case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL": case "CALL": case "CALLCODE": case "DELEGATECALL": case "STATICCALL":
this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db); this.lookupAccount(toAddress(log.stack.peek(1).toString(16)), db);

View file

@ -17,7 +17,10 @@
package tracers package tracers
import ( import (
"crypto/ecdsa"
"crypto/rand"
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"math/big" "math/big"
"path/filepath" "path/filepath"
@ -31,7 +34,9 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests" "github.com/ethereum/go-ethereum/tests"
) )
@ -116,6 +121,83 @@ type callTracerTest struct {
Result *callTrace `json:"result"` Result *callTrace `json:"result"`
} }
func TestPrestateTracerCreate2(t *testing.T) {
unsigned_tx := types.NewTransaction(1, common.HexToAddress("0x00000000000000000000000000000000deadbeef"),
new(big.Int), 5000000, big.NewInt(1), []byte{})
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
if err != nil {
t.Fatalf("err %v", err)
}
signer := types.NewEIP155Signer(big.NewInt(1))
tx, err := types.SignTx(unsigned_tx, signer, privateKeyECDSA)
if err != nil {
t.Fatalf("err %v", err)
}
/**
This comes from one of the test-vectors on the Skinny Create2 - EIP
address 0x00000000000000000000000000000000deadbeef
salt 0x00000000000000000000000000000000000000000000000000000000cafebabe
init_code 0xdeadbeef
gas (assuming no mem expansion): 32006
result: 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7
*/
origin, _ := signer.Sender(tx)
context := vm.Context{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
Origin: origin,
Coinbase: common.Address{},
BlockNumber: new(big.Int).SetUint64(8000000),
Time: new(big.Int).SetUint64(5),
Difficulty: big.NewInt(0x30000),
GasLimit: uint64(6000000),
GasPrice: big.NewInt(1),
}
alloc := core.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
// the address
alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
Nonce: 1,
Code: hexutil.MustDecode("0x63deadbeef60005263cafebabe6004601c6000F560005260206000F3"),
Balance: big.NewInt(1),
}
alloc[origin] = core.GenesisAccount{
Nonce: 1,
Code: []byte{},
Balance: big.NewInt(500000000000000),
}
statedb := tests.MakePreState(ethdb.NewMemDatabase(), alloc)
// Create the tracer, the EVM environment and run it
tracer, err := New("prestateTracer")
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
evm := vm.NewEVM(context, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(signer)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, _, _, err = st.TransitionDb(); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
// Retrieve the trace result and compare against the etalon
res, err := tracer.GetResult()
if err != nil {
t.Fatalf("failed to retrieve trace result: %v", err)
}
ret := make(map[string]interface{})
if err := json.Unmarshal(res, &ret); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err)
}
if _, has := ret["0x60f3f640a8508fc6a86d45df051962668e1e8ac7"]; !has {
t.Fatalf("Expected 0x60f3f640a8508fc6a86d45df051962668e1e8ac7 in result")
}
}
// Iterates over all the input-output datasets in the tracer test harness and // Iterates over all the input-output datasets in the tracer test harness and
// runs the JavaScript tracers against them. // runs the JavaScript tracers against them.
func TestCallTracer(t *testing.T) { func TestCallTracer(t *testing.T) {
@ -185,8 +267,9 @@ func TestCallTracer(t *testing.T) {
if err := json.Unmarshal(res, ret); err != nil { if err := json.Unmarshal(res, ret); err != nil {
t.Fatalf("failed to unmarshal trace result: %v", err) t.Fatalf("failed to unmarshal trace result: %v", err)
} }
if !reflect.DeepEqual(ret, test.Result) { if !reflect.DeepEqual(ret, test.Result) {
t.Fatalf("trace mismatch: have %+v, want %+v", ret, test.Result) t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, test.Result)
} }
}) })
} }