From 658a9ea10887a20d07aac66f9ac751cb5f904d67 Mon Sep 17 00:00:00 2001 From: Prem Chaitanya Prathi Date: Thu, 25 Jun 2026 18:57:35 +0530 Subject: [PATCH] test(mix-sim): chat-ui-over-mixnet test setup - config*.toml: disable cover traffic (mix-disable-cover-traffic=true) and bump RLN userMessageLimit 4 -> 100 to match the chat client's RLN default. - setup_credentials.nim: DefaultUserMessageLimit -> 100. - chat-ui/: env.sh + run_chat_ui.sh launch two logos-chat-ui clients that adopt the two provisioned chat memberships (via CHAT_NODEKEY) against the 5-node sim, plus a README runbook. Creds (rln_tree.db, rln_keystore_*.json) are generated by build_setup.sh, not checked in. --- simulations/mixnet/chat-ui/.gitignore | 1 + simulations/mixnet/chat-ui/README.md | 81 +++++++++++++++++++++++ simulations/mixnet/chat-ui/env.sh | 26 ++++++++ simulations/mixnet/chat-ui/run_chat_ui.sh | 36 ++++++++++ simulations/mixnet/config.toml | 3 +- simulations/mixnet/config1.toml | 3 +- simulations/mixnet/config2.toml | 3 +- simulations/mixnet/config3.toml | 3 +- simulations/mixnet/config4.toml | 3 +- simulations/mixnet/setup_credentials.nim | 2 +- 10 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 simulations/mixnet/chat-ui/.gitignore create mode 100644 simulations/mixnet/chat-ui/README.md create mode 100644 simulations/mixnet/chat-ui/env.sh create mode 100755 simulations/mixnet/chat-ui/run_chat_ui.sh diff --git a/simulations/mixnet/chat-ui/.gitignore b/simulations/mixnet/chat-ui/.gitignore new file mode 100644 index 000000000..2fb0daef2 --- /dev/null +++ b/simulations/mixnet/chat-ui/.gitignore @@ -0,0 +1 @@ +run-*/ diff --git a/simulations/mixnet/chat-ui/README.md b/simulations/mixnet/chat-ui/README.md new file mode 100644 index 000000000..f24449fd4 --- /dev/null +++ b/simulations/mixnet/chat-ui/README.md @@ -0,0 +1,81 @@ +# Testing logos-chat-ui against the local mixnet sim + +Run two `logos-chat-ui` clients that exchange end-to-end messages **through the +5-node mix sim** (Sphinx routing + RLN spam protection + exit-node delivery). + +The two clients adopt the **two provisioned chat memberships** the sim already +generates (peer-IDs `…1Qx…` and `…RABscN`, the same identities `run_chat_mix*.sh` +use), via `CHAT_NODEKEY`. RLN keystores are peer-ID-derived, so fixing the nodekey +makes the right `rln_keystore_.json` resolve. + +## Prerequisites + +- Nix (the chat-ui builds via `nix run`). +- This sim built + provisioned (run from `simulations/mixnet/`): + +```bash +make -C ../../ wakunode2 # build the mix node binary +./build_setup.sh # generate rln_tree.db + 7 keystores +``` + +> `build_setup.sh` regenerates `rln_tree.db` + all keystores from +> `setup_credentials.nim`. This sim is configured with **cover traffic disabled** +> and **userMessageLimit = 100** (matches the chat's RLN default). + +## 1. Start the 5 mix nodes + +Each in its own terminal, bootstrap first: + +```bash +./run_mix_node.sh # bootstrap (tcp/60001) +./run_mix_node1.sh # tcp/60002 +./run_mix_node2.sh # tcp/60003 +./run_mix_node3.sh # tcp/60004 +./run_mix_node4.sh # tcp/60005 +``` + +Wait for `MixRlnSpamProtection started` + `Node setup complete` on each. + +## 2. Start the two chat-ui clients + +```bash +cd chat-ui +./run_chat_ui.sh A # ClientA on tcp/60010 +./run_chat_ui.sh B # ClientB on tcp/60011 +``` + +Each opens a GUI window. The bottom status bar should show **`MIX 5/4`** (mix pool +full) with the send button enabled. + +To iterate on a local chat-ui checkout instead of the pushed branch: + +```bash +CHAT_UI="$HOME/Code/logos-chat-ui" ./run_chat_ui.sh A +``` + +## 3. Exchange messages + +1. In **ClientA**: click **My Bundle** and copy the intro bundle. +2. In **ClientB**: **+ new** → paste A's bundle + a first message → create. +3. Send messages each way — they route A↔B through the mixnet. + +## How the config flows + +`run_chat_ui.sh` sets env that `logos-chat-ui` reads into the chat config: + +| env | meaning | +|-----|---------| +| `CHAT_MIX_NODES` | the 5 mix nodes (`multiaddr:curve25519pubkey`) — **hardcoded**, the chat does no mix-peer discovery | +| `CHAT_STATIC_PEER` | bootstrap node (relay the chat connects to) | +| `CHAT_CLUSTER_ID` / `CHAT_SHARD_ID` | `2` / `0` (must match the mix nodes) | +| `CHAT_NODEKEY` | adopt a provisioned chat identity so its RLN keystore resolves | +| `CHAT_MIX_REQUIRED` | force Required (mix) mode | + +## Notes / limitations + +- **Load:** 5 mix nodes at `log-level=TRACE` (the default in `config*.toml`) write + multi-GB logs and can starve a desktop machine. For real testing prefer fleet + nodes; locally, lower `log-level` if the UI feels sluggish. +- **Static membership only:** the two chat slots are fixed. Adding more clients + means adding their peer-IDs to `setup_credentials.nim` + re-running `build_setup.sh`. +- **No mix discovery on the client:** all mix nodes must be in `CHAT_MIX_NODES`. diff --git a/simulations/mixnet/chat-ui/env.sh b/simulations/mixnet/chat-ui/env.sh new file mode 100644 index 000000000..ba8162d1e --- /dev/null +++ b/simulations/mixnet/chat-ui/env.sh @@ -0,0 +1,26 @@ +# Shared env for running logos-chat-ui clients against this mixnet sim. +# Values mirror ../config*.toml (5 mix nodes on tcp/60001-60005, clusterId 2, +# shard 0). Sourced by run_chat_ui.sh. + +# The 5 sim mix nodes as :, comma-separated. +# NOTE: the chat client seeds its mix pool from this STATIC list — it does NOT do +# mix-peer discovery — so every node must be listed explicitly. +export CHAT_MIX_NODES="\ +/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o:9d09ce624f76e8f606265edb9cca2b7de9b41772a6d784bddaf92ffa8fba7d2c,\ +/ip4/127.0.0.1/tcp/60002/p2p/16Uiu2HAmLtKaFaSWDohToWhWUZFLtqzYZGPFuXwKrojFVF6az5UF:9231e86da6432502900a84f867004ce78632ab52cd8e30b1ec322cd795710c2a,\ +/ip4/127.0.0.1/tcp/60003/p2p/16Uiu2HAmTEDHwAziWUSz6ZE23h5vxG2o4Nn7GazhMor4bVuMXTrA:275cd6889e1f29ca48e5b9edb800d1a94f49f13d393a0ecf1a07af753506de6c,\ +/ip4/127.0.0.1/tcp/60004/p2p/16Uiu2HAmPwRKZajXtfb1Qsv45VVfRZgK3ENdfmnqzSrVm3BczF6f:e0ed594a8d506681be075e8e23723478388fb182477f7a469309a25e7076fc18,\ +/ip4/127.0.0.1/tcp/60005/p2p/16Uiu2HAmRhxmCHBYdXt1RibXrjAUNJbduAhzaTHwFCZT4qWnqZAu:8fd7a1a7c19b403d231452a9b1ea40eb1cc76f455d918ef8980e7685f9eeeb1f" + +# Bootstrap mix node, which doubles as the relay the chat connects to (for +# receiving + RLN membership broadcast). +export CHAT_STATIC_PEER="/ip4/127.0.0.1/tcp/60001/p2p/16Uiu2HAmPiEs2ozjjJF2iN2Pe2FYeMC9w4caRHKYdLdAfjgbWM6o" + +export CHAT_CLUSTER_ID=2 +export CHAT_SHARD_ID=0 +export CHAT_MIN_MIX_POOL=4 +export CHAT_MIX_REQUIRED=1 # force Required (mix) mode without the UI toggle + +# logos-chat-ui flake to run. Override with a local checkout to iterate, e.g. +# CHAT_UI="$HOME/Code/logos-chat-ui" ./run_chat_ui.sh A +export CHAT_UI="${CHAT_UI:-github:logos-co/logos-chat-ui?ref=feat/logos-testnetv02-mix}" diff --git a/simulations/mixnet/chat-ui/run_chat_ui.sh b/simulations/mixnet/chat-ui/run_chat_ui.sh new file mode 100755 index 000000000..cab2f0a7d --- /dev/null +++ b/simulations/mixnet/chat-ui/run_chat_ui.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Run a logos-chat-ui client against this mixnet sim. +# +# ./run_chat_ui.sh A # first client (adopts provisioned chat membership 1) +# ./run_chat_ui.sh B # second client (adopts provisioned chat membership 2) +# +# Each client adopts one of the two provisioned chat memberships via CHAT_NODEKEY +# (the same nodekeys run_chat_mix*.sh use), and runs from a per-client dir holding +# the RLN tree + keystores — mountMix loads rln_keystore_.json + rln_tree.db +# from cwd, and CHAT_NODEKEY fixes the peerId so the right keystore resolves. +# +# Prereqs (from ../): +# 1. make wakunode2 # build the mix node binary +# 2. ./build_setup.sh # generate rln_tree.db + keystores +# 3. ./run_mix_node.sh and run_mix_node1..4.sh # all 5 mix nodes running +set -euo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +SIM="$(cd "$HERE/.." && pwd)" +source "$HERE/env.sh" + +case "${1:-}" in + A) export CHAT_NAME=ClientA CHAT_PORT=60010 \ + CHAT_NODEKEY=35eace7ccb246f20c487e05015ca77273d8ecaed0ed683de3d39bf4f69336feb ;; + B) export CHAT_NAME=ClientB CHAT_PORT=60011 \ + CHAT_NODEKEY=cb6fe589db0e5d5b48f7e82d33093e4d9d35456f4aaffc2322c473a173b2ac49 ;; + *) echo "usage: $0 "; exit 1 ;; +esac + +DIR="$HERE/run-${1}" +mkdir -p "$DIR" +cp -f "$SIM/rln_tree.db" "$DIR/" 2>/dev/null \ + || { echo "missing rln_tree.db — run ../build_setup.sh first"; exit 1; } +cp -f "$SIM"/rln_keystore_*.json "$DIR/" + +cd "$DIR" +exec nix run "$CHAT_UI" --accept-flake-config diff --git a/simulations/mixnet/config.toml b/simulations/mixnet/config.toml index fcf3eda39..94ede5ace 100644 --- a/simulations/mixnet/config.toml +++ b/simulations/mixnet/config.toml @@ -27,5 +27,6 @@ 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=4 +mix-user-message-limit=100 mix-disable-spam-protection=false +mix-disable-cover-traffic=true diff --git a/simulations/mixnet/config1.toml b/simulations/mixnet/config1.toml index a65cc2f5a..1dffb30b5 100644 --- a/simulations/mixnet/config1.toml +++ b/simulations/mixnet/config1.toml @@ -28,6 +28,7 @@ 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=4 +mix-user-message-limit=100 mix-disable-spam-protection=false +mix-disable-cover-traffic=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"] diff --git a/simulations/mixnet/config2.toml b/simulations/mixnet/config2.toml index b37bb9759..d6089cdda 100644 --- a/simulations/mixnet/config2.toml +++ b/simulations/mixnet/config2.toml @@ -28,6 +28,7 @@ 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=4 +mix-user-message-limit=100 mix-disable-spam-protection=false +mix-disable-cover-traffic=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"] diff --git a/simulations/mixnet/config3.toml b/simulations/mixnet/config3.toml index 9b256ea08..635ce5316 100644 --- a/simulations/mixnet/config3.toml +++ b/simulations/mixnet/config3.toml @@ -28,6 +28,7 @@ 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=4 +mix-user-message-limit=100 mix-disable-spam-protection=false +mix-disable-cover-traffic=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"] diff --git a/simulations/mixnet/config4.toml b/simulations/mixnet/config4.toml index d616896e6..186494c44 100644 --- a/simulations/mixnet/config4.toml +++ b/simulations/mixnet/config4.toml @@ -28,6 +28,7 @@ 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=4 +mix-user-message-limit=100 mix-disable-spam-protection=false +mix-disable-cover-traffic=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"] diff --git a/simulations/mixnet/setup_credentials.nim b/simulations/mixnet/setup_credentials.nim index f1f053d80..b954727f7 100644 --- a/simulations/mixnet/setup_credentials.nim +++ b/simulations/mixnet/setup_credentials.nim @@ -20,7 +20,7 @@ import const KeystorePassword = "mix-rln-password" # Must match protocol.nim - DefaultUserMessageLimit = 4'u64 # R=4 slots per 10s epoch + DefaultUserMessageLimit = 100'u64 # R=100 slots per 10s epoch (chat default) # Peer IDs derived from nodekeys in config files # config.toml: nodekey = "f98e3fba96c32e8d1967d460f1b79457380e1a895f7971cecc8528abe733781a"