Nakamoto Consensus's Probabilistic Finality and Selfish Mining TODO
Concept
Nakamoto consensus produces blocks via proof of work and treats the chain with the greatest cumulative work as canonical — finality here isn't absolute, it's probabilistic. The more honest blocks get stacked on top of a given block, the bigger the gap an attacker has to make up to revert it, so the probability of reversion decreases exponentially as confirmations accumulate. This guarantee holds only under the assumptions that the attacker's hash power is less than the honest majority's and that network propagation is fast enough. Selfish mining is a strategy where a miner withholds a mined block instead of publishing it immediately, keeping a secret chain, then releases it strategically when an honest block appears, invalidating honest miners' work. This strategy shows that an attacker can earn a reward share above their actual hash-power share even well below a majority, revealing that a protocol's incentive-compatibility is a separate question from its safety threshold.
How many confirmations to wait for is a decision that converts a safety parameter into money, and the existence of incentive-based attacks means an honest-majority assumption alone can't justify a system's safety.
Code & Formula
# 나카모토 합의의 확률적 최종성 — 공격자 해시파워 비율과 확인 수(confirmation)에 따른
# 되돌림(reorg) 성공 확률을 랜덤 워크 시뮬레이션으로 추정한다 (selfish mining 없이 정직한 다수 가정).
import random
random.seed(11)
def simulate_reorg_attempt(attacker_ratio, confirmations, max_steps=10000):
"""정직한 체인이 confirmations만큼 앞서 있을 때, 공격자가 따라잡는지 랜덤 워크로 시뮬레이션.
lead > 0: 정직한 체인이 앞선 블록 수. 공격자가 lead를 0 이하로 만들면 추월 성공."""
lead = confirmations
for _ in range(max_steps):
if random.random() < attacker_ratio:
lead -= 1 # 공격자가 블록을 캔다
else:
lead += 1 # 정직한 채굴자가 블록을 캔다
if lead <= 0:
return True # 공격자가 따라잡음 (reorg 성공)
if lead > confirmations + 50:
return False # 격차가 충분히 벌어져 사실상 안전
return False
def estimate_reorg_probability(attacker_ratio, confirmations, trials=2000):
successes = sum(
simulate_reorg_attempt(attacker_ratio, confirmations) for _ in range(trials)
)
return successes / trials
print("공격자 해시파워 비율별, 확인 수(confirmation)에 따른 되돌림 성공 확률 (시뮬레이션):\n")
for attacker_ratio in [0.10, 0.30, 0.45]:
print(f"attacker_ratio = {attacker_ratio}")
for conf in [1, 3, 6]:
p = estimate_reorg_probability(attacker_ratio, conf, trials=1000)
print(f" confirmations={conf}: 되돌림 확률 ≈ {p*100:.1f}%")
print()
print("-> 확인 수가 늘수록, 공격자 비율이 낮을수록 되돌림 확률이 지수적으로 감소한다.")
print(" (해시파워가 정직한 쪽보다 크면(>=50%) 확인 수와 무관하게 결국 따라잡는다.)")
docs/code/algorithms/algorithms-58.py
Exercise
Write a script that takes an attacker's hash-power share and a confirmation count as input and estimates the probability of a successful reversion via a random-walk simulation, then plot the probability curve against confirmation count.
Practical Connection
In a prediction market, deciding how many confirmations to require before crediting a deposit or finalizing settlement has to weigh the probabilistic-finality curve against the amount at stake — and the same question resurfaces, just reshaped into finality rules and reorg risk, on a proof-of-stake chain.
If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.