config: remove global rng from NimbusConfiguration
move the rng to EthContext
This commit is contained in:
parent
34972c6cea
commit
9108301eef
|
@ -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()
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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.} =
|
||||||
|
|
|
@ -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()[])
|
|
|
@ -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) =
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue