WIP Working local network sim with discovery

* The bootstrap_nodes.txt file in the node's data dir is now optional
* Log more data on start-up
* Use the latest ENR APIs
* Fix simulation build errors
This commit is contained in:
Zahary Karadjov 2020-02-11 19:35:42 +02:00 committed by zah
parent d2f59ebab9
commit 7f395e554a
5 changed files with 38 additions and 20 deletions

View File

@ -180,7 +180,11 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
var bootNodes: seq[ENode] var bootNodes: seq[ENode]
for node in conf.bootstrapNodes: bootNodes.addBootstrapNode(node) for node in conf.bootstrapNodes: bootNodes.addBootstrapNode(node)
bootNodes.loadBootstrapFile(string conf.bootstrapNodesFile) bootNodes.loadBootstrapFile(string conf.bootstrapNodesFile)
bootNodes.loadBootstrapFile(conf.dataDir / "bootstrap_nodes.txt")
let persistentBootstrapFile = conf.dataDir / "bootstrap_nodes.txt"
if fileExists(persistentBootstrapFile):
bootNodes.loadBootstrapFile(persistentBootstrapFile)
bootNodes = filterIt(bootNodes, it.pubkey != netKeys.pubkey) bootNodes = filterIt(bootNodes, it.pubkey != netKeys.pubkey)
let let
@ -1036,16 +1040,22 @@ when hasPrompt:
# createThread(t, processPromptCommands, addr p) # createThread(t, processPromptCommands, addr p)
when isMainModule: when isMainModule:
when compiles(defaultChroniclesStream.output.writer):
defaultChroniclesStream.output.writer =
proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
stdout.write(msg)
debug "Launching beacon node",
version = fullVersionStr,
cmdParams = commandLineParams()
randomize() randomize()
let config = BeaconNodeConf.load( let config = BeaconNodeConf.load(
version = clientId, version = clientId,
copyrightBanner = clientId & "\p" & copyrights) copyrightBanner = clientId & "\p" & copyrights)
when compiles(defaultChroniclesStream.output.writer): debug "Configuration loaded", config
defaultChroniclesStream.output.writer =
proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
stdout.write(msg)
if config.logLevel != LogLevel.NONE: if config.logLevel != LogLevel.NONE:
setLogLevel(config.logLevel) setLogLevel(config.logLevel)

View File

@ -1,6 +1,6 @@
import import
os, options, strformat, strutils, os, options, strformat, strutils,
chronicles, confutils, chronicles, confutils, json_serialization,
confutils/defs, chronicles/options as chroniclesOptions, confutils/defs, chronicles/options as chroniclesOptions,
spec/[crypto] spec/[crypto]
@ -289,3 +289,8 @@ iterator validatorKeys*(conf: BeaconNodeConf): ValidatorPrivKey =
yield ValidatorPrivKey.init(readFile(file).string) yield ValidatorPrivKey.init(readFile(file).string)
except CatchableError as err: except CatchableError as err:
warn "Failed to load a validator private key", file, err = err.msg warn "Failed to load a validator private key", file, err = err.msg
template writeValue*(writer: var JsonWriter,
value: TypedInputFile|InputFile|InputDir|OutPath|OutDir|OutFile) =
writer.writeValue(string value)

View File

@ -1,6 +1,6 @@
import import
os, net, strutils, strformat, parseutils, os, net, strutils, strformat, parseutils,
chronicles, stew/result, eth/keys, eth/trie/db, eth/p2p/enode, chronicles, stew/[result, objects], eth/keys, eth/trie/db, eth/p2p/enode,
eth/p2p/discoveryv5/[enr, protocol, node, discovery_db, types], eth/p2p/discoveryv5/[enr, protocol, node, discovery_db, types],
libp2p/[multiaddress, multicodec, peer], libp2p/[multiaddress, multicodec, peer],
libp2p/crypto/crypto as libp2pCrypto, libp2p/crypto/crypto as libp2pCrypto,
@ -93,18 +93,19 @@ proc parseBootstrapAddress*(address: TaintedString): Result[ENode, cstring] =
var enrRec: enr.Record var enrRec: enr.Record
if enrRec.fromURI(string address): if enrRec.fromURI(string address):
try: try:
# TODO: handle IPv6
let ipBytes = enrRec.get("ip", seq[byte])
if ipBytes.len != 4:
return err "Malformed ENR IP address"
let let
ip = IpAddress(family: IpAddressFamily.IPv4, ip = IpAddress(family: IpAddressFamily.IPv4,
address_v4: cast[array[4, uint8]](enrRec.get("ip", int))) address_v4: toArray(4, ipBytes))
tcpPort = Port enrRec.get("tcp", int) udpPort = Port enrRec.get("udp", uint16)
udpPort = Port enrRec.get("udp", int)
var pubKey: keys.PublicKey var pubKey: keys.PublicKey
if not enrRec.get(pubKey): if not enrRec.get(pubKey):
return err "Failed to read public key from ENR record" return err "Failed to read public key from ENR record"
return ok ENode(pubkey: pubkey, return ok ENode(pubkey: pubkey,
address: Address(ip: ip, address: Address(ip: ip, udpPort: udpPort))
tcpPort: tcpPort,
udpPort: udpPort))
except CatchableError: except CatchableError:
# This will continue to the failure path below # This will continue to the failure path below
discard discard

View File

@ -1,6 +1,7 @@
import import
options, tables, strutils, sequtils, options, tables, strutils, sequtils,
chronos, json_serialization, chronicles, metrics, libp2p/crypto/secp, json_serialization, json_serialization/std/net,
metrics, chronos, chronicles, metrics, libp2p/crypto/secp,
eth/keys, eth/p2p/enode, eth/net/nat, eth/p2p/discoveryv5/enr, eth/keys, eth/p2p/enode, eth/net/nat, eth/p2p/discoveryv5/enr,
eth2_discovery, version, conf eth2_discovery, version, conf
@ -229,7 +230,7 @@ when networkBackend in [libp2p, libp2pDaemon]:
await node.start() await node.start()
await sleepAsync(10.seconds) await sleepAsync(10.seconds)
if libp2p_peers.get == 0: if libp2p_peers.value == 0:
fatal "Failed to connect to any bootstrap node. Quitting" fatal "Failed to connect to any bootstrap node. Quitting"
quit 1 quit 1

View File

@ -1,9 +1,10 @@
import import
algorithm, typetraits, net, algorithm, typetraits, net as stdNet,
stew/[varints,base58], stew/shims/[macros, tables], chronos, chronicles, stew/[varints,base58], stew/shims/[macros, tables], chronos, chronicles,
stint, faststreams/output_stream, serialization, stint, faststreams/output_stream, serialization,
json_serialization/std/options, eth/p2p/p2p_protocol_dsl, json_serialization/std/[net, options],
eth/p2p/discoveryv5/node, eth/[keys, async_utils], eth/p2p/[enode, p2p_protocol_dsl],
eth/p2p/discoveryv5/[enr, node],
# TODO: create simpler to use libp2p modules that use re-exports # TODO: create simpler to use libp2p modules that use re-exports
libp2p/[switch, multistream, connection, libp2p/[switch, multistream, connection,
multiaddress, peerinfo, peer, multiaddress, peerinfo, peer,
@ -208,11 +209,11 @@ proc runDiscoveryLoop*(node: Eth2Node) {.async.} =
await sleepAsync seconds(1) await sleepAsync seconds(1)
proc init*(T: type Eth2Node, conf: BeaconNodeConf, proc init*(T: type Eth2Node, conf: BeaconNodeConf,
switch: Switch, privKey: PrivateKey): T = switch: Switch, privKey: keys.PrivateKey): T =
new result new result
result.switch = switch result.switch = switch
result.peers = initTable[PeerID, Peer]() result.peers = initTable[PeerID, Peer]()
result.discovery = Eth2DiscoveryProtocol.new(conf, privKey.getBytes) result.discovery = Eth2DiscoveryProtocol.new(conf, privKey.data)
result.wantedPeers = conf.maxPeers result.wantedPeers = conf.maxPeers
newSeq result.protocolStates, allProtocols.len newSeq result.protocolStates, allProtocols.len