-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrun_wasabi_anonymity_study.py
More file actions
97 lines (84 loc) · 4.31 KB
/
Copy pathrun_wasabi_anonymity_study.py
File metadata and controls
97 lines (84 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python3
"""Evaluate the practical anonymity of real Wasabi 2.0 (WabiSabi) rounds.
Scores the per-output anonymity of cached Wasabi rounds
(``data/wasabi2_rounds_enriched.json``, produced by ``fetch_wasabi_rounds.py``)
on the Diaz et al. degree and Serjantov-Danezis effective set, under a *trusted*
coordinator with its deterministic decomposition and ignoring tagging/sybil
side channels (the generous, structural reading). Writes
``wasabi_anonymity_results.json``.
Usage::
python fetch_wasabi_rounds.py --rounds 80 # refresh the dataset first
python run_wasabi_anonymity_study.py
"""
from __future__ import annotations
import json
import time
from dataclasses import asdict
from pathlib import Path
from coinjoin_simulator.wasabi_anonymity import build_wasabi_study
OUTPUT_PATH = Path("wasabi_anonymity_results.json")
def main() -> None:
study = build_wasabi_study()
if study.n_rounds == 0:
print(
"No Wasabi rounds found. Run `python fetch_wasabi_rounds.py` first "
"to populate data/wasabi2_rounds_enriched.json."
)
return
payload = {
"generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"threat_model": (
"trusted coordinator + deterministic decomposition; tagging, "
"address-reuse, timing, and sybil side channels ignored (a generous "
"structural upper bound on Wasabi 2.0 output anonymity)"
),
"n_rounds": study.n_rounds,
"total_standard_outputs": study.total_standard_outputs,
"total_nonstandard_outputs": study.total_nonstandard_outputs,
"standard_value_sats": study.standard_value_sats,
"nonstandard_value_sats": study.nonstandard_value_sats,
"nonstandard_value_share": study.nonstandard_value_share,
"mean_naive_set": study.mean_naive_set,
"mean_effective_set": study.mean_effective_set,
"mean_degree": study.mean_degree,
"mean_degree_given_candidates": study.mean_degree_given_candidates,
"median_effective_set": study.median_effective_set,
"median_round_median_effective_set": study.median_round_median_effective_set,
"round_weighted_mean_effective_set": study.round_weighted_mean_effective_set,
"round_weighted_mean_degree": study.round_weighted_mean_degree,
"round_weighted_deanonymized_fraction": study.round_weighted_deanonymized_fraction,
"value_weighted_mean_effective_set": study.value_weighted_mean_effective_set,
"value_weighted_mean_degree": study.value_weighted_mean_degree,
"mean_bayes_vulnerability": study.mean_bayes_vulnerability,
"mean_worst_case_effective_set": study.mean_worst_case_effective_set,
"deanonymized_fraction": study.deanonymized_fraction,
"amount_bins": [asdict(b) for b in study.amount_bins],
"denomination_summary": [asdict(b) for b in study.denomination_summary],
"rounds": [asdict(r) for r in study.rounds],
}
OUTPUT_PATH.write_text(json.dumps(payload, indent=2) + "\n")
print(f"Wrote {OUTPUT_PATH}\n")
print(f"Wasabi 2.0 anonymity over {study.n_rounds} real rounds "
f"({study.total_standard_outputs} standard outputs):")
print(f" mean same-denomination set (Wasabi number): {study.mean_naive_set:.1f}")
print(f" mean effective set (Diaz/Serjantov-Danezis): {study.mean_effective_set:.1f}")
print(f" mean Diaz degree vs same-denom N: {study.mean_degree:.3f}")
print(
" mean degree given feasible candidates: "
f"{study.mean_degree_given_candidates:.3f}"
)
print(f" median effective set: {study.median_effective_set:.1f}")
print(
" round-weighted mean effective set: "
f"{study.round_weighted_mean_effective_set:.1f}"
)
print(f" nonstandard output value share: {study.nonstandard_value_share:.1%}")
print(f" deanonymized output fraction: {study.deanonymized_fraction:.3f}")
print(
"\nNote: this is the generous structural bound (trusted coordinator, no "
"side channels). Wasabi 2.0's real weaknesses are the central coordinator "
"and the absence of sybil-cost (fidelity-bond) protection, which this "
"number deliberately does not penalize."
)
if __name__ == "__main__":
main()