diff --git a/reports/blend/pd/README.md b/reports/blend/pd/README.md index 702b5cb..ceb9784 100644 --- a/reports/blend/pd/README.md +++ b/reports/blend/pd/README.md @@ -6,7 +6,7 @@ This report quantifies how a node's **peering degree** — the number of symmetr ## Headline -A peering degree of **6–8** is the operating sweet spot across the sizes measured here (10³–10⁵ nodes; the simulator and the exact metrics carry to 10⁶ — see §5). Below 6, propagation is slow, eclipse is non-negligible at high adversary fractions, and — the sharpest failure — the responsive sub-network *shatters* under heavy churn: a degree-`d` network survives churn only up to `u_c = 1 − 1/(d − 1)`, which is 50 % at degree 3 but 80 % at degree 6 and 86 % at degree 8. Above ~8 the speed, eclipse, and churn gains flatten while observation and full-deanonymization exposure keep climbing, so there is no reason to go higher for transport alone. Anonymity is bought separately, with the number of blend hops: the whole-path capture rate is exactly `f_adv^blend_hops` and does not depend on degree. +A peering degree of **6–8** is the operating sweet spot across the sizes tested (10³–10⁵ for the detailed grids, with a 10⁶ run confirming the results carry; §5). Below 6, propagation is slow, eclipse is non-negligible at high adversary fractions, and — the sharpest failure — the responsive sub-network *shatters* under heavy churn: a degree-`d` network survives churn only up to `u_c = 1 − 1/(d − 1)`, which is 50 % at degree 3 but 80 % at degree 6 and 86 % at degree 8. Above ~8 the speed, eclipse, and churn gains flatten while observation and full-deanonymization exposure keep climbing, so there is no reason to go higher for transport alone. Anonymity is bought separately, with the number of blend hops: the whole-path capture rate is exactly `f_adv^blend_hops` and does not depend on degree. | knob | recommended | why | |---|---|---| @@ -38,6 +38,8 @@ A node's exposure is not only *whether* it is deanonymized but *how soon*: if ea 6. **Messaging redundancy is reliability and exposure in one dial.** Sending each message over `R` independent cascades delivers it if *any* cascade survives — `delivery = 1 − (1 − (1 − u)^blend_hops)^R` — but captures it if *any* cascade is adversarial — `deanon = 1 − (1 − f_adv^blend_hops)^R`. Both obey the same law, so redundancy recovers delivery *and* speeds linking by ≈ `R×` together; it cannot buy reliability without spending anonymity (§3.8). +7. **Correlated outages are the *milder* failure for the live network, not the harsher one.** When failures cluster by AS or region — and peering is regional enough that a failure domain is also a connectivity domain — whole neighbourhoods vanish and every surviving neighbourhood stays whole. Live coverage then holds at 1.000 through 80 % churn, at every degree tested, and the percolation threshold of finding 4 never appears; at degree 4 and 70 % churn, scattered failure annihilates the network (coverage 0.001, delivery 0.000) while the same number of clustered failures still delivers 30 % of messages. The cost is that dead domains become unreachable islands rather than offline nodes among live peers, so coverage *of all nodes* falls instead. The uncorrelated threshold of finding 4 is therefore the conservative case for the operating network (§3.9). + **The tension, in one line.** Axes 1, 2-eclipse, and 4 all want *more* degree; axis 2-observation and axis 3-full-deanonymization want *less*. Because whole-path deanonymization (axis 3) depends only on the blend-path length, the resolution is to raise the degree to where speed, eclipse, and churn saturate (6–8) and to control anonymity independently through the number of blend hops. Messaging redundancy (finding 6) does not escape the trade — it moves reliability and anonymity together, never apart — and time itself is an axis: exposure is a rate, and a high-stake node accumulates it fastest (finding 5). *Method note: the peer graph is a deterministic, exactly d-regular matching-union reconstructible from one seed; the adversary observation/eclipse counts and both deanonymization rates are computed in closed form, so they carry no sampling error at any N; propagation delays are Monte-Carlo over random senders (1 000 rounds × 8 topologies = 8 000 rounds per cell; see §5 for the resulting error bars). Delays fold a geographic link base (15–200 ms), an exponential transport jitter, and a per-node processing lag ({10, 50, 100} ms); mixing is the residual wait to a relay's next free-running release on a Uniform{0…3}-second clock.* @@ -269,12 +271,38 @@ Expressing the cost as *time* rather than as a per-emission probability is what ![Fig 17 — redundancy speeds linking](report-figures/17_time_to_link_vs_stake_redundancy.png) *Fig 17 — Time to link vs stake, one line per redundancy R (α = 0.9). Each extra cascade multiplies the capture rate by ≈ R, cutting the time to link proportionally.* + +### 3.9 Correlated outages — when whole regions go dark + +§3.5 removes nodes independently. Real outages do not work that way: a datacentre, an AS or a region fails as a unit. To model that, the network is partitioned into equal-sized **failure domains** and a `regional` churn mode takes domains down whole, until exactly the same number of nodes are dead as under uniform churn — so the two are compared at identical churn on identical topologies. + +One modelling point decides whether this is interesting at all. If peering ignores regions, then dropping whole regions still removes a *uniformly random* set of nodes, and correlated churn is statistically indistinguishable from uniform churn — the clustering exists in the operator's world but not in the graph's. Correlation only matters when a failure domain is also a **connectivity** domain, so these runs place 75 % of every node's peers inside its own region (40 domains, N = 20 000, 6 400 rounds/cell). + +The result runs opposite to the intuition that correlated failure is the harsher case: + +| degree | u | live coverage (uniform → regional) | all-node coverage | delivery | +|---|---|---|---|---| +| 4 | 0.5 | 0.853 → **1.000** | 0.854 → 0.751 | 0.370 → 0.489 | +| 4 | 0.6 | 0.532 → **1.000** | 0.533 → 0.641 | 0.113 → 0.403 | +| 4 | 0.7 | 0.001 → **1.000** | 0.001 → 0.511 | 0.000 → 0.297 | +| 8 | 0.6 | 0.980 → **1.000** | 0.980 → 0.787 | 0.384 → 0.407 | +| 8 | 0.8 | 0.608 → **1.000** | 0.609 → 0.491 | 0.072 → 0.197 | + +**Clustered failure does not fragment the network; scattered failure does.** Under regional churn the live coverage is **1.000 at every degree and every churn level tested, up to 80 % of the network dead** — the percolation threshold of §3.5 simply does not appear. The reason is structural: removing a domain removes an entire neighbourhood and leaves every surviving neighbourhood whole, so a survivor keeps all its local peers, while uniform churn of the same size damages *every* neighbourhood at once. Degree 4 at 70 % churn is the extreme case: scattered failure has annihilated the network (live coverage 0.001, delivery 0.000) while the same number of clustered failures leaves the survivors perfectly connected and still delivering 30 % of messages (**Fig 22**). + +The price is paid on the other side of the ledger. Dead domains become unreachable islands — under uniform churn an offline node is surrounded by live peers and still *receives* the flood, but a whole dead region has no live interior, so all-node coverage falls (degree 8: 0.993 at `u = 0.2` down to 0.491 at `u = 0.8`, against ~1.0 → 0.609 for uniform). Which figure matters depends on the question: for keeping the *operating* network in consensus, correlated churn is the milder failure; for delivering to nodes that will come back, it is the harsher one. + +Two consequences for the rest of the report. First, **§3.5's `u_c = 1 − 1/(degree − 1)` is the uncorrelated case, and it is the conservative one** for the live network — a real deployment whose outages cluster by AS or region will hold together past that threshold, not fall short of it. Second, delivery is never worse under correlated churn and is dramatically better past the uniform threshold, because delivery needs the relay to be *routable*, and clustered failure is what preserves routability. + +![Fig 22 — correlated vs uniform churn](report-figures/22_churn_correlated_vs_uniform.png) +*Fig 22 — Correlated (AS/region) outages against uniform churn at matched churn (N = 20 000, degree 8, 1 hop, 40 domains, 75 % locality). Solid = coverage of the live network, dashed = coverage of all nodes. Regional churn holds the live network at 1.000 throughout while stranding the dead domains; uniform churn keeps the dead reachable but takes the whole network down with it.* + --- ## 4. Design guidance -**Choose the peering degree for transport, and set it at 6–8.** Speed (§3.1), eclipse resistance (§3.3), and churn resilience (§3.5) all improve with degree and all saturate by 6–8; the percolation threshold of §3.5 is the binding constraint, ruling out degree 3–4 for any deployment expecting substantial churn. That constraint inverts into a sizing rule: to keep the network connected through a churn fraction `u`, the degree must satisfy **`degree > 1 + 1/(1 − u)`** — degree 4 to survive 50 % churn, 6 to approach 80 %, 8 for 86 %, with a margin above the threshold rather than at it (the critical point itself is where behaviour becomes erratic). Going above ~8 buys little transport and steadily worsens observation and full deanonymization (§3.3, §3.4), so a higher degree is justified only where worst-case eclipse at very low degree, or churn beyond ~86 %, would otherwise be a concern. +**Choose the peering degree for transport, and set it at 6–8.** Speed (§3.1), eclipse resistance (§3.3), and churn resilience (§3.5) all improve with degree and all saturate by 6–8; the percolation threshold of §3.5 is the binding constraint, ruling out degree 3–4 for any deployment expecting substantial churn. That constraint inverts into a sizing rule: to keep the network connected through a churn fraction `u`, the degree must satisfy **`degree > 1 + 1/(1 − u)`** — degree 4 to survive 50 % churn, 6 to approach 80 %, 8 for 86 %, with a margin above the threshold rather than at it (the critical point itself is where behaviour becomes erratic). Going above ~8 buys little transport and steadily worsens observation and full deanonymization (§3.3, §3.4), so a higher degree is justified only where worst-case eclipse at very low degree, or churn beyond ~86 %, would otherwise be a concern. Size the degree against the *uncorrelated* threshold: it is the conservative one, since outages that cluster by AS or region leave the surviving network connected well past it (§3.9). **Choose the blend-path length for anonymity, independently.** Whole-path deanonymization is `f_adv^blend_hops` and does not depend on degree, so the number of hops is a free anonymity control: `blend_hops ≥ ln ε / ln f_adv` for a whole-path-capture target ε against an assumed adversary fraction `f_adv` (§3.4). The cost is paid in latency (1.5–2.7 s/hop by degree, §3.1) and reliability (a `(1 − u)` factor per hop, §3.5), and those costs — not the anonymity benefit — are what bound the usable path length at a given churn level. @@ -290,11 +318,11 @@ Expressing the cost as *time* rather than as a per-emission probability is what ## 5. Validity and caveats - **Structural adversary; timing correlation is the next study, and is blocked on cover traffic.** The adversary is modelled as controlling *nodes* and their peerings: it observes messages traversing relays it owns (deanonymization) and honest nodes it peers (observation). It does **not** perform timing or traffic-analysis correlation across honest relays. That is not an oversight but a sequencing constraint — a timing adversary is only meaningful against a network that emits **cover traffic**, which the Blend design calls for and this simulator does not yet generate. Modelling cover traffic and then the timing-correlation adversary against it is the natural next step; until then a timing attack here would face an unrealistically bare traffic pattern and its results would not transfer. An adversary that adaptively targets the transport path of a *specific* known sender is likewise outside the current model. -- **Uniform, uncorrelated churn.** Unresponsive nodes are an independent uniform-random sample. Correlated outages (by region/AS) or adversarially placed churn would degrade coverage faster than the uniform percolation of §3.5; the results here are the average, not the worst, case for reliability. +- **Churn is modelled both ways; adversarial churn is not.** §3.5 removes nodes independently and §3.9 removes whole AS/region failure domains, at matched churn — and the correlated case turns out to be *gentler* on the live network, so the uncorrelated threshold is the conservative one. What remains outside the model is **adversarially placed** churn: an attacker who chooses which nodes to silence (a cut set rather than a random or clustered set) would be worse than either, and the worst-case placement machinery used for the adversary in §3.3 has no counterpart here. Regional churn also assumes equal-sized domains; real AS sizes are heavy-tailed, so a single dominant provider failing would remove a larger, less uniform slice than modelled. - **Exactly d-regular topology — by design, not by simplification.** Every node has exactly the same number of peers because the protocol requires it: the peer graph is derived by every node from one global seed, so the degree is a protocol constant rather than an emergent property. This is the topology the deployed network will have, so the results are not an idealisation of some heavier-tailed reality — a degree *distribution* would be a different protocol, not a more realistic model of this one. - **Sampled propagation, exact structure — and what each is worth.** Only the propagation quantities are sampled: they are Monte-Carlo over **1 000 rounds × 8 independent topologies = 8 000 rounds per cell**, which puts the standard error at **≤ 0.009 on every delivery rate**, **≤ 0.001 on every coverage figure** (bar the critical cell below), and **≤ 0.04 s on every full-delay mean** (the redundancy study uses 1 200 × 8 = 9 600 rounds per cell, SEM ≤ 0.006, and the churn-threshold study 800 × 8 = 6 400). That is a digit finer than the tables quote, so the reported two-decimal rates and 0.1-second delays are resolved rather than sampling noise; error bars were computed across topologies, which captures graph-to-graph variation as well as round-to-round. Everything else — the graph invariants, the observation and eclipse counts, both deanonymization rates, and therefore all of §3.6–§3.8's derived times — is closed-form and carries **no sampling error at all** at any N. The worst-case adversary placement is a greedy envelope characterized at N ≤ 10⁵. - **One cell is intrinsically unstable, by physics rather than sampling.** Coverage at degree 3 with `u = 0.5` sits exactly on that degree's percolation threshold, where the giant component is bimodal: five of eight topologies delivered to no one, three to 0.3–8.6 % of the network. Five times the rounds moved its mean only from 0.019 to 0.024 and left the spread untouched (SEM 0.009), because the variation is across *topologies*, not rounds — it is the critical point. §3.5 therefore states the threshold law rather than a mean there. -- **Measured to 10⁵, not to 10⁶.** Every figure and table here comes from runs at N ≤ 100 000. The simulator is built for 10⁶ — the graph builder, the memory guard and the exact adversary reductions all handle it, and `make sweep-fullscale` runs that grid — but no 10⁶ run backs the numbers in this report. The size-scaling evidence is §3.2's three decades (10³/10⁴/10⁵), over which the full delay rose 18 %; extrapolating that trend to 10⁶ is an inference, not a measurement. +- **The tables are 10⁵; 10⁶ is a separate, lighter check.** Every table and figure in §3.1–§3.9 comes from runs at N ≤ 100 000, where the sampling is heavy. A dedicated 10⁶ run (`make sweep-fullscale`) confirms the results carry: the adversary closed forms are reproduced to within 1.6×10⁻⁴ at a million nodes, coverage under churn is indistinguishable from 10⁵ (degree 8 at `u = 0.5`: 0.9958 against 0.9959), delivery still tracks `(1 − u)^hops`, and the full delay rises only 5.8 % from 10⁵ to 10⁶ (degree 8, 3 hops: 5.86 s → 6.20 s). That run samples 192 rounds per cell rather than 8 000, so it is a **scaling check with ±0.04 error bars, not a source of headline numbers** — which is why the tables above are not restated from it. - **Single mixing setting in the headline sweep.** The multi-second totals assume a Uniform{0…3}-second free-running mix clock; the per-hop mixing cost scales with `max_blend_delay`, but the *shape* of every finding (degree convexity, `f_adv^hops` deanonymization, `(1 − u)^hops` delivery, the coverage percolation) is independent of it. - **Idealised emission and linking model (§3.6–§3.8).** The time-to-link and stake-inference results assume one emission per 30 s slot with the emitter drawn exactly proportional to stake, independent emissions, and that a single wholly-adversarial cascade is a definitive, permanent link. A real adversary doing statistical disclosure could link *faster* by correlating partial observations; conversely, cover traffic, non-stake-proportional sending, or key rotation would slow it. The redundancy cascades are treated as independent given the responsive mask (a shared-relay correlation trims delivery by < 1.5 %, §6); attribution uses the whole-path capture rate, not once-linked cheaper observation, so these times are conservative upper bounds within the structural model. @@ -303,10 +331,10 @@ Expressing the cost as *time* rather than as a per-emission probability is what ## 6. Reproducibility -The simulator, configs, and analytic checks live in [`tools/simulators/blend/pd`](../../../tools/simulators/blend/pd). From that directory: `make install`, then `make sweep` runs the main grid (`configs/default.yaml`: N up to 10⁵, degree 3–16, 1–5 blend hops, `f_adv` up to 0.5, unresponsive fractions to 0.5, all three placement modes, 8 topology seeds) into `runs/_default/`, writing three tables — `propagation.parquet`, `adversary.parquet`, and `deanon.parquet` — and rendering the figures. `make sweep-fullscale` extends the exact metrics to 10⁶ nodes. The messaging-redundancy study (§3.8) and the linkability figures come from `configs/redundancy.yaml` (`python -m pd.sweep --config configs/redundancy.yaml`), which sweeps `redundancy` ∈ {1, 2, 3, 4} alongside the churn and adversary grids; the churn-threshold study (§3.5, Fig 20) comes from `configs/percolation.yaml`, which walks the unresponsive fraction to 0.9 so each degree's collapse can be located against `u_c = 1 − 1/(degree − 1)`. Round counts in all three configs are set for statistical resolution, not speed — see the sampling-error note in §5. `make verify` runs the analytic anchors (d-regularity; `observed ≈ 1 − (1 − f)^degree`; `eclipsed ≈ f^degree`; delivery `≈ (1 − u)^blend_hops`; both deanonymization rates against a direct Monte-Carlo of the same draw; and — check 6 — `deanon_R` / `delivery_R = 1 − (1 − x)^R` for R independent cascades and the time-to-link geometric law), and `make test` the unit suite (`test_linkability.py` covers the time-to-link and stake formulae). The time-to-link and stake-inference curves are computed by `pd.linkability` from these exact rates. +The simulator, configs, and analytic checks live in [`tools/simulators/blend/pd`](../../../tools/simulators/blend/pd). From that directory: `make install`, then `make sweep` runs the main grid (`configs/default.yaml`: N up to 10⁵, degree 3–16, 1–5 blend hops, `f_adv` up to 0.5, unresponsive fractions to 0.5, all three placement modes, 8 topology seeds) into `runs/_default/`, writing three tables — `propagation.parquet`, `adversary.parquet`, and `deanon.parquet` — and rendering the figures. `make sweep-fullscale` extends the exact metrics to 10⁶ nodes. The messaging-redundancy study (§3.8) and the linkability figures come from `configs/redundancy.yaml` (`python -m pd.sweep --config configs/redundancy.yaml`), which sweeps `redundancy` ∈ {1, 2, 3, 4} alongside the churn and adversary grids; the churn-threshold study (§3.5, Fig 20) comes from `configs/percolation.yaml`, which walks the unresponsive fraction to 0.9 so each degree's collapse can be located against `u_c = 1 − 1/(degree − 1)`; and the correlated-outage study (§3.9, Fig 22) from `configs/correlated-churn.yaml` (`make correlated-churn`), which partitions the network into failure domains and runs both churn modes on the same topologies. `make sweep-fullscale` produces the 10⁶ scaling check described in §5. Round counts in all three configs are set for statistical resolution, not speed — see the sampling-error note in §5. `make verify` runs the analytic anchors (d-regularity; `observed ≈ 1 − (1 − f)^degree`; `eclipsed ≈ f^degree`; delivery `≈ (1 − u)^blend_hops`; both deanonymization rates against a direct Monte-Carlo of the same draw; and — check 6 — `deanon_R` / `delivery_R = 1 − (1 − x)^R` for R independent cascades and the time-to-link geometric law), and `make test` the unit suite (`test_linkability.py` covers the time-to-link and stake formulae). The time-to-link and stake-inference curves are computed by `pd.linkability` from these exact rates. The figures of record for this report are the copies checked in under [`report-figures/`](report-figures); the simulator does not commit its own generated figures. To regenerate: run the sweeps above, then copy `runs/<…>/figures/*.png` into `report-figures/`. ## Figures -All twenty-one rendered figures are versioned in [`report-figures/`](report-figures): `01`–`03` propagation delay (vs degree, vs path length, vs N); `04`–`09` adversary observation and eclipse (vs `f_adv`, vs degree, and heatmaps); `10`–`11` reliability under churn (delivery and coverage); `12`–`15` deanonymization (whole-path and full, vs path length, `f_adv`, and degree); `16`–`18` linkability over time (time to link vs stake, with redundancy, and time to learn stake vs threshold); `19` the redundancy reliability-vs-anonymity trade-off in probability and `21` the same trade in delivery-vs-time-to-link; `20` the churn-percolation threshold. Fifteen of the twenty-one are embedded above; the other six (`04`–`06`, `09`, `11`, `13`) are alternative cuts of data already shown — for instance 11 and 20 both plot coverage against churn, and 20 supersedes 11 by walking the churn past every degree's threshold. +All twenty-two rendered figures are versioned in [`report-figures/`](report-figures): `01`–`03` propagation delay (vs degree, vs path length, vs N); `04`–`09` adversary observation and eclipse (vs `f_adv`, vs degree, and heatmaps); `10`–`11` reliability under churn (delivery and coverage); `12`–`15` deanonymization (whole-path and full, vs path length, `f_adv`, and degree); `16`–`18` linkability over time (time to link vs stake, with redundancy, and time to learn stake vs threshold); `19` the redundancy reliability-vs-anonymity trade-off in probability and `21` the same trade in delivery-vs-time-to-link; `20` the churn-percolation threshold; `22` correlated versus uniform outages. Sixteen of the twenty-two are embedded above; the other six (`04`–`06`, `09`, `11`, `13`) are alternative cuts of data already shown — for instance 11 and 20 both plot coverage against churn, and 20 supersedes 11 by walking the churn past every degree's threshold. diff --git a/reports/blend/pd/report-figures/22_churn_correlated_vs_uniform.png b/reports/blend/pd/report-figures/22_churn_correlated_vs_uniform.png new file mode 100644 index 0000000..79c8e3e Binary files /dev/null and b/reports/blend/pd/report-figures/22_churn_correlated_vs_uniform.png differ