Add staticnodes, protocols, and whisper config options (#319)

This commit is contained in:
kdeme 2019-04-23 15:49:49 +02:00 committed by Jacek Sieka
parent c7acb879db
commit 46fb9dc1b2
2 changed files with 101 additions and 12 deletions

View File

@ -10,6 +10,7 @@
import import
parseopt, strutils, macros, os, times, parseopt, strutils, macros, os, times,
chronos, eth/[keys, common, p2p, net/nat], chronicles, nimcrypto/hash, chronos, eth/[keys, common, p2p, net/nat], chronicles, nimcrypto/hash,
eth/p2p/rlpx_protocols/whisper_protocol,
./db/select_backend, ./db/select_backend,
./vm/interpreter/vm_forks ./vm/interpreter/vm_forks
@ -96,6 +97,12 @@ type
Shh ## enable shh_ set of RPC API Shh ## enable shh_ set of RPC API
Debug ## enable debug_ set of RPC API Debug ## enable debug_ set of RPC API
ProtocolFlags* {.pure.} = enum
## Protocol flags
Eth ## enable eth subprotocol
Shh ## enable whisper subprotocol
Les ## enable les subprotocol
RpcConfiguration* = object RpcConfiguration* = object
## JSON-RPC configuration object ## JSON-RPC configuration object
flags*: set[RpcFlags] ## RPC flags flags*: set[RpcFlags] ## RPC flags
@ -125,6 +132,7 @@ type
## Network configuration object ## Network configuration object
flags*: set[NetworkFlags] ## Network flags flags*: set[NetworkFlags] ## Network flags
bootNodes*: seq[ENode] ## List of bootnodes bootNodes*: seq[ENode] ## List of bootnodes
staticNodes*: seq[ENode] ## List of static nodes to connect to
bindPort*: uint16 ## Main TCP bind port bindPort*: uint16 ## Main TCP bind port
discPort*: uint16 ## Discovery UDP bind port discPort*: uint16 ## Discovery UDP bind port
maxPeers*: int ## Maximum allowed number of peers maxPeers*: int ## Maximum allowed number of peers
@ -134,6 +142,7 @@ type
nodeKey*: PrivateKey ## Server private key nodeKey*: PrivateKey ## 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
DebugConfiguration* = object DebugConfiguration* = object
## Debug configuration object ## Debug configuration object
@ -169,9 +178,11 @@ type
rpc*: RpcConfiguration ## JSON-RPC configuration rpc*: RpcConfiguration ## JSON-RPC configuration
net*: NetConfiguration ## Network configuration net*: NetConfiguration ## Network configuration
debug*: DebugConfiguration ## Debug configuration debug*: DebugConfiguration ## Debug configuration
shh*: WhisperConfig ## Whisper configuration
const const
defaultRpcApi = {RpcFlags.Eth, RpcFlags.Shh} defaultRpcApi = {RpcFlags.Eth, RpcFlags.Shh}
defaultProtocols = {ProtocolFlags.Eth, ProtocolFlags.Shh}
defaultLogLevel = LogLevel.WARN defaultLogLevel = LogLevel.WARN
var nimbusConfig {.threadvar.}: NimbusConfiguration var nimbusConfig {.threadvar.}: NimbusConfiguration
@ -236,6 +247,14 @@ proc processInteger*(v: string, o: var int): ConfigStatus =
except: except:
result = ErrorParseOption result = ErrorParseOption
proc processFloat*(v: string, o: var float): ConfigStatus =
## Convert string to float.
try:
o = parseFloat(v)
result = Success
except:
result = ErrorParseOption
proc processAddressPortsList(v: string, proc processAddressPortsList(v: string,
o: var seq[TransportAddress]): ConfigStatus = o: var seq[TransportAddress]): ConfigStatus =
## Convert <hostname:port>;...;<hostname:port> to list of `TransportAddress`. ## Convert <hostname:port>;...;<hostname:port> to list of `TransportAddress`.
@ -273,6 +292,19 @@ proc processRpcApiList(v: string, flags: var set[RpcFlags]): ConfigStatus =
warn "unknown rpc api", name = item warn "unknown rpc api", name = item
result = ErrorIncorrectOption result = ErrorIncorrectOption
proc processProtocolList(v: string, flags: var set[ProtocolFlags]): ConfigStatus =
var list = newSeq[string]()
processList(v, list)
result = Success
for item in list:
case item.toLowerAscii()
of "eth": flags.incl ProtocolFlags.Eth
of "shh": flags.incl ProtocolFlags.Shh
of "les": flags.incl ProtocolFlags.Les
else:
warn "unknown protocol", name = item
result = ErrorIncorrectOption
proc processENode(v: string, o: var ENode): ConfigStatus = proc processENode(v: string, o: var ENode): ConfigStatus =
## Convert string to ENode. ## Convert string to ENode.
let res = initENode(v, o) let res = initENode(v, o)
@ -427,6 +459,8 @@ proc processNetArguments(key, value: string): ConfigStatus =
result = processENodesList(value, config.net.bootNodes) result = processENodesList(value, config.net.bootNodes)
elif skey == "bootnodesv5": elif skey == "bootnodesv5":
result = processENodesList(value, config.net.bootNodes) result = processENodesList(value, config.net.bootNodes)
elif skey == "staticnodes":
result = processENodesList(value, config.net.staticNodes)
elif skey == "testnet": elif skey == "testnet":
config.net.setNetwork(RopstenNet) config.net.setNetwork(RopstenNet)
elif skey == "mainnet": elif skey == "mainnet":
@ -493,6 +527,29 @@ proc processNetArguments(key, value: string): ConfigStatus =
else: else:
error "not a valid NAT mechanism, nor a valid IP address", value error "not a valid NAT mechanism, nor a valid IP address", value
result = ErrorParseOption result = ErrorParseOption
elif skey == "protocols":
config.net.protocols = {}
result = processProtocolList(value, config.net.protocols)
else:
result = EmptyOption
proc processShhArguments(key, value: string): ConfigStatus =
## Processes only `Shh` related command line options
result = Success
let config = getConfiguration()
let skey = key.toLowerAscii()
if skey == "shh-maxsize":
var res = 0
result = processInteger(value, res)
if result == Success:
config.shh.maxMsgSize = res.uint32
elif skey == "shh-pow":
var res = 0.0
result = processFloat(value, res)
if result == Success:
config.shh.powRequirement = res
elif skey == "shh-light":
config.shh.isLightNode = true
else: else:
result = EmptyOption result = EmptyOption
@ -571,12 +628,19 @@ proc initConfiguration(): NimbusConfiguration =
result.net.discPort = 30303'u16 result.net.discPort = 30303'u16
result.net.ident = NimbusIdent result.net.ident = NimbusIdent
result.net.nat = NatAny result.net.nat = NatAny
result.net.protocols = defaultProtocols
const dataDir = getDefaultDataDir() const dataDir = getDefaultDataDir()
result.dataDir = getHomeDir() / dataDir result.dataDir = getHomeDir() / dataDir
result.prune = PruneMode.Full result.prune = PruneMode.Full
## Whisper defaults
result.shh.maxMsgSize = defaultMaxMsgSize
result.shh.powRequirement = defaultMinPow
result.shh.isLightNode = false
result.shh.bloom = fullBloom()
## Debug defaults ## Debug defaults
result.debug.flags = {} result.debug.flags = {}
result.debug.logLevel = defaultLogLevel result.debug.logLevel = defaultLogLevel
@ -608,6 +672,7 @@ NETWORKING OPTIONS:
--bootnodes:<value> Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers) --bootnodes:<value> Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)
--bootnodesv4:<value> Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes) --bootnodesv4:<value> Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)
--bootnodesv5:<value> Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes) --bootnodesv5:<value> Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)
--staticnodes:<value> Comma separated enode URLs to connect with
--port:<value> Network listening TCP port (default: 30303) --port:<value> Network listening TCP port (default: 30303)
--discport:<value> Network listening UDP port (defaults to --port argument) --discport:<value> Network listening UDP port (defaults to --port argument)
--maxpeers:<value> Maximum number of network peers (default: 25) --maxpeers:<value> Maximum number of network peers (default: 25)
@ -623,6 +688,12 @@ NETWORKING OPTIONS:
--morden Use Ethereum Morden Test Network --morden Use Ethereum Morden Test Network
--networkid:<value> Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby) (default: 3) --networkid:<value> Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby) (default: 3)
--ident:<value> Client identifier (default is '$1') --ident:<value> Client identifier (default is '$1')
--protocols:<value> Enable specific set of protocols (default: $4)
WHISPER OPTIONS:
--shh-maxsize:<value> Max message size accepted (default: $5)
--shh-pow:<value> Minimum POW accepted (default: $6)
--shh-light Run as Whisper light client (no outgoing messages)
API AND CONSOLE OPTIONS: API AND CONSOLE OPTIONS:
--rpc Enable the HTTP-RPC server --rpc Enable the HTTP-RPC server
@ -637,7 +708,10 @@ LOGGING AND DEBUGGING OPTIONS:
""" % [ """ % [
NimbusIdent, NimbusIdent,
join(logLevels, ", "), join(logLevels, ", "),
$defaultLogLevel $defaultLogLevel,
strip($defaultProtocols, chars = {'{','}'}),
$defaultMaxMsgSize,
$defaultMinPow
] ]
proc processArguments*(msg: var string): ConfigStatus = proc processArguments*(msg: var string): ConfigStatus =
@ -679,6 +753,7 @@ proc processArguments*(msg: var string): ConfigStatus =
processArgument processEthArguments, key, value, msg processArgument processEthArguments, key, value, msg
processArgument processRpcArguments, key, value, msg processArgument processRpcArguments, key, value, msg
processArgument processNetArguments, key, value, msg processArgument processNetArguments, key, value, msg
processArgument processShhArguments, key, value, msg
processArgument processDebugArguments, key, value, msg processArgument processDebugArguments, key, value, msg
if result != Success: if result != Success:
msg = "Unknown option: '" & key & "'." msg = "Unknown option: '" & key & "'."

View File

@ -12,8 +12,8 @@ import
eth/keys, db/[storage_types, db_chain, select_backend], eth/keys, db/[storage_types, db_chain, select_backend],
eth/common as eth_common, eth/p2p as eth_p2p, eth/common as eth_common, eth/p2p as eth_p2p,
chronos, json_rpc/rpcserver, chronicles, chronos, json_rpc/rpcserver, chronicles,
eth/p2p/rlpx_protocols/[eth_protocol, les_protocol], eth/p2p/rlpx_protocols/[eth_protocol, les_protocol, whisper_protocol],
eth/p2p/blockchain_sync, eth/net/nat, eth/p2p/blockchain_sync, eth/net/nat, eth/p2p/peer_pool,
config, genesis, rpc/[common, p2p, debug, whisper], p2p/chain, config, genesis, rpc/[common, p2p, debug, whisper], p2p/chain,
eth/trie/db eth/trie/db
@ -91,16 +91,24 @@ proc start(): NimbusObject =
doAssert(canonicalHeadHashKey().toOpenArray in trieDB) doAssert(canonicalHeadHashKey().toOpenArray in trieDB)
nimbus.ethNode = newEthereumNode(keypair, address, conf.net.networkId, nimbus.ethNode = newEthereumNode(keypair, address, conf.net.networkId,
nil, nimbusClientId) nil, nimbusClientId,
addAllCapabilities = false)
# Add protocol capabilities based on protocol flags
if ProtocolFlags.Eth in conf.net.protocols:
nimbus.ethNode.addCapability eth
if ProtocolFlags.Shh in conf.net.protocols:
nimbus.ethNode.addCapability Whisper
nimbus.ethNode.configureWhisper(conf.shh)
if ProtocolFlags.Les in conf.net.protocols:
nimbus.ethNode.addCapability les
nimbus.ethNode.chain = newChain(chainDB) nimbus.ethNode.chain = newChain(chainDB)
if RpcFlags.Eth in conf.rpc.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:
setupEthRpc(nimbus.ethNode, chainDB, nimbus.rpcServer) setupEthRpc(nimbus.ethNode, chainDB, nimbus.rpcServer)
if RpcFlags.Shh in conf.rpc.flags and ProtocolFlags.Shh in conf.net.protocols:
if RpcFlags.Shh in conf.rpc.flags:
setupWhisperRPC(nimbus.rpcServer) setupWhisperRPC(nimbus.rpcServer)
if RpcFlags.Debug in conf.rpc.flags: if RpcFlags.Debug in conf.rpc.flags:
setupDebugRpc(chainDB, nimbus.rpcServer) setupDebugRpc(chainDB, nimbus.rpcServer)
@ -112,9 +120,15 @@ proc start(): NimbusObject =
result = "EXITING" result = "EXITING"
nimbus.rpcServer.start() nimbus.rpcServer.start()
# Connect directly to the static nodes
for enode in conf.net.staticNodes:
asyncCheck nimbus.ethNode.peerPool.connectToNode(newNode(enode))
# Connect via discovery
waitFor nimbus.ethNode.connectToNetwork(conf.net.bootNodes, waitFor nimbus.ethNode.connectToNetwork(conf.net.bootNodes,
enableDiscovery = NoDiscover notin conf.net.flags) enableDiscovery = NoDiscover notin conf.net.flags)
if ProtocolFlags.Eth in conf.net.protocols:
# TODO: temp code until the CLI/RPC interface is fleshed out # TODO: temp code until the CLI/RPC interface is fleshed out
let status = waitFor nimbus.ethNode.fastBlockchainSync() let status = waitFor nimbus.ethNode.fastBlockchainSync()
if status != syncSuccess: if status != syncSuccess: