Code Cleanup. Specific config for app (#1206)

* Code Cleanup. Specific config for app
This commit is contained in:
KonradStaniec 2022-08-30 07:40:03 +02:00 committed by GitHub
parent 1ab5c29530
commit 0353803012
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 247 additions and 86 deletions

View File

@ -20,27 +20,44 @@ import
beacon_chain/spec/beaconstate,
beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
beacon_chain/[light_client, nimbus_binary_common, version],
./rpc/rpc_eth_lc_api
./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 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)
# TODO Find what can throw exception
proc run() {.raises: [Exception, Defect].}=
proc run() {.raises: [Exception, Defect].} =
{.pop.}
var config = makeBannerAndConfig(
"Nimbus light client " & fullVersionStr, LightClientConf)
"Nimbus light client " & fullVersionStr, LcProxyConf)
{.push raises: [Defect].}
# Required as both Eth2Node and LightClient requires correct config type
var lcConfig = config.asLightClientConf()
setupLogging(config.logLevel, config.logStdout, config.logFile)
notice "Launching light client",
notice "Launching light client proxy",
version = fullVersionStr, cmdParams = commandLineParams(), config
let metadata = loadEth2Network(config.eth2Network)
for node in metadata.bootstrapNodes:
config.bootstrapNodes.add node
lcConfig.bootstrapNodes.add node
template cfg(): auto = metadata.cfg
let
@ -67,56 +84,13 @@ proc run() {.raises: [Exception, Defect].}=
netKeys = getRandomNetKeys(rng[])
network = createEth2Node(
rng, config, netKeys, cfg,
forkDigests, getBeaconTime, genesis_validators_root)
rng, lcConfig, netKeys, cfg,
forkDigests, getBeaconTime, genesis_validators_root
)
eth1Mon =
if config.web3Urls.len > 0:
let res = Eth1Monitor.init(
cfg, db = nil, getBeaconTime, config.web3Urls,
none(DepositContractSnapshot), metadata.eth1Network,
forcePolling = false,
rng[].loadJwtSecret(config, allowCreate = false),
true)
waitFor res.ensureDataProvider()
res
else:
nil
rpcServerWithProxy = initRpcProxy(config)
rpcServerWithProxy =
if config.web3Urls.len > 0:
var web3Url = config.web3Urls[0]
fixupWeb3Urls web3Url
let proxyUri = some web3Url
if proxyUri.isSome:
info "Initializing LC eth API proxy", proxyUri = proxyUri.get
let
ta = initTAddress("127.0.0.1:8545")
clientConfig =
case parseUri(proxyUri.get).scheme.toLowerAscii():
of "http", "https":
getHttpClientConfig(proxyUri.get)
of "ws", "wss":
getWebSocketClientConfig(proxyUri.get)
else:
fatal "Unsupported scheme", proxyUri = proxyUri.get
quit QuitFailure
RpcProxy.new([ta], clientConfig)
else:
warn "Ignoring `rpcEnabled`, no `proxyUri` provided"
nil
else:
nil
lcProxy =
if rpcServerWithProxy != nil:
let res = LightClientRpcProxy(proxy: rpcServerWithProxy)
res.installEthApiHandlers()
res
else:
nil
lcProxy = LightClientRpcProxy(proxy: rpcServerWithProxy)
optimisticHandler = proc(signedBlock: ForkedMsgTrustedSignedBeaconBlock):
Future[void] {.async.} =
@ -127,21 +101,7 @@ proc run() {.raises: [Exception, Defect].}=
when stateFork >= BeaconStateFork.Bellatrix:
if blck.message.is_execution_block:
template payload(): auto = blck.message.body.execution_payload
if eth1Mon != nil:
await eth1Mon.ensureDataProvider()
# engine_newPayloadV1
discard await eth1Mon.newExecutionPayload(payload)
# engine_forkchoiceUpdatedV1
discard await eth1Mon.runForkchoiceUpdated(
headBlockRoot = payload.block_hash,
safeBlockRoot = payload.block_hash, # stub value
finalizedBlockRoot = ZERO_HASH)
if lcProxy != nil:
lcProxy.executionPayload.ok payload.asEngineExecutionPayload()
lcProxy.executionPayload.ok payload.asEngineExecutionPayload()
else: discard
return
@ -149,9 +109,11 @@ proc run() {.raises: [Exception, Defect].}=
getBeaconTime, optimisticHandler)
lightClient = createLightClient(
network, rng, config, cfg, forkDigests, getBeaconTime,
network, rng, lcConfig, cfg, forkDigests, getBeaconTime,
genesis_validators_root, LightClientFinalizationMode.Optimistic)
lcProxy.installEthApiHandlers()
info "Listening to incoming network requests"
network.initBeaconSync(cfg, forkDigests, genesisBlockRoot, getBeaconTime)
network.addValidator(
@ -170,16 +132,14 @@ proc run() {.raises: [Exception, Defect].}=
toValidationResult(
optimisticProcessor.processSignedBeaconBlock(signedBlock)))
lightClient.installMessageValidators()
waitFor network.startListening()
waitFor network.start()
if lcProxy != nil:
waitFor lcProxy.proxy.start()
waitFor lcProxy.proxy.start()
proc onFinalizedHeader(
lightClient: LightClient, finalizedHeader: BeaconBlockHeader) =
info "New LC finalized header",
finalized_header = shortLog(finalizedHeader)
info "New LC finalized header", finalized_header = shortLog(finalizedHeader)
optimisticProcessor.setFinalizedHeader(finalizedHeader)
proc onOptimisticHeader(
@ -193,10 +153,6 @@ proc run() {.raises: [Exception, Defect].}=
lightClient.trustedBlockRoot = some config.trustedBlockRoot
func shouldSyncOptimistically(wallSlot: Slot): bool =
# Check whether an EL is connected
if eth1Mon == nil and lcProxy == nil:
return false
# Check whether light client is used
let optimisticHeader = lightClient.optimisticHeader.valueOr:
return false
@ -249,15 +205,8 @@ proc run() {.raises: [Exception, Defect].}=
var nextExchangeTransitionConfTime: Moment
proc onSecond(time: Moment) =
# engine_exchangeTransitionConfigurationV1
if time > nextExchangeTransitionConfTime and eth1Mon != nil:
nextExchangeTransitionConfTime = time + chronos.minutes(1)
traceAsyncErrors eth1Mon.exchangeTransitionConfiguration()
let wallSlot = getBeaconTime().slotOrZero()
if checkIfShouldStopAtEpoch(wallSlot, config.stopAtEpoch):
quit(0)
updateBlocksGossipStatus(wallSlot + 1)
lightClient.updateGossipStatus(wallSlot + 1)
proc runOnSecondLoop() {.async.} =

212
lc_proxy/lc_proxy_conf.nim Normal file
View File

@ -0,0 +1,212 @@
# beacon_chain
# Copyright (c) 2022 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
when (NimMajor, NimMinor) < (1, 4):
{.push raises: [Defect].}
else:
{.push raises: [].}
import
std/os,
json_serialization/std/net,
beacon_chain/light_client,
beacon_chain/conf
export net, conf
proc defaultLCPDataDir*(): string =
let dataDir = when defined(windows):
"AppData" / "Roaming" / "LightClientProxy"
elif defined(macosx):
"Library" / "Application Support" / "LightClientProxy"
else:
".cache" / "lightclientproxy"
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 LcProxyConf* = object
# Config
configFile* {.
desc: "Loads the configuration from a TOML file"
name: "config-file" .}: Option[InputFile]
# Logging
logLevel* {.
desc: "Sets the log level"
defaultValue: "INFO"
name: "log-level" .}: string
logStdout* {.
hidden
desc: "Specifies what kind of logs should be written to stdout (auto, colors, nocolors, json)"
defaultValueDesc: "auto"
defaultValue: StdoutLogKind.Auto
name: "log-format" .}: StdoutLogKind
logFile* {.
desc: "Specifies a path for the written Json log file (deprecated)"
name: "log-file" .}: Option[OutFile]
# Storage
dataDir* {.
desc: "The directory where nimbus will store all blockchain data"
defaultValue: defaultLCPDataDir()
defaultValueDesc: $defaultDataLCPDirDesc
abbr: "d"
name: "data-dir" .}: OutDir
# Network
eth2Network* {.
desc: "The Eth2 network to join"
defaultValueDesc: "mainnet"
name: "network" .}: Option[string]
# Libp2p
bootstrapNodes* {.
desc: "Specifies one or more bootstrap nodes to use when connecting to the network"
abbr: "b"
name: "bootstrap-node" .}: seq[string]
bootstrapNodesFile* {.
desc: "Specifies a line-delimited file of bootstrap Ethereum network addresses"
defaultValue: ""
name: "bootstrap-file" .}: InputFile
listenAddress* {.
desc: "Listening address for the Ethereum LibP2P and Discovery v5 traffic"
defaultValue: defaultListenAddress
defaultValueDesc: $defaultListenAddressDesc
name: "listen-address" .}: ValidIpAddress
tcpPort* {.
desc: "Listening TCP port for Ethereum LibP2P traffic"
defaultValue: defaultEth2TcpPort
defaultValueDesc: $defaultEth2TcpPortDesc
name: "tcp-port" .}: Port
udpPort* {.
desc: "Listening UDP port for node discovery"
defaultValue: defaultEth2TcpPort
defaultValueDesc: $defaultEth2TcpPortDesc
name: "udp-port" .}: Port
maxPeers* {.
desc: "The target number of peers to connect to"
defaultValue: 160 # 5 (fanout) * 64 (subnets) / 2 (subs) for a heathy mesh
name: "max-peers" .}: int
hardMaxPeers* {.
desc: "The maximum number of peers to connect to. Defaults to maxPeers * 1.5"
name: "hard-max-peers" .}: Option[int]
nat* {.
desc: "Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>"
defaultValue: NatConfig(hasExtIp: false, nat: NatAny)
defaultValueDesc: "any"
name: "nat" .}: NatConfig
enrAutoUpdate* {.
desc: "Discovery can automatically update its ENR with the IP address " &
"and UDP port as seen by other nodes it communicates with. " &
"This option allows to enable/disable this functionality"
defaultValue: false
name: "enr-auto-update" .}: bool
agentString* {.
defaultValue: "nimbus",
desc: "Node agent string which is used as identifier in network"
name: "agent-string" .}: string
discv5Enabled* {.
desc: "Enable Discovery v5"
defaultValue: true
name: "discv5" .}: bool
directPeers* {.
desc: "The list of priviledged, secure and known peers to connect and" &
"maintain the connection to, this requires a not random netkey-file." &
"In the complete multiaddress format like:" &
"/ip4/<address>/tcp/<port>/p2p/<peerId-public-key>." &
"Peering agreements are established out of band and must be reciprocal."
name: "direct-peer" .}: seq[string]
# Light client
trustedBlockRoot* {.
desc: "Recent trusted finalized block root to initialize light client from"
name: "trusted-block-root" .}: Eth2Digest
rpcPort* {.
desc: "HTTP port for the JSON-RPC server"
defaultValue: 8545
name: "rpc-port" .}: Port
rpcAddress* {.
desc: "Listening address of the RPC server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "rpc-address" .}: ValidIpAddress
web3ClientConfig* {.
desc: "url of web3 data provider"
defaultValue: defaultWeb3ClientConfig
name: "web3-url" .}: Web3ClientConfig
proc parseCmdArg*(T: type Web3ClientConfig, 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)
elif (normalizedScheme == "ws" or normalizedScheme == "wss"):
Web3ClientConfig(kind: WsClient, url: p)
else:
raise newException(
ConfigurationError, "Web3 client uri should have defined scheme (http/https/ws/wss)"
)
proc completeCmdArg*(T: type Web3ClientConfig, val: TaintedString): seq[string] =
return @[]
func asLightClientConf*(pc: LcProxyConf): LightClientConf =
return LightClientConf(
configFile: pc.configFile,
logLevel: pc.logLevel,
logStdout: pc.logStdout,
logFile: pc.logFile,
dataDir: pc.dataDir,
eth2Network: pc.eth2Network,
bootstrapNodes: pc.bootstrapNodes,
bootstrapNodesFile: pc.bootstrapNodesFile,
listenAddress: pc.listenAddress,
tcpPort: pc.tcpPort,
udpPort: pc.udpPort,
maxPeers: pc.maxPeers,
hardMaxPeers: pc.hardMaxPeers,
nat: pc.nat,
enrAutoUpdate: pc.enrAutoUpdate,
agentString: pc.agentString,
discv5Enabled: pc.discv5Enabled,
directPeers: pc.directPeers,
trustedBlockRoot: pc.trustedBlockRoot,
web3Urls: @[],
jwtSecret: none(string),
stopAtEpoch: 0
)