feat(sim): exercise rln-gifter EIP-191 auth in mix_lez_chat sim

Wires the existing mix_lez_chat simulation to drive the gifter's
EIP-191 allowlist auth path end-to-end:

* bumps vendor/nwaku and vendor/logos-lez-rln (and, transitively,
  logos-delivery-module and its bundled logos-delivery copy) to pick up
  the auth plugin, the auto-registering client's EIP-191 signing, and
  the new --mix-gifter-allowlist / --mix-gifter-auth-key CLI flags.
* adds a `gifterAuthKey` knob on WakuConfig + the JSON config bridge in
  client_api so chat sender/receiver instances sign their gifter
  requests too.
* commits 5 fixed test secp256k1 keys (one per non-gifter mix node and
  per chat client) under simulations/mix_lez_chat/fixtures/gifter_auth/
  along with their derived addresses.
* run_simulation.sh sources keys.env+addresses.env, sets
  `mixGifterAllowlist` on mix node 0, and threads the matching
  `mixGifterAuthKey` / `gifterAuthKey` into nodes 1-3 and the
  receiver/sender configs.

Test fixtures only — keys must never be reused outside this sim.
This commit is contained in:
Arseniy Klempner 2026-05-13 11:10:27 -06:00
parent 6c12e6a003
commit bba01ee9dc
No known key found for this signature in database
GPG Key ID: 51653F18863BD24B
8 changed files with 51 additions and 6 deletions

View File

@ -63,6 +63,8 @@ proc createChatClient(
wakuCfg.minMixPoolSize = config["minMixPoolSize"].getInt(4)
if config.hasKey("gifterNodeAddr"):
wakuCfg.gifterNodeAddr = config["gifterNodeAddr"].getStr("")
if config.hasKey("gifterAuthKey"):
wakuCfg.gifterAuthKey = config["gifterAuthKey"].getStr("")
# Create Waku client
let wakuClient = initWakuClient(wakuCfg)

View File

@ -0,0 +1,6 @@
# Ethereum addresses derived from keys.env. Keep in sync if those keys change.
ADDR_MIX1=0x8ba6d3237e6f2c84b0e3d71aa57bc5869d3b5218
ADDR_MIX2=0x8e3d4d0a713087e2263e2fcdec894c283c777dcc
ADDR_MIX3=0xca282bbf8bf3636e15af3ad8caf11cdd38bf35d8
ADDR_SENDER=0x0b6872aaae7a2d4f3c701793cde57b93337f4d4a
ADDR_RECEIVER=0xb5dda07309f5ab06e0847f6036c305ea9ae26937

View File

@ -0,0 +1,9 @@
# Test fixtures for the RLN gifter EIP-191 auth path. NOT FOR PRODUCTION.
# Each value is a 64-hex-char secp256k1 private key. addresses.env holds
# the corresponding Ethereum addresses; if these keys change, regenerate
# the addresses (any keccak256(secp256k1 pubkey)[12:] tool will do).
KEY_MIX1=2c974e0a453f65dd2230d403f6981fc18f9a3ad7675afb647910e0798a3eaa4f
KEY_MIX2=b880df1f571109e646f641636794dfe7ffefc2aab19290ba0d720c407758304d
KEY_MIX3=0b1b5e18839a3e15b119519092e4a94a71122acf57d8b2e1014df0121cb6f0ea
KEY_SENDER=5284ac01fed5fcb6b26933ac4a901412b66fcd7ee5b945b799f147a3b42f49ef
KEY_RECEIVER=a5619d6bfde09f54165ec9da55a7be7380f1b258c8279177dbda5ac235d0e904

View File

@ -179,6 +179,16 @@ CONFIG_ACCOUNT=$(echo "$SETUP_OUTPUT" | grep -oE 'Config account:\s+\S+' | awk '
GIFTER_ACCOUNT=$(cat "$GIFTER_ACCOUNT_FILE" 2>/dev/null || true)
[ -z "$GIFTER_ACCOUNT" ] && die "Gifter account not found at $GIFTER_ACCOUNT_FILE"
# EIP-191 auth fixtures: per-process secp256k1 keys and the allowlist installed
# on the gifter (mix node 0). Keys are committed test fixtures — not for prod.
GIFTER_AUTH_DIR="$SCRIPT_DIR/fixtures/gifter_auth"
# shellcheck disable=SC1091
source "$GIFTER_AUTH_DIR/keys.env"
# shellcheck disable=SC1091
source "$GIFTER_AUTH_DIR/addresses.env"
GIFTER_ALLOWLIST="$ADDR_MIX1,$ADDR_MIX2,$ADDR_MIX3,$ADDR_SENDER,$ADDR_RECEIVER"
echo " Gifter allowlist: $GIFTER_ALLOWLIST"
# ---------- Phase 3: Prerequisites ----------
echo "[3/6] Verifying prerequisites..."
LOGOSCORE="${LOGOSCORE:-$(nix build github:logos-co/logos-liblogos/7df6195 --override-input logos-cpp-sdk github:logos-co/logos-cpp-sdk/a4bd66c --no-link --print-out-paths)/bin/logoscore}"
@ -238,9 +248,11 @@ for i in $(seq 0 $((NUM_NODES - 1))); do
GIFTER_FIELDS=""
if [ "$i" -eq 0 ]; then
GIFTER_FIELDS="\"mixGifterService\": true, \"mixGifterWalletAccount\": \"$GIFTER_ACCOUNT\","
GIFTER_FIELDS="\"mixGifterService\": true, \"mixGifterWalletAccount\": \"$GIFTER_ACCOUNT\", \"mixGifterAllowlist\": \"$GIFTER_ALLOWLIST\","
else
GIFTER_FIELDS="\"mixGifterNode\": \"$BOOTSTRAP_PEER\", \"mixGifterWalletAccount\": \"$GIFTER_ACCOUNT\","
# KEY_MIX1..3 align with non-gifter nodes 1..3.
AUTH_KEY_VAR="KEY_MIX$i"
GIFTER_FIELDS="\"mixGifterNode\": \"$BOOTSTRAP_PEER\", \"mixGifterWalletAccount\": \"$GIFTER_ACCOUNT\", \"mixGifterAuthKey\": \"${!AUTH_KEY_VAR}\","
fi
cat > "$NODE_CONFIG" <<EOF
@ -402,6 +414,7 @@ cat > "$RECV_CONFIG" <<EOF
"destPeerAddr": "$BOOTSTRAP_PEER",
"minMixPoolSize": 4,
"gifterNodeAddr": "$BOOTSTRAP_PEER",
"gifterAuthKey": "$KEY_RECEIVER",
"staticPeers": [$CHAT_STATIC_PEERS]
}
EOF
@ -470,6 +483,7 @@ cat > "$SEND_CONFIG" <<EOF
"destPeerAddr": "$BOOTSTRAP_PEER",
"minMixPoolSize": 4,
"gifterNodeAddr": "$BOOTSTRAP_PEER",
"gifterAuthKey": "$KEY_SENDER",
"staticPeers": [$CHAT_STATIC_PEERS]
}
EOF

View File

@ -2,6 +2,8 @@ import
chronicles,
chronos,
confutils,
eth/common/addresses as eth_addresses,
eth/common/keys as eth_keys,
eth/p2p/discoveryv5/enr as eth_enr,
libp2p/crypto/crypto,
libp2p/crypto/curve25519,
@ -104,6 +106,7 @@ type WakuConfig* = object
destPeerAddr*: string
minMixPoolSize*: int
gifterNodeAddr*: string
gifterAuthKey*: string
type
WakuClient* = ref object
@ -125,7 +128,8 @@ proc DefaultConfig*(): WakuConfig =
shardId: @[shardId], pubsubTopic: &"/waku/2/rs/{clusterId}/{shardId}",
staticPeers: LogosDevStaticPeers,
mixEnabled: false, mixNodes: @[], destPeerAddr: "", minMixPoolSize: 4,
gifterNodeAddr: "")
gifterNodeAddr: "",
gifterAuthKey: "")
proc sendBytes*(client: WakuClient, contentTopic: string,
@ -376,8 +380,18 @@ proc start*(client: WakuClient) {.async.} =
gifterPeer = client.cfg.gifterNodeAddr,
idCommitment = idCommitmentHex[0 .. 15] & "..."
var authPayload = none(seq[byte])
if client.cfg.gifterAuthKey.len > 0:
let seckey = eth_keys.PrivateKey.fromHex(client.cfg.gifterAuthKey).valueOr:
error "Failed to parse gifter auth key", error = $error
quit(QuitFailure)
let sig = seckey.sign(rln_gifter_protocol.eip191Message(idCommitmentHex))
authPayload = some(@(sig.toRaw()))
info "Signing gifter request with EIP-191 auth key",
signer = seckey.toPublicKey().to(eth_addresses.Address).to0xHex()
let regRes = await gifterClient.requestMembership(
idCommitmentHex, uint64(lezGm.userMessageLimit), gifterPeer
idCommitmentHex, uint64(lezGm.userMessageLimit), gifterPeer, authPayload
)
if regRes.isErr:
error "Failed to register via gifter", error = regRes.error

@ -1 +1 @@
Subproject commit f3f1aa6c609fae776712e04ccf0aa5a64f004391
Subproject commit 6f0c33ea3846d89b615a053edf38ffc2768d091f

2
vendor/nwaku vendored

@ -1 +1 @@
Subproject commit 48065f7d703568dbc458abf9432a63adc2e80b33
Subproject commit 41d73f92eb4e7810f830d18e8634d72759472936