Skip to content

Commit

Permalink
Merge pull request #35 from m-Peter/eth-get-transaction-by-hash-endpoint
Browse files Browse the repository at this point in the history
Implement the `eth_getTransactionByHash` JSON-RPC endpoint
  • Loading branch information
m-Peter authored Feb 1, 2024
2 parents 0ef8dd5 + 746afca commit 4d4d3d3
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 32 deletions.
55 changes: 39 additions & 16 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,31 +290,54 @@ func (s *BlockChainAPI) GetTransactionCount(

// eth_getTransactionByHash
// GetTransactionByHash returns the transaction for the given hash
func (s *BlockChainAPI) GetTransactionByHash(
func (b *BlockChainAPI) GetTransactionByHash(
ctx context.Context,
hash common.Hash,
) (*RPCTransaction, error) {
txPayload, err := b.Store.GetTransactionByHash(ctx, hash)
if err != nil {
return nil, err
}

decodedTx, err := hex.DecodeString(txPayload.Transaction)
if err != nil {
return nil, err
}
tx := &types.Transaction{}
encodedLen := uint(len(txPayload.Transaction))
err = tx.DecodeRLP(
rlp.NewStream(
bytes.NewReader(decodedTx),
uint64(encodedLen),
),
)
if err != nil {
return nil, err
}

// TODO(m-Peter): Add BlockHash to storage
blockHash := common.HexToHash("0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2")
to := common.HexToAddress("0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb")
index := uint64(64)
index := uint64(0)
v, r, s := tx.RawSignatureValues()

tx := &RPCTransaction{
txResult := &RPCTransaction{
BlockHash: (*common.Hash)(&blockHash),
BlockNumber: (*hexutil.Big)(big.NewInt(6139707)),
BlockNumber: (*hexutil.Big)(big.NewInt(int64(txPayload.BlockHeight))),
From: common.HexToAddress("0xa7d9ddbe1f17865597fbd27ec712455208b6b76d"),
Gas: hexutil.Uint64(50000),
GasPrice: (*hexutil.Big)(big.NewInt(20000000000)),
Hash: common.HexToHash("0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"),
Input: hexutil.Bytes("0x68656c6c6f21"),
Nonce: hexutil.Uint64(21),
To: &to,
Gas: hexutil.Uint64(txPayload.GasConsumed),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(),
Input: hexutil.Bytes(tx.Data()),
Nonce: hexutil.Uint64(tx.Nonce()),
To: tx.To(),
TransactionIndex: (*hexutil.Uint64)(&index),
Value: (*hexutil.Big)(big.NewInt(4290000000000000)),
V: (*hexutil.Big)(big.NewInt(37)),
R: (*hexutil.Big)(big.NewInt(150)),
S: (*hexutil.Big)(big.NewInt(250)),
Value: (*hexutil.Big)(tx.Value()),
Type: hexutil.Uint64(uint64(tx.Type())),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
}
return tx, nil
return txResult, nil
}

// eth_getTransactionByBlockHashAndIndex
Expand Down
51 changes: 37 additions & 14 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,31 +275,54 @@ func TestBlockChainAPI(t *testing.T) {
})

t.Run("GetTransactionByHash", func(t *testing.T) {
event := transactionExecutedEvent(
3,
"0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c",
"b88c02f88982029a01808083124f809499466ed2e37b892a2ee3e9cd55a98b68f5735db280a4c6888fa10000000000000000000000000000000000000000000000000000000000000006c001a0f84168f821b427dc158c4d8083bdc4b43e178cf0977a2c5eefbcbedcc4e351b0a066a747a38c6c266b9dc2136523cef04395918de37773db63d574aabde59c12eb",
false,
2,
22514,
"0000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000002a",
"f85af8589499466ed2e37b892a2ee3e9cd55a98b68f5735db2e1a024abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503daa0000000000000000000000000000000000000000000000000000000000000002a",
)

store := blockchainAPI.Store
store.StoreTransaction(context.Background(), event)

tx, err := blockchainAPI.GetTransactionByHash(
context.Background(),
common.Hash{0, 1, 2},
common.HexToHash("0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c"),
)
require.NoError(t, err)

blockHash := common.HexToHash("0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2")
to := common.HexToAddress("0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb")
index := uint64(64)
to := common.HexToAddress("0x99466ED2E37B892A2Ee3E9CD55a98b68f5735db2")
index := uint64(0)
input, err := hex.DecodeString("c6888fa10000000000000000000000000000000000000000000000000000000000000006")
require.NoError(t, err)

r, err := hexutil.DecodeBig("0xf84168f821b427dc158c4d8083bdc4b43e178cf0977a2c5eefbcbedcc4e351b0")
require.NoError(t, err)
s, err := hexutil.DecodeBig("0x66a747a38c6c266b9dc2136523cef04395918de37773db63d574aabde59c12eb")
require.NoError(t, err)

expectedTx := &api.RPCTransaction{
BlockHash: (*common.Hash)(&blockHash),
BlockNumber: (*hexutil.Big)(big.NewInt(6139707)),
From: common.HexToAddress("0xa7d9ddbe1f17865597fbd27ec712455208b6b76d"),
Gas: hexutil.Uint64(50000),
GasPrice: (*hexutil.Big)(big.NewInt(20000000000)),
Hash: common.HexToHash("0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"),
Input: hexutil.Bytes("0x68656c6c6f21"),
Nonce: hexutil.Uint64(21),
BlockNumber: (*hexutil.Big)(big.NewInt(3)),
From: common.HexToAddress("0xa7d9ddBE1f17865597fBD27EC712455208B6B76d"),
Gas: hexutil.Uint64(22514),
GasPrice: (*hexutil.Big)(big.NewInt(0)),
Hash: common.HexToHash("0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c"),
Input: hexutil.Bytes(input),
Nonce: hexutil.Uint64(1),
To: &to,
TransactionIndex: (*hexutil.Uint64)(&index),
Value: (*hexutil.Big)(big.NewInt(4290000000000000)),
V: (*hexutil.Big)(big.NewInt(37)),
R: (*hexutil.Big)(big.NewInt(150)),
S: (*hexutil.Big)(big.NewInt(250)),
Value: (*hexutil.Big)(big.NewInt(0)),
Type: hexutil.Uint64(2),
V: (*hexutil.Big)(big.NewInt(1)),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
}

assert.Equal(t, expectedTx, tx)
Expand Down
1 change: 0 additions & 1 deletion api/fixtures/eth_json_rpc_requests.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
{"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","0x2"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getStorageAt","params":["0x295a70b2de5e3953354a6a8344e616ed314d7251","0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9","latest"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByBlockHashAndIndex","params":["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", "0x0"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByBlockNumberAndIndex","params":["0x29c", "0x0"]}
{"jsonrpc":"2.0","id":1,"method":"eth_coinbase"}
Expand Down
1 change: 0 additions & 1 deletion api/fixtures/eth_json_rpc_responses.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
{"jsonrpc":"2.0","id":1,"result":"0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"}
{"jsonrpc":"2.0","id":1,"result":"0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"}
{"jsonrpc":"2.0","id":1,"result":"0x0"}
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2","blockNumber":"0x5daf3b","from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d","gas":"0xc350","gasPrice":"0x4a817c800","hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b","input":"0x3078363836353663366336663231","nonce":"0x15","to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb","transactionIndex":"0x40","value":"0xf3dbb76162000","type":"0x0","v":"0x25","r":"0x96","s":"0xfa"}}
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b","blockNumber":"0x5daf3b","from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d","gas":"0xc350","gasPrice":"0x4a817c800","hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b","input":"0x3078363836353663366336663231","nonce":"0x15","to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb","transactionIndex":"0x40","value":"0xf3dbb76162000","type":"0x0","v":"0x25","r":"0x96","s":"0xfa"}}
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2","blockNumber":"0x5daf3b","from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d","gas":"0xc350","gasPrice":"0x4a817c800","hash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b","input":"0x3078363836353663366336663231","nonce":"0x15","to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb","transactionIndex":"0x40","value":"0xf3dbb76162000","type":"0x0","v":"0x25","r":"0x96","s":"0xfa"}}
{"jsonrpc":"2.0","id":1,"result":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb"}
Expand Down
30 changes: 30 additions & 0 deletions api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,36 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) {

assert.Equal(t, expectedResponse, strings.TrimSuffix(string(content), "\n"))
})

t.Run("eth_getTransactionByHash", func(t *testing.T) {
request := `{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c"]}`
expectedResponse := `{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2","blockNumber":"0x3","from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d","gas":"0x57f2","gasPrice":"0x0","hash":"0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c","input":"0xc6888fa10000000000000000000000000000000000000000000000000000000000000006","nonce":"0x1","to":"0x99466ed2e37b892a2ee3e9cd55a98b68f5735db2","transactionIndex":"0x0","value":"0x0","type":"0x2","v":"0x1","r":"0xf84168f821b427dc158c4d8083bdc4b43e178cf0977a2c5eefbcbedcc4e351b0","s":"0x66a747a38c6c266b9dc2136523cef04395918de37773db63d574aabde59c12eb"}}`

event := transactionExecutedEvent(
3,
"0xb47d74ea64221eb941490bdc0c9a404dacd0a8573379a45c992ac60ee3e83c3c",
"b88c02f88982029a01808083124f809499466ed2e37b892a2ee3e9cd55a98b68f5735db280a4c6888fa10000000000000000000000000000000000000000000000000000000000000006c001a0f84168f821b427dc158c4d8083bdc4b43e178cf0977a2c5eefbcbedcc4e351b0a066a747a38c6c266b9dc2136523cef04395918de37773db63d574aabde59c12eb",
false,
2,
22514,
"0000000000000000000000000000000000000000",
"000000000000000000000000000000000000000000000000000000000000002a",
"f85af8589499466ed2e37b892a2ee3e9cd55a98b68f5735db2e1a024abdb5865df5079dcc5ac590ff6f01d5c16edbc5fab4e195d9febd1114503daa0000000000000000000000000000000000000000000000000000000000000002a",
)

err := store.StoreTransaction(context.Background(), event)
require.NoError(t, err)

resp := rpcRequest(url, request, "origin", "test.com")
defer resp.Body.Close()

content, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}

assert.Equal(t, expectedResponse, strings.TrimSuffix(string(content), "\n"))
})
}

func TestServerJSONRPCOveWebSocketHandler(t *testing.T) {
Expand Down

0 comments on commit 4d4d3d3

Please sign in to comment.