add freeroute simulation results.

This commit is contained in:
M Alghazwi 2026-07-21 13:36:23 +02:00
parent 1408d7e473
commit a0f8a77e9d
No known key found for this signature in database
GPG Key ID: 646E567CAD7DB607
5 changed files with 81 additions and 3 deletions

View File

@ -0,0 +1,65 @@
# freeroutesim results
In the simulation here we consider a path compromised only when every hop is malicious. Each user stops after their first compromised path. users without a compromise run for the full 365 days.
We used the following constant params:
| Parameter | Value |
|-------------------------------------| ---: |
| Users | 5,000 |
| duration | 365 days |
| Topology epoch lifetime | 3,600 seconds |
| path length | 3 hops |
| Vanguard path length | 4 hops, including 2 vanguards and 1 guard |
| Malicious node fraction target | 0.10 |
| Malicious bandwidth fraction target | 0.10 |
| Churn probability per epoch | 0.03 |
Both user models were tested with `random`, `bandwidth-random`, `guard`, and `vanguard` routing. The vanguard sampler requires the number of vanguards to be less than `hops - 1`, so its experiments use four hops and two vanguards rather than the three-hop configuration used by the other modes.
## Run summaries
| Model | Mode | Hops | Compromised after 365 days |
| --- | --- | ---: | ---: |
| Simple | Random | 3 | 100.00% |
| Simple | Bandwidth random | 3 | 100.00% |
| Simple | Guard | 3 | 81.38% |
| Simple | Vanguard (2) | 4 | 19.34% |
| Hidden service | Random | 3 | 100.00% |
| Hidden service | Bandwidth random | 3 | 100.00% |
| Hidden service | Guard | 3 | 72.94% |
| Hidden service | Vanguard (2) | 4 | 15.80% |
| Simple | Random | 14 | 0.00% |
## Uniform-random with different path-length
The simple model was also run in uniform-random mode for every path length from 3 through 14 hops. All other parameters match the ones listed above.
| Hops | Compromised users | Compromised after 365 days | Total messages processed |
| ---: | ---: | ---: | ---: |
| 3 | 5,000 | 100.00% | 4,480,737 |
| 4 | 5,000 | 100.00% | 28,197,495 |
| 5 | 2,495 | 49.90% | 191,932,617 |
| 6 | 359 | 7.18% | 253,472,958 |
| 7 | 21 | 0.42% | 262,498,767 |
| 8 | 1 | 0.02% | 262,978,430 |
| 9 | 0 | 0.00% | 263,015,009 |
| 10 | 0 | 0.00% | 263,016,691 |
| 11 | 0 | 0.00% | 263,020,669 |
| 12 | 0 | 0.00% | 263,015,369 |
| 13 | 0 | 0.00% | 263,014,927 |
| 14 | 0 | 0.00% | 263,020,495 |
## Figures
### Simple model:
![Simple model routing-mode comparison](img/simple_modes.png)
### Hidden-service model:
![Hidden-service model routing-mode comparison](img/hidden_service_modes.png)
### Uniform-random path:
![Uniform-random path-length sweep from 3 through 14 hops](img/random_hops.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

View File

@ -124,18 +124,21 @@ def plot_results(
) -> None:
figure, (time_axis, message_axis) = plt.subplots(1, 2, figsize=(13, 5.5))
for result in results:
colors = plt.get_cmap("tab20").colors if len(results) > 10 else [None] * len(results)
for result, color in zip(results, colors):
time_axis.step(
result.time.x,
result.time.probability,
where="post",
label=result.label,
color=color,
)
message_axis.step(
result.messages.x,
result.messages.probability,
where="post",
label=result.label,
color=color,
)
configure_axis(
@ -150,14 +153,24 @@ def plot_results(
)
if log_messages:
message_axis.set_xscale("symlog", linthresh=1)
message_axis.set_xlim(left=0)
if len(results) > 1:
if len(results) > 6:
handles, labels = time_axis.get_legend_handles_labels()
figure.legend(
handles,
labels,
loc="lower center",
ncol=6,
bbox_to_anchor=(0.5, -0.01),
)
elif len(results) > 1:
time_axis.legend()
message_axis.legend()
if title:
figure.suptitle(title)
figure.tight_layout()
figure.tight_layout(rect=(0, 0.09, 1, 1) if len(results) > 6 else None)
output.parent.mkdir(parents=True, exist_ok=True)
figure.savefig(output, dpi=200, bbox_inches="tight")
print(f"wrote {output}")