Skip to content

Commit

Permalink
Merge pull request #29 from m-Peter/eth-get-block-by-number-endpoint
Browse files Browse the repository at this point in the history
Implement `eth_getBlockByNumber` RPC endpoint
  • Loading branch information
m-Peter authored Jan 26, 2024
2 parents 96a9e6e + a42bb6a commit 81219d9
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 31 deletions.
18 changes: 13 additions & 5 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,26 +374,34 @@ func (s *BlockChainAPI) GetBlockByNumber(
fullTx bool,
) (map[string]interface{}, error) {
block := map[string]interface{}{}

blockExecutedPayload, err := s.Store.GetBlockByNumber(ctx, uint64(blockNumber))
if err != nil {
return block, err
}

block["number"] = hexutil.Uint64(blockExecutedPayload.Height)
block["hash"] = blockExecutedPayload.Hash
block["parentHash"] = blockExecutedPayload.ParentBlockHash
block["receiptsRoot"] = blockExecutedPayload.ReceiptRoot
block["transactions"] = blockExecutedPayload.TransactionHashes

block["difficulty"] = "0x4ea3f27bc"
block["extraData"] = "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32"
block["gasLimit"] = "0x1388"
block["gasUsed"] = "0x0"
block["hash"] = "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae"
block["logsBloom"] = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
block["miner"] = "0xbb7b8287f3f0a933474a79eae42cbca977791171"
block["mixHash"] = "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843"
block["nonce"] = "0x689056015818adbe"
block["number"] = "0x1b4"
block["parentHash"] = "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54"
block["receiptsRoot"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
block["sha3Uncles"] = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
block["size"] = "0x220"
block["stateRoot"] = "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d"
block["timestamp"] = "0x55ba467c"
block["totalDifficulty"] = "0x78ed983323d"
block["transactions"] = []string{}
block["transactionsRoot"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
block["uncles"] = []string{}

return block, nil
}

Expand Down
99 changes: 92 additions & 7 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,37 @@ func TestBlockChainAPI(t *testing.T) {

t.Run("BlockNumber", func(t *testing.T) {
blockNumber := blockchainAPI.BlockNumber()

assert.Equal(t, hexutil.Uint64(0), blockNumber)

event := blockExecutedEvent(
1,
"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9",
7766279631452241920,
"0xe81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
[]string{"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"},
)
store := blockchainAPI.Store
err := store.StoreBlock(context.Background(), event)
require.NoError(t, err)

blockNumber = blockchainAPI.BlockNumber()
assert.Equal(t, hexutil.Uint64(1), blockNumber)

event = blockExecutedEvent(
2,
"0xaae4530246e61ae58479824ab0863f99ca50414d27aec0c269ae6a7cfc4c7f5b",
7766279631452241920,
"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9",
"0x0000000000000000000000000000000000000000000000000000000000000000",
[]string{"0xaae4530246e61ae58479824ab0863f99ca50414d27aec0c269ae6a7cfc4c7f5b"},
)

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

blockNumber = blockchainAPI.BlockNumber()
assert.Equal(t, hexutil.Uint64(2), blockNumber)
})

t.Run("Syncing", func(t *testing.T) {
Expand Down Expand Up @@ -370,32 +399,45 @@ func TestBlockChainAPI(t *testing.T) {
})

t.Run("GetBlockByNumber", func(t *testing.T) {
event := blockExecutedEvent(
1,
"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9",
7766279631452241920,
"0xe81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
[]string{"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"},
)
store := blockchainAPI.Store
err := store.StoreBlock(context.Background(), event)
require.NoError(t, err)

block, err := blockchainAPI.GetBlockByNumber(
context.Background(),
rpc.PendingBlockNumber,
rpc.BlockNumber(1),
false,
)
require.NoError(t, err)

expectedBlock := map[string]interface{}{}
expectedBlock["number"] = hexutil.Uint64(1)
expectedBlock["hash"] = "0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"
expectedBlock["parentHash"] = "0xe81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0"
expectedBlock["receiptsRoot"] = "0x0000000000000000000000000000000000000000000000000000000000000000"
expectedBlock["transactions"] = []string{"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"}

expectedBlock["difficulty"] = "0x4ea3f27bc"
expectedBlock["extraData"] = "0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32"
expectedBlock["gasLimit"] = "0x1388"
expectedBlock["gasUsed"] = "0x0"
expectedBlock["hash"] = "0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae"
expectedBlock["logsBloom"] = "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
expectedBlock["miner"] = "0xbb7b8287f3f0a933474a79eae42cbca977791171"
expectedBlock["mixHash"] = "0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843"
expectedBlock["nonce"] = "0x689056015818adbe"
expectedBlock["number"] = "0x1b4"
expectedBlock["parentHash"] = "0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54"
expectedBlock["receiptsRoot"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
expectedBlock["sha3Uncles"] = "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
expectedBlock["size"] = "0x220"
expectedBlock["stateRoot"] = "0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d"
expectedBlock["timestamp"] = "0x55ba467c"
expectedBlock["totalDifficulty"] = "0x78ed983323d"
expectedBlock["transactions"] = []string{}
expectedBlock["transactionsRoot"] = "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
expectedBlock["uncles"] = []string{}

Expand Down Expand Up @@ -802,3 +844,46 @@ func transactionExecutedEvent(
},
}
}

func blockExecutedEvent(
blockHeight uint64,
blockHash string,
totalSupply uint64,
parentBlockHash string,
receiptRoot string,
transactionHashes []string,
) cadence.Event {
hashes := make([]cadence.Value, len(transactionHashes))
for i, hash := range transactionHashes {
hashes[i] = cadence.String(hash)
}

return cadence.Event{
EventType: cadence.NewEventType(
stdlib.FlowLocation{},
"evm.BlockExecuted",
[]cadence.Field{
cadence.NewField("blockHeight", cadence.UInt64Type{}),
cadence.NewField("blockHash", cadence.StringType{}),
cadence.NewField("totalSupply", cadence.UInt64Type{}),
cadence.NewField("parentBlockHash", cadence.StringType{}),
cadence.NewField("receiptRoot", cadence.StringType{}),
cadence.NewField(
"transactionHashes",
cadence.NewVariableSizedArrayType(cadence.StringType{}),
),
},
nil,
),
Fields: []cadence.Value{
cadence.NewUInt64(blockHeight),
cadence.String(blockHash),
cadence.NewUInt64(totalSupply),
cadence.String(parentBlockHash),
cadence.String(receiptRoot),
cadence.NewArray(hashes).WithType(
cadence.NewVariableSizedArrayType(cadence.StringType{}),
),
},
}
}
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 @@ -13,7 +13,6 @@
{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x85d995eba9763907fdf35cd2034144dd9d53ce32cbec21349d4b12823c6860c5"]}
{"jsonrpc":"2.0","id":1,"method":"eth_coinbase"}
{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByHash","params":["0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae",false]}
{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x1b4",true]}
{"jsonrpc":"2.0","id":1,"method":"eth_getBlockTransactionCountByHash","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getBlockTransactionCountByNumber","params":["0xe8"]}
{"jsonrpc":"2.0","id":1,"method":"eth_getUncleCountByBlockHash","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"]}
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 @@ -13,7 +13,6 @@
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2","blockNumber":"0x5daf3b","contractAddress":null,"cumulativeGasUsed":"0xc350","effectiveGasPrice":"0x4a817c800","from":"0xa7d9ddbe1f17865597fbd27ec712455208b6b76d","gasUsed":"0x9c40","logs":[],"logsBloom":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b","status":"0x1","to":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb","transactionHash":"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b","transactionIndex":"0x40","type":"0x2"}}
{"jsonrpc":"2.0","id":1,"result":"0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb"}
{"jsonrpc":"2.0","id":1,"result":{"difficulty":"0x4ea3f27bc","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","gasLimit":"0x1388","gasUsed":"0x0","hash":"0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","mixHash":"0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843","nonce":"0x689056015818adbe","number":"0x1b4","parentHash":"0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","stateRoot":"0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d","timestamp":"0x55ba467c","totalDifficulty":"0x78ed983323d","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}}
{"jsonrpc":"2.0","id":1,"result":{"difficulty":"0x4ea3f27bc","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","gasLimit":"0x1388","gasUsed":"0x0","hash":"0xdc0818cf78f21a8e70579cb46a43643f78291264dda342ae31049421c82d21ae","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","mixHash":"0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843","nonce":"0x689056015818adbe","number":"0x1b4","parentHash":"0xe99e022112df268087ea7eafaf4790497fd21dbeeb6bd7a1721df161a6657a54","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","stateRoot":"0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d","timestamp":"0x55ba467c","totalDifficulty":"0x78ed983323d","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}}
{"jsonrpc":"2.0","id":1,"result":"0x188aa"}
{"jsonrpc":"2.0","id":1,"result":"0x20a"}
{"jsonrpc":"2.0","id":1,"result":"0x0"}
Expand Down
28 changes: 28 additions & 0 deletions api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api_test

import (
"bytes"
"context"
_ "embed"
"io"
"net/http"
Expand All @@ -15,6 +16,7 @@ import (
"github.com/onflow/flow-evm-gateway/storage"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

//go:embed fixtures/eth_json_rpc_requests.json
Expand Down Expand Up @@ -53,6 +55,32 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) {

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

t.Run("eth_getBlockByNumber", func(t *testing.T) {
request := `{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["0x1",false]}`
expectedResponse := `{"jsonrpc":"2.0","id":1,"result":{"difficulty":"0x4ea3f27bc","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","gasLimit":"0x1388","gasUsed":"0x0","hash":"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","mixHash":"0x4fffe9ae21f1c9e15207b1f472d5bbdd68c9595d461666602f2be20daf5e7843","nonce":"0x689056015818adbe","number":"0x1","parentHash":"0xe81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","stateRoot":"0xddc8b0234c2e0cad087c8b389aa7ef01f7d79b2570bccb77ce48648aa61c904d","timestamp":"0x55ba467c","totalDifficulty":"0x78ed983323d","transactions":["0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]}}`

event := blockExecutedEvent(
1,
"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9",
7766279631452241920,
"0xe81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421c0",
"0x0000000000000000000000000000000000000000000000000000000000000000",
[]string{"0xf31ee13dad8f38431fd31278b12be62e6b77e6923f0b7a446eb1affb61f21fc9"},
)
err := store.StoreBlock(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
7 changes: 4 additions & 3 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,16 @@ func runIndexer(ctx context.Context, store *storage.Store, logger zerolog.Logger
}

logger.Info().Msgf("block %d %s:", response.Height, response.BlockID)
if len(response.Events) > 0 {
store.StoreBlockHeight(ctx, response.Height)
}

for _, event := range response.Events {
logger.Info().Msgf(" %s", event.Value)
if event.Type == "flow.evm.TransactionExecuted" {
store.UpdateAccountNonce(ctx, event.Value)
store.StoreLog(ctx, event.Value)
}
if event.Type == "flow.evm.BlockExecuted" {
store.StoreBlock(ctx, event.Value)
}
}

lastHeight = response.Height
Expand Down
Loading

0 comments on commit 81219d9

Please sign in to comment.