Use rpcProxy in lc proxy (#1238)
* Use rpcProxy in lc proxy * Remove nimbus config from cors handler
This commit is contained in:
parent
8dff89ecad
commit
2b7bc4f2ef
|
@ -14,31 +14,20 @@ import
|
|||
std/[os, strutils],
|
||||
chronicles, chronicles/chronos_tools, chronos,
|
||||
eth/keys,
|
||||
json_rpc/[rpcserver, rpcclient],
|
||||
json_rpc/rpcproxy,
|
||||
beacon_chain/eth1/eth1_monitor,
|
||||
beacon_chain/gossip_processing/optimistic_processor,
|
||||
beacon_chain/networking/topic_params,
|
||||
beacon_chain/spec/beaconstate,
|
||||
beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
|
||||
beacon_chain/[light_client, nimbus_binary_common, version],
|
||||
../nimbus/rpc/cors,
|
||||
./rpc/rpc_eth_lc_api,
|
||||
./lc_proxy_conf
|
||||
|
||||
from beacon_chain/consensus_object_pools/consensus_manager import runForkchoiceUpdated
|
||||
from beacon_chain/gossip_processing/block_processor import newExecutionPayload
|
||||
from beacon_chain/gossip_processing/eth2_processor import toValidationResult
|
||||
|
||||
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
|
||||
|
||||
func getConfiguredChainId(networkMetadata: Eth2NetworkMetadata): Quantity =
|
||||
if networkMetadata.eth1Network.isSome():
|
||||
let
|
||||
|
@ -105,13 +94,18 @@ proc run() {.raises: [Exception, Defect].} =
|
|||
forkDigests, getBeaconTime, genesis_validators_root
|
||||
)
|
||||
|
||||
rpcClient = waitFor initRpcClient(config)
|
||||
# TODO: for now we serve all cross origin requests
|
||||
authHooks = @[httpCors(@[])]
|
||||
|
||||
rpcHttpServer = newRpcHttpServer(
|
||||
[initTAddress(config.rpcAddress, config.rpcPort)]
|
||||
clientConfig = config.web3url.asClientConfig()
|
||||
|
||||
rpcProxy = RpcProxy.new(
|
||||
[initTAddress(config.rpcAddress, config.rpcPort)],
|
||||
clientConfig,
|
||||
authHooks
|
||||
)
|
||||
|
||||
lcProxy = LightClientRpcProxy.new(rpcHttpServer, rpcClient, chainId)
|
||||
lcProxy = LightClientRpcProxy.new(rpcProxy, chainId)
|
||||
|
||||
optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock):
|
||||
Future[void] {.async.} =
|
||||
|
@ -156,7 +150,7 @@ proc run() {.raises: [Exception, Defect].} =
|
|||
|
||||
waitFor network.startListening()
|
||||
waitFor network.start()
|
||||
rpcHttpServer.start()
|
||||
waitFor rpcProxy.start()
|
||||
waitFor lcProxy.verifyChaindId()
|
||||
|
||||
proc onFinalizedHeader(
|
||||
|
|
|
@ -14,7 +14,8 @@ import
|
|||
std/os,
|
||||
json_serialization/std/net,
|
||||
beacon_chain/light_client,
|
||||
beacon_chain/conf
|
||||
beacon_chain/conf,
|
||||
json_rpc/[rpcproxy]
|
||||
|
||||
export net, conf
|
||||
|
||||
|
@ -28,19 +29,17 @@ proc defaultLCPDataDir*(): string =
|
|||
|
||||
getHomeDir() / dataDir
|
||||
|
||||
|
||||
type Web3ClientType* = enum
|
||||
WsClient, HttpClient
|
||||
|
||||
type Web3ClientConfig* = object
|
||||
kind*: Web3ClientType
|
||||
url*: string
|
||||
|
||||
const
|
||||
defaultWeb3Address* = (static "http://127.0.0.1:8546")
|
||||
defaultWeb3ClientConfig* = Web3ClientConfig(url: defaultWeb3Address, kind: HttpClient)
|
||||
defaultDataLCPDirDesc* = defaultLCPDataDir()
|
||||
|
||||
type
|
||||
Web3UrlKind* = enum
|
||||
HttpUrl, WsUrl
|
||||
|
||||
ValidatedWeb3Url* = object
|
||||
kind*: Web3UrlKind
|
||||
web3Url*: string
|
||||
|
||||
type LcProxyConf* = object
|
||||
# Config
|
||||
configFile* {.
|
||||
|
@ -164,25 +163,25 @@ type LcProxyConf* = object
|
|||
defaultValueDesc: $defaultAdminListenAddressDesc
|
||||
name: "rpc-address" .}: ValidIpAddress
|
||||
|
||||
web3ClientConfig* {.
|
||||
# There is no default as its need to be provided by the user
|
||||
web3url* {.
|
||||
desc: "url of web3 data provider"
|
||||
defaultValue: defaultWeb3ClientConfig
|
||||
name: "web3-url" .}: Web3ClientConfig
|
||||
name: "web3-url" .}: ValidatedWeb3Url
|
||||
|
||||
proc parseCmdArg*(T: type Web3ClientConfig, p: TaintedString): T
|
||||
proc parseCmdArg*(T: type ValidatedWeb3Url, p: TaintedString): T
|
||||
{.raises: [Defect, ConfigurationError].} =
|
||||
let url = parseUri(p)
|
||||
let normalizedScheme = url.scheme.toLowerAscii()
|
||||
if (normalizedScheme == "http" or normalizedScheme == "https"):
|
||||
Web3ClientConfig(kind: HttpClient, url: p)
|
||||
ValidatedWeb3Url(kind: HttpUrl, web3Url: p)
|
||||
elif (normalizedScheme == "ws" or normalizedScheme == "wss"):
|
||||
Web3ClientConfig(kind: WsClient, url: p)
|
||||
ValidatedWeb3Url(kind: WsUrl, web3Url: p)
|
||||
else:
|
||||
raise newException(
|
||||
ConfigurationError, "Web3 client uri should have defined scheme (http/https/ws/wss)"
|
||||
ConfigurationError, "Web3 url should have defined scheme (http/https/ws/wss)"
|
||||
)
|
||||
|
||||
proc completeCmdArg*(T: type Web3ClientConfig, val: TaintedString): seq[string] =
|
||||
proc completeCmdArg*(T: type ValidatedWeb3Url, val: TaintedString): seq[string] =
|
||||
return @[]
|
||||
|
||||
func asLightClientConf*(pc: LcProxyConf): LightClientConf =
|
||||
|
@ -210,3 +209,13 @@ func asLightClientConf*(pc: LcProxyConf): LightClientConf =
|
|||
jwtSecret: none(string),
|
||||
stopAtEpoch: 0
|
||||
)
|
||||
|
||||
# TODO: Cannot use ClientConfig in LcProxyConf due to the fact that
|
||||
# it contain `set[TLSFlags]` which does not have proper toml serialization
|
||||
func asClientConfig*(url: ValidatedWeb3Url): ClientConfig =
|
||||
case url.kind
|
||||
of HttpUrl:
|
||||
getHttpClientConfig(url.web3Url)
|
||||
of WsUrl:
|
||||
getWebSocketClientConfig(url.web3Url, flags = {})
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import
|
|||
stint,
|
||||
stew/byteutils,
|
||||
chronicles,
|
||||
json_rpc/[rpcserver, rpcclient],
|
||||
json_rpc/[rpcproxy, rpcserver, rpcclient],
|
||||
web3,
|
||||
web3/[ethhexstrings, ethtypes],
|
||||
beacon_chain/eth1/eth1_monitor,
|
||||
|
@ -36,8 +36,7 @@ template encodeQuantity(value: Quantity): HexQuantityStr =
|
|||
hexQuantityStr(encodeQuantity(value.uint64))
|
||||
|
||||
type LightClientRpcProxy* = ref object
|
||||
client*: RpcClient
|
||||
server*: RpcServer
|
||||
proxy: RpcProxy
|
||||
executionPayload*: Opt[ExecutionPayloadV1]
|
||||
chainId: Quantity
|
||||
|
||||
|
@ -54,13 +53,15 @@ template checkPreconditions(payload: Opt[ExecutionPayloadV1], quantityTag: strin
|
|||
# fetched on demand.
|
||||
raise newException(ValueError, "Only latest block is supported")
|
||||
|
||||
template rpcClient(lcProxy: LightClientRpcProxy): RpcClient = lcProxy.proxy.getClient()
|
||||
|
||||
proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
||||
template payload(): Opt[ExecutionPayloadV1] = lcProxy.executionPayload
|
||||
|
||||
lcProxy.server.rpc("eth_chainId") do() -> HexQuantityStr:
|
||||
lcProxy.proxy.rpc("eth_chainId") do() -> HexQuantityStr:
|
||||
return encodeQuantity(lcProxy.chainId)
|
||||
|
||||
lcProxy.server.rpc("eth_blockNumber") do() -> HexQuantityStr:
|
||||
lcProxy.proxy.rpc("eth_blockNumber") do() -> HexQuantityStr:
|
||||
## Returns the number of most recent block.
|
||||
if payload.isNone:
|
||||
raise newException(ValueError, "Syncing")
|
||||
|
@ -68,7 +69,7 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
|||
return encodeQuantity(payload.get.blockNumber)
|
||||
|
||||
# TODO quantity tag should be better typed
|
||||
lcProxy.server.rpc("eth_getBalance") do(address: Address, quantityTag: string) -> HexQuantityStr:
|
||||
lcProxy.proxy.rpc("eth_getBalance") do(address: Address, quantityTag: string) -> HexQuantityStr:
|
||||
checkPreconditions(payload, quantityTag)
|
||||
|
||||
# When requesting state for `latest` block number, we need to translate
|
||||
|
@ -81,7 +82,7 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
|||
|
||||
info "Forwarding get_Balance", executionBn = blockNumber
|
||||
|
||||
let proof = await lcProxy.client.eth_getProof(address, @[], blockId(blockNumber))
|
||||
let proof = await lcProxy.rpcClient.eth_getProof(address, @[], blockId(blockNumber))
|
||||
|
||||
let accountResult = getAccountFromProof(
|
||||
executionPayload.stateRoot,
|
||||
|
@ -98,7 +99,7 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
|||
else:
|
||||
raise newException(ValueError, accountResult.error)
|
||||
|
||||
lcProxy.server.rpc("eth_getStorageAt") do(address: Address, slot: HexDataStr, quantityTag: string) -> HexDataStr:
|
||||
lcProxy.proxy.rpc("eth_getStorageAt") do(address: Address, slot: HexDataStr, quantityTag: string) -> HexDataStr:
|
||||
checkPreconditions(payload, quantityTag)
|
||||
|
||||
let
|
||||
|
@ -108,7 +109,7 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
|||
|
||||
info "Forwarding eth_getStorageAt", executionBn = blockNumber
|
||||
|
||||
let proof = await lcProxy.client.eth_getProof(address, @[uslot], blockId(blockNumber))
|
||||
let proof = await lcProxy.rpcClient.eth_getProof(address, @[uslot], blockId(blockNumber))
|
||||
|
||||
let dataResult = getStorageData(executionPayload.stateRoot, uslot, proof)
|
||||
|
||||
|
@ -118,15 +119,23 @@ proc installEthApiHandlers*(lcProxy: LightClientRpcProxy) =
|
|||
else:
|
||||
raise newException(ValueError, dataResult.error)
|
||||
|
||||
# TODO This methods are forwarded directly to provider therefore thay are not
|
||||
# validated in any way
|
||||
lcProxy.proxy.registerProxyMethod("net_version")
|
||||
lcProxy.proxy.registerProxyMethod("eth_call")
|
||||
|
||||
# TODO cache blocks received from light client, and respond using them in this
|
||||
# call. It would also enable handling of numerical `quantityTag` for the
|
||||
# set of cached blocks
|
||||
lcProxy.proxy.registerProxyMethod("eth_getBlockByNumber")
|
||||
|
||||
proc new*(
|
||||
T: type LightClientRpcProxy,
|
||||
server: RpcServer,
|
||||
client: RpcClient,
|
||||
proxy: RpcProxy,
|
||||
chainId: Quantity): T =
|
||||
|
||||
return LightClientRpcProxy(
|
||||
client: client,
|
||||
server: server,
|
||||
proxy: proxy,
|
||||
chainId: chainId
|
||||
)
|
||||
|
||||
|
@ -136,7 +145,7 @@ proc verifyChaindId*(p: LightClientRpcProxy): Future[void] {.async.} =
|
|||
# retry 2 times, if the data provider will fail despite re-tries, propagate
|
||||
# exception to the caller.
|
||||
let providerId = awaitWithRetries(
|
||||
p.client.eth_chainId(),
|
||||
p.rpcClient.eth_chainId(),
|
||||
retries = 2,
|
||||
timeout = seconds(30)
|
||||
)
|
||||
|
|
|
@ -14,8 +14,7 @@ import
|
|||
chronos/apps/http/[httptable, httpserver],
|
||||
json_rpc/rpcserver,
|
||||
httputils,
|
||||
websock/websock as ws,
|
||||
../config
|
||||
websock/websock as ws
|
||||
|
||||
proc sameOrigin(a, b: Uri): bool =
|
||||
a.hostname == b.hostname and
|
||||
|
|
Loading…
Reference in New Issue