Implement Fluffy JSON-RPC endpoints. (#2364)

* Implement eth_getBalance, eth_getTransactionCount, eth_getStorageAt and eth_getCode JSON-RPCs.

* Fixes.
This commit is contained in:
web3-developer 2024-06-15 01:03:18 +08:00 committed by GitHub
parent 4c458190e9
commit 1377f93d50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 124 additions and 60 deletions

View File

@ -349,7 +349,7 @@ proc run(config: PortalConf) {.raises: [CatchableError].} =
) )
if historyNetwork.isSome(): if historyNetwork.isSome():
rpcHttpServerWithProxy.installEthApiHandlers( rpcHttpServerWithProxy.installEthApiHandlers(
historyNetwork.get(), beaconLightClient historyNetwork.get(), beaconLightClient, stateNetwork
) )
rpcHttpServerWithProxy.installPortalApiHandlers( rpcHttpServerWithProxy.installPortalApiHandlers(
historyNetwork.get().portalProtocol, "history" historyNetwork.get().portalProtocol, "history"

View File

@ -223,7 +223,8 @@ proc processContentLoop(n: StateNetwork) {.async: (raises: []).} =
trace "processContentLoop canceled" trace "processContentLoop canceled"
proc start*(n: StateNetwork) = proc start*(n: StateNetwork) =
info "Starting Portal State Network", protocolId = n.portalProtocol.protocolId info "Starting Portal execution state network",
protocolId = n.portalProtocol.protocolId
n.portalProtocol.start() n.portalProtocol.start()
n.processContentLoop = processContentLoop(n) n.processContentLoop = processContentLoop(n)

View File

@ -12,9 +12,11 @@ import
json_rpc/[rpcproxy, rpcserver], json_rpc/[rpcproxy, rpcserver],
web3/conversions, # sigh, for FixedBytes marshalling web3/conversions, # sigh, for FixedBytes marshalling
web3/eth_api_types, web3/eth_api_types,
eth/[common/eth_types, rlp], web3/primitives as web3types,
eth/common/eth_types,
beacon_chain/spec/forks, beacon_chain/spec/forks,
../network/history/[history_network, history_content], ../network/history/[history_network, history_content],
../network/state/[state_network, state_content, state_endpoints],
../network/beacon/beacon_light_client ../network/beacon/beacon_light_client
from ../../nimbus/transaction import getSender, ValidationError from ../../nimbus/transaction import getSender, ValidationError
@ -127,6 +129,7 @@ proc installEthApiHandlers*(
rpcServerWithProxy: var RpcProxy, rpcServerWithProxy: var RpcProxy,
historyNetwork: HistoryNetwork, historyNetwork: HistoryNetwork,
beaconLightClient: Opt[LightClient], beaconLightClient: Opt[LightClient],
stateNetwork: Opt[StateNetwork],
) = ) =
# Supported API # Supported API
rpcServerWithProxy.registerProxyMethod("eth_blockNumber") rpcServerWithProxy.registerProxyMethod("eth_blockNumber")
@ -343,53 +346,113 @@ proc installEthApiHandlers*(
return filteredLogs return filteredLogs
else: else:
# bloomfilter returned false, there are no logs matching the criteria # bloomfilter returned false, there are no logs matching the criteria
return return @[]
@[]
# rpcServerWithProxy.rpc("eth_getBalance") do( rpcServerWithProxy.rpc("eth_getBalance") do(
# data: Address, quantityTag: RtBlockIdentifier data: web3Types.Address, quantityTag: RtBlockIdentifier
# ) -> UInt256: ) -> UInt256:
# ## Returns the balance of the account of given address. ## Returns the balance of the account of given address.
# ## ##
# ## data: address to check for balance. ## data: address to check for balance.
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter. ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# ## Returns integer of the current balance in wei. ## Returns integer of the current balance in wei.
# # TODO if stateNetwork.isNone():
# raiseAssert("Not implemented") raise newException(ValueError, "State sub-network not enabled")
# rpcServerWithProxy.rpc("eth_getTransactionCount") do( if quantityTag.kind == bidAlias:
# data: Address, quantityTag: RtBlockIdentifier # TODO: Implement
# ) -> Quantity: raise newException(ValueError, "tag not yet implemented")
# ## Returns the number of transactions sent from an address. else:
# ## let
# ## data: address. blockNumber = quantityTag.number.uint64.u256
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter. blockHash = (await historyNetwork.getBlockHashByNumber(blockNumber)).valueOr:
# ## Returns integer of the number of transactions send from this address. raise newException(ValueError, error)
# # TODO
# raiseAssert("Not implemented")
# rpcServerWithProxy.rpc("eth_getStorageAt") do( balance = (await stateNetwork.get().getBalance(blockHash, data.EthAddress)).valueOr:
# data: Address, slot: UInt256, quantityTag: RtBlockIdentifier # Should we return 0 here or throw a more detailed error?
# ) -> FixedBytes[32]: raise newException(ValueError, "Unable to get balance")
# ## Returns the value from a storage position at a given address.
# ##
# ## data: address of the storage.
# ## slot: integer of the position in the storage.
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# ## Returns: the value at this storage position.
# # TODO
# raiseAssert("Not implemented")
# rpcServerWithProxy.rpc("eth_getCode") do( return balance
# data: Address, quantityTag: RtBlockIdentifier
# ) -> seq[byte]: rpcServerWithProxy.rpc("eth_getTransactionCount") do(
# ## Returns code at a given address. data: web3Types.Address, quantityTag: RtBlockIdentifier
# ## ) -> Quantity:
# ## data: address ## Returns the number of transactions sent from an address.
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter. ##
# ## Returns the code from the given address. ## data: address.
# # TODO ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# raiseAssert("Not implemented") ## Returns integer of the number of transactions send from this address.
if stateNetwork.isNone():
raise newException(ValueError, "State sub-network not enabled")
if quantityTag.kind == bidAlias:
# TODO: Implement
raise newException(ValueError, "tag not yet implemented")
else:
let
blockNumber = quantityTag.number.uint64.u256
blockHash = (await historyNetwork.getBlockHashByNumber(blockNumber)).valueOr:
raise newException(ValueError, error)
nonce = (
await stateNetwork.get().getTransactionCount(blockHash, data.EthAddress)
).valueOr:
# Should we return 0 here or throw a more detailed error?
raise newException(ValueError, "Unable to get transaction count")
return nonce.Quantity
rpcServerWithProxy.rpc("eth_getStorageAt") do(
data: web3Types.Address, slot: UInt256, quantityTag: RtBlockIdentifier
) -> FixedBytes[32]:
## Returns the value from a storage position at a given address.
##
## data: address of the storage.
## slot: integer of the position in the storage.
## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
## Returns: the value at this storage position.
if stateNetwork.isNone():
raise newException(ValueError, "State sub-network not enabled")
if quantityTag.kind == bidAlias:
# TODO: Implement
raise newException(ValueError, "tag not yet implemented")
else:
let
blockNumber = quantityTag.number.uint64.u256
blockHash = (await historyNetwork.getBlockHashByNumber(blockNumber)).valueOr:
raise newException(ValueError, error)
slotValue = (
await stateNetwork.get().getStorageAt(blockHash, data.EthAddress, slot)
).valueOr:
# Should we return 0 here or throw a more detailed error?
raise newException(ValueError, "Unable to get storage slot")
return FixedBytes[32](slotValue.toBytesBE())
rpcServerWithProxy.rpc("eth_getCode") do(
data: web3Types.Address, quantityTag: RtBlockIdentifier
) -> seq[byte]:
## Returns code at a given address.
##
## data: address
## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
## Returns the code from the given address.
if stateNetwork.isNone():
raise newException(ValueError, "State sub-network not enabled")
if quantityTag.kind == bidAlias:
# TODO: Implement
raise newException(ValueError, "tag not yet implemented")
else:
let
blockNumber = quantityTag.number.uint64.u256
blockHash = (await historyNetwork.getBlockHashByNumber(blockNumber)).valueOr:
raise newException(ValueError, error)
bytecode = (await stateNetwork.get().getCode(blockHash, data.EthAddress)).valueOr:
# Should we return empty sequence here or throw a more detailed error?
raise newException(ValueError, "Unable to get code")
return bytecode.asSeq()
# rpcServerWithProxy.rpc("eth_getProof") do( # rpcServerWithProxy.rpc("eth_getProof") do(
# address: Address, slots: seq[UInt256], quantityTag: RtBlockIdentifier # address: Address, slots: seq[UInt256], quantityTag: RtBlockIdentifier