Merge 5ec18fb4735a822c8f39e1ccb96415895bdb6281 into 27ae07adaaea7beeae02cea9f8647b18cd9fb482

This commit is contained in:
Simon-Pierre Vivier 2026-05-07 18:43:24 +00:00 committed by GitHub
commit 7a29fb9b26
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
68 changed files with 1322 additions and 1363 deletions

View File

@ -240,6 +240,10 @@ chat2mix: | $(NIMBLEDEPS_STAMP) build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble chat2mix
chat2disco: | $(NIMBLEDEPS_STAMP) build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble chat2disco
rln-db-inspector: | $(NIMBLEDEPS_STAMP) build deps librln
echo -e $(BUILD_MSG) "build/$@" && \
nimble rln_db_inspector

View File

@ -12,7 +12,7 @@ import
chronicles,
chronos,
eth/keys,
bearssl,
stew/[byteutils, results],
metrics,
metrics/chronos_httpserver
@ -301,7 +301,7 @@ proc readInput(wfd: AsyncFD) {.thread, raises: [Defect, CatchableError].} =
{.pop.}
# @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError
proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
let
transp = fromPipe(rfd)
conf = Chat2Conf.load()
@ -309,7 +309,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
if conf.nodekey.isSome():
conf.nodekey.get()
else:
PrivateKey.random(Secp256k1, rng[]).tryGet()
PrivateKey.random(Secp256k1, rng).tryGet()
# set log level
if conf.logLevel != LogLevel.NONE:
@ -564,7 +564,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
runForever()
proc main(rng: ref HmacDrbgContext) {.async.} =
proc main(rng: crypto.Rng) {.async.} =
let (rfd, wfd) = createAsyncPipe()
if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe:
raise newException(ValueError, "Could not initialize pipe!")

View File

@ -0,0 +1,438 @@
## chat2disco is an example of usage of Waku v2 with Kademlia service discovery.
## Users create named chat rooms; the app derives a service ID from the room name,
## advertises via Kademlia, and discovers/connects to other peers with the same service.
when not (compileOption("threads")):
{.fatal: "Please, compile this program with the --threads:on option!".}
{.push raises: [].}
import std/[strformat, strutils, times, options, sequtils, tables]
import
confutils,
chronicles,
chronos,
eth/keys,
stew/byteutils,
results,
metrics,
metrics/chronos_httpserver
import
libp2p/[
switch,
crypto/crypto,
stream/connection,
multiaddress,
peerinfo,
peerid,
protobuf/minprotobuf,
extended_peer_record,
]
import
waku/[
waku_core,
waku_enr,
discovery/waku_kademlia,
waku_node,
node/waku_metrics,
node/peer_manager,
factory/builder,
common/utils/nat,
waku_relay,
],
./config_chat2disco
import libp2p/protocols/pubsub/rpc/messages, libp2p/protocols/pubsub/pubsub
import libp2p/protocols/service_discovery/types
logScope:
topics = "chat2disco"
const Help = """
Commands: /[?|help|create|rooms|switch|nick|exit]
help: Prints this help
create <room>: Create/join a chat room via service discovery
rooms: List joined rooms
switch <room>: Switch active room for sending messages
nick: change nickname
exit: exits chat session
"""
type
ChatRoom = object
serviceId*: string
contentTopic*: string
discovered*: seq[RemotePeerInfo]
Chat = ref object
node: WakuNode
transp: StreamTransport
subscribed: bool
started: bool
nick: string
prompt: bool
rooms: Table[string, ChatRoom]
currentRoom: string
PrivateKey* = crypto.PrivateKey
Topic* = waku_core.PubsubTopic
#####################
## chat2 protobufs ##
#####################
type
SelectResult*[T] = Result[T, string]
Chat2Message* = object
timestamp*: int64
nick*: string
payload*: seq[byte]
proc init*(T: type Chat2Message, buffer: seq[byte]): ProtoResult[T] =
var msg = Chat2Message()
let pb = initProtoBuffer(buffer)
var timestamp: uint64
discard ?pb.getField(1, timestamp)
msg.timestamp = int64(timestamp)
discard ?pb.getField(2, msg.nick)
discard ?pb.getField(3, msg.payload)
ok(msg)
proc encode*(message: Chat2Message): ProtoBuffer =
var serialised = initProtoBuffer()
serialised.write(1, uint64(message.timestamp))
serialised.write(2, message.nick)
serialised.write(3, message.payload)
return serialised
proc toString*(message: Chat2Message): string =
let time = message.timestamp.fromUnix().local().format("'<'MMM' 'dd,' 'HH:mm'>'")
return time & " " & message.nick & ": " & string.fromBytes(message.payload)
#####################
proc showChatPrompt(c: Chat) =
if not c.prompt:
try:
stdout.write(">> ")
stdout.flushFile()
c.prompt = true
except IOError:
discard
proc getChatLine(payload: seq[byte]): string =
let pb = Chat2Message.init(payload).valueOr:
return string.fromBytes(payload)
return $pb
proc readNick(transp: StreamTransport): Future[string] {.async.} =
stdout.write("Choose a nickname >> ")
stdout.flushFile()
return await transp.readLine()
proc startMetricsServer(
serverIp: IpAddress, serverPort: Port
): Result[MetricsHttpServerRef, string] =
info "Starting metrics HTTP server", serverIp = $serverIp, serverPort = $serverPort
let server = MetricsHttpServerRef.new($serverIp, serverPort).valueOr:
return err("metrics HTTP server start failed: " & $error)
try:
waitFor server.start()
except CatchableError:
return err("metrics HTTP server start failed: " & getCurrentExceptionMsg())
info "Metrics HTTP server started", serverIp = $serverIp, serverPort = $serverPort
ok(server)
proc publish(c: Chat, line: string) =
let time = getTime().toUnix()
let chat2pb =
Chat2Message(timestamp: time, nick: c.nick, payload: line.toBytes()).encode()
let room =
try:
c.rooms[c.currentRoom]
except KeyError:
error "current room not found in rooms table", room = c.currentRoom
return
var message = WakuMessage(
payload: chat2pb.buffer,
contentTopic: room.contentTopic,
version: 0,
timestamp: getNanosecondTime(time),
)
try:
(waitFor c.node.publish(some(DefaultPubsubTopic), message)).isOkOr:
error "failed to publish message", error = error
except CatchableError:
error "caught error publishing message: ", error = getCurrentExceptionMsg()
# TODO This should read or be subscribe handler subscribe
proc readAndPrint(c: Chat) {.async.} =
while true:
await sleepAsync(100.millis)
# TODO Implement
proc writeAndPrint(c: Chat) {.async.} =
while true:
showChatPrompt(c)
let line = await c.transp.readLine()
if line.startsWith("/help") or line.startsWith("/?") or not c.started:
echo Help
continue
elif line.startsWith("/create"):
let roomName = line[7 ..^ 1].strip()
if roomName.len == 0:
echo "Usage: /create <room-name>"
continue
if roomName in c.rooms:
echo &"Already in room '{roomName}'. Use /switch {roomName} to make it active."
continue
let serviceIdStr = "/waku/chat-room/" & roomName & "/1.0.0"
let contentTopic = "/chat2disco/1/" & roomName & "/proto"
let serviceInfo = ServiceInfo(id: serviceIdStr, data: @[])
if not c.node.wakuKademlia.isNil():
c.node.wakuKademlia.advertiseService(serviceInfo)
echo &"Advertising service: {serviceIdStr}"
let peers = await c.node.wakuKademlia.lookup(serviceIdStr)
echo &"Discovered {peers.len} peer(s) for room '{roomName}'"
if peers.len > 0:
await c.node.connectToNodes(peers)
echo "Connected to discovered peers"
c.rooms[roomName] = ChatRoom(
serviceId: serviceIdStr, contentTopic: contentTopic, discovered: peers
)
else:
echo "Warning: Kademlia not available. Room created locally only."
c.rooms[roomName] =
ChatRoom(serviceId: serviceIdStr, contentTopic: contentTopic, discovered: @[])
c.currentRoom = roomName
echo &"Created/joined room '{roomName}'. Content topic: {contentTopic}"
elif line.startsWith("/rooms"):
if c.rooms.len == 0:
echo "No rooms joined yet. Use /create <room-name> to create one."
else:
echo "Joined rooms:"
for name, room in c.rooms:
let marker = if name == c.currentRoom: " *" else: ""
echo &" {name} ({room.discovered.len} peers){marker}"
elif line.startsWith("/switch"):
let roomName = line[7 ..^ 1].strip()
if roomName.len == 0:
echo "Usage: /switch <room-name>"
continue
if roomName notin c.rooms:
echo &"Room '{roomName}' not found. Use /create {roomName} to create it."
continue
c.currentRoom = roomName
echo &"Switched to room '{roomName}'"
elif line.startsWith("/nick"):
c.nick = await readNick(c.transp)
echo "You are now known as " & c.nick
elif line.startsWith("/exit"):
echo "quitting..."
try:
await c.node.stop()
except:
echo "exception happened when stopping: " & getCurrentExceptionMsg()
quit(QuitSuccess)
else:
if c.started:
if c.rooms.len == 0:
echo "No room active. Use /create <room-name> first."
else:
c.publish(line)
else:
try:
if line.startsWith("/") and "p2p" in line:
await c.node.connectToNodes(@[line])
except:
echo &"unable to dial remote peer {line}"
echo getCurrentExceptionMsg()
proc readWriteLoop(c: Chat) {.async.} =
asyncSpawn c.writeAndPrint()
asyncSpawn c.readAndPrint()
proc readInput(wfd: AsyncFD) {.thread, raises: [Defect, CatchableError].} =
let transp = fromPipe(wfd)
while true:
let line = stdin.readLine()
discard waitFor transp.write(line & "\r\n")
{.pop.}
proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
let
transp = fromPipe(rfd)
conf = Chat2DiscoConf.load()
nodekey =
if conf.nodekey.isSome():
conf.nodekey.get()
else:
PrivateKey.random(Secp256k1, rng).tryGet()
# set log level
if conf.logLevel != LogLevel.NONE:
setLogLevel(conf.logLevel)
let (extIp, extTcpPort, extUdpPort) = setupNat(
conf.nat,
clientId,
Port(uint16(conf.tcpPort) + conf.portsShift),
Port(uint16(conf.udpPort) + conf.portsShift),
).valueOr:
raise newException(ValueError, "setupNat error " & error)
var enrBuilder = EnrBuilder.init(nodeKey)
let record = enrBuilder.build().valueOr:
error "failed to create enr record", error
quit(QuitFailure)
let node = block:
var builder = WakuNodeBuilder.init()
builder.withNodeKey(nodeKey)
builder.withRecord(record)
builder
.withNetworkConfigurationDetails(
conf.listenAddress,
Port(uint16(conf.tcpPort) + conf.portsShift),
extIp,
extTcpPort,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport,
)
.tryGet()
builder.build().tryGet()
if conf.relay:
(await node.mountRelay()).isOkOr:
error "failed to mount relay", error
quit(QuitFailure)
await node.mountLibp2pPing()
var kadBootstrapPeers: seq[(PeerId, seq[MultiAddress])] = @[]
if conf.kadBootstrapNodes.len > 0:
for nodeStr in conf.kadBootstrapNodes:
let (peerId, ma) = parseFullAddress(nodeStr).valueOr:
error "Failed to parse kademlia bootstrap node", node = nodeStr, error = error
continue
kadBootstrapPeers.add((peerId, @[ma]))
node.wakuKademlia = WakuKademlia.new(
switch = node.switch,
peerManager = node.peerManager,
bootstrapNodes = kadBootstrapPeers,
xprPublishing = false,
disableBootstrapping = true,
)
let catchRes = catch:
node.switch.mount(node.wakuKademlia.protocol)
if catchRes.isErr():
error "failed to mount kademlia discovery", error = catchRes.error.msg
quit(QuitFailure)
# node start include kademlia
await node.start()
let nick = await readNick(transp)
echo "Welcome, " & nick & "!"
var chat = Chat(
node: node,
transp: transp,
subscribed: true,
started: true,
nick: nick,
prompt: false,
)
let peerInfo = node.switch.peerInfo
let listenStr = $peerInfo.addrs[0] & "/p2p/" & $peerInfo.peerId
echo &"Listening on\n {listenStr}"
# Subscribe to relay topic
if conf.relay:
proc handler(topic: PubsubTopic, msg: WakuMessage): Future[void] {.async, gcsafe.} =
for roomName, room in chat.rooms:
if msg.contentTopic == room.contentTopic:
let chatLine = getChatLine(msg.payload)
let prefix =
if chat.rooms.len > 1:
"[" & roomName & "] "
else:
""
try:
echo &"{prefix}{chatLine}"
except ValueError:
echo prefix & chatLine
chat.prompt = false
showChatPrompt(chat)
break
node.subscribe(
(kind: PubsubSub, topic: DefaultPubsubTopic), WakuRelayHandler(handler)
).isOkOr:
error "failed to subscribe to pubsub topic",
topic = DefaultPubsubTopic, error = error
if conf.metricsLogging:
startMetricsLog()
if conf.metricsServer:
let metricsServer = startMetricsServer(
conf.metricsServerAddress, Port(conf.metricsServerPort + conf.portsShift)
)
await chat.readWriteLoop()
runForever()
proc main(rng: crypto.Rng) {.async.} =
let (rfd, wfd) = createAsyncPipe()
if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe:
raise newException(ValueError, "Could not initialize pipe!")
var thread: Thread[AsyncFD]
thread.createThread(readInput, wfd)
try:
await processInput(rfd, rng)
except ConfigurationError as e:
raise e
when isMainModule:
let rng = crypto.newRng()
try:
waitFor(main(rng))
except CatchableError as e:
raise e

View File

@ -0,0 +1,156 @@
import
chronicles,
chronos,
confutils,
confutils/defs,
confutils/std/net,
eth/keys,
libp2p/crypto/crypto,
libp2p/crypto/secp,
nimcrypto/utils,
std/strutils
import waku/waku_core
const defaultMetricsAddress* = parseIpAddress("127.0.0.1")
type Chat2DiscoConf* = object ## General node config
logLevel* {.
desc: "Sets the log level.", defaultValue: LogLevel.INFO, name: "log-level"
.}: LogLevel
nodekey* {.desc: "P2P node private key as 64 char hex string.", name: "nodekey".}:
Option[crypto.PrivateKey]
listenAddress* {.
defaultValue: defaultListenAddress(config),
desc: "Listening address for the LibP2P traffic.",
name: "listen-address"
.}: IpAddress
tcpPort* {.desc: "TCP listening port.", defaultValue: 60000, name: "tcp-port".}: Port
udpPort* {.desc: "UDP listening port.", defaultValue: 60000, name: "udp-port".}: Port
portsShift* {.
desc: "Add a shift to all port numbers.", defaultValue: 0, name: "ports-shift"
.}: uint16
nat* {.
desc:
"Specify method to use for determining public address. " &
"Must be one of: any, none, upnp, pmp, extip:<IP>.",
defaultValue: "any"
.}: string
## Relay config
relay* {.
desc: "Enable relay protocol: true|false", defaultValue: true, name: "relay"
.}: bool
keepAlive* {.
desc: "Enable keep-alive for idle connections: true|false",
defaultValue: false,
name: "keep-alive"
.}: bool
clusterId* {.
desc:
"Cluster id that the node is running in. Node in a different cluster id is disconnected.",
defaultValue: 0,
name: "cluster-id"
.}: uint16
shards* {.
desc:
"Shards index to subscribe to [0..NUM_SHARDS_IN_NETWORK-1]. Argument may be repeated.",
defaultValue: @[uint16(0)],
name: "shard"
.}: seq[uint16]
## Metrics config
metricsServer* {.
desc: "Enable the metrics server: true|false",
defaultValue: false,
name: "metrics-server"
.}: bool
metricsServerAddress* {.
desc: "Listening address of the metrics server.",
defaultValue: defaultMetricsAddress,
name: "metrics-server-address"
.}: IpAddress
metricsServerPort* {.
desc: "Listening HTTP port of the metrics server.",
defaultValue: 8008,
name: "metrics-server-port"
.}: uint16
metricsLogging* {.
desc: "Enable metrics logging: true|false",
defaultValue: true,
name: "metrics-logging"
.}: bool
## Chat2 configuration
contentTopic* {.
desc: "Content topic for chat messages.",
defaultValue: "/chat2disco/1/default/proto",
name: "content-topic"
.}: string
## Websocket Configuration
websocketSupport* {.
desc: "Enable websocket: true|false",
defaultValue: false,
name: "websocket-support"
.}: bool
websocketPort* {.
desc: "WebSocket listening port.", defaultValue: 8000, name: "websocket-port"
.}: Port
websocketSecureSupport* {.
desc: "WebSocket Secure Support.",
defaultValue: false,
name: "websocket-secure-support"
.}: bool
## Kademlia Discovery config
kadBootstrapNodes* {.
desc:
"Peer multiaddr for kademlia discovery bootstrap node (must include /p2p/<peerID>). Argument may be repeated.",
name: "kad-bootstrap-node"
.}: seq[string]
# NOTE: Keys are different in nim-libp2p
proc parseCmdArg*(T: type crypto.PrivateKey, p: string): T =
try:
let key = SkPrivateKey.init(utils.fromHex(p)).tryGet()
result = crypto.PrivateKey(scheme: Secp256k1, skkey: key)
except CatchableError as e:
raise newException(ValueError, "Invalid private key")
proc completeCmdArg*(T: type crypto.PrivateKey, val: string): seq[string] =
return @[]
proc parseCmdArg*(T: type IpAddress, p: string): T =
try:
result = parseIpAddress(p)
except CatchableError as e:
raise newException(ValueError, "Invalid IP address")
proc completeCmdArg*(T: type IpAddress, val: string): seq[string] =
return @[]
proc parseCmdArg*(T: type Port, p: string): T =
try:
result = Port(parseInt(p))
except CatchableError as e:
raise newException(ValueError, "Invalid Port number")
proc completeCmdArg*(T: type Port, val: string): seq[string] =
return @[]
func defaultListenAddress*(conf: Chat2DiscoConf): IpAddress =
(static parseIpAddress("0.0.0.0"))

4
apps/chat2disco/nim.cfg Normal file
View File

@ -0,0 +1,4 @@
-d:chronicles_line_numbers
-d:chronicles_runtime_filtering:on
-d:discv5_protocol_id:d5waku
path = "../.."

View File

@ -12,7 +12,7 @@ import
chronicles,
chronos,
eth/keys,
bearssl,
results,
stew/[byteutils],
metrics,
@ -31,6 +31,7 @@ import
nameresolving/dnsresolver,
protocols/mix/curve25519,
protocols/mix/mix_protocol,
extended_peer_record,
] # define DNS resolution
import
waku/[
@ -48,6 +49,7 @@ import
waku_store/common,
waku_filter_v2/client,
common/logging,
waku_mix,
],
./config_chat2mix
@ -57,7 +59,8 @@ import ../../waku/waku_rln_relay
logScope:
topics = "chat2 mix"
const Help = """
const Help =
"""
Commands: /[?|help|connect|nick|exit]
help: Prints this help
connect: dials a remote peer
@ -388,7 +391,7 @@ proc maintainSubscription(
{.pop.}
# @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError
proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
proc processInput(rfd: AsyncFD, rng: crypto.Rng) {.async.} =
let
transp = fromPipe(rfd)
conf = Chat2Conf.load()
@ -396,7 +399,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
if conf.nodekey.isSome():
conf.nodekey.get()
else:
PrivateKey.random(Secp256k1, rng[]).tryGet()
PrivateKey.random(Secp256k1, rng).tryGet()
# set log level
if conf.logLevel != LogLevel.NONE:
@ -428,16 +431,16 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
builder.withRecord(record)
builder
.withNetworkConfigurationDetails(
conf.listenAddress,
Port(uint16(conf.tcpPort) + conf.portsShift),
extIp,
extTcpPort,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport,
)
.tryGet()
.withNetworkConfigurationDetails(
conf.listenAddress,
Port(uint16(conf.tcpPort) + conf.portsShift),
extIp,
extTcpPort,
wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift),
wsEnabled = conf.websocketSupport,
wssEnabled = conf.websocketSecureSupport,
)
.tryGet()
builder.build().tryGet()
node.mountAutoSharding(conf.clusterId, conf.numShardsInNetwork).isOkOr:
@ -447,15 +450,20 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
error "failed to mount waku metadata protocol: ", err = error
quit(QuitFailure)
var providedServices: seq[ServiceInfo] = @[]
let (mixPrivKey, mixPubKey) = generateKeyPair().valueOr:
error "failed to generate mix key pair", error = error
return
(await node.mountMix(conf.clusterId, mixPrivKey, conf.mixnodes)).isOkOr:
let mixService = ServiceInfo(id: MixProtocolID, data: @(mixPubKey))
providedServices.add(mixService)
(await node.mountMix(mixPrivKey)).isOkOr:
error "failed to mount waku mix protocol: ", error = $error
quit(QuitFailure)
# Setup extended kademlia discovery if bootstrap nodes are provided
# Setup kademlia discovery if bootstrap nodes are provided
if conf.kadBootstrapNodes.len > 0:
var kadBootstrapPeers: seq[(PeerId, seq[MultiAddress])]
for nodeStr in conf.kadBootstrapNodes:
@ -466,23 +474,8 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
if kadBootstrapPeers.len > 0:
node.wakuKademlia = WakuKademlia.new(
node.switch,
ExtendedKademliaDiscoveryParams(
bootstrapNodes: kadBootstrapPeers,
mixPubKey: some(mixPubKey),
advertiseMix: false,
),
node.peerManager,
getMixNodePoolSize = proc(): int {.gcsafe, raises: [].} =
if node.wakuMix.isNil():
0
else:
node.getMixNodePoolSize(),
isNodeStarted = proc(): bool {.gcsafe, raises: [].} =
node.started,
).valueOr:
error "failed to setup kademlia discovery", error = error
quit(QuitFailure)
node.switch, node.peerManager, kadBootstrapPeers, providedServices
)
#await node.mountRendezvousClient(conf.clusterId)
@ -490,9 +483,11 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
node.peerManager.start()
if not node.wakuKademlia.isNil():
(await node.wakuKademlia.start(minMixPeers = MinMixNodePoolSize)).isOkOr:
error "failed to start kademlia discovery", error = error
quit(QuitFailure)
await node.wakuKademlia.start()
# Wire mix protocol with kademlia for peer discovery
if not node.wakuMix.isNil() and not node.wakuKademlia.isNil():
node.wakuMix.setKademlia(node.wakuKademlia)
await node.mountLibp2pPing()
#await node.mountPeerExchangeClient()
@ -645,8 +640,8 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
currentpoolSize = node.getMixNodePoolSize()
echo "ready to publish messages now"
# Once min mixnodes are discovered loop as per default setting
node.startPeerExchangeLoop()
# Peer exchange disabled - using Kademlia discovery only
# node.startPeerExchangeLoop()
if conf.metricsLogging:
startMetricsLog()
@ -660,7 +655,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} =
runForever()
proc main(rng: ref HmacDrbgContext) {.async.} =
proc main(rng: crypto.Rng) {.async.} =
let (rfd, wfd) = createAsyncPipe()
if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe:
raise newException(ValueError, "Could not initialize pipe!")

View File

@ -85,12 +85,6 @@ type
defaultValue: @[]
.}: seq[string]
mixnodes* {.
desc:
"Multiaddress and mix-key of mix node to be statically specified in format multiaddr:mixPubKey. Argument may be repeated.",
name: "mixnode"
.}: seq[MixNodePubInfo]
keepAlive* {.
desc: "Enable keep-alive for idle connections: true|false",
defaultValue: false,
@ -236,23 +230,6 @@ type
name: "kad-bootstrap-node"
.}: seq[string]
proc parseCmdArg*(T: type MixNodePubInfo, p: string): T =
let elements = p.split(":")
if elements.len != 2:
raise newException(
ValueError, "Invalid format for mix node expected multiaddr:mixPublicKey"
)
let multiaddr = MultiAddress.init(elements[0]).valueOr:
raise newException(ValueError, "Invalid multiaddress format")
if not multiaddr.contains(multiCodec("ip4")).get():
raise newException(
ValueError, "Invalid format for ip address, expected a ipv4 multiaddress"
)
return MixNodePubInfo(
multiaddr: elements[0], pubKey: intoCurve25519Key(ncrutils.fromHex(elements[1]))
)
# NOTE: Keys are different in nim-libp2p
proc parseCmdArg*(T: type crypto.PrivateKey, p: string): T =
try:

View File

@ -423,7 +423,7 @@ proc initAndStartApp(
let
# some hardcoded parameters
rng = keys.newRng()
key = crypto.PrivateKey.random(Secp256k1, rng[])[]
key = crypto.PrivateKey.random(Secp256k1, rng)[]
nodeTcpPort = Port(60000)
nodeUdpPort = Port(9000)
flags = CapabilitiesBitfield.init(

View File

@ -159,7 +159,7 @@ proc pingNode(
error "Failed to ping the peer", peer = peerInfo, err = msg
return false
proc main(rng: ref HmacDrbgContext): Future[int] {.async.} =
proc main(rng: crypto.Rng): Future[int] {.async.} =
let conf: WakuCanaryConf = WakuCanaryConf.load()
# create dns resolver
@ -190,7 +190,7 @@ proc main(rng: ref HmacDrbgContext): Future[int] {.async.} =
quit(QuitFailure)
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
nodeKey = crypto.PrivateKey.random(Secp256k1, rng)[]
bindIp = parseIpAddress("0.0.0.0")
wsBindPort = Port(conf.nodePort + WebSocketPortOffset)
nodeTcpPort = Port(conf.nodePort)

View File

@ -5,6 +5,8 @@ if defined(release):
else:
switch("nimcache", "nimcache/debug/$projectName")
switch("passL", getCurrentDir() / "librln_v0.9.0.a")
if defined(windows):
switch("passL", "rln.lib")
switch("define", "postgres=false")
@ -90,6 +92,9 @@ if not defined(macosx) and not defined(android):
nimStackTraceOverride
switch("import", "libbacktrace")
# Shim to provide valueOr and withValue for Option[T]
switch("import", "waku/common/option_shim")
--define:
nimOldCaseObjects
# https://github.com/status-im/nim-confutils/issues/9
@ -118,6 +123,5 @@ if defined(android):
switch("cincludes", sysRoot & "/usr/include/")
# begin Nimble config (version 2)
when withDir(thisDir(), system.fileExists("nimble.paths")):
--noNimblePath
include "nimble.paths"
# end Nimble config

View File

@ -43,13 +43,13 @@ proc messagePushHandler(
contentTopic = message.contentTopic,
timestamp = message.timestamp
proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} =
proc setupAndSubscribe(rng: crypto.Rng) {.async.} =
# use notice to filter all waku messaging
setupLog(logging.LogLevel.NOTICE, logging.LogFormat.TEXT)
notice "starting subscriber", wakuPort = wakuPort
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
nodeKey = crypto.PrivateKey.random(Secp256k1, rng)[]
ip = parseIpAddress("0.0.0.0")
flags = CapabilitiesBitfield.init(relay = true)

View File

@ -7,8 +7,8 @@ import
confutils,
libp2p/crypto/crypto,
libp2p/crypto/curve25519,
libp2p/protocols/mix,
libp2p/protocols/mix/curve25519,
libp2p_mix,
libp2p_mix/curve25519,
libp2p/multiaddress,
eth/keys,
eth/p2p/discoveryv5/enr,
@ -48,13 +48,13 @@ proc splitPeerIdAndAddr(maddr: string): (string, string) =
peerId = parts[1]
return (address, peerId)
proc setupAndPublish(rng: ref HmacDrbgContext, conf: LightPushMixConf) {.async.} =
proc setupAndPublish(rng: crypto.Rng, conf: LightPushMixConf) {.async.} =
# use notice to filter all waku messaging
setupLog(logging.LogLevel.DEBUG, logging.LogFormat.TEXT)
notice "starting publisher", wakuPort = conf.port
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).get()
nodeKey = crypto.PrivateKey.random(Secp256k1, rng).get()
ip = parseIpAddress("0.0.0.0")
flags = CapabilitiesBitfield.init(relay = true)

View File

@ -35,13 +35,13 @@ const
LightpushPubsubTopic = PubsubTopic("/waku/2/rs/1/0")
LightpushContentTopic = ContentTopic("/examples/1/light-pubsub-example/proto")
proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} =
proc setupAndPublish(rng: crypto.Rng) {.async.} =
# use notice to filter all waku messaging
setupLog(logging.LogLevel.NOTICE, logging.LogFormat.TEXT)
notice "starting publisher", wakuPort = wakuPort
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).get()
nodeKey = crypto.PrivateKey.random(Secp256k1, rng).get()
ip = parseIpAddress("0.0.0.0")
flags = CapabilitiesBitfield.init(relay = true)

View File

@ -37,13 +37,13 @@ const bootstrapNode =
const wakuPort = 60000
const discv5Port = 9000
proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} =
proc setupAndPublish(rng: crypto.Rng) {.async.} =
# use notice to filter all waku messaging
setupLog(logging.LogLevel.NOTICE, logging.LogFormat.TEXT)
notice "starting publisher", wakuPort = wakuPort, discv5Port = discv5Port
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).get()
nodeKey = crypto.PrivateKey.random(Secp256k1, rng).get()
ip = parseIpAddress("0.0.0.0")
flags = CapabilitiesBitfield.init(relay = true)

View File

@ -35,13 +35,13 @@ const bootstrapNode =
const wakuPort = 50000
const discv5Port = 8000
proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} =
proc setupAndSubscribe(rng: crypto.Rng) {.async.} =
# use notice to filter all waku messaging
setupLog(logging.LogLevel.NOTICE, logging.LogFormat.TEXT)
notice "starting subscriber", wakuPort = wakuPort, discv5Port = discv5Port
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
nodeKey = crypto.PrivateKey.random(Secp256k1, rng)[]
ip = parseIpAddress("0.0.0.0")
flags = CapabilitiesBitfield.init(relay = true)

View File

@ -1,607 +0,0 @@
{
"version": 2,
"packages": {
"nim": {
"version": "2.2.4",
"vcsRevision": "911e0dbb1f76de61fa0215ab1bb85af5334cc9a8",
"url": "https://github.com/nim-lang/Nim.git",
"downloadMethod": "git",
"dependencies": [],
"checksums": {
"sha1": "68bb85cbfb1832ce4db43943911b046c3af3caab"
}
},
"unittest2": {
"version": "0.2.5",
"vcsRevision": "26f2ef3ae0ec72a2a75bfe557e02e88f6a31c189",
"url": "https://github.com/status-im/nim-unittest2",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "02bb3751ba9ddc3c17bfd89f2e41cb6bfb8fc0c9"
}
},
"bearssl": {
"version": "0.2.8",
"vcsRevision": "22c6a76ce015bc07e011562bdcfc51d9446c1e82",
"url": "https://github.com/status-im/nim-bearssl",
"downloadMethod": "git",
"dependencies": [
"nim",
"unittest2"
],
"checksums": {
"sha1": "da4dd7ae96d536bdaf42dca9c85d7aed024b6a86"
}
},
"bearssl_pkey_decoder": {
"version": "#21dd3710df9345ed2ad8bf8f882761e07863b8e0",
"vcsRevision": "21dd3710df9345ed2ad8bf8f882761e07863b8e0",
"url": "https://github.com/vacp2p/bearssl_pkey_decoder",
"downloadMethod": "git",
"dependencies": [
"nim",
"bearssl"
],
"checksums": {
"sha1": "21b42e2e6ddca6c875d3fc50f36a5115abf51714"
}
},
"jwt": {
"version": "#18f8378de52b241f321c1f9ea905456e89b95c6f",
"vcsRevision": "18f8378de52b241f321c1f9ea905456e89b95c6f",
"url": "https://github.com/vacp2p/nim-jwt.git",
"downloadMethod": "git",
"dependencies": [
"nim",
"bearssl",
"bearssl_pkey_decoder"
],
"checksums": {
"sha1": "bcfd6fc9c5e10a52b87117219b7ab5c98136bc8e"
}
},
"testutils": {
"version": "0.8.1",
"vcsRevision": "6ce5e5e2301ccbc04b09d27ff78741ff4d352b4d",
"url": "https://github.com/status-im/nim-testutils",
"downloadMethod": "git",
"dependencies": [
"nim",
"unittest2"
],
"checksums": {
"sha1": "96a11cf8b84fa9bd12d4a553afa1cc4b7f9df4e3"
}
},
"db_connector": {
"version": "0.1.0",
"vcsRevision": "29450a2063970712422e1ab857695c12d80112a6",
"url": "https://github.com/nim-lang/db_connector",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "4f2e67d0e4b61af9ac5575509305660b473f01a4"
}
},
"results": {
"version": "0.5.1",
"vcsRevision": "df8113dda4c2d74d460a8fa98252b0b771bf1f27",
"url": "https://github.com/arnetheduck/nim-results",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "a9c011f74bc9ed5c91103917b9f382b12e82a9e7"
}
},
"nat_traversal": {
"version": "0.0.1",
"vcsRevision": "860e18c37667b5dd005b94c63264560c35d88004",
"url": "https://github.com/status-im/nim-nat-traversal",
"downloadMethod": "git",
"dependencies": [
"nim",
"results"
],
"checksums": {
"sha1": "1a376d3e710590ef2c48748a546369755f0a7c97"
}
},
"stew": {
"version": "0.5.0",
"vcsRevision": "4382b18f04b3c43c8409bfcd6b62063773b2bbaa",
"url": "https://github.com/status-im/nim-stew",
"downloadMethod": "git",
"dependencies": [
"nim",
"results",
"unittest2"
],
"checksums": {
"sha1": "db22942939773ab7d5a0f2b2668c237240c67dd6"
}
},
"zlib": {
"version": "0.1.0",
"vcsRevision": "e680f269fb01af2c34a2ba879ff281795a5258fe",
"url": "https://github.com/status-im/nim-zlib",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"results"
],
"checksums": {
"sha1": "bbde4f5a97a84b450fef7d107461e5f35cf2b47f"
}
},
"httputils": {
"version": "0.4.1",
"vcsRevision": "f142cb2e8bd812dd002a6493b6082827bb248592",
"url": "https://github.com/status-im/nim-http-utils",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"results",
"unittest2"
],
"checksums": {
"sha1": "016774ab31c3afff9a423f7d80584905ee59c570"
}
},
"chronos": {
"version": "4.2.2",
"vcsRevision": "45f43a9ad8bd8bcf5903b42f365c1c879bd54240",
"url": "https://github.com/status-im/nim-chronos",
"downloadMethod": "git",
"dependencies": [
"nim",
"results",
"stew",
"bearssl",
"httputils",
"unittest2"
],
"checksums": {
"sha1": "3a4c9477df8cef20a04e4f1b54a2d74fdfc2a3d0"
}
},
"metrics": {
"version": "0.2.1",
"vcsRevision": "a1296caf3ebb5f30f51a5feae7749a30df2824c2",
"url": "https://github.com/status-im/nim-metrics",
"downloadMethod": "git",
"dependencies": [
"nim",
"chronos",
"results",
"stew"
],
"checksums": {
"sha1": "84bb09873d7677c06046f391c7b473cd2fcff8a2"
}
},
"faststreams": {
"version": "0.5.0",
"vcsRevision": "ce27581a3e881f782f482cb66dc5b07a02bd615e",
"url": "https://github.com/status-im/nim-faststreams",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"unittest2"
],
"checksums": {
"sha1": "ee61e507b805ae1df7ec936f03f2d101b0d72383"
}
},
"snappy": {
"version": "0.1.0",
"vcsRevision": "00bfcef94f8ef6981df5d5b994897f6695badfb2",
"url": "https://github.com/status-im/nim-snappy",
"downloadMethod": "git",
"dependencies": [
"nim",
"faststreams",
"unittest2",
"results",
"stew"
],
"checksums": {
"sha1": "e572d60d6a3178c5b1cde2400c51ad771812cd3d"
}
},
"serialization": {
"version": "0.5.2",
"vcsRevision": "b0f2fa32960ea532a184394b0f27be37bd80248b",
"url": "https://github.com/status-im/nim-serialization",
"downloadMethod": "git",
"dependencies": [
"nim",
"faststreams",
"unittest2",
"stew"
],
"checksums": {
"sha1": "fa35c1bb76a0a02a2379fe86eaae0957c7527cb8"
}
},
"toml_serialization": {
"version": "0.2.18",
"vcsRevision": "b5b387e6fb2a7cc75d54a269b07cc6218361bd46",
"url": "https://github.com/status-im/nim-toml-serialization",
"downloadMethod": "git",
"dependencies": [
"nim",
"faststreams",
"serialization",
"stew"
],
"checksums": {
"sha1": "76ae1c2af5dd092849b41750ff29217980dc9ca3"
}
},
"confutils": {
"version": "0.1.0",
"vcsRevision": "7728f6bd81a1eedcfe277d02ea85fdb805bcc05a",
"url": "https://github.com/status-im/nim-confutils",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"serialization",
"results"
],
"checksums": {
"sha1": "8bc8c30b107fdba73b677e5f257c6c42ae1cdc8e"
}
},
"json_serialization": {
"version": "0.4.4",
"vcsRevision": "c343b0e243d9e17e2c40f3a8a24340f7c4a71d44",
"url": "https://github.com/status-im/nim-json-serialization",
"downloadMethod": "git",
"dependencies": [
"nim",
"faststreams",
"serialization",
"stew",
"results"
],
"checksums": {
"sha1": "8b3115354104858a0ac9019356fb29720529c2bd"
}
},
"chronicles": {
"version": "0.12.2",
"vcsRevision": "27ec507429a4eb81edc20f28292ee8ec420be05b",
"url": "https://github.com/status-im/nim-chronicles",
"downloadMethod": "git",
"dependencies": [
"nim",
"faststreams",
"serialization",
"json_serialization",
"testutils"
],
"checksums": {
"sha1": "02febb20d088120b2836d3306cfa21f434f88f65"
}
},
"presto": {
"version": "0.1.1",
"vcsRevision": "d66043dd7ede146442e6c39720c76a20bde5225f",
"url": "https://github.com/status-im/nim-presto",
"downloadMethod": "git",
"dependencies": [
"nim",
"chronos",
"chronicles",
"metrics",
"results",
"stew"
],
"checksums": {
"sha1": "8df97c45683abe2337bdff43b844c4fbcc124ca2"
}
},
"stint": {
"version": "0.8.2",
"vcsRevision": "470b7892561b5179ab20bd389a69217d6213fe58",
"url": "https://github.com/status-im/nim-stint",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"unittest2"
],
"checksums": {
"sha1": "d8f871fd617e7857192d4609fe003b48942a8ae5"
}
},
"minilru": {
"version": "0.1.0",
"vcsRevision": "6dd93feb60f4cded3c05e7af7209cf63fb677893",
"url": "https://github.com/status-im/nim-minilru",
"downloadMethod": "git",
"dependencies": [
"nim",
"results",
"unittest2"
],
"checksums": {
"sha1": "0be03a5da29fdd4409ea74a60fd0ccce882601b4"
}
},
"sqlite3_abi": {
"version": "3.53.0.0",
"vcsRevision": "8240e8e2819dfce1b67fa2733135d01b5cc80ae0",
"url": "https://github.com/arnetheduck/nim-sqlite3-abi",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "fb7a6e6f36fc4eb4dfa6634dbcbf5cd0dfd0ebf0"
}
},
"dnsclient": {
"version": "0.3.4",
"vcsRevision": "23214235d4784d24aceed99bbfe153379ea557c8",
"url": "https://github.com/ba0f3/dnsclient.nim",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "65262c7e533ff49d6aca5539da4bc6c6ce132f40"
}
},
"unicodedb": {
"version": "0.13.2",
"vcsRevision": "66f2458710dc641dd4640368f9483c8a0ec70561",
"url": "https://github.com/nitely/nim-unicodedb",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "739102d885d99bb4571b1955f5f12aee423c935b"
}
},
"regex": {
"version": "0.26.3",
"vcsRevision": "4593305ed1e49731fc75af1dc572dd2559aad19c",
"url": "https://github.com/nitely/nim-regex",
"downloadMethod": "git",
"dependencies": [
"nim",
"unicodedb"
],
"checksums": {
"sha1": "4d24e7d7441137cd202e16f2359a5807ddbdc31f"
}
},
"nimcrypto": {
"version": "0.6.4",
"vcsRevision": "721fb99ee099b632eb86dfad1f0d96ee87583774",
"url": "https://github.com/cheatfate/nimcrypto",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "f9ab24fa940ed03d0fb09729a7303feb50b7eaec"
}
},
"websock": {
"version": "0.3.0",
"vcsRevision": "c105d98e6522e0e2cbe3dfa11b07a273e9fd0e7b",
"url": "https://github.com/status-im/nim-websock",
"downloadMethod": "git",
"dependencies": [
"nim",
"chronos",
"httputils",
"chronicles",
"stew",
"nimcrypto",
"bearssl",
"results",
"zlib"
],
"checksums": {
"sha1": "1294a66520fa4541e261dec8a6a84f774fb8c0ac"
}
},
"json_rpc": {
"version": "#43bbf499143eb45046c83ac9794c9e3280a2b8e7",
"vcsRevision": "43bbf499143eb45046c83ac9794c9e3280a2b8e7",
"url": "https://github.com/status-im/nim-json-rpc.git",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"nimcrypto",
"stint",
"chronos",
"httputils",
"chronicles",
"websock",
"serialization",
"json_serialization",
"unittest2"
],
"checksums": {
"sha1": "30ff6ead115b88c79862c5c7e37b1c9852eea59f"
}
},
"lsquic": {
"version": "0.0.1",
"vcsRevision": "4fb03ee7bfb39aecb3316889fdcb60bec3d0936f",
"url": "https://github.com/vacp2p/nim-lsquic",
"downloadMethod": "git",
"dependencies": [
"nim",
"zlib",
"stew",
"chronos",
"nimcrypto",
"unittest2",
"chronicles"
],
"checksums": {
"sha1": "f465fa994346490d0924d162f53d9b5aec62f948"
}
},
"secp256k1": {
"version": "0.6.0.3.2",
"vcsRevision": "d8f1288b7c72f00be5fc2c5ea72bf5cae1eafb15",
"url": "https://github.com/status-im/nim-secp256k1",
"downloadMethod": "git",
"dependencies": [
"nim",
"stew",
"results",
"nimcrypto"
],
"checksums": {
"sha1": "6618ef9de17121846a8c1d0317026b0ce8584e10"
}
},
"eth": {
"version": "0.9.0",
"vcsRevision": "d9135e6c3c5d6d819afdfb566aa8d958756b73a8",
"url": "https://github.com/status-im/nim-eth",
"downloadMethod": "git",
"dependencies": [
"nim",
"nimcrypto",
"stint",
"secp256k1",
"chronos",
"chronicles",
"stew",
"nat_traversal",
"metrics",
"sqlite3_abi",
"confutils",
"testutils",
"unittest2",
"results",
"minilru",
"snappy"
],
"checksums": {
"sha1": "2e01b0cfff9523d110562af70d19948280f8013e"
}
},
"web3": {
"version": "0.8.0",
"vcsRevision": "cdfe5601d2812a58e54faf53ee634452d01e5918",
"url": "https://github.com/status-im/nim-web3",
"downloadMethod": "git",
"dependencies": [
"nim",
"chronicles",
"chronos",
"bearssl",
"eth",
"faststreams",
"json_rpc",
"serialization",
"json_serialization",
"nimcrypto",
"stew",
"stint",
"results"
],
"checksums": {
"sha1": "26a112af032ef1536f97da2ca7364af618a11b80"
}
},
"dnsdisc": {
"version": "0.1.0",
"vcsRevision": "38f2e0f52c0a8f032ef4530835e519d550706d9e",
"url": "https://github.com/status-im/nim-dnsdisc",
"downloadMethod": "git",
"dependencies": [
"nim",
"bearssl",
"chronicles",
"chronos",
"eth",
"secp256k1",
"stew",
"testutils",
"unittest2",
"nimcrypto",
"results"
],
"checksums": {
"sha1": "055b882a0f6b1d1e57a25a7af99d2e5ac6268154"
}
},
"libp2p": {
"version": "#ff8d51857b4b79a68468e7bcc27b2026cca02996",
"vcsRevision": "ff8d51857b4b79a68468e7bcc27b2026cca02996",
"url": "https://github.com/vacp2p/nim-libp2p.git",
"downloadMethod": "git",
"dependencies": [
"nim",
"nimcrypto",
"dnsclient",
"bearssl",
"chronicles",
"chronos",
"metrics",
"secp256k1",
"stew",
"websock",
"unittest2",
"results",
"serialization",
"lsquic",
"jwt"
],
"checksums": {
"sha1": "fa2a7552c6ec860717b77ce34cf0b7afe4570234"
}
},
"taskpools": {
"version": "0.1.0",
"vcsRevision": "9e8ccc754631ac55ac2fd495e167e74e86293edb",
"url": "https://github.com/status-im/nim-taskpools",
"downloadMethod": "git",
"dependencies": [
"nim"
],
"checksums": {
"sha1": "09e1b2fdad55b973724d61227971afc0df0b7a81"
}
},
"ffi": {
"version": "0.1.3",
"vcsRevision": "06111de155253b34e47ed2aaed1d61d08d62cc1b",
"url": "https://github.com/logos-messaging/nim-ffi",
"downloadMethod": "git",
"dependencies": [
"nim",
"chronos",
"chronicles",
"taskpools"
],
"checksums": {
"sha1": "6f9d49375ea1dc71add55c72ac80a808f238e5b0"
}
}
},
"tasks": {}
}

View File

@ -21,9 +21,9 @@ import
../testlib/[common, wakucore, wakunode, testasync, futures, testutils],
../waku_filter_v2/waku_filter_utils
proc generateRequestId(rng: ref HmacDrbgContext): string =
proc generateRequestId(rng: crypto.Rng): string =
var bytes: array[10, byte]
hmacDrbgGenerate(rng[], bytes)
rng.generate(bytes)
return toHex(bytes)
proc createRequest(

View File

@ -35,10 +35,10 @@ from ../../waku/waku_noise/noise_utils import randomSeqByte
proc buildRandomIdentityCredentials(): IdentityCredential =
# We generate a random identity credential (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
let
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
IdentityCredential(
idTrapdoor: idTrapdoor,

View File

@ -1,4 +1,4 @@
import chronos, bearssl/rand, eth/[keys, p2p]
import chronos, eth/[keys, p2p]
import libp2p/crypto/crypto
@ -9,10 +9,10 @@ proc localAddress*(port: int): Address =
result = Address(udpPort: port, tcpPort: port, ip: parseIpAddress("127.0.0.1"))
proc setupTestNode*(
rng: ref HmacDrbgContext, capabilities: varargs[ProtocolInfo, `protocolInfo`]
rng: crypto.Rng, capabilities: varargs[ProtocolInfo, `protocolInfo`]
): EthereumNode =
let
keys1 = keys.KeyPair.random(rng[])
keys1 = keys.KeyPair.random(rng)
address = localAddress(nextPort)
result = newEthereumNode(
keys1,
@ -29,11 +29,11 @@ proc setupTestNode*(
# Copied from here: https://github.com/status-im/nim-libp2p/blob/d522537b19a532bc4af94fcd146f779c1f23bad0/tests/helpers.nim#L28
type RngWrap = object
rng: ref rand.HmacDrbgContext
rng: Rng
var rngVar: RngWrap
proc getRng(): ref rand.HmacDrbgContext =
proc getRng(): Rng =
# TODO if `rngVar` is a threadvar like it should be, there are random and
# spurious compile failures on mac - this is not gcsafe but for the
# purpose of the tests, it's ok as long as we only use a single thread
@ -42,5 +42,5 @@ proc getRng(): ref rand.HmacDrbgContext =
rngVar.rng = crypto.newRng()
rngVar.rng
template rng*(): ref rand.HmacDrbgContext =
template rng*(): Rng =
getRng()

View File

@ -52,7 +52,7 @@ suite "Waku DNS Discovery":
)
.get() # No link entries
let treeKeys = keys.KeyPair.random(rng[])
let treeKeys = keys.KeyPair.random(rng)
# Sign tree
check:

View File

@ -46,10 +46,10 @@ procSuite "Credentials test suite":
# We generate a random identity credential (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
var
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
var idCredential = IdentityCredential(
idTrapdoor: idTrapdoor,
@ -85,10 +85,10 @@ procSuite "Credentials test suite":
# We generate two random identity credentials (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
var
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
idCredential = IdentityCredential(
idTrapdoor: idTrapdoor,
idNullifier: idNullifier,
@ -141,10 +141,10 @@ procSuite "Credentials test suite":
# We generate random identity credentials (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
let
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
idCredential = IdentityCredential(
idTrapdoor: idTrapdoor,
idNullifier: idNullifier,
@ -193,10 +193,10 @@ procSuite "Credentials test suite":
# We generate random identity credentials (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
let
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
idCredential = IdentityCredential(
idTrapdoor: idTrapdoor,
idNullifier: idNullifier,
@ -254,10 +254,10 @@ procSuite "Credentials test suite":
# We generate random identity credentials (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
let
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)
idTrapdoor = randomSeqByte(rng, 32)
idNullifier = randomSeqByte(rng, 32)
idSecretHash = randomSeqByte(rng, 32)
idCommitment = randomSeqByte(rng, 32)
idCredential = IdentityCredential(
idTrapdoor: idTrapdoor,
idNullifier: idNullifier,

View File

@ -16,7 +16,7 @@ suite "KeyFile test suite":
removeFile(filepath)
# The secret
var secret = randomSeqByte(rng[], 300)
var secret = randomSeqByte(rng, 300)
# We create a keyfile encrypting the secret with password
let keyfile = createKeyFileJson(secret, password)
@ -42,9 +42,9 @@ suite "KeyFile test suite":
test "Create/Save/Load multiple keyfiles in same file":
# We set different passwords for different keyfiles that will be stored in same file
let password1 = string.fromBytes(randomSeqByte(rng[], 20))
let password1 = string.fromBytes(randomSeqByte(rng, 20))
let password2 = ""
let password3 = string.fromBytes(randomSeqByte(rng[], 20))
let password3 = string.fromBytes(randomSeqByte(rng, 20))
var keyfile: KfResult[JsonNode]
let filepath = "./test.keyfile"
@ -53,40 +53,40 @@ suite "KeyFile test suite":
# We generate 6 different secrets and we encrypt them using 3 different passwords, and we store the obtained keystore
let secret1 = randomSeqByte(rng[], 300)
let secret1 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret1, password1)
check:
keyfile.isOk()
saveKeyFile(filepath, keyfile.get()).isOk()
let secret2 = randomSeqByte(rng[], 300)
let secret2 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret2, password2)
check:
keyfile.isOk()
saveKeyFile(filepath, keyfile.get()).isOk()
let secret3 = randomSeqByte(rng[], 300)
let secret3 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret3, password3)
check:
keyfile.isOk()
saveKeyFile(filepath, keyfile.get()).isOk()
# We encrypt secret4 with password3
let secret4 = randomSeqByte(rng[], 300)
let secret4 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret4, password3)
check:
keyfile.isOk()
saveKeyFile(filepath, keyfile.get()).isOk()
# We encrypt secret5 with password1
let secret5 = randomSeqByte(rng[], 300)
let secret5 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret5, password1)
check:
keyfile.isOk()
saveKeyFile(filepath, keyfile.get()).isOk()
# We encrypt secret6 with password1
let secret6 = randomSeqByte(rng[], 300)
let secret6 = randomSeqByte(rng, 300)
keyfile = createKeyFileJson(secret6, password1)
check:
keyfile.isOk()
@ -343,7 +343,7 @@ suite "KeyFile test suite (adapted from nim-eth keyfile tests)":
test "Scrypt keyfiles":
let
expectedSecret = randomSeqByte(rng[], 300)
expectedSecret = randomSeqByte(rng, 300)
password = "miawmiawcat"
# By default, keyfiles' encryption key is derived from password using PBKDF2.

View File

@ -27,7 +27,7 @@ procSuite "Waku Noise":
let maxMessageLength = 3 * NoisePaddingBlockSize
for messageLen in 0 .. maxMessageLength:
let
message = randomSeqByte(rng[], messageLen)
message = randomSeqByte(rng, messageLen)
padded = pkcs7_pad(message, NoisePaddingBlockSize)
unpadded = pkcs7_unpad(padded, NoisePaddingBlockSize)
@ -37,11 +37,11 @@ procSuite "Waku Noise":
message == unpadded
test "ChaChaPoly Encryption/Decryption: random byte sequences":
let cipherState = randomChaChaPolyCipherState(rng[])
let cipherState = randomChaChaPolyCipherState(rng)
# We encrypt/decrypt random byte sequences
let
plaintext: seq[byte] = randomSeqByte(rng[], rand(1 .. 128))
plaintext: seq[byte] = randomSeqByte(rng, rand(1 .. 128))
ciphertext: ChaChaPolyCiphertext = encrypt(cipherState, plaintext)
decryptedCiphertext: seq[byte] = decrypt(cipherState, ciphertext)
@ -49,7 +49,7 @@ procSuite "Waku Noise":
plaintext == decryptedCiphertext
test "ChaChaPoly Encryption/Decryption: random strings":
let cipherState = randomChaChaPolyCipherState(rng[])
let cipherState = randomChaChaPolyCipherState(rng)
# We encrypt/decrypt random strings
var plaintext: string
@ -64,10 +64,10 @@ procSuite "Waku Noise":
plaintext.toBytes() == decryptedCiphertext
test "Noise public keys: encrypt and decrypt a public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng)
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk)
@ -75,20 +75,20 @@ procSuite "Waku Noise":
noisePublicKey == decryptedPk
test "Noise public keys: decrypt an unencrypted public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng)
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, noisePublicKey)
check:
noisePublicKey == decryptedPk
test "Noise public keys: encrypt an encrypted public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng)
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
encryptedPk2: NoisePublicKey = encryptNoisePublicKey(cs, encryptedPk)
@ -96,10 +96,10 @@ procSuite "Waku Noise":
encryptedPk == encryptedPk2
test "Noise public keys: encrypt, decrypt and decrypt a public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng)
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
decryptedPk: NoisePublicKey = decryptNoisePublicKey(cs, encryptedPk)
decryptedPk2: NoisePublicKey = decryptNoisePublicKey(cs, decryptedPk)
@ -109,7 +109,7 @@ procSuite "Waku Noise":
test "Noise public keys: serialize and deserialize an unencrypted public key":
let
noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(noisePublicKey)
deserializedNoisePublicKey: NoisePublicKey =
intoNoisePublicKey(serializedNoisePublicKey)
@ -118,10 +118,10 @@ procSuite "Waku Noise":
noisePublicKey == deserializedNoisePublicKey
test "Noise public keys: encrypt, serialize, deserialize and decrypt a public key":
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng[])
let noisePublicKey: NoisePublicKey = genNoisePublicKey(rng)
let
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng[])
cs: ChaChaPolyCipherState = randomChaChaPolyCipherState(rng)
encryptedPk: NoisePublicKey = encryptNoisePublicKey(cs, noisePublicKey)
serializedNoisePublicKey: seq[byte] = serializeNoisePublicKey(encryptedPk)
deserializedNoisePublicKey: NoisePublicKey =
@ -134,7 +134,7 @@ procSuite "Waku Noise":
test "PayloadV2: serialize/deserialize PayloadV2 to byte sequence":
let
payload2: PayloadV2 = randomPayloadV2(rng[])
payload2: PayloadV2 = randomPayloadV2(rng)
serializedPayload = serializePayloadV2(payload2)
check:
@ -149,7 +149,7 @@ procSuite "Waku Noise":
test "PayloadV2: Encode/Decode a Waku Message (version 2) to a PayloadV2":
# We encode to a WakuMessage a random PayloadV2
let
payload2 = randomPayloadV2(rng[])
payload2 = randomPayloadV2(rng)
msg = encodePayloadV2(payload2)
check:
@ -173,8 +173,8 @@ procSuite "Waku Noise":
test "Noise State Machine: Diffie-Hellman operation":
#We generate random keypairs
let
aliceKey = genKeyPair(rng[])
bobKey = genKeyPair(rng[])
aliceKey = genKeyPair(rng)
bobKey = genKeyPair(rng)
# A Diffie-Hellman operation between Alice's private key and Bob's public key must be equal to
# a Diffie-hellman operation between Alice's public key and Bob's private key
@ -188,10 +188,10 @@ procSuite "Waku Noise":
test "Noise State Machine: Cipher State primitives":
# We generate a random Cipher State, associated data ad and plaintext
var
cipherState: CipherState = randomCipherState(rng[])
cipherState: CipherState = randomCipherState(rng)
nonce: uint64 = uint64(rand(0 .. int.high))
ad: seq[byte] = randomSeqByte(rng[], rand(1 .. 128))
plaintext: seq[byte] = randomSeqByte(rng[], rand(1 .. 128))
ad: seq[byte] = randomSeqByte(rng, rand(1 .. 128))
plaintext: seq[byte] = randomSeqByte(rng, rand(1 .. 128))
# We set the random nonce generated in the cipher state
setNonce(cipherState, nonce)
@ -218,7 +218,7 @@ procSuite "Waku Noise":
setCipherStateKey(cipherState, EmptyKey)
nonce = getNonce(cipherState)
plaintext = randomSeqByte(rng[], rand(1 .. 128))
plaintext = randomSeqByte(rng, rand(1 .. 128))
ciphertext = encryptWithAd(cipherState, ad, plaintext)
check:
@ -230,7 +230,7 @@ procSuite "Waku Noise":
nonce = getNonce(cipherState)
# Note that we set ciphertext minimum length to 16 to not trigger checks on authentication tag length
ciphertext = randomSeqByte(rng[], rand(16 .. 128))
ciphertext = randomSeqByte(rng, rand(16 .. 128))
plaintext = decryptWithAd(cipherState, ad, ciphertext)
check:
@ -241,9 +241,9 @@ procSuite "Waku Noise":
# Note that NonceMax is uint64.high - 1 = 2^64-1-1 and that nonce is increased after each encryption and decryption operation
# We generate a test Cipher State with nonce set to MaxNonce
cipherState = randomCipherState(rng[])
cipherState = randomCipherState(rng)
setNonce(cipherState, NonceMax)
plaintext = randomSeqByte(rng[], rand(1 .. 128))
plaintext = randomSeqByte(rng, rand(1 .. 128))
# We test if encryption fails with a NoiseNonceMaxError error. Any subsequent encryption call over the Cipher State should fail similarly and leave the nonce unchanged
for _ in [1 .. 5]:
@ -257,9 +257,9 @@ procSuite "Waku Noise":
# Since nonce is increased after decryption as well, we need to generate a proper ciphertext in order to test MaxNonceError error handling
# We cannot call encryptWithAd to encrypt a plaintext using a nonce equal MaxNonce, since this will trigger a MaxNonceError.
# To perform such test, we then need to encrypt a test plaintext using directly ChaChaPoly primitive
cipherState = randomCipherState(rng[])
cipherState = randomCipherState(rng)
setNonce(cipherState, NonceMax)
plaintext = randomSeqByte(rng[], rand(1 .. 128))
plaintext = randomSeqByte(rng, rand(1 .. 128))
# We perform encryption using the Cipher State key, NonceMax and ad
# By Noise specification the nonce is 8 bytes long out of the 12 bytes supported by ChaChaPoly, thus we copy the Little endian conversion of the nonce to a ChaChaPolyNonce
@ -308,7 +308,7 @@ procSuite "Waku Noise":
########################################
# We generate a random byte sequence and execute a mixHash over it
mixHash(symmetricState, randomSeqByte(rng[], rand(1 .. 128)))
mixHash(symmetricState, randomSeqByte(rng, rand(1 .. 128)))
# mixHash changes only the handshake hash value of the Symmetric state
check:
@ -324,7 +324,7 @@ procSuite "Waku Noise":
########################################
# We generate random input key material and we execute mixKey
var inputKeyMaterial = randomSeqByte(rng[], rand(1 .. 128))
var inputKeyMaterial = randomSeqByte(rng, rand(1 .. 128))
mixKey(symmetricState, inputKeyMaterial)
# mixKey changes the Symmetric State's chaining key and encryption key of the embedded Cipher State
@ -345,7 +345,7 @@ procSuite "Waku Noise":
########################################
# We generate random input key material and we execute mixKeyAndHash
inputKeyMaterial = randomSeqByte(rng[], rand(1 .. 128))
inputKeyMaterial = randomSeqByte(rng, rand(1 .. 128))
mixKeyAndHash(symmetricState, inputKeyMaterial)
# mixKeyAndHash executes a mixKey and a mixHash using the input key material
@ -368,7 +368,7 @@ procSuite "Waku Noise":
var initialSymmetricState = symmetricState
# We generate random plaintext and we execute encryptAndHash
var plaintext = randomChaChaPolyKey(rng[])
var plaintext = randomChaChaPolyKey(rng)
var nonce = getNonce(getCipherState(symmetricState))
var ciphertext = encryptAndHash(symmetricState, plaintext)
@ -421,11 +421,11 @@ procSuite "Waku Noise":
let hsPattern = NoiseHandshakePatterns["XX"]
# We initialize Alice's and Bob's Handshake State
let aliceStaticKey = genKeyPair(rng[])
let aliceStaticKey = genKeyPair(rng)
var aliceHS =
initialize(hsPattern = hsPattern, staticKey = aliceStaticKey, initiator = true)
let bobStaticKey = genKeyPair(rng[])
let bobStaticKey = genKeyPair(rng)
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey)
var
@ -440,15 +440,15 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -458,13 +458,13 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# At this step, Bob writes and returns a payload
bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
bobStep = stepHandshake(rng, bobHS, transportMessage = sentTransportMessage).get()
# While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
aliceStep = stepHandshake(rng, aliceHS, readPayloadV2 = bobStep.payload2).get()
check:
aliceStep.transportMessage == sentTransportMessage
@ -474,14 +474,14 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -494,13 +494,13 @@ procSuite "Waku Noise":
let prevBobHS = bobHS
let bobStep1 =
stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, bobHS, transportMessage = sentTransportMessage).get()
let aliceStep1 =
stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep1.payload2).get()
stepHandshake(rng, aliceHS, readPayloadV2 = bobStep1.payload2).get()
let aliceStep2 =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
let bobStep2 =
stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep2.payload2).get()
stepHandshake(rng, bobHS, readPayloadV2 = aliceStep2.payload2).get()
check:
aliceStep1 == default(HandshakeStepResult)
@ -529,7 +529,7 @@ procSuite "Waku Noise":
for _ in 0 .. 10:
# Alice writes to Bob
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
@ -538,7 +538,7 @@ procSuite "Waku Noise":
message == readMessage
# Bob writes to Alice
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
@ -550,15 +550,15 @@ procSuite "Waku Noise":
let hsPattern = NoiseHandshakePatterns["XXpsk0"]
# We generate a random psk
let psk = randomSeqByte(rng[], 32)
let psk = randomSeqByte(rng, 32)
# We initialize Alice's and Bob's Handshake State
let aliceStaticKey = genKeyPair(rng[])
let aliceStaticKey = genKeyPair(rng)
var aliceHS = initialize(
hsPattern = hsPattern, staticKey = aliceStaticKey, psk = psk, initiator = true
)
let bobStaticKey = genKeyPair(rng[])
let bobStaticKey = genKeyPair(rng)
var bobHS = initialize(hsPattern = hsPattern, staticKey = bobStaticKey, psk = psk)
var
@ -573,15 +573,15 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -591,13 +591,13 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# At this step, Bob writes and returns a payload
bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
bobStep = stepHandshake(rng, bobHS, transportMessage = sentTransportMessage).get()
# While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
aliceStep = stepHandshake(rng, aliceHS, readPayloadV2 = bobStep.payload2).get()
check:
aliceStep.transportMessage == sentTransportMessage
@ -607,14 +607,14 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -640,7 +640,7 @@ procSuite "Waku Noise":
for _ in 0 .. 10:
# Alice writes to Bob
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
@ -649,7 +649,7 @@ procSuite "Waku Noise":
message == readMessage
# Bob writes to Alice
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
@ -661,8 +661,8 @@ procSuite "Waku Noise":
let hsPattern = NoiseHandshakePatterns["K1K1"]
# We initialize Alice's and Bob's Handshake State
let aliceStaticKey = genKeyPair(rng[])
let bobStaticKey = genKeyPair(rng[])
let aliceStaticKey = genKeyPair(rng)
let bobStaticKey = genKeyPair(rng)
# This handshake has the following pre-message pattern:
# -> s
@ -696,15 +696,15 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -714,13 +714,13 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# At this step, Bob writes and returns a payload
bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
bobStep = stepHandshake(rng, bobHS, transportMessage = sentTransportMessage).get()
# While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
aliceStep = stepHandshake(rng, aliceHS, readPayloadV2 = bobStep.payload2).get()
check:
aliceStep.transportMessage == sentTransportMessage
@ -730,14 +730,14 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake_message and the (encrypted) transportMessage
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transportMessage alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -763,7 +763,7 @@ procSuite "Waku Noise":
for _ in 0 .. 10:
# Alice writes to Bob
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
@ -772,7 +772,7 @@ procSuite "Waku Noise":
message == readMessage
# Bob writes to Alice
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()
@ -784,8 +784,8 @@ procSuite "Waku Noise":
let hsPattern = NoiseHandshakePatterns["XK1"]
# We initialize Alice's and Bob's Handshake State
let aliceStaticKey = genKeyPair(rng[])
let bobStaticKey = genKeyPair(rng[])
let aliceStaticKey = genKeyPair(rng)
let bobStaticKey = genKeyPair(rng)
# This handshake has the following pre-message pattern:
# <- s
@ -816,15 +816,15 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# By being the handshake initiator, Alice writes a Waku2 payload v2 containing her handshake message
# and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -834,13 +834,13 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# At this step, Bob writes and returns a payload
bobStep = stepHandshake(rng[], bobHS, transportMessage = sentTransportMessage).get()
bobStep = stepHandshake(rng, bobHS, transportMessage = sentTransportMessage).get()
# While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(rng[], aliceHS, readPayloadV2 = bobStep.payload2).get()
aliceStep = stepHandshake(rng, aliceHS, readPayloadV2 = bobStep.payload2).get()
check:
aliceStep.transportMessage == sentTransportMessage
@ -850,14 +850,14 @@ procSuite "Waku Noise":
###############
# We generate a random transport message
sentTransportMessage = randomSeqByte(rng[], 32)
sentTransportMessage = randomSeqByte(rng, 32)
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message
aliceStep =
stepHandshake(rng[], aliceHS, transportMessage = sentTransportMessage).get()
stepHandshake(rng, aliceHS, transportMessage = sentTransportMessage).get()
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(rng[], bobHS, readPayloadV2 = aliceStep.payload2).get()
bobStep = stepHandshake(rng, bobHS, readPayloadV2 = aliceStep.payload2).get()
check:
bobStep.transportMessage == sentTransportMessage
@ -883,7 +883,7 @@ procSuite "Waku Noise":
for _ in 0 .. 10:
# Alice writes to Bob
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(aliceHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(bobHSResult, payload2, defaultMessageNametagBuffer).get()
@ -892,7 +892,7 @@ procSuite "Waku Noise":
message == readMessage
# Bob writes to Alice
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(bobHSResult, message, defaultMessageNametagBuffer)
readMessage =
readMessage(aliceHSResult, payload2, defaultMessageNametagBuffer).get()

View File

@ -25,22 +25,22 @@ procSuite "Waku Noise Sessions":
let hsPattern = NoiseHandshakePatterns["WakuPairing"]
# Alice static/ephemeral key initialization and commitment
let aliceStaticKey = genKeyPair(rng[])
let aliceEphemeralKey = genKeyPair(rng[])
let s = randomSeqByte(rng[], 32)
let aliceStaticKey = genKeyPair(rng)
let aliceEphemeralKey = genKeyPair(rng)
let s = randomSeqByte(rng, 32)
let aliceCommittedStaticKey = commitPublicKey(getPublicKey(aliceStaticKey), s)
# Bob static/ephemeral key initialization and commitment
let bobStaticKey = genKeyPair(rng[])
let bobEphemeralKey = genKeyPair(rng[])
let r = randomSeqByte(rng[], 32)
let bobStaticKey = genKeyPair(rng)
let bobEphemeralKey = genKeyPair(rng)
let r = randomSeqByte(rng, 32)
let bobCommittedStaticKey = commitPublicKey(getPublicKey(bobStaticKey), r)
# Content Topic information
let applicationName = "waku-noise-sessions"
let applicationVersion = "0.1"
let shardId = "10"
let qrMessageNametag = randomSeqByte(rng[], MessageNametagLength)
let qrMessageNametag = randomSeqByte(rng, MessageNametagLength)
# Out-of-band Communication
@ -133,7 +133,7 @@ procSuite "Waku Noise Sessions":
# and the (encrypted) transport message
# The message is sent with a messageNametag equal to the one received through the QR code
aliceStep = stepHandshake(
rng[],
rng,
aliceHS,
transportMessage = sentTransportMessage,
messageNametag = qrMessageNametag,
@ -168,7 +168,7 @@ procSuite "Waku Noise Sessions":
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
# Note that Bob verifies if the received payloadv2 has the expected messageNametag set
bobStep = stepHandshake(
rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = qrMessageNametag
rng, bobHS, readPayloadV2 = readPayloadV2, messageNametag = qrMessageNametag
)
.get()
@ -199,7 +199,7 @@ procSuite "Waku Noise Sessions":
# At this step, Bob writes and returns a payload
bobStep = stepHandshake(
rng[],
rng,
bobHS,
transportMessage = sentTransportMessage,
messageNametag = bobMessageNametag,
@ -233,7 +233,7 @@ procSuite "Waku Noise Sessions":
# While Alice reads and returns the (decrypted) transport message
aliceStep = stepHandshake(
rng[],
rng,
aliceHS,
readPayloadV2 = readPayloadV2,
messageNametag = aliceMessageNametag,
@ -265,7 +265,7 @@ procSuite "Waku Noise Sessions":
# Similarly as in first step, Alice writes a Waku2 payload containing the handshake message and the (encrypted) transport message
aliceStep = stepHandshake(
rng[],
rng,
aliceHS,
transportMessage = sentTransportMessage,
messageNametag = aliceMessageNametag,
@ -299,7 +299,7 @@ procSuite "Waku Noise Sessions":
# Bob reads Alice's payloads, and returns the (decrypted) transport message Alice sent to him
bobStep = stepHandshake(
rng[], bobHS, readPayloadV2 = readPayloadV2, messageNametag = bobMessageNametag
rng, bobHS, readPayloadV2 = readPayloadV2, messageNametag = bobMessageNametag
)
.get()
@ -333,7 +333,7 @@ procSuite "Waku Noise Sessions":
# Note that we exchange more than the number of messages contained in the nametag buffer to test if they are filled correctly as the communication proceeds
for i in 0 .. 10 * MessageNametagBufferSize:
# Alice writes to Bob
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
aliceHSResult,
message,
@ -350,7 +350,7 @@ procSuite "Waku Noise Sessions":
message == readMessage
# Bob writes to Alice
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
bobHSResult,
message,
@ -368,13 +368,13 @@ procSuite "Waku Noise Sessions":
# We test how nametag buffers help in detecting lost messages
# Alice writes two messages to Bob, but only the second is received
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
aliceHSResult,
message,
outboundMessageNametagBuffer = aliceHSResult.nametagsOutbound,
)
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
aliceHSResult,
message,
@ -390,7 +390,7 @@ procSuite "Waku Noise Sessions":
# We adjust bob nametag buffer for next test (i.e. the missed message is correctly recovered)
delete(bobHSResult.nametagsInbound, 2)
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
bobHSResult, message, outboundMessageNametagBuffer = bobHSResult.nametagsOutbound
)
@ -405,7 +405,7 @@ procSuite "Waku Noise Sessions":
message == readMessage
# We test if a missing nametag is correctly detected
message = randomSeqByte(rng[], 32)
message = randomSeqByte(rng, 32)
payload2 = writeMessage(
aliceHSResult,
message,

View File

@ -1,7 +1,7 @@
{.used.}
import
std/[sequtils, strutils, net],
std/[options, sequtils, strutils, net],
stew/byteutils,
testutils/unittests,
chronicles,

View File

@ -1,4 +1,4 @@
import std/[times, random], bearssl/rand, libp2p/crypto/crypto
import std/[times, random], libp2p/crypto/crypto
## Randomization
@ -11,14 +11,14 @@ proc randomize*() =
## RNG
# Copied from here: https://github.com/status-im/nim-libp2p/blob/d522537b19a532bc4af94fcd146f779c1f23bad0/tests/helpers.nim#L28
type Rng = object
rng: ref HmacDrbgContext
type RngState = object
rng: Rng
# Typically having a module variable is considered bad design. This case should
# be considered as an exception and it should be used only in the tests.
var rngVar: Rng
var rngVar: RngState
proc getRng(): ref HmacDrbgContext =
proc getRng(): Rng =
# TODO: if `rngVar` is a threadvar like it should be, there are random and
# spurious compile failures on mac - this is not gcsafe but for the
# purpose of the tests, it's ok as long as we only use a single thread
@ -28,5 +28,5 @@ proc getRng(): ref HmacDrbgContext =
rngVar.rng
template rng*(): ref HmacDrbgContext =
template rng*(): Rng =
getRng()

View File

@ -22,13 +22,13 @@ proc ts*(offset = 0, origin = now()): Timestamp =
# Switch
proc generateEcdsaKey*(): libp2p_keys.PrivateKey =
libp2p_keys.PrivateKey.random(ECDSA, rng[]).get()
libp2p_keys.PrivateKey.random(ECDSA, rng).get()
proc generateEcdsaKeyPair*(): libp2p_keys.KeyPair =
libp2p_keys.KeyPair.random(ECDSA, rng[]).get()
libp2p_keys.KeyPair.random(ECDSA, rng).get()
proc generateSecp256k1Key*(): libp2p_keys.PrivateKey =
libp2p_keys.PrivateKey.random(Secp256k1, rng[]).get()
libp2p_keys.PrivateKey.random(Secp256k1, rng).get()
proc ethSecp256k1Key*(hex: string): eth_keys.PrivateKey =
eth_keys.PrivateKey.fromHex(hex).get()

View File

@ -38,8 +38,8 @@ suite "Waku Discovery v5":
let
rng = eth_keys.newRng()
pk1 = eth_keys.PrivateKey.random(rng[])
pk2 = eth_keys.PrivateKey.random(rng[])
pk1 = eth_keys.PrivateKey.random(rng)
pk2 = eth_keys.PrivateKey.random(rng)
suite "shardingPredicate":
var
@ -423,7 +423,7 @@ suite "Waku Discovery v5":
let myRng = libp2p_keys.newRng()
var confBuilder = defaultTestWakuConfBuilder()
confBuilder.withNodeKey(libp2p_keys.PrivateKey.random(Secp256k1, myRng[])[])
confBuilder.withNodeKey(libp2p_keys.PrivateKey.random(Secp256k1, myRng))
confBuilder.discv5Conf.withEnabled(true)
confBuilder.discv5Conf.withUdpPort(9000.Port)
let conf = confBuilder.build().valueOr:
@ -434,7 +434,7 @@ suite "Waku Discovery v5":
(waitFor startWaku(addr waku0)).isOkOr:
raiseAssert error
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng[])[])
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng))
confBuilder.discv5Conf.withBootstrapNodes(@[waku0.node.enr.toURI()])
confBuilder.discv5Conf.withEnabled(true)
confBuilder.discv5Conf.withUdpPort(9001.Port)
@ -454,7 +454,7 @@ suite "Waku Discovery v5":
confBuilder.discv5Conf.withBootstrapNodes(@[waku1.node.enr.toURI()])
confBuilder.withP2pTcpPort(60003.Port)
confBuilder.discv5Conf.withUdpPort(9003.Port)
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng[])[])
confBuilder.withNodeKey(crypto.PrivateKey.random(Secp256k1, myRng))
let conf2 = confBuilder.build().valueOr:
raiseAssert error

View File

@ -1,7 +1,7 @@
{.used.}
import
std/[os, strutils, sequtils, sysrand, math],
std/[options, os, strutils, sequtils, sysrand, math],
stew/byteutils,
testutils/unittests,
chronos,

View File

@ -446,7 +446,7 @@ proc createEthAccount*(
let gasPrice = Quantity(await web3.provider.eth_gasPrice())
web3.defaultAccount = accounts[0]
let pk = keys.PrivateKey.random(rng[])
let pk = keys.PrivateKey.random(rng)
let acc = Address(toCanonicalAddress(pk.toPublicKey()))
var tx: TransactionArgs
@ -464,7 +464,7 @@ proc createEthAccount*(
return (pk, acc)
proc createEthAccount*(web3: Web3): (keys.PrivateKey, Address) =
let pk = keys.PrivateKey.random(rng[])
let pk = keys.PrivateKey.random(rng)
let acc = Address(toCanonicalAddress(pk.toPublicKey()))
return (pk, acc)

View File

@ -1,7 +1,7 @@
{.used.}
import
std/sequtils,
std/[options, sequtils],
testutils/unittests,
chronicles,
chronos,

View File

@ -22,7 +22,7 @@ type TestResponseTuple = tuple[status: int, data: string, headers: HttpTable]
proc testWakuNode(): WakuNode =
let
privkey = crypto.PrivateKey.random(Secp256k1, rng[]).tryGet()
privkey = crypto.PrivateKey.random(Secp256k1, rng).tryGet()
bindIp = parseIpAddress("0.0.0.0")
extIp = parseIpAddress("127.0.0.1")
port = Port(0)

View File

@ -24,7 +24,7 @@ import
proc testWakuNode(): WakuNode =
let
privkey = crypto.PrivateKey.random(Secp256k1, rng[]).tryGet()
privkey = crypto.PrivateKey.random(Secp256k1, rng).tryGet()
bindIp = parseIpAddress("0.0.0.0")
extIp = parseIpAddress("127.0.0.1")
port = Port(0)

View File

@ -29,7 +29,7 @@ import
proc testWakuNode(): WakuNode =
let
privkey = crypto.PrivateKey.random(Secp256k1, rng[]).tryGet()
privkey = crypto.PrivateKey.random(Secp256k1, rng).tryGet()
bindIp = parseIpAddress("0.0.0.0")
extIp = parseIpAddress("127.0.0.1")
port = Port(0)

View File

@ -266,7 +266,8 @@ type WakuNodeConf* = object
## Circuit-relay config
isRelayClient* {.
desc: """Set the node as a relay-client.
desc:
"""Set the node as a relay-client.
Set it to true for nodes that run behind a NAT or firewall and
hence would have reachability issues.""",
defaultValue: false,
@ -636,12 +637,6 @@ with the drawback of consuming some more bandwidth.""",
name: "mixkey"
.}: Option[string]
mixnodes* {.
desc:
"Multiaddress and mix-key of mix node to be statically specified in format multiaddr:mixPubKey. Argument may be repeated.",
name: "mixnode"
.}: seq[MixNodePubInfo]
# Kademlia Discovery config
enableKadDiscovery* {.
desc:
@ -735,22 +730,6 @@ proc isNumber(x: string): bool =
except ValueError:
result = false
proc parseCmdArg*(T: type MixNodePubInfo, p: string): T =
let elements = p.split(":")
if elements.len != 2:
raise newException(
ValueError, "Invalid format for mix node expected multiaddr:mixPublicKey"
)
let multiaddr = MultiAddress.init(elements[0]).valueOr:
raise newException(ValueError, "Invalid multiaddress format")
if not multiaddr.contains(multiCodec("ip4")).get():
raise newException(
ValueError, "Invalid format for ip address, expected a ipv4 multiaddress"
)
return MixNodePubInfo(
multiaddr: elements[0], pubKey: intoCurve25519Key(ncrutils.fromHex(elements[1]))
)
proc parseCmdArg*(T: type ProtectedShard, p: string): T =
let elements = p.split(":")
if elements.len != 2:
@ -834,22 +813,6 @@ proc readValue*(
except CatchableError:
raise newException(SerializationError, getCurrentExceptionMsg())
proc readValue*(
r: var TomlReader, value: var MixNodePubInfo
) {.raises: [SerializationError].} =
try:
value = parseCmdArg(MixNodePubInfo, r.readValue(string))
except CatchableError:
raise newException(SerializationError, getCurrentExceptionMsg())
proc readValue*(
r: var EnvvarReader, value: var MixNodePubInfo
) {.raises: [SerializationError].} =
try:
value = parseCmdArg(MixNodePubInfo, r.readValue(string))
except CatchableError:
raise newException(SerializationError, getCurrentExceptionMsg())
proc readValue*(
r: var TomlReader, value: var ProtectedShard
) {.raises: [SerializationError].} =
@ -1067,7 +1030,6 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
b.storeServiceConf.storeSyncConf.withRelayJitterSec(n.storeSyncRelayJitter)
b.mixConf.withEnabled(n.mix)
b.mixConf.withMixNodes(n.mixnodes)
b.withMix(n.mix)
if n.mixkey.isSome():
b.mixConf.withMixKey(n.mixkey.get())

View File

@ -27,7 +27,7 @@ requires "nim >= 2.2.4",
"toml_serialization",
"faststreams",
# Networking & P2P
"https://github.com/vacp2p/nim-libp2p.git#ff8d51857b4b79a68468e7bcc27b2026cca02996",
"https://github.com/vacp2p/nim-libp2p.git#e41a3ab8ff143fa30e75357f81200545590f0ec6",
"eth",
"nat_traversal",
"dnsdisc",
@ -60,6 +60,7 @@ requires "nim >= 2.2.4",
# Packages not on nimble (use git URLs)
requires "https://github.com/logos-messaging/nim-ffi"
requires "https://github.com/logos-co/nim-libp2p-mix"
requires "https://github.com/vacp2p/nim-lsquic"
requires "https://github.com/vacp2p/nim-jwt.git#057ec95eb5af0eea9c49bfe9025b3312c95dc5f2"
@ -432,6 +433,16 @@ task chat2mix, "Build example Waku chat mix usage":
"-d:chronicles_sinks=textlines[file] -d:chronicles_log_level=TRACE "
# -d:ssl - cause unlisted exception error in libp2p/utility...
task chat2disco, "Build example Waku chat with service discovery":
# NOTE For debugging, set debug level. For chat usage we want minimal log
# output to STDOUT. Can be fixed by redirecting logs to file (e.g.)
#buildBinary name, "examples/", "-d:chronicles_log_level=WARN"
let name = "chat2disco"
buildBinary name,
"apps/chat2disco/",
"-d:chronicles_sinks=textlines -d:chronicles_log_level=DEBUG "
task chat2bridge, "Build chat2bridge":
let name = "chat2bridge"
buildBinary name, "apps/chat2bridge/"

View File

@ -1,6 +1,6 @@
{.push raises: [].}
import bearssl/rand, std/times, chronos
import std/times, chronos, libp2p/crypto/crypto
import stew/byteutils
import waku/utils/requests as request_utils
import waku/waku_core/[topics/content_topic, message/message, time]
@ -19,7 +19,7 @@ type
PartiallyConnected
Connected
proc new*(T: typedesc[RequestId], rng: ref HmacDrbgContext): T =
proc new*(T: typedesc[RequestId], rng: crypto.Rng): T =
## Generate a new RequestId using the provided RNG.
RequestId(request_utils.generateRequestId(rng))

View File

@ -0,0 +1,26 @@
# Shim to provide valueOr and withValue for Option[T]
{.push raises: [].}
import std/options
template valueOr*[T](self: Option[T], def: untyped): T =
let s = self
if s.isSome():
s.get()
else:
def
template withValue*[T](self: Option[T], value, body: untyped) =
let s = self
if s.isSome():
let value {.inject.} = s.get()
body
template withValue*[T](self: Option[T], value, body, elseStmt: untyped) =
let s = self
if s.isSome():
let value {.inject.} = s.get()
body
else:
elseStmt

View File

@ -1,13 +1,13 @@
import
chronos,
chronicles,
bearssl/rand,
libp2p/crypto/crypto,
libp2p/protocols/connectivity/autonat/client,
libp2p/protocols/connectivity/autonat/service
const AutonatCheckInterval = Opt.some(chronos.seconds(30))
proc getAutonatService*(rng: ref HmacDrbgContext): AutonatService =
proc getAutonatService*(rng: crypto.Rng): AutonatService =
## AutonatService request other peers to dial us back
## flagging us as Reachable or NotReachable.
## minConfidence is used as threshold to determine the state.

View File

@ -7,6 +7,8 @@ import
chronicles,
metrics,
libp2p/multiaddress,
libp2p/crypto/crypto,
libp2p/crypto/rng,
eth/keys as eth_keys,
eth/p2p/discoveryv5/node,
eth/p2p/discoveryv5/protocol
@ -80,7 +82,7 @@ proc shardingPredicate*(
proc new*(
T: type WakuDiscoveryV5,
rng: ref HmacDrbgContext,
rng: crypto.Rng,
conf: WakuDiscoveryV5Config,
record: Option[waku_enr.Record],
peerManager: Option[PeerManager] = none(PeerManager),
@ -88,7 +90,7 @@ proc new*(
newAsyncEventQueue[SubscriptionEvent](30),
): T =
let protocol = newProtocol(
rng = rng,
rng = bearSslDrbgRef(rng),
config = conf.discv5Config.get(protocol.defaultDiscoveryConfig),
bindPort = conf.port,
bindIp = conf.address,
@ -405,7 +407,7 @@ proc setupDiscoveryV5*(
nodeTopicSubscriptionQueue: AsyncEventQueue[SubscriptionEvent],
conf: Discv5Conf,
dynamicBootstrapNodes: seq[RemotePeerInfo],
rng: ref HmacDrbgContext,
rng: crypto.Rng,
key: crypto.PrivateKey,
p2pListenAddress: IpAddress,
portsShift: uint16,

View File

@ -5,120 +5,30 @@ import
chronos,
chronicles,
results,
stew/byteutils,
libp2p/crypto/curve25519,
libp2p/crypto/crypto,
libp2p_mix/mix_protocol,
libp2p/[peerid, multiaddress, switch],
libp2p/extended_peer_record,
libp2p/crypto/curve25519,
libp2p/protocols/[kademlia, kad_disco],
libp2p/protocols/kademlia_discovery/types as kad_types,
libp2p/protocols/mix/mix_protocol
libp2p/protocols/[kademlia, service_discovery],
libp2p/protocols/service_discovery/types
import waku/waku_core, waku/node/peer_manager
logScope:
topics = "waku extended kademlia discovery"
topics = "waku kademlia"
const
DefaultExtendedKademliaDiscoveryInterval* = chronos.seconds(5)
ExtendedKademliaDiscoveryStartupDelay* = chronos.seconds(5)
const DefaultKademliaDiscoveryInterval* = chronos.seconds(60)
type
MixNodePoolSizeProvider* = proc(): int {.gcsafe, raises: [].}
NodeStartedProvider* = proc(): bool {.gcsafe, raises: [].}
ExtendedKademliaDiscoveryParams* = object
bootstrapNodes*: seq[(PeerId, seq[MultiAddress])]
mixPubKey*: Option[Curve25519Key]
advertiseMix*: bool = false
WakuKademlia* = ref object
protocol*: KademliaDiscovery
peerManager: PeerManager
discoveryLoop: Future[void]
running*: bool
getMixNodePoolSize: MixNodePoolSizeProvider
isNodeStarted: NodeStartedProvider
proc new*(
T: type WakuKademlia,
switch: Switch,
params: ExtendedKademliaDiscoveryParams,
peerManager: PeerManager,
getMixNodePoolSize: MixNodePoolSizeProvider = nil,
isNodeStarted: NodeStartedProvider = nil,
): Result[T, string] =
if params.bootstrapNodes.len == 0:
info "creating kademlia discovery as seed node (no bootstrap nodes)"
let kademlia = KademliaDiscovery.new(
switch,
bootstrapNodes = params.bootstrapNodes,
config = KadDHTConfig.new(
validator = kad_types.ExtEntryValidator(), selector = kad_types.ExtEntrySelector()
),
codec = ExtendedKademliaDiscoveryCodec,
)
try:
switch.mount(kademlia)
except CatchableError:
return err("failed to mount kademlia discovery: " & getCurrentExceptionMsg())
# Register services BEFORE starting kademlia so they are included in the
# initial self-signed peer record published to the DHT
if params.advertiseMix:
if params.mixPubKey.isSome():
let alreadyAdvertising = kademlia.startAdvertising(
ServiceInfo(id: MixProtocolID, data: @(params.mixPubKey.get()))
)
if alreadyAdvertising:
warn "mix service was already being advertised"
debug "extended kademlia advertising mix service",
keyHex = byteutils.toHex(params.mixPubKey.get()),
bootstrapNodes = params.bootstrapNodes.len
else:
warn "mix advertising enabled but no key provided"
info "kademlia discovery created",
bootstrapNodes = params.bootstrapNodes.len, advertiseMix = params.advertiseMix
return ok(
WakuKademlia(
protocol: kademlia,
peerManager: peerManager,
running: false,
getMixNodePoolSize: getMixNodePoolSize,
isNodeStarted: isNodeStarted,
)
)
proc extractMixPubKey(service: ServiceInfo): Option[Curve25519Key] =
if service.id != MixProtocolID:
trace "service is not mix protocol",
serviceId = service.id, mixProtocolId = MixProtocolID
return none(Curve25519Key)
if service.data.len != Curve25519KeySize:
warn "invalid mix pub key length from kademlia record",
expected = Curve25519KeySize,
actual = service.data.len,
dataHex = byteutils.toHex(service.data)
return none(Curve25519Key)
debug "found mix protocol service",
dataLen = service.data.len, expectedLen = Curve25519KeySize
let key = intoCurve25519Key(service.data)
debug "successfully extracted mix pub key", keyHex = byteutils.toHex(key)
return some(key)
proc remotePeerInfoFrom(record: ExtendedPeerRecord): Option[RemotePeerInfo] =
debug "processing kademlia record",
peerId = record.peerId,
numAddresses = record.addresses.len,
numServices = record.services.len,
serviceIds = record.services.mapIt(it.id)
type WakuKademlia* = ref object
protocol*: ServiceDiscovery
peerManager: PeerManager
loopInterval: Duration
#periodicWalkFut: Future[void]
periodicLookupFut: Future[void]
discoveredServices*: seq[string]
proc toRemotePeerInfo(record: ExtendedPeerRecord): Option[RemotePeerInfo] =
if record.addresses.len == 0:
trace "kademlia record missing addresses", peerId = record.peerId
return none(RemotePeerInfo)
@ -132,17 +42,15 @@ proc remotePeerInfoFrom(record: ExtendedPeerRecord): Option[RemotePeerInfo] =
var mixPubKey = none(Curve25519Key)
for service in record.services:
debug "checking service",
peerId = record.peerId, serviceId = service.id, dataLen = service.data.len
mixPubKey = extractMixPubKey(service)
if mixPubKey.isSome():
debug "extracted mix public key from service", peerId = record.peerId
break
if service.id != MixProtocolID:
continue
if service.data.len != Curve25519KeySize:
continue
mixPubKey = some(intoCurve25519Key(service.data))
break
if record.services.len > 0 and mixPubKey.isNone():
debug "record has services but no valid mix key",
peerId = record.peerId, services = record.services.mapIt(it.id)
return none(RemotePeerInfo)
return some(
RemotePeerInfo.init(
record.peerId,
@ -153,128 +61,150 @@ proc remotePeerInfoFrom(record: ExtendedPeerRecord): Option[RemotePeerInfo] =
)
)
proc lookupMixPeers*(
wk: WakuKademlia
): Future[Result[int, string]] {.async: (raises: []).} =
## Lookup mix peers via kademlia and add them to the peer store.
## Returns the number of mix peers found and added.
if wk.protocol.isNil():
return err("cannot lookup mix peers: kademlia not mounted")
let mixService = ServiceInfo(id: MixProtocolID, data: @[])
var records: seq[ExtendedPeerRecord]
try:
records = await wk.protocol.lookup(mixService)
except CatchableError:
return err("mix peer lookup failed: " & getCurrentExceptionMsg())
debug "mix peer lookup returned records", numRecords = records.len
var added = 0
for record in records:
let peerOpt = remotePeerInfoFrom(record)
if peerOpt.isNone():
continue
let peerInfo = peerOpt.get()
if peerInfo.mixPubKey.isNone():
continue
wk.peerManager.addPeer(peerInfo, PeerOrigin.Kademlia)
info "mix peer added via kademlia lookup",
peerId = $peerInfo.peerId, mixPubKey = byteutils.toHex(peerInfo.mixPubKey.get())
added.inc()
info "mix peer lookup complete", found = added
return ok(added)
proc runDiscoveryLoop(
wk: WakuKademlia, interval: Duration, minMixPeers: int
) {.async: (raises: []).} =
info "extended kademlia discovery loop started", interval = interval
try:
while true:
# Wait for node to be started
if not wk.isNodeStarted.isNil() and not wk.isNodeStarted():
await sleepAsync(ExtendedKademliaDiscoveryStartupDelay)
continue
var records: seq[ExtendedPeerRecord]
try:
records = await wk.protocol.randomRecords()
except CatchableError as e:
warn "extended kademlia discovery failed", error = e.msg
await sleepAsync(interval)
continue
debug "received random records from kademlia", numRecords = records.len
var added = 0
for record in records:
let peerOpt = remotePeerInfoFrom(record)
if peerOpt.isNone():
continue
let peerInfo = peerOpt.get()
wk.peerManager.addPeer(peerInfo, PeerOrigin.Kademlia)
debug "peer added via extended kademlia discovery",
peerId = $peerInfo.peerId,
addresses = peerInfo.addrs.mapIt($it),
protocols = peerInfo.protocols,
hasMixPubKey = peerInfo.mixPubKey.isSome()
added.inc()
if added > 0:
info "added peers from extended kademlia discovery", count = added
# Targeted mix peer lookup when pool is low
if minMixPeers > 0 and not wk.getMixNodePoolSize.isNil() and
wk.getMixNodePoolSize() < minMixPeers:
debug "mix node pool below threshold, performing targeted lookup",
currentPoolSize = wk.getMixNodePoolSize(), threshold = minMixPeers
let found = (await wk.lookupMixPeers()).valueOr:
warn "targeted mix peer lookup failed", error = error
0
if found > 0:
info "found mix peers via targeted kademlia lookup", count = found
await sleepAsync(interval)
except CancelledError as e:
debug "extended kademlia discovery loop cancelled", error = e.msg
except CatchableError as e:
error "extended kademlia discovery loop failed", error = e.msg
proc start*(
wk: WakuKademlia,
interval: Duration = DefaultExtendedKademliaDiscoveryInterval,
minMixPeers: int = 0,
): Future[Result[void, string]] {.async: (raises: []).} =
if wk.running:
return err("already running")
try:
await wk.protocol.start()
except CatchableError as e:
return err("failed to start kademlia discovery: " & e.msg)
wk.discoveryLoop = wk.runDiscoveryLoop(interval, minMixPeers)
info "kademlia discovery started"
return ok()
proc stop*(wk: WakuKademlia) {.async: (raises: []).} =
if not wk.running:
#[ proc randomWalk*(
self: WakuKademlia
): Future[seq[RemotePeerInfo]] {.async: (raises: []).} =
let res = catch:
await self.protocol.randomRecords()
let records = res.valueOr:
error "kademlia discovery lookup failed", error = res.error.msg
return
info "Stopping kademlia discovery"
var peerInfos = newSeqOfCap[RemotePeerInfo](records.len)
for record in records:
let peerInfo = toRemotePeerInfo(record).valueOr:
continue
wk.running = false
self.peerManager.addPeer(peerInfo, PeerOrigin.Kademlia)
if not wk.discoveryLoop.isNil():
await wk.discoveryLoop.cancelAndWait()
wk.discoveryLoop = nil
debug "peer added via random walk",
peerId = $peerInfo.peerId,
addresses = peerInfo.addrs.mapIt($it),
protocols = peerInfo.protocols
if not wk.protocol.isNil():
await wk.protocol.stop()
info "Successfully stopped kademlia discovery"
peerInfos.add(peerInfo)
return peerInfos ]#
proc lookup*(
self: WakuKademlia, codec: string
): Future[seq[RemotePeerInfo]] {.async: (raises: []).} =
let serviceId = hashServiceId(codec)
let catchRes = catch:
await self.protocol.lookup(serviceId)
let lookupRes = catchRes.valueOr:
error "kademlia discovery lookup failed", error = catchRes.error.msg
return
let ads = lookupRes.valueOr:
error "kademlia discovery lookup failed", error
return
var peerInfos = newSeqOfCap[RemotePeerInfo](ads.len)
for ad in ads:
let peerInfo = toRemotePeerInfo(ad.data).valueOr:
continue
self.peerManager.addPeer(peerInfo, PeerOrigin.Kademlia)
debug "peer added via service discovery",
service = codec,
peerId = $peerInfo.peerId,
addresses = peerInfo.addrs.mapIt($it),
protocols = peerInfo.protocols
peerInfos.add(peerInfo)
return peerInfos
proc registerLookupService*(self: WakuKademlia, serviceId: string) =
if serviceId notin self.discoveredServices:
discard self.protocol.startDiscovering(serviceId)
self.discoveredServices.add(serviceId)
proc advertiseService*(self: WakuKademlia, service: ServiceInfo) =
self.protocol.addProvidedService(service)
self.registerLookupService(service.id)
#[ proc periodicRandomWalk(
self: WakuKademlia, interval: Duration
) {.async: (raises: [CancelledError]).} =
debug "periodic random walk started", interval = interval
while true:
await sleepAsync(interval)
discard await self.randomWalk() ]#
proc periodicLookup(
self: WakuKademlia, interval: Duration
) {.async: (raises: [CancelledError]).} =
debug "periodic service lookup started", interval = interval
while true:
await sleepAsync(interval)
let services = self.discoveredServices
if services.len == 0:
continue
for serviceId in services:
let peers = await self.lookup(serviceId)
debug "periodic lookup complete", service = serviceId, peerCount = peers.len
proc new*(
T: type WakuKademlia,
switch: Switch,
peerManager: PeerManager,
bootstrapNodes: seq[(PeerId, seq[MultiAddress])] = @[],
providedServices: seq[ServiceInfo] = @[],
loopInterval: Duration = DefaultKademliaDiscoveryInterval,
xprPublishing: bool = true,
disableBootstrapping: bool = false,
): T =
if bootstrapNodes.len == 0:
debug "creating kademlia discovery as seed node (no bootstrap nodes)"
let kademlia = ServiceDiscovery.new(
switch,
bootstrapNodes = bootstrapNodes,
config = KadDHTConfig.new(
validator = ExtEntryValidator(),
selector = ExtEntrySelector(),
disableBootstrapping = disableBootstrapping,
),
rng = switch.rng,
# change from defaults for local testing
discoConfig =
ServiceDiscoveryConfig.new(advertExpiry = 60.secs, ipSimCoefficient = 0.0),
services = providedServices,
xprPublishing = xprPublishing,
)
var initialServices: seq[string]
for svc in providedServices:
initialServices.add(svc.id)
return WakuKademlia(
protocol: kademlia,
peerManager: peerManager,
loopInterval: loopInterval,
discoveredServices: initialServices,
)
proc start*(self: WakuKademlia) =
#[ if self.periodicWalkFut.isNil():
self.periodicWalkFut = self.periodicRandomWalk(self.loopInterval) ]#
if self.periodicLookupFut.isNil():
self.periodicLookupFut = self.periodicLookup(self.loopInterval)
proc stop*(self: WakuKademlia) =
#[ if not self.periodicWalkFut.isNil():
self.periodicWalkFut.cancelSoon()
self.periodicWalkFut = nil ]#
if not self.periodicLookupFut.isNil():
self.periodicLookupFut.cancelSoon()
self.periodicLookupFut = nil

View File

@ -14,13 +14,14 @@ import
../discovery/waku_discv5,
../waku_node,
../node/peer_manager,
../node/waku_switch,
../common/rate_limit/setting,
../common/utils/parse_size_units,
../common/broker/broker_context
type
WakuNodeBuilder* = object # General
nodeRng: Option[ref crypto.HmacDrbgContext]
nodeRng: Option[crypto.Rng]
nodeKey: Option[crypto.PrivateKey]
netConfig: Option[NetConfig]
record: Option[enr.Record]
@ -56,7 +57,7 @@ proc init*(T: type WakuNodeBuilder): WakuNodeBuilder =
## General
proc withRng*(builder: var WakuNodeBuilder, rng: ref crypto.HmacDrbgContext) =
proc withRng*(builder: var WakuNodeBuilder, rng: crypto.Rng) =
builder.nodeRng = some(rng)
proc withNodeKey*(builder: var WakuNodeBuilder, nodeKey: crypto.PrivateKey) =
@ -156,7 +157,7 @@ proc withSwitchConfiguration*(
## Build
proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
var rng: ref crypto.HmacDrbgContext
var rng: crypto.Rng
if builder.nodeRng.isNone():
rng = crypto.newRng()
else:
@ -189,7 +190,7 @@ proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
wsAddress = builder.netConfig.get().wsHostAddress,
transportFlags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay},
rng = rng,
maxConnections = builder.switchMaxConnections.get(builders.MaxConnections),
maxConnections = builder.switchMaxConnections.get(MaxConnections),
wssEnabled = builder.netConfig.get().wssEnabled,
secureKeyPath = builder.switchSslSecureKey.get(""),
secureCertPath = builder.switchSslSecureCert.get(""),
@ -209,7 +210,7 @@ proc build*(builder: WakuNodeBuilder): Result[WakuNode, string] =
maxServicePeers = some(builder.maxServicePeers),
colocationLimit = builder.colocationLimit,
shardedPeerManagement = builder.shardAware,
maxConnections = builder.switchMaxConnections.get(builders.MaxConnections),
maxConnections = builder.switchMaxConnections.get(MaxConnections),
)
var node: WakuNode

View File

@ -1,5 +1,5 @@
import chronicles, std/options, results
import libp2p/crypto/crypto, libp2p/crypto/curve25519, libp2p/protocols/mix/curve25519
import libp2p/crypto/crypto, libp2p/crypto/curve25519, libp2p_mix/curve25519
import ../waku_conf, waku/waku_mix
logScope:
@ -11,7 +11,6 @@ logScope:
type MixConfBuilder* = object
enabled: Option[bool]
mixKey: Option[string]
mixNodes: seq[MixNodePubInfo]
proc init*(T: type MixConfBuilder): MixConfBuilder =
MixConfBuilder()
@ -22,9 +21,6 @@ proc withEnabled*(b: var MixConfBuilder, enabled: bool) =
proc withMixKey*(b: var MixConfBuilder, mixKey: string) =
b.mixKey = some(mixKey)
proc withMixNodes*(b: var MixConfBuilder, mixNodes: seq[MixNodePubInfo]) =
b.mixNodes = mixNodes
proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
if not b.enabled.get(false):
return ok(none[MixConf]())
@ -32,12 +28,8 @@ proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
if b.mixKey.isSome():
let mixPrivKey = intoCurve25519Key(ncrutils.fromHex(b.mixKey.get()))
let mixPubKey = public(mixPrivKey)
return ok(
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes))
)
return ok(some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey)))
else:
let (mixPrivKey, mixPubKey) = generateKeyPair().valueOr:
return err("Generate key pair error: " & $error)
return ok(
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes))
)
return ok(some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey)))

View File

@ -283,13 +283,13 @@ proc withStaticNodes*(builder: var WakuConfBuilder, staticNodes: seq[string]) =
## Building
proc nodeKey(
builder: WakuConfBuilder, rng: ref HmacDrbgContext
builder: WakuConfBuilder, rng: crypto.Rng
): Result[crypto.PrivateKey, string] =
if builder.nodeKey.isSome():
return ok(builder.nodeKey.get())
else:
warn "missing node key, generating new set"
let nodeKey = crypto.PrivateKey.random(Secp256k1, rng[]).valueOr:
let nodeKey = crypto.PrivateKey.random(Secp256k1, rng).valueOr:
error "Failed to generate key", error = error
return err("Failed to generate key: " & $error)
return ok(nodeKey)
@ -433,7 +433,7 @@ proc applyNetworkConf(builder: var WakuConfBuilder) =
warn "Failed to process entry nodes from network conf", error = processed.error()
proc build*(
builder: var WakuConfBuilder, rng: ref HmacDrbgContext = crypto.newRng()
builder: var WakuConfBuilder, rng: crypto.Rng = crypto.newRng()
): Result[WakuConf, string] =
## Return a WakuConf that contains all mandatory parameters
## Applies some sane defaults that are applicable across any usage

View File

@ -1,5 +1,5 @@
import
std/[options, sequtils],
std/[options, sequtils, sugar],
chronicles,
chronos,
libp2p/peerid,
@ -7,7 +7,9 @@ import
libp2p/protocols/connectivity/relay/relay,
libp2p/nameresolving/dnsresolver,
libp2p/crypto/crypto,
libp2p/crypto/curve25519
libp2p/crypto/curve25519,
libp2p/extended_peer_record,
libp2p_mix/mix_protocol
import
./internal_config,
@ -30,6 +32,7 @@ import
../waku_filter_v2,
../waku_peer_exchange,
../discovery/waku_kademlia,
../waku_mix/protocol,
../node/peer_manager,
../node/peer_manager/peer_store/waku_peer_storage,
../node/peer_manager/peer_store/migrations as peer_store_sqlite_migrations,
@ -54,7 +57,7 @@ proc setupPeerStorage(): Result[Option[WakuPeerStorage], string] =
proc initNode(
conf: WakuConf,
netConfig: NetConfig,
rng: ref HmacDrbgContext,
rng: crypto.Rng,
record: enr.Record,
peerStore: Option[WakuPeerStorage],
relay: Relay,
@ -121,10 +124,11 @@ proc initNode(
builder.withRateLimit(conf.rateLimit)
builder.withCircuitRelay(relay)
let node = ?builder.build().mapErr(
proc(err: string): string =
"failed to create waku node instance: " & err
)
let node =
?builder.build().mapErr(
proc(err: string): string =
"failed to create waku node instance: " & err
)
ok(node)
@ -159,38 +163,22 @@ proc setupProtocols(
error "Unrecoverable error occurred", error = msg
quit(QuitFailure)
var providedServices: seq[ServiceInfo]
# For testing lets use only one hard-coded service
let deliveryService = ServiceInfo(id: "delivery", data: @[])
providedServices.add(deliveryService)
#mount mix
if conf.mixConf.isSome():
let mixConf = conf.mixConf.get()
(await node.mountMix(conf.clusterId, mixConf.mixKey, mixConf.mixnodes)).isOkOr:
#let mixService = ServiceInfo(id: MixProtocolID, data: @(mixConf.mixPubKey))
#providedServices.add(mixService)
(await node.mountMix(mixConf.mixKey)).isOkOr:
return err("failed to mount waku mix protocol: " & $error)
# Setup extended kademlia discovery
if conf.kademliaDiscoveryConf.isSome():
let mixPubKey =
if conf.mixConf.isSome():
some(conf.mixConf.get().mixPubKey)
else:
none(Curve25519Key)
node.wakuKademlia = WakuKademlia.new(
node.switch,
ExtendedKademliaDiscoveryParams(
bootstrapNodes: conf.kademliaDiscoveryConf.get().bootstrapNodes,
mixPubKey: mixPubKey,
advertiseMix: conf.mixConf.isSome(),
),
node.peerManager,
getMixNodePoolSize = proc(): int {.gcsafe, raises: [].} =
if node.wakuMix.isNil():
0
else:
node.getMixNodePoolSize(),
isNodeStarted = proc(): bool {.gcsafe, raises: [].} =
node.started,
).valueOr:
return err("failed to setup kademlia discovery: " & error)
if conf.storeServiceConf.isSome():
let storeServiceConf = conf.storeServiceConf.get()
@ -214,6 +202,9 @@ proc setupProtocols(
except CatchableError:
return err("failed to mount waku store protocol: " & getCurrentExceptionMsg())
#let storeService = ServiceInfo(id: WakuStoreCodec, data: @[])
#providedServices.add(storeService)
if storeServiceConf.storeSyncConf.isSome():
let confStoreSync = storeServiceConf.storeSyncConf.get()
@ -226,6 +217,11 @@ proc setupProtocols(
).isOkOr:
return err("failed to mount waku store sync protocol: " & $error)
#let reconciliationService = ServiceInfo(id: WakuReconciliationCodec, data: @[])
#let transferService = ServiceInfo(id: WakuTransferCodec, data: @[])
#providedServices.add(reconciliationService)
#providedServices.add(transferService)
if conf.remoteStoreNode.isSome():
let storeNode = parsePeerInfo(conf.remoteStoreNode.get()).valueOr:
return err("failed to set node waku store-sync peer: " & error)
@ -309,10 +305,16 @@ proc setupProtocols(
protectedShard = shardKey.shard, publicKey = shardKey.key
node.wakuRelay.addSignedShardsValidator(subscribedProtectedShards, conf.clusterId)
#let relayService = ServiceInfo(id: WakuRelayCodec, data: @[])
#providedServices.add(relayService)
if conf.rendezvous:
await node.mountRendezvous(conf.clusterId, shards)
await node.mountRendezvousClient(conf.clusterId)
#let rendezvousService = ServiceInfo(id: WakuRendezVousCodec, data: @[])
#providedServices.add(rendezvousService)
# Keepalive mounted on all nodes
try:
await mountLibp2pPing(node)
@ -349,6 +351,9 @@ proc setupProtocols(
except CatchableError:
return err("failed to mount waku lightpush protocol: " & getCurrentExceptionMsg())
#let lightpushService = ServiceInfo(id: WakuLightPushCodec, data: @[])
#providedServices.add(lightpushService)
mountLightPushClient(node)
mountLegacyLightPushClient(node)
if conf.remoteLightPushNode.isSome():
@ -371,6 +376,9 @@ proc setupProtocols(
except CatchableError:
return err("failed to mount waku filter protocol: " & getCurrentExceptionMsg())
#let filterService = ServiceInfo(id: WakuFilterPushCodec, data: @[])
#providedServices.add(filterService)
await node.mountFilterClient()
if conf.remoteFilterNode.isSome():
let filterNode = parsePeerInfo(conf.remoteFilterNode.get()).valueOr:
@ -391,6 +399,9 @@ proc setupProtocols(
return
err("failed to mount waku peer-exchange protocol: " & getCurrentExceptionMsg())
#let peerXchangeService = ServiceInfo(id: WakuPeerExchangeCodec, data: @[])
#providedServices.add(peerXchangeService)
if conf.remotePeerExchangeNode.isSome():
let peerExchangeNode = parsePeerInfo(conf.remotePeerExchangeNode.get()).valueOr:
return err("failed to set node waku peer-exchange peer: " & error)
@ -399,6 +410,25 @@ proc setupProtocols(
if conf.peerExchangeDiscovery:
await node.mountPeerExchangeClient()
if conf.kademliaDiscoveryConf.isSome():
let kademlia = WakuKademlia.new(
node.switch,
node.peerManager,
conf.kademliaDiscoveryConf.get().bootstrapNodes,
providedServices,
)
let catchRes = catch:
node.switch.mount(kademlia.protocol)
if catchRes.isErr():
return err("failed to mount kademlia discovery: " & catchRes.error.msg)
node.wakuKademlia = kademlia
# Connect kademlia to mix for peer discovery
if not node.wakuMix.isNil() and not node.wakuKademlia.isNil():
node.wakuMix.setKademlia(node.wakuKademlia)
return ok()
## Start node
@ -450,15 +480,10 @@ proc startNode*(
if conf.relay:
node.peerManager.start()
if not node.wakuKademlia.isNil():
let minMixPeers = if conf.mixConf.isSome(): 4 else: 0
(await node.wakuKademlia.start(minMixPeers = minMixPeers)).isOkOr:
return err("failed to start kademlia discovery: " & error)
return ok()
proc setupNode*(
wakuConf: WakuConf, rng: ref HmacDrbgContext = crypto.newRng(), relay: Relay
wakuConf: WakuConf, rng: crypto.Rng = crypto.newRng(), relay: Relay
): Future[Result[WakuNode, string]] {.async.} =
let netConfig = (
await networkConfiguration(

View File

@ -59,7 +59,7 @@ const git_version* {.strdefine.} = "n/a"
type Waku* = ref object
stateInfo*: WakuStateInfo
conf*: WakuConf
rng*: ref HmacDrbgContext
rng*: crypto.Rng
key: crypto.PrivateKey
@ -81,7 +81,7 @@ type Waku* = ref object
brokerCtx*: BrokerContext
proc setupSwitchServices(
waku: Waku, conf: WakuConf, circuitRelay: Relay, rng: ref HmacDrbgContext
waku: Waku, conf: WakuConf, circuitRelay: Relay, rng: crypto.Rng
) =
proc onReservation(addresses: seq[MultiAddress]) {.gcsafe, raises: [].} =
info "circuit relay handler new reserve event",

View File

@ -50,7 +50,6 @@ type StoreSyncConf* {.requiresInit.} = object
type MixConf* = ref object
mixKey*: Curve25519Key
mixPubKey*: Curve25519Key
mixnodes*: seq[MixNodePubInfo]
type KademliaDiscoveryConf* = object
bootstrapNodes*: seq[(PeerId, seq[MultiAddress])]

View File

@ -17,7 +17,7 @@ import
libp2p/transports/tcptransport,
libp2p/transports/wstransport,
libp2p/utility,
libp2p/protocols/mix
libp2p_mix
import
../waku_node,

View File

@ -23,6 +23,7 @@ import
common/utils/parse_size_units,
common/broker/broker_context,
node/health_monitor/online_monitor,
node/waku_switch,
],
./peer_store/peer_storage,
./waku_peer_store

View File

@ -7,7 +7,8 @@ import
eth/p2p/discoveryv5/enr,
libp2p/builders,
libp2p/peerstore,
libp2p/crypto/curve25519
libp2p/crypto/curve25519,
libp2p_mix/pool
import
../../waku_core,

View File

@ -8,7 +8,6 @@ import
results,
eth/keys,
nimcrypto,
bearssl/rand,
stew/byteutils,
eth/p2p/discoveryv5/enr,
libp2p/crypto/crypto,
@ -23,8 +22,8 @@ import
libp2p/transports/wstransport,
libp2p/utility,
libp2p/utils/offsettedseq,
libp2p/protocols/mix,
libp2p/protocols/mix/mix_protocol
libp2p_mix,
libp2p_mix/mix_protocol
import
waku/[
@ -126,7 +125,7 @@ type
wakuAutoSharding*: Option[Sharding]
enr*: enr.Record
libp2pPing*: Ping
rng*: ref rand.HmacDrbgContext
rng*: crypto.Rng
brokerCtx*: BrokerContext
wakuRendezvous*: WakuRendezVous
wakuRendezvousClient*: rendezvous_client.WakuRendezVousClient
@ -206,7 +205,7 @@ proc new*(
peerManager: PeerManager,
rateLimitSettings: ProtocolRateLimitSettings = DefaultProtocolRateLimit,
# TODO: make this argument required after tests are updated
rng: ref HmacDrbgContext = crypto.newRng(),
rng: crypto.Rng = crypto.newRng(),
): T {.raises: [Defect, LPError, IOError, TLSStreamProtocolError].} =
## Creates a Waku Node instance.
@ -297,10 +296,7 @@ proc getMixNodePoolSize*(node: WakuNode): int =
return node.wakuMix.poolSize()
proc mountMix*(
node: WakuNode,
clusterId: uint16,
mixPrivKey: Curve25519Key,
mixnodes: seq[MixNodePubInfo],
node: WakuNode, mixPrivKey: Curve25519Key
): Future[Result[void, string]] {.async.} =
info "mounting mix protocol", nodeId = node.info #TODO log the config used
@ -312,10 +308,13 @@ proc mountMix*(
info "local addr", localaddr = localaddrStr
node.wakuMix = WakuMix.new(
localaddrStr, node.peerManager, clusterId, mixPrivKey, mixnodes
mixPrivKey = mixPrivKey,
nodeAddr = localaddrStr,
switch = node.switch,
wakuKademlia = node.wakuKademlia,
).valueOr:
error "Waku Mix protocol initialization failed", err = error
return
return err("Waku Mix protocol initialization failed: " & error)
#TODO: should we do the below only for exit node? Also, what if multiple protocols use mix?
node.wakuMix.registerDestReadBehavior(WakuLightPushCodec, readLp(int(-1)))
let catchRes = catch:
@ -573,6 +572,9 @@ proc start*(node: WakuNode) {.async.} =
if not node.wakuRendezvousClient.isNil():
await node.wakuRendezvousClient.start()
if not node.wakuKademlia.isNil():
node.wakuKademlia.start()
## The switch uses this mapper to update peer info addrs
## with announced addrs after start
let addressMapper = proc(
@ -632,12 +634,12 @@ proc stop*(node: WakuNode) {.async.} =
not node.wakuPeerExchangeClient.pxLoopHandle.isNil():
await node.wakuPeerExchangeClient.pxLoopHandle.cancelAndWait()
if not node.wakuKademlia.isNil():
await node.wakuKademlia.stop()
if not node.wakuRendezvousClient.isNil():
await node.wakuRendezvousClient.stopWait()
if not node.wakuKademlia.isNil():
node.wakuKademlia.stop()
node.started = false
proc isReady*(node: WakuNode): Future[bool] {.async: (raises: [Exception]).} =

View File

@ -9,20 +9,25 @@ import
libp2p/crypto/crypto,
libp2p/protocols/pubsub/gossipsub,
libp2p/protocols/rendezvous,
libp2p/protocols/connectivity/relay/relay,
libp2p/protocols/connectivity/relay/[client, relay],
libp2p/protocols/connectivity/autonat/[client, service],
libp2p/services/hpservice,
libp2p/services/autorelayservice,
libp2p/nameresolving/nameresolver,
libp2p/builders,
libp2p/switch,
libp2p/transports/[transport, tcptransport, wstransport]
libp2p/transports/[transport, tcptransport, wstransport],
libp2p/peeraddrpolicy
# override nim-libp2p default value (which is also 1)
# override nim-libp2p default values (which are also 50 & 1)
const MaxConnections* = 50
const MaxConnectionsPerPeer* = 1
proc withWsTransport*(b: SwitchBuilder): SwitchBuilder =
#[ proc withWsTransport*(b: SwitchBuilder): SwitchBuilder =
b.withTransport(
proc(upgr: Upgrade, privateKey: crypto.PrivateKey): Transport =
WsTransport.new(upgr)
)
) ]#
proc getSecureKey(path: string): TLSPrivateKey {.raises: [Defect, IOError].} =
trace "Key path is.", path = path
@ -42,7 +47,7 @@ proc getSecureCert(path: string): TLSCertificate {.raises: [Defect, IOError].} =
except TLSStreamProtocolError as exc:
info "exception raised from getSecureCert", err = exc.msg
proc withWssTransport*(
#[ proc withWssTransport*(
b: SwitchBuilder, secureKeyPath: string, secureCertPath: string
): SwitchBuilder {.raises: [Defect, IOError].} =
let key: TLSPrivateKey = getSecureKey(secureKeyPath)
@ -51,7 +56,7 @@ proc withWssTransport*(
tlsPrivateKey = key,
tlsCertificate = cert,
{TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}, # THIS IS INSECURE, NO?
)
) ]#
proc newWakuSwitch*(
privKey = none(crypto.PrivateKey),
@ -59,12 +64,12 @@ proc newWakuSwitch*(
wsAddress = none(MultiAddress),
secureManagers: openarray[SecureProtocol] = [SecureProtocol.Noise],
transportFlags: set[ServerFlags] = {},
rng: ref HmacDrbgContext,
rng: crypto.Rng,
inTimeout: Duration = 5.minutes,
outTimeout: Duration = 5.minutes,
maxConnections = MaxConnections,
maxIn = -1,
maxOut = -1,
maxIn = int.high,
maxOut = int.high,
maxConnsPerPeer = MaxConnectionsPerPeer,
nameResolver: NameResolver = nil,
sendSignedPeerRecord = false,
@ -73,15 +78,20 @@ proc newWakuSwitch*(
secureCertPath: string = "",
agentString = none(string), # defaults to nim-libp2p version
peerStoreCapacity = none(int), # defaults to 1.25 maxConnections
rendezvous: RendezVous = nil,
rendezvous: RendezVousConfig = nil,
circuitRelay: Relay,
maxNumRelays: int = 5,
): Switch {.raises: [Defect, IOError, LPError].} =
let
autonatService = AutonatService.new(AutonatClient(), rng)
autoRelayService = AutoRelayService.new(maxNumRelays, RelayClient.new(), nil, rng)
hpService: Service = HPService.new(autonatService, autoRelayService)
var b = SwitchBuilder
.new()
.withRng(rng)
.withMaxConnections(maxConnections)
.withMaxIn(maxIn)
.withMaxOut(maxOut)
.withMaxInOut(maxIn, maxOut)
.withMaxConnsPerPeer(maxConnsPerPeer)
.withYamux()
.withMplex(inTimeout, outTimeout)
@ -89,8 +99,9 @@ proc newWakuSwitch*(
.withTcpTransport(transportFlags)
.withNameResolver(nameResolver)
.withSignedPeerRecord(sendSignedPeerRecord)
.withCircuitRelay(circuitRelay)
.withAutonat()
#.withAddressPolicy(publicRoutableAddressPolicy)
#.withCircuitRelay(circuitRelay)
#.withServices(@[hpService])
if peerStoreCapacity.isSome():
b = b.withPeerStore(peerStoreCapacity.get())
@ -104,10 +115,10 @@ proc newWakuSwitch*(
if wsAddress.isSome():
b = b.withAddresses(@[wsAddress.get(), address])
if wssEnabled:
#[ if wssEnabled:
b = b.withWssTransport(secureKeyPath, secureCertPath)
else:
b = b.withWsTransport()
b = b.withWsTransport() ]#
else:
b = b.withAddress(address)

View File

@ -2,9 +2,9 @@
{.push raises: [].}
import bearssl/rand, stew/byteutils
import libp2p/crypto/crypto, stew/byteutils
proc generateRequestId*(rng: ref HmacDrbgContext): string =
proc generateRequestId*(rng: crypto.Rng): string =
var bytes: array[10, byte]
hmacDrbgGenerate(rng[], bytes)
rng.generate(bytes)
return byteutils.toHex(bytes)

View File

@ -3,7 +3,7 @@
import
std/[options, bitops, sequtils, net, tables], results, eth/keys, libp2p/crypto/crypto
import ../common/enr, ../waku_core/codecs
import libp2p/protocols/mix
import libp2p_mix
const CapabilitiesEnrField* = "waku2"

View File

@ -7,7 +7,7 @@ import
chronicles,
chronos,
libp2p/protocols/protocol,
bearssl/rand,
libp2p/crypto/crypto,
stew/byteutils
import
waku/
@ -22,13 +22,13 @@ logScope:
type WakuFilterClient* = ref object of LPProtocol
brokerCtx: BrokerContext
rng: ref HmacDrbgContext
rng: Rng
peerManager: PeerManager
pushHandlers: seq[FilterPushHandler]
func generateRequestId(rng: ref HmacDrbgContext): string =
func generateRequestId(rng: crypto.Rng): string =
var bytes: array[10, byte]
hmacDrbgGenerate(rng[], bytes)
rng.generate(bytes)
return byteutils.toHex(bytes)
proc sendSubscribeRequest(
@ -210,7 +210,7 @@ proc initProtocolHandler(wfc: WakuFilterClient) =
wfc.codec = WakuFilterPushCodec
proc new*(
T: type WakuFilterClient, peerManager: PeerManager, rng: ref HmacDrbgContext
T: type WakuFilterClient, peerManager: PeerManager, rng: crypto.Rng
): T =
let brokerCtx = globalBrokerContext()
let wfc = WakuFilterClient(

View File

@ -1,6 +1,6 @@
{.push raises: [].}
import std/options, results, chronicles, chronos, metrics, bearssl/rand, stew/byteutils
import std/options, results, chronicles, chronos, metrics, libp2p/crypto/crypto, stew/byteutils
import libp2p/peerid, libp2p/stream/connection
import
../waku_core/peers,
@ -16,11 +16,11 @@ logScope:
topics = "waku lightpush client"
type WakuLightPushClient* = ref object
rng*: ref rand.HmacDrbgContext
rng*: Rng
peerManager*: PeerManager
proc new*(
T: type WakuLightPushClient, peerManager: PeerManager, rng: ref rand.HmacDrbgContext
T: type WakuLightPushClient, peerManager: PeerManager, rng: crypto.Rng
): T =
WakuLightPushClient(peerManager: peerManager, rng: rng)

View File

@ -7,7 +7,7 @@ import
chronicles,
chronos,
metrics,
bearssl/rand
libp2p/crypto/crypto
import
../node/peer_manager/peer_manager,
../waku_core,
@ -22,7 +22,7 @@ logScope:
topics = "waku lightpush"
type WakuLightPush* = ref object of LPProtocol
rng*: ref rand.HmacDrbgContext
rng*: Rng
peerManager*: PeerManager
pushHandler*: PushMessageHandler
requestRateLimiter*: RequestRateLimiter
@ -156,7 +156,7 @@ proc initProtocolHandler(wl: WakuLightPush) =
proc new*(
T: type WakuLightPush,
peerManager: PeerManager,
rng: ref rand.HmacDrbgContext,
rng: crypto.Rng,
pushHandler: PushMessageHandler,
autoSharding: Option[Sharding],
rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](),

View File

@ -1,6 +1,6 @@
{.push raises: [].}
import std/options, results, chronicles, chronos, metrics, bearssl/rand, stew/byteutils
import std/options, results, chronicles, chronos, metrics, libp2p/crypto/crypto, stew/byteutils
import libp2p/peerid
import
../waku_core/peers,
@ -17,12 +17,12 @@ logScope:
type WakuLegacyLightPushClient* = ref object
peerManager*: PeerManager
rng*: ref rand.HmacDrbgContext
rng*: Rng
proc new*(
T: type WakuLegacyLightPushClient,
peerManager: PeerManager,
rng: ref rand.HmacDrbgContext,
rng: crypto.Rng,
): T =
WakuLegacyLightPushClient(peerManager: peerManager, rng: rng)

View File

@ -1,6 +1,6 @@
{.push raises: [].}
import std/options, results, stew/byteutils, chronicles, chronos, metrics, bearssl/rand
import std/options, results, stew/byteutils, chronicles, chronos, metrics, libp2p/crypto/crypto
import
../node/peer_manager/peer_manager,
../waku_core,
@ -14,7 +14,7 @@ logScope:
topics = "waku lightpush legacy"
type WakuLegacyLightPush* = ref object of LPProtocol
rng*: ref rand.HmacDrbgContext
rng*: Rng
peerManager*: PeerManager
pushHandler*: PushMessageHandler
requestRateLimiter*: RequestRateLimiter
@ -116,7 +116,7 @@ proc initProtocolHandler(wl: WakuLegacyLightPush) =
proc new*(
T: type WakuLegacyLightPush,
peerManager: PeerManager,
rng: ref rand.HmacDrbgContext,
rng: crypto.Rng,
pushHandler: PushMessageHandler,
rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](),
): T =

View File

@ -5,103 +5,130 @@ import chronicles, std/options, chronos, results, metrics
import
libp2p/crypto/curve25519,
libp2p/crypto/crypto,
libp2p/protocols/mix,
libp2p/protocols/mix/mix_node,
libp2p/protocols/mix/mix_protocol,
libp2p/protocols/mix/mix_metrics,
libp2p/protocols/mix/delay_strategy,
libp2p/[multiaddress, peerid],
libp2p_mix,
libp2p_mix/mix_node,
libp2p_mix/mix_protocol,
libp2p_mix/mix_metrics,
libp2p_mix/delay_strategy,
libp2p_mix/delay,
libp2p/[multiaddress, peerid, switch],
libp2p/extended_peer_record,
eth/common/keys
import
waku/node/peer_manager,
waku/waku_core,
waku/waku_enr,
waku/node/peer_manager/waku_peer_store
waku/node/peer_manager/waku_peer_store,
waku/discovery/waku_kademlia
logScope:
topics = "waku mix"
const minMixPoolSize = 4
const
MinimumMixPoolSize = 4
DefaultMixPoolMaintenanceInterval = chronos.seconds(10)
type
WakuMix* = ref object of MixProtocol
peerManager*: PeerManager
clusterId: uint16
pubKey*: Curve25519Key
type WakuMix* = ref object of MixProtocol
pubKey*: Curve25519Key
targetMixPoolSize: int
currentMixPoolSize: int
maintenanceInterval: Duration
maintenanceIntervalFut: Future[void]
wakuKademlia: WakuKademlia
WakuMixResult*[T] = Result[T, string]
proc poolSize*(self: WakuMix): int =
if self.nodePool.isNil():
0
else:
self.nodePool.len()
MixNodePubInfo* = object
multiAddr*: string
pubKey*: Curve25519Key
proc mixPoolMaintenance(
self: WakuMix, interval: Duration
) {.async: (raises: [CancelledError]).} =
debug "mix pool maintenance loop started", interval = interval
proc processBootNodes(
bootnodes: seq[MixNodePubInfo], peermgr: PeerManager, mix: WakuMix
) =
var count = 0
for node in bootnodes:
let pInfo = parsePeerInfo(node.multiAddr).valueOr:
error "Failed to get peer id from multiaddress: ",
error = error, multiAddr = $node.multiAddr
continue
let peerId = pInfo.peerId
var peerPubKey: crypto.PublicKey
if not peerId.extractPublicKey(peerPubKey):
warn "Failed to extract public key from peerId, skipping node", peerId = peerId
while true:
await sleepAsync(interval)
self.currentMixPoolSize = self.poolSize()
mix_pool_size.set(self.currentMixPoolSize.int64)
if self.currentMixPoolSize >= self.targetMixPoolSize:
continue
if peerPubKey.scheme != PKScheme.Secp256k1:
warn "Peer public key is not Secp256k1, skipping node",
peerId = peerId, scheme = peerPubKey.scheme
# Skip discovery if kademlia not available
if self.wakuKademlia.isNil():
debug "kademlia not available for mix peer discovery"
continue
let multiAddr = MultiAddress.init(node.multiAddr).valueOr:
error "Failed to parse multiaddress", multiAddr = node.multiAddr, error = error
continue
trace "mix node pool below threshold, performing targeted lookup",
currentPoolSize = self.currentMixPoolSize, threshold = self.targetMixPoolSize
let mixPubInfo = MixPubInfo.init(peerId, multiAddr, node.pubKey, peerPubKey.skkey)
mix.nodePool.add(mixPubInfo)
count.inc()
let mixPeers = await self.wakuKademlia.lookup(MixProtocolID)
peermgr.addPeer(
RemotePeerInfo.init(peerId, @[multiAddr], mixPubKey = some(node.pubKey))
)
mix_pool_size.set(count)
info "using mix bootstrap nodes ", count = count
trace "mix peer discovery completed", discoveredPeers = mixPeers.len
proc new*(
T: typedesc[WakuMix],
nodeAddr: string,
peermgr: PeerManager,
clusterId: uint16,
mixPrivKey: Curve25519Key,
bootnodes: seq[MixNodePubInfo],
): WakuMixResult[T] =
nodeAddr: string,
switch: Switch,
targetMixPoolSize: int = MinimumMixPoolSize,
maintenanceInterval: Duration = DefaultMixPoolMaintenanceInterval,
wakuKademlia: WakuKademlia = nil,
): Result[T, string] =
let mixPubKey = public(mixPrivKey)
info "mixPubKey", mixPubKey = mixPubKey
debug "Mix Public Key", mixPubKey = mixPubKey
let nodeMultiAddr = MultiAddress.init(nodeAddr).valueOr:
return err("failed to parse mix node address: " & $nodeAddr & ", error: " & error)
let localMixNodeInfo = initMixNodeInfo(
peermgr.switch.peerInfo.peerId, nodeMultiAddr, mixPubKey, mixPrivKey,
peermgr.switch.peerInfo.publicKey.skkey, peermgr.switch.peerInfo.privateKey.skkey,
switch.peerInfo.peerId, nodeMultiAddr, mixPubKey, mixPrivKey,
switch.peerInfo.publicKey.skkey, switch.peerInfo.privateKey.skkey,
)
var m = WakuMix(peerManager: peermgr, clusterId: clusterId, pubKey: mixPubKey)
procCall MixProtocol(m).init(
localMixNodeInfo,
peermgr.switch,
delayStrategy =
ExponentialDelayStrategy.new(meanDelayMs = 50, rng = crypto.newRng()),
let mix = WakuMix(
pubKey: mixPubKey,
targetMixPoolSize: targetMixPoolSize,
currentMixPoolSize: 0,
maintenanceInterval: maintenanceInterval,
maintenanceIntervalFut: nil,
wakuKademlia: wakuKademlia,
)
processBootNodes(bootnodes, peermgr, m)
procCall MixProtocol(mix).init(localMixNodeInfo, switch)
if m.nodePool.len < minMixPoolSize:
warn "publishing with mix won't work until atleast 3 mix nodes in node pool"
return ok(m)
return ok(mix)
proc poolSize*(mix: WakuMix): int =
mix.nodePool.len
proc setKademlia*(self: WakuMix, wakuKademlia: WakuKademlia) =
self.wakuKademlia = wakuKademlia
# Mix Protocol
method start*(self: WakuMix) {.async.} =
if self.started:
warn "Starting Waku Mix twice"
return
info "Starting Waku Mix"
await procCall start(MixProtocol(self))
self.maintenanceIntervalFut = self.mixPoolMaintenance(self.maintenanceInterval)
info "Waku Mix Started"
method stop*(self: WakuMix) {.async.} =
if not self.started:
return
info "Stopping Waku Mix"
if not self.maintenanceIntervalFut.isNil():
self.maintenanceIntervalFut.cancelSoon()
self.maintenanceIntervalFut = nil
await procCall stop(MixProtocol(self))
info "Successfully stopped Waku Mix"

View File

@ -12,7 +12,7 @@ import std/[options, strutils]
import stew/byteutils
import chronos
import chronicles
import bearssl/rand
import libp2p/crypto/crypto
import stew/endians2
import nimcrypto/[sha2, hmac]
@ -168,9 +168,9 @@ proc setCipherStateKey*(cs: var CipherState, key: ChaChaPolyKey) =
cs.k = key
# Generates a random Symmetric Cipher State for test purposes
proc randomCipherState*(rng: var HmacDrbgContext, nonce: uint64 = 0): CipherState =
proc randomCipherState*(rng: crypto.Rng, nonce: uint64 = 0): CipherState =
var randomCipherState: CipherState
hmacDrbgGenerate(rng, randomCipherState.k)
rng.generate(randomCipherState.k)
setNonce(randomCipherState, nonce)
return randomCipherState

View File

@ -7,7 +7,7 @@
import std/[options, strutils, tables]
import chronos
import chronicles
import bearssl/rand
import libp2p/crypto/crypto
import results
import libp2p/crypto/[chacha20poly1305, curve25519]
@ -237,7 +237,7 @@ proc processMessagePatternPayload(
# We process an input handshake message according to current handshake state and we return the next handshake step's handshake message
proc processMessagePatternTokens(
rng: var rand.HmacDrbgContext,
rng: crypto.Rng,
hs: var HandshakeState,
inputHandshakeMessage: seq[NoisePublicKey] = @[],
): Result[seq[NoisePublicKey], cstring] {.
@ -480,7 +480,7 @@ proc initialize*(
# If the user is writing the handshake message, the transport message (if not empty) and eventually a non-empty message nametag has to be passed to transportMessage and messageNametag and readPayloadV2 can be left to its default value
# It the user is reading the handshake message, the read payload v2 has to be passed to readPayloadV2 and the transportMessage can be left to its default values. Decryption is skipped if the payloadv2 read doesn't have a message nametag equal to messageNametag (empty input nametags are converted to all-0 MessageNametagLength bytes arrays)
proc stepHandshake*(
rng: var rand.HmacDrbgContext,
rng: crypto.Rng,
hs: var HandshakeState,
readPayloadV2: PayloadV2 = default(PayloadV2),
transportMessage: seq[byte] = @[],

View File

@ -8,7 +8,7 @@
import std/[algorithm, base64, oids, options, strutils, tables, sequtils]
import chronos
import chronicles
import bearssl/rand
import libp2p/crypto/crypto
import results
import stew/[endians2, byteutils]
import nimcrypto/sha2
@ -28,9 +28,9 @@ logScope:
#################################
# Generates random byte sequences of given size
proc randomSeqByte*(rng: var HmacDrbgContext, size: int): seq[byte] =
proc randomSeqByte*(rng: crypto.Rng, size: int): seq[byte] =
var output = newSeq[byte](size.uint32)
hmacDrbgGenerate(rng, output)
rng.generate(output)
return output
# Pads a payload according to PKCS#7 as per RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3
@ -149,7 +149,7 @@ proc isDefault*[T](value: T): bool =
#################################
# Generate random (public, private) Elliptic Curve key pairs
proc genKeyPair*(rng: var HmacDrbgContext): KeyPair =
proc genKeyPair*(rng: crypto.Rng): KeyPair =
var keyPair: KeyPair
keyPair.privateKey = EllipticCurveKey.random(rng)
keyPair.publicKey = keyPair.privateKey.public()
@ -319,18 +319,18 @@ proc dh*(private: EllipticCurveKey, public: EllipticCurveKey): EllipticCurveKey
#################################
# Generates a random ChaChaPolyKey for testing encryption/decryption
proc randomChaChaPolyKey*(rng: var HmacDrbgContext): ChaChaPolyKey =
proc randomChaChaPolyKey*(rng: crypto.Rng): ChaChaPolyKey =
var key: ChaChaPolyKey
hmacDrbgGenerate(rng, key)
rng.generate(key)
return key
# Generates a random ChaChaPoly Cipher State for testing encryption/decryption
proc randomChaChaPolyCipherState*(rng: var HmacDrbgContext): ChaChaPolyCipherState =
proc randomChaChaPolyCipherState*(rng: crypto.Rng): ChaChaPolyCipherState =
var randomCipherState: ChaChaPolyCipherState
randomCipherState.k = randomChaChaPolyKey(rng)
hmacDrbgGenerate(rng, randomCipherState.nonce)
rng.generate(randomCipherState.nonce)
randomCipherState.ad = newSeq[byte](32)
hmacDrbgGenerate(rng, randomCipherState.ad)
rng.generate(randomCipherState.ad)
return randomCipherState
#################################################################
@ -351,7 +351,7 @@ proc toNoisePublicKey*(publicKey: EllipticCurveKey): NoisePublicKey =
return noisePublicKey
# Generates a random Noise public key
proc genNoisePublicKey*(rng: var HmacDrbgContext): NoisePublicKey =
proc genNoisePublicKey*(rng: crypto.Rng): NoisePublicKey =
var noisePublicKey: NoisePublicKey
# We generate a random key pair
let keyPair: KeyPair = genKeyPair(rng)
@ -446,7 +446,7 @@ proc `==`*(p1, p2: PayloadV2): bool =
(p1.transportMessage == p2.transportMessage)
# Generates a random PayloadV2
proc randomPayloadV2*(rng: var HmacDrbgContext): PayloadV2 =
proc randomPayloadV2*(rng: crypto.Rng): PayloadV2 =
var payload2: PayloadV2
# We set a random messageNametag
let randMessageNametag = randomSeqByte(rng, MessageNametagLength)

View File

@ -366,7 +366,8 @@ proc new*(
triggerSelf = true,
msgIdProvider = defaultMessageIdProvider,
maxMessageSize = maxMessageSize,
parameters = GossipsubParameters,
rng = switch.rng,
parameters = GossipSubParams.init(),
)
w.brokerCtx = globalBrokerContext()

View File

@ -7,8 +7,7 @@ import
chronicles,
libp2p/protocols/rendezvous,
libp2p/crypto/curve25519,
libp2p/switch,
libp2p/utils/semaphore
libp2p/switch
import metrics except collect
@ -107,10 +106,10 @@ proc new*(
switch: switch,
rng: rng,
sema: newAsyncSemaphore(MaxSimultanesousAdvertisements),
minDuration: rendezvous.MinimumAcceptedDuration,
maxDuration: rendezvous.MaximumDuration,
minTTL: rendezvous.MinimumAcceptedDuration.seconds.uint64,
maxTTL: rendezvous.MaximumDuration.seconds.uint64,
config: RendezVousConfig.new(
minDuration = rendezvous.MinimumDuration,
maxDuration = rendezvous.MaximumDuration,
),
peers: @[], # Will be populated from selectPeer calls
cookiesSaved: initTable[PeerId, Table[string, seq[byte]]](),
peerRecordValidator: checkWakuPeerRecord,

View File

@ -8,7 +8,6 @@ import
stew/byteutils,
libp2p/protocols/rendezvous,
libp2p/protocols/rendezvous/protobuf,
libp2p/utils/semaphore,
libp2p/utils/offsettedseq,
libp2p/crypto/curve25519,
libp2p/switch,
@ -51,7 +50,7 @@ proc advertise*(
self: WakuRendezVous,
namespace: string,
peers: seq[PeerId],
ttl: timer.Duration = self.minDuration,
ttl: timer.Duration = rendezvous.MinimumDuration,
): Future[Result[void, string]] {.async: (raises: []).} =
trace "advertising via waku rendezvous",
namespace = namespace, ttl = ttl, peers = $peers, peerRecord = $self.getPeerRecord()
@ -154,14 +153,14 @@ proc new*(
let rng = newRng()
let wrv = T(
rng: rng,
salt: string.fromBytes(generateBytes(rng[], 8)),
salt: string.fromBytes(generateBytes(rng, 8)),
registered: initOffsettedSeq[RegisteredData](),
expiredDT: Moment.now() - 1.days,
sema: newAsyncSemaphore(SemaphoreDefaultSize),
minDuration: rendezvous.MinimumAcceptedDuration,
maxDuration: rendezvous.MaximumDuration,
minTTL: rendezvous.MinimumAcceptedDuration.seconds.uint64,
maxTTL: rendezvous.MaximumDuration.seconds.uint64,
config: RendezVousConfig.new(
minDuration = rendezvous.MinimumDuration,
maxDuration = rendezvous.MaximumDuration,
),
peerRecordValidator: checkWakuPeerRecord,
)

View File

@ -6,7 +6,7 @@ import
chronicles,
chronos,
metrics,
bearssl/rand
libp2p/crypto/crypto
import
../node/peer_manager, ../utils/requests, ./protocol_metrics, ./common, ./rpc_codec
@ -20,11 +20,11 @@ const MaxQueryRetries = 5 # Maximum number of store peers to try before giving u
type WakuStoreClient* = ref object
peerManager: PeerManager
rng: ref rand.HmacDrbgContext
rng: Rng
storeMsgMetricsPerShard*: Table[string, float64]
proc new*(
T: type WakuStoreClient, peerManager: PeerManager, rng: ref rand.HmacDrbgContext
T: type WakuStoreClient, peerManager: PeerManager, rng: crypto.Rng
): T {.gcsafe.} =
WakuStoreClient(peerManager: peerManager, rng: rng)

View File

@ -8,7 +8,6 @@ import
results,
chronicles,
chronos,
bearssl/rand,
libp2p/crypto/crypto,
libp2p/protocols/protocol,
libp2p/protobuf/minprotobuf,
@ -30,7 +29,7 @@ type StoreQueryRequestHandler* =
type WakuStore* = ref object of LPProtocol
peerManager: PeerManager
rng: ref rand.HmacDrbgContext
rng: Rng
requestHandler*: StoreQueryRequestHandler
requestRateLimiter*: RequestRateLimiter
@ -154,7 +153,7 @@ proc initProtocolHandler(self: WakuStore) =
proc new*(
T: type WakuStore,
peerManager: PeerManager,
rng: ref rand.HmacDrbgContext,
rng: crypto.Rng,
requestHandler: StoreQueryRequestHandler,
rateLimitSetting: Option[RateLimitSetting] = none[RateLimitSetting](),
): T =