Skip to content

Commit

Permalink
chore: Circuit relay (#3112)
Browse files Browse the repository at this point in the history
* undo apt install libpcre (not circuit-relay related.)
* nat.nim: protect against possible exceptions when calling getExternalIP
* new external CLI argument, isRelayClient
* waku factory change to mount circuit hop proto by default
* waku_node: move autonat_service to a separate module
  • Loading branch information
Ivansete-status authored Oct 28, 2024
1 parent 268e7e6 commit cfde7ee
Show file tree
Hide file tree
Showing 22 changed files with 304 additions and 117 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ jobs:
run: |
postgres_enabled=0
if [ ${{ runner.os }} == "Linux" ]; then
sudo apt-get update
sudo apt-get install -y libpcre3 libpcre3-dev
sudo docker run --rm -d -e POSTGRES_PASSWORD=test123 -p 5432:5432 postgres:15.4-alpine3.18
postgres_enabled=1
fi
Expand Down
2 changes: 1 addition & 1 deletion apps/liteprotocoltester/liteprotocoltester.nim
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ when isMainModule:
error "Starting esential REST server failed.", error = $error
quit(QuitFailure)

var wakuApp = Waku.init(wakuConf).valueOr:
var wakuApp = Waku.new(wakuConf).valueOr:
error "Waku initialization failed", error = error
quit(QuitFailure)

Expand Down
4 changes: 2 additions & 2 deletions apps/wakunode2/wakunode2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ when isMainModule:
error "failure while loading the configuration", error = error
quit(QuitFailure)

## Also called within Waku.init. The call to startRestServerEsentials needs the following line
## Also called within Waku.new. The call to startRestServerEsentials needs the following line
logging.setupLog(conf.logLevel, conf.logFormat)

case conf.cmd
Expand All @@ -66,7 +66,7 @@ when isMainModule:
error "Starting esential REST server failed.", error = $error
quit(QuitFailure)

var waku = Waku.init(confCopy).valueOr:
var waku = Waku.new(confCopy).valueOr:
error "Waku initialization failed", error = error
quit(QuitFailure)

Expand Down
2 changes: 1 addition & 1 deletion examples/wakustealthcommitments/node_spec.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ proc setup*(): Waku =
conf.rlnRelay = twnClusterConf.rlnRelay

debug "Starting node"
var waku = Waku.init(conf).valueOr:
var waku = Waku.new(conf).valueOr:
error "Waku initialization failed", error = error
quit(QuitFailure)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ proc createWaku(configJson: cstring): Future[Result[Waku, string]] {.async.} =
formattedString & ". expected type: " & $typeof(confValue)
)

let wakuRes = Waku.init(conf).valueOr:
let wakuRes = Waku.new(conf).valueOr:
error "waku initialization failed", error = error
return err("Failed setting up Waku: " & $error)

Expand Down
10 changes: 5 additions & 5 deletions tests/factory/test_node_factory.nim
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{.used.}

import testutils/unittests, chronos
import testutils/unittests, chronos, libp2p/protocols/connectivity/relay/relay

import ../testlib/wakunode, waku/factory/node_factory, waku/waku_node

suite "Node Factory":
test "Set up a node based on default configurations":
let conf = defaultTestWakuNodeConf()

let node = setupNode(conf).valueOr:
let node = setupNode(conf, relay = Relay.new()).valueOr:
raiseAssert error

check:
Expand All @@ -23,7 +23,7 @@ suite "Node Factory":
var conf = defaultTestWakuNodeConf()
conf.store = true

let node = setupNode(conf).valueOr:
let node = setupNode(conf, relay = Relay.new()).valueOr:
raiseAssert error

check:
Expand All @@ -35,7 +35,7 @@ test "Set up a node with Filter enabled":
var conf = defaultTestWakuNodeConf()
conf.filter = true

let node = setupNode(conf).valueOr:
let node = setupNode(conf, relay = Relay.new()).valueOr:
raiseAssert error

check:
Expand All @@ -45,7 +45,7 @@ test "Set up a node with Filter enabled":
test "Start a node based on default configurations":
let conf = defaultTestWakuNodeConf()

let node = setupNode(conf).valueOr:
let node = setupNode(conf, relay = Relay.new()).valueOr:
raiseAssert error

assert not node.isNil(), "Node can't be nil"
Expand Down
20 changes: 5 additions & 15 deletions tests/test_peer_manager.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{.used.}

import
std/[options, sequtils, times, sugar],
std/[options, sequtils, times, sugar, net],
stew/shims/net as stewNet,
testutils/unittests,
chronos,
Expand Down Expand Up @@ -269,14 +269,9 @@ procSuite "Peer Manager":
database = SqliteDatabase.new(":memory:")[]
storage = WakuPeerStorage.new(database)[]
node1 = newTestWakuNode(
generateSecp256k1Key(),
ValidIpAddress.init("127.0.0.1"),
Port(44048),
peerStorage = storage,
)
node2 = newTestWakuNode(
generateSecp256k1Key(), ValidIpAddress.init("127.0.0.1"), Port(34023)
generateSecp256k1Key(), getPrimaryIPAddr(), Port(44048), peerStorage = storage
)
node2 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(34023))

node1.mountMetadata(0).expect("Mounted Waku Metadata")
node2.mountMetadata(0).expect("Mounted Waku Metadata")
Expand Down Expand Up @@ -344,14 +339,9 @@ procSuite "Peer Manager":
database = SqliteDatabase.new(":memory:")[]
storage = WakuPeerStorage.new(database)[]
node1 = newTestWakuNode(
generateSecp256k1Key(),
ValidIpAddress.init("127.0.0.1"),
Port(44048),
peerStorage = storage,
)
node2 = newTestWakuNode(
generateSecp256k1Key(), ValidIpAddress.init("127.0.0.1"), Port(34023)
generateSecp256k1Key(), getPrimaryIPAddr(), Port(44048), peerStorage = storage
)
node2 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(34023))

node1.mountMetadata(0).expect("Mounted Waku Metadata")
node2.mountMetadata(0).expect("Mounted Waku Metadata")
Expand Down
4 changes: 2 additions & 2 deletions tests/test_waku_switch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ suite "Waku Switch":
## Given
let
sourceSwitch = newTestSwitch()
wakuSwitch = newWakuSwitch(rng = rng())
wakuSwitch = newWakuSwitch(rng = rng(), circuitRelay = Relay.new())
await sourceSwitch.start()
await wakuSwitch.start()

Expand All @@ -46,7 +46,7 @@ suite "Waku Switch":
asyncTest "Waku Switch acts as circuit relayer":
## Setup
let
wakuSwitch = newWakuSwitch(rng = rng())
wakuSwitch = newWakuSwitch(rng = rng(), circuitRelay = Relay.new())
sourceClient = RelayClient.new()
destClient = RelayClient.new()
sourceSwitch = newCircuitRelayClientSwitch(sourceClient)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_wakunode.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{.used.}

import
std/[sequtils, strutils],
std/[sequtils, strutils, net],
stew/byteutils,
stew/shims/net as stewNet,
testutils/unittests,
Expand Down Expand Up @@ -169,7 +169,7 @@ suite "WakuNode":
nodeKey = generateSecp256k1Key()
bindIp = parseIpAddress("0.0.0.0")
bindPort = Port(61006)
extIp = some(parseIpAddress("127.0.0.1"))
extIp = some(getPrimaryIPAddr())
extPort = some(Port(61008))
node = newTestWakuNode(nodeKey, bindIp, bindPort, extIp, extPort)

Expand Down Expand Up @@ -205,7 +205,7 @@ suite "WakuNode":
nodeKey = generateSecp256k1Key()
bindIp = parseIpAddress("0.0.0.0")
bindPort = Port(61010)
extIp = some(parseIpAddress("127.0.0.1"))
extIp = some(getPrimaryIPAddr())
extPort = some(Port(61012))
domainName = "example.com"
expectedDns4Addr =
Expand Down
8 changes: 4 additions & 4 deletions tests/wakunode2/test_app.nim
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ suite "Wakunode2 - Waku":
## Given
var conf = defaultTestWakuNodeConf()

let waku = Waku.init(conf).valueOr:
let waku = Waku.new(conf).valueOr:
raiseAssert error

## When
Expand All @@ -35,7 +35,7 @@ suite "Wakunode2 - Waku initialization":
var conf = defaultTestWakuNodeConf()
conf.peerPersistence = true

let waku = Waku.init(conf).valueOr:
let waku = Waku.new(conf).valueOr:
raiseAssert error

check:
Expand All @@ -46,7 +46,7 @@ suite "Wakunode2 - Waku initialization":
var conf = defaultTestWakuNodeConf()

## When
var waku = Waku.init(conf).valueOr:
var waku = Waku.new(conf).valueOr:
raiseAssert error

(waitFor startWaku(addr waku)).isOkOr:
Expand All @@ -73,7 +73,7 @@ suite "Wakunode2 - Waku initialization":
conf.tcpPort = Port(0)

## When
var waku = Waku.init(conf).valueOr:
var waku = Waku.new(conf).valueOr:
raiseAssert error

(waitFor startWaku(addr waku)).isOkOr:
Expand Down
11 changes: 4 additions & 7 deletions tests/wakunode_rest/test_rest_admin.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{.used.}

import
std/[sequtils, strformat],
std/[sequtils, strformat, net],
stew/shims/net,
testutils/unittests,
presto,
Expand Down Expand Up @@ -38,12 +38,9 @@ suite "Waku v2 Rest API - Admin":
var client {.threadvar.}: RestClientRef

asyncSetup:
node1 =
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("127.0.0.1"), Port(60600))
node2 =
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("127.0.0.1"), Port(60602))
node3 =
newTestWakuNode(generateSecp256k1Key(), parseIpAddress("127.0.0.1"), Port(60604))
node1 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60600))
node2 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60602))
node3 = newTestWakuNode(generateSecp256k1Key(), getPrimaryIPAddr(), Port(60604))

await allFutures(node1.start(), node2.start(), node3.start())
await allFutures(
Expand Down
7 changes: 6 additions & 1 deletion waku/common/utils/nat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ proc setupNat*(
warn "NAT already initialized, skipping as cannot be done multiple times"
else:
singletonNat = true
let extIp = getExternalIP(strategy)
var extIp = none(IpAddress)
try:
extIp = getExternalIP(strategy)
except Exception:
warn "exception in setupNat", error = getCurrentExceptionMsg()

if extIP.isSome():
endpoint.ip = some(extIp.get())
# RedirectPorts in considered a gcsafety violation
Expand Down
36 changes: 36 additions & 0 deletions waku/discovery/autonat_service.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import
chronos,
chronicles,
bearssl/rand,
libp2p/protocols/connectivity/autonat/client,
libp2p/protocols/connectivity/autonat/service,
libp2p/protocols/connectivity/autonat/core

const AutonatCheckInterval = Opt.some(chronos.seconds(30))

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 = AutonatCheckInterval,
askNewConnectedPeers = false,
numPeersToAsk = 3,
maxQueueSize = 3,
minConfidence = 0.7,
)

proc statusAndConfidenceHandler(
networkReachability: NetworkReachability, confidence: Opt[float]
): Future[void] {.async.} =
if confidence.isSome():
info "Peer reachability status",
networkReachability = networkReachability, confidence = confidence.get()

autonatService.statusAndConfidenceHandler(statusAndConfidenceHandler)

return autonatService
20 changes: 18 additions & 2 deletions waku/discovery/waku_discv5.nim
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ proc new*(
topicSubscriptionQueue: queue,
)

proc updateAnnouncedMultiAddress*(
wd: WakuDiscoveryV5, addresses: seq[MultiAddress]
): Result[void, string] =
let encodedAddrs = multiaddr.encodeMultiaddrs(addresses)

wd.protocol.updateRecord([(MultiaddrEnrField, encodedAddrs)]).isOkOr:
return err("failed to update multiaddress in ENR: " & $error)

debug "ENR updated successfully with new multiaddress",
enrUri = wd.protocol.localNode.record.toUri(), enr = $(wd.protocol.localNode.record)

return ok()

proc updateENRShards(
wd: WakuDiscoveryV5, newTopics: seq[PubsubTopic], add: bool
): Result[void, string] =
Expand Down Expand Up @@ -286,7 +299,9 @@ proc subscriptionsListener(wd: WakuDiscoveryV5) {.async.} =
if subRes.isErr() and unsubRes.isErr():
continue

debug "ENR updated successfully"
debug "ENR updated successfully",
enrUri = wd.protocol.localNode.record.toUri(),
enr = $(wd.protocol.localNode.record)

wd.predicate =
shardingPredicate(wd.protocol.localNode.record, wd.protocol.bootstrapRecords)
Expand Down Expand Up @@ -314,7 +329,8 @@ proc start*(wd: WakuDiscoveryV5): Future[Result[void, string]] {.async: (raises:
asyncSpawn wd.subscriptionsListener()

debug "Successfully started discovery v5 service"
info "Discv5: discoverable ENR ", enr = wd.protocol.localNode.record.toUri()
info "Discv5: discoverable ENR ",
enrUri = wd.protocol.localNode.record.toUri(), enr = $(wd.protocol.localNode.record)

ok()

Expand Down
16 changes: 14 additions & 2 deletions waku/factory/builder.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import
libp2p/crypto/crypto,
libp2p/builders,
libp2p/nameresolving/nameresolver,
libp2p/transports/wstransport
libp2p/transports/wstransport,
libp2p/protocols/connectivity/relay/client,
libp2p/protocols/connectivity/relay/relay
import
../waku_enr,
../discovery/waku_discv5,
Expand Down Expand Up @@ -38,6 +40,7 @@ type
switchSslSecureKey: Option[string]
switchSslSecureCert: Option[string]
switchSendSignedPeerRecord: Option[bool]
circuitRelay: Relay

#Rate limit configs for non-relay req-resp protocols
rateLimitSettings: Option[seq[string]]
Expand Down Expand Up @@ -116,6 +119,9 @@ proc withColocationLimit*(builder: var WakuNodeBuilder, colocationLimit: int) =
proc withRateLimit*(builder: var WakuNodeBuilder, limits: seq[string]) =
builder.rateLimitSettings = some(limits)

proc withCircuitRelay*(builder: var WakuNodeBuilder, circuitRelay: Relay) =
builder.circuitRelay = circuitRelay

## Waku switch

proc withSwitchConfiguration*(
Expand Down Expand Up @@ -154,6 +160,12 @@ proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
if builder.record.isNone():
return err("node record is required")

let circuitRelay =
if builder.circuitRelay.isNil():
Relay.new()
else:
builder.circuitRelay

var switch: Switch
try:
switch = newWakuSwitch(
Expand All @@ -170,7 +182,7 @@ proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
sendSignedPeerRecord = builder.switchSendSignedPeerRecord.get(false),
agentString = builder.switchAgentString,
peerStoreCapacity = builder.peerStorageCapacity,
services = @[Service(getAutonatService(rng))],
circuitRelay = circuitRelay,
)
except CatchableError:
return err("failed to create switch: " & getCurrentExceptionMsg())
Expand Down
Loading

0 comments on commit cfde7ee

Please sign in to comment.