enhance net-key command line option to accept random, hex, and path

- previously it only accept hex
- fix #587
This commit is contained in:
jangko 2022-07-27 23:07:54 +07:00
parent a087d65542
commit a5d4759bfd
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
6 changed files with 103 additions and 27 deletions

View File

@ -317,11 +317,14 @@ type
defaultValueDesc: $DiscoveryType.V4 defaultValueDesc: $DiscoveryType.V4
name: "discovery" .}: DiscoveryType name: "discovery" .}: DiscoveryType
nodeKeyHex* {. netKey* {.
desc: "P2P node private key (as 32 bytes hex string)" desc: "P2P ethereum node (secp256k1) private key (random, path, hex)"
defaultValue: "" longDesc:
defaultValueDesc: "random" "- random: generate random network key for this node instance\n" &
name: "node-key" .}: string "- path : path to where the private key will be loaded or auto generated\n" &
"- hex : 32 bytes hex of network private key"
defaultValue: "random"
name: "net-key" .}: string
agentString* {. agentString* {.
desc: "Node agent string which is used as identifier in network" desc: "Node agent string which is used as identifier in network"

View File

@ -8,8 +8,9 @@
# those terms. # those terms.
import import
std/[strutils, os],
accounts/manager, accounts/manager,
stew/results, stew/[results, io2, byteutils],
eth/keys eth/keys
export manager export manager
@ -32,12 +33,45 @@ proc randomPrivateKey*(ctx: EthContext): PrivateKey =
proc randomKeyPair*(ctx: EthContext): KeyPair = proc randomKeyPair*(ctx: EthContext): KeyPair =
random(KeyPair, ctx.rng[]) random(KeyPair, ctx.rng[])
proc hexToKeyPair*(ctx: EthContext, hexPrivateKey: string): Result[KeyPair, string] = proc containsOnlyHexDigits(hex: string): bool =
if hexPrivateKey.len == 0: const HexDigitsX = HexDigits + {'x'}
for c in hex:
if c notin HexDigitsX:
return false
true
proc getNetKeys*(ctx: EthContext, netKey, dataDir: string): Result[KeyPair, string] =
if netKey.len == 0 or netKey == "random":
let privateKey = ctx.randomPrivateKey() let privateKey = ctx.randomPrivateKey()
ok(privateKey.toKeyPair()) return ok(privateKey.toKeyPair())
else: elif netKey.len in {64, 66} and netKey.containsOnlyHexDigits:
let res = PrivateKey.fromHex(hexPrivateKey) let res = PrivateKey.fromHex(netKey)
if res.isErr: if res.isErr:
return err($res.error) return err($res.error)
ok(res.get().toKeyPair()) return ok(res.get().toKeyPair())
else:
# TODO: should we secure the private key with
# keystore encryption?
if fileAccessible(netKey, {AccessFlags.Find}):
try:
let lines = netKey.readLines(1)
if lines.len == 0:
return err("empty network key file")
let rc = PrivateKey.fromHex(lines[0])
if rc.isErr:
return err($rc.error)
return ok(rc.get().toKeyPair())
except IOError as e:
return err("cannot open network key file: " & e.msg)
except ValueError as ex:
return err("invalid hex string in network key file: " & ex.msg)
else:
let privateKey = ctx.randomPrivateKey()
try:
createDir(netKey.splitFile.dir)
netKey.writeFile(privateKey.toRaw.to0xHex)
except IOError as e:
return err("could not write network key file: " & e.msg)
return ok(privateKey.toKeyPair())

View File

@ -22,7 +22,7 @@ import
metrics, metrics,
metrics/[chronos_httpserver, chronicles_support], metrics/[chronos_httpserver, chronicles_support],
stew/shims/net as stewNet, stew/shims/net as stewNet,
websock/types as ws, websock/websock as ws,
"."/[conf_utils, config, constants, context, genesis, sealer, utils, version], "."/[conf_utils, config, constants, context, genesis, sealer, utils, version],
./db/[storage_types, db_chain, select_backend], ./db/[storage_types, db_chain, select_backend],
./graphql/ethapi, ./graphql/ethapi,
@ -69,21 +69,21 @@ proc manageAccounts(nimbus: NimbusNode, conf: NimbusConf) =
if string(conf.keyStore).len > 0: if string(conf.keyStore).len > 0:
let res = nimbus.ctx.am.loadKeystores(string conf.keyStore) let res = nimbus.ctx.am.loadKeystores(string conf.keyStore)
if res.isErr: if res.isErr:
echo res.error() fatal "Load keystore error", msg = res.error()
quit(QuitFailure) quit(QuitFailure)
if string(conf.importKey).len > 0: if string(conf.importKey).len > 0:
let res = nimbus.ctx.am.importPrivateKey(string conf.importKey) let res = nimbus.ctx.am.importPrivateKey(string conf.importKey)
if res.isErr: if res.isErr:
echo res.error() fatal "Import private key error", msg = res.error()
quit(QuitFailure) quit(QuitFailure)
proc setupP2P(nimbus: NimbusNode, conf: NimbusConf, proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
chainDB: BaseChainDB, protocols: set[ProtocolFlag]) = chainDB: BaseChainDB, protocols: set[ProtocolFlag]) =
## Creating P2P Server ## Creating P2P Server
let kpres = nimbus.ctx.hexToKeyPair(conf.nodeKeyHex) let kpres = nimbus.ctx.getNetKeys(conf.netKey, conf.dataDir.string)
if kpres.isErr: if kpres.isErr:
echo kpres.error() fatal "Get network keys error", msg = kpres.error
quit(QuitFailure) quit(QuitFailure)
let keypair = kpres.get() let keypair = kpres.get()
@ -117,7 +117,8 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
addAllCapabilities = false, minPeers = conf.maxPeers, addAllCapabilities = false, minPeers = conf.maxPeers,
bootstrapNodes = bootstrapNodes, bootstrapNodes = bootstrapNodes,
bindUdpPort = conf.udpPort, bindTcpPort = conf.tcpPort, bindUdpPort = conf.udpPort, bindTcpPort = conf.tcpPort,
bindIp = conf.listenAddress) bindIp = conf.listenAddress,
rng = nimbus.ctx.rng)
# Add protocol capabilities based on protocol flags # Add protocol capabilities based on protocol flags
if ProtocolFlag.Eth in protocols: if ProtocolFlag.Eth in protocols:
@ -187,12 +188,12 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics) discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics) discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
# Provide JWT authentication handler for websockets # Provide JWT authentication handler for rpcHttpServer
let jwtKey = block: let jwtKey = block:
# Create or load shared secret # Create or load shared secret
let rc = nimbus.ctx.rng.jwtSharedSecret(conf) let rc = nimbus.ctx.rng.jwtSharedSecret(conf)
if rc.isErr: if rc.isErr:
error "Failed create or load shared secret", fatal "Failed create or load shared secret",
msg = $(rc.unsafeError) # avoid side effects msg = $(rc.unsafeError) # avoid side effects
quit(QuitFailure) quit(QuitFailure)
rc.value rc.value
@ -250,7 +251,10 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
# Construct server object # Construct server object
nimbus.wsRpcServer = newRpcWebSocketServer( nimbus.wsRpcServer = newRpcWebSocketServer(
initTAddress(conf.wsAddress, conf.wsPort), initTAddress(conf.wsAddress, conf.wsPort),
authHooks = hooks authHooks = hooks,
# yuck, we should remove this ugly cast when
# we fix nim-websock
rng = cast[ws.Rng](nimbus.ctx.rng)
) )
setupCommonRpc(nimbus.ethNode, conf, nimbus.wsRpcServer) setupCommonRpc(nimbus.ethNode, conf, nimbus.wsRpcServer)
@ -284,7 +288,7 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
let rs = validateSealer(conf, nimbus.ctx, nimbus.chainRef) let rs = validateSealer(conf, nimbus.ctx, nimbus.chainRef)
if rs.isErr: if rs.isErr:
echo rs.error fatal "Engine signer validation error", msg = rs.error
quit(QuitFailure) quit(QuitFailure)
proc signFunc(signer: EthAddress, message: openArray[byte]): Result[RawSignature, cstring] {.gcsafe.} = proc signFunc(signer: EthAddress, message: openArray[byte]): Result[RawSignature, cstring] {.gcsafe.} =
@ -297,7 +301,7 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
nimbus.chainRef.clique.authorize(conf.engineSigner, signFunc) nimbus.chainRef.clique.authorize(conf.engineSigner, signFunc)
# always create sealing engine instanca but not always run it # always create sealing engine instance but not always run it
# e.g. engine api need sealing engine without it running # e.g. engine api need sealing engine without it running
var initialState = EngineStopped var initialState = EngineStopped
if chainDB.headTotalDifficulty() > chainDB.ttd: if chainDB.headTotalDifficulty() > chainDB.ttd:

View File

@ -1,8 +1,9 @@
import import
std/[os], std/[os],
pkg/[unittest2, confutils], pkg/[unittest2, confutils],
eth/[p2p, common], eth/[p2p, common, keys],
../nimbus/[config, chain_config], stew/byteutils,
../nimbus/[config, chain_config, context],
./test_helpers ./test_helpers
proc `==`(a, b: ChainId): bool = proc `==`(a, b: ChainId): bool =
@ -208,5 +209,39 @@ proc configurationMain*() =
check conf.engineApiEnabled == false check conf.engineApiEnabled == false
check conf.rpcEnabled == false check conf.rpcEnabled == false
let ctx = newEthContext()
test "net-key random":
let conf = makeConfig(@["--net-key:random"])
check conf.netKey == "random"
let rc = ctx.getNetKeys(conf.netKey, conf.dataDir.string)
check rc.isOk
test "net-key hex without 0x prefix":
let conf = makeConfig(@["--net-key:9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"])
check conf.netKey == "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
let rc = ctx.getNetKeys(conf.netKey, conf.dataDir.string)
check rc.isOk
let pkhex = rc.get.seckey.toRaw.to0xHex
check pkhex == "0x9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
test "net-key hex with 0x prefix":
let conf = makeConfig(@["--net-key:0x9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"])
check conf.netKey == "0x9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
let rc = ctx.getNetKeys(conf.netKey, conf.dataDir.string)
check rc.isOk
let pkhex = rc.get.seckey.toRaw.to0xHex
check pkhex == "0x9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
test "net-key path":
let conf = makeConfig(@["--net-key:nimcache/key.txt"])
check conf.netKey == "nimcache/key.txt"
let rc1 = ctx.getNetKeys(conf.netKey, conf.dataDir.string)
check rc1.isOk
let pkhex1 = rc1.get.seckey.toRaw.to0xHex
let rc2 = ctx.getNetKeys(conf.netKey, conf.dataDir.string)
check rc2.isOk
let pkhex2 = rc2.get.seckey.toRaw.to0xHex
check pkhex1 == pkhex2
when isMainModule: when isMainModule:
configurationMain() configurationMain()

View File

@ -278,7 +278,7 @@ proc hashLogEntries*(logs: seq[Log]): string =
proc setupEthNode*( proc setupEthNode*(
conf: NimbusConf, ctx: EthContext, conf: NimbusConf, ctx: EthContext,
capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode =
let keypair = ctx.hexToKeyPair(conf.nodeKeyHex).tryGet() let keypair = ctx.getNetKeys(conf.netKey, conf.dataDir.string).tryGet()
let srvAddress = Address( let srvAddress = Address(
ip: conf.listenAddress, tcpPort: conf.tcpPort, udpPort: conf.udpPort) ip: conf.listenAddress, tcpPort: conf.tcpPort, udpPort: conf.udpPort)

2
vendor/nim-json-rpc vendored

@ -1 +1 @@
Subproject commit 0fee4be2ccbbfa3f158b741c3a34b04130c8b424 Subproject commit 5ccdaed0adfb1534ee1d193fc6f97e7961008bbe