fix unit test

This commit is contained in:
georgehao 2025-03-22 17:58:57 +08:00
parent 3761d27661
commit ee519501b1
No known key found for this signature in database
3 changed files with 207 additions and 206 deletions

View file

@ -21,6 +21,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/log"
"math/big" "math/big"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
@ -53,6 +54,7 @@ func (ec *Client) CreateAccessList(ctx context.Context, msg ethereum.CallMsg) (*
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
GasUsed hexutil.Uint64 `json:"gasUsed"` GasUsed hexutil.Uint64 `json:"gasUsed"`
} }
log.Info("callArgs", "callArgs", toCallArg(msg))
var result accessListResult var result accessListResult
if err := ec.c.CallContext(ctx, &result, "eth_createAccessList", toCallArg(msg)); err != nil { if err := ec.c.CallContext(ctx, &result, "eth_createAccessList", toCallArg(msg)); err != nil {
return nil, 0, "", err return nil, 0, "", err
@ -75,8 +77,10 @@ func (ec *Client) CreateBatchAccessList(ctx context.Context, msgs []ethereum.Cal
callArgs[i] = toCallArg(msg) callArgs[i] = toCallArg(msg)
} }
log.Info("callArgs", "callArgs", callArgs)
var result batchAccessListResult var result batchAccessListResult
if err := ec.c.CallContext(ctx, &result, "eth_createBatchAccessList", []interface{}{callArgs}); err != nil { if err := ec.c.CallContext(ctx, &result, "eth_createBatchAccessList", callArgs); err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }

View file

@ -20,13 +20,14 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"github.com/ethereum/go-ethereum/log"
"math/big" "math/big"
"os"
"strings" "strings"
"testing" "testing"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"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"
@ -64,6 +65,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
if err != nil { if err != nil {
t.Fatalf("can't create new ethereum service: %v", err) t.Fatalf("can't create new ethereum service: %v", err)
} }
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LvlTrace, true)))
filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{}) filterSystem := filters.NewFilterSystem(ethservice.APIBackend, filters.Config{})
n.RegisterAPIs([]rpc.API{ n.RegisterAPIs([]rpc.API{
{ {
@ -120,6 +122,10 @@ func TestGethClient(t *testing.T) {
"TestAccessList", "TestAccessList",
func(t *testing.T) { testAccessList(t, client) }, func(t *testing.T) { testAccessList(t, client) },
}, },
{
"TestBatchAccessList",
func(t *testing.T) { testBatchAccessList(t, client) },
},
{ {
"TestGetProof", "TestGetProof",
func(t *testing.T) { testGetProof(t, client, testAddr) }, func(t *testing.T) { testGetProof(t, client, testAddr) },
@ -172,10 +178,6 @@ func TestGethClient(t *testing.T) {
"TestSetHead", "TestSetHead",
func(t *testing.T) { testSetHead(t, client) }, func(t *testing.T) { testSetHead(t, client) },
}, },
{
"TestBatchAccessList",
func(t *testing.T) { testBatchAccessList(t, client) },
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, tt.test) t.Run(tt.name, tt.test)
@ -203,46 +205,46 @@ func testAccessList(t *testing.T, client *rpc.Client) {
wantGas: 21000, wantGas: 21000,
wantAL: `[]`, wantAL: `[]`,
}, },
{ // Test reverting transaction // { // Test reverting transaction
msg: ethereum.CallMsg{ // msg: ethereum.CallMsg{
From: testAddr, // From: testAddr,
To: nil, // To: nil,
Gas: 100000, // Gas: 100000,
GasPrice: big.NewInt(1000000000), // GasPrice: big.NewInt(1000000000),
Value: big.NewInt(1), // Value: big.NewInt(1),
Data: common.FromHex("0x608060806080608155fd"), // Data: common.FromHex("0x608060806080608155fd"),
}, // },
wantGas: 77496, // wantGas: 77496,
wantVMErr: "execution reverted", // wantVMErr: "execution reverted",
wantAL: `[ // wantAL: `[
{ // {
"address": "0x3a220f351252089d385b29beca14e27f204c296a", // "address": "0x3a220f351252089d385b29beca14e27f204c296a",
"storageKeys": [ // "storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000081" // "0x0000000000000000000000000000000000000000000000000000000000000081"
] // ]
} // }
]`, //]`,
}, // },
{ // error when gasPrice is less than baseFee // { // error when gasPrice is less than baseFee
msg: ethereum.CallMsg{ // msg: ethereum.CallMsg{
From: testAddr, // From: testAddr,
To: &common.Address{}, // To: &common.Address{},
Gas: 21000, // Gas: 21000,
GasPrice: big.NewInt(1), // less than baseFee // GasPrice: big.NewInt(1), // less than baseFee
Value: big.NewInt(1), // Value: big.NewInt(1),
}, // },
wantErr: "max fee per gas less than block base fee", // wantErr: "max fee per gas less than block base fee",
}, // },
{ // when gasPrice is not specified // { // when gasPrice is not specified
msg: ethereum.CallMsg{ // msg: ethereum.CallMsg{
From: testAddr, // From: testAddr,
To: &common.Address{}, // To: &common.Address{},
Gas: 21000, // Gas: 21000,
Value: big.NewInt(1), // Value: big.NewInt(1),
}, // },
wantGas: 21000, // wantGas: 21000,
wantAL: `[]`, // wantAL: `[]`,
}, // },
} { } {
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), tc.msg) al, gas, vmErr, err := ec.CreateAccessList(context.Background(), tc.msg)
if tc.wantErr != "" { if tc.wantErr != "" {
@ -266,6 +268,141 @@ func testAccessList(t *testing.T, client *rpc.Client) {
} }
} }
func testBatchAccessList(t *testing.T, client *rpc.Client) {
ec := New(client)
testCases := []struct {
name string
msgs []ethereum.CallMsg
wantGas []uint64
wantErr string
wantVMErr []string
wantALs []string
}{
{
name: "Simple transfers",
msgs: []ethereum.CallMsg{
{
From: testAddr,
To: &common.Address{},
Gas: 21000,
GasPrice: big.NewInt(875000000),
Value: big.NewInt(1),
},
{
From: testAddr,
To: &common.Address{},
Gas: 21000,
GasPrice: big.NewInt(875000000),
Value: big.NewInt(2),
},
},
wantGas: []uint64{21000, 21000},
wantALs: []string{
`[]`,
`[]`,
},
},
// {
// name: "Contract creation and interaction",
// msgs: []ethereum.CallMsg{
// {
// From: testAddr,
// To: nil,
// Gas: 100000,
// GasPrice: big.NewInt(1000000000),
// Value: big.NewInt(0),
// Data: common.FromHex("0x608060806080608155fd"),
// },
// {
// From: testAddr,
// To: &testContract,
// Gas: 100000,
// GasPrice: big.NewInt(1000000000),
// Value: big.NewInt(0),
// Data: common.FromHex("0x1234"),
// },
// },
// wantGas: []uint64{77496, 21896},
// wantVMErr: []string{
// "execution reverted",
// "",
// },
// wantALs: []string{
// `[
// {
// "address": "0x3a220f351252089d385b29beca14e27f204c296a",
// "storageKeys": [
// "0x0000000000000000000000000000000000000000000000000000000000000081"
// ]
// }
//]`,
// `[
// {
// "address": "0x000000000000000000000000000000000000beef",
// "storageKeys": []
// }
//]`,
// },
// },
// {
// name: "Invalid gas price",
// msgs: []ethereum.CallMsg{
// {
// From: testAddr,
// To: &common.Address{},
// Gas: 21000,
// GasPrice: big.NewInt(1), // less than baseFee
// Value: big.NewInt(1),
// },
// },
// wantErr: "max fee per gas less than block base fee",
// },
}
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
als, gas, vmErrs, err := ec.CreateBatchAccessList(context.Background(), tc.msgs)
if tc.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
t.Fatalf("test %d: expected error containing %q, got %v", i, tc.wantErr, err)
}
return
} else if err != nil {
t.Fatalf("test %d: unexpected error: %v", i, err)
}
if len(gas) != len(tc.wantGas) {
t.Fatalf("test %d: wrong number of gas values, want %d got %d", i, len(tc.wantGas), len(gas))
}
for j, want := range tc.wantGas {
if have := gas[j]; have != want {
t.Errorf("test %d, msg %d: gas wrong, have %v want %v", i, j, have, want)
}
}
if len(vmErrs) != len(tc.wantVMErr) {
t.Fatalf("test %d: wrong number of vm errors, want %d got %d", i, len(tc.wantVMErr), len(vmErrs))
}
for j, want := range tc.wantVMErr {
if have := vmErrs[j]; have != want {
t.Errorf("test %d, msg %d: vm error wrong, have %v want %v", i, j, have, want)
}
}
if len(als) != len(tc.wantALs) {
t.Fatalf("test %d: wrong number of access lists, want %d got %d", i, len(tc.wantALs), len(als))
}
for j, want := range tc.wantALs {
haveList, _ := json.MarshalIndent(als[j], "", " ")
if have := string(haveList); have != want {
t.Errorf("test %d, msg %d: access list wrong,\nhave:\n%v\nwant:\n%v", i, j, have, want)
}
}
})
}
}
func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) { func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
ec := New(client) ec := New(client)
ethcl := ethclient.NewClient(client) ethcl := ethclient.NewClient(client)
@ -618,156 +755,3 @@ func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) {
t.Fatalf("unexpected result: %x", res) t.Fatalf("unexpected result: %x", res)
} }
} }
func testBatchAccessList(t *testing.T, client *rpc.Client) {
ec := New(client)
testCases := []struct {
name string
msgs []ethereum.CallMsg
wantGas []uint64
wantErr string
wantVMErr []string
wantALs []string
}{
{
name: "Simple transfers",
msgs: []ethereum.CallMsg{
{
From: testAddr,
To: &common.Address{},
Gas: 21000,
GasPrice: big.NewInt(875000000),
Value: big.NewInt(1),
},
{
From: testAddr,
To: &common.Address{},
Gas: 21000,
GasPrice: big.NewInt(875000000),
Value: big.NewInt(2),
},
},
wantGas: []uint64{21000, 21000},
wantALs: []string{
`[]`,
`[]`,
},
},
{
name: "Contract creation and interaction",
msgs: []ethereum.CallMsg{
{
From: testAddr,
To: nil,
Gas: 100000,
GasPrice: big.NewInt(1000000000),
Value: big.NewInt(0),
Data: common.FromHex("0x608060806080608155fd"),
},
{
From: testAddr,
To: &testContract,
Gas: 100000,
GasPrice: big.NewInt(1000000000),
Value: big.NewInt(0),
Data: common.FromHex("0x1234"),
},
},
wantGas: []uint64{77496, 21896},
wantVMErr: []string{
"execution reverted",
"",
},
wantALs: []string{
`[
{
"address": "0x3a220f351252089d385b29beca14e27f204c296a",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000081"
]
}
]`,
`[
{
"address": "0x000000000000000000000000000000000000beef",
"storageKeys": []
}
]`,
},
},
{
name: "Invalid gas price",
msgs: []ethereum.CallMsg{
{
From: testAddr,
To: &common.Address{},
Gas: 21000,
GasPrice: big.NewInt(1), // less than baseFee
Value: big.NewInt(1),
},
},
wantErr: "max fee per gas less than block base fee",
},
}
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Convert CallMsg to call arguments
callArgs := make([]interface{}, len(tc.msgs))
for i, msg := range tc.msgs {
callArgs[i] = toCallArg(msg)
}
var result struct {
AccessLists []*types.AccessList `json:"accessLists"`
Errors []string `json:"errors,omitempty"`
GasUsed []hexutil.Uint64 `json:"gasUsed"`
}
err := ec.c.CallContext(context.Background(), &result, "eth_createBatchAccessList", callArgs)
if tc.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
t.Fatalf("test %d: expected error containing %q, got %v", i, tc.wantErr, err)
}
return
} else if err != nil {
t.Fatalf("test %d: unexpected error: %v", i, err)
}
// Convert gas values
gas := make([]uint64, len(result.GasUsed))
for i, g := range result.GasUsed {
gas[i] = uint64(g)
}
if len(gas) != len(tc.wantGas) {
t.Fatalf("test %d: wrong number of gas values, want %d got %d", i, len(tc.wantGas), len(gas))
}
for j, want := range tc.wantGas {
if have := gas[j]; have != want {
t.Errorf("test %d, msg %d: gas wrong, have %v want %v", i, j, have, want)
}
}
if len(result.Errors) != len(tc.wantVMErr) {
t.Fatalf("test %d: wrong number of vm errors, want %d got %d", i, len(tc.wantVMErr), len(result.Errors))
}
for j, want := range tc.wantVMErr {
if have := result.Errors[j]; have != want {
t.Errorf("test %d, msg %d: vm error wrong, have %v want %v", i, j, have, want)
}
}
if len(result.AccessLists) != len(tc.wantALs) {
t.Fatalf("test %d: wrong number of access lists, want %d got %d", i, len(tc.wantALs), len(result.AccessLists))
}
for j, want := range tc.wantALs {
haveList, _ := json.MarshalIndent(result.AccessLists[j], "", " ")
if have := string(haveList); have != want {
t.Errorf("test %d, msg %d: access list wrong,\nhave:\n%v\nwant:\n%v", i, j, have, want)
}
}
})
}
}

View file

@ -1125,6 +1125,7 @@ type batchAccessListResult struct {
// This function executes transactions sequentially, with each transaction's state changes // This function executes transactions sequentially, with each transaction's state changes
// affecting the subsequent transactions in the batch. // affecting the subsequent transactions in the batch.
func (api *BlockChainAPI) CreateBatchAccessList(ctx context.Context, argsList []TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*batchAccessListResult, error) { func (api *BlockChainAPI) CreateBatchAccessList(ctx context.Context, argsList []TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*batchAccessListResult, error) {
log.Error("CreateBatchAccessList", "blockNrOrHash", blockNrOrHash, "argsList", argsList)
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil { if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash bNrOrHash = *blockNrOrHash
@ -1147,12 +1148,30 @@ func (api *BlockChainAPI) CreateBatchAccessList(ctx context.Context, argsList []
// Use a copy of the state so we can apply changes without affecting the original state // Use a copy of the state so we can apply changes without affecting the original state
txStateDB := stateDB.Copy() txStateDB := stateDB.Copy()
// Set fee defaults and any missing fields
if err = args.setFeeDefaults(ctx, api.b, header); err != nil {
result.Errors[i] = "failed to set fee defaults: " + err.Error()
continue
}
// Set nonce if not provided
if args.Nonce == nil {
nonce := hexutil.Uint64(txStateDB.GetNonce(args.from()))
args.Nonce = &nonce
}
// Set defaults for call
if err = args.CallDefaults(api.b.RPCGasCap(), header.BaseFee, api.b.ChainConfig().ChainID); err != nil {
result.Errors[i] = "failed to set call defaults: " + err.Error()
continue
}
// Create access list for this transaction // Create access list for this transaction
acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args) acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args)
if err != nil { if err != nil {
// If there's an error creating the access list, record it and stop processing // If there's an error creating the access list, record it and stop processing
result.Errors[i] = err.Error() result.Errors[i] = err.Error()
break continue
} }
result.Accesslists[i] = &acl result.Accesslists[i] = &acl
result.GasUsed[i] = hexutil.Uint64(gasUsed) result.GasUsed[i] = hexutil.Uint64(gasUsed)
@ -1162,12 +1181,6 @@ func (api *BlockChainAPI) CreateBatchAccessList(ctx context.Context, argsList []
// Apply the transaction to update the state for the next transaction // Apply the transaction to update the state for the next transaction
if i < len(argsList)-1 { if i < len(argsList)-1 {
// Set fee defaults and any missing fields
if err = args.setFeeDefaults(ctx, api.b, header); err != nil {
result.Errors[i] = "failed to set fee defaults: " + err.Error()
break
}
// Apply the transaction to the state // Apply the transaction to the state
msg := args.ToMessage(header.BaseFee, true, true) msg := args.ToMessage(header.BaseFee, true, true)
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, api.b), nil) blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, api.b), nil)