From e56bd994ffb77860ed1219de6ab9d202241adf2b Mon Sep 17 00:00:00 2001 From: KonradStaniec Date: Mon, 21 Nov 2022 13:28:15 +0100 Subject: [PATCH] Add eth_getCode to lc proxy (#1310) --- lc_proxy/rpc/rpc_eth_lc_api.nim | 40 +++++++++++++++++++++++++++++++++ lc_proxy/validate_proof.nim | 4 +++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lc_proxy/rpc/rpc_eth_lc_api.nim b/lc_proxy/rpc/rpc_eth_lc_api.nim index 16007f620..12b2c9b80 100644 --- a/lc_proxy/rpc/rpc_eth_lc_api.nim +++ b/lc_proxy/rpc/rpc_eth_lc_api.nim @@ -13,6 +13,7 @@ import stew/[byteutils, results], chronicles, json_rpc/[rpcproxy, rpcserver, rpcclient], + eth/common/eth_types as etypes, web3, web3/[ethhexstrings, ethtypes], beacon_chain/eth1/eth1_monitor, @@ -34,6 +35,9 @@ template encodeQuantity(value: UInt256): HexQuantityStr = template encodeHexData(value: UInt256): HexDataStr = hexDataStr("0x" & toBytesBE(value).toHex) +template bytesToHex(bytes: seq[byte]): HexDataStr = + hexDataStr("0x" & toHex(bytes)) + template encodeQuantity(value: Quantity): HexQuantityStr = hexQuantityStr(encodeQuantity(value.uint64)) @@ -192,6 +196,42 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) = else: raise newException(ValueError, accountResult.error) + lcProxy.proxy.rpc("eth_getCode") do(address: Address, quantityTag: string) -> HexDataStr: + let + executionPayload = lcProxy.getPayloadByTag(quantityTag) + blockNumber = executionPayload.blockNumber.uint64 + + let + proof = await lcProxy.rpcClient.eth_getProof(address, @[], blockId(blockNumber)) + accountResult = getAccountFromProof( + executionPayload.stateRoot, + proof.address, + proof.balance, + proof.nonce, + proof.codeHash, + proof.storageHash, + proof.accountProof + ) + + if accountResult.isErr(): + raise newException(ValueError, accountResult.error) + + let account = accountResult.get() + + if account.codeHash == etypes.EMPTY_CODE_HASH: + # account does not have any code, return empty hex data + return hexDataStr("0x") + + let code = await lcProxy.rpcClient.eth_getCode( + address, + blockId(blockNumber) + ) + + if isValidCode(account, code): + return bytesToHex(code) + else: + raise newException(ValueError, "received code which does not match account code hash") + # TODO This methods are forwarded directly to provider therefore thay are not # validated in any way lcProxy.proxy.registerProxyMethod("net_version") diff --git a/lc_proxy/validate_proof.nim b/lc_proxy/validate_proof.nim index f39e672c8..f65180d36 100644 --- a/lc_proxy/validate_proof.nim +++ b/lc_proxy/validate_proof.nim @@ -95,7 +95,6 @@ proc getStorageData( of InvalidProof: return err(proofResult.errorMsg) - proc getStorageData*( stateRoot: FixedBytes[32], requestedSlot: UInt256, @@ -128,3 +127,6 @@ proc getStorageData*( return err("received proof for invalid slot") return getStorageData(account, sproof) + +func isValidCode*(account: etypes.Account, code: openArray[byte]): bool = + return account.codeHash == keccakHash(code)