From d1127d77b1726ae7cd90745f70002171457af8db Mon Sep 17 00:00:00 2001 From: Kim De Mey Date: Thu, 17 Feb 2022 14:13:39 +0100 Subject: [PATCH] Add cli option to start fluffy with a netkey file (#974) Default the network key will be taken from a network key file instead of randomly generated on each run. This is done because the data that gets stored in the content database is dependant on the network key used, as the node id is derived from this. --- fluffy/common/common_utils.nim | 44 +++++++++++++++++++++++++++++++++- fluffy/conf.nim | 18 +++++++++----- fluffy/fluffy.nim | 7 +++++- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/fluffy/common/common_utils.nim b/fluffy/common/common_utils.nim index a01334ee2..913abf77f 100644 --- a/fluffy/common/common_utils.nim +++ b/fluffy/common/common_utils.nim @@ -9,7 +9,7 @@ import std/[os, strutils], - chronicles, + chronicles, stew/io2, eth/p2p/discoveryv5/enr iterator strippedLines(filename: string): string {.raises: [ref IOError].} = @@ -43,3 +43,45 @@ proc loadBootstrapFile*(bootstrapFile: string, else: fatal "Unknown bootstrap file format", ext quit 1 + +# Note: +# Currently just works with the network private key stored as hex in a file. +# In the future it would be nice to re-use keystore from nimbus-eth2 for this. +# However that would require the pull the keystore.nim and parts of +# keystore_management.nim out of nimbus-eth2. +proc getPersistentNetKey*( + rng: var BrHmacDrbgContext, keyFilePath: string, dataDir: string): + PrivateKey = + if fileAccessible(keyFilePath, {AccessFlags.Find}): + info "Network key file is present, reading key", key_file = keyFilePath + + let readResult = readAllChars(keyFilePath) + if readResult.isErr(): + fatal "Could not load network key file", key_file = keyFilePath + quit QuitFailure + + let netKeyInHex = readResult.get() + if netKeyInHex.len() == 64: + let netKey = PrivateKey.fromHex(netkeyInHex) + if netKey.isOk(): + info "Network key was successfully read", key_file = keyFilePath + netKey.get() + else: + fatal "Invalid private key length in file", key_file = keyFilePath + quit QuitFailure + else: + fatal "Invalid private key from file", key_file = keyFilePath + quit QuitFailure + + else: + info "Network key file is missing, creating a new one", + key_file = keyFilePath + let key = PrivateKey.random(rng) + + if io2.writeFile(keyFilePath, $key).isErr: + fatal "Failed to write the network key file", key_file = keyFilePath + quit 1 + + info "New network key file was created", key_file = keyFilePath + + key diff --git a/fluffy/conf.nim b/fluffy/conf.nim index 9ad0b620b..bdf36b5ee 100644 --- a/fluffy/conf.nim +++ b/fluffy/conf.nim @@ -83,18 +83,24 @@ type "This option allows to enable/disable this functionality" name: "enr-auto-update" .}: bool - networkKey* {. - desc: "Private key (secp256k1) for the p2p network, hex encoded. Safer keyfile support to be added.", - defaultValue: PrivateKey.random(keys.newRng()[]) - defaultValueDesc: "random" - name: "network-key-unsafe" .}: PrivateKey - dataDir* {. desc: "The directory where fluffy will store the content data" defaultValue: defaultDataDir() defaultValueDesc: $defaultDataDirDesc name: "data-dir" .}: OutDir + networkKeyFile* {. + desc: "Source of network (secp256k1) private key file" + defaultValue: config.dataDir / "netkey", + name: "netkey-file" }: string + + networkKey* {. + hidden + desc: "Private key (secp256k1) for the p2p network, hex encoded.", + defaultValue: none(PrivateKey) + defaultValueDesc: "none" + name: "netkey-unsafe" .}: Option[PrivateKey] + metricsEnabled* {. defaultValue: false desc: "Enable the metrics server" diff --git a/fluffy/fluffy.nim b/fluffy/fluffy.nim index 163cb461f..63ffce924 100644 --- a/fluffy/fluffy.nim +++ b/fluffy/fluffy.nim @@ -54,6 +54,11 @@ proc run(config: PortalConf) {.raises: [CatchableError, Defect].} = except CatchableError as exc: raise exc # TODO: Ideally we don't have the Exception here except Exception as exc: raiseAssert exc.msg + netkey = + if config.networkKey.isSome(): + config.networkKey.get() + else: + getPersistentNetKey(rng[], config.networkKeyFile, config.dataDir.string) var bootstrapRecords: seq[Record] loadBootstrapFile(string config.bootstrapNodesFile, bootstrapRecords) @@ -63,7 +68,7 @@ proc run(config: PortalConf) {.raises: [CatchableError, Defect].} = discoveryConfig = DiscoveryConfig.init( config.tableIpLimit, config.bucketIpLimit, config.bitsPerHop) d = newProtocol( - config.networkKey, + netkey, extIp, none(Port), extUdpPort, bootstrapRecords = bootstrapRecords, bindIp = bindIp, bindPort = udpPort,