mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-07 03:33:33 +00:00
55 lines
2.2 KiB
Python
55 lines
2.2 KiB
Python
|
|
import numpy as np
|
||
|
|
|
||
|
|
from tsi_sim.blocktree import build_tree
|
||
|
|
from tsi_sim.latency import FixedSlotLatency
|
||
|
|
|
||
|
|
|
||
|
|
def _winners(*groups):
|
||
|
|
return [np.array(g, dtype=np.int64) for g in groups]
|
||
|
|
|
||
|
|
|
||
|
|
def test_latency_induces_fork_and_longest_chain():
|
||
|
|
# L=2. slot0: node0; slot1: node1 (can't see block1 yet -> forks on genesis);
|
||
|
|
# slot3: node2 (sees both, builds on the earlier-slot tip -> block1).
|
||
|
|
active = np.array([0, 1, 3], dtype=np.int64)
|
||
|
|
winners = _winners([0], [1], [2])
|
||
|
|
tree = build_tree(active, winners, FixedSlotLatency(2), np.random.default_rng(0))
|
||
|
|
|
||
|
|
assert tree.n_blocks == 4 # genesis + 3
|
||
|
|
assert tree.height.tolist() == [0, 1, 1, 2]
|
||
|
|
# block 3 built on block 1 (earlier slot wins the height-1 tie)
|
||
|
|
assert tree.parent[3] == 1
|
||
|
|
assert tree.canonical_chain() == [3, 1] # tip-first
|
||
|
|
# block 2 is the orphan
|
||
|
|
canon = set(tree.canonical_chain())
|
||
|
|
orphans = [b for b in range(1, tree.n_blocks) if b not in canon]
|
||
|
|
assert orphans == [2]
|
||
|
|
|
||
|
|
|
||
|
|
def test_same_slot_multiwinner_forks_even_at_zero_latency():
|
||
|
|
active = np.array([0, 1], dtype=np.int64)
|
||
|
|
winners = _winners([0, 1], [2]) # two winners in slot 0 -> guaranteed fork
|
||
|
|
tree = build_tree(active, winners, FixedSlotLatency(0), np.random.default_rng(0))
|
||
|
|
# blocks 1 and 2 are siblings at height 1 on genesis
|
||
|
|
assert tree.parent[1] == 0 and tree.parent[2] == 0
|
||
|
|
assert tree.height[1] == 1 and tree.height[2] == 1
|
||
|
|
# block 3 at slot 1 extends one of them (height 2)
|
||
|
|
assert tree.height[3] == 2
|
||
|
|
assert len(tree.canonical_chain()) == 2
|
||
|
|
|
||
|
|
|
||
|
|
def test_self_extension_within_latency():
|
||
|
|
# A single node winning consecutive slots builds on its own block despite latency.
|
||
|
|
active = np.array([0, 1], dtype=np.int64)
|
||
|
|
winners = _winners([5], [5])
|
||
|
|
tree = build_tree(active, winners, FixedSlotLatency(10), np.random.default_rng(0))
|
||
|
|
assert tree.parent[2] == 1 # node 5 self-extends
|
||
|
|
assert tree.height.tolist() == [0, 1, 2]
|
||
|
|
|
||
|
|
|
||
|
|
def test_ancestors():
|
||
|
|
active = np.array([0, 1, 2], dtype=np.int64)
|
||
|
|
winners = _winners([0], [0], [0]) # one node, clean chain
|
||
|
|
tree = build_tree(active, winners, FixedSlotLatency(0), np.random.default_rng(0))
|
||
|
|
assert tree.ancestors(3) == [3, 2, 1]
|