mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-04-14 04:03:20 +00:00
Merge 91ef9d45e20a7cc80fbc721689f4673ee4bcc5ac into 7d54103053748f4a28724e22ad7a794a0dcc78ae
This commit is contained in:
commit
b62234c4e1
@ -24,6 +24,7 @@ The simulation includes:
|
||||
| `run_chat_mix.sh` | Chat app instance 1 |
|
||||
| `run_chat_mix1.sh` | Chat app instance 2 |
|
||||
| `build_setup.sh` | Build and generate RLN credentials |
|
||||
| `check_cover_traffic.sh` | Monitor cover traffic metrics from all nodes |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@ -130,3 +131,35 @@ To exit the chat apps, enter `/exit`:
|
||||
>> /exit
|
||||
quitting...
|
||||
```
|
||||
|
||||
## Running Without DoS Protection
|
||||
|
||||
To test cover traffic without RLN spam protection (avoids heavy proof generation compute), the config files include two flags:
|
||||
|
||||
```toml
|
||||
mix-user-message-limit=2 # slots per epoch (reduce for lighter testing)
|
||||
mix-disable-spam-protection=true # skip RLN proof generation/verification
|
||||
```
|
||||
|
||||
These are already set in `config.toml` through `config4.toml`. To re-enable RLN, set `mix-disable-spam-protection=false` (or remove the line) and ensure credentials are generated via `./build_setup.sh`.
|
||||
|
||||
When running without DoS protection, cover traffic uses an internal epoch timer and does not require RLN credentials or `rln_tree.db`.
|
||||
|
||||
### Monitoring Cover Traffic
|
||||
|
||||
Use the metrics script to verify cover traffic is working:
|
||||
|
||||
```bash
|
||||
./check_cover_traffic.sh
|
||||
```
|
||||
|
||||
Key metrics to look for:
|
||||
- `mix_cover_emitted_total` — cover messages generated per node (should increase each epoch)
|
||||
- `mix_cover_received_total` — cover messages received back at origin after 3-hop mix path
|
||||
- `mix_slots_exhausted_total` — expected when slots per epoch are low
|
||||
|
||||
### Note on Rate Limit and Expected Errors
|
||||
|
||||
The default `mix-user-message-limit=2` (R=2) with path length L=3 yields a fractional cover target of `R/(1+L) = 0.5` packets per epoch. Because this is not an integer, epoch boundary jitter can cause two cover emissions in one epoch, exhausting all slots and leaving none for forwarding. This produces `SLOT_EXHAUSTED` and `SPAM_PROOF_GEN_FAILED` errors at intermediate hops — these are expected with the default config.
|
||||
|
||||
For a clean setup, R should be a multiple of `(1+L) = 4`. Setting `mix-user-message-limit=4` gives exactly 1 cover packet per epoch with 3 slots remaining for forwarding, eliminating these errors.
|
||||
|
||||
18
simulations/mixnet/check_cover_traffic.sh
Executable file
18
simulations/mixnet/check_cover_traffic.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
# Check cover traffic metrics from all mix nodes.
|
||||
# Ports: 8008 + ports-shift (1-5) = 8009-8013
|
||||
|
||||
echo "=== Cover Traffic Metrics ==="
|
||||
echo ""
|
||||
|
||||
for i in 1 2 3 4 5; do
|
||||
port=$((8008 + i))
|
||||
echo "--- Node $i (port $port) ---"
|
||||
metrics=$(curl -s "http://127.0.0.1:$port/metrics" 2>/dev/null)
|
||||
if [ -z "$metrics" ]; then
|
||||
echo " (unreachable)"
|
||||
else
|
||||
echo "$metrics" | grep -E "mix_cover_|mix_slots_" | grep -v "^#" || echo " (no cover metrics yet)"
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
@ -7,6 +7,7 @@ lightpush = true
|
||||
max-connections = 150
|
||||
peer-exchange = false
|
||||
metrics-logging = false
|
||||
metrics-server = true
|
||||
cluster-id = 2
|
||||
discv5-discovery = false
|
||||
discv5-udp-port = 9000
|
||||
@ -26,3 +27,5 @@ nat = "extip:127.0.0.1"
|
||||
ext-multiaddr = ["/ip4/127.0.0.1/tcp/60001"]
|
||||
ext-multiaddr-only = true
|
||||
ip-colocation-limit=0
|
||||
mix-user-message-limit=2
|
||||
mix-disable-spam-protection=true
|
||||
|
||||
@ -7,6 +7,7 @@ lightpush = true
|
||||
max-connections = 150
|
||||
peer-exchange = false
|
||||
metrics-logging = false
|
||||
metrics-server = true
|
||||
cluster-id = 2
|
||||
discv5-discovery = false
|
||||
discv5-udp-port = 9001
|
||||
@ -27,4 +28,6 @@ nat = "extip:127.0.0.1"
|
||||
ext-multiaddr = ["/ip4/127.0.0.1/tcp/60002"]
|
||||
ext-multiaddr-only = true
|
||||
ip-colocation-limit=0
|
||||
mix-user-message-limit=2
|
||||
mix-disable-spam-protection=true
|
||||
#staticnode = ["/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o", "/ip4/127.0.0.1/tcp/60003/p2p/16Uiu2HAmTEDHwAziWUSz6ZE23h5vxG2o4Nn7GazhMor4bVuMXTrA","/ip4/127.0.0.1/tcp/60004/p2p/16Uiu2HAmPwRKZajXtfb1Qsv45VVfRZgK3ENdfmnqzSrVm3BczF6f","/ip4/127.0.0.1/tcp/60005/p2p/16Uiu2HAmRhxmCHBYdXt1RibXrjAUNJbduAhzaTHwFCZT4qWnqZAu"]
|
||||
|
||||
@ -7,6 +7,7 @@ lightpush = true
|
||||
max-connections = 150
|
||||
peer-exchange = false
|
||||
metrics-logging = false
|
||||
metrics-server = true
|
||||
cluster-id = 2
|
||||
discv5-discovery = false
|
||||
discv5-udp-port = 9002
|
||||
@ -27,4 +28,6 @@ nat = "extip:127.0.0.1"
|
||||
ext-multiaddr = ["/ip4/127.0.0.1/tcp/60003"]
|
||||
ext-multiaddr-only = true
|
||||
ip-colocation-limit=0
|
||||
mix-user-message-limit=2
|
||||
mix-disable-spam-protection=true
|
||||
#staticnode = ["/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o", "/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAmLtKaFaSWDohToWhWUZFLtqzYZGPFuXwKrojFVF6az5UF","/ip4/127.0.0.1/tcp/60004/p2p/16Uiu2HAmPwRKZajXtfb1Qsv45VVfRZgK3ENdfmnqzSrVm3BczF6f","/ip4/127.0.0.1/tcp/60005/p2p/16Uiu2HAmRhxmCHBYdXt1RibXrjAUNJbduAhzaTHwFCZT4qWnqZAu"]
|
||||
|
||||
@ -7,6 +7,7 @@ lightpush = true
|
||||
max-connections = 150
|
||||
peer-exchange = false
|
||||
metrics-logging = false
|
||||
metrics-server = true
|
||||
cluster-id = 2
|
||||
discv5-discovery = false
|
||||
discv5-udp-port = 9003
|
||||
@ -27,4 +28,6 @@ nat = "extip:127.0.0.1"
|
||||
ext-multiaddr = ["/ip4/127.0.0.1/tcp/60004"]
|
||||
ext-multiaddr-only = true
|
||||
ip-colocation-limit=0
|
||||
mix-user-message-limit=2
|
||||
mix-disable-spam-protection=true
|
||||
#staticnode = ["/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAmLtKaFaSWDohToWhWUZFLtqzYZGPFuXwKrojFVF6az5UF", "/ip4/127.0.0.1/tcp/60003/p2p/16Uiu2HAmTEDHwAziWUSz6ZE23h5vxG2o4Nn7GazhMor4bVuMXTrA","/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o","/ip4/127.0.0.1/tcp/60005/p2p/16Uiu2HAmRhxmCHBYdXt1RibXrjAUNJbduAhzaTHwFCZT4qWnqZAu"]
|
||||
|
||||
@ -7,6 +7,7 @@ lightpush = true
|
||||
max-connections = 150
|
||||
peer-exchange = false
|
||||
metrics-logging = false
|
||||
metrics-server = true
|
||||
cluster-id = 2
|
||||
discv5-discovery = false
|
||||
discv5-udp-port = 9004
|
||||
@ -27,4 +28,6 @@ nat = "extip:127.0.0.1"
|
||||
ext-multiaddr = ["/ip4/127.0.0.1/tcp/60005"]
|
||||
ext-multiaddr-only = true
|
||||
ip-colocation-limit=0
|
||||
mix-user-message-limit=2
|
||||
mix-disable-spam-protection=true
|
||||
#staticnode = ["/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o", "/ip4/127.0.0.1/tcp/60003/p2p/16Uiu2HAmTEDHwAziWUSz6ZE23h5vxG2o4Nn7GazhMor4bVuMXTrA","/ip4/127.0.0.1/tcp/60004/p2p/16Uiu2HAmPwRKZajXtfb1Qsv45VVfRZgK3ENdfmnqzSrVm3BczF6f","/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAmLtKaFaSWDohToWhWUZFLtqzYZGPFuXwKrojFVF6az5UF"]
|
||||
|
||||
@ -20,8 +20,8 @@ import
|
||||
|
||||
const
|
||||
KeystorePassword = "mix-rln-password" # Must match protocol.nim
|
||||
DefaultUserMessageLimit = 100'u64 # Network-wide default rate limit
|
||||
SpammerUserMessageLimit = 3'u64 # Lower limit for spammer testing
|
||||
DefaultUserMessageLimit = 2'u64 # ~12 msgs/min with 10s epochs
|
||||
SpammerUserMessageLimit = 3'u64 # Higher limit for spammer testing
|
||||
|
||||
# Peer IDs derived from nodekeys in config files
|
||||
# config.toml: nodekey = "f98e3fba96c32e8d1967d460f1b79457380e1a895f7971cecc8528abe733781a"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/[sequtils, strutils, net],
|
||||
std/[options, sequtils, strutils, net],
|
||||
stew/byteutils,
|
||||
testutils/unittests,
|
||||
chronicles,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/[os, strutils, sequtils, sysrand, math],
|
||||
std/[options, os, strutils, sequtils, sysrand, math],
|
||||
stew/byteutils,
|
||||
testutils/unittests,
|
||||
chronos,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/sequtils,
|
||||
std/[options, sequtils],
|
||||
testutils/unittests,
|
||||
chronicles,
|
||||
chronos,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/net,
|
||||
std/[net, options],
|
||||
testutils/unittests,
|
||||
chronos,
|
||||
libp2p/crypto/crypto,
|
||||
|
||||
@ -643,6 +643,17 @@ with the drawback of consuming some more bandwidth.""",
|
||||
name: "mixnode"
|
||||
.}: seq[MixNodePubInfo]
|
||||
|
||||
mixUserMessageLimit* {.
|
||||
desc: "Maximum messages per RLN epoch for mix cover traffic. If not set, uses plugin default.",
|
||||
name: "mix-user-message-limit"
|
||||
.}: Option[int]
|
||||
|
||||
mixDisableSpamProtection* {.
|
||||
desc: "Disable RLN spam protection for mix protocol (for testing only).",
|
||||
defaultValue: false,
|
||||
name: "mix-disable-spam-protection"
|
||||
.}: bool
|
||||
|
||||
# Kademlia Discovery config
|
||||
enableKadDiscovery* {.
|
||||
desc:
|
||||
@ -1073,6 +1084,9 @@ proc toWakuConf*(n: WakuNodeConf): ConfResult[WakuConf] =
|
||||
b.withMix(n.mix)
|
||||
if n.mixkey.isSome():
|
||||
b.mixConf.withMixKey(n.mixkey.get())
|
||||
if n.mixUserMessageLimit.isSome():
|
||||
b.mixConf.withUserMessageLimit(n.mixUserMessageLimit.get())
|
||||
b.mixConf.withDisableSpamProtection(n.mixDisableSpamProtection)
|
||||
|
||||
b.filterServiceConf.withEnabled(n.filter)
|
||||
b.filterServiceConf.withSubscriptionTimeout(n.filterSubscriptionTimeout)
|
||||
|
||||
2
vendor/mix-rln-spam-protection-plugin
vendored
2
vendor/mix-rln-spam-protection-plugin
vendored
@ -1 +1 @@
|
||||
Subproject commit 037f8e100bfedffdbad1c4442e760d10a2437428
|
||||
Subproject commit bf56c9b9a640e612ce34aa3776c4eedfd5366ab3
|
||||
2
vendor/nim-libp2p
vendored
2
vendor/nim-libp2p
vendored
@ -1 +1 @@
|
||||
Subproject commit ff8d51857b4b79a68468e7bcc27b2026cca02996
|
||||
Subproject commit 145dcbc2aa4d5dc3025d7578b147561b5aa40388
|
||||
28
waku/common/option_shims.nim
Normal file
28
waku/common/option_shims.nim
Normal file
@ -0,0 +1,28 @@
|
||||
# Compatibility shims for std/options
|
||||
# The results library removed valueOr/withValue support for Option[T].
|
||||
# These templates restore that functionality.
|
||||
|
||||
{.push raises: [].}
|
||||
|
||||
import std/options
|
||||
|
||||
template valueOr*[T](self: Option[T], def: untyped): T =
|
||||
let tmp = self
|
||||
if tmp.isSome():
|
||||
tmp.get()
|
||||
else:
|
||||
def
|
||||
|
||||
template withValue*[T](self: Option[T], value, body: untyped): untyped =
|
||||
let tmp = self
|
||||
if tmp.isSome():
|
||||
let value {.inject.} = tmp.get()
|
||||
body
|
||||
|
||||
template withValue*[T](self: Option[T], value, body, elseBody: untyped): untyped =
|
||||
let tmp = self
|
||||
if tmp.isSome():
|
||||
let value {.inject.} = tmp.get()
|
||||
body
|
||||
else:
|
||||
elseBody
|
||||
@ -24,6 +24,7 @@ import
|
||||
|
||||
import std/times except TimeInterval, Duration, seconds, minutes
|
||||
|
||||
import ../option_shims
|
||||
import ./[single_token_limiter, service_metrics, timed_map]
|
||||
|
||||
export token_bucket, setting, service_metrics
|
||||
|
||||
@ -10,7 +10,7 @@ import
|
||||
eth/keys as eth_keys,
|
||||
eth/p2p/discoveryv5/node,
|
||||
eth/p2p/discoveryv5/protocol
|
||||
import ../node/peer_manager/peer_manager, ../waku_core, ../waku_enr
|
||||
import ../common/option_shims, ../node/peer_manager/peer_manager, ../waku_core, ../waku_enr
|
||||
|
||||
export protocol, waku_enr
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@ type MixConfBuilder* = object
|
||||
enabled: Option[bool]
|
||||
mixKey: Option[string]
|
||||
mixNodes: seq[MixNodePubInfo]
|
||||
userMessageLimit: Option[int]
|
||||
disableSpamProtection: bool
|
||||
|
||||
proc init*(T: type MixConfBuilder): MixConfBuilder =
|
||||
MixConfBuilder()
|
||||
@ -25,6 +27,12 @@ proc withMixKey*(b: var MixConfBuilder, mixKey: string) =
|
||||
proc withMixNodes*(b: var MixConfBuilder, mixNodes: seq[MixNodePubInfo]) =
|
||||
b.mixNodes = mixNodes
|
||||
|
||||
proc withUserMessageLimit*(b: var MixConfBuilder, limit: int) =
|
||||
b.userMessageLimit = some(limit)
|
||||
|
||||
proc withDisableSpamProtection*(b: var MixConfBuilder, disable: bool) =
|
||||
b.disableSpamProtection = disable
|
||||
|
||||
proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
|
||||
if not b.enabled.get(false):
|
||||
return ok(none[MixConf]())
|
||||
@ -33,11 +41,11 @@ proc build*(b: MixConfBuilder): Result[Option[MixConf], string] =
|
||||
let mixPrivKey = intoCurve25519Key(ncrutils.fromHex(b.mixKey.get()))
|
||||
let mixPubKey = public(mixPrivKey)
|
||||
return ok(
|
||||
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes))
|
||||
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes, userMessageLimit: b.userMessageLimit, disableSpamProtection: b.disableSpamProtection))
|
||||
)
|
||||
else:
|
||||
let (mixPrivKey, mixPubKey) = generateKeyPair().valueOr:
|
||||
return err("Generate key pair error: " & $error)
|
||||
return ok(
|
||||
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes))
|
||||
some(MixConf(mixKey: mixPrivKey, mixPubKey: mixPubKey, mixNodes: b.mixNodes, userMessageLimit: b.userMessageLimit, disableSpamProtection: b.disableSpamProtection))
|
||||
)
|
||||
|
||||
@ -167,7 +167,7 @@ proc setupProtocols(
|
||||
#mount mix
|
||||
if conf.mixConf.isSome():
|
||||
let mixConf = conf.mixConf.get()
|
||||
(await node.mountMix(conf.clusterId, mixConf.mixKey, mixConf.mixnodes)).isOkOr:
|
||||
(await node.mountMix(conf.clusterId, mixConf.mixKey, mixConf.mixnodes, mixConf.userMessageLimit, mixConf.disableSpamProtection)).isOkOr:
|
||||
return err("failed to mount waku mix protocol: " & $error)
|
||||
|
||||
# Setup extended kademlia discovery
|
||||
|
||||
@ -51,6 +51,8 @@ type MixConf* = ref object
|
||||
mixKey*: Curve25519Key
|
||||
mixPubKey*: Curve25519Key
|
||||
mixnodes*: seq[MixNodePubInfo]
|
||||
userMessageLimit*: Option[int]
|
||||
disableSpamProtection*: bool
|
||||
|
||||
type KademliaDiscoveryConf* = object
|
||||
bootstrapNodes*: seq[(PeerId, seq[MultiAddress])]
|
||||
|
||||
@ -2,6 +2,7 @@ import chronicles, chronos, results
|
||||
import std/options
|
||||
|
||||
import
|
||||
waku/common/option_shims,
|
||||
waku/node/peer_manager,
|
||||
waku/waku_core,
|
||||
waku/waku_lightpush/[common, client, rpc],
|
||||
|
||||
@ -28,6 +28,7 @@ import
|
||||
../../waku_lightpush/client as lightpush_client,
|
||||
../../waku_lightpush as lightpush_protocol,
|
||||
../peer_manager,
|
||||
../../common/option_shims,
|
||||
../../common/rate_limit/setting,
|
||||
../../waku_rln_relay
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import
|
||||
libp2p/transports/tcptransport,
|
||||
libp2p/utility
|
||||
|
||||
import ../waku_node, ../peer_manager
|
||||
import ../../common/option_shims, ../waku_node, ../peer_manager
|
||||
|
||||
logScope:
|
||||
topics = "waku node ping api"
|
||||
|
||||
@ -31,6 +31,7 @@ import
|
||||
waku_mix,
|
||||
node/waku_node,
|
||||
node/peer_manager,
|
||||
common/option_shims,
|
||||
common/broker/broker_context,
|
||||
events/message_events,
|
||||
]
|
||||
|
||||
@ -19,6 +19,7 @@ import
|
||||
events/peer_events,
|
||||
common/nimchronos,
|
||||
common/enr,
|
||||
common/option_shims,
|
||||
common/callbacks,
|
||||
common/utils/parse_size_units,
|
||||
common/broker/broker_context,
|
||||
|
||||
@ -10,6 +10,7 @@ import
|
||||
libp2p/crypto/curve25519
|
||||
|
||||
import
|
||||
../../common/option_shims,
|
||||
../../waku_core,
|
||||
../../waku_enr/sharding,
|
||||
../../waku_enr/capabilities,
|
||||
|
||||
@ -57,6 +57,7 @@ import
|
||||
waku_rln_relay,
|
||||
common/rate_limit/setting,
|
||||
common/callbacks,
|
||||
common/option_shims,
|
||||
common/nimchronos,
|
||||
common/broker/broker_context,
|
||||
common/broker/request_broker,
|
||||
@ -329,6 +330,7 @@ proc mountMix*(
|
||||
mixPrivKey: Curve25519Key,
|
||||
mixnodes: seq[MixNodePubInfo],
|
||||
userMessageLimit: Option[int] = none(int),
|
||||
disableSpamProtection: bool = false,
|
||||
): Future[Result[void, string]] {.async.} =
|
||||
info "mounting mix protocol", nodeId = node.info #TODO log the config used
|
||||
|
||||
@ -361,7 +363,7 @@ proc mountMix*(
|
||||
|
||||
node.wakuMix = WakuMix.new(
|
||||
localaddrStr, node.peerManager, clusterId, mixPrivKey, mixnodes, publishMessage,
|
||||
userMessageLimit,
|
||||
userMessageLimit, disableSpamProtection,
|
||||
).valueOr:
|
||||
error "Waku Mix protocol initialization failed", err = error
|
||||
return
|
||||
|
||||
@ -10,6 +10,7 @@ import
|
||||
presto/route,
|
||||
presto/common
|
||||
import
|
||||
../../../common/option_shims,
|
||||
../../../waku_core,
|
||||
../../../waku_node,
|
||||
../../../node/peer_manager,
|
||||
|
||||
@ -10,6 +10,7 @@ import
|
||||
presto/common
|
||||
|
||||
import
|
||||
waku/common/option_shims,
|
||||
waku/node/peer_manager,
|
||||
waku/waku_lightpush_legacy/common,
|
||||
../../../waku_node,
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import
|
||||
std/[strformat, sugar], results, chronicles, uri, json_serialization, presto/route
|
||||
import
|
||||
../../../common/option_shims,
|
||||
../../../waku_core,
|
||||
../../../waku_store_legacy/common,
|
||||
../../../waku_store_legacy/self_req_handler,
|
||||
|
||||
@ -10,6 +10,7 @@ import
|
||||
presto/common
|
||||
|
||||
import
|
||||
waku/common/option_shims,
|
||||
waku/node/peer_manager,
|
||||
waku/waku_lightpush/common,
|
||||
../../../waku_node,
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import
|
||||
std/[strformat, sugar], results, chronicles, uri, json_serialization, presto/route
|
||||
import
|
||||
../../../common/option_shims,
|
||||
../../../waku_core,
|
||||
../../../waku_store/common,
|
||||
../../../waku_store/self_req_handler,
|
||||
|
||||
@ -8,7 +8,7 @@ import
|
||||
eth/keys,
|
||||
libp2p/[multiaddress, multicodec],
|
||||
libp2p/crypto/crypto
|
||||
import ../common/enr, ../waku_core/topics/pubsub_topic
|
||||
import ../common/enr, ../common/option_shims, ../waku_core/topics/pubsub_topic
|
||||
|
||||
logScope:
|
||||
topics = "waku enr sharding"
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import std/options, results, chronicles, chronos, metrics, bearssl/rand, stew/byteutils
|
||||
import libp2p/peerid, libp2p/stream/connection
|
||||
import
|
||||
../common/option_shims,
|
||||
../waku_core/peers,
|
||||
../node/peer_manager,
|
||||
../utils/requests,
|
||||
|
||||
@ -9,6 +9,7 @@ import
|
||||
metrics,
|
||||
bearssl/rand
|
||||
import
|
||||
../common/option_shims,
|
||||
../node/peer_manager/peer_manager,
|
||||
../waku_core,
|
||||
../waku_core/topics/sharding,
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import std/options, results, chronicles, chronos, metrics, bearssl/rand, stew/byteutils
|
||||
import libp2p/peerid
|
||||
import
|
||||
../common/option_shims,
|
||||
../waku_core/peers,
|
||||
../node/peer_manager,
|
||||
../utils/requests,
|
||||
|
||||
@ -11,6 +11,7 @@ import
|
||||
libp2p/protocols/mix/mix_metrics,
|
||||
libp2p/protocols/mix/delay_strategy,
|
||||
libp2p/protocols/mix/spam_protection,
|
||||
libp2p/protocols/mix/cover_traffic,
|
||||
libp2p/[multiaddress, multicodec, peerid, peerinfo],
|
||||
eth/common/keys
|
||||
|
||||
@ -87,6 +88,7 @@ proc new*(
|
||||
bootnodes: seq[MixNodePubInfo],
|
||||
publishMessage: PublishMessage,
|
||||
userMessageLimit: Option[int] = none(int),
|
||||
disableSpamProtection: bool = false,
|
||||
): WakuMixResult[T] =
|
||||
let mixPubKey = public(mixPrivKey)
|
||||
trace "mixPubKey", mixPubKey = mixPubKey
|
||||
@ -97,33 +99,47 @@ proc new*(
|
||||
peermgr.switch.peerInfo.publicKey.skkey, peermgr.switch.peerInfo.privateKey.skkey,
|
||||
)
|
||||
|
||||
# Initialize spam protection with persistent credentials
|
||||
# Use peerID in keystore path so multiple peers can run from same directory
|
||||
# Tree path is shared across all nodes to maintain the full membership set
|
||||
let peerId = peermgr.switch.peerInfo.peerId
|
||||
var spamProtectionConfig = defaultConfig()
|
||||
spamProtectionConfig.keystorePath = "rln_keystore_" & $peerId & ".json"
|
||||
spamProtectionConfig.keystorePassword = "mix-rln-password"
|
||||
if userMessageLimit.isSome():
|
||||
spamProtectionConfig.userMessageLimit = userMessageLimit.get()
|
||||
# rlnResourcesPath left empty to use bundled resources (via "tree_height_/" placeholder)
|
||||
let totalSlots = userMessageLimit.get(2)
|
||||
let ct = ConstantRateCoverTraffic.new(
|
||||
totalSlots = totalSlots,
|
||||
epochDurationSec = 10.0,
|
||||
useInternalEpochTimer = disableSpamProtection,
|
||||
)
|
||||
|
||||
let spamProtection = newMixRlnSpamProtection(spamProtectionConfig).valueOr:
|
||||
return err("failed to create spam protection: " & error)
|
||||
var spamProtectionOpt = default(Opt[SpamProtection])
|
||||
if not disableSpamProtection:
|
||||
# Initialize spam protection with persistent credentials
|
||||
let peerId = peermgr.switch.peerInfo.peerId
|
||||
var spamProtectionConfig = defaultConfig()
|
||||
spamProtectionConfig.keystorePath = "rln_keystore_" & $peerId & ".json"
|
||||
spamProtectionConfig.keystorePassword = "mix-rln-password"
|
||||
if userMessageLimit.isSome():
|
||||
spamProtectionConfig.userMessageLimit = userMessageLimit.get()
|
||||
|
||||
let spamProtection = newMixRlnSpamProtection(spamProtectionConfig).valueOr:
|
||||
return err("failed to create spam protection: " & error)
|
||||
spamProtectionOpt = Opt.some(SpamProtection(spamProtection))
|
||||
else:
|
||||
info "mix spam protection disabled"
|
||||
|
||||
var mixRlnSpam: MixRlnSpamProtection
|
||||
if spamProtectionOpt.isSome():
|
||||
mixRlnSpam = MixRlnSpamProtection(spamProtectionOpt.get())
|
||||
|
||||
var m = WakuMix(
|
||||
peerManager: peermgr,
|
||||
clusterId: clusterId,
|
||||
pubKey: mixPubKey,
|
||||
mixRlnSpamProtection: spamProtection,
|
||||
publishMessage: publishMessage,
|
||||
mixRlnSpamProtection: mixRlnSpam,
|
||||
)
|
||||
procCall MixProtocol(m).init(
|
||||
localMixNodeInfo,
|
||||
peermgr.switch,
|
||||
spamProtection = Opt.some(SpamProtection(spamProtection)),
|
||||
delayStrategy =
|
||||
ExponentialDelayStrategy.new(meanDelayMs = 100, rng = crypto.newRng()),
|
||||
spamProtection = spamProtectionOpt,
|
||||
delayStrategy = Opt.some(DelayStrategy(
|
||||
ExponentialDelayStrategy.new(meanDelay = 100, rng = crypto.newRng()))),
|
||||
coverTraffic = Opt.some(CoverTraffic(ct)),
|
||||
)
|
||||
|
||||
processBootNodes(bootnodes, peermgr, m)
|
||||
@ -140,6 +156,8 @@ proc setupSpamProtectionCallbacks(mix: WakuMix) =
|
||||
## Set up the publish callback for spam protection coordination.
|
||||
## This enables the plugin to broadcast membership updates and proof metadata
|
||||
## via Waku relay.
|
||||
if mix.mixRlnSpamProtection.isNil():
|
||||
return
|
||||
if mix.publishMessage.isNil():
|
||||
warn "PublishMessage callback not available, spam protection coordination disabled"
|
||||
return
|
||||
|
||||
@ -8,11 +8,12 @@ import
|
||||
libp2p/protocols/rendezvous,
|
||||
libp2p/crypto/curve25519,
|
||||
libp2p/switch,
|
||||
libp2p/utils/semaphore
|
||||
chronos/asyncsync
|
||||
|
||||
import metrics except collect
|
||||
|
||||
import
|
||||
waku/common/option_shims,
|
||||
waku/node/peer_manager,
|
||||
waku/waku_core/peers,
|
||||
waku/waku_core/codecs,
|
||||
|
||||
@ -8,7 +8,7 @@ import
|
||||
stew/byteutils,
|
||||
libp2p/protocols/rendezvous,
|
||||
libp2p/protocols/rendezvous/protobuf,
|
||||
libp2p/utils/semaphore,
|
||||
chronos/asyncsync,
|
||||
libp2p/utils/offsettedseq,
|
||||
libp2p/crypto/curve25519,
|
||||
libp2p/switch,
|
||||
@ -19,6 +19,7 @@ import metrics except collect
|
||||
import
|
||||
../node/peer_manager,
|
||||
../common/callbacks,
|
||||
../common/option_shims,
|
||||
../waku_enr/capabilities,
|
||||
../waku_core/peers,
|
||||
../waku_core/codecs,
|
||||
|
||||
@ -8,6 +8,7 @@ import
|
||||
metrics,
|
||||
bearssl/rand
|
||||
import
|
||||
../common/option_shims,
|
||||
../node/peer_manager, ../utils/requests, ./protocol_metrics, ./common, ./rpc_codec
|
||||
|
||||
logScope:
|
||||
|
||||
@ -13,6 +13,7 @@ import
|
||||
|
||||
import
|
||||
../common/databases/db_sqlite,
|
||||
../common/option_shims,
|
||||
../waku_core,
|
||||
../waku_archive,
|
||||
../common/nimchronos,
|
||||
|
||||
@ -14,6 +14,7 @@ import
|
||||
eth/p2p/discoveryv5/enr
|
||||
import
|
||||
../common/nimchronos,
|
||||
../common/option_shims,
|
||||
../common/protobuf,
|
||||
../common/paging,
|
||||
../waku_enr,
|
||||
|
||||
@ -13,6 +13,7 @@ import
|
||||
eth/p2p/discoveryv5/enr
|
||||
import
|
||||
../common/nimchronos,
|
||||
../common/option_shims,
|
||||
../common/protobuf,
|
||||
../waku_enr,
|
||||
../waku_core/codecs,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user