mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-07 19:53:10 +00:00
52 lines
2.4 KiB
Python
52 lines
2.4 KiB
Python
|
|
"""Honest stake churn (TSI tracks active stake) and the emergent p_ref metric."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import pandas as pd
|
||
|
|
|
||
|
|
from tsi_sim.config import SimConfig
|
||
|
|
from tsi_sim.engine import _churn_active_fraction, run_trajectory
|
||
|
|
|
||
|
|
BASE = dict(n_nodes=400, stake_dist="pareto", topology="blend", degree=6,
|
||
|
|
link_latency_mean=0.5, link_latency_dist="geo", blend_hops=3, blend_delay_max=4.0,
|
||
|
|
max_uncles=2, uncle_window=300, k=256, epochs=16, genesis_d_factor=0.5)
|
||
|
|
|
||
|
|
|
||
|
|
def test_churn_schedule_shapes():
|
||
|
|
sine = SimConfig(**BASE, churn_amp=0.3, churn_period=4, churn_mode="sine")
|
||
|
|
assert _churn_active_fraction(sine, 0) == 1.0 # cos(0)=1 -> no drop
|
||
|
|
assert abs(_churn_active_fraction(sine, 2) - 0.7) < 1e-9 # trough at half period
|
||
|
|
ramp = SimConfig(**BASE, churn_amp=0.3, churn_period=4, churn_mode="ramp")
|
||
|
|
assert abs(_churn_active_fraction(ramp, 4) - 0.7) < 1e-9
|
||
|
|
assert abs(_churn_active_fraction(ramp, 8) - 0.7) < 1e-9 # holds after ramp
|
||
|
|
step = SimConfig(**BASE, churn_amp=0.3, churn_period=4, churn_mode="step")
|
||
|
|
assert _churn_active_fraction(step, 3) == 1.0
|
||
|
|
assert abs(_churn_active_fraction(step, 4) - 0.7) < 1e-9
|
||
|
|
|
||
|
|
|
||
|
|
def test_churn_zero_is_bit_identical():
|
||
|
|
off = pd.DataFrame(run_trajectory(SimConfig(**BASE)))
|
||
|
|
z = pd.DataFrame(run_trajectory(SimConfig(**BASE, churn_amp=0.0)))
|
||
|
|
assert (off.mean_ratio.to_numpy() == z.mean_ratio.to_numpy()).all()
|
||
|
|
|
||
|
|
|
||
|
|
def test_tsi_tracks_active_stake_under_churn():
|
||
|
|
"""A step drop in active stake: D_hat/D_active stays ~1, D_hat/D_total drops to active_frac."""
|
||
|
|
cfg = SimConfig(**{**BASE, "epochs": 20}, churn_amp=0.3, churn_period=6, churn_mode="step")
|
||
|
|
df = pd.DataFrame(run_trajectory(cfg))
|
||
|
|
tail = df[df.epoch >= 14]
|
||
|
|
# D_hat/D_total tracks the reduced active fraction (~0.7)
|
||
|
|
assert 0.6 < tail.mean_ratio.mean() < 0.8
|
||
|
|
# corrected for active fraction, accuracy is ~1
|
||
|
|
corrected = (tail.mean_ratio / tail.active_stake_frac).mean()
|
||
|
|
assert abs(corrected - 1.0) < 0.05
|
||
|
|
assert tail.range_ratio.max() == 0.0 # churn does not break consensus
|
||
|
|
|
||
|
|
|
||
|
|
def test_p_ref_recorded_and_high_at_recommended_window():
|
||
|
|
cfg = SimConfig(**{**BASE, "blend_delay_max": 8.0, "uncle_window": 300})
|
||
|
|
df = pd.DataFrame(run_trajectory(cfg))
|
||
|
|
assert "p_ref" in df.columns
|
||
|
|
# at a generous window, most orphans get referenced
|
||
|
|
assert df[df.epoch >= 8].p_ref.mean() > 0.7
|