Skip to content

Commit

Permalink
eth/tracers: fix prestate tracer bug with create with value (#10960)
Browse files Browse the repository at this point in the history
fixes #9531

Changes:
- fixes a bug with the prestate tracer where we were incorrectly
subtracting the value of a transaction from the "to" address balance in
the "pre" state (should not be done for CREATE calls)
- fixes a bug with the prestate tracer where we were incorrectly adding
the value of a transaction to the "from" address balance in the "pre"
state (should not be done for CREATE calls)
- fixes a bug with the prestate tracer where we were incorrectly
decrementing the nonce value of a transaction's "from" address in the
"pre" state (should not be done for CREATE calls)
- adds a test generator that can generate the test files for us based on
real life transaction hash and node rpc url - check README
https://github.com/ledgerwatch/erigon/blob/fix-prestate-tracer-on-create-e2/eth/tracers/internal/tracetest/testgenerator/README.md
- adds test cases
- fixes some existing test cases that were setup with incorrect data
  • Loading branch information
taratorio committed Jul 2, 2024
1 parent c3bd739 commit 605e701
Show file tree
Hide file tree
Showing 15 changed files with 610 additions and 43 deletions.
1 change: 1 addition & 0 deletions eth/tracers/internal/tracetest/calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type callContext struct {
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
Time math.HexOrDecimal64 `json:"timestamp"`
GasLimit math.HexOrDecimal64 `json:"gasLimit"`
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
Miner libcommon.Address `json:"miner"`
}

Expand Down
44 changes: 19 additions & 25 deletions eth/tracers/internal/tracetest/prestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (

libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/dir"

"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/consensus"
"github.com/ledgerwatch/erigon/core"
Expand Down Expand Up @@ -99,41 +98,36 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
t.Fatalf("failed to parse testcase input: %v", err)
}
// Configure a blockchain with the given prestate
var (
signer = types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time))
origin, _ = signer.Sender(tx)
txContext = evmtypes.TxContext{
Origin: origin,
GasPrice: tx.GetFeeCap(),
}
context = evmtypes.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: consensus.Transfer,
Coinbase: test.Context.Miner,
BlockNumber: uint64(test.Context.Number),
Time: uint64(test.Context.Time),
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
rules = test.Genesis.Config.Rules(context.BlockNumber, context.Time)
)
signer := types.MakeSigner(test.Genesis.Config, uint64(test.Context.Number), uint64(test.Context.Time))
context := evmtypes.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: consensus.Transfer,
Coinbase: test.Context.Miner,
BlockNumber: uint64(test.Context.Number),
Time: uint64(test.Context.Time),
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
if test.Context.BaseFee != nil {
context.BaseFee, _ = uint256.FromBig((*big.Int)(test.Context.BaseFee))
}
rules := test.Genesis.Config.Rules(context.BlockNumber, context.Time)
m := mock.Mock(t)
dbTx, err := m.DB.BeginRw(m.Ctx)
require.NoError(t, err)
defer dbTx.Rollback()
statedb, _ := tests.MakePreState(rules, dbTx, test.Genesis.Alloc, context.BlockNumber, m.HistoryV3)
if test.Genesis.BaseFee != nil {
context.BaseFee, _ = uint256.FromBig(test.Genesis.BaseFee)
}
statedb, err := tests.MakePreState(rules, dbTx, test.Genesis.Alloc, context.BlockNumber, m.HistoryV3)
require.NoError(t, err)
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, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
msg, err := tx.AsMessage(*signer, nil, rules) // BaseFee is set to nil and not to contet.BaseFee, to match the output to go-ethereum tests
msg, err := tx.AsMessage(*signer, (*big.Int)(test.Context.BaseFee), rules)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
txContext := core.NewEVMTxContext(msg)
evm := vm.NewEVM(context, txContext, statedb, test.Genesis.Config, vm.Config{Debug: true, Tracer: tracer})
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.GetGas()).AddBlobGas(tx.GetBlobGas()))
if _, err = st.TransitionDb(true /* refunds */, false /* gasBailout */); err != nil {
t.Fatalf("failed to execute transaction: %v", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"result": {
"0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": {
"balance": "0xc820f93200f4000",
"nonce": 93
"nonce": 94
},
"0x332b656504f4eabb44c8617a42af37461a34e9dc": {
"balance": "0x11faea4f35e5af80000",
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
},
"0xf0c5cef39b17c213cfe090a46b8c7760ffb7928a": {
"balance": "0x15b6828e22bb12188",
"nonce": 746
"nonce": 747
}
},
"post": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"genesis": {
"baseFeePerGas": "51088069741",
"difficulty": "14315558652874667",
"extraData": "0xd883010a10846765746888676f312e31362e35856c696e7578",
"gasLimit": "30058590",
Expand Down Expand Up @@ -62,6 +61,7 @@
"difficulty": "14322823549655084",
"timestamp": "1651623279",
"gasLimit": "30029237",
"baseFeePerGas": "45737281170",
"miner": "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7"
},
"input": "0x02f8b4018312acfc8459682f00851a46bcf47a8302b1a194ffa397285ce46fb78c588a9e993286aac68c37cd80b844fb90b3200000000000000000000000002a549b4af9ec39b03142da6dc32221fc390b553300000000000000000000000000000000000000000000000000000000000cb3d5c001a03002079d2873f7963c4278200c43aa71efad262b2150bc8524480acfc38b5faaa077d44aa09d56b9cf99443c7f55aaad1bbae9cfb5bbb9de31eaf7a8f9e623e980",
Expand All @@ -81,7 +81,7 @@
},
"post": {
"0x808b4da0be6c9512e948521452227efc619bea52": {
"balance": "0x2cd72a36dd031f089",
"balance": "0x2cd9bcb9a59f4e871",
"nonce": 1223933
},
"0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"pre": {
"0x082d4cdf07f386ffa9258f52a5c49db4ac321ec6": {
"balance": "0xc820f93200f4000",
"nonce": 93
"nonce": 94
},
"0x332b656504f4eabb44c8617a42af37461a34e9dc": {
"balance": "0x11faea4f35e5af80000",
Expand Down

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions eth/tracers/internal/tracetest/testgenerator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
build/
24 changes: 24 additions & 0 deletions eth/tracers/internal/tracetest/testgenerator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Background

A tool for generating a test case for a given tracer. It communicates to a node via rpc to build:

1. `genesis` using the parent block of the given `txnHash` and its pre-state
2. `config` for the chain by using the node `admin_nodeInfo` API
3. `input` which is the raw transaction bytes of the given `txnHash`
4. `result` which is result of tracing the given `txnHash` with the given `tracerConfig`

# Pre-requisites

1. install node.js & npm: https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

# Usage

```
cd eth/tracers/internal/tracetest/testgenerator
npm install
npm start -- \
--rpcUrl=http://localhost:8545 \
--txnHash=0x5c08231a3c34bd1be6ac7df553d451246175f3dad3245ab5e4413cde35ace52e \
--traceConfig='{"tracer": "prestateTracer", "tracerConfig": { "diffMode": true } }' \
--outputFilePath=../testdata/prestate_tracer_with_diff_mode/create_with_value.json
```
148 changes: 148 additions & 0 deletions eth/tracers/internal/tracetest/testgenerator/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions eth/tracers/internal/tracetest/testgenerator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "testgenerator",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"scripts": {
"start": "npm run build && node build/index.js",
"build": "tsc"
},
"author": "",
"license": "ISC",
"dependencies": {
"ethers": "^6.13.1"
},
"devDependencies": {
"@types/node": "^20.14.9",
"typescript": "^5.5.2"
}
}
Loading

0 comments on commit 605e701

Please sign in to comment.