From db295501e23fe2c81adb48ffa60c6a09f453b77b Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Fri, 29 Mar 2024 18:01:09 -0600 Subject: [PATCH] enabling holepunching and other libp2p goodies --- codex/codex.nim | 77 +++++++++++++++++++++++++++++++++------ codex/conf.nim | 4 ++ codex/utils/addrutils.nim | 7 ++-- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/codex/codex.nim b/codex/codex.nim index d8edc38e..fb023334 100644 --- a/codex/codex.nim +++ b/codex/codex.nim @@ -16,6 +16,10 @@ import std/cpuinfo import pkg/chronos import pkg/presto import pkg/libp2p +import pkg/libp2p/protocols/connectivity/autonat/client +import pkg/libp2p/protocols/connectivity/autonat/service +import pkg/libp2p/protocols/connectivity/relay/client +import pkg/libp2p/services/[autorelayservice, hpservice] import pkg/confutils import pkg/confutils/defs import pkg/nitro @@ -196,24 +200,73 @@ proc stop*(s: CodexServer) {.async.} = s.repoStore.stop(), s.maintenance.stop()) +proc getAutonatService*(rng: ref HmacDrbgContext): AutonatService = + ## AutonatService request other peers to dial us back + ## flagging us as Reachable or NotReachable. + ## minConfidence is used as threshold to determine the state. + ## If maxQueueSize > numPeersToAsk past samples are considered + ## in the calculation. + ## + + let + autonatService = AutonatService.new( + autonatClient = AutonatClient.new(), + rng = rng, + scheduleInterval = Opt.some(chronos.seconds(120)), + askNewConnectedPeers = false, + numPeersToAsk = 3, + maxQueueSize = 3, + minConfidence = 0.7) + + proc statusAndConfidenceHandler( + networkReachability: NetworkReachability, + confidence: Opt[float]): Future[void] {.gcsafe, async.} = + if confidence.isSome(): + info "Peer reachability status", + networkReachability = networkReachability, confidence = confidence.get() + + autonatService.statusAndConfidenceHandler(statusAndConfidenceHandler) + + return autonatService + proc new*( T: type CodexServer, config: CodexConf, privateKey: CodexPrivateKey): CodexServer = ## create CodexServer including setting up datastore, repostore, etc + ## + + var + builder = SwitchBuilder.new() + .withPrivateKey(privateKey) + .withAddresses(config.listenAddrs) + .withRng(Rng.instance()) + .withNoise() + .withYamux() + .withMplex(5.minutes, 5.minutes) + .withMaxConnections(config.maxPeers) + .withAgentVersion(config.agentString) + .withSignedPeerRecord(true) + .withTcpTransport({ServerFlags.ReuseAddr}) + .withAutonat() + .withRendezVous() + # .withObservedAddrManager() + + builder = if config.lpRelay: + builder.withCircuitRelay() + else: + let + relayClient = RelayClient.new() + autoRelayService = AutoRelayService.new(1, relayClient, nil, Rng.instance()) + autonatService = getAutonatService(Rng.instance()) + hpservice = HPService.new(autonatService, autoRelayService) + + builder + .withCircuitRelay(relayClient) + .withServices(@[Service(hpservice)]) + let - switch = SwitchBuilder - .new() - .withPrivateKey(privateKey) - .withAddresses(config.listenAddrs) - .withRng(Rng.instance()) - .withNoise() - .withMplex(5.minutes, 5.minutes) - .withMaxConnections(config.maxPeers) - .withAgentVersion(config.agentString) - .withSignedPeerRecord(true) - .withTcpTransport({ServerFlags.ReuseAddr}) - .build() + switch = builder.build var cache: CacheStore = nil diff --git a/codex/conf.nim b/codex/conf.nim index 8ec99041..c9cc287e 100644 --- a/codex/conf.nim +++ b/codex/conf.nim @@ -166,6 +166,10 @@ type abbr: "b" name: "bootstrap-node" }: seq[SignedPeerRecord] + lpRelay* {. + desc: "Should this node be a circuit relay" + name: "libp2p-relay" }: bool + maxPeers* {. desc: "The maximum number of peers to connect to" defaultValue: 160 diff --git a/codex/utils/addrutils.nim b/codex/utils/addrutils.nim index f044581a..6ae00e39 100644 --- a/codex/utils/addrutils.nim +++ b/codex/utils/addrutils.nim @@ -17,10 +17,9 @@ import pkg/libp2p import pkg/stew/shims/net func remapAddr*( - address: MultiAddress, - ip: Option[ValidIpAddress] = ValidIpAddress.none, - port: Option[Port] = Port.none -): MultiAddress = + address: MultiAddress, + ip: Option[ValidIpAddress] = ValidIpAddress.none, + port: Option[Port] = Port.none): MultiAddress = ## Remap addresses to new IP and/or Port ##