davidrusu 5c64a0bd11
Cryptarchia: rework specification (#116)
* cryptarchia/ghost: prep for move to weight based fork choice

* cryptarchia/ghost: remove common_prefix_len helper

* cryptarchia/ghost: common_prefix_depth returns depth of both chains

* cryptarchia/ghost: fix chain density calculation

* cryptarchia/ghost: maxvalid_bg uses block ids rather than chains

* cryptarchia/ghost: unimported_orphans returns orphans w.r.t. to tip

* cryptarchia/ghost: remove redundant check

* cryptarchia/ghost: rewrite unimported_orphan w/ common_prefix_depths

* cryptarchia/ghost: validate_header w.r.t. block parent

* cryptachia/ghost: rewrite on_block to remove dependency on Chain

* cryptarchia/ghost: remove Chain abstraction

* cryptarchia/ghost: remove local / fork naming in common_prefix_depth

* cryptarchia/ghost: rewrite common_prefix_depth in terms of iter_chain

* cryptarchia/ghost: impl GHOST fork choice rule

* cryptarchia/ghost: integrate GHOST with maxvalid fork choice

* cryptarchia: remove unused imports

* cryptarchia: cleanup

* cryptarchia: cleanup

* cryptarchia: remove height from ledger state

* cryptachia/ghost: update fork choice rule comments

* cryptarchia: switch back to longest chain

* cryptarchia: update tests

* cryptarchia: remove debug log
2025-02-25 16:54:54 +04:00

44 lines
1.5 KiB
Python

from unittest import TestCase
import numpy as np
from .cryptarchia import Leader, EpochState, LedgerState, Coin, phi, Slot
from .test_common import mk_config
class TestLeader(TestCase):
def test_slot_leader_statistics(self):
epoch = EpochState(
stake_distribution_snapshot=LedgerState(block=None),
nonce_snapshot=LedgerState(block=None, nonce=b"1010101010"),
inferred_total_active_stake=1000,
)
coin = Coin(sk=0, value=10)
f = 0.05
l = Leader(
config=mk_config([coin]).replace(active_slot_coeff=f),
coin=coin,
)
# We'll use the Margin of Error equation to decide how many samples we need.
# https://en.wikipedia.org/wiki/Margin_of_error
margin_of_error = 1e-4
p = phi(f=f, alpha=10 / epoch.total_active_stake())
std = np.sqrt(p * (1 - p))
Z = 3 # we want 3 std from the mean to be within the margin of error
N = int((Z * std / margin_of_error) ** 2)
# After N slots, the measured leader rate should be within the
# interval `p +- margin_of_error` with high probabiltiy
leader_rate = (
sum(
l.try_prove_slot_leader(epoch, Slot(slot), bytes(32)) is not None
for slot in range(N)
)
/ N
)
assert (
abs(leader_rate - p) < margin_of_error
), f"{leader_rate} != {p}, err={abs(leader_rate - p)} > {margin_of_error}"