From 35a2f9820901282b58b28b350ec2b047be0a9e42 Mon Sep 17 00:00:00 2001 From: JukLee0ira Date: Wed, 30 Oct 2024 09:54:13 +0800 Subject: [PATCH] add test --- .../contract_tracer/simple_opCode.json | 67 ++++++++++++++ eth/tracers/testing/calltrace_test.go | 91 +++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 eth/tracers/testdata/contract_tracer/simple_opCode.json diff --git a/eth/tracers/testdata/contract_tracer/simple_opCode.json b/eth/tracers/testdata/contract_tracer/simple_opCode.json new file mode 100644 index 0000000000000..d8daa188e4456 --- /dev/null +++ b/eth/tracers/testdata/contract_tracer/simple_opCode.json @@ -0,0 +1,67 @@ +{ + "context": { + "difficulty": "3502894804", + "gasLimit": "4722976", + "miner": "0x1585936b53834b021f68cc13eeefdec2efc8e724", + "number": "2289806", + "timestamp": "1513601314" + }, + "genesis": { + "alloc": { + "0x0024f658a46fbb89d8ac105e98d7ac7cbbaf27c5": { + "balance": "0x0", + "code": "0x", + "nonce": "9", + "storage": {} + }, + "0x7ef6c7dc8f8e9dbb026382537906991b07f2da86": { + "balance": "0x4d87094125a369d9bd5", + "code": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c8063773a1154146037578063ccbac9f514603f575b600080fd5b603d6059565b005b60456099565b6040516050919060b6565b60405180910390f35b446000819055507facb85192b17e57cdd6ffdc2af021cc70c3a2269771b37b82dd36695fec903af5600054604051608f919060b6565b60405180910390a1565b60005481565b6000819050919050565b60b081609f565b82525050565b600060208201905060c9600083018460a9565b9291505056fea26469706673582212206c5f0ead8b2711f212408856a646c0e33b66df9c87c135b64651e31409588e7864736f6c63430008120033", + "nonce": "1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x3e77b453e919df1d5620826b6e3709443da2cb6fa3f01166311eebd8013e02bb": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000005a37b834" + } + }, + "0x873c36f9fd02e0c57a393afe80d14f244fe04378": { + "balance": "0x1780d77678137ac1b775", + "code": "0x", + "nonce": "0x10", + "storage": {} + } + }, + "config": { + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "IstanbulBlock":1561651, + "chainId": 4761, + "daoForkSupport": true, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 10, + "eip158Block": 10, + "ethash": {}, + "homesteadBlock": 0 + }, + "difficulty": "3509749784", + "extraData": "0x4554482e45544846414e532e4f52472d4641313738394444", + "gasLimit": "4727564", + "hash": "0x609948ac3bd3c00b7736b933248891d6c901ee28f066241bddb28f4e00a9f440", + "miner": "0xbbf5029fd710d227630c8b7d338051b8e76d50b3", + "mixHash": "0xb131e4507c93c7377de00e7c271bf409ec7492767142ff0f45c882f8068c2ada", + "nonce": "0x4eb12e19c16d43da", + "number": "2289805", + "stateRoot": "0xc7f10f352bff82fac3c2999d3085093d12652e19c7fd32591de49dc5d91b4f1f", + "timestamp": "1513601261", + "totalDifficulty": "7143276353481064" + }, + "input": "0xf86910840ee6b28082a72e947ef6c7dc8f8e9dbb026382537906991b07f2da868084773a1154822555a0a90b352128680ed1277fd0819acdfb1da9e71558854effa68358d36e41e0d170a0685835cae1e3a0b5a57019683cb3150fe22bfab465d0b2568e7266ace66042cd", + "tracerConfig": { + "opCode": "PREVRANDAO" + }, + "result": + ["0x7ef6c7dc8f8e9dbb026382537906991b07f2da86"] + +} \ No newline at end of file diff --git a/eth/tracers/testing/calltrace_test.go b/eth/tracers/testing/calltrace_test.go index 8e9720fbec50b..fcf0c6aaeba76 100644 --- a/eth/tracers/testing/calltrace_test.go +++ b/eth/tracers/testing/calltrace_test.go @@ -241,3 +241,94 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { statedb.RevertToSnapshot(snap) } } + +type contractTracerTest struct { + Genesis *core.Genesis `json:"genesis"` + Context *callContext `json:"context"` + Input string `json:"input"` + TracerConfig json.RawMessage `json:"tracerConfig"` + Result []string `json:"result"` +} + +func testContractTracer(tracerName string, dirPath string, t *testing.T) { + files, err := os.ReadDir(filepath.Join("..", "testdata", dirPath)) + if err != nil { + t.Fatalf("failed to retrieve tracer test suite: %v", err) + } + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".json") { + continue + } + file := file // capture range variable + t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) { + t.Parallel() + + var ( + test = new(contractTracerTest) + tx = new(types.Transaction) + ) + // Call tracer test found, read if from disk + if blob, err := os.ReadFile(filepath.Join("..", "testdata", dirPath, file.Name())); err != nil { + t.Fatalf("failed to read testcase: %v", err) + } else if err := json.Unmarshal(blob, test); err != nil { + t.Fatalf("failed to parse testcase: %v", err) + } + if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { + t.Fatalf("failed to parse testcase input: %v", err) + } + // Configure a blockchain with the given prestate + var ( + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + origin, _ = signer.Sender(tx) + txContext = vm.TxContext{ + Origin: origin, + GasPrice: tx.GasPrice(), + } + context = vm.BlockContext{ + CanTransfer: core.CanTransfer, + Transfer: core.Transfer, + Coinbase: test.Context.Miner, + BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), + Time: new(big.Int).SetUint64(uint64(test.Context.Time)), + Difficulty: (*big.Int)(test.Context.Difficulty), + GasLimit: uint64(test.Context.GasLimit), + } + statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc) + ) + tracer, err := tracers.New(tracerName, new(tracers.Context), test.TracerConfig) + if err != nil { + t.Fatalf("failed to create call tracer: %v", err) + } + evm := vm.NewEVM(context, txContext, statedb, nil, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer}) + msg, err := tx.AsMessage(signer, nil, nil, nil) + 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(common.Address{}); 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 := new([]string) + if err := json.Unmarshal(res, ret); err != nil { + t.Fatalf("failed to unmarshal trace result: %v", err) + } + + if !reflect.DeepEqual(*ret, test.Result) { + // uncomment this for easier debugging + //have, _ := json.MarshalIndent(ret, "", " ") + //want, _ := json.MarshalIndent(test.Result, "", " ") + //t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want)) + t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", *ret, test.Result) + } + }) + } +} + +func TestContractTracer(t *testing.T) { + testContractTracer("contractTracer", "contract_tracer", t) +}