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
name: "discovery" .}: DiscoveryType
nodeKeyHex* {.
desc: "P2P node private key (as 32 bytes hex string)"
defaultValue: ""
defaultValueDesc: "random"
name: "node-key" .}: string
netKey* {.
desc: "P2P ethereum node (secp256k1) private key (random, path, hex)"
longDesc:
"- random: generate random network key for this node instance\n" &
"- 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* {.
desc: "Node agent string which is used as identifier in network"

View File

@ -8,8 +8,9 @@
# those terms.
import
std/[strutils, os],
accounts/manager,
stew/results,
stew/[results, io2, byteutils],
eth/keys
export manager
@ -32,12 +33,45 @@ proc randomPrivateKey*(ctx: EthContext): PrivateKey =
proc randomKeyPair*(ctx: EthContext): KeyPair =
random(KeyPair, ctx.rng[])
proc hexToKeyPair*(ctx: EthContext, hexPrivateKey: string): Result[KeyPair, string] =
if hexPrivateKey.len == 0:
proc containsOnlyHexDigits(hex: string): bool =
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()
ok(privateKey.toKeyPair())
else:
let res = PrivateKey.fromHex(hexPrivateKey)
return ok(privateKey.toKeyPair())
elif netKey.len in {64, 66} and netKey.containsOnlyHexDigits:
let res = PrivateKey.fromHex(netKey)
if res.isErr:
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/[chronos_httpserver, chronicles_support],
stew/shims/net as stewNet,
websock/types as ws,
websock/websock as ws,
"."/[conf_utils, config, constants, context, genesis, sealer, utils, version],
./db/[storage_types, db_chain, select_backend],
./graphql/ethapi,
@ -69,21 +69,21 @@ proc manageAccounts(nimbus: NimbusNode, conf: NimbusConf) =
if string(conf.keyStore).len > 0:
let res = nimbus.ctx.am.loadKeystores(string conf.keyStore)
if res.isErr:
echo res.error()
fatal "Load keystore error", msg = res.error()
quit(QuitFailure)
if string(conf.importKey).len > 0:
let res = nimbus.ctx.am.importPrivateKey(string conf.importKey)
if res.isErr:
echo res.error()
fatal "Import private key error", msg = res.error()
quit(QuitFailure)
proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
chainDB: BaseChainDB, protocols: set[ProtocolFlag]) =
## Creating P2P Server
let kpres = nimbus.ctx.hexToKeyPair(conf.nodeKeyHex)
let kpres = nimbus.ctx.getNetKeys(conf.netKey, conf.dataDir.string)
if kpres.isErr:
echo kpres.error()
fatal "Get network keys error", msg = kpres.error
quit(QuitFailure)
let keypair = kpres.get()
@ -117,7 +117,8 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
addAllCapabilities = false, minPeers = conf.maxPeers,
bootstrapNodes = bootstrapNodes,
bindUdpPort = conf.udpPort, bindTcpPort = conf.tcpPort,
bindIp = conf.listenAddress)
bindIp = conf.listenAddress,
rng = nimbus.ctx.rng)
# Add protocol capabilities based on protocol flags
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)
# Provide JWT authentication handler for websockets
# Provide JWT authentication handler for rpcHttpServer
let jwtKey = block:
# Create or load shared secret
let rc = nimbus.ctx.rng.jwtSharedSecret(conf)
if rc.isErr:
error "Failed create or load shared secret",
fatal "Failed create or load shared secret",
msg = $(rc.unsafeError) # avoid side effects
quit(QuitFailure)
rc.value
@ -250,7 +251,10 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
# Construct server object
nimbus.wsRpcServer = newRpcWebSocketServer(
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)
@ -284,7 +288,7 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
let rs = validateSealer(conf, nimbus.ctx, nimbus.chainRef)
if rs.isErr:
echo rs.error
fatal "Engine signer validation error", msg = rs.error
quit(QuitFailure)
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)
# 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
var initialState = EngineStopped
if chainDB.headTotalDifficulty() > chainDB.ttd:

View File

@ -1,8 +1,9 @@
import
std/[os],
pkg/[unittest2, confutils],
eth/[p2p, common],
../nimbus/[config, chain_config],
eth/[p2p, common, keys],
stew/byteutils,
../nimbus/[config, chain_config, context],
./test_helpers
proc `==`(a, b: ChainId): bool =
@ -208,5 +209,39 @@ proc configurationMain*() =
check conf.engineApiEnabled == 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:
configurationMain()

View File

@ -278,7 +278,7 @@ proc hashLogEntries*(logs: seq[Log]): string =
proc setupEthNode*(
conf: NimbusConf, ctx: EthContext,
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(
ip: conf.listenAddress, tcpPort: conf.tcpPort, udpPort: conf.udpPort)

2
vendor/nim-json-rpc vendored

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