Skip to content

Commit 084bc45

Browse files
authored
CLI and logging updates (#3903)
* CLI and logging updates Companion to status-im/nimbus-eth2#7842, bumps eth2 * bump * lint * lint * docs * nph
1 parent e84c502 commit 084bc45

24 files changed

+161
-296
lines changed

.github/workflows/lint.yml

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,11 @@ jobs:
3737
uses: actions/checkout@v4
3838
with:
3939
fetch-depth: 2 # In PR, has extra merge commit: ^1 = PR, ^2 = base
40-
41-
- name: Check nph formatting
42-
# Pin nph to a specific version to avoid sudden style differences.
43-
# Updating nph version should be accompanied with running the new
44-
# version on the nimbus_verified_proxy directory.
45-
run: |
46-
VERSION="v0.6.1"
47-
ARCHIVE="nph-linux_x64.tar.gz"
48-
curl -L "https://github.com/arnetheduck/nph/releases/download/${VERSION}/${ARCHIVE}" -o ${ARCHIVE}
49-
tar -xzf ${ARCHIVE}
50-
./nph nimbus_verified_proxy/
51-
./nph portal/
52-
git diff --exit-code
53-
40+
- name: Check `nph` formatting
41+
uses: arnetheduck/nph-action@v1
42+
with:
43+
version: 0.6.2
44+
options: "nimbus_verified_proxy/ portal/"
5445
- name: Check copyright year & version
5546
if: ${{ !cancelled() }} && github.event_name == 'pull_request'
5647
run: |

execution_chain/conf.nim

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018-2025 Status Research & Development GmbH
1+
# Copyright (c) 2018-2026 Status Research & Development GmbH
22
# Licensed under either of
33
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
44
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
@@ -9,27 +9,19 @@
99
{.push raises: [].}
1010

1111
import
12-
std/[
13-
options,
14-
strutils,
15-
os,
16-
uri,
17-
net
18-
],
19-
pkg/[
20-
chronos/transports/common,
21-
chronicles,
22-
confutils,
23-
confutils/defs,
24-
confutils/std/net as confnet,
25-
confutils/toml/defs as tomldefs,
26-
confutils/json/defs as jsdefs,
27-
json_serialization/std/net as jsnet,
28-
toml_serialization/std/net as tomlnet,
29-
results,
30-
beacon_chain/buildinfo,
31-
beacon_chain/nimbus_binary_common,
32-
],
12+
std/[options, strutils, os, uri, net],
13+
chronos/transports/common,
14+
chronicles,
15+
confutils,
16+
confutils/defs,
17+
confutils/std/net as confnet,
18+
confutils/toml/defs as tomldefs,
19+
confutils/json/defs as jsdefs,
20+
json_serialization/std/net as jsnet,
21+
toml_serialization/std/net as tomlnet,
22+
results,
23+
beacon_chain/buildinfo,
24+
beacon_chain/nimbus_binary_common,
3325
toml_serialization,
3426
eth/[common, net/nat, net/nat_toml],
3527
./networking/bootnodes,
@@ -94,12 +86,12 @@ type
9486
name: "data-dir" .}: Option[OutDir]
9587

9688
era1DirFlag* {.
97-
desc: "Directory where era1 (pre-merge) archive can be found"
89+
desc: "Directory for era1 archive (pre-merge history)"
9890
defaultValueDesc: "<data-dir>/era1"
9991
name: "era1-dir" .}: Option[OutDir]
10092

10193
eraDirFlag* {.
102-
desc: "Directory where era (post-merge) archive can be found"
94+
desc: "Directory for era archive (post-merge history)"
10395
defaultValueDesc: "<data-dir>/era"
10496
name: "era-dir" .}: Option[OutDir]
10597

@@ -135,14 +127,14 @@ type
135127
defaultValueDesc: $DEFAULT_GAS_LIMIT
136128
name: "gas-limit" .}: uint64
137129

130+
# https://ethereum.org/developers/docs/networks/#ethereum-testnets
138131
network {.
139-
separator: "\pETHEREUM NETWORK OPTIONS:"
140132
desc: "Name or id number of Ethereum network"
141133
longDesc:
142134
"- mainnet/1 : Ethereum main network\n" &
143-
"- sepolia/11155111: Test network (proof-of-work)\n" &
144-
"- hoodi/560048 : The second long-standing, merged-from-genesis, public Ethereum testnet\n" &
145-
"- path : /path/to/genesis-or-network-configuration.json\n" &
135+
"- sepolia/11155111: Testnet for smart contract testing\n" &
136+
"- hoodi/560048 : Testnet for staking and hard forks\n" &
137+
"- custom/path : /path/to/genesis-or-network-configuration.json\n" &
146138
"Both --network: name/path --network:id can be set at the same time to override network id number"
147139
defaultValue: @[] # the default value is set in makeConfig
148140
defaultValueDesc: "mainnet(1)"
@@ -173,9 +165,8 @@ type
173165
defaultValue: "INFO"
174166
name: "log-level" .}: string
175167

176-
logStdout* {.
177-
hidden
178-
desc: "Specifies what kind of logs should be written to stdout (auto, colors, nocolors, json)"
168+
logFormat* {.
169+
desc: "Choice of log format (auto, colors, nocolors, json)"
179170
defaultValueDesc: "auto"
180171
defaultValue: StdoutLogKind.Auto
181172
name: "log-format" .}: StdoutLogKind
@@ -806,6 +797,12 @@ func dbOptions*(config: ExecutionClientConf, noKeyCache = false): DbOptions =
806797
maxSnapshots = config.aristoDbMaxSnapshots,
807798
)
808799

800+
func jwtSecretOpt*(config: ExecutionClientConf): Opt[InputFile] =
801+
if config.jwtSecret.isSome:
802+
Opt.some config.jwtSecret.get
803+
else:
804+
Opt.none InputFile
805+
809806
{.pop.}
810807

811808
#-------------------------------------------------------------------
@@ -825,3 +822,4 @@ proc makeConfig*(cmdLine = commandLineParams(), ignoreUnknown = false): Executio
825822
when isMainModule:
826823
# for testing purpose
827824
discard makeConfig()
825+

execution_chain/nimbus.nim

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# nimbus
2-
# Copyright (c) 2025 Status Research & Development GmbH
2+
# Copyright (c) 2025-2026 Status Research & Development GmbH
33
# Licensed under either of
44
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
55
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
@@ -51,9 +51,17 @@ const
5151
copyright = "Copyright (c) " & compileYear & " Status Research & Development GmbH"
5252

5353
type NStartUpCmd* {.pure.} = enum
54-
nimbus
55-
beaconNode
56-
executionClient
54+
nimbus = "Run Ethereum node"
55+
beaconNode = "Run beacon node in stand-alone mode"
56+
executionClient = "Run execution client in stand-alone mode"
57+
58+
proc matchSymbolName*(T: type enum, p: string): T {.raises: [ValueError].} =
59+
let p = normalize(p)
60+
for e in T:
61+
if e.symbolName.normalize() == p:
62+
return e
63+
64+
raise (ref ValueError)(msg: p & " does not match")
5765

5866
#!fmt: off
5967
type
@@ -65,24 +73,23 @@ type
6573
desc: "Loads the configuration from a TOML file"
6674
name: "config-file" .}: Option[InputFile]
6775

76+
network* {.
77+
desc: "Name of Ethereum network to join (mainnet, hoodi, sepolia, custom/folder)"
78+
defaultValueDesc: "mainnet"
79+
name: "network" .}: Option[string]
80+
6881
dataDirFlag* {.
6982
desc: "The directory where nimbus will store all blockchain data"
7083
abbr: "d"
7184
name: "data-dir" .}: Option[OutDir]
7285

73-
eth2Network* {.
74-
desc: "The network to join (mainnet, hoodi, sepolia, custom/folder)"
75-
defaultValueDesc: "mainnet"
76-
name: "network" .}: Option[string]
77-
7886
logLevel* {.
7987
desc: "Sets the log level for process and topics (e.g. \"DEBUG; TRACE:discv5,libp2p; REQUIRED:none; DISABLED:none\")"
8088
defaultValue: "INFO"
8189
name: "log-level" .}: string
8290

83-
logStdout* {.
84-
hidden
85-
desc: "Specifies what kind of logs should be written to stdout (auto, colors, nocolors, json)"
91+
logFormat* {.
92+
desc: "Choice of log format (auto, colors, nocolors, json)"
8693
defaultValueDesc: "auto"
8794
defaultValue: StdoutLogKind.Auto
8895
name: "log-format" .}: StdoutLogKind
@@ -113,15 +120,15 @@ type
113120
# to keep compatibility with `--tcp-port` that is used in both, use
114121
# consecutive ports unless specific ports are set - to be evaluated
115122
executionTcpPort* {.
116-
desc: "Listening TCP port for Ethereum devp2p traffic"
123+
desc: "Listening TCP port for execution client network (devp2p)"
117124
name: "execution-tcp-port" .}: Option[Port]
118125

119126
executionUdpPort* {.
120127
desc: "Listening UDP port for execution node discovery"
121128
name: "execution-udp-port" .}: Option[Port]
122129

123130
beaconTcpPort* {.
124-
desc: "Listening TCP port for Ethereum libp2p traffic"
131+
desc: "Listening TCP port for consensus client network (libp2p)"
125132
name: "beacon-tcp-port" .}: Option[Port]
126133

127134
beaconUdpPort* {.
@@ -141,6 +148,7 @@ type
141148
defaultValue: true
142149
name: "el-sync" .}: bool
143150

151+
# detect if user added --engine-api option which is not valid in unified mode
144152
engineApiEnabled* {.
145153
hidden
146154
desc: "Enable the Engine API"
@@ -180,7 +188,7 @@ var jwtKey: JwtSharedKey
180188

181189
proc dataDir*(config: NimbusConf): string =
182190
string config.dataDirFlag.get(
183-
OutDir defaultDataDir("", config.eth2Network.loadEth2Network().cfg.name)
191+
OutDir defaultDataDir("", config.network.loadEth2Network().cfg.name)
184192
)
185193

186194
proc justWait(tsp: ThreadSignalPtr) {.async: (raises: [CancelledError]).} =
@@ -208,21 +216,20 @@ proc runBeaconNode(p: BeaconThreadConfig) {.thread.} =
208216
stderr.writeLine error # Logging not yet set up
209217
quit QuitFailure
210218

211-
let engineUrl = EngineApiUrl.init(
212-
&"http://127.0.0.1:{defaultEngineApiPort}/", Opt.some(@(distinctBase(jwtKey)))
213-
)
219+
let engineUrl =
220+
EngineApiUrl.init(&"http://127.0.0.1:{defaultEngineApiPort}/", Opt.some(jwtKey))
214221

215222
config.metricsEnabled = false
216-
config.elUrls =
217-
@[
218-
EngineApiUrlConfigValue(
219-
url: engineUrl.url, jwtSecret: some toHex(distinctBase(jwtKey))
220-
)
221-
]
223+
config.elUrls.add EngineApiUrlConfigValue(
224+
url: engineUrl.url, jwtSecret: some toHex(distinctBase(jwtKey))
225+
)
226+
222227
config.statusBarEnabled = false # Multi-threading issues due to logging
223228
config.tcpPort = p.tcpPort
224229
config.udpPort = p.udpPort
225230

231+
config.rpcEnabled.reset() # --rpc is meant for the EL
232+
226233
info "Launching beacon node",
227234
version = fullVersionStr,
228235
bls_backend = $BLS_BACKEND,
@@ -291,13 +298,14 @@ proc runCombinedClient() =
291298
# go away
292299
discard randomBytes(distinctBase(jwtKey))
293300

294-
const banner = "Nimbus v0.0.1"
301+
const banner = "Nimbus v0.0.1\p\pSubcommand options can also be used with the main node, see `beaconNode --help` and `executionClient --help`"
295302

296-
var config = NimbusConf.loadWithBanners(banner, copyright, [specBanner], true).valueOr:
303+
var config = NimbusConf.loadWithBanners(
304+
banner, copyright, [specBanner], ignoreUnknown = true, setupLogger = true
305+
).valueOr:
297306
writePanicLine error # Logging not yet set up
298307
quit QuitFailure
299308

300-
setupLogging(config.logLevel, config.logStdout, none OutFile)
301309
setupFileLimits()
302310

303311
ProcessState.setupStopHandlers()
@@ -383,32 +391,28 @@ proc main() {.noinline, raises: [CatchableError].} =
383391
isBN = false
384392
for i in 0 ..< params.len:
385393
try:
386-
discard NimbusCmd.parseCmdArg(params[i])
394+
discard NimbusCmd.matchSymbolName(params[i])
387395
isEC = true
388-
params.delete(i)
389396
break
390397
except ValueError:
391398
discard
392399
try:
393-
discard BNStartUpCmd.parseCmdArg(params[i])
400+
discard BNStartUpCmd.matchSymbolName(params[i])
394401
isBN = true
395-
params.delete(i)
396402
break
397403
except ValueError:
398404
discard
399405

400406
try:
401-
let cmd = NStartUpCmd.parseCmdArg(params[i])
402-
403-
if cmd == NStartUpCmd.beaconNode:
407+
case NStartUpCmd.matchSymbolName(params[i])
408+
of NStartUpCmd.beaconNode:
404409
isBN = true
405-
params.delete(i)
406410
break
407-
408-
if cmd == NStartUpCmd.executionClient:
411+
of NStartUpCmd.executionClient:
409412
isEC = true
410-
params.delete(i)
411413
break
414+
else:
415+
discard
412416
except ValueError:
413417
discard
414418

execution_chain/nimbus_execution_client.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ proc runExeClient*(
343343
# noinline to keep it in stack traces
344344
proc main*(config = makeConfig(), nimbus = NimbusNode(nil)) {.noinline.} =
345345
# Set up logging before everything else
346-
setupLogging(config.logLevel, config.logStdout)
346+
setupLogging(config.logLevel, config.logFormat)
347347
setupFileLimits()
348348

349349
info "Launching execution client", version = FullVersionStr, config

execution_chain/rpc.nim

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Nimbus
2-
# Copyright (c) 2022-2025 Status Research & Development GmbH
2+
# Copyright (c) 2022-2026 Status Research & Development GmbH
33
# Licensed under either of
44
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
55
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
@@ -206,16 +206,10 @@ proc setupRpc*(nimbus: NimbusNode, config: ExecutionClientConf,
206206
return
207207

208208
# Provide JWT authentication handler for rpcHttpServer
209-
let jwtKey = block:
210-
# Create or load shared secret
211-
let rc = nimbus.rng.jwtSharedSecret(config)
212-
if rc.isErr:
213-
fatal "Failed create or load shared secret",
214-
msg = $(rc.unsafeError) # avoid side effects
215-
quit(QuitFailure)
216-
rc.value
217-
218209
let
210+
jwtKey = nimbus.rng.jwtSharedSecret(config).valueOr:
211+
fatal "Failed create or load shared secret", error
212+
quit(QuitFailure)
219213
allowedOrigins = config.getAllowedOrigins()
220214
jwtAuthHook = httpJwtAuth(jwtKey)
221215
corsHook = httpCors(allowedOrigins)

0 commit comments

Comments
 (0)