diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index 785337034..824b41ed4 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -128,6 +128,7 @@ proc getStateFromSnapshot(conf: BeaconNodeConf, state: var BeaconState): bool = proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async.} = let netKeys = getPersistentNetKeys(conf) + ourPubKey = netKeys.pubkey.skkey nickname = if conf.nodeName == "auto": shortForm(netKeys) else: conf.nodeName db = BeaconChainDB.init(kvStore LmdbStoreRef.init(conf.databaseDir)) @@ -183,14 +184,18 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async var bootNodes: seq[ENode] var bootEnrs: seq[enr.Record] - for node in conf.bootstrapNodes: addBootstrapNode(node, bootNodes, bootEnrs) - loadBootstrapFile(string conf.bootstrapNodesFile, bootNodes, bootEnrs) + for node in conf.bootstrapNodes: addBootstrapNode(node, bootNodes, bootEnrs, ourPubKey) + loadBootstrapFile(string conf.bootstrapNodesFile, bootNodes, bootEnrs, ourPubKey) + + when networkBackend == libp2pDaemon: + for enr in bootEnrs: + let enode = toENode(enr) + if enode.isOk: + bootNodes.add enode.value let persistentBootstrapFile = conf.dataDir / "bootstrap_nodes.txt" if fileExists(persistentBootstrapFile): - loadBootstrapFile(persistentBootstrapFile, bootNodes, bootEnrs) - - bootNodes = filterIt(bootNodes, it.pubkey != netKeys.pubkey.skkey) + loadBootstrapFile(persistentBootstrapFile, bootNodes, bootEnrs, ourPubKey) let network = await createEth2Node(conf, bootNodes) diff --git a/beacon_chain/eth2_discovery.nim b/beacon_chain/eth2_discovery.nim index 6ca451033..cad73ae02 100644 --- a/beacon_chain/eth2_discovery.nim +++ b/beacon_chain/eth2_discovery.nim @@ -9,6 +9,7 @@ import type Eth2DiscoveryProtocol* = protocol.Protocol Eth2DiscoveryId* = NodeId + PublicKey = keys.PublicKey export Eth2DiscoveryProtocol, open, start, close, result @@ -82,15 +83,22 @@ proc toENode*(enrRec: enr.Record): Result[ENode, cstring] = let ip = IpAddress(family: IpAddressFamily.IPv4, address_v4: toArray(4, ipBytes)) + tcpPort = Port enrRec.get("tcp", uint16) 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, udpPort: udpPort)) + address: Address(ip: ip, + tcpPort: tcpPort, + udpPort: udpPort)) except CatchableError: return err "Invalid ENR record" +# TODO +# This will be resoted to its more generalized form (returning ENode) +# once we refactor the discv5 code to be more easily bootstrapped with +# trusted, but non-signed bootstrap addresses. proc parseBootstrapAddress*(address: TaintedString): Result[enr.Record, cstring] = if address.len == 0: return err "an empty string is not a valid bootstrap node" @@ -127,27 +135,32 @@ proc parseBootstrapAddress*(address: TaintedString): Result[enr.Record, cstring] proc addBootstrapNode*(bootstrapAddr: string, bootNodes: var seq[ENode], - bootEnrs: var seq[enr.Record]) = - let enodeRes = parseBootstrapAddress(bootstrapAddr) - if enodeRes.isOk: - bootEnrs.add enodeRes.value + bootEnrs: var seq[enr.Record], + localPubKey: PublicKey) = + let enrRes = parseBootstrapAddress(bootstrapAddr) + if enrRes.isOk: + let enodeRes = enrRes.value.toENode + if enodeRes.isOk: + if enodeRes.value.pubKey != localPubKey: + bootEnrs.add enrRes.value else: warn "Ignoring invalid bootstrap address", - bootstrapAddr, reason = enodeRes.error + bootstrapAddr, reason = enrRes.error proc loadBootstrapFile*(bootstrapFile: string, bootNodes: var seq[ENode], - bootEnrs: var seq[enr.Record]) = + bootEnrs: var seq[enr.Record], + localPubKey: PublicKey) = if bootstrapFile.len == 0: return let ext = splitFile(bootstrapFile).ext if cmpIgnoreCase(ext, ".txt") == 0: for ln in lines(bootstrapFile): - addBootstrapNode(ln, bootNodes, bootEnrs) + addBootstrapNode(ln, bootNodes, bootEnrs, localPubKey) elif cmpIgnoreCase(ext, ".yaml") == 0: # TODO. This is very ugly, but let's try to negotiate the # removal of YAML metadata. for ln in lines(bootstrapFile): - addBootstrapNode(string(ln[3..^2]), bootNodes, bootEnrs) + addBootstrapNode(string(ln[3..^2]), bootNodes, bootEnrs, localPubKey) else: error "Unknown bootstrap file format", ext quit 1 diff --git a/beacon_chain/eth2_network.nim b/beacon_chain/eth2_network.nim index 6acf55973..5d4ba9ba1 100644 --- a/beacon_chain/eth2_network.nim +++ b/beacon_chain/eth2_network.nim @@ -203,12 +203,6 @@ when networkBackend in [libp2p, libp2pDaemon]: bootstrapEnrs: seq[enr.Record]) {.async.} = when networkBackend == libp2pDaemon: var connected = false - var bootstrapNodes = bootstrapNodes - for enr in bootstrapEnrs: - let enode = toENode(enr) - if enode.isOk: - bootstrapNodes.add enode.value - for bootstrapNode in bootstrapNodes: try: let peerInfo = toPeerInfo(bootstrapNode) @@ -233,11 +227,10 @@ when networkBackend in [libp2p, libp2pDaemon]: node.addKnownPeer bootstrapNode await node.start() - when false: - await sleepAsync(10.seconds) - if libp2p_successful_dials.value == 0: - fatal "Failed to connect to any bootstrap node. Quitting", bootstrapEnrs - quit 1 + await sleepAsync(10.seconds) + if bootstrapEnrs.len > 0 and libp2p_successful_dials.value == 0: + fatal "Failed to connect to any bootstrap node. Quitting", bootstrapEnrs + quit 1 proc saveConnectionAddressFile*(node: Eth2Node, filename: string) = when networkBackend == libp2p: diff --git a/vendor/nim-eth b/vendor/nim-eth index 9d7fc76c7..5ca1a21ec 160000 --- a/vendor/nim-eth +++ b/vendor/nim-eth @@ -1 +1 @@ -Subproject commit 9d7fc76c7a7b713dd509e88ba075b928749e51b2 +Subproject commit 5ca1a21ecdcb63de71c40f30f5b5d22eb7e344f5