2018-04-27 08:53:53 +00:00
|
|
|
# Nimbus
|
|
|
|
# Copyright (c) 2018 Status Research & Development GmbH
|
|
|
|
# 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-07-22 21:34:43 +00:00
|
|
|
import
|
2018-07-26 20:08:43 +00:00
|
|
|
os, strutils, net, eth_common, db/[storage_types, db_chain],
|
2018-07-22 21:34:43 +00:00
|
|
|
asyncdispatch2, json_rpc/rpcserver, eth_keys,
|
2018-10-16 00:10:01 +00:00
|
|
|
eth_p2p, eth_p2p/rlpx_protocols/[eth_protocol, les_protocol],
|
|
|
|
eth_p2p/blockchain_sync,
|
2018-08-29 08:49:01 +00:00
|
|
|
config, genesis, rpc/[common, p2p], p2p/chain,
|
2018-10-05 00:20:12 +00:00
|
|
|
eth_trie/db
|
2018-07-26 20:08:43 +00:00
|
|
|
|
2018-09-06 17:05:22 +00:00
|
|
|
const UseSqlite = false
|
2018-07-26 20:08:43 +00:00
|
|
|
|
|
|
|
when UseSqlite:
|
|
|
|
import db/backends/sqlite_backend
|
|
|
|
else:
|
|
|
|
import db/backends/rocksdb_backend
|
2018-06-20 17:27:32 +00:00
|
|
|
|
|
|
|
## TODO:
|
|
|
|
## * No IPv6 support
|
|
|
|
## * No multiple bind addresses support
|
|
|
|
## * No database support
|
|
|
|
|
2018-07-12 11:14:04 +00:00
|
|
|
const
|
|
|
|
nimbusClientId = "nimbus 0.1.0"
|
|
|
|
|
2018-06-20 17:27:32 +00:00
|
|
|
when not defined(windows):
|
|
|
|
from posix import SIGINT, SIGTERM
|
|
|
|
|
|
|
|
type
|
|
|
|
NimbusState = enum
|
|
|
|
Starting, Running, Stopping, Stopped
|
|
|
|
|
|
|
|
NimbusObject = ref object
|
2018-07-20 17:02:19 +00:00
|
|
|
rpcServer*: RpcHttpServer
|
2018-07-12 11:14:04 +00:00
|
|
|
ethNode*: EthereumNode
|
2018-06-20 17:27:32 +00:00
|
|
|
state*: NimbusState
|
|
|
|
|
2018-07-26 20:08:43 +00:00
|
|
|
proc initializeEmptyDb(db: BaseChainDB) =
|
2018-08-01 12:50:44 +00:00
|
|
|
echo "Writing genesis to DB"
|
|
|
|
let networkId = getConfiguration().net.networkId.toPublicNetwork()
|
|
|
|
if networkId == CustomNet:
|
|
|
|
raise newException(Exception, "Custom genesis not implemented")
|
|
|
|
else:
|
|
|
|
defaultGenesisBlockForNetwork(networkId).commit(db)
|
2018-07-26 20:08:43 +00:00
|
|
|
|
2018-06-20 17:27:32 +00:00
|
|
|
proc start(): NimbusObject =
|
|
|
|
var nimbus = NimbusObject()
|
|
|
|
var conf = getConfiguration()
|
|
|
|
|
|
|
|
## Creating RPC Server
|
|
|
|
if RpcFlags.Enabled in conf.rpc.flags:
|
2018-07-20 17:02:19 +00:00
|
|
|
nimbus.rpcServer = newRpcHttpServer(conf.rpc.binds)
|
2018-06-20 17:27:32 +00:00
|
|
|
setupCommonRpc(nimbus.rpcServer)
|
|
|
|
|
|
|
|
## Creating P2P Server
|
|
|
|
if conf.net.nodekey.isZeroKey():
|
|
|
|
conf.net.nodekey = newPrivateKey()
|
|
|
|
|
|
|
|
var keypair: KeyPair
|
|
|
|
keypair.seckey = conf.net.nodekey
|
|
|
|
keypair.pubkey = conf.net.nodekey.getPublicKey()
|
|
|
|
|
|
|
|
var address: Address
|
|
|
|
address.ip = parseIpAddress("0.0.0.0")
|
|
|
|
address.tcpPort = Port(conf.net.bindPort)
|
|
|
|
address.udpPort = Port(conf.net.discPort)
|
|
|
|
|
2018-09-24 22:25:17 +00:00
|
|
|
createDir(conf.dataDir)
|
|
|
|
let trieDB = trieDB newChainDb(conf.dataDir)
|
2018-07-26 20:08:43 +00:00
|
|
|
let chainDB = newBaseChainDB(trieDB)
|
|
|
|
|
|
|
|
if canonicalHeadHashKey().toOpenArray notin trieDB:
|
|
|
|
initializeEmptyDb(chainDb)
|
2018-08-02 14:07:44 +00:00
|
|
|
assert(canonicalHeadHashKey().toOpenArray in trieDB)
|
2018-07-26 20:08:43 +00:00
|
|
|
|
2018-07-12 11:14:04 +00:00
|
|
|
nimbus.ethNode = newEthereumNode(keypair, address, conf.net.networkId,
|
|
|
|
nil, nimbusClientId)
|
2018-06-20 17:27:32 +00:00
|
|
|
|
2018-08-29 08:49:01 +00:00
|
|
|
nimbus.ethNode.chain = newChain(chainDB)
|
2018-07-26 20:08:43 +00:00
|
|
|
|
2018-06-20 17:27:32 +00:00
|
|
|
if RpcFlags.Enabled in conf.rpc.flags:
|
2018-08-29 08:49:01 +00:00
|
|
|
setupEthRpc(nimbus.ethNode, chainDB, nimbus.rpcServer)
|
2018-06-20 17:27:32 +00:00
|
|
|
|
|
|
|
## Starting servers
|
|
|
|
nimbus.state = Starting
|
|
|
|
if RpcFlags.Enabled in conf.rpc.flags:
|
|
|
|
nimbus.rpcServer.rpc("admin_quit") do() -> string:
|
|
|
|
nimbus.state = Stopping
|
|
|
|
result = "EXITING"
|
|
|
|
nimbus.rpcServer.start()
|
2018-07-12 11:14:04 +00:00
|
|
|
|
2018-09-25 13:30:44 +00:00
|
|
|
waitFor nimbus.ethNode.connectToNetwork(conf.net.bootNodes,
|
|
|
|
enableDiscovery = NoDiscover notin conf.net.flags)
|
2018-07-22 21:34:43 +00:00
|
|
|
|
|
|
|
# TODO: temp code until the CLI/RPC interface is fleshed out
|
2018-08-29 08:49:01 +00:00
|
|
|
let status = waitFor nimbus.ethNode.fastBlockchainSync()
|
|
|
|
if status != syncSuccess:
|
|
|
|
echo "Block sync failed: ", status
|
2018-07-12 11:14:04 +00:00
|
|
|
|
2018-06-20 17:27:32 +00:00
|
|
|
nimbus.state = Running
|
|
|
|
result = nimbus
|
|
|
|
|
|
|
|
proc stop*(nimbus: NimbusObject) {.async.} =
|
|
|
|
echo "Graceful shutdown"
|
|
|
|
nimbus.rpcServer.stop()
|
|
|
|
|
|
|
|
proc process*(nimbus: NimbusObject) =
|
|
|
|
if nimbus.state == Running:
|
|
|
|
when not defined(windows):
|
|
|
|
proc signalBreak(udata: pointer) =
|
|
|
|
nimbus.state = Stopping
|
|
|
|
# Adding SIGINT, SIGTERM handlers
|
2018-08-29 08:49:01 +00:00
|
|
|
# discard addSignal(SIGINT, signalBreak)
|
|
|
|
# discard addSignal(SIGTERM, signalBreak)
|
2018-06-20 17:27:32 +00:00
|
|
|
|
|
|
|
# Main loop
|
|
|
|
while nimbus.state == Running:
|
|
|
|
poll()
|
|
|
|
|
|
|
|
# Stop loop
|
|
|
|
waitFor nimbus.stop()
|
2018-04-27 08:53:53 +00:00
|
|
|
|
|
|
|
when isMainModule:
|
|
|
|
var message: string
|
2018-06-20 17:27:32 +00:00
|
|
|
|
|
|
|
## Pring Nimbus header
|
|
|
|
echo NimbusHeader
|
|
|
|
|
|
|
|
## Processing command line arguments
|
2018-05-02 15:01:10 +00:00
|
|
|
if processArguments(message) != ConfigStatus.Success:
|
2018-04-27 08:53:53 +00:00
|
|
|
echo message
|
|
|
|
quit(QuitFailure)
|
|
|
|
else:
|
|
|
|
if len(message) > 0:
|
|
|
|
echo message
|
2018-06-20 17:27:32 +00:00
|
|
|
quit(QuitSuccess)
|
2018-04-27 08:53:53 +00:00
|
|
|
|
2018-06-20 17:27:32 +00:00
|
|
|
var nimbus = start()
|
|
|
|
nimbus.process()
|