config: fix new config based on input from jamie and zahary

This commit is contained in:
jangko 2021-09-16 22:59:46 +07:00
parent 69f2a0f95a
commit a3badea928
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
22 changed files with 723 additions and 502 deletions

View File

@ -16,8 +16,8 @@ import
proc genesisToTrie(filePath: string): HexaryTrie =
# TODO: Doing our best here with API that exists, to be improved.
var cn: CustomNetwork
if not loadCustomNetwork(filePath, cn):
var cn: NetworkParams
if not loadNetworkParams(filePath, cn):
quit(1)
var chainDB = newBaseChainDB(

View File

@ -21,8 +21,8 @@ proc processNode(genesisFile, chainFile,
conf = makeConfig(@["--customnetwork:" & genesisFile])
chainDB = newBaseChainDB(newMemoryDb(),
pruneTrie = false,
conf.networkId.get,
conf.customNetwork.get()
conf.networkId,
conf.networkParams
)
initializeEmptyDb(chainDB)

View File

@ -67,13 +67,13 @@ proc processNode(ctx: GraphqlRef, node: JsonNode, fileName: string, testStatusIM
proc main() =
let
conf = makeConfig(@["--customnetwork:" & genesisFile])
conf = makeConfig(@["--custom-network:" & genesisFile])
ethCtx = newEthContext()
ethNode = setupEthNode(conf, ethCtx, eth)
chainDB = newBaseChainDB(newMemoryDb(),
pruneTrie = false,
conf.networkId.get,
conf.customNetwork.get
conf.networkId,
conf.networkParams
)
initializeEmptyDb(chainDB)

View File

@ -15,7 +15,7 @@ import
json_serialization/std/options as jsoptions,
json_serialization/std/tables as jstable,
json_serialization/lexer,
./forks
"."/[forks, genesis_alloc]
type
CliqueOptions = object
@ -83,7 +83,7 @@ type
balance*: UInt256
nonce* : AccountNonce
CustomNetwork* = object
NetworkParams* = object
config* : ChainConfig
genesis*: Genesis
@ -159,19 +159,19 @@ template to(a: string, b: type UInt256): UInt256 =
# json_serialization decode table stuff
UInt256.fromHex(a)
proc loadCustomNetwork*(fileName: string, cg: var CustomNetwork): bool =
proc loadNetworkParams*(fileName: string, cg: var NetworkParams): bool =
var cc: CustomChain
try:
cc = Json.loadFile(fileName, CustomChain, allowUnknownFields = true)
except IOError as e:
error "Genesis config file error", fileName, msg=e.msg
error "Network params I/O error", fileName, msg=e.msg
return false
except JsonReaderError as e:
error "Invalid genesis config file format", fileName, msg=e.formatMsg("")
error "Invalid network params file format", fileName, msg=e.formatMsg("")
return false
except:
var msg = getCurrentExceptionMsg()
error "Error loading genesis block config file", fileName, msg
error "Error loading network params file", fileName, msg
return false
cg.genesis = cc.genesis
@ -237,14 +237,14 @@ proc toFork*(c: ChainConfig, number: BlockNumber): Fork =
elif number >= c.homesteadBlock: FkHomestead
else: FkFrontier
proc chainConfig*(id: NetworkId, cn: CustomNetwork): ChainConfig =
proc chainConfigForNetwork(id: NetworkId): ChainConfig =
# For some public networks, NetworkId and ChainId value are identical
# but that is not always the case
result = case id
of MainNet:
ChainConfig(
poaEngine: false, # TODO: use real engine conf: PoW
poaEngine: false,
chainId: MainNet.ChainId,
homesteadBlock: 1_150_000.toBlockNumber, # 14/03/2016 20:49:53
daoForkBlock: 1_920_000.toBlockNumber,
@ -263,7 +263,7 @@ proc chainConfig*(id: NetworkId, cn: CustomNetwork): ChainConfig =
)
of RopstenNet:
ChainConfig(
poaEngine: false, # TODO: use real engine conf: PoW
poaEngine: false,
chainId: RopstenNet.ChainId,
homesteadBlock: 0.toBlockNumber,
daoForkSupport: false,
@ -281,7 +281,7 @@ proc chainConfig*(id: NetworkId, cn: CustomNetwork): ChainConfig =
)
of RinkebyNet:
ChainConfig(
poaEngine: true, # TODO: use real engine conf: PoA
poaEngine: true,
chainId: RinkebyNet.ChainId,
homesteadBlock: 1.toBlockNumber,
daoForkSupport: false,
@ -299,7 +299,7 @@ proc chainConfig*(id: NetworkId, cn: CustomNetwork): ChainConfig =
)
of GoerliNet:
ChainConfig(
poaEngine: true, # TODO: use real engine conf: PoA
poaEngine: true,
chainId: GoerliNet.ChainId,
homesteadBlock: 0.toBlockNumber,
daoForkSupport: false,
@ -316,6 +316,47 @@ proc chainConfig*(id: NetworkId, cn: CustomNetwork): ChainConfig =
londonBlock: 5_062_605.toBlockNumber # June 30, 2021
)
else:
# everything else will use CustomNet config
trace "Custom genesis block configuration loaded", conf=cn.config
cn.config
ChainConfig()
proc genesisBlockForNetwork(id: NetworkId): Genesis =
result = case id
of MainNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
gasLimit: 5000,
difficulty: 17179869184.u256,
alloc: decodePrealloc(mainnetAllocData)
)
of RopstenNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x3535353535353535353535353535353535353535353535353535353535353535"),
gasLimit: 16777216,
difficulty: 1048576.u256,
alloc: decodePrealloc(testnetAllocData)
)
of RinkebyNet:
Genesis(
nonce: 0.toBlockNonce,
timestamp: initTime(0x58ee40ba, 0),
extraData: hexToSeqByte("0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
gasLimit: 4700000,
difficulty: 1.u256,
alloc: decodePrealloc(rinkebyAllocData)
)
of GoerliNet:
Genesis(
nonce: 0.toBlockNonce,
timestamp: initTime(0x5c51a607, 0),
extraData: hexToSeqByte("0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
gasLimit: 0xa00000,
difficulty: 1.u256,
alloc: decodePrealloc(goerliAllocData)
)
else:
Genesis()
proc networkParams*(id: NetworkId): NetworkParams =
result.genesis = genesisBlockForNetwork(id)
result.config = chainConfigForNetwork(id)

View File

@ -1,5 +1,5 @@
# Nimbus
# Copyright (c) 2021 Status Research & Development GmbH
# Copyright (c) 2018-2021 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
@ -10,6 +10,7 @@
import
std/[options, strutils, times, os],
pkg/[
chronicles,
confutils,
confutils/defs,
stew/byteutils,
@ -21,6 +22,8 @@ import
constants, vm_compile_info
]
export stewNet
const
NimbusName* = "nimbus-eth1"
## project name string
@ -41,6 +44,8 @@ const
NimVersion = staticExec("nim --version").strip()
# TODO: fix this agent-string format to match other
# eth clients format
NimbusIdent* = "$# v$# [$#: $#, $#, $#, $#]" % [
NimbusName,
NimbusVersion,
@ -99,8 +104,8 @@ const
defaultEthGraphqlPort = 8547
defaultListenAddress = (static ValidIpAddress.init("0.0.0.0"))
defaultAdminListenAddress = (static ValidIpAddress.init("127.0.0.1"))
defaultListenAddressDesc = $defaultListenAddress
defaultAdminListenAddressDesc = $defaultAdminListenAddress
defaultListenAddressDesc = $defaultListenAddress & ", meaning all network interfaces"
defaultAdminListenAddressDesc = $defaultAdminListenAddress & ", meaning local host only"
logLevelDesc = getLogLevels()
type
@ -108,8 +113,9 @@ type
Full
Archive
NimbusCmd* = enum
NimbusCmd* {.pure.} = enum
noCommand
`import`
ProtocolFlag* {.pure.} = enum
## Protocol flags
@ -121,14 +127,10 @@ type
Eth ## enable eth_ set of RPC API
Debug ## enable debug_ set of RPC API
EnodeList* = object
value*: seq[Enode]
Protocols* = object
value*: set[ProtocolFlag]
RpcApi* = object
value*: set[RpcFlag]
DiscoveryType* {.pure.} = enum
None
V4
V5
NimbusConf* = object of RootObj
## Main Nimbus configuration object
@ -142,7 +144,7 @@ type
name: "data-dir" }: OutDir
keyStore* {.
desc: "Directory for the keystore files"
desc: "Load one or more keystore files from this directory"
defaultValue: defaultKeystoreDir()
defaultValueDesc: "inside datadir"
abbr: "k"
@ -155,20 +157,15 @@ type
abbr : "p"
name: "prune-mode" }: PruneMode
importBlocks* {.
desc: "Import RLP encoded block(s) in a file, validate, write to database and quit"
defaultValue: ""
abbr: "b"
name: "import-blocks" }: InputFile
importKey* {.
desc: "Import unencrypted 32 bytes hex private key file"
desc: "Import unencrypted 32 bytes hex private key from a file"
defaultValue: ""
abbr: "e"
name: "import-key" }: InputFile
engineSigner* {.
desc: "Enable sealing engine to run and producing blocks at specified interval (only PoA/Clique supported)"
desc: "Set the signer address(as 20 bytes hex) and enable sealing engine to run and " &
"producing blocks at specified interval (only PoA/Clique supported)"
defaultValue: ZERO_ADDRESS
defaultValueDesc: ""
abbr: "s"
@ -179,182 +176,164 @@ type
defaultValueDesc: ""
name: "verify-from" }: Option[uint64]
network {.
separator: "\pETHEREUM NETWORK OPTIONS:"
desc: "Name or id number of Ethereum network(mainnet(1), ropsten(3), rinkeby(4), goerli(5), kovan(42), other=custom)"
#[longDesc:
"- mainnet: Ethereum main network\n" &
"- ropsten: Test network (proof-of-work, the one most like Ethereum mainnet)\n" &
"- rinkeby: Test network (proof-of-authority, for those running Geth clients)\n" &
"- görli : Test network (proof-of-authority, works across all clients)\n" &
"- kovan : Test network (proof-of-authority, for those running OpenEthereum clients)"]#
defaultValue: "" # the default value is set in makeConfig
defaultValueDesc: "mainnet(1)"
abbr: "i"
name: "network" }: string
customNetwork {.
desc: "Use custom genesis block for private Ethereum Network (as /path/to/genesis.json)"
defaultValueDesc: ""
abbr: "c"
name: "custom-network" }: Option[NetworkParams]
networkId* {.
hidden # TODO: use ignore from confutils if its become available
defaultValue: MainNet
name: "network-id"}: NetworkId
networkParams* {.
hidden # TODO: use ignore from confutils if its become available
defaultValue: NetworkParams()
name: "network-params"}: NetworkParams
logLevel* {.
separator: "\pLOGGING AND DEBUGGING OPTIONS:"
desc: "Sets the log level for process and topics (" & logLevelDesc & ")"
defaultValue: LogLevel.INFO
defaultValueDesc: $LogLevel.INFO
name: "log-level" }: LogLevel
logFile* {.
desc: "Specifies a path for the written Json log file"
name: "log-file" }: Option[OutFile]
logMetricsEnabled* {.
desc: "Enable metrics logging"
defaultValue: false
name: "log-metrics" .}: bool
logMetricsInterval* {.
desc: "Interval at which to log metrics, in seconds"
defaultValue: 10
name: "log-metrics-interval" .}: int
bootstrapNodes {.
separator: "\pNETWORKING OPTIONS:"
desc: "Specifies one or more bootstrap nodes(as enode URL) to use when connecting to the network"
defaultValue: @[]
defaultValueDesc: ""
abbr: "b"
name: "bootstrap-node" }: seq[string]
bootstrapFile {.
desc: "Specifies a line-delimited file of bootstrap Ethereum network addresses(enode URL). " &
"By default, addresses will be added to bootstrap node list. " &
"But if the first line equals to `override` word, it will override built-in list"
defaultValue: ""
name: "bootstrap-file" }: InputFile
staticPeers {.
desc: "Connect to one or more trusted peers(as enode URL)"
defaultValue: @[]
defaultValueDesc: ""
name: "static-peers" }: seq[string]
listenAddress* {.
desc: "Listening IP address for Ethereum P2P and Discovery traffic"
defaultValue: defaultListenAddress
defaultValueDesc: $defaultListenAddressDesc
name: "listen-address" }: ValidIpAddress
tcpPort* {.
desc: "Ethereum P2P network listening TCP port"
defaultValue: defaultPort
defaultValueDesc: $defaultPort
name: "tcp-port" }: Port
udpPort* {.
desc: "Ethereum P2P network listening UDP port"
defaultValue: 0 # set udpPort defaultValue in `makeConfig`
defaultValueDesc: "default to --tcp-port"
name: "udp-port" }: Port
maxPeers* {.
desc: "Maximum number of peers to connect to"
defaultValue: 25
name: "max-peers" }: int
nat* {.
desc: "Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>"
defaultValue: NatConfig(hasExtIp: false, nat: NatAny)
defaultValueDesc: "any"
name: "nat" .}: NatConfig
discovery* {.
desc: "Specify method to find suitable peer in an Ethereum network (None, V4, V5)"
#[longDesc:
"- None: Disables the peer discovery mechanism (manual peer addition)\n" &
"- V4 : Node Discovery Protocol v4(default)\n" &
"- V5 : Node Discovery Protocol v5"]#
defaultValue: DiscoveryType.V4
defaultValueDesc: $DiscoveryType.V4
name: "discovery" .}: DiscoveryType
nodeKeyHex* {.
desc: "P2P node private key (as 32 bytes hex string)"
defaultValue: ""
defaultValueDesc: "random"
name: "node-key" .}: string
agentString* {.
desc: "Node agent string which is used as identifier in network"
defaultValue: NimbusIdent
defaultValueDesc: $NimbusIdent
name: "agent-string" .}: string
protocols {.
desc: "Enable specific set of protocols (available: Eth, Les)"
defaultValue: @[]
defaultValueDesc: $ProtocolFlag.Eth
name: "protocols" .}: seq[string]
case cmd* {.
command
defaultValue: noCommand }: NimbusCmd
defaultValue: NimbusCmd.noCommand }: NimbusCmd
of noCommand:
mainnet* {.
separator: "\pETHEREUM NETWORK OPTIONS:"
defaultValue: false
defaultValueDesc: ""
desc: "Use Ethereum main network (default)"
}: bool
ropsten* {.
desc: "Use Ropsten test network (proof-of-work, the one most like Ethereum mainnet)"
defaultValue: false
defaultValueDesc: ""
}: bool
rinkeby* {.
desc: "Use Rinkeby test network (proof-of-authority, for those running Geth clients)"
defaultValue: false
defaultValueDesc: ""
}: bool
goerli* {.
desc: "Use Görli test network (proof-of-authority, works across all clients)"
defaultValue: false
defaultValueDesc: ""
}: bool
kovan* {.
desc: "Use Kovan test network (proof-of-authority, for those running OpenEthereum clients)"
defaultValue: false
defaultValueDesc: ""
}: bool
networkId* {.
desc: "Network id (1=mainnet, 3=ropsten, 4=rinkeby, 5=goerli, 42=kovan, other=custom)"
defaultValueDesc: "mainnet"
abbr: "i"
name: "network-id" }: Option[NetworkId]
customNetwork* {.
desc: "Use custom genesis block for private Ethereum Network (as /path/to/genesis.json)"
defaultValueDesc: ""
abbr: "c"
name: "custom-network" }: Option[CustomNetwork]
bootNodes* {.
separator: "\pNETWORKING OPTIONS:"
desc: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)"
defaultValue: EnodeList()
defaultValueDesc: ""
name: "boot-nodes" }: EnodeList
bootNodesv4* {.
desc: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)"
defaultValue: EnodeList()
defaultValueDesc: ""
name: "boot-nodes-v4" }: EnodeList
bootNodesv5* {.
desc: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)"
defaultValue: EnodeList()
defaultValueDesc: ""
name: "boot-nodes-v5" }: EnodeList
staticNodes* {.
desc: "Comma separated enode URLs to connect with"
defaultValue: EnodeList()
defaultValueDesc: ""
name: "static-nodes" }: EnodeList
listenAddress* {.
desc: "Listening address for the Ethereum P2P and Discovery traffic"
defaultValue: defaultListenAddress
defaultValueDesc: $defaultListenAddressDesc
name: "listen-address" }: ValidIpAddress
tcpPort* {.
desc: "Network listening TCP port"
defaultValue: defaultPort
defaultValueDesc: $defaultPort
name: "tcp-port" }: Port
udpPort* {.
desc: "Network listening UDP port"
defaultValue: 0 # set udpPort defaultValue in `makeConfig`
defaultValueDesc: "default to --tcp-port"
name: "udp-port" }: Port
maxPeers* {.
desc: "The maximum number of peers to connect to"
defaultValue: 25
name: "max-peers" }: int
maxEndPeers* {.
desc: "Maximum number of pending connection attempts"
defaultValue: 0
name: "max-end-peers" }: int
nat* {.
desc: "Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>"
defaultValue: NatConfig(hasExtIp: false, nat: NatAny)
defaultValueDesc: "any"
name: "nat" .}: NatConfig
noDiscover* {.
desc: "Disables the peer discovery mechanism (manual peer addition)"
defaultValue: false
name: "no-discover" .}: bool
discv5Enabled* {.
desc: "Enable Discovery v5"
defaultValue: false
name: "discv5" .}: bool
nodeKeyHex* {.
desc: "P2P node private key (as hexadecimal string)"
defaultValue: ""
defaultValueDesc: "random"
name: "node-key" .}: string
agentString* {.
desc: "Node agent string which is used as identifier in network"
defaultValue: NimbusIdent
defaultValueDesc: $NimbusIdent
name: "agent-string" .}: string
protocols* {.
desc: "Enable specific set of protocols (Eth, Les)"
defaultValue: Protocols(value: {ProtocolFlag.Eth})
defaultValueDesc: $ProtocolFlag.Eth
name: "protocols" .}: Protocols
metricsEnabled* {.
separator: "\pLOCAL SERVICE OPTIONS:"
desc: "Enable the metrics server"
defaultValue: false
name: "metrics" }: bool
metricsPort* {.
desc: "Listening HTTP port of the metrics server"
defaultValue: defaultMetricsServerPort
defaultValueDesc: $defaultMetricsServerPort
name: "metrics-port" }: Port
metricsAddress* {.
desc: "Listening address of the metrics server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "metrics-address" }: ValidIpAddress
rpcEnabled* {.
separator: "\pLOCAL SERVICE OPTIONS:"
desc: "Enable the JSON-RPC server"
defaultValue: false
name: "rpc" }: bool
rpcPort* {.
desc: "Listening HTTP port for the JSON-RPC server"
desc: "Listening port of the JSON-RPC server"
defaultValue: defaultEthRpcPort
defaultValueDesc: $defaultEthRpcPort
name: "rpc-port" }: Port
rpcAddress* {.
desc: "Listening address of the RPC server"
desc: "Listening IP address of the JSON-RPC server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "rpc-address" }: ValidIpAddress
rpcApi* {.
desc: "Enable specific set of RPC API from list (comma-separated) (available: eth, debug)"
defaultValue: RpcApi(value: {RpcFlag.Eth})
rpcApi {.
desc: "Enable specific set of RPC API (available: eth, debug)"
defaultValue: @[]
defaultValueDesc: $RpcFlag.Eth
name: "rpc-api" }: RpcApi
name: "rpc-api" }: seq[string]
wsEnabled* {.
desc: "Enable the Websocket JSON-RPC server"
@ -362,60 +341,65 @@ type
name: "ws" }: bool
wsPort* {.
desc: "Listening Websocket port for the JSON-RPC server"
desc: "Listening port of the Websocket JSON-RPC server"
defaultValue: defaultEthWsPort
defaultValueDesc: $defaultEthWsPort
name: "ws-port" }: Port
wsAddress* {.
desc: "Listening address of the Websocket JSON-RPC server"
desc: "Listening IP address of the Websocket JSON-RPC server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "ws-address" }: ValidIpAddress
wsApi* {.
desc: "Enable specific set of Websocket RPC API from list (comma-separated) (available: eth, debug)"
defaultValue: RpcApi(value: {RpcFlag.Eth})
wsApi {.
desc: "Enable specific set of Websocket RPC API (available: eth, debug)"
defaultValue: @[]
defaultValueDesc: $RpcFlag.Eth
name: "ws-api" }: RpcApi
name: "ws-api" }: seq[string]
graphqlEnabled* {.
desc: "Enable the HTTP-GraphQL server"
desc: "Enable the GraphQL HTTP server"
defaultValue: false
name: "graphql" }: bool
graphqlPort* {.
desc: "Listening HTTP port for the GraphQL server"
desc: "Listening port of the GraphQL HTTP server"
defaultValue: defaultEthGraphqlPort
defaultValueDesc: $defaultEthGraphqlPort
name: "graphql-port" }: Port
graphqlAddress* {.
desc: "Listening address of the GraphQL server"
desc: "Listening IP address of the GraphQL HTTP server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "graphql-address" }: ValidIpAddress
logLevel* {.
separator: "\pLOGGING AND DEBUGGING OPTIONS:"
desc: "Sets the log level for process and topics (" & logLevelDesc & ")"
defaultValue: LogLevel.INFO
defaultValueDesc: $LogLevel.INFO
name: "log-level" }: LogLevel
logFile* {.
desc: "Specifies a path for the written Json log file"
name: "log-file" }: Option[OutFile]
logMetricsEnabled* {.
desc: "Enable metrics logging"
metricsEnabled* {.
desc: "Enable the built-in metrics HTTP server"
defaultValue: false
name: "log-metrics" .}: bool
name: "metrics" }: bool
metricsPort* {.
desc: "Listening port of the built-in metrics HTTP server"
defaultValue: defaultMetricsServerPort
defaultValueDesc: $defaultMetricsServerPort
name: "metrics-port" }: Port
metricsAddress* {.
desc: "Listening IP address of the built-in metrics HTTP server"
defaultValue: defaultAdminListenAddress
defaultValueDesc: $defaultAdminListenAddressDesc
name: "metrics-address" }: ValidIpAddress
of `import`:
blocksFile* {.
argument
desc: "Import RLP encoded block(s) from a file, validate, write to database and quit"
defaultValue: ""
name: "blocks-file" }: InputFile
logMetricsInterval* {.
desc: "Interval at which to log metrics, in seconds"
defaultValue: 10
name: "log-metrics-interval" .}: int
proc parseCmdArg(T: type NetworkId, p: TaintedString): T =
parseInt(p.string).T
@ -439,54 +423,16 @@ proc processList(v: string, o: var seq[string]) =
if len(n) > 0:
o.add(n)
proc parseCmdArg(T: type EnodeList, p: TaintedString): T =
var list = newSeq[string]()
processList(p.string, list)
for item in list:
let res = ENode.fromString(item)
if res.isErr:
raise newException(ValueError, "failed to parse EnodeList")
result.value.add res.get()
proc completeCmdArg(T: type EnodeList, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg(T: type Protocols, p: TaintedString): T =
var list = newSeq[string]()
processList(p.string, list)
for item in list:
case item.toLowerAscii()
of "eth": result.value.incl ProtocolFlag.Eth
of "les": result.value.incl ProtocolFlag.Les
else:
raise newException(ValueError, "unknown protocol: " & item)
proc completeCmdArg(T: type Protocols, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg(T: type RpcApi, p: TaintedString): T =
var list = newSeq[string]()
processList(p.string, list)
for item in list:
case item.toLowerAscii()
of "eth": result.value.incl RpcFlag.Eth
of "debug": result.value.incl RpcFlag.Debug
else:
raise newException(ValueError, "unknown rpc api: " & item)
proc completeCmdArg(T: type RpcApi, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg(T: type CustomNetwork, p: TaintedString): T =
proc parseCmdArg(T: type NetworkParams, p: TaintedString): T =
try:
if not loadCustomNetwork(p.string, result):
if not loadNetworkParams(p.string, result):
raise newException(ValueError, "failed to load customNetwork")
except Exception as exc:
# on linux/mac, nim compiler refuse to compile
# with unlisted exception error
raise newException(ValueError, "failed to load customNetwork")
proc completeCmdArg(T: type CustomNetwork, val: TaintedString): seq[string] =
proc completeCmdArg(T: type NetworkParams, val: TaintedString): seq[string] =
return @[]
proc setBootnodes(output: var seq[ENode], nodeUris: openarray[string]) =
@ -494,37 +440,131 @@ proc setBootnodes(output: var seq[ENode], nodeUris: openarray[string]) =
for item in nodeUris:
output.add(ENode.fromString(item).tryGet())
proc getBootNodes*(conf: NimbusConf): seq[Enode] =
if conf.mainnet:
result.setBootnodes(MainnetBootnodes)
elif conf.ropsten:
result.setBootnodes(RopstenBootnodes)
elif conf.rinkeby:
result.setBootnodes(RinkebyBootnodes)
elif conf.goerli:
result.setBootnodes(GoerliBootnodes)
elif conf.kovan:
result.setBootnodes(KovanBootnodes)
elif conf.bootnodes.value.len > 0:
result = conf.bootnodes.value
elif conf.bootnodesv4.value.len > 0:
result = conf.bootnodesv4.value
elif conf.bootnodesv5.value.len > 0:
result = conf.bootnodesv5.value
iterator repeatingList(listOfList: openArray[string]): string =
for strList in listOfList:
var list = newSeq[string]()
processList(strList, list)
for item in list:
yield item
proc append(output: var seq[ENode], nodeUris: openArray[string]) =
for item in repeatingList(nodeUris):
let res = ENode.fromString(item)
if res.isErr:
warn "Ignoring invalid bootstrap address", address=item
continue
output.add res.get()
iterator strippedLines(filename: string): (int, string) =
var i = 0
for line in lines(filename):
let stripped = strip(line)
if stripped.startsWith('#'): # Comments
continue
if stripped.len > 0:
yield (i, stripped)
inc i
proc loadBootstrapFile(fileName: string, output: var seq[Enode]) =
if fileName.len == 0:
return
try:
for i, ln in strippedLines(fileName):
if cmpIgnoreCase(ln, "override") == 0 and i == 0:
# override built-in list if the first line is 'override'
output = newSeq[ENode]()
continue
let res = ENode.fromString(ln)
if res.isErr:
warn "Ignoring invalid bootstrap address", address=ln, line=i, file=fileName
continue
output.add res.get()
except IOError as e:
error "Could not read bootstrap file", msg = e.msg
quit 1
proc getNetworkId(conf: NimbusConf): Option[NetworkId] =
if conf.mainnet:
some MainNet
elif conf.ropsten:
some RopstenNet
elif conf.rinkeby:
some RinkebyNet
elif conf.goerli:
some GoerliNet
elif conf.kovan:
some KovanNet
if conf.network.len == 0:
return none NetworkId
let network = toLowerAscii(conf.network)
case network
of "mainnet": return some MainNet
of "ropsten": return some RopstenNet
of "rinkeby": return some RinkebyNet
of "goerli" : return some GoerliNet
of "kovan" : return some KovanNet
else:
conf.networkId
try:
some parseInt(network).NetworkId
except CatchableError:
error "Failed to parse network name or id", network
quit QuitFailure
proc getProtocolFlags*(conf: NimbusConf): set[ProtocolFlag] =
if conf.protocols.len == 0:
return {ProtocolFlag.Eth}
for item in repeatingList(conf.protocols):
case item.toLowerAscii()
of "eth": result.incl ProtocolFlag.Eth
of "les": result.incl ProtocolFlag.Les
else:
error "Unknown protocol", name=item
quit QuitFailure
proc getRpcFlags(api: openArray[string]): set[RpcFlag] =
if api.len == 0:
return {RpcFlag.Eth}
for item in repeatingList(api):
case item.toLowerAscii()
of "eth": result.incl RpcFlag.Eth
of "debug": result.incl RpcFlag.Debug
else:
error "Unknown RPC API: ", name=item
quit QuitFailure
proc getRpcFlags*(conf: NimbusConf): set[RpcFlag] =
getRpcFlags(conf.rpcApi)
proc getWsFlags*(conf: NimbusConf): set[RpcFlag] =
getRpcFlags(conf.wsApi)
proc getBootNodes*(conf: NimbusConf): seq[Enode] =
# Ignore standard bootnodes if customNetwork is loaded
if conf.customNetwork.isNone:
case conf.networkId
of MainNet:
result.setBootnodes(MainnetBootnodes)
of RopstenNet:
result.setBootnodes(RopstenBootnodes)
of RinkebyNet:
result.setBootnodes(RinkebyBootnodes)
of GoerliNet:
result.setBootnodes(GoerliBootnodes)
of KovanNet:
result.setBootnodes(KovanBootnodes)
else:
# custom network id
discard
# always allow custom boostrap nodes
# if it is set by user
if conf.bootstrapNodes.len > 0:
result.append(conf.bootstrapNodes)
# bootstrap nodes loaded from file might append or
# override built-in bootnodes
loadBootstrapFile(string conf.bootstrapFile, result)
proc getStaticPeers*(conf: NimbusConf): seq[Enode] =
result.append(conf.staticPeers)
proc makeConfig*(cmdLine = commandLineParams()): NimbusConf =
{.push warning[ProveInit]: off.}
@ -535,28 +575,32 @@ proc makeConfig*(cmdLine = commandLineParams()): NimbusConf =
)
{.pop.}
result.networkId = result.getNetworkId()
var networkId = result.getNetworkId()
if result.networkId.isNone and result.customNetwork.isSome:
# WARNING: networkId and chainId are two distinct things
# they usage should not be mixed in other places.
# We only set networkId to chainId if networkId not set in cli and
# --custom-network is set.
# If chainId is not defined in config file, it's ok because
# the default networkId `CustomNetwork` has 0 value too.
result.networkId = some(NetworkId(result.customNetwork.get().config.chainId))
if result.customNetwork.isSome:
result.networkParams = result.customNetwork.get()
if networkId.isNone:
# WARNING: networkId and chainId are two distinct things
# they usage should not be mixed in other places.
# We only set networkId to chainId if networkId not set in cli and
# --custom-network is set.
# If chainId is not defined in config file, it's ok because
# zero means CustomNet
networkId = some(NetworkId(result.networkParams.config.chainId))
if result.networkId.isNone:
if networkId.isNone:
# bootnodes is set via getBootNodes
result.networkId = some MainNet
result.mainnet = true
networkId = some MainNet
if result.udpPort == Port(0):
# if udpPort not set in cli, then
result.udpPort = result.tcpPort
result.networkId = networkId.get()
if result.customNetwork.isNone:
result.customNetwork = some CustomNetwork()
result.networkParams = networkParams(result.networkId)
if result.cmd == noCommand:
if result.udpPort == Port(0):
# if udpPort not set in cli, then
result.udpPort = result.tcpPort
when isMainModule:
# for testing purpose

View File

@ -16,9 +16,9 @@ type
BaseChainDB* = ref object
db* : TrieDatabaseRef
pruneTrie*: bool
config* : ChainConfig
networkId*: NetworkId
customNetwork*: CustomNetwork
config* : ChainConfig
genesis* : Genesis
# startingBlock, currentBlock, and highestBlock
# are progress indicator
@ -34,14 +34,14 @@ proc newBaseChainDB*(
db: TrieDatabaseRef,
pruneTrie: bool = true,
id: NetworkId = MainNet,
cn = CustomNetwork() ): BaseChainDB =
params = networkParams(MainNet)): BaseChainDB =
new(result)
result.db = db
result.pruneTrie = pruneTrie
result.config = chainConfig(id, cn)
result.networkId = id
result.customNetwork = cn
result.config = params.config
result.genesis = params.genesis
proc `$`*(db: BaseChainDB): string =
result = "BaseChainDB"

View File

@ -1,51 +1,11 @@
import
std/[times, tables],
eth/[common, rlp, trie, p2p], stew/[byteutils],
std/tables,
eth/[common, rlp, trie, p2p],
chronicles, eth/trie/db,
./db/[db_chain, state_db],
./genesis_alloc, ./constants,
./constants,
./chain_config, ./forks, ./p2p/gaslimit
proc genesisBlockForNetwork*(id: NetworkId, cn: CustomNetwork): Genesis =
result = case id
of MainNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
gasLimit: 5000,
difficulty: 17179869184.u256,
alloc: decodePrealloc(mainnetAllocData)
)
of RopstenNet:
Genesis(
nonce: 66.toBlockNonce,
extraData: hexToSeqByte("0x3535353535353535353535353535353535353535353535353535353535353535"),
gasLimit: 16777216,
difficulty: 1048576.u256,
alloc: decodePrealloc(testnetAllocData)
)
of RinkebyNet:
Genesis(
nonce: 0.toBlockNonce,
timestamp: initTime(0x58ee40ba, 0),
extraData: hexToSeqByte("0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
gasLimit: 4700000,
difficulty: 1.u256,
alloc: decodePrealloc(rinkebyAllocData)
)
of GoerliNet:
Genesis(
nonce: 0.toBlockNonce,
timestamp: initTime(0x5c51a607, 0),
extraData: hexToSeqByte("0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
gasLimit: 0xa00000,
difficulty: 1.u256,
alloc: decodePrealloc(goerliAllocData)
)
else:
# everything else will use custom genesis
cn.genesis
proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader =
let (tdb, pruneTrie) = if db.isNil: (newMemoryDB(), true)
else: (db.db, db.pruneTrie)
@ -78,18 +38,14 @@ proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader =
elif db.isNil.not and db.config.toFork(0.toBlockNumber) >= FkLondon:
result.baseFee = EIP1559_INITIAL_BASE_FEE.u256
if g.gasLimit == 0:
if g.gasLimit.isZero:
result.gasLimit = GENESIS_GAS_LIMIT
if g.difficulty == 0:
if g.difficulty.isZero:
result.difficulty = GENESIS_DIFFICULTY
proc commit*(g: Genesis, db: BaseChainDB) =
let b = g.toBlock(db)
doAssert(b.blockNumber == 0, "can't commit genesis block with number > 0")
discard db.persistHeaderToDb(b)
proc initializeEmptyDb*(db: BaseChainDB) =
trace "Writing genesis to DB"
let genesis = genesisBlockForNetwork(db.networkId, db.customNetwork)
genesis.commit(db)
let b = db.genesis.toBlock(db)
doAssert(b.blockNumber.isZero, "can't commit genesis block with number > 0")
discard db.persistHeaderToDb(b)

View File

@ -41,43 +41,17 @@ type
wsRpcServer: RpcWebSocketServer
sealingEngine: SealingEngineRef
ctx: EthContext
chainRef: Chain
template init(T: type RpcHttpServer, ip: ValidIpAddress, port: Port): T =
newRpcHttpServer([initTAddress(ip, port)])
template init(T: type RpcWebSocketServer, ip: ValidIpAddress, port: Port): T =
newRpcWebSocketServer(initTAddress(ip, port))
proc start(nimbus: NimbusNode, conf: NimbusConf) =
## logging
setLogLevel(conf.logLevel)
if conf.logFile.isSome:
let logFile = string conf.logFile.get()
defaultChroniclesStream.output.outFile = nil # to avoid closing stdout
discard defaultChroniclesStream.output.open(logFile, fmAppend)
createDir(string conf.dataDir)
let trieDB = trieDB newChainDb(string conf.dataDir)
let networkId = conf.networkId.get()
let customNetwork = conf.customNetwork.get()
var chainDB = newBaseChainDB(trieDB,
conf.pruneMode == PruneMode.Full,
networkId,
customNetwork
)
chainDB.populateProgress()
if canonicalHeadHashKey().toOpenArray notin trieDB:
initializeEmptyDb(chainDb)
doAssert(canonicalHeadHashKey().toOpenArray in trieDB)
if string(conf.importBlocks).len > 0:
proc importBlocks(conf: NimbusConf, chainDB: BaseChainDB) =
if string(conf.blocksFile).len > 0:
# success or not, we quit after importing blocks
if not importRlpBlock(string conf.importBlocks, chainDB):
if not importRlpBlock(string conf.blocksFile, chainDB):
quit(QuitFailure)
else:
quit(QuitSuccess)
proc manageAccounts(nimbus: NimbusNode, conf: NimbusConf) =
if string(conf.keyStore).len > 0:
let res = nimbus.ctx.am.loadKeystores(string conf.keyStore)
if res.isErr:
@ -90,17 +64,8 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
echo res.error()
quit(QuitFailure)
# metrics logging
if conf.logMetricsEnabled:
# https://github.com/nim-lang/Nim/issues/17369
var logMetrics: proc(udata: pointer) {.gcsafe, raises: [Defect].}
logMetrics = proc(udata: pointer) =
{.gcsafe.}:
let registry = defaultRegistry
info "metrics", registry
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
chainDB: BaseChainDB, protocols: set[ProtocolFlag]) =
## Creating P2P Server
let kpres = nimbus.ctx.hexToKeyPair(conf.nodeKeyHex)
if kpres.isErr:
@ -131,33 +96,58 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
if extPorts.isSome:
(address.tcpPort, address.udpPort) = extPorts.get()
nimbus.ethNode = newEthereumNode(keypair, address, networkId,
nimbus.ethNode = newEthereumNode(keypair, address, conf.networkId,
nil, conf.agentString,
addAllCapabilities = false,
minPeers = conf.maxPeers)
# Add protocol capabilities based on protocol flags
if ProtocolFlag.Eth in conf.protocols.value:
if ProtocolFlag.Eth in protocols:
nimbus.ethNode.addCapability eth
if ProtocolFlag.Les in conf.protocols.value:
if ProtocolFlag.Les in protocols:
nimbus.ethNode.addCapability les
# chainRef: some name to avoid module-name/filed/function misunderstandings
let chainRef = newChain(chainDB)
nimbus.ethNode.chain = chainRef
nimbus.chainRef = newChain(chainDB)
nimbus.ethNode.chain = nimbus.chainRef
if conf.verifyFrom.isSome:
let verifyFrom = conf.verifyFrom.get()
chainRef.extraValidation = 0 < verifyFrom
chainRef.verifyFrom = verifyFrom
nimbus.chainRef.extraValidation = 0 < verifyFrom
nimbus.chainRef.verifyFrom = verifyFrom
# Connect directly to the static nodes
let staticPeers = conf.getStaticPeers()
for enode in staticPeers:
asyncCheck nimbus.ethNode.peerPool.connectToNode(newNode(enode))
# Connect via discovery
let bootNodes = conf.getBootNodes()
if bootNodes.len > 0:
waitFor nimbus.ethNode.connectToNetwork(bootNodes,
enableDiscovery = conf.discovery != DiscoveryType.None)
proc localServices(nimbus: NimbusNode, conf: NimbusConf,
chainDB: BaseChainDB, protocols: set[ProtocolFlag]) =
# metrics logging
if conf.logMetricsEnabled:
# https://github.com/nim-lang/Nim/issues/17369
var logMetrics: proc(udata: pointer) {.gcsafe, raises: [Defect].}
logMetrics = proc(udata: pointer) =
{.gcsafe.}:
let registry = defaultRegistry
info "metrics", registry
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
discard setTimer(Moment.fromNow(conf.logMetricsInterval.seconds), logMetrics)
# Creating RPC Server
if conf.rpcEnabled:
nimbus.rpcServer = RpcHttpServer.init(conf.rpcAddress, conf.rpcPort)
nimbus.rpcServer = newRpcHttpServer([initTAddress(conf.rpcAddress, conf.rpcPort)])
setupCommonRpc(nimbus.ethNode, conf, nimbus.rpcServer)
# Enable RPC APIs based on RPC flags and protocol flags
if RpcFlag.Eth in conf.rpcApi.value and ProtocolFlag.Eth in conf.protocols.value:
let rpcFlags = conf.getRpcFlags()
if RpcFlag.Eth in rpcFlags and ProtocolFlag.Eth in protocols:
setupEthRpc(nimbus.ethNode, nimbus.ctx, chainDB, nimbus.rpcServer)
if RpcFlag.Debug in conf.rpcApi.value:
if RpcFlag.Debug in rpcFlags:
setupDebugRpc(chainDB, nimbus.rpcServer)
nimbus.rpcServer.rpc("admin_quit") do() -> string:
@ -169,13 +159,14 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
# Creating Websocket RPC Server
if conf.wsEnabled:
nimbus.wsRpcServer = RpcWebSocketServer.init(conf.wsAddress, conf.wsPort)
nimbus.wsRpcServer = newRpcWebSocketServer(initTAddress(conf.wsAddress, conf.wsPort))
setupCommonRpc(nimbus.ethNode, conf, nimbus.wsRpcServer)
# Enable Websocket RPC APIs based on RPC flags and protocol flags
if RpcFlag.Eth in conf.wsApi.value and ProtocolFlag.Eth in conf.protocols.value:
let wsFlags = conf.getWsFlags()
if RpcFlag.Eth in wsFlags and ProtocolFlag.Eth in protocols:
setupEthRpc(nimbus.ethNode, nimbus.ctx, chainDB, nimbus.wsRpcServer)
if RpcFlag.Debug in conf.wsApi.value:
if RpcFlag.Debug in wsFlags:
setupDebugRpc(chainDB, nimbus.wsRpcServer)
nimbus.wsRpcServer.start()
@ -185,12 +176,12 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
nimbus.graphqlServer.start()
if conf.engineSigner != ZERO_ADDRESS:
let rs = validateSealer(conf, nimbus.ctx, chainRef)
let rs = validateSealer(conf, nimbus.ctx, nimbus.chainRef)
if rs.isErr:
echo rs.error
quit(QuitFailure)
nimbus.sealingEngine = SealingEngineRef.new(
chainRef, nimbus.ctx, conf.engineSigner
nimbus.chainRef, nimbus.ctx, conf.engineSigner
)
nimbus.sealingEngine.start()
@ -199,31 +190,53 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
info "Starting metrics HTTP server", address = conf.metricsAddress, port = conf.metricsPort
startMetricsHttpServer($conf.metricsAddress, conf.metricsPort)
# Connect directly to the static nodes
for enode in conf.staticNodes.value:
asyncCheck nimbus.ethNode.peerPool.connectToNode(newNode(enode))
proc start(nimbus: NimbusNode, conf: NimbusConf) =
## logging
setLogLevel(conf.logLevel)
if conf.logFile.isSome:
let logFile = string conf.logFile.get()
defaultChroniclesStream.output.outFile = nil # to avoid closing stdout
discard defaultChroniclesStream.output.open(logFile, fmAppend)
# Connect via discovery
let bootNodes = conf.getBootNodes()
waitFor nimbus.ethNode.connectToNetwork(bootNodes,
enableDiscovery = not conf.noDiscover)
createDir(string conf.dataDir)
let trieDB = trieDB newChainDb(string conf.dataDir)
var chainDB = newBaseChainDB(trieDB,
conf.pruneMode == PruneMode.Full,
conf.networkId,
conf.networkParams
)
chainDB.populateProgress()
if ProtocolFlag.Eth in conf.protocols.value:
# TODO: temp code until the CLI/RPC interface is fleshed out
let status = waitFor nimbus.ethNode.fastBlockchainSync()
if status != syncSuccess:
debug "Block sync failed: ", status
if canonicalHeadHashKey().toOpenArray notin trieDB:
initializeEmptyDb(chainDb)
doAssert(canonicalHeadHashKey().toOpenArray in trieDB)
if nimbus.state == Starting:
# it might have been set to "Stopping" with Ctrl+C
nimbus.state = Running
let protocols = conf.getProtocolFlags()
case conf.cmd
of NimbusCmd.`import`:
importBlocks(conf, chainDB)
else:
manageAccounts(nimbus, conf)
setupP2P(nimbus, conf, chainDB, protocols)
localServices(nimbus, conf, chainDB, protocols)
if ProtocolFlag.Eth in protocols:
# TODO: temp code until the CLI/RPC interface is fleshed out
let status = waitFor nimbus.ethNode.fastBlockchainSync()
if status != syncSuccess:
debug "Block sync failed: ", status
if nimbus.state == Starting:
# it might have been set to "Stopping" with Ctrl+C
nimbus.state = Running
proc stop*(nimbus: NimbusNode, conf: NimbusConf) {.async, gcsafe.} =
trace "Graceful shutdown"
if conf.rpcEnabled:
nimbus.rpcServer.stop()
if conf.wsEnabled:
nimbus.wsRpcServer.start()
nimbus.wsRpcServer.stop()
if conf.graphqlEnabled:
await nimbus.graphqlServer.stop()
if conf.engineSigner != ZERO_ADDRESS:

View File

@ -115,10 +115,9 @@ func calculateForkIds(c: ChainConfig,
prevFork = result[fork].nextFork
prevCRC = result[fork].crc
proc setForkId(c: Chain, cn: CustomNetwork)
proc setForkId(c: Chain)
{. raises: [Defect,CatchableError].} =
let g = genesisBlockForNetwork(c.db.networkId, cn)
c.blockZeroHash = g.toBlock.blockHash
c.blockZeroHash = toBlock(c.db.genesis).blockHash
let genesisCRC = crc32(0, c.blockZeroHash.data)
c.forkIds = calculateForkIds(c.db.config, genesisCRC)
@ -136,7 +135,7 @@ proc initChain(c: Chain; db: BaseChainDB; poa: Clique; extraValidation: bool)
if not db.config.daoForkSupport:
db.config.daoForkBlock = db.config.homesteadBlock
c.extraValidation = extraValidation
c.setForkId(db.customNetwork)
c.setForkId()
# Initalise the PoA state regardless of whether it is needed on the current
# network. For non-PoA networks (when `db.config.poaEngine` is `false`),

View File

@ -34,7 +34,7 @@ proc setupCommonRPC*(node: EthereumNode, conf: NimbusConf, server: RpcServer) =
result = "0x" & $keccak_256.digest(rawdata)
server.rpc("net_version") do() -> string:
result = $conf.networkId.get()
result = $conf.networkId
server.rpc("net_listening") do() -> bool:
let numPeers = node.peerPool.connectedNodes.len
@ -46,8 +46,9 @@ proc setupCommonRPC*(node: EthereumNode, conf: NimbusConf, server: RpcServer) =
server.rpc("net_nodeInfo") do() -> NodeInfo:
let enode = toEnode(node)
let nodeId = toNodeId(node.keys.pubkey)
result = NodeInfo(
id: node.discovery.thisNode.id.toHex,
id: nodeId.toHex,
name: conf.agentString,
enode: $enode,
ip: $enode.address.ip,

View File

@ -0,0 +1,3 @@
enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303
enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303
enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303

View File

@ -0,0 +1,4 @@
override
enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303
enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303
enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303

View File

@ -0,0 +1,46 @@
{
"config": {
"chainId": 1,
"homesteadBlock": 0,
"eip150Block": 0,
"eip158Block": 0,
"londonBlock": 1337
},
"genesis": {
"coinbase": "0x0000000000000000000000000000000000000000",
"difficulty": "0x20000",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x2fefd8",
"nonce": "0x0000000000000000",
"timestamp": "0x1234",
"alloc": {
"cf49fda3be353c69b41ed96333cd24302da4556f": {
"balance": "0x123450000000000000000"
},
"0161e041aad467a890839d5b08b138c1e6373072": {
"balance": "0x123450000000000000000"
},
"87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
"balance": "0x123450000000000000000"
},
"b97de4b8c857e4f6bc354f226dc3249aaee49209": {
"balance": "0x123450000000000000000"
},
"c5065c9eeebe6df2c2284d046bfc906501846c51": {
"balance": "0x123450000000000000000"
},
"0000000000000000000000000000000000000314": {
"balance": "0x0",
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
}
},
"0000000000000000000000000000000000000315": {
"balance": "0x9999999999999999999999999999999",
"code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
}
}
}
}

View File

@ -43,7 +43,8 @@ type
## transactions.
prng: Rand
accounts: Table[string,PrivateKey] ## accounts table
boot: CustomNetwork ## imported Genesis configuration
networkId: NetworkId
boot: NetworkParams ## imported Genesis configuration
batch: seq[seq[BlockHeader]] ## collect header chains
chain: Chain
@ -192,15 +193,17 @@ proc initPrettyPrinters(pp: var PrettyPrinters; ap: TesterPool) =
proc resetChainDb(ap: TesterPool; extraData: Blob; debug = false) =
## Setup new block chain with bespoke genesis
ap.chain = BaseChainDB(
db: newMemoryDb(),
config: ap.boot.config).newChain
let chainDB = newBaseChainDB(
newMemoryDb(),
id = ap.networkId,
params = ap.boot)
ap.chain = newChain(chainDB)
ap.chain.clique.db.populateProgress
# new genesis block
var g = ap.boot.genesis
if 0 < extraData.len:
g.extraData = extraData
g.commit(ap.chain.clique.db)
chainDB.genesis.extraData = extraData
initializeEmptyDB(chainDB)
# fine tune Clique descriptor
ap.chain.clique.cfg.debug = debug
ap.chain.clique.cfg.prettyPrint.initPrettyPrinters(ap)
@ -242,9 +245,9 @@ proc sayHeaderChain*(ap: TesterPool; indent = 0): TesterPool {.discardable.} =
proc newVoterPool*(networkId = GoerliNet): TesterPool =
TesterPool(
boot: CustomNetwork(
genesis: genesisBlockForNetwork(networkId, CustomNetwork()),
config: chainConfig(networkId, CustomNetwork()))).initTesterPool
networkId: networkId,
boot: networkParams(networkId)
).initTesterPool
# ------------------------------------------------------------------------------
# Public: getter

View File

@ -2,17 +2,20 @@ import
std/[os],
pkg/[unittest2, confutils],
eth/[p2p, common],
../nimbus/[config, chain_config]
../nimbus/[config, chain_config],
./test_helpers
proc `==`(a, b: ChainId): bool =
a.int == b.int
proc configurationMain*() =
suite "configuration test suite":
const genesisFile = "tests" / "customgenesis" / "calaveras.json"
const
genesisFile = "tests" / "customgenesis" / "calaveras.json"
bootNode = "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303"
test "data-dir and key-store":
let conf = makeConfig(@[]) # don't use makeConfig default cmdLine from inside all_tests
let conf = makeTestConfig()
check conf.dataDir.string == defaultDataDir()
check conf.keyStore.string == defaultKeystoreDir()
@ -25,7 +28,7 @@ proc configurationMain*() =
check dd.keyStore.string == "banana/bin"
test "prune-mode":
let aa = makeConfig(@[])
let aa = makeTestConfig()
check aa.pruneMode == PruneMode.Full
let bb = makeConfig(@["--prune-mode:full"])
@ -38,39 +41,143 @@ proc configurationMain*() =
check dd.pruneMode == PruneMode.Archive
test "import":
let aa = makeConfig(@[])
check aa.importBlocks.string == ""
let aa = makeTestConfig()
check aa.cmd == NimbusCmd.noCommand
let bb = makeConfig(@["--import-blocks:" & genesisFile])
check bb.importBlocks.string == genesisFile
let cc = makeConfig(@["-b:" & genesisFile])
check cc.importBlocks.string == genesisFile
let bb = makeConfig(@["import", genesisFile])
check bb.cmd == NimbusCmd.`import`
check bb.blocksFile.string == genesisFile
test "network-id":
let aa = makeConfig(@[])
check aa.networkId.get() == MainNet
check aa.mainnet == true
check aa.customNetwork.get() == CustomNetwork()
let aa = makeTestConfig()
check aa.networkId == MainNet
check aa.networkParams != NetworkParams()
let conf = makeConfig(@["--custom-network:" & genesisFile, "--network-id:345"])
check conf.networkId.get() == 345.NetworkId
let conf = makeConfig(@["--custom-network:" & genesisFile, "--network:345"])
check conf.networkId == 345.NetworkId
test "network-id first, custom-network next":
let conf = makeConfig(@["--network-id:678", "--custom-network:" & genesisFile])
check conf.networkId.get() == 678.NetworkId
let conf = makeConfig(@["--network:678", "--custom-network:" & genesisFile])
check conf.networkId == 678.NetworkId
test "network-id set, no custom-network":
let conf = makeConfig(@["--network:678"])
check conf.networkId == 678.NetworkId
check conf.networkParams == NetworkParams()
test "network-id not set, copy from chainId of customnetwork":
let conf = makeConfig(@["--custom-network:" & genesisFile])
check conf.networkId.get() == 123.NetworkId
check conf.networkId == 123.NetworkId
test "network-id not set, goerli set":
let conf = makeConfig(@["--goerli"])
check conf.networkId.get() == GoerliNet
let conf = makeConfig(@["--network:goerli"])
check conf.networkId == GoerliNet
test "network-id set, goerli set":
let conf = makeConfig(@["--goerli", "--network-id:123"])
check conf.networkId.get() == GoerliNet
let conf = makeConfig(@["--network:goerli", "--network:123"])
check conf.networkId == 123.NetworkId
test "rpc-api":
let conf = makeTestConfig()
let flags = conf.getRpcFlags()
check RpcFlag.Eth in flags
let aa = makeConfig(@["--rpc-api:eth"])
let ax = aa.getRpcFlags()
check RpcFlag.Eth in ax
let bb = makeConfig(@["--rpc-api:eth", "--rpc-api:debug"])
let bx = bb.getRpcFlags()
check RpcFlag.Eth in bx
check RpcFlag.Debug in bx
let cc = makeConfig(@["--rpc-api:eth,debug"])
let cx = cc.getRpcFlags()
check RpcFlag.Eth in cx
check RpcFlag.Debug in cx
test "ws-api":
let conf = makeTestConfig()
let flags = conf.getWsFlags()
check RpcFlag.Eth in flags
let aa = makeConfig(@["--ws-api:eth"])
let ax = aa.getWsFlags()
check RpcFlag.Eth in ax
let bb = makeConfig(@["--ws-api:eth", "--ws-api:debug"])
let bx = bb.getWsFlags()
check RpcFlag.Eth in bx
check RpcFlag.Debug in bx
let cc = makeConfig(@["--ws-api:eth,debug"])
let cx = cc.getWsFlags()
check RpcFlag.Eth in cx
check RpcFlag.Debug in cx
test "protocols":
let conf = makeTestConfig()
let flags = conf.getProtocolFlags()
check ProtocolFlag.Eth in flags
let aa = makeConfig(@["--protocols:les"])
let ax = aa.getProtocolFlags()
check ProtocolFlag.Les in ax
let bb = makeConfig(@["--protocols:eth", "--protocols:les"])
let bx = bb.getProtocolFlags()
check ProtocolFlag.Eth in bx
check ProtocolFlag.Les in bx
let cc = makeConfig(@["--protocols:eth,les"])
let cx = cc.getProtocolFlags()
check ProtocolFlag.Eth in cx
check ProtocolFlag.Les in cx
test "bootstrap-node and bootstrap-file":
let conf = makeTestConfig()
let bootnodes = conf.getBootnodes()
let bootNodeLen = bootnodes.len
check bootNodeLen > 0 # mainnet bootnodes
let aa = makeConfig(@["--bootstrap-node:" & bootNode])
let ax = aa.getBootNodes()
check ax.len == bootNodeLen + 1
const
bootFilePath = "tests" / "bootstrap"
bootFileAppend = bootFilePath / "append_bootnodes.txt"
bootFileOverride = bootFilePath / "override_bootnodes.txt"
let bb = makeConfig(@["--bootstrap-file:" & bootFileAppend])
let bx = bb.getBootNodes()
check bx.len == bootNodeLen + 3
let cc = makeConfig(@["--bootstrap-file:" & bootFileOverride])
let cx = cc.getBootNodes()
check cx.len == 3
test "static-peers":
let conf = makeTestConfig()
check conf.getStaticPeers().len == 0
let aa = makeConfig(@["--static-peers:" & bootNode])
check aa.getStaticPeers().len == 1
let bb = makeConfig(@["--static-peers:" & bootNode & "," & bootNode])
check bb.getStaticPeers().len == 2
let cc = makeConfig(@["--static-peers:" & bootNode, "--static-peers:" & bootNode])
check cc.getStaticPeers().len == 2
test "chainId of custom-network is oneof std network":
const
chainid1 = "tests" / "customgenesis" / "chainid1.json"
let conf = makeConfig(@["--custom-network:" & chainid1])
check conf.networkId == 1.NetworkId
check conf.networkParams.config.londonBlock == 1337
check conf.getBootnodes().len == 0
when isMainModule:
configurationMain()

View File

@ -60,11 +60,11 @@ template runTests(name: string, hex: bool, calculator: typed) =
check diff == t.currentDifficulty
proc difficultyMain*() =
let mainnetConfig = chainConfig(MainNet, CustomNetwork())
let mainnetConfig = networkParams(MainNet).config
func calcDifficultyMainNetWork(timeStamp: EthTime, parent: BlockHeader): DifficultyInt =
mainnetConfig.calcDifficulty(timeStamp, parent)
let ropstenConfig = chainConfig(RopstenNet, CustomNetwork())
let ropstenConfig = networkParams(RopstenNet).config
func calcDifficultyRopsten(timeStamp: EthTime, parent: BlockHeader): DifficultyInt =
ropstenConfig.calcDifficulty(timeStamp, parent)

View File

@ -86,7 +86,7 @@ template runTest(network: untyped) =
test `network`.astToStr:
var
memDB = newMemoryDB()
chainDB = newBaseChainDB(memDB, true, network)
chainDB = newBaseChainDB(memDB, true, network, networkParams(network))
chain = newChain(chainDB)
for x in `network IDs`:

View File

@ -8,39 +8,39 @@ const dataFolder = "tests" / "customgenesis"
proc genesisTest() =
suite "Genesis":
test "Correct mainnet hash":
let g = genesisBlockForNetwork(MainNet, CustomNetwork())
let g = networkParams(MainNet).genesis
let b = g.toBlock
check(b.blockHash == "D4E56740F876AEF8C010B86A40D5F56745A118D0906A34E69AEC8C0DB1CB8FA3".toDigest)
test "Correct ropstennet hash":
let g = genesisBlockForNetwork(RopstenNet, CustomNetwork())
let g = networkParams(RopstenNet).genesis
let b = g.toBlock
check(b.blockHash == "41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d".toDigest)
test "Correct rinkebynet hash":
let g = genesisBlockForNetwork(RinkebyNet, CustomNetwork())
let g = networkParams(RinkebyNet).genesis
let b = g.toBlock
check(b.blockHash == "6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177".toDigest)
test "Correct goerlinet hash":
let g = genesisBlockForNetwork(GoerliNet, CustomNetwork())
let g = networkParams(GoerliNet).genesis
let b = g.toBlock
check(b.blockHash == "bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a".toDigest)
proc customGenesisTest() =
suite "Custom Genesis":
test "loadCustomGenesis":
var cga, cgb, cgc: CustomNetwork
check loadCustomNetwork(dataFolder / "berlin2000.json", cga)
check loadCustomNetwork(dataFolder / "chainid7.json", cgb)
check loadCustomNetwork(dataFolder / "noconfig.json", cgc)
var cga, cgb, cgc: NetworkParams
check loadNetworkParams(dataFolder / "berlin2000.json", cga)
check loadNetworkParams(dataFolder / "chainid7.json", cgb)
check loadNetworkParams(dataFolder / "noconfig.json", cgc)
check cga.config.poaEngine == false
check cgb.config.poaEngine == false
check cgc.config.poaEngine == false
test "calaveras.json":
var cg: CustomNetwork
check loadCustomNetwork(dataFolder / "calaveras.json", cg)
var cg: NetworkParams
check loadNetworkParams(dataFolder / "calaveras.json", cg)
let h = toBlock(cg.genesis, nil)
let stateRoot = "664c93de37eb4a72953ea42b8c046cdb64c9f0b0bca5505ade8d970d49ebdb8c".toDigest
let genesisHash = "eb9233d066c275efcdfed8037f4fc082770176aefdbcb7691c71da412a5670f2".toDigest

View File

@ -63,7 +63,7 @@ proc setupChain(): BaseChainDB =
if not parseGenesisAlloc($(jn["pre"]), genesis.alloc):
quit(QuitFailure)
let customNetwork = CustomNetwork(
let customNetwork = NetworkParams(
config: config,
genesis: genesis
)
@ -95,7 +95,7 @@ proc setupChain(): BaseChainDB =
proc graphqlMain*() =
let
conf = makeConfig(@[]) # don't use makeConfig default cmdLine from inside all_tests
conf = makeTestConfig()
ethCtx = newEthContext()
ethNode = setupEthNode(conf, ethCtx, eth)
chainDB = setupChain()

View File

@ -275,13 +275,17 @@ proc hashLogEntries*(logs: seq[Log]): string =
proc setupEthNode*(conf: NimbusConf, ctx: EthContext, capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode =
let keypair = ctx.hexToKeyPair(conf.nodeKeyHex).tryGet()
var srvAddress: Address
srvAddress.ip = parseIpAddress("0.0.0.0")
srvAddress.ip = conf.listenAddress
srvAddress.tcpPort = conf.tcpPort
srvAddress.udpPort = conf.udpPort
result = newEthereumNode(
keypair, srvAddress,
conf.networkId.get(),
conf.networkId,
nil, conf.agentString,
addAllCapabilities = false)
for capability in capabilities:
result.addCapability capability
proc makeTestConfig*(): NimbusConf =
# commandLineParams() will not works inside all_tests
makeConfig(@[])

View File

@ -124,14 +124,14 @@ proc rpcMain*() =
suite "Remote Procedure Calls":
# TODO: Include other transports such as Http
let
conf = makeConfig(@[]) # don't use makeConfig default cmdLine from inside all_tests
conf = makeTestConfig()
ctx = newEthContext()
ethNode = setupEthNode(conf, ctx, eth)
chain = newBaseChainDB(
newMemoryDb(),
conf.pruneMode == PruneMode.Full,
conf.networkId.get(),
conf.customNetwork.get()
conf.networkId,
conf.networkParams
)
signer: EthAddress = hexToByteArray[20]("0x0e69cde81b1aa07a45c32c6cd85d67229d36bb1b")
ks2: EthAddress = hexToByteArray[20]("0xa3b2222afa5c987da6ef773fde8d01b9f23d481f")
@ -182,7 +182,7 @@ proc rpcMain*() =
test "net_version":
let res = await client.net_version()
check res == $conf.networkId.get()
check res == $conf.networkId
test "net_listening":
let res = await client.net_listening()

View File

@ -45,7 +45,7 @@ proc main() {.used.} =
# 52029 first block with receipts logs
# 66407 failed transaction
# nimbus --rpcapi: eth, debug --prune: archive
# nimbus --rpc-api: eth, debug --prune: archive
var conf = makeConfig()
let db = newChainDb(string conf.dataDir)