Skip to content

Commit

Permalink
core/state_transition: Avoid out of gas when tracing system txs (#20)
Browse files Browse the repository at this point in the history
* core/state_transition: avoid comparing basefee and feecap for system transaction when enabling basefee

* eth/tracers: change using basefee instead of gas price is 0, and add more checking after and before enabling venoki for debug_traceInternalsAndAccounts unittest

* eth/tracers/tracetest: support run all tests with hash and path scheme

* core/state_transition: skip full logic check gasFeecap with system txs
  • Loading branch information
huyngopt1994 committed Feb 25, 2025
1 parent aa865df commit 2349b92
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 32 deletions.
8 changes: 3 additions & 5 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func (st *StateTransition) preCheck() error {
}
}
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
if !st.evm.Config.IsSystemTransaction && st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 {
if l := st.gasFeeCap.BitLen(); l > 256 {
Expand Down Expand Up @@ -420,10 +420,8 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
// 6. caller has enough balance to cover asset transfer for **topmost** call

// Check clauses 1-3, buy gas if everything is correct
if !st.evm.Config.IsSystemTransaction {
if err := st.preCheck(); err != nil {
return nil, err
}
if err := st.preCheck(); err != nil {
return nil, err
}

if tracer := st.evm.Config.Tracer; tracer != nil {
Expand Down
57 changes: 49 additions & 8 deletions eth/tracers/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,18 @@ func TestTraceBlock(t *testing.T) {
}

func TestTraceInternalsAndAccounts_BatchTransferAccounts(t *testing.T) {
t.Parallel()
testTraceInternalsAndAccounts_BatchTransferAccounts(t, false)
testTraceInternalsAndAccounts_BatchTransferAccounts(t, true)
}

func testTraceInternalsAndAccounts_BatchTransferAccounts(t *testing.T, enabledVenoki bool) {
accounts := newAccounts(2)
chainConfig := params.TestChainConfig
if enabledVenoki {
chainConfig.VenokiBlock = big.NewInt(0)
}

genesis := &core.Genesis{Alloc: core.GenesisAlloc{
accounts[0].addr: {
// Contract code
Expand Down Expand Up @@ -496,22 +507,22 @@ func TestTraceInternalsAndAccounts_BatchTransferAccounts(t *testing.T) {
Balance: big.NewInt(params.Ether),
},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
}, Config: params.TestChainConfig}
}, Config: chainConfig}
genBlocks := 3
signer := types.HomesteadSigner{}
api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
if i == 1 {
// Batch send to this account:
// - "0x05ba56c60ceb54f53294bf60d606a919eea4282e"
data1 := common.FromHex("0x876e586100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000005ba56c60ceb54f53294bf60d606a919eea4282e")
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 4*params.TxGas, big.NewInt(0), data1), signer, accounts[1].key)
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 4*params.TxGas, b.BaseFee(), data1), signer, accounts[1].key)
b.AddTx(tx1)

// Batch send to these accounts:
// - "0x359aef78ffa9807889258d0dd398172ca3b77eb1"
// - "0x45f60b415111e3e7abb4c79fc659d3dee430dff5"
data2 := common.FromHex("0x876e5861000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000359aef78ffa9807889258d0dd398172ca3b77eb100000000000000000000000045f60b415111e3e7abb4c79fc659d3dee430dff5")
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 10*params.TxGas, big.NewInt(0), data2), signer, accounts[1].key)
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 10*params.TxGas, b.BaseFee(), data2), signer, accounts[1].key)
b.AddTx(tx2)
}
}))
Expand Down Expand Up @@ -562,22 +573,52 @@ func TestTraceInternalsAndAccounts_BatchTransferAccounts(t *testing.T) {
t.Errorf("got %v, wanted %v", callOpsLen, expectedCallOpsLen)
}

roninTreasuryAddress := common.HexToAddress("")
if genesis.Config.RoninTreasuryAddress != nil {
roninTreasuryAddress = *genesis.Config.RoninTreasuryAddress
}

expectedDirtyAccounts := map[common.Address]*big.Int{}
expectedDirtyAccounts[common.HexToAddress("0x05bA56C60ceb54f53294bF60d606a919eeA4282E")] = big.NewInt(1)
expectedDirtyAccounts[common.HexToAddress("0x359aEf78fFa9807889258D0DD398172CA3B77eB1")] = big.NewInt(1)
expectedDirtyAccounts[common.HexToAddress("0x45F60B415111e3E7aBB4c79FC659d3DeE430dfF5")] = big.NewInt(1)
expectedDirtyAccounts[accounts[1].addr] = big.NewInt(1000000000000000000)
expectedDirtyAccounts[accounts[0].addr] = big.NewInt(999999999999999997)

if enabledVenoki {
expectedDirtyAccounts[roninTreasuryAddress] = big.NewInt(0)
}

for _, actual := range result.DirtyAccounts {
expectedBalance, exists := expectedDirtyAccounts[actual.Address]
if !exists {
t.Errorf("account %v not found", actual.Address)
}

if !enabledVenoki {
if actual.Balance.ToInt().Cmp(expectedBalance) != 0 {
t.Errorf("account balance %v is not match got %v, wanted %v", actual.Address, actual.Balance, expectedBalance)
}
continue
}

if actual.Address == roninTreasuryAddress {
if actual.Balance.ToInt().Cmp(expectedBalance) <= 0 {
t.Errorf("account balance %v should be bigger than init balance got %v, wanted %v", actual.Address, actual.Balance, expectedBalance)
}
continue
}
if actual.Address == accounts[1].addr {
if actual.Balance.ToInt().Cmp(expectedBalance) >= 0 {
t.Errorf("account balance %v should be smaller than init balance got %v, wanted %v", actual.Address, actual.Balance, expectedBalance)
}
continue
}

if actual.Balance.ToInt().Cmp(expectedBalance) != 0 {
t.Errorf("account balance is not match got %v, wanted %v", actual.Balance, expectedBalance)
t.Errorf("account balance %v is not match got %v, wanted %v", actual.Address, actual.Balance, expectedBalance)
}

}
}

Expand Down Expand Up @@ -608,12 +649,12 @@ func TestTraceInternalsAndAccounts_CreateContract(t *testing.T) {
if i == 1 {
// Call `deploy` method to create a new contract
data1 := common.FromHex("0x775c300c")
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 100*params.TxGas, big.NewInt(0), data1), signer, accounts[1].key)
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 100*params.TxGas, b.BaseFee(), data1), signer, accounts[1].key)
b.AddTx(tx1)

// Call `deploy` method to create a new contract
data2 := common.FromHex("0x775c300c")
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 100*params.TxGas, big.NewInt(0), data2), signer, accounts[1].key)
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 100*params.TxGas, b.BaseFee(), data2), signer, accounts[1].key)
b.AddTx(tx2)
}
})
Expand Down Expand Up @@ -714,12 +755,12 @@ func TestTraceInternalsAndAccounts_Create2Contract(t *testing.T) {
if i == 1 {
// Call `deploy` method to create a new contract
data1 := common.FromHex("0x2b85ba3800000000000000000000000000000000000000000000000000000000686f6c61")
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 100*params.TxGas, big.NewInt(0), data1), signer, accounts[1].key)
tx1, _ := types.SignTx(types.NewTransaction(uint64(0), accounts[0].addr, big.NewInt(0), 100*params.TxGas, b.BaseFee(), data1), signer, accounts[1].key)
b.AddTx(tx1)

// Call `deploy` method to create a new contract
data2 := common.FromHex("0x2b85ba3800000000000000000000000000000000000000000000000000000000686f6c62")
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 100*params.TxGas, big.NewInt(0), data2), signer, accounts[1].key)
tx2, _ := types.SignTx(types.NewTransaction(uint64(1), accounts[0].addr, big.NewInt(0), 100*params.TxGas, b.BaseFee(), data2), signer, accounts[1].key)
b.AddTx(tx2)
}
})
Expand Down
7 changes: 4 additions & 3 deletions eth/tracers/internal/tracetest/calltrace2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ type callTracer2Test struct {
}

func TestCallTracer2Native(t *testing.T) {
testCallTracer2("callTracer2", "call_tracer2", t)
testCallTracer2("callTracer2", "call_tracer2", rawdb.HashScheme, t)
testCallTracer2("callTracer2", "call_tracer2", rawdb.PathScheme, t)
}

func testCallTracer2(tracerName string, dirPath string, t *testing.T) {
func testCallTracer2(tracerName string, dirPath string, scheme string, t *testing.T) {
files, err := ioutil.ReadDir(filepath.Join("testdata", dirPath))
if err != nil {
t.Fatalf("failed to retrieve tracer test suite: %v", err)
Expand Down Expand Up @@ -162,7 +163,7 @@ func testCallTracer2(tracerName string, dirPath string, t *testing.T) {
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, scheme)
)
defer triedb.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
Expand Down
13 changes: 8 additions & 5 deletions eth/tracers/internal/tracetest/calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,21 @@ type callTracerTest struct {
// Iterates over all the input-output datasets in the tracer test harness and
// runs the JavaScript tracers against them.
func TestCallTracerLegacy(t *testing.T) {
testCallTracer("callTracerLegacy", "call_tracer_legacy", t)
testCallTracer("callTracerLegacy", "call_tracer_legacy", rawdb.HashScheme, t)
testCallTracer("callTracerLegacy", "call_tracer_legacy", rawdb.PathScheme, t)
}

func TestCallTracerNative(t *testing.T) {
testCallTracer("callTracer", "call_tracer", t)
testCallTracer("callTracer", "call_tracer", rawdb.HashScheme, t)
testCallTracer("callTracer", "call_tracer", rawdb.PathScheme, t)
}

func TestCallTracerNativeWithLog(t *testing.T) {
testCallTracer("callTracer", "call_tracer_withLog", t)
testCallTracer("callTracer", "call_tracer_withLog", rawdb.HashScheme, t)
testCallTracer("callTracer", "call_tracer_withLog", rawdb.PathScheme, t)
}

func testCallTracer(tracerName string, dirPath string, t *testing.T) {
func testCallTracer(tracerName string, dirPath string, scheme string, t *testing.T) {
isLegacy := strings.HasSuffix(dirPath, "_legacy")
files, err := os.ReadDir(filepath.Join("testdata", dirPath))
if err != nil {
Expand Down Expand Up @@ -137,7 +140,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
GasLimit: uint64(test.Context.GasLimit),
BaseFee: test.Genesis.BaseFee,
}
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, scheme)
)
triedb.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
Expand Down
14 changes: 8 additions & 6 deletions eth/tracers/internal/tracetest/flat_calltrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type flatCallTracerTest struct {
Result []flatCallTrace `json:"result"`
}

func flatCallTracerTestRunner(tracerName string, filename string, dirPath string, t testing.TB) error {
func flatCallTracerTestRunner(tracerName string, filename string, dirPath string, scheme string, t testing.TB) error {
// Call tracer test found, read if from disk
blob, err := os.ReadFile(filepath.Join("testdata", dirPath, filename))
if err != nil {
Expand Down Expand Up @@ -100,7 +100,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, scheme)
defer triedb.Close()

// Create the tracer, the EVM environment and run it
Expand Down Expand Up @@ -152,10 +152,11 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
// Iterates over all the input-output datasets in the tracer parity test harness and
// runs the Native tracer against them.
func TestFlatCallTracerNative(t *testing.T) {
testFlatCallTracer("flatCallTracer", "call_tracer_flat", t)
testFlatCallTracer("flatCallTracer", "call_tracer_flat", rawdb.HashScheme, t)
testFlatCallTracer("flatCallTracer", "call_tracer_flat", rawdb.PathScheme, t)
}

func testFlatCallTracer(tracerName string, dirPath string, t *testing.T) {
func testFlatCallTracer(tracerName string, dirPath string, scheme 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)
Expand All @@ -167,7 +168,7 @@ func testFlatCallTracer(tracerName string, dirPath string, t *testing.T) {
file := file // capture range variable
t.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(t *testing.T) {
t.Parallel()
err := flatCallTracerTestRunner(tracerName, file.Name(), dirPath, t)
err := flatCallTracerTestRunner(tracerName, file.Name(), dirPath, scheme, t)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -203,7 +204,8 @@ func BenchmarkFlatCallTracer(b *testing.B) {
filename := strings.TrimPrefix(file, "testdata/call_tracer_flat/")
b.Run(camel(strings.TrimSuffix(filename, ".json")), func(b *testing.B) {
for n := 0; n < b.N; n++ {
err := flatCallTracerTestRunner("flatCallTracer", filename, "call_tracer_flat", b)
// Should replace based on Hash/Path Scheme
err := flatCallTracerTestRunner("flatCallTracer", filename, "call_tracer_flat", rawdb.HashScheme, b)
if err != nil {
b.Fatal(err)
}
Expand Down
13 changes: 8 additions & 5 deletions eth/tracers/internal/tracetest/prestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,21 @@ type testcase struct {
}

func TestPrestateTracerLegacy(t *testing.T) {
testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", t)
testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", rawdb.HashScheme, t)
testPrestateDiffTracer("prestateTracerLegacy", "prestate_tracer_legacy", rawdb.PathScheme, t)
}

func TestPrestateTracer(t *testing.T) {
testPrestateDiffTracer("prestateTracer", "prestate_tracer", t)
testPrestateDiffTracer("prestateTracer", "prestate_tracer", rawdb.HashScheme, t)
testPrestateDiffTracer("prestateTracer", "prestate_tracer", rawdb.PathScheme, t)
}

func TestPrestateWithDiffModeTracer(t *testing.T) {
testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", t)
testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", rawdb.HashScheme, t)
testPrestateDiffTracer("prestateTracer", "prestate_tracer_with_diff_mode", rawdb.PathScheme, t)
}

func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
func testPrestateDiffTracer(tracerName string, dirPath string, scheme 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)
Expand Down Expand Up @@ -108,7 +111,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
GasLimit: uint64(test.Context.GasLimit),
BaseFee: test.Genesis.BaseFee,
}
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, scheme)
)
defer triedb.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
Expand Down

0 comments on commit 2349b92

Please sign in to comment.