mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-07 19:53:10 +00:00
75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
import numpy as np
|
|
|
|
from tsi_sim.blocktree import BlockTree
|
|
from tsi_sim.tsi import density_m, referenced_uncle_ids, slot_stats, update_D
|
|
|
|
|
|
def make_tree(slots, parents, heights, uncles):
|
|
n = len(slots)
|
|
return BlockTree(
|
|
slot=np.array(slots, np.int64),
|
|
parent=np.array(parents, np.int64),
|
|
height=np.array(heights, np.int64),
|
|
leader=np.zeros(n, np.int64),
|
|
uncles=uncles,
|
|
)
|
|
|
|
|
|
def test_density_counts_honest_plus_deduped_uncles_in_window():
|
|
# canonical 1(slot0),4(slot3); orphans 2(slot1),3(slot2). block4 refs uncles 2 and 3.
|
|
tree = make_tree(
|
|
slots=[-1, 0, 1, 2, 3],
|
|
parents=[-1, 0, 0, 0, 1],
|
|
heights=[0, 1, 1, 1, 2],
|
|
uncles=[(), (), (), (), (2, 3)],
|
|
)
|
|
canonical = [4, 1] # tip-first
|
|
# window T=10 includes all slots
|
|
assert density_m(tree, canonical, T=10) == 4 # 2 honest (slots 0,3) + 2 uncles (1,2)
|
|
# window T=2 excludes slots 2,3 -> honest {slot0}=1, uncle slot1=1 (slot2 excluded)
|
|
assert density_m(tree, canonical, T=2) == 2
|
|
|
|
|
|
def test_uncle_counted_by_own_slot_and_deduped():
|
|
tree = make_tree(
|
|
slots=[-1, 0, 5, 1],
|
|
parents=[-1, 0, 1, 0],
|
|
heights=[0, 1, 2, 1],
|
|
uncles=[(), (), (3,), ()], # block2 (slot5) references orphan 3 (slot1)
|
|
)
|
|
canonical = [2, 1]
|
|
assert referenced_uncle_ids(tree, canonical) == {3}
|
|
# uncle counted by its OWN slot (1), so window T=2 includes it
|
|
assert density_m(tree, canonical, T=2) == 2 # honest slot0 + uncle slot1
|
|
# window that excludes the uncle's own slot
|
|
assert density_m(tree, canonical, T=1) == 1 # only honest slot0
|
|
|
|
|
|
def test_slot_stats_q_and_qeff():
|
|
# active slots 0,1,2 in window; honest occupies 0,2; orphan at slot1 recovered by uncle
|
|
tree = make_tree(
|
|
slots=[-1, 0, 1, 2],
|
|
parents=[-1, 0, 0, 1],
|
|
heights=[0, 1, 1, 2],
|
|
uncles=[(), (), (), (2,)], # block3 refs orphan 2 (slot1)
|
|
)
|
|
canonical = [3, 1]
|
|
active = np.array([0, 1, 2], np.int64)
|
|
ref = referenced_uncle_ids(tree, canonical)
|
|
ss = slot_stats(tree, canonical, ref, active, T=10)
|
|
assert ss.n_active == 3
|
|
assert ss.n_honest == 2 # slots 0 and 2
|
|
assert ss.n_recovered == 1 # slot 1 recovered via uncle
|
|
assert abs(ss.q - 2 / 3) < 1e-9
|
|
assert abs(ss.q_eff - 1.0) < 1e-9
|
|
|
|
|
|
def test_update_D_fixed_point():
|
|
f, T = 1 / 30, 3000
|
|
m = int(round(T * f)) # measured density == f -> D unchanged
|
|
assert abs(update_D(1000.0, m, T, f, beta=1.0) - 1000.0) < 1e-6
|
|
# measured below f -> estimate drops
|
|
assert update_D(1000.0, m - 20, T, f, 1.0) < 1000.0
|
|
# clamp at 1
|
|
assert update_D(1.0, 0, T, f, 1.0) == 1.0
|