nym-swizzle
Application-layer traffic-shape obfuscation for privacy-preserving apps — primarily wallets, or anything that fetches sequential, index-addressed data (blocks, notes, checkpoints) or broadcasts at meaningful moments.
A mixnet hides who is talking; it does not hide what your query pattern
says about you. nym-swizzle provides two composable primitives to shape
the pattern itself:
delay— schedule an async action after a randomly sampled delay (uniform, Poisson-process, or normal, with rejection-resampled bounds). The wrapped future is guaranteed not to be polled before its scheduled time.range— decompose an index range into randomly sized, deliberately overlapping, shuffled chunks with full-coverage guarantees, plus start-edge obfuscation: randomized start overlap (anonymity by noise) and checkpoint snapping (anonymity by collision). Push drivers execute the plan with bounded concurrency, either fire-and-forget (for_each_concurrent) or yielding each chunk's result as it completes (stream_concurrent).
All sampling is crypto-grade (OS entropy by default) and seedable (ChaCha20) for reproducible plans — seeds derived from a VRF are treated as opaque seed material.
use Duration;
use ;
// decorrelate a broadcast from the sync milestone that triggered it
let mut s = uniform;
let result = s.run.await;
// resume a sync without your start height linking you to yesterday's session
new
.snap_start
.start_jitter
.plan
.for_each_concurrent
.await;
Examples
Zcash: ready-made policy layer
For Zcash light clients there is a dedicated crate,
nym-swizzle-zcash, which packages these primitives
into chain-specific policy (quantized sync ranges, decoupled persistable
broadcast scheduling) and ships a live example against a public lightwalletd:
It is a separate crate so its example's gRPC/TLS stack (dev-dependencies only) never touches this crate's wasm dependency guarantee.
Profiling harness
A development-time harness proves the statistical claims (delay distributions, chunk geometry, seeded determinism) with SVG plots backed by hard numeric checks:
# plots land in <workspace>/target/swizzle-profiling/
The harness streams 10M samples per delay distribution (and 50k chunk plans / 500k jitter observations) through fixed-size accumulators, holding every sample moment within 0.5–1% of theory.
Wasm
Every non-dev dependency compiles for wasm32-unknown-unknown; the crate is
designed to be wrapped, unmodified, by a wasm-pack wrapper crate with
JavaScript conveniences. Verify with:
Caveats
- Overlap widths and checkpoint spacing trade anonymity-set size against re-downloaded data; there are no settled numbers — the defaults are conservative starting points, not validated recommendations.
- Transport concerns (never broadcast over the sync session; destination splitting) and deduplication of overlapping results stay the application's responsibility.