Skip to content

Commit 62e7448

Browse files
authored
Merge pull request #1404 from maticnetwork/lmartins/rpc-state-sync-tests
StateSync Unit Tests on RPC Methods
2 parents 14ea2ca + b0bba24 commit 62e7448

16 files changed

+364
-116
lines changed

internal/ethapi/api.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/davecgh/go-spew/spew"
3030
"github.com/tyler-smith/go-bip39"
3131

32+
"github.com/ethereum/go-ethereum"
3233
"github.com/ethereum/go-ethereum/accounts"
3334
"github.com/ethereum/go-ethereum/accounts/keystore"
3435
"github.com/ethereum/go-ethereum/accounts/scwallet"
@@ -704,7 +705,10 @@ func (api *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, blo
704705

705706
var txHash common.Hash
706707

707-
borReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64(), api.b.ChainConfig())
708+
borReceipt, err := api.b.GetBorBlockReceipt(ctx, block.Hash())
709+
if err != nil && err != ethereum.NotFound {
710+
return nil, err
711+
}
708712
if borReceipt != nil {
709713
receipts = append(receipts, borReceipt)
710714

@@ -1115,7 +1119,10 @@ func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rp
11151119
result[i] = marshalReceipt(receipt, block.Hash(), block.NumberU64(), signer, txs[i], i, false)
11161120
}
11171121

1118-
stateSyncReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64(), api.b.ChainConfig())
1122+
stateSyncReceipt, err := api.b.GetBorBlockReceipt(ctx, block.Hash())
1123+
if err != nil && err != ethereum.NotFound {
1124+
return nil, err
1125+
}
11191126
if stateSyncReceipt != nil {
11201127
tx, _, _, _ := rawdb.ReadBorTransaction(api.b.ChainDb(), stateSyncReceipt.TxHash)
11211128
result = append(result, marshalReceipt(stateSyncReceipt, block.Hash(), block.NumberU64(), signer, tx, len(result), true))
@@ -1901,7 +1908,7 @@ func (api *TransactionAPI) getAllBlockTransactions(ctx context.Context, block *t
19011908

19021909
stateSyncPresent := false
19031910

1904-
borReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64(), api.b.ChainConfig())
1911+
borReceipt, _ := api.b.GetBorBlockReceipt(ctx, block.Hash())
19051912
if borReceipt != nil {
19061913
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
19071914
if txHash != (common.Hash{}) {
@@ -2074,7 +2081,10 @@ func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash commo
20742081
}
20752082

20762083
if !found {
2077-
tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(api.b.ChainDb(), hash)
2084+
tx, blockHash, blockNumber, index, err = api.b.GetBorBlockTransaction(ctx, hash)
2085+
if err != nil {
2086+
return nil, err
2087+
}
20782088
borTx = true
20792089
}
20802090

@@ -2086,7 +2096,10 @@ func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash commo
20862096

20872097
if borTx {
20882098
// Fetch bor block receipt
2089-
receipt = rawdb.ReadBorReceipt(api.b.ChainDb(), blockHash, blockNumber, api.b.ChainConfig())
2099+
receipt, err = api.b.GetBorBlockReceipt(ctx, blockHash)
2100+
if err != nil && err != ethereum.NotFound {
2101+
return nil, err
2102+
}
20902103
} else {
20912104
receipts, err := api.b.GetReceipts(ctx, blockHash)
20922105
if err != nil {

internal/ethapi/api_test.go

Lines changed: 164 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -587,10 +587,16 @@ func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) er
587587
}
588588
func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
589589
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
590-
return true, tx, blockHash, blockNumber, index, nil
590+
found := true
591+
if tx == nil {
592+
found = false
593+
}
594+
return found, tx, blockHash, blockNumber, index, nil
595+
}
596+
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
597+
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction {
598+
return nil
591599
}
592-
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
593-
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
594600
func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
595601
return 0, nil
596602
}
@@ -625,7 +631,8 @@ func (b testBackend) ServiceFilter(ctx context.Context, session *bloombits.Match
625631

626632
// GetBorBlockTransaction returns bor block tx
627633
func (b testBackend) GetBorBlockTransaction(ctx context.Context, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
628-
panic("implement me")
634+
tx, blockHash, blockNumber, index := rawdb.ReadBorTransaction(b.ChainDb(), hash)
635+
return tx, blockHash, blockNumber, index, nil
629636
}
630637

631638
func (b testBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
@@ -683,14 +690,9 @@ func (b testBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*
683690
}
684691

685692
func (b testBackend) GetBorBlockReceipt(ctx context.Context, hash common.Hash) (*types.Receipt, error) {
686-
number := rawdb.ReadHeaderNumber(b.db, hash)
687-
if number == nil {
688-
return nil, nil
689-
}
690-
691-
receipt := rawdb.ReadRawBorReceipt(b.db, hash, *number)
693+
receipt := b.chain.GetBorReceiptByHash(hash)
692694
if receipt == nil {
693-
return nil, nil
695+
return nil, ethereum.NotFound
694696
}
695697

696698
return receipt, nil
@@ -1902,9 +1904,12 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
19021904
}
19031905
}
19041906

1905-
func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) {
1907+
func setupTransactionsToApiTest(t *testing.T) (*TransactionAPI, []common.Hash, []struct {
1908+
txHash common.Hash
1909+
file string
1910+
}) {
19061911
config := *params.TestChainConfig
1907-
1912+
genBlocks := 5
19081913
config.ShanghaiBlock = big.NewInt(0)
19091914
config.CancunBlock = big.NewInt(0)
19101915

@@ -1935,7 +1940,7 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
19351940
},
19361941
}
19371942
signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID)
1938-
txHashes = make([]common.Hash, genBlocks)
1943+
txHashes = make([]common.Hash, genBlocks+1)
19391944
)
19401945

19411946
// Set the terminal total difficulty in the config
@@ -1974,20 +1979,6 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
19741979
StorageKeys: []common.Hash{{0}},
19751980
}}
19761981
tx, err = types.SignTx(types.NewTx(&types.AccessListTx{Nonce: uint64(i), To: nil, Gas: 58100, GasPrice: b.BaseFee(), Data: common.FromHex("0x60806040"), AccessList: accessList}), signer, acc1Key)
1977-
case 5:
1978-
// blob tx
1979-
fee := big.NewInt(500)
1980-
fee.Add(fee, b.BaseFee())
1981-
tx, err = types.SignTx(types.NewTx(&types.BlobTx{
1982-
Nonce: uint64(i),
1983-
GasTipCap: uint256.NewInt(1),
1984-
GasFeeCap: uint256.MustFromBig(fee),
1985-
Gas: params.TxGas,
1986-
To: acc2Addr,
1987-
BlobFeeCap: uint256.NewInt(1),
1988-
BlobHashes: []common.Hash{{1}},
1989-
Value: new(uint256.Int),
1990-
}), signer, acc1Key)
19911982
}
19921983
if err != nil {
19931984
t.Errorf("failed to sign tx: %v", err)
@@ -1997,16 +1988,8 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
19971988
txHashes[i] = tx.Hash()
19981989
}
19991990
})
2000-
return backend, txHashes
2001-
}
20021991

2003-
func TestRPCGetTransactionReceipt(t *testing.T) {
2004-
t.Parallel()
2005-
2006-
var (
2007-
backend, txHashes = setupReceiptBackend(t, 6)
2008-
api = NewTransactionAPI(backend, new(AddrLocker))
2009-
)
1992+
txHashes[genBlocks] = mockStateSyncTxOnCurrentBlock(t, backend)
20101993

20111994
var testSuite = []struct {
20121995
txHash common.Hash
@@ -2047,12 +2030,45 @@ func TestRPCGetTransactionReceipt(t *testing.T) {
20472030
txHash: common.HexToHash("deadbeef"),
20482031
file: "txhash-notfound",
20492032
},
2050-
// 7. blob tx
2033+
// 7. state sync tx found
20512034
{
20522035
txHash: txHashes[5],
2053-
file: "blob-tx",
2036+
file: "state-sync-tx",
20542037
},
20552038
}
2039+
// map sprint 0 to block 6
2040+
backend.ChainConfig().Bor.Sprint["0"] = uint64(genBlocks)
2041+
2042+
api := NewTransactionAPI(backend, new(AddrLocker))
2043+
2044+
return api, txHashes, testSuite
2045+
}
2046+
2047+
func mockStateSyncTxOnCurrentBlock(t *testing.T, backend *testBackend) common.Hash {
2048+
// State Sync Tx Setup
2049+
var stateSyncLogs []*types.Log
2050+
block, err := backend.BlockByHash(context.Background(), backend.CurrentBlock().Hash())
2051+
if err != nil {
2052+
t.Errorf("failed to get current block: %v", err)
2053+
}
2054+
2055+
types.DeriveFieldsForBorLogs(stateSyncLogs, block.Hash(), block.NumberU64(), 0, 0)
2056+
2057+
// Write bor receipt
2058+
rawdb.WriteBorReceipt(backend.ChainDb(), block.Hash(), block.NumberU64(), &types.ReceiptForStorage{
2059+
Status: types.ReceiptStatusSuccessful, // make receipt status successful
2060+
Logs: stateSyncLogs,
2061+
})
2062+
2063+
// Write bor tx reverse lookup
2064+
rawdb.WriteBorTxLookupEntry(backend.ChainDb(), block.Hash(), block.NumberU64())
2065+
return types.GetDerivedBorTxHash(types.BorReceiptKey(block.NumberU64(), block.Hash()))
2066+
}
2067+
2068+
func TestRPCGetTransactionReceipt(t *testing.T) {
2069+
var (
2070+
api, _, testSuite = setupTransactionsToApiTest(t)
2071+
)
20562072

20572073
for i, tt := range testSuite {
20582074
var (
@@ -2067,6 +2083,48 @@ func TestRPCGetTransactionReceipt(t *testing.T) {
20672083
testRPCResponseWithFile(t, i, result, "eth_getTransactionReceipt", tt.file)
20682084
}
20692085
}
2086+
func TestRPCGetTransactionByHash(t *testing.T) {
2087+
var (
2088+
api, _, testSuite = setupTransactionsToApiTest(t)
2089+
)
2090+
2091+
for i, tt := range testSuite {
2092+
var (
2093+
result interface{}
2094+
err error
2095+
)
2096+
result, err = api.GetTransactionByHash(context.Background(), tt.txHash)
2097+
if err != nil {
2098+
t.Errorf("test %d: want no error, have %v", i, err)
2099+
continue
2100+
}
2101+
testRPCResponseWithFile(t, i, result, "eth_getTransactionByHash", tt.file)
2102+
}
2103+
}
2104+
2105+
func TestRPCGetBlockTransactionCountByHash(t *testing.T) {
2106+
var (
2107+
api, _, _ = setupTransactionsToApiTest(t)
2108+
)
2109+
2110+
cnt := api.GetBlockTransactionCountByHash(context.Background(), api.b.CurrentBlock().Hash())
2111+
2112+
// 2 txs: create-contract-with-access-list + state sync tx
2113+
expected := hexutil.Uint(2)
2114+
require.Equal(t, expected, *cnt)
2115+
}
2116+
2117+
func TestRPCGetTransactionByBlockHashAndIndex(t *testing.T) {
2118+
var (
2119+
api, _, _ = setupTransactionsToApiTest(t)
2120+
)
2121+
2122+
createContractWithAccessList := api.GetTransactionByBlockHashAndIndex(context.Background(), api.b.CurrentBlock().Hash(), 0)
2123+
stateSyncTx := api.GetTransactionByBlockHashAndIndex(context.Background(), api.b.CurrentBlock().Hash(), 1)
2124+
2125+
testRPCResponseWithFile(t, 0, createContractWithAccessList, "eth_getTransactionByBlockHashAndIndex", "create-contract-with-access-list")
2126+
testRPCResponseWithFile(t, 1, stateSyncTx, "eth_getTransactionByBlockHashAndIndex", "state-sync-tx")
2127+
}
20702128

20712129
func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc string, file string) {
20722130
data, err := json.MarshalIndent(result, "", " ")
@@ -2086,8 +2144,47 @@ func testRPCResponseWithFile(t *testing.T, testid int, result interface{}, rpc s
20862144
}
20872145

20882146
func TestRPCGetTransactionReceiptsByBlock(t *testing.T) {
2089-
t.Parallel()
2147+
api, blockNrOrHash, testSuite := setupBlocksToApiTest(t)
20902148

2149+
receipts, err := api.GetTransactionReceiptsByBlock(context.Background(), blockNrOrHash)
2150+
if err != nil {
2151+
t.Fatal("api error")
2152+
}
2153+
2154+
for i, tt := range testSuite {
2155+
data, err := json.Marshal(receipts[i])
2156+
if err != nil {
2157+
t.Errorf("test %d: json marshal error", i)
2158+
continue
2159+
}
2160+
want, have := tt.want, string(data)
2161+
require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
2162+
}
2163+
}
2164+
2165+
func TestRPCGetBlockReceipts(t *testing.T) {
2166+
api, blockNrOrHash, testSuite := setupBlocksToApiTest(t)
2167+
2168+
receipts, err := api.GetBlockReceipts(context.Background(), blockNrOrHash)
2169+
if err != nil {
2170+
t.Fatal("api error")
2171+
}
2172+
2173+
for i, tt := range testSuite {
2174+
data, err := json.Marshal(receipts[i])
2175+
if err != nil {
2176+
t.Errorf("test %d: json marshal error", i)
2177+
continue
2178+
}
2179+
want, have := tt.want, string(data)
2180+
require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
2181+
}
2182+
}
2183+
2184+
func setupBlocksToApiTest(t *testing.T) (*BlockChainAPI, rpc.BlockNumberOrHash, []struct {
2185+
txHash common.Hash
2186+
want string
2187+
}) {
20912188
// Initialize test accounts
20922189
var (
20932190
acc1Key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
@@ -2103,7 +2200,7 @@ func TestRPCGetTransactionReceiptsByBlock(t *testing.T) {
21032200
contract: {Balance: big.NewInt(params.Ether), Code: common.FromHex("0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a9059cbb14610030575b600080fd5b61004a6004803603810190610045919061016a565b610060565b60405161005791906101c5565b60405180910390f35b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516100bf91906101ef565b60405180910390a36001905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610101826100d6565b9050919050565b610111816100f6565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b6000819050919050565b61014781610134565b811461015257600080fd5b50565b6000813590506101648161013e565b92915050565b60008060408385031215610181576101806100d1565b5b600061018f8582860161011f565b92505060206101a085828601610155565b9150509250929050565b60008115159050919050565b6101bf816101aa565b82525050565b60006020820190506101da60008301846101b6565b92915050565b6101e981610134565b82525050565b600060208201905061020460008301846101e0565b9291505056fea2646970667358221220b469033f4b77b9565ee84e0a2f04d496b18160d26034d54f9487e57788fd36d564736f6c63430008120033")},
21042201
},
21052202
}
2106-
genTxs = 5
2203+
genTxs = 6
21072204
genBlocks = 1
21082205
signer = types.LatestSignerForChainID(params.TestChainConfig.ChainID)
21092206
txHashes = make([]common.Hash, 0, genTxs)
@@ -2149,6 +2246,11 @@ func TestRPCGetTransactionReceiptsByBlock(t *testing.T) {
21492246
}
21502247
})
21512248

2249+
txHashes = append(txHashes, mockStateSyncTxOnCurrentBlock(t, backend))
2250+
2251+
// map sprint 0 to block 1
2252+
backend.ChainConfig().Bor.Sprint["0"] = 1
2253+
21522254
api := NewBlockChainAPI(backend)
21532255
blockHashes := make([]common.Hash, genBlocks+1)
21542256
ctx := context.Background()
@@ -2315,20 +2417,27 @@ func TestRPCGetTransactionReceiptsByBlock(t *testing.T) {
23152417
"type": "0x1"
23162418
}`,
23172419
},
2420+
// 5. state sync tx
2421+
{
2422+
txHash: txHashes[5],
2423+
want: `{
2424+
"blockHash": "0x1728b788dfe51e507d25f14f01414b5a17f807953c13833811d2afae1982b53b",
2425+
"blockNumber": "0x1",
2426+
"contractAddress": null,
2427+
"cumulativeGasUsed": "0x0",
2428+
"effectiveGasPrice": "0x0",
2429+
"from": "0x0000000000000000000000000000000000000000",
2430+
"gasUsed": "0x0",
2431+
"logs": [],
2432+
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
2433+
"status": "0x1",
2434+
"to": "0x0000000000000000000000000000000000000000",
2435+
"transactionHash": "0xba46f68d5c3729ac3fb672fec579fc2cad543bc9edf5b2d47d7c6636ac2fbec9",
2436+
"transactionIndex": "0x5",
2437+
"type": "0x0"
2438+
}`,
2439+
},
23182440
}
23192441

2320-
receipts, err := api.GetTransactionReceiptsByBlock(context.Background(), blockNrOrHash)
2321-
if err != nil {
2322-
t.Fatal("api error")
2323-
}
2324-
2325-
for i, tt := range testSuite {
2326-
data, err := json.Marshal(receipts[i])
2327-
if err != nil {
2328-
t.Errorf("test %d: json marshal error", i)
2329-
continue
2330-
}
2331-
want, have := tt.want, string(data)
2332-
require.JSONEqf(t, want, have, "test %d: json not match, want: %s, have: %s", i, want, have)
2333-
}
2442+
return api, blockNrOrHash, testSuite
23342443
}

0 commit comments

Comments
 (0)