# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference)
# Canonical Residual: https://corpusfetch.com/c/where-must-an-instance-of-a-bft-ledger-reject-a-commitment-it-can-already-prove.md
# Remnant Warrant:    https://corpusfetch.com/c/where-must-an-instance-of-a-bft-ledger-reject-a-commitment-it-can-already-prove.warrant.json
# Markdown SHA-256:   3d658f06494f69c6e2dee8786f6a46acd4d1e6faf576a53a20bb9d531df7e405
# Code AST SHA-256:   f9d7bf09b99343d81365e49cafa70cbea4a22760d4b95148b98699a91bc82d3e
# Verified Classes:   InadmissibleProofError, QuorumCertificate, CommitmentLedger
# Defensive Guards:   2 fail-closed invariants (zero external deps)

from dataclasses import dataclass


class InadmissibleProofError(RuntimeError):
    """Raised when a node attempts to act on a valid but view-stale proof."""


@dataclass(frozen=True)
class QuorumCertificate:
    view: int
    slot: str
    commitment: str
    signers: frozenset


class CommitmentLedger:
    def __init__(self, high_qc_view: int):
        self.high_qc_view = high_qc_view

    def admit_proof(self, proof: QuorumCertificate) -> bool:
        if proof.view >= self.high_qc_view:
            return True
        return False

    def act_on_proof(self, proof: QuorumCertificate) -> str:
        # A node holding a valid QC must still check view-scoped authority.
        if not self.admit_proof(proof):
            raise InadmissibleProofError(
                f"QC for slot={proof.slot!r} formed at view={proof.view} "
                f"is stale relative to high_qc_view={self.high_qc_view}; "
                f"must defer, not veto or finalize"
            )
        # Admissible: safe to veto conflicting commitment or finalize.
        return f"finalized {proof.commitment} at slot {proof.slot}"


def handle_equivocation(
    ledger: CommitmentLedger, stale_qc: QuorumCertificate
) -> str:
    # The dangerous path: node can prove inclusion but proof is inadmissible.
    if not ledger.admit_proof(stale_qc):
        raise InadmissibleProofError(
            "refusing to broadcast view-stale QC as equivocation proof; "
            "queue for reconciliation and continue voting on current view"
        )
    return ledger.act_on_proof(stale_qc)


# Reproduces the observed view-11 / view-12 boundary.
ledger = CommitmentLedger(high_qc_view=12)
stale = QuorumCertificate(
    view=11, slot="T-4471", commitment="payload_p", signers=frozenset("ABCDE")
)
handle_equivocation(ledger, stale)  # raises InadmissibleProofError
