Add eth_chainId endpoint to light client proxy (#1232)

* Add eth_chainId endpoint
This commit is contained in:
KonradStaniec 2022-09-21 18:44:46 +02:00 committed by GitHub
parent a5dc16537e
commit 519f78388e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 7 deletions

View File

@ -39,6 +39,20 @@ proc initRpcClient(config: LcProxyConf): Future[RpcClient] {.async.} =
await httpClient.connect(config.web3ClientConfig.url)
return httpClient
func getConfiguredChainId(networkMetadata: Eth2NetworkMetadata): Quantity =
if networkMetadata.eth1Network.isSome():
let
net = networkMetadata.eth1Network.get()
chainId = case net
of mainnet: 1.Quantity
of ropsten: 3.Quantity
of rinkeby: 4.Quantity
of goerli: 5.Quantity
of sepolia: 11155111.Quantity
return chainId
else:
return networkMetadata.cfg.DEPOSIT_CHAIN_ID.Quantity
# TODO Find what can throw exception
proc run() {.raises: [Exception, Defect].} =
{.pop.}
@ -54,7 +68,9 @@ proc run() {.raises: [Exception, Defect].} =
notice "Launching light client proxy",
version = fullVersionStr, cmdParams = commandLineParams(), config
let metadata = loadEth2Network(config.eth2Network)
let
metadata = loadEth2Network(config.eth2Network)
chainId = getConfiguredChainId(metadata)
for node in metadata.bootstrapNodes:
lcConfig.bootstrapNodes.add node
@ -95,7 +111,7 @@ proc run() {.raises: [Exception, Defect].} =
[initTAddress(config.rpcAddress, config.rpcPort)]
)
lcProxy = LightClientRpcProxy(server: rpcHttpServer, client: rpcClient)
lcProxy = LightClientRpcProxy.new(rpcHttpServer, rpcClient, chainId)
optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock):
Future[void] {.async.} =
@ -140,7 +156,8 @@ proc run() {.raises: [Exception, Defect].} =
waitFor network.startListening()
waitFor network.start()
lcProxy.server.start()
rpcHttpServer.start()
waitFor lcProxy.verifyChaindId()
proc onFinalizedHeader(
lightClient: LightClient, finalizedHeader: BeaconBlockHeader) =

View File

@ -13,8 +13,9 @@ import
chronicles,
json_rpc/[rpcserver, rpcclient],
web3,
web3/ethhexstrings,
web3/[ethhexstrings, ethtypes],
beacon_chain/eth1/eth1_monitor,
beacon_chain/networking/network_metadata,
beacon_chain/spec/forks,
../validate_proof
@ -23,10 +24,11 @@ export forks
logScope:
topics = "light_proxy"
proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.}
template encodeQuantity(value: UInt256): HexQuantityStr =
hexQuantityStr("0x" & value.toHex())
template encodeHexData(value: UInt256): HexDataStr =
hexDataStr("0x" & toBytesBE(value).toHex)
@ -35,9 +37,9 @@ template encodeQuantity(value: Quantity): HexQuantityStr =
type LightClientRpcProxy* = ref object
client*: RpcClient
server*: RpcHttpServer
server*: RpcServer
executionPayload*: Opt[ExecutionPayloadV1]
chainId: Quantity
template checkPreconditions(payload: Opt[ExecutionPayloadV1], quantityTag: string) =
if payload.isNone():
@ -55,6 +57,9 @@ template checkPreconditions(payload: Opt[ExecutionPayloadV1], quantityTag: strin
proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
template payload(): Opt[ExecutionPayloadV1] = lcProxy.executionPayload
lcProxy.server.rpc("eth_chainId") do() -> HexQuantityStr:
return encodeQuantity(lcProxy.chainId)
lcProxy.server.rpc("eth_blockNumber") do() -> HexQuantityStr:
## Returns the number of most recent block.
if payload.isNone:
@ -112,3 +117,37 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
return encodeHexData(slotValue)
else:
raise newException(ValueError, dataResult.error)
proc new*(
T: type LightClientRpcProxy,
server: RpcServer,
client: RpcClient,
chainId: Quantity): T =
return LightClientRpcProxy(
client: client,
server: server,
chainId: chainId
)
proc verifyChaindId*(p: LightClientRpcProxy): Future[void] {.async.} =
let localId = p.chainId
# retry 2 times, if the data provider will fail despite re-tries, propagate
# exception to the caller.
let providerId = awaitWithRetries(
p.client.eth_chainId(),
retries = 2,
timeout = seconds(30)
)
# this configuration error, in theory we could allow proxy to chung on, but
# it would only mislead the user. It is better to fail fast here.
if localId != providerId:
fatal "The specified data provider serves data for a different chain",
expectedChain = distinctBase(localId),
providerChain = distinctBase(providerId)
quit 1
return