research/tools/simulators/blend/pd/tests/test_mixclock.py
Marcin Pawlowski 6ad63ce2f3
Add pd: peering-degree Blend Monte-Carlo graph simulator
Static-graph simulator quantifying how a node's peering degree trades off
propagation speed, adversary exposure, deanonymization, and reliability in the
Blend network. Scales to 1e6 nodes (sparse CSR + sampled Dijkstra); the
adversary and deanonymization metrics are exact at every N.

Model (ms): seeded d-regular peer graph (matching-union), Blend cascade
(sender -> blend_hops timed-release mix relays -> final flood), geographic link
base + exponential transport jitter, per-node processing lag, free-running
release-clock mixing.

Metrics:
- propagation: full-delay mean/p50/p90/p99, path/broadcast split, coverage times
- reliability: message success-delivery-rate ~ (1-unresponsive_frac)^blend_hops
  and flood coverage, with unresponsive nodes modelled as routing holes
- adversary (exact): observed/eclipsed fractions, random + worst-case placement
- deanonymization (exact): P(whole blend path adversarial) ~ f_adv^blend_hops,
  and full deanonymization (path adversarial AND honest sender peered with an
  adversary) = deanon_rate * observed_frac

Deterministic blake2b seed streams, three parquet tables, joblib parallelism,
memguard, an analytic verify harness, 50 unit tests, and an auto-installing
Makefile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 17:59:55 +02:00

25 lines
649 B
Python

import numpy as np
from pd.mixclock import mean_residual_ms, mix_wait
def test_zero_max_delay_is_zero():
rng = np.random.default_rng(0)
w = mix_wait(rng, 0, 1000)
assert np.all(w == 0.0)
def test_residual_within_bounds():
rng = np.random.default_rng(1)
m = 5
w = mix_wait(rng, m, 100000)
assert w.min() >= 0.0
assert w.max() <= m * 1000.0 + 1e-6 # residual within a covering interval (<= M seconds)
def test_mean_matches_analytic():
rng = np.random.default_rng(2)
for m in (1, 3, 8):
w = mix_wait(rng, m, 400000)
assert abs(w.mean() - mean_residual_ms(m)) < 0.03 * mean_residual_ms(m)