config: remove global rng from NimbusConfiguration

move the rng to EthContext
This commit is contained in:
jangko 2021-09-07 20:45:01 +07:00
parent 34972c6cea
commit 9108301eef
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
8 changed files with 96 additions and 85 deletions

View File

@ -97,7 +97,7 @@ type
maxPendingPeers*: int ## Maximum allowed pending peers maxPendingPeers*: int ## Maximum allowed pending peers
networkId*: NetworkId ## Network ID as integer networkId*: NetworkId ## Network ID as integer
ident*: string ## Server ident name string ident*: string ## Server ident name string
nodeKey*: PrivateKey ## Server private key nodeKey*: string ## Server private key
nat*: NatStrategy ## NAT strategy nat*: NatStrategy ## NAT strategy
externalIP*: string ## user-provided external IP externalIP*: string ## user-provided external IP
protocols*: set[ProtocolFlags]## Enabled subprotocols protocols*: set[ProtocolFlags]## Enabled subprotocols
@ -125,9 +125,6 @@ type
net*: NetConfiguration ## Network configuration net*: NetConfiguration ## Network configuration
debug*: DebugConfiguration ## Debug configuration debug*: DebugConfiguration ## Debug configuration
customGenesis*: CustomGenesis ## Custom Genesis Configuration customGenesis*: CustomGenesis ## Custom Genesis Configuration
# You should only create one instance of the RNG per application / library
# Ref is used so that it can be shared between components
rng*: ref BrHmacDrbgContext
importKey*: string importKey*: string
importFile*: string importFile*: string
verifyFromOk*: bool ## activate `verifyFrom` setting verifyFromOk*: bool ## activate `verifyFrom` setting
@ -350,15 +347,6 @@ proc processENodesList(v: string, o: var seq[ENode]): ConfigStatus =
else: else:
break break
proc processPrivateKey(v: string, o: var PrivateKey): ConfigStatus =
## Convert hexadecimal string to private key object.
let seckey = PrivateKey.fromHex(v)
if seckey.isOk():
o = seckey[]
return Success
result = ErrorParseOption
proc processPruneList(v: string, flags: var PruneMode): ConfigStatus = proc processPruneList(v: string, flags: var PruneMode): ConfigStatus =
var list = newSeq[string]() var list = newSeq[string]()
processList(v, list) processList(v, list)
@ -556,10 +544,7 @@ proc processNetArguments(key, value: string): ConfigStatus =
if result == Success: if result == Success:
config.net.maxPendingPeers = res config.net.maxPendingPeers = res
elif skey == "nodekey": elif skey == "nodekey":
var res: PrivateKey config.net.nodeKey = value
result = processPrivateKey(value, res)
if result == Success:
config.net.nodeKey = res
elif skey == "ident": elif skey == "ident":
config.net.ident = value config.net.ident = value
elif skey == "nat": elif skey == "nat":
@ -660,7 +645,6 @@ proc getDefaultKeystoreDir*(): string =
proc initConfiguration(): NimbusConfiguration = proc initConfiguration(): NimbusConfiguration =
## Allocates and initializes `NimbusConfiguration` with default values ## Allocates and initializes `NimbusConfiguration` with default values
result = new NimbusConfiguration result = new NimbusConfiguration
result.rng = newRng()
## Graphql defaults ## Graphql defaults
result.graphql.enabled = false result.graphql.enabled = false
@ -685,7 +669,6 @@ proc initConfiguration(): NimbusConfiguration =
result.net.ident = NimbusIdent result.net.ident = NimbusIdent
result.net.nat = NatAny result.net.nat = NatAny
result.net.protocols = defaultProtocols result.net.protocols = defaultProtocols
result.net.nodekey = random(PrivateKey, result.rng[])
const const
dataDir = getDefaultDataDir() dataDir = getDefaultDataDir()

View File

@ -8,15 +8,36 @@
# those terms. # those terms.
import import
accounts/manager accounts/manager,
stew/results,
eth/keys
export manager export manager
type type
EthContext* = ref object EthContext* = ref object
am*: AccountsManager am*: AccountsManager
# You should only create one instance of the RNG per application / library
# Ref is used so that it can be shared between components
rng*: ref BrHmacDrbgContext
proc newEthContext*(): EthContext = proc newEthContext*(): EthContext =
result = new(EthContext) result = new(EthContext)
result.am = AccountsManager.init() result.am = AccountsManager.init()
result.rng = newRng()
proc randomPrivateKey*(ctx: EthContext): PrivateKey =
random(PrivateKey, ctx.rng[])
proc randomKeyPair*(ctx: EthContext): KeyPair =
random(KeyPair, ctx.rng[])
proc hexToKeyPair*(ctx: EthContext, hexPrivateKey: string): Result[KeyPair, string] =
if hexPrivateKey.len == 0:
let privateKey = ctx.randomPrivateKey()
ok(privateKey.toKeyPair())
else:
let res = PrivateKey.fromHex(hexPrivateKey)
if res.isErr:
return err($res.error)
ok(res.get().toKeyPair())

View File

@ -20,7 +20,7 @@ import
./sync/protocol_eth65, ./sync/protocol_eth65,
config, genesis, rpc/[common, p2p, debug], p2p/chain, config, genesis, rpc/[common, p2p, debug], p2p/chain,
eth/trie/db, metrics, metrics/[chronos_httpserver, chronicles_support], eth/trie/db, metrics, metrics/[chronos_httpserver, chronicles_support],
graphql/ethapi, graphql/ethapi, context,
"."/[utils, conf_utils, sealer, constants] "."/[utils, conf_utils, sealer, constants]
## TODO: ## TODO:
@ -36,12 +36,13 @@ type
Starting, Running, Stopping Starting, Running, Stopping
NimbusNode = ref object NimbusNode = ref object
rpcServer*: RpcHttpServer rpcServer: RpcHttpServer
ethNode*: EthereumNode ethNode: EthereumNode
state*: NimbusState state: NimbusState
graphqlServer*: GraphqlHttpServerRef graphqlServer: GraphqlHttpServerRef
wsRpcServer*: RpcWebSocketServer wsRpcServer: RpcWebSocketServer
sealingEngine*: SealingEngineRef sealingEngine: SealingEngineRef
ctx: EthContext
proc start(nimbus: NimbusNode) = proc start(nimbus: NimbusNode) =
var conf = getConfiguration() var conf = getConfiguration()
@ -71,7 +72,14 @@ proc start(nimbus: NimbusNode) =
else: else:
quit(QuitSuccess) quit(QuitSuccess)
let res = conf.loadKeystoreFiles() if conf.keyStore.len > 0:
let res = nimbus.ctx.am.loadKeystores(conf.keyStore)
if res.isErr:
echo res.error()
quit(QuitFailure)
if conf.importKey.len > 0:
let res = nimbus.ctx.am.importPrivateKey(conf.importKey)
if res.isErr: if res.isErr:
echo res.error() echo res.error()
quit(QuitFailure) quit(QuitFailure)
@ -88,7 +96,12 @@ proc start(nimbus: NimbusNode) =
discard setTimer(Moment.fromNow(conf.debug.logMetricsInterval.seconds), logMetrics) discard setTimer(Moment.fromNow(conf.debug.logMetricsInterval.seconds), logMetrics)
## Creating P2P Server ## Creating P2P Server
let keypair = conf.net.nodekey.toKeyPair() let kpres = nimbus.ctx.hexToKeyPair(conf.net.nodekey)
if kpres.isErr:
echo kpres.error()
quit(QuitFailure)
let keypair = kpres.get()
var address: Address var address: Address
address.ip = parseIpAddress("0.0.0.0") address.ip = parseIpAddress("0.0.0.0")
@ -136,7 +149,7 @@ proc start(nimbus: NimbusNode) =
# Enable RPC APIs based on RPC flags and protocol flags # Enable RPC APIs based on RPC flags and protocol flags
if RpcFlags.Eth in conf.rpc.flags and ProtocolFlags.Eth in conf.net.protocols: if RpcFlags.Eth in conf.rpc.flags and ProtocolFlags.Eth in conf.net.protocols:
setupEthRpc(nimbus.ethNode, chainDB, nimbus.rpcServer) setupEthRpc(nimbus.ethNode, nimbus.ctx, chainDB, nimbus.rpcServer)
if RpcFlags.Debug in conf.rpc.flags: if RpcFlags.Debug in conf.rpc.flags:
setupDebugRpc(chainDB, nimbus.rpcServer) setupDebugRpc(chainDB, nimbus.rpcServer)
@ -148,7 +161,7 @@ proc start(nimbus: NimbusNode) =
# Enable Websocket RPC APIs based on RPC flags and protocol flags # Enable Websocket RPC APIs based on RPC flags and protocol flags
if RpcFlags.Eth in conf.ws.flags and ProtocolFlags.Eth in conf.net.protocols: if RpcFlags.Eth in conf.ws.flags and ProtocolFlags.Eth in conf.net.protocols:
setupEthRpc(nimbus.ethNode, chainDB, nimbus.wsRpcServer) setupEthRpc(nimbus.ethNode, nimbus.ctx, chainDB, nimbus.wsRpcServer)
if RpcFlags.Debug in conf.ws.flags: if RpcFlags.Debug in conf.ws.flags:
setupDebugRpc(chainDB, nimbus.wsRpcServer) setupDebugRpc(chainDB, nimbus.wsRpcServer)
@ -165,11 +178,13 @@ proc start(nimbus: NimbusNode) =
nimbus.graphqlServer.start() nimbus.graphqlServer.start()
if conf.engineSigner != ZERO_ADDRESS: if conf.engineSigner != ZERO_ADDRESS:
let rs = validateSealer(chainRef) let rs = validateSealer(conf, nimbus.ctx, chainRef)
if rs.isErr: if rs.isErr:
echo rs.error echo rs.error
quit(QuitFailure) quit(QuitFailure)
nimbus.sealingEngine = SealingEngineRef.new(chainRef) nimbus.sealingEngine = SealingEngineRef.new(
chainRef, nimbus.ctx, conf.engineSigner
)
nimbus.sealingEngine.start() nimbus.sealingEngine.start()
# metrics server # metrics server
@ -224,7 +239,7 @@ proc process*(nimbus: NimbusNode) =
waitFor nimbus.stop() waitFor nimbus.stop()
when isMainModule: when isMainModule:
var nimbus = NimbusNode(state: Starting) var nimbus = NimbusNode(state: Starting, ctx: newEthContext())
## Ctrl+C handling ## Ctrl+C handling
proc controlCHandler() {.noconv.} = proc controlCHandler() {.noconv.} =

View File

@ -1,10 +0,0 @@
import eth/keys, config
proc getRng*(): ref BrHmacDrbgContext =
getConfiguration().rng
proc randomPrivateKey*(): PrivateKey =
random(PrivateKey, getRng()[])
proc randomKeyPair*(): KeyPair =
random(KeyPair, getRng()[])

View File

@ -18,8 +18,7 @@ import
clique_sealer, clique_sealer,
clique_snapshot], clique_snapshot],
./p2p/gaslimit, ./p2p/gaslimit,
./chain_config, "."/[chain_config, utils, context]
./utils
type type
EngineState = enum EngineState = enum
@ -30,16 +29,18 @@ type
state: EngineState state: EngineState
engineLoop: Future[void] engineLoop: Future[void]
chain: Chain chain: Chain
ctx: EthContext
signer: EthAddress
proc validateSealer*(chain: Chain): Result[void, string] = proc validateSealer*(conf: NimbusConfiguration, ctx: EthContext, chain: Chain): Result[void, string] =
let conf = getConfiguration()
if conf.engineSigner == ZERO_ADDRESS: if conf.engineSigner == ZERO_ADDRESS:
return err("signer address should not zero, use --engine-signer to set signer address") return err("signer address should not zero, use --engine-signer to set signer address")
if conf.engineSigner notin conf.accounts: let res = ctx.am.getAccount(conf.engineSigner)
if res.isErr:
return err("signer address not in registered accounts, use --import-key/account to register the account") return err("signer address not in registered accounts, use --import-key/account to register the account")
let acc = conf.accounts[conf.engineSigner] let acc = res.get()
if not acc.unlocked: if not acc.unlocked:
return err("signer account not unlocked, please unlock it first via rpc/password file") return err("signer account not unlocked, please unlock it first via rpc/password file")
@ -119,21 +120,20 @@ proc generateBlock(engine: SealingEngineRef, ethBlock: var EthBlock): Result[voi
ok() ok()
proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
let clique = engine.chain.clique
proc signerFunc(signer: EthAddress, message: openArray[byte]): proc signerFunc(signer: EthAddress, message: openArray[byte]):
Result[RawSignature, cstring] {.gcsafe.} = Result[RawSignature, cstring] {.gcsafe.} =
let let
hashData = keccakHash(message) hashData = keccakHash(message)
conf = getConfiguration() ctx = engine.ctx
acc = conf.accounts[signer] acc = ctx.am.getAccount(signer).tryGet()
rawSign = sign(acc.privateKey, SkMessage(hashData.data)).toRaw rawSign = sign(acc.privateKey, SkMessage(hashData.data)).toRaw
ok(rawSign) ok(rawSign)
proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} = clique.authorize(engine.signer, signerFunc)
let clique = engine.chain.clique
let conf = getConfiguration()
clique.authorize(conf.engineSigner, signerFunc)
# convert times.Duration to chronos.Duration # convert times.Duration to chronos.Duration
let period = chronos.seconds(clique.cfg.period.inSeconds) let period = chronos.seconds(clique.cfg.period.inSeconds)
@ -164,9 +164,14 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
info "block generated", number=blk.header.blockNumber info "block generated", number=blk.header.blockNumber
proc new*(_: type SealingEngineRef, chain: Chain): SealingEngineRef = proc new*(_: type SealingEngineRef,
chain: Chain,
ctx: EthContext,
signer: EthAddress): SealingEngineRef =
SealingEngineRef( SealingEngineRef(
chain: chain chain: chain,
ctx: ctx,
signer: signer
) )
proc start*(engine: SealingEngineRef) = proc start*(engine: SealingEngineRef) =

View File

@ -13,7 +13,8 @@ import
eth/[p2p, common, trie/db, rlp, trie], eth/[p2p, common, trie/db, rlp, trie],
graphql, ../nimbus/graphql/ethapi, graphql/test_common, graphql, ../nimbus/graphql/ethapi, graphql/test_common,
../nimbus/sync/protocol_eth65, ../nimbus/sync/protocol_eth65,
../nimbus/[genesis, config, chain_config], ../nimbus/db/[db_chain, state_db], ../nimbus/[genesis, config, chain_config, context],
../nimbus/db/[db_chain, state_db],
../nimbus/p2p/chain, ../premix/parser, ./test_helpers ../nimbus/p2p/chain, ../premix/parser, ./test_helpers
type type
@ -83,7 +84,8 @@ proc graphqlMain*() =
) )
let let
ethNode = setupEthNode(eth) ethCtx = newEthContext()
ethNode = setupEthNode(conf, ethCtx, eth)
chainDB = newBaseChainDB(newMemoryDb(), chainDB = newBaseChainDB(newMemoryDb(),
pruneTrie = false, pruneTrie = false,
conf.net.networkId conf.net.networkId

View File

@ -11,7 +11,7 @@ import
testutils/markdown_reports, testutils/markdown_reports,
../nimbus/[constants, config, transaction, utils, errors, forks], ../nimbus/[constants, config, transaction, utils, errors, forks],
../nimbus/db/accounts_cache, ../nimbus/db/accounts_cache,
../nimbus/random_keys ../nimbus/context
func revmap(x: Table[Fork, string]): Table[string, Fork] = func revmap(x: Table[Fork, string]): Table[string, Fork] =
result = initTable[string, Fork]() result = initTable[string, Fork]()
@ -272,11 +272,8 @@ proc getFixtureTransaction*(j: JsonNode, dataIndex, gasIndex, valueIndex: int):
proc hashLogEntries*(logs: seq[Log]): string = proc hashLogEntries*(logs: seq[Log]): string =
toLowerAscii("0x" & $keccakHash(rlp.encode(logs))) toLowerAscii("0x" & $keccakHash(rlp.encode(logs)))
proc setupEthNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = proc setupEthNode*(conf: NimbusConfiguration, ctx: EthContext, capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode =
var conf = getConfiguration() let keypair = ctx.hexToKeyPair(conf.net.nodekey).tryGet()
conf.net.nodekey = randomPrivateKey()
let keypair = conf.net.nodekey.toKeyPair()
var srvAddress: Address var srvAddress: Address
srvAddress.ip = parseIpAddress("0.0.0.0") srvAddress.ip = parseIpAddress("0.0.0.0")
srvAddress.tcpPort = Port(conf.net.bindPort) srvAddress.tcpPort = Port(conf.net.bindPort)

View File

@ -123,16 +123,14 @@ proc setupEnv(chain: BaseChainDB, signer, ks2: EthAddress, ctx: EthContext): Tes
proc rpcMain*() = proc rpcMain*() =
suite "Remote Procedure Calls": suite "Remote Procedure Calls":
# TODO: Include other transports such as Http # TODO: Include other transports such as Http
var
ethNode = setupEthNode(eth)
chain = newBaseChainDB(newMemoryDb())
let let
conf = getConfiguration()
ctx = newEthContext()
ethNode = setupEthNode(conf, ctx, eth)
chain = newBaseChainDB(newMemoryDb())
signer: EthAddress = hexToByteArray[20]("0x0e69cde81b1aa07a45c32c6cd85d67229d36bb1b") signer: EthAddress = hexToByteArray[20]("0x0e69cde81b1aa07a45c32c6cd85d67229d36bb1b")
ks2: EthAddress = hexToByteArray[20]("0xa3b2222afa5c987da6ef773fde8d01b9f23d481f") ks2: EthAddress = hexToByteArray[20]("0xa3b2222afa5c987da6ef773fde8d01b9f23d481f")
ks3: EthAddress = hexToByteArray[20]("0x597176e9a64aad0845d83afdaf698fbeff77703b") ks3: EthAddress = hexToByteArray[20]("0x597176e9a64aad0845d83afdaf698fbeff77703b")
conf = getConfiguration()
ctx = newEthContext()
ethNode.chain = newChain(chain) ethNode.chain = newChain(chain)
conf.keyStore = "tests" / "keystore" conf.keyStore = "tests" / "keystore"