diff --git a/lc_proxy/lc_proxy.nim b/lc_proxy/lc_proxy.nim index 8a51c5600..9496e8de0 100644 --- a/lc_proxy/lc_proxy.nim +++ b/lc_proxy/lc_proxy.nim @@ -14,6 +14,7 @@ import std/[os, strutils], chronicles, chronicles/chronos_tools, chronos, eth/keys, + json_rpc/[rpcserver, rpcclient], beacon_chain/eth1/eth1_monitor, beacon_chain/gossip_processing/optimistic_processor, beacon_chain/networking/topic_params, @@ -27,16 +28,16 @@ from beacon_chain/consensus_object_pools/consensus_manager import runForkchoiceU from beacon_chain/gossip_processing/block_processor import newExecutionPayload from beacon_chain/gossip_processing/eth2_processor import toValidationResult -proc initRpcProxy(config: LcProxyConf): RpcProxy {.raises: [CatchableError, Defect].} = - let ta = initTAddress(config.rpcAddress, config.rpcPort) - let clientConfig = - case config.web3ClientConfig.kind - of WsClient: - getWebSocketClientConfig(config.web3ClientConfig.url) - of HttpClient: - getHttpClientConfig(config.web3ClientConfig.url) - - return RpcProxy.new([ta], clientConfig) +proc initRpcClient(config: LcProxyConf): Future[RpcClient] {.async.} = + case config.web3ClientConfig.kind + of WsClient: + let wssClient = newRpcWebSocketClient() + await wssClient.connect(config.web3ClientConfig.url) + return wssClient + of HttpClient: + let httpClient = newRpcHttpClient() + await httpClient.connect(config.web3ClientConfig.url) + return httpClient # TODO Find what can throw exception proc run() {.raises: [Exception, Defect].} = @@ -88,9 +89,13 @@ proc run() {.raises: [Exception, Defect].} = forkDigests, getBeaconTime, genesis_validators_root ) - rpcServerWithProxy = initRpcProxy(config) + rpcClient = waitFor initRpcClient(config) - lcProxy = LightClientRpcProxy(proxy: rpcServerWithProxy) + rpcHttpServer = newRpcHttpServer( + [initTAddress(config.rpcAddress, config.rpcPort)] + ) + + lcProxy = LightClientRpcProxy(server: rpcHttpServer, client: rpcClient) optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock): Future[void] {.async.} = @@ -135,7 +140,7 @@ proc run() {.raises: [Exception, Defect].} = waitFor network.startListening() waitFor network.start() - waitFor lcProxy.proxy.start() + lcProxy.server.start() proc onFinalizedHeader( lightClient: LightClient, finalizedHeader: BeaconBlockHeader) = diff --git a/lc_proxy/rpc/rpc_eth_lc_api.nim b/lc_proxy/rpc/rpc_eth_lc_api.nim index c18cdae40..6a7c6ddeb 100644 --- a/lc_proxy/rpc/rpc_eth_lc_api.nim +++ b/lc_proxy/rpc/rpc_eth_lc_api.nim @@ -8,44 +8,63 @@ {.push raises: [Defect].} import - json_rpc/[rpcproxy, rpcserver], - web3/conversions, - ../../nimbus/rpc/[hexstrings, rpc_types], + stint, + chronicles, + json_rpc/[rpcserver, rpcclient], + web3, + web3/ethhexstrings, beacon_chain/eth1/eth1_monitor, beacon_chain/spec/forks -export rpcproxy, forks +export forks + +logScope: + topics = "light_proxy" template encodeQuantity(value: UInt256): HexQuantityStr = - HexQuantityStr("0x" & value.toHex()) + hexQuantityStr("0x" & value.toHex()) -proc encodeQuantity(q: Quantity): hexstrings.HexQuantityStr = - return hexstrings.encodeQuantity(distinctBase(q)) +template encodeQuantity(value: Quantity): HexQuantityStr = + hexQuantityStr(encodeQuantity(value.uint64)) type LightClientRpcProxy* = ref object - proxy*: RpcProxy + client*: RpcClient + server*: RpcHttpServer executionPayload*: Opt[ExecutionPayloadV1] proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) = template payload(): Opt[ExecutionPayloadV1] = lcProxy.executionPayload - lcProxy.proxy.rpc("eth_blockNumber") do() -> HexQuantityStr: + lcProxy.server.rpc("eth_blockNumber") do() -> HexQuantityStr: ## Returns the number of most recent block. if payload.isNone: raise newException(ValueError, "Syncing") return encodeQuantity(payload.get.blockNumber) - lcProxy.proxy.rpc("eth_getBlockByNumber") do( - quantityTag: string, fullTransactions: bool) -> Option[rpc_types.BlockObject]: - ## Returns information about a block by number. + # TODO quantity tag should be better typed + lcProxy.server.rpc("eth_getBalance") do(address: Address, quantityTag: string) -> HexQuantityStr: if payload.isNone: raise newException(ValueError, "Syncing") if quantityTag != "latest": + # TODO for now we support only latest block, as its semanticly most streight + # forward i.e it is last received and valid ExecutionPayloadV1. + # Ultimatly we could keep track of n last valid payload and support number + # queries for this set of blocks + # `Pending` coud be mapped to some optimisc header with block fetched on demand raise newException(ValueError, "Only latest block is supported") - if fullTransactions: - raise newException(ValueError, "Transaction bodies not supported") + # When requesting state for `latest` block number, we need to translate + # `latest` to actual block number as `latest` on proxy and on data provider + # can mean different blocks and ultimatly piece received piece of state + # must by validated against correct state root + let blockNumber = payload.get.blockNumber.uint64 - return some rpc_types.BlockObject(number: some(encodeQuantity(payload.get.blockNumber))) + info "Forwarding get_Balance", executionBn = blockNumber + + # TODO this could be realised by eth_getProof as it return also balance + # of the account + let b = await lcProxy.client.eth_getBalance(address, blockId(blockNumber)) + + return encodeQuantity(b) diff --git a/vendor/nimbus-eth2 b/vendor/nimbus-eth2 index 64972e3c8..59092e5b3 160000 --- a/vendor/nimbus-eth2 +++ b/vendor/nimbus-eth2 @@ -1 +1 @@ -Subproject commit 64972e3c8a6eccc49054e95a893048916b1806a4 +Subproject commit 59092e5b3bc38ed42995fc7276f7c4601b890988