2018-04-27 08:53:53 +00:00
# Nimbus
2019-01-06 22:06:26 +00:00
# Copyright (c) 2018-2019 Status Research & Development GmbH
2018-04-27 08:53:53 +00:00
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
2018-10-16 00:10:01 +00:00
import
2019-01-06 22:06:26 +00:00
parseopt , strutils , macros , os , times ,
2019-04-17 01:56:28 +00:00
chronos , eth / [ keys , common , p2p , net / nat ] , chronicles , nimcrypto / hash ,
2019-04-23 13:49:49 +00:00
eth / p2p / rlpx_protocols / whisper_protocol ,
2019-01-06 22:06:26 +00:00
. / db / select_backend ,
2018-11-28 19:02:21 +00:00
. / vm / interpreter / vm_forks
2018-04-27 08:53:53 +00:00
2019-01-15 15:25:14 +00:00
const
2018-04-27 08:53:53 +00:00
NimbusName * = " Nimbus "
## project name string
2018-05-02 15:01:10 +00:00
2018-04-27 08:53:53 +00:00
NimbusMajor * : int = 0
## is the major number of Nimbus' version.
NimbusMinor * : int = 0
## is the minor number of Nimbus' version.
NimbusPatch * : int = 1
## is the patch number of Nimbus' version.
NimbusVersion * = $ NimbusMajor & " . " & $ NimbusMinor & " . " & $ NimbusPatch
## is the version of Nimbus as a string.
2019-01-15 15:25:14 +00:00
NimbusIdent * = " $1 / $2 ( $3 / $4 ) " % [ NimbusName , NimbusVersion , hostCPU , hostOS ]
## project ident name for networking services
let
NimbusCopyright * = " Copyright (C) 2018- " & $ ( now ( ) . utc . year ) & " Status Research & Development GmbH "
## copyright string
2018-06-20 17:27:32 +00:00
NimbusHeader * = NimbusName & " Version " & NimbusVersion &
2019-01-06 22:06:26 +00:00
" [ " & hostOS & " : " & hostCPU & " , " & nimbus_db_backend & " ] \r \n " &
2018-06-20 17:27:32 +00:00
NimbusCopyright
## is the header which printed, when nimbus binary got executed
const
MainnetBootnodes = [
2019-07-30 09:00:55 +00:00
# Ethereum Foundation Go Bootnodes
" enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303 " , # bootnode-aws-ap-southeast-1-001
" enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303 " , # bootnode-aws-us-east-1-001
" enode://ca6de62fce278f96aea6ec5a2daadb877e51651247cb96ee310a318def462913b653963c155a0ef6c7d50048bba6e6cea881130857413d9f50a621546b590758@34.255.23.113:30303 " , # bootnode-aws-eu-west-1-001
" enode://279944d8dcd428dffaa7436f25ca0ca43ae19e7bcf94a8fb7d1641651f92d121e972ac2e8f381414b80cc8e5555811c2ec6e1a99bb009b3f53c4c69923e11bd8@35.158.244.151:30303 " , # bootnode-aws-eu-central-1-001
" enode://8499da03c47d637b20eee24eec3c356c9a2e6148d6fe25ca195c7949ab8ec2c03e3556126b0d7ed644675e78c4318b08691b7b57de10e5f0d40d05b09238fa0a@52.187.207.27:30303 " , # bootnode-azure-australiaeast-001
" enode://103858bdb88756c71f15e9b5e09b56dc1be52f0a5021d46301dbbfb7e130029cc9d0d6f73f693bc29b665770fff7da4d34f3c6379fe12721b5d7a0bcb5ca1fc1@191.234.162.198:30303 " , # bootnode-azure-brazilsouth-001
" enode://715171f50508aba88aecd1250af392a45a330af91d7b90701c436b618c86aaa1589c9184561907bebbb56439b8f8787bc01f49a7c77276c58c1b09822d75e8e8@52.231.165.108:30303 " , # bootnode-azure-koreasouth-001
" enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303 " , # bootnode-azure-westus-001
# Ethereum Foundation C++ Bootnodes
2018-06-20 17:27:32 +00:00
" enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303 " # DE
]
RopstenBootnodes = [
" enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303 " , # US-Azure geth
" enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303 " , # US-Azure parity
" enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303 " , # Parity
" enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303 " # @gpip
]
RinkebyBootnodes = [
" enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303 " , # IE
" enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303 " , # INFURA
" enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303 " , # AKASHA
]
DiscoveryV5Bootnodes = [
" enode://06051a5573c81934c9554ef2898eb13b33a34b94cf36b202b69fde139ca17a85051979867720d4bdae4323d4943ddf9aeeb6643633aa656e0be843659795007a@35.177.226.168:30303 " ,
" enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30304 " ,
" enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30306 " ,
" enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30307 "
]
KovanBootnodes = [
" enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303 " ,
" enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303 " ,
" enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303 " ,
" enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303 " ,
" enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303 "
]
2018-04-27 08:53:53 +00:00
type
ConfigStatus * = enum
## Configuration status flags
2018-06-20 17:27:32 +00:00
Success , ## Success
EmptyOption , ## No options in category
ErrorUnknownOption , ## Unknown option in command line found
ErrorParseOption , ## Error in parsing command line option
ErrorIncorrectOption , ## Option has incorrect value
Error ## Unspecified error
2018-04-27 08:53:53 +00:00
RpcFlags * {. pure . } = enum
## RPC flags
2018-06-20 17:27:32 +00:00
Enabled ## RPC enabled
2018-11-22 06:40:09 +00:00
Eth ## enable eth_ set of RPC API
Shh ## enable shh_ set of RPC API
Debug ## enable debug_ set of RPC API
2018-04-27 08:53:53 +00:00
2019-04-23 13:49:49 +00:00
ProtocolFlags * {. pure . } = enum
## Protocol flags
Eth ## enable eth subprotocol
Shh ## enable whisper subprotocol
Les ## enable les subprotocol
2018-04-27 08:53:53 +00:00
RpcConfiguration * = object
## JSON-RPC configuration object
2018-06-20 17:27:32 +00:00
flags * : set [ RpcFlags ] ## RPC flags
binds * : seq [ TransportAddress ] ## RPC bind address
2018-04-27 08:53:53 +00:00
2018-08-01 12:50:44 +00:00
PublicNetwork * = enum
CustomNet = 0
MainNet = 1
MordenNet = 2
RopstenNet = 3
RinkebyNet = 4
KovanNet = 42
2018-04-27 08:53:53 +00:00
NetworkFlags * = enum
## Ethereum network flags
2018-06-20 17:27:32 +00:00
NoDiscover , ## Peer discovery disabled
V5Discover , ## Dicovery V5 enabled
2018-04-27 08:53:53 +00:00
DebugFlags * {. pure . } = enum
## Debug selection flags
2018-06-20 17:27:32 +00:00
Enabled , ## Debugging enabled
Test1 , ## Test1 enabled
Test2 , ## Test2 enabled
Test3 ## Test3 enabled
2018-04-27 08:53:53 +00:00
NetConfiguration * = object
## Network configuration object
2018-06-20 17:27:32 +00:00
flags * : set [ NetworkFlags ] ## Network flags
bootNodes * : seq [ ENode ] ## List of bootnodes
2019-04-23 13:49:49 +00:00
staticNodes * : seq [ ENode ] ## List of static nodes to connect to
2018-06-20 17:27:32 +00:00
bindPort * : uint16 ## Main TCP bind port
discPort * : uint16 ## Discovery UDP bind port
2019-07-16 10:43:05 +00:00
metricsServer * : bool ## Enable metrics server
metricsServerPort * : uint16 ## metrics HTTP server port
2018-06-20 17:27:32 +00:00
maxPeers * : int ## Maximum allowed number of peers
maxPendingPeers * : int ## Maximum allowed pending peers
2018-07-22 21:34:43 +00:00
networkId * : uint ## Network ID as integer
2018-06-20 17:27:32 +00:00
ident * : string ## Server ident name string
nodeKey * : PrivateKey ## Server private key
2019-04-17 01:56:28 +00:00
nat * : NatStrategy ## NAT strategy
externalIP * : string ## user-provided external IP
2019-04-23 13:49:49 +00:00
protocols * : set [ ProtocolFlags ] ## Enabled subprotocols
2018-04-27 08:53:53 +00:00
DebugConfiguration * = object
## Debug configuration object
2018-06-20 17:27:32 +00:00
flags * : set [ DebugFlags ] ## Debug flags
2019-03-20 13:41:25 +00:00
logLevel * : LogLevel ## Log level
logFile * : string ## Log file
2019-07-16 10:43:05 +00:00
logMetrics * : bool ## Enable metrics logging
logMetricsInterval * : int ## Metrics logging interval
2018-04-27 08:53:53 +00:00
2018-11-30 03:03:30 +00:00
PruneMode * {. pure . } = enum
Full
Archive
2018-08-01 12:50:44 +00:00
ChainConfig * = object
chainId * : uint
homesteadBlock * : BlockNumber
daoForkBlock * : BlockNumber
daoForkSupport * : bool
# EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
eip150Block * : BlockNumber
eip150Hash * : Hash256
eip155Block * : BlockNumber
eip158Block * : BlockNumber
byzantiumBlock * : BlockNumber
constantinopleBlock * : BlockNumber
2018-04-27 08:53:53 +00:00
NimbusConfiguration * = ref object
## Main Nimbus configuration object
2018-09-24 22:25:17 +00:00
dataDir * : string
keyFile * : string
2018-11-30 03:03:30 +00:00
prune * : PruneMode
2018-06-20 17:27:32 +00:00
rpc * : RpcConfiguration ## JSON-RPC configuration
net * : NetConfiguration ## Network configuration
debug * : DebugConfiguration ## Debug configuration
2019-04-23 13:49:49 +00:00
shh * : WhisperConfig ## Whisper configuration
2018-04-27 08:53:53 +00:00
2018-11-22 06:40:09 +00:00
const
defaultRpcApi = { RpcFlags . Eth , RpcFlags . Shh }
2019-04-23 13:49:49 +00:00
defaultProtocols = { ProtocolFlags . Eth , ProtocolFlags . Shh }
2019-03-20 13:41:25 +00:00
defaultLogLevel = LogLevel . WARN
2019-07-30 09:00:55 +00:00
defaultNetwork = MainNet
2018-11-22 06:40:09 +00:00
2018-04-27 08:53:53 +00:00
var nimbusConfig {. threadvar . } : NimbusConfiguration
2018-06-20 17:27:32 +00:00
proc getConfiguration * ( ) : NimbusConfiguration {. gcsafe . }
2018-04-27 08:53:53 +00:00
2018-08-01 12:50:44 +00:00
proc publicChainConfig * ( id : PublicNetwork ) : ChainConfig =
result = case id
of MainNet :
ChainConfig (
chainId : MainNet . uint ,
2018-11-28 19:02:21 +00:00
homesteadBlock : forkBlocks [ FkHomestead ] ,
daoForkBlock : forkBlocks [ FkDao ] ,
2018-08-01 12:50:44 +00:00
daoForkSupport : true ,
2018-11-28 19:02:21 +00:00
eip150Block : forkBlocks [ FkTangerine ] ,
2018-08-01 12:50:44 +00:00
eip150Hash : toDigest ( " 2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0 " ) ,
2018-11-28 19:02:21 +00:00
eip155Block : forkBlocks [ FkSpurious ] ,
eip158Block : forkBlocks [ FkSpurious ] ,
byzantiumBlock : forkBlocks [ FkByzantium ]
2018-08-01 12:50:44 +00:00
)
of RopstenNet :
ChainConfig (
chainId : RopstenNet . uint ,
2019-07-10 07:40:46 +00:00
homesteadBlock : 0 . toBlockNumber ,
2018-08-01 12:50:44 +00:00
daoForkSupport : true ,
2019-07-10 07:40:46 +00:00
eip150Block : 0 . toBlockNumber ,
2018-08-01 12:50:44 +00:00
eip150Hash : toDigest ( " 41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d " ) ,
2019-07-10 07:40:46 +00:00
eip155Block : 10 . toBlockNumber ,
eip158Block : 10 . toBlockNumber ,
byzantiumBlock : 1700000 . toBlockNumber
2018-08-01 12:50:44 +00:00
)
of RinkebyNet :
ChainConfig (
chainId : RinkebyNet . uint ,
2019-07-10 07:40:46 +00:00
homesteadBlock : 1 . toBlockNumber ,
2018-08-01 12:50:44 +00:00
daoForkSupport : true ,
2019-07-10 07:40:46 +00:00
eip150Block : 2 . toBlockNumber ,
2018-08-01 12:50:44 +00:00
eip150Hash : toDigest ( " 9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9 " ) ,
2019-07-10 07:40:46 +00:00
eip155Block : 3 . toBlockNumber ,
eip158Block : 3 . toBlockNumber ,
byzantiumBlock : 1035301 . toBlockNumber
2018-08-01 12:50:44 +00:00
)
else :
2018-08-03 11:10:07 +00:00
error " No chain config for public network " , networkId = id
doAssert ( false , " No chain config for " & $ id )
ChainConfig ( )
2018-08-01 12:50:44 +00:00
result . chainId = uint ( id )
2018-04-27 08:53:53 +00:00
proc processList ( v : string , o : var seq [ string ] ) =
2018-05-01 00:47:35 +00:00
## Process comma-separated list of strings.
2018-04-27 08:53:53 +00:00
if len ( v ) > 0 :
for n in v . split ( { ' ' , ' , ' } ) :
if len ( n ) > 0 :
o . add ( n )
2019-01-08 11:29:56 +00:00
proc processInteger * ( v : string , o : var int ) : ConfigStatus =
2018-05-01 00:47:35 +00:00
## Convert string to integer.
2018-04-27 08:53:53 +00:00
try :
o = parseInt ( v )
2018-04-30 07:24:51 +00:00
result = Success
except :
result = ErrorParseOption
2019-04-23 13:49:49 +00:00
proc processFloat * ( v : string , o : var float ) : ConfigStatus =
## Convert string to float.
try :
o = parseFloat ( v )
result = Success
except :
result = ErrorParseOption
2018-06-20 17:27:32 +00:00
proc processAddressPortsList ( v : string ,
o : var seq [ TransportAddress ] ) : ConfigStatus =
## Convert <hostname:port>;...;<hostname:port> to list of `TransportAddress`.
var list = newSeq [ string ] ( )
2018-05-01 00:47:35 +00:00
processList ( v , list )
for item in list :
2018-06-20 17:27:32 +00:00
var tas4 : seq [ TransportAddress ]
var tas6 : seq [ TransportAddress ]
try :
tas4 = resolveTAddress ( item , IpAddressFamily . IPv4 )
except :
discard
try :
tas6 = resolveTAddress ( item , IpAddressFamily . IPv6 )
except :
discard
if len ( tas4 ) = = 0 and len ( tas6 ) = = 0 :
result = ErrorParseOption
2018-05-01 00:47:35 +00:00
break
2018-06-20 17:27:32 +00:00
else :
for a in tas4 : o . add ( a )
for a in tas6 : o . add ( a )
result = Success
2018-05-01 00:47:35 +00:00
2018-11-22 06:40:09 +00:00
proc processRpcApiList ( v : string , flags : var set [ RpcFlags ] ) : ConfigStatus =
var list = newSeq [ string ] ( )
processList ( v , list )
result = Success
for item in list :
case item . toLowerAscii ( )
of " eth " : flags . incl RpcFlags . Eth
2018-11-28 02:25:36 +00:00
of " shh " : flags . incl RpcFlags . Shh
2018-11-22 06:40:09 +00:00
of " debug " : flags . incl RpcFlags . Debug
else :
warn " unknown rpc api " , name = item
result = ErrorIncorrectOption
2019-04-23 13:49:49 +00:00
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
2018-05-01 00:47:35 +00:00
proc processENode ( v : string , o : var ENode ) : ConfigStatus =
## Convert string to ENode.
let res = initENode ( v , o )
if res = = ENodeStatus . Success :
result = Success
else :
result = ErrorParseOption
proc processENodesList ( v : string , o : var seq [ ENode ] ) : ConfigStatus =
## Convert comma-separated list of strings to list of ENode.
var
node : ENode
list = newSeq [ string ] ( )
processList ( v , list )
for item in list :
result = processENode ( item , node )
if result = = Success :
o . add ( node )
else :
break
2018-04-30 07:24:51 +00:00
2018-05-02 15:01:10 +00:00
proc processPrivateKey ( v : string , o : var PrivateKey ) : ConfigStatus =
## Convert hexadecimal string to private key object.
try :
o = initPrivateKey ( v )
result = Success
except :
result = ErrorParseOption
# proc processHexBytes(v: string, o: var seq[byte]): ConfigStatus =
# ## Convert hexadecimal string to seq[byte].
# try:
# o = fromHex(v)
# result = Success
# except:
# result = ErrorParseOption
# proc processHexString(v: string, o: var string): ConfigStatus =
# ## Convert hexadecimal string to string.
# try:
# o = parseHexStr(v)
# result = Success
# except:
# result = ErrorParseOption
# proc processJson(v: string, o: var JsonNode): ConfigStatus =
# ## Convert string to JSON.
# try:
# o = parseJson(v)
# result = Success
# except:
# result = ErrorParseOption
2018-11-30 03:03:30 +00:00
proc processPruneList ( v : string , flags : var PruneMode ) : ConfigStatus =
var list = newSeq [ string ] ( )
processList ( v , list )
result = Success
for item in list :
case item . toLowerAscii ( )
of " full " : flags = PruneMode . Full
of " archive " : flags = PruneMode . Archive
else :
warn " unknown prune flags " , name = item
result = ErrorIncorrectOption
2018-09-24 22:25:17 +00:00
proc processEthArguments ( key , value : string ) : ConfigStatus =
result = Success
let config = getConfiguration ( )
case key . toLowerAscii ( )
of " keyfile " :
if fileExists ( value ) :
config . keyFile = value
else :
result = ErrorIncorrectOption
2018-12-28 08:24:57 +00:00
of " datadir " :
2018-09-24 22:25:17 +00:00
config . dataDir = value
2018-11-30 03:03:30 +00:00
of " prune " :
result = processPruneList ( value , config . prune )
2018-09-24 22:25:17 +00:00
else :
result = EmptyOption
2018-04-27 08:53:53 +00:00
proc processRpcArguments ( key , value : string ) : ConfigStatus =
## Processes only `RPC` related command line options
result = Success
let config = getConfiguration ( )
let skey = key . toLowerAscii ( )
if skey = = " rpc " :
2018-11-22 06:40:09 +00:00
if RpcFlags . Enabled notin config . rpc . flags :
config . rpc . flags . incl ( RpcFlags . Enabled )
config . rpc . flags . incl ( defaultRpcApi )
2018-04-27 08:53:53 +00:00
elif skey = = " rpcbind " :
2018-06-20 17:27:32 +00:00
config . rpc . binds . setLen ( 0 )
result = processAddressPortsList ( value , config . rpc . binds )
2018-11-22 06:40:09 +00:00
elif skey = = " rpcapi " :
if RpcFlags . Enabled in config . rpc . flags :
config . rpc . flags . excl ( defaultRpcApi )
else :
config . rpc . flags . incl ( RpcFlags . Enabled )
result = processRpcApiList ( value , config . rpc . flags )
2018-04-27 08:53:53 +00:00
else :
result = EmptyOption
2018-08-01 12:50:44 +00:00
proc setBootnodes ( onodes : var seq [ ENode ] , nodeUris : openarray [ string ] ) =
2018-06-20 17:27:32 +00:00
var node : ENode
2018-08-01 12:50:44 +00:00
onodes = newSeqOfCap [ ENode ] ( nodeUris . len )
for item in nodeUris :
2018-06-20 17:27:32 +00:00
doAssert ( processENode ( item , node ) = = Success )
2018-08-01 12:50:44 +00:00
onodes . add ( node )
2018-06-20 17:27:32 +00:00
2018-08-02 08:18:12 +00:00
macro availableEnumValues ( T : type enum ) : untyped =
let impl = getTypeImpl ( T ) [ 1 ] . getTypeImpl ( )
result = newNimNode ( nnkBracket )
for i in 1 .. < impl . len : result . add ( newCall ( " uint " , copyNimTree ( impl [ i ] ) ) )
2018-08-01 12:50:44 +00:00
proc toPublicNetwork * ( id : uint ) : PublicNetwork {. inline . } =
2018-08-02 08:18:12 +00:00
if id in availableEnumValues ( PublicNetwork ) :
result = PublicNetwork ( id )
2018-08-01 12:50:44 +00:00
proc setNetwork ( conf : var NetConfiguration , id : PublicNetwork ) =
2018-06-20 17:27:32 +00:00
## Set network id and default network bootnodes
2018-08-01 12:50:44 +00:00
conf . networkId = uint ( id )
case id
2018-06-20 17:27:32 +00:00
of MainNet :
conf . bootNodes . setBootnodes ( MainnetBootnodes )
of MordenNet :
2018-08-01 12:50:44 +00:00
discard
2018-06-20 17:27:32 +00:00
of RopstenNet :
conf . bootNodes . setBootnodes ( RopstenBootnodes )
of RinkebyNet :
conf . bootNodes . setBootnodes ( RinkebyBootnodes )
of KovanNet :
conf . bootNodes . setBootnodes ( KovanBootnodes )
of CustomNet :
2018-08-01 12:50:44 +00:00
discard
proc setNetwork ( conf : var NetConfiguration , id : uint ) =
## Set network id and default network bootnodes
let pubNet = toPublicNetwork ( id )
if pubNet = = CustomNet :
2018-06-20 17:27:32 +00:00
conf . networkId = id
else :
2018-08-01 12:50:44 +00:00
conf . setNetwork ( pubNet )
2018-06-20 17:27:32 +00:00
2018-04-27 08:53:53 +00:00
proc processNetArguments ( key , value : string ) : ConfigStatus =
## Processes only `Networking` related command line options
result = Success
let config = getConfiguration ( )
let skey = key . toLowerAscii ( )
if skey = = " bootnodes " :
2018-09-25 13:30:44 +00:00
result = processENodesList ( value , config . net . bootNodes )
2018-04-27 08:53:53 +00:00
elif skey = = " bootnodesv4 " :
2018-06-20 17:27:32 +00:00
result = processENodesList ( value , config . net . bootNodes )
2018-04-27 08:53:53 +00:00
elif skey = = " bootnodesv5 " :
2018-06-20 17:27:32 +00:00
result = processENodesList ( value , config . net . bootNodes )
2019-04-23 13:49:49 +00:00
elif skey = = " staticnodes " :
result = processENodesList ( value , config . net . staticNodes )
2018-04-27 08:53:53 +00:00
elif skey = = " testnet " :
2018-06-20 17:27:32 +00:00
config . net . setNetwork ( RopstenNet )
2018-04-27 08:53:53 +00:00
elif skey = = " mainnet " :
2018-06-20 17:27:32 +00:00
config . net . setNetwork ( MainNet )
elif skey = = " ropsten " :
config . net . setNetwork ( RopstenNet )
elif skey = = " rinkeby " :
config . net . setNetwork ( RinkebyNet )
elif skey = = " kovan " :
config . net . setNetwork ( KovanNet )
elif skey = = " networkid " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
2018-08-01 12:50:44 +00:00
config . net . setNetwork ( uint ( result ) )
2018-04-27 08:53:53 +00:00
elif skey = = " nodiscover " :
config . net . flags . incl ( NoDiscover )
elif skey = = " v5discover " :
config . net . flags . incl ( V5Discover )
2018-06-20 17:27:32 +00:00
config . net . bootNodes . setBootnodes ( DiscoveryV5Bootnodes )
2018-04-27 08:53:53 +00:00
elif skey = = " port " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
config . net . bindPort = uint16 ( res and 0xFFFF )
2018-05-02 15:01:10 +00:00
elif skey = = " discport " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
config . net . discPort = uint16 ( res and 0xFFFF )
2019-07-17 22:50:16 +00:00
elif skey = = " metricsserver " and defined ( insecure ) :
2019-07-16 10:43:05 +00:00
config . net . metricsServer = true
2019-07-17 22:50:16 +00:00
elif skey = = " metricsserverport " and defined ( insecure ) :
2019-07-11 23:38:32 +00:00
var res = 0
result = processInteger ( value , res )
if result = = Success :
2019-07-16 10:43:05 +00:00
config . net . metricsServerPort = uint16 ( res and 0xFFFF )
2018-04-27 08:53:53 +00:00
elif skey = = " maxpeers " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
config . net . maxPeers = res
elif skey = = " maxpendpeers " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
config . net . maxPendingPeers = res
2018-05-02 15:01:10 +00:00
elif skey = = " nodekey " :
var res : PrivateKey
result = processPrivateKey ( value , res )
if result = = Success :
config . net . nodeKey = res
2018-06-20 17:27:32 +00:00
elif skey = = " ident " :
config . net . ident = value
2019-04-17 01:56:28 +00:00
elif skey = = " nat " :
case value . toLowerAscii :
of " any " :
config . net . nat = NatAny
of " upnp " :
config . net . nat = NatUpnp
of " pmp " :
config . net . nat = NatPmp
of " none " :
config . net . nat = NatNone
else :
if isIpAddress ( value ) :
config . net . externalIP = value
config . net . nat = NatNone
else :
error " not a valid NAT mechanism, nor a valid IP address " , value
result = ErrorParseOption
2019-04-23 13:49:49 +00:00
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
2018-04-27 08:53:53 +00:00
else :
result = EmptyOption
proc processDebugArguments ( key , value : string ) : ConfigStatus =
## Processes only `Debug` related command line options
let config = getConfiguration ( )
result = Success
let skey = key . toLowerAscii ( )
if skey = = " debug " :
config . debug . flags . incl ( DebugFlags . Enabled )
elif skey = = " test " :
var res = newSeq [ string ] ( )
processList ( value , res )
for item in res :
if item = = " test1 " :
config . debug . flags . incl ( DebugFlags . Test1 )
elif item = = " test2 " :
config . debug . flags . incl ( DebugFlags . Test2 )
elif item = = " test3 " :
config . debug . flags . incl ( DebugFlags . Test3 )
2019-03-20 13:41:25 +00:00
elif skey = = " log-level " :
try :
let logLevel = parseEnum [ LogLevel ] ( value )
if logLevel > = enabledLogLevel :
config . debug . logLevel = logLevel
else :
result = ErrorIncorrectOption
except ValueError :
result = ErrorIncorrectOption
elif skey = = " log-file " :
if len ( value ) = = 0 :
result = ErrorIncorrectOption
else :
config . debug . logFile = value
2019-07-16 10:43:05 +00:00
elif skey = = " logmetrics " :
config . debug . logMetrics = true
elif skey = = " logmetricsinterval " :
var res = 0
result = processInteger ( value , res )
if result = = Success :
config . debug . logMetricsInterval = res
2019-07-17 22:50:16 +00:00
else :
result = EmptyOption
2018-04-27 08:53:53 +00:00
proc dumpConfiguration * ( ) : string =
## Dumps current configuration as string
let config = getConfiguration ( )
result = repr config
2019-03-20 13:41:25 +00:00
template processArgument ( processor , key , value , msg : untyped ) =
2018-06-20 17:27:32 +00:00
## Checks if arguments got processed successfully
2019-03-20 13:41:25 +00:00
var res = processor ( string ( key ) , string ( value ) )
2018-04-27 08:53:53 +00:00
if res = = Success :
2019-03-20 13:41:25 +00:00
result = res
2018-04-27 08:53:53 +00:00
continue
elif res = = ErrorParseOption :
2019-03-20 13:41:25 +00:00
msg = " Error processing option ' " & key & " ' with value ' " & value & " ' . "
2018-04-27 08:53:53 +00:00
result = res
break
2018-06-20 17:27:32 +00:00
elif res = = ErrorIncorrectOption :
2019-03-20 13:41:25 +00:00
msg = " Incorrect value for option ' " & key & " ' : ' " & value & " ' . "
2018-06-20 17:27:32 +00:00
result = res
break
2019-01-08 11:29:56 +00:00
proc getDefaultDataDir * ( ) : string =
when defined ( windows ) :
" AppData " / " Roaming " / " Nimbus " / " DB "
elif defined ( macosx ) :
" Library " / " Application Support " / " Nimbus " / " DB "
else :
" .cache " / " nimbus " / " db "
2018-06-20 17:27:32 +00:00
proc initConfiguration ( ) : NimbusConfiguration =
## Allocates and initializes `NimbusConfiguration` with default values
result = new NimbusConfiguration
## RPC defaults
result . rpc . flags = { }
result . rpc . binds = @ [ initTAddress ( " 127.0.0.1:8545 " ) ]
## Network defaults
2019-07-30 09:00:55 +00:00
result . net . setNetwork ( defaultNetwork )
2018-06-20 17:27:32 +00:00
result . net . maxPeers = 25
result . net . maxPendingPeers = 0
result . net . bindPort = 30303 'u 16
result . net . discPort = 30303 'u 16
2019-07-16 10:43:05 +00:00
result . net . metricsServer = false
result . net . metricsServerPort = 9093 'u 16
2019-01-15 15:25:14 +00:00
result . net . ident = NimbusIdent
2019-04-17 01:56:28 +00:00
result . net . nat = NatAny
2019-04-23 13:49:49 +00:00
result . net . protocols = defaultProtocols
2018-04-27 08:53:53 +00:00
2019-01-08 11:29:56 +00:00
const dataDir = getDefaultDataDir ( )
2018-09-24 22:25:17 +00:00
result . dataDir = getHomeDir ( ) / dataDir
2018-11-30 03:03:30 +00:00
result . prune = PruneMode . Full
2018-09-24 22:25:17 +00:00
2019-04-23 13:49:49 +00:00
## Whisper defaults
result . shh . maxMsgSize = defaultMaxMsgSize
result . shh . powRequirement = defaultMinPow
result . shh . isLightNode = false
result . shh . bloom = fullBloom ( )
2018-06-20 17:27:32 +00:00
## Debug defaults
result . debug . flags = { }
2019-03-20 13:41:25 +00:00
result . debug . logLevel = defaultLogLevel
2019-07-16 10:43:05 +00:00
result . debug . logMetrics = false
result . debug . logMetricsInterval = 10
2018-06-20 17:27:32 +00:00
proc getConfiguration * ( ) : NimbusConfiguration =
## Retreive current configuration object `NimbusConfiguration`.
if isNil ( nimbusConfig ) :
nimbusConfig = initConfiguration ( )
result = nimbusConfig
2018-04-27 08:53:53 +00:00
proc getHelpString * ( ) : string =
2019-03-20 13:41:25 +00:00
var logLevels : seq [ string ]
for level in LogLevel :
if level < enabledLogLevel :
continue
logLevels . add ( $ level )
2019-07-17 22:50:16 +00:00
when defined ( insecure ) :
let metricsServerHelp = """
- - metricsServer Enable the metrics HTTP server
- - metricsServerPort : < value > Metrics HTTP server port on localhost ( default : 9093 ) """
else :
let metricsServerHelp = " "
2018-06-20 17:27:32 +00:00
result = """
2018-04-27 08:53:53 +00:00
USAGE :
nimbus [ options ]
2018-05-02 15:01:10 +00:00
ETHEREUM OPTIONS :
- - keyfile : < value > Use keyfile storage file
2018-09-24 22:25:17 +00:00
- - datadir : < value > Base directory for all blockchain - related data
2018-11-30 03:03:30 +00:00
- - prune : < value > Blockchain prune mode ( full or archive )
2018-05-02 15:01:10 +00:00
2018-04-27 08:53:53 +00:00
NETWORKING OPTIONS :
- - 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 )
2018-09-24 22:25:17 +00:00
- - bootnodesv5 : < value > Comma separated enode URLs for P2P v5 discovery bootstrap ( light server , light nodes )
2019-04-23 13:49:49 +00:00
- - staticnodes : < value > Comma separated enode URLs to connect with
2018-05-02 15:01:10 +00:00
- - port : < value > Network listening TCP port ( default : 30303 )
2019-07-17 22:50:16 +00:00
- - discport : < value > Network listening UDP port ( defaults to - - port argument ) $ 7
2018-04-27 08:53:53 +00:00
- - maxpeers : < value > Maximum number of network peers ( default : 25 )
- - maxpendpeers : < value > Maximum number of pending connection attempts ( default : 0 )
2019-04-17 01:56:28 +00:00
- - nat : < value > NAT port mapping mechanism ( any | none | upnp | pmp | < external IP > ) ( default : " any " )
2018-04-27 08:53:53 +00:00
- - nodiscover Disables the peer discovery mechanism ( manual peer addition )
- - v5discover Enables the experimental RLPx V5 ( Topic Discovery ) mechanism
2018-05-02 15:01:10 +00:00
- - nodekey : < value > P2P node private key ( as hexadecimal string )
2019-07-30 09:00:55 +00:00
- - networkid : < value > Network identifier ( integer , 1 = Frontier , 2 = Morden ( disused ) , 3 = Ropsten , 4 = Rinkeby ) ( default : $ 8 )
- - testnet Use Ethereum Default Test Network ( Ropsten )
- - ropsten Use Ethereum Ropsten Test Network
2018-06-20 17:27:32 +00:00
- - rinkeby Use Ethereum Rinkeby Test Network
- - ident : < value > Client identifier ( default is ' $ 1 ' )
2019-04-23 13:49:49 +00:00
- - 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 )
2018-05-02 15:01:10 +00:00
2018-04-27 08:53:53 +00:00
API AND CONSOLE OPTIONS :
- - rpc Enable the HTTP - RPC server
2018-06-20 17:27:32 +00:00
- - rpcbind : < value > HTTP - RPC server will bind to given comma separated address : port pairs ( default : 127 .0 .0 .1 : 8545 )
2018-11-28 02:25:36 +00:00
- - rpcapi : < value > Enable specific set of rpc api from comma separated list ( eth , shh , debug )
2018-04-27 08:53:53 +00:00
LOGGING AND DEBUGGING OPTIONS :
2019-03-20 13:41:25 +00:00
- - log - level : < value > One of : $ 2 ( default : $ 3 )
- - log - file : < value > Optional log file , replacing stdout
2019-07-16 10:43:05 +00:00
- - logMetrics Enable metrics logging
- - logMetricsInterval : < value > Interval at which to log metrics , in seconds ( default : 10 )
2018-04-27 08:53:53 +00:00
- - debug Enable debug mode
- - test : < value > Perform specified test
2018-06-20 17:27:32 +00:00
""" % [
2019-03-20 13:41:25 +00:00
NimbusIdent ,
join ( logLevels , " , " ) ,
2019-04-23 13:49:49 +00:00
$ defaultLogLevel ,
strip ( $ defaultProtocols , chars = { ' { ' , ' } ' } ) ,
$ defaultMaxMsgSize ,
2019-07-17 22:50:16 +00:00
$ defaultMinPow ,
metricsServerHelp ,
2019-07-30 09:00:55 +00:00
$ ord ( defaultNetwork )
2018-06-20 17:27:32 +00:00
]
2018-04-27 08:53:53 +00:00
2019-07-31 11:54:48 +00:00
when declared ( os . paramCount ) : # not available with `--app:lib`
proc processArguments * ( msg : var string ) : ConfigStatus =
## Process command line argument and update `NimbusConfiguration`.
let config = getConfiguration ( )
# At this point `config.net.bootnodes` is likely populated with network default
# bootnodes. We want to override those if at least one custom bootnode is
# specified on the command line. We temporarily set `config.net.bootNodes`
# to empty seq, and in the end restore it if no bootnodes were spricified on
# the command line.
# TODO: This is pretty hacky and it's better to refactor it to make a clear
# distinction between default and custom bootnodes.
var tempBootNodes : seq [ ENode ]
2018-09-25 13:30:44 +00:00
swap ( tempBootNodes , config . net . bootNodes )
2019-07-31 11:54:48 +00:00
# The same trick is done to discPort
config . net . discPort = 0
var opt = initOptParser ( )
var length = 0
for kind , key , value in opt . getopt ( ) :
result = Error
case kind
of cmdArgument :
discard
of cmdLongOption , cmdShortOption :
inc ( length )
case key . toLowerAscii ( )
of " help " , " h " :
msg = getHelpString ( )
result = Success
break
of " version " , " ver " , " v " :
msg = NimbusVersion
result = Success
break
else :
processArgument processEthArguments , key , value , msg
processArgument processRpcArguments , key , value , msg
processArgument processNetArguments , key , value , msg
processArgument processShhArguments , key , value , msg
processArgument processDebugArguments , key , value , msg
if result ! = Success :
msg = " Unknown option: ' " & key & " ' . "
break
of cmdEnd :
doAssert ( false ) # we're never getting this kind here
if config . net . bootNodes . len = = 0 :
# No custom bootnodes were specified on the command line, restore to
# previous values
swap ( tempBootNodes , config . net . bootNodes )
if config . net . discPort = = 0 :
config . net . discPort = config . net . bindPort
2018-04-27 08:53:53 +00:00
2019-03-20 13:41:25 +00:00
proc processConfiguration * ( pathname : string ) : ConfigStatus =
2018-04-27 08:53:53 +00:00
## Process configuration file `pathname` and update `NimbusConfiguration`.
result = Success
2019-03-20 13:41:25 +00:00