Execution-identity specifiers and the ASSURE/REQUIRE rename - #58
Merged
Conversation
SEND_MESSAGE becomes ASSURE and RECEIVE_MESSAGE becomes REQUIRE at the unchanged opcodes 0x42 and 0x43, across CONDITIONS.md, VALIDATION.md rule 3, and the COSTS.md constant table. The mode halves follow the pair: the sender half is now the assurer half and the receiver half the requirer half, in the record tuple, the operand lists, and the signature lines. The ledger semantics are untouched: ASSURE contributes weight +1 and REQUIRE weight -1, and the record vocabulary (message record, message ledger) keeps its names. The rename is Bitcoin-native terminology work: the pair reads as what each condition demands of the transaction rather than as a transport metaphor, and the halves read as the two roles the mode packs. Chia's CHIP-0025 names stay mapped in the glossary, updated in the docs commit of this PR. Decision by Evan, 2026-08-20.
…ve-bit halves The 2026-08-18 amendment, decided by Evan and recorded in the execution plan. Taproot splits Chia's puzzle-hash identity into the coin's script commitment and the executing program, and the specifier table carried only the first, so program-to-program trust had no faithful addressing field. VALIDATION.md changes: - The transaction view's BitLisp input gains its execution identity: tapleaf, the executing leaf's 32-byte leaf hash, and merkleRoot, the spending path's 32-byte root. Base consensus authenticates both against the spent scriptPubKey through the control block, so the pair is validator-filled and unforgeable. - Rule 3 commitment values widen from 0..7 to 0..31: bit 3 composes tapleaf and bit 4 merkleRoot onto the eight prevout rows, each set bit appending its operand after the low bits' operands, tapleaf first. Announcements share the table. - The mode repacks as assurer times 32 plus requirer, ten bits. - The stability table gains both fields as content-class rows, with the per-spend caveat: a tapleaf commitment addresses the program the counterpart runs in this transaction, not the coin. - Author guidance gains the grafted-leaf and moved-root cautions: a leaf hash survives grafting into any tree and a root survives rehoming under any internal key, so execution identity alone never pins a coin. Internal-key addressing is declined on soundness, not deferred: the control block proves no possession of the internal key, so an IPK specifier would read as key-holder identity while proving nothing. CONDITIONS.md changes: the two specifier operand domains (exactly 32 bytes each, merkleRoot never empty since a BitLisp counterpart always executes a leaf of some tree), ASSERT_ANNOUNCEMENT mode 0..31, ASSURE and REQUIRE mode 0..1023 with five-bit halves. Every deployed-Chia mode combination survives the re-encode at its new packing. The widening was chosen over repurposing an existing value because specifier fields are validator-filled, the uniform bit rule reads as one spec sentence, and the re-encode is cheapest before anything ships.
…named Implements the two spec commits. The specifier table composes the tapleaf hash (bit 3) and merkle root (bit 4) onto the eight prevout rows, both operands exactly 32 bytes, appended after the base operands with tapleaf first. ASSURE and REQUIRE modes widen to 0..1023 with five-bit halves, ASSERT_ANNOUNCEMENT to 0..31. The transaction model's input gains tapleaf and merkle_root, required together with a condition list: a BitLisp input always executes a leaf of some tree, so the model refuses the impossible shape. Self specifiers fill the new fields from the input, and the corpus loader accepts the two keys, with the runner demanding them on its target input before installing computed conditions. SEND_MESSAGE and RECEIVE_MESSAGE become ASSURE and REQUIRE throughout: the opcode constants, the dataclasses, the compiler's condition vocabulary, and the runner's display names. The record fields follow the halves rename, assurer_commitment and requirer on ASSURE, assurer and requirer_commitment on REQUIRE, and the vector harness pins the renamed keys. The language-level name change breaks source compatibility for programs spelling the old names, the same deliberate break as prior reserved-word changes.
CONSOLIDATE_MODE repacks from 8 times 3 plus 2 to 32 times 3 plus 2 under the five-bit halves, the same assurer half 3 (own scriptPubKey and amount) and requirer half 2 (a scriptPubKey argument). SEND_MESSAGE and RECEIVE_MESSAGE become ASSURE and REQUIRE at the call sites. The compiled bytes change only at the mode constant, so the vault mod hash, every curried instance, and every derived scriptPubKey re-pin in the vector commit.
Mechanical re-encode, spec commits authorize every change here: - Every condition-carrying input in the validation corpus gains the now-required tapleaf and merkle_root fields. Vault instance inputs carry their curried root as both values (a single-leaf tree's root equals its leaf hash), the hostile foreign-script inputs and the family suites carry fixed filler, which no case reads through an execution-identity mode. - Every ASSURE and REQUIRE mode re-packs from three-bit to five-bit halves, identical semantics at the new encoding. - The vault files re-pin every VAULT-side value: the mode constant changed the compiled vault body, so the vault mod hash, both curried instances, their roots, scriptPubKeys, and every emitted condition list are regenerated from source. The triggered program, targets, and signatures are byte-identical to before, visible in the diff as unchanged hex. - The old mode-domain boundary cases move to the new boundaries: mode 64 becomes 1024 for the pair, announcement mode 8 becomes 32, each still pinning bad_condition_arg. - New conditions cases pin the execution-identity operands: parse at both new bits including mode 1023 and announcement mode 31, operand order (base fields, then tapleaf, then merkle root), and wrong-size rejection for both fields. - New validation cases pin the ledger semantics: tapleaf and merkle-root addressed pairs balance, a mismatched identity never balances, same-script inputs with different tapleaves do not satisfy each other (the grafted-leaf discrimination), and announcement asserts at an identity mode match and miss. - Parsed-expectation keys follow the rename: assurer_commitment, requirer, assurer, requirer_commitment.
… rules Every test fixture constructing a condition-carrying input gains the execution-identity pair the model now requires: fixed filler in the family invariant suites, per-input distinct values in the message invariants so composed self specifiers discriminate, and the honest instance roots in the vault suite. The message invariants' mode pool extends past the prevout values to tapleaf alone, merkle root alone, both, and both over prevout fields, so every rule 3 property now also quantifies over execution-identity commitments. New coverage: the model refuses a condition-carrying input without the pair and either field at the wrong size, the corpus loader maps those defects to context errors, and the runner refuses a target input missing the pair before computing conditions. The vault suite re-pins the vault mod hash after the mode re-encode and spells the hand-assembled consolidation lists at the ten-bit mode. Renamed fields and condition names follow the spec throughout.
The condition record gains decision 26 (the execution-identity amendment with the grafted-leaf and moved-root caveats and the IPK decline), decision 27 (the ASSURE and REQUIRE rename with the assurer and requirer halves), and divergence row C23. The glossary maps the renamed pair to CHIP-0025's names and adds the half and execution-identity terms. The comparison doc's message row states the new packing. The vault doc re-pins the vault mod hash, spells the consolidation paths at mode 98, and reads the ledger consequences in the new vocabulary. The vectors README documents the identity keys and renamed expectation fields. The execution plan flips the amendment bullet to landed.
… residue swept Ten verified findings from the pre-merge review round, applied: - The five-bit half width and mode bound now derive from the specifier table (SPECIFIER_COMMITMENT_MAX, _MESSAGE_MODE_MAX) instead of six scattered literals, and the dead high-half mask is gone. Boundary behavior and error text unchanged, pinned by the existing 1023/1024 and 31/32 vectors. - self_specifier raises on an unknown field kind instead of silently falling through to outpoint bytes, matching the sig digest builder one screen down. - The three 32-byte specifier operand checks merged into one branch with identical rendered errors. - bitlisp-run's help documents the execution-identity keys its target input now requires, so exit 2 matches the shape text. - Rename residue swept everywhere the old transport vocabulary survived: parse helper names, docstrings, the message and duplicate invariant suites' DSL, vault.bl comments and its require-conditions helper, and the corpus case names (send/recv to assure/require). The vault recompiles byte-identical, mod hash unchanged, so no vector hex moved. - TxInput's identity checks use direct attribute access like their neighbors, the corpus loader hoists its key sets above the input loop, and the seal and merge property helpers use dataclasses.replace so future TxInput fields carry through. - The vault tests' thirteen hand-expanded inputs collapse into a bl_input helper stating the single-leaf fact (leaf hash equals root) once. Flagged for Evan, deliberately not taken here: exporting a specifier radix constant to the language would break the pinned one-name-per-opcode compiler contract (vault.bl keeps its bare 32 with a comment), and rejecting identity fields on non-condition inputs would break the runner's pre-evaluation target, a spec-governed shape that stays permitted.
One transaction-view clarification, decided by Evan 2026-08-20 closing the review round's converse-guard flag: an input without a condition list, whether a non-BitLisp input or a BitLisp spend whose evaluation has not yet produced one, may carry the execution-identity pair or not, and no rule reads it from either. The state is physically real (every taproot script-path input has a leaf and a root) and load-bearing for the single-spend runner, whose target input holds identity before evaluation installs its conditions. The strict direction stays closed: a condition-carrying input must carry the pair.
Decision by Evan, 2026-08-20, closing the review round's radix flag by matching deployed Chialisp practice (ground rule 3): the one production message user in the vendored corpora, tibetswap's v2r_rebase.clsp, writes the packed mode as a bare literal with a comment naming the halves (18 ; puzzle-puzzle), no radix constant and no packing helper. CONSOLIDATE_MODE follows: the literal 98 with the halves named in the comment, replacing the derived arithmetic. defconstant evaluates at declaration, so the compiled bytes, the mod hash, and every vector are unchanged, pinned by test_mod_hashes_pinned. Upstream source informed this choice: references/tibet at the pinned clone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands the 2026-08-18 execution-identity amendment (decision by Evan, recorded in the execution plan) plus the 2026-08-20 rename of the addressed message pair.
What changed
Spec sections
CONDITIONS.md message family (specifier operand domains, mode ranges), VALIDATION.md transaction view and rule 3 (specifier table, ledger, stability classes, author guidance). Decisions 26 and 27 and divergence row C23 in docs/condition-record.md.
Read the commits in this order
spec: rename the addressed message pair to ASSURE and REQUIREspec: the specifier table gains execution identity, modes widen to five-bit halvesconditions: execution-identity specifiers, ten-bit modes, the pair renamedpuzzles: the vault re-encodes its consolidation mode, pair renamedvectors: the corpus re-pins under execution identity and the renametests: identity fields on every BitLisp fixture, coverage for the new rulesdocs: decisions 26 and 27, divergence C23, glossary and corpus shapeVerify independently
The vault closure tests (
test_vm_vectors_match_source,test_validation_vectors_match_source) recompile the puzzle sources and recompute every pinned program and conditions payload, so the regenerated vault vectors are checked against source both directions. In the vault vector diff, the triggered-program values and every signature are byte-identical to before, which is visible directly: only VAULT-side hex moves. The VM diff harness is untouched by this PR (no operator changes).Notes for review