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,65 +346,125 @@ 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]:
# ## 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.
# # TODO
# raiseAssert("Not implemented")
# rpcServerWithProxy.rpc("eth_getProof") do( rpcServerWithProxy.rpc("eth_getTransactionCount") do(
# address: Address, slots: seq[UInt256], quantityTag: RtBlockIdentifier data: web3Types.Address, quantityTag: RtBlockIdentifier
# ) -> ProofResponse: ) -> Quantity:
# ## Returns information about an account and storage slots (if the account is a contract ## Returns the number of transactions sent from an address.
# ## and the slots are requested) along with account and storage proofs which prove the ##
# ## existence of the values in the state. ## data: address.
# ## See spec here: https://eips.ethereum.org/EIPS/eip-1186 ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# ## ## Returns integer of the number of transactions send from this address.
# ## data: address of the account. if stateNetwork.isNone():
# ## slots: integers of the positions in the storage to return with storage proofs. raise newException(ValueError, "State sub-network not enabled")
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# ## Returns: the proof response containing the account, account proof and storage proof if quantityTag.kind == bidAlias:
# # TODO # TODO: Implement
# raiseAssert("Not implemented") 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(
# address: Address, slots: seq[UInt256], quantityTag: RtBlockIdentifier
# ) -> ProofResponse:
# ## Returns information about an account and storage slots (if the account is a contract
# ## and the slots are requested) along with account and storage proofs which prove the
# ## existence of the values in the state.
# ## See spec here: https://eips.ethereum.org/EIPS/eip-1186
# ##
# ## data: address of the account.
# ## slots: integers of the positions in the storage to return with storage proofs.
# ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter.
# ## Returns: the proof response containing the account, account proof and storage proof
# # TODO
# raiseAssert("Not implemented")