diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index f962b10c1..7a9c41889 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -180,7 +180,11 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async var bootNodes: seq[ENode] for node in conf.bootstrapNodes: bootNodes.addBootstrapNode(node) 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) let @@ -1036,16 +1040,22 @@ when hasPrompt: # createThread(t, processPromptCommands, addr p) 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() let config = BeaconNodeConf.load( version = clientId, copyrightBanner = clientId & "\p" & copyrights) - when compiles(defaultChroniclesStream.output.writer): - defaultChroniclesStream.output.writer = - proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} = - stdout.write(msg) + debug "Configuration loaded", config if config.logLevel != LogLevel.NONE: setLogLevel(config.logLevel) diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index c09cbdee7..a8803e0cd 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -1,6 +1,6 @@ import os, options, strformat, strutils, - chronicles, confutils, + chronicles, confutils, json_serialization, confutils/defs, chronicles/options as chroniclesOptions, spec/[crypto] @@ -289,3 +289,8 @@ iterator validatorKeys*(conf: BeaconNodeConf): ValidatorPrivKey = yield ValidatorPrivKey.init(readFile(file).string) except CatchableError as err: 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) + diff --git a/beacon_chain/eth2_discovery.nim b/beacon_chain/eth2_discovery.nim index 8a80c2d91..09ce4dda4 100644 --- a/beacon_chain/eth2_discovery.nim +++ b/beacon_chain/eth2_discovery.nim @@ -1,6 +1,6 @@ import 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], libp2p/[multiaddress, multicodec, peer], libp2p/crypto/crypto as libp2pCrypto, @@ -93,18 +93,19 @@ proc parseBootstrapAddress*(address: TaintedString): Result[ENode, cstring] = var enrRec: enr.Record if enrRec.fromURI(string address): try: + # TODO: handle IPv6 + let ipBytes = enrRec.get("ip", seq[byte]) + if ipBytes.len != 4: + return err "Malformed ENR IP address" let ip = IpAddress(family: IpAddressFamily.IPv4, - address_v4: cast[array[4, uint8]](enrRec.get("ip", int))) - tcpPort = Port enrRec.get("tcp", int) - udpPort = Port enrRec.get("udp", int) + address_v4: toArray(4, ipBytes)) + udpPort = Port enrRec.get("udp", uint16) var pubKey: keys.PublicKey if not enrRec.get(pubKey): return err "Failed to read public key from ENR record" return ok ENode(pubkey: pubkey, - address: Address(ip: ip, - tcpPort: tcpPort, - udpPort: udpPort)) + address: Address(ip: ip, udpPort: udpPort)) except CatchableError: # This will continue to the failure path below discard diff --git a/beacon_chain/eth2_network.nim b/beacon_chain/eth2_network.nim index a62713320..c5d759e5a 100644 --- a/beacon_chain/eth2_network.nim +++ b/beacon_chain/eth2_network.nim @@ -1,6 +1,7 @@ import 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, eth2_discovery, version, conf @@ -229,7 +230,7 @@ when networkBackend in [libp2p, libp2pDaemon]: await node.start() await sleepAsync(10.seconds) - if libp2p_peers.get == 0: + if libp2p_peers.value == 0: fatal "Failed to connect to any bootstrap node. Quitting" quit 1 diff --git a/beacon_chain/libp2p_backend.nim b/beacon_chain/libp2p_backend.nim index 95529999b..e54374057 100644 --- a/beacon_chain/libp2p_backend.nim +++ b/beacon_chain/libp2p_backend.nim @@ -1,9 +1,10 @@ import - algorithm, typetraits, net, + algorithm, typetraits, net as stdNet, stew/[varints,base58], stew/shims/[macros, tables], chronos, chronicles, stint, faststreams/output_stream, serialization, - json_serialization/std/options, eth/p2p/p2p_protocol_dsl, - eth/p2p/discoveryv5/node, + json_serialization/std/[net, options], + 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 libp2p/[switch, multistream, connection, multiaddress, peerinfo, peer, @@ -208,11 +209,11 @@ proc runDiscoveryLoop*(node: Eth2Node) {.async.} = await sleepAsync seconds(1) proc init*(T: type Eth2Node, conf: BeaconNodeConf, - switch: Switch, privKey: PrivateKey): T = + switch: Switch, privKey: keys.PrivateKey): T = new result result.switch = switch result.peers = initTable[PeerID, Peer]() - result.discovery = Eth2DiscoveryProtocol.new(conf, privKey.getBytes) + result.discovery = Eth2DiscoveryProtocol.new(conf, privKey.data) result.wantedPeers = conf.maxPeers newSeq result.protocolStates, allProtocols.len