git / moonbite-network / tests/test_calc.py · raw
"""Tests for Milestone 9 — Security Analysis (attacker success probability).Reference values are taken directly from the Bitcoin whitepaper(Nakamoto 2008, section 11)."""import sysfrom pathlib import Pathimport pytestsys.path.insert(0, str(Path(__file__).resolve().parent.parent))from calc import ( # noqa: E402 attacker_success_probability, recommend_confirmations,)def test_z_zero_is_certain(): # With zero confirmations the attacker is already even; P = 1. assert attacker_success_probability(0.1, 0) == 1.0def test_whitepaper_q01_z5(): assert attacker_success_probability(0.1, 5) == pytest.approx(0.0009137, abs=1e-6)def test_whitepaper_q01_z10(): assert attacker_success_probability(0.1, 10) == pytest.approx(0.0000012, abs=1e-7)def test_whitepaper_q03_z5(): assert attacker_success_probability(0.3, 5) == pytest.approx(0.1773523, abs=1e-6)def test_monotonic_decreasing_in_z(): probs = [attacker_success_probability(0.1, z) for z in range(1, 11)] for earlier, later in zip(probs, probs[1:]): assert later < earlierdef test_higher_q_needs_more_confirmations(): assert recommend_confirmations(0.1) < recommend_confirmations(0.3)def test_recommend_q01_is_5(): assert recommend_confirmations(0.1) == 5def test_recommend_q03_is_24(): assert recommend_confirmations(0.3) == 24@pytest.mark.parametrize( "q, expected_z", [ (0.10, 5), (0.15, 8), (0.20, 11), (0.25, 15), (0.30, 24), (0.35, 41), (0.40, 89), (0.45, 340), ],)def test_whitepaper_solving_table(q, expected_z): assert recommend_confirmations(q, 0.001) == expected_zdef test_majority_raises(): with pytest.raises(ValueError): recommend_confirmations(0.5)