mirror of
https://github.com/Xahau/xahaud.git
synced 2026-04-29 15:37:46 +00:00
test(testnet): assert zero entropy in degraded ledgers
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
""":descr: 4/5 liveness, 3/5 stall, zero entropy (bootstrap skip), recovery"""
|
||||
""":descr: 4/5 liveness, 3/5 zero-entropy fallback, recovery"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -20,21 +20,36 @@ async def scenario(ctx, log):
|
||||
# Snapshot validated seq before dropping to 3/5.
|
||||
val_before = ctx.validated_ledger_index(0)
|
||||
|
||||
# --- 3/5 validation stall ---
|
||||
# --- 3/5 degraded window ---
|
||||
ctx.stop_node(3)
|
||||
await ctx.wait_for_nodes_down(nodes=[3], timeout=30)
|
||||
|
||||
# 10s ≈ 3 rounds at 3s cadence — enough to validate if quorum existed.
|
||||
# 10s ≈ 3 rounds at 3s cadence.
|
||||
await ctx.sleep(10)
|
||||
|
||||
val_after = ctx.validated_ledger_index(0)
|
||||
log(f"3/5: validated ledger {val_before} → {val_after}")
|
||||
|
||||
if val_after and val_before and val_after > val_before:
|
||||
raise AssertionError(
|
||||
f"Validated ledger advanced ({val_before}→{val_after}) "
|
||||
f"with only 3/5 validators"
|
||||
)
|
||||
# Accepted/built ledgers may still later appear as validated once the full
|
||||
# network rejoins. For ConsensusEntropy the key invariant is that every
|
||||
# ledger created during this sub-quorum window carries ZERO entropy.
|
||||
degraded_zero = 0
|
||||
degraded_end = val_after or val_before
|
||||
if val_before and degraded_end and degraded_end > val_before:
|
||||
for seq in range(val_before + 1, degraded_end + 1):
|
||||
ce, _ = get_entropy_tx(ctx, seq)
|
||||
digest, entropy_count, is_zero = entropy_fields(ce)
|
||||
|
||||
if not is_zero:
|
||||
raise AssertionError(
|
||||
f"Ledger {seq}: expected ZERO entropy during 3/5 window, "
|
||||
f"got Digest={digest[:16]}... EntropyCount={entropy_count}"
|
||||
)
|
||||
|
||||
degraded_zero += 1
|
||||
log(f" Degraded ledger {seq}: EntropyCount={entropy_count} ZERO")
|
||||
|
||||
log(f"3/5 entropy summary: {degraded_zero} zero")
|
||||
|
||||
# Log checks tied to actual transition mechanics:
|
||||
# - seq=1 proposals are emitted once commit-set phase is entered
|
||||
@@ -64,20 +79,21 @@ async def scenario(ctx, log):
|
||||
await ctx.wait_for_ledgers(1, node_id=0, timeout=120)
|
||||
|
||||
val_recovered = ctx.validated_ledger_index(0)
|
||||
log(f"Recovered: validated seq {val_before} → {val_recovered}")
|
||||
pre_recovery = max(v for v in [val_before, val_after] if v is not None)
|
||||
log(f"Recovered: validated seq {pre_recovery} → {val_recovered}")
|
||||
|
||||
if not val_recovered or not val_before or val_recovered <= val_before:
|
||||
if not val_recovered or val_recovered <= pre_recovery:
|
||||
raise AssertionError(
|
||||
f"Validated ledger did not advance after recovery "
|
||||
f"({val_before} → {val_recovered})"
|
||||
f"({pre_recovery} → {val_recovered})"
|
||||
)
|
||||
|
||||
# Inspect recovery ledgers: during the stall, entropy falls to zero
|
||||
# (bootstrap skip). The first ledger after val_before may still carry
|
||||
# real entropy from an in-flight round before node 3 went down.
|
||||
# Inspect post-recovery ledgers separately from the degraded window above.
|
||||
# Once the network is back at quorum, non-zero entropy is valid again but
|
||||
# must still be quorum-met.
|
||||
zero_count = 0
|
||||
nonzero_count = 0
|
||||
for seq in range(val_before + 1, val_recovered + 1):
|
||||
for seq in range(pre_recovery + 1, val_recovered + 1):
|
||||
ce, _ = get_entropy_tx(ctx, seq)
|
||||
digest, entropy_count, is_zero = entropy_fields(ce)
|
||||
|
||||
@@ -98,13 +114,4 @@ async def scenario(ctx, log):
|
||||
|
||||
log(f"Entropy summary: {zero_count} zero, {nonzero_count} non-zero")
|
||||
|
||||
# With quorum-gated entropy, sub-quorum reveals produce zero entropy.
|
||||
# Allow at most 1 non-zero in case node 3 completes the full pipeline
|
||||
# (commit + reveal) before dying — that's a valid quorum-met round.
|
||||
if nonzero_count > 1:
|
||||
raise AssertionError(
|
||||
f"Expected at most 1 non-zero entropy ledger during stall, "
|
||||
f"got {nonzero_count}"
|
||||
)
|
||||
|
||||
log("PASS")
|
||||
|
||||
Reference in New Issue
Block a user