Skip to content

Commit

Permalink
trace_callMany: tests and not loosing ibs state of all executed txs (
Browse files Browse the repository at this point in the history
…#11879)

closes #11798

---------

Co-authored-by: JkLondon <[email protected]>
Co-authored-by: alex.sharov <[email protected]>
  • Loading branch information
3 people authored Sep 12, 2024
1 parent 4fde7fc commit 3b7f6b9
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 4 deletions.
8 changes: 4 additions & 4 deletions turbo/jsonrpc/trace_adhoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,9 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
if isHistoricalStateReader {
baseTxNum = historicalStateReader.GetTxNum()
}

blockCtx := transactions.NewEVMBlockContext(engine, header, parentNrOrHash.RequireCanonical, dbtx, api._blockReader, chainConfig)

for txIndex, msg := range msgs {
if isHistoricalStateReader {
historicalStateReader.SetTxNum(baseTxNum + uint64(txIndex))
Expand Down Expand Up @@ -1258,7 +1261,6 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
vmConfig.Tracer = &ot
}

blockCtx := transactions.NewEVMBlockContext(engine, header, parentNrOrHash.RequireCanonical, dbtx, api._blockReader, chainConfig)
if useParent {
blockCtx.GasLimit = math.MaxUint64
blockCtx.MaxGasLimit = true
Expand Down Expand Up @@ -1286,8 +1288,6 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
finalizeTxStateWriter = noop
}

ibs.Reset()

var txFinalized bool
var execResult *evmtypes.ExecutionResult
if args.isBorStateSyncTxn {
Expand Down Expand Up @@ -1316,7 +1316,7 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
evm := vm.NewEVM(blockCtx, txCtx, ibs, chainConfig, vmConfig)
gp := new(core.GasPool).AddGas(msg.Gas()).AddBlobGas(msg.BlobGas())

execResult, err = core.ApplyMessage(evm, msg, gp, true /* refunds */, gasBailout /* gasBailout */)
execResult, err = core.ApplyMessage(evm, msg, gp, true /* refunds */, gasBailout /*gasBailout*/)
}
if err != nil {
return nil, nil, fmt.Errorf("first run for txIndex %d error: %w", txIndex, err)
Expand Down
217 changes: 217 additions & 0 deletions turbo/jsonrpc/trace_adhoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,223 @@ func TestCoinbaseBalance(t *testing.T) {
}
}

func TestSwapBalance(t *testing.T) {
m, _, _ := rpcdaemontest.CreateTestSentry(t)
api := NewTraceAPI(newBaseApiForTest(m), m.DB, &httpcfg.HttpCfg{})
// Call GetTransactionReceipt for transaction which is not in the database
var latest = rpc.LatestBlockNumber
results, err := api.CallMany(context.Background(), json.RawMessage(`
[
[{"from":"0x71562b71999873db5b286df957af199ec94617f7","to":"0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b","gas":"0x5208","gasPrice":"0x0","value":"0x2"},["trace", "stateDiff"]],
[{"from":"0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b","to":"0x71562b71999873db5b286df957af199ec94617f7","gas":"0x5208","gasPrice":"0x0","value":"0x1"},["trace", "stateDiff"]]
]
`), &rpc.BlockNumberOrHash{BlockNumber: &latest}, nil)

/*
Let's assume A - 0x71562b71999873db5b286df957af199ec94617f7 B - 0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b
A has big balance.
1. Sending 2 wei from rich existing account to empty account. Gp: 0 wei. Spent: 2 wei
2. Return 1 wei to initial sender. Gp: 0 wei. Spent: 1 wei.
Balance new: 1 wei
Balance old diff is 1 wei.
*/
if err != nil {
t.Errorf("calling CallMany: %v", err)
}
if results == nil {
t.Errorf("expected empty array, got nil")
}

if len(results) != 2 {
t.Errorf("expected array with 2 elements, got %d elements", len(results))
}

// Checking state diff
if res, ok := results[0].StateDiff[libcommon.HexToAddress("0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b")]; !ok {
t.Errorf("don't found B in first tx")
} else {
b, okConv := res.Balance.(map[string]*hexutil.Big)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(2), b[i].Uint64())
}
}

if res, ok := results[0].StateDiff[libcommon.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")]; !ok {
t.Errorf("don't found A in first tx")
} else {
b, okConv := res.Balance.(map[string]*StateDiffBalance)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(2), b[i].From.Uint64()-b[i].To.Uint64())
}
}

if res, ok := results[1].StateDiff[libcommon.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")]; !ok {
t.Errorf("don't found A in second tx")
} else {
b, okConv := res.Balance.(map[string]*StateDiffBalance)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(1), b[i].To.Uint64()-b[i].From.Uint64())
}
}

if res, ok := results[1].StateDiff[libcommon.HexToAddress("0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b")]; !ok {
t.Errorf("don't found B in second tx")
} else {
b, okConv := res.Balance.(map[string]*hexutil.Big)
if !okConv {
b := res.Balance.(map[string]*StateDiffBalance)
for i := range b {
require.Equal(t, uint64(1), b[i].From.Uint64()-b[i].To.Uint64())
}
} else {
for i := range b {
require.Equal(t, uint64(1), b[i].Uint64())
}
}
}
}

func TestCorrectStateDiff(t *testing.T) {
m, _, _ := rpcdaemontest.CreateTestSentry(t)
api := NewTraceAPI(newBaseApiForTest(m), m.DB, &httpcfg.HttpCfg{})
// Call GetTransactionReceipt for transaction which is not in the database
var latest = rpc.LatestBlockNumber
results, err := api.CallMany(context.Background(), json.RawMessage(`
[
[{"from":"0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e","to":"0x703c4b2bD70c169f5717101CaeE543299Fc946C7","gas":"0x5208","gasPrice":"0x0","value":"0x1"},["trace", "stateDiff"]],
[{"from":"0x71562b71999873db5b286df957af199ec94617f7","to":"0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b","gas":"0x5208","gasPrice":"0x0","value":"0x2"},["trace", "stateDiff"]],
[{"from":"0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b","to":"0x71562b71999873db5b286df957af199ec94617f7","gas":"0x5208","gasPrice":"0x0","value":"0x1"},["trace", "stateDiff"]]
]
`), &rpc.BlockNumberOrHash{BlockNumber: &latest}, nil)

/*
C->D 1 wei
A->B 2 wei
B->A 1 wei
*/
if err != nil {
t.Errorf("calling CallMany: %v", err)
}
if results == nil {
t.Errorf("expected empty array, got nil")
}

if len(results) != 3 {
t.Errorf("expected array with 3 elements, got %d elements", len(results))
}

// Checking state diff
if _, ok := results[0].StateDiff[libcommon.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")]; ok {
t.Errorf("A shouldn't be in first sd")
}
if _, ok := results[0].StateDiff[libcommon.HexToAddress("0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b")]; ok {
t.Errorf("B shouldn't be in first sd")
}

if res, ok := results[0].StateDiff[libcommon.HexToAddress("0x703c4b2bD70c169f5717101CaeE543299Fc946C7")]; !ok {
t.Errorf("don't found C in first tx")
} else {
b, okConv := res.Balance.(map[string]*hexutil.Big)
if !okConv {
b := res.Balance.(map[string]*StateDiffBalance)
for i := range b {
require.Equal(t, uint64(1), b[i].To.Uint64()-b[i].From.Uint64())
}
} else {
for i := range b {
require.Equal(t, uint64(1), b[i].Uint64())
}
}
}

if res, ok := results[0].StateDiff[libcommon.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")]; !ok {
t.Errorf("don't found C in first tx")
} else {
b, okConv := res.Balance.(map[string]*StateDiffBalance)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(1), b[i].From.Uint64()-b[i].To.Uint64())
}
}

if _, ok := results[1].StateDiff[libcommon.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")]; ok {
t.Errorf("C shouldn't be in second sd")
}
if _, ok := results[1].StateDiff[libcommon.HexToAddress("0x703c4b2bD70c169f5717101CaeE543299Fc946C7")]; ok {
t.Errorf("D shouldn't be in second sd")
}

if res, ok := results[1].StateDiff[libcommon.HexToAddress("0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b")]; !ok {
t.Errorf("don't found B in first tx")
} else {
b, okConv := res.Balance.(map[string]*hexutil.Big)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(2), b[i].Uint64())
}
}

if res, ok := results[1].StateDiff[libcommon.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")]; !ok {
t.Errorf("don't found A in first tx")
} else {
b, okConv := res.Balance.(map[string]*StateDiffBalance)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(2), b[i].From.Uint64()-b[i].To.Uint64())
}
}

if _, ok := results[2].StateDiff[libcommon.HexToAddress("0x0D3ab14BBaD3D99F4203bd7a11aCB94882050E7e")]; ok {
t.Errorf("C shouldn't be in third sd")
}
if _, ok := results[2].StateDiff[libcommon.HexToAddress("0x703c4b2bD70c169f5717101CaeE543299Fc946C7")]; ok {
t.Errorf("D shouldn't be in third sd")
}

if res, ok := results[2].StateDiff[libcommon.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")]; !ok {
t.Errorf("don't found A in second tx")
} else {
b, okConv := res.Balance.(map[string]*StateDiffBalance)
if !okConv {
t.Errorf("bad interface %+v", res.Balance)
}
for i := range b {
require.Equal(t, uint64(1), b[i].To.Uint64()-b[i].From.Uint64())
}
}

if res, ok := results[2].StateDiff[libcommon.HexToAddress("0x14627ea0e2B27b817DbfF94c3dA383bB73F8C30b")]; !ok {
t.Errorf("don't found B in second tx")
} else {
b, okConv := res.Balance.(map[string]*hexutil.Big)
if !okConv {
b := res.Balance.(map[string]*StateDiffBalance)
for i := range b {
require.Equal(t, uint64(1), b[i].From.Uint64()-b[i].To.Uint64())
}
} else {
for i := range b {
require.Equal(t, uint64(1), b[i].Uint64())
}
}
}
}

func TestReplayTransaction(t *testing.T) {
m, _, _ := rpcdaemontest.CreateTestSentry(t)
api := NewTraceAPI(newBaseApiForTest(m), m.DB, &httpcfg.HttpCfg{})
Expand Down

0 comments on commit 3b7f6b9

Please sign in to comment.