Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/condition-comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ delegate to.
| own parent | `ASSERT_MY_PARENT_ID` 71 | `ASSERT_MY_TXID` `0x31`, normative, the txid half of the outpoint |
| own program | `ASSERT_MY_PUZZLEHASH` 72 | `ASSERT_MY_SCRIPTPUBKEY` `0x32`, normative, raw script bytes |
| own amount | `ASSERT_MY_AMOUNT` 73 | `ASSERT_MY_AMOUNT` `0x33`, normative |
| own taproot components | absent | `ASSERT_MY_TAPROOT` `0x37`, normative, the D-CC2 mirror |
| own taproot components | absent | removed (decision 29): `ASSERT_MY_TAPTREE` `0x38` subsumes the derivation assert, `0x37` now a visible gap |
| own taptree | absent | `ASSERT_MY_TAPTREE` `0x38`, normative, reads the control block's internal key and merkle root at the generic cost (decision 28) |
| own birth time or height | `ASSERT_MY_BIRTH_SECONDS` 74, `ASSERT_MY_BIRTH_HEIGHT` 75 | declined, a chain read outside the transaction view (C13) |
| ephemerality | `ASSERT_EPHEMERAL` 76, the coin was created in the same block it is spent | declined, structurally inexpressible within one transaction (C14) |
Expand Down
24 changes: 21 additions & 3 deletions docs/condition-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Section 4 registers the rules that have no external reference at all.
| C21 | per-spend base cost | 450,000 (SPEND_COST) charged for each coin spend under the hard fork 2 pricing flag, before any condition's own cost | no per-spend constant, conditions alone charge | A Bitcoin input's fixed overhead, prevout fetch and per-input iteration, is work base consensus performs and prices in weight for every input of every transaction, so a cost-unit constant would charge it twice. Declined with a falsifier pre-registered: the Phase 4 measurement pass isolates per-spend overhead Chia-style, n spends of k conditions against nk conditions in fewer spends, and a measured non-byte-proportional overhead introduces the constant then, a tightening that is cheap before publication. Ratified 2026-08-09, decision 25. | `conditions/costs.json` totals contain no per-list constant |
| C22 | signature-condition cost | 1,200,000 (AGG_SIG_COST) per occurrence in every regime, pricing one BLS pairing toward the bundle aggregate | 1,300,000 (CONDITION_SIG_ASSERT_COST), equal to the VM's SECP_VERIFY_COST, PROVISIONAL | Both layers of BitLisp price the same BIP340 verification, so the condition constant ties to the operator constant rather than to Chia's BLS figure: one Phase 4 measurement settles both, and a program can never buy the same verification cheaper in one layer than the other. Chia's magnitude corroborates the range, their pairing being work of the same order. Ratified 2026-08-09, decision 25. | `conditions/costs.json` signature cases |
| C23 | execution-identity addressing | none: puzzle hash is both the coin's script commitment and the executing program, one field carries both meanings | the specifier table composes the executing leaf's tapleaf hash (bit 3) and the spending path's merkle root (bit 4) onto the prevout rows, commitment values 0 to 31, the mode packed as assurer times 32 plus requirer, both fields validator-filled from the control block. The pair itself is renamed ASSURE and REQUIRE (decision 27) | Taproot splits Chia's one identity into two, and the C9 mapping carried only the script commitment, so program-to-program trust had no faithful addressing field. Internal-key addressing declined as attacker-satisfiable (no possession proof in BIP341). Grafted-leaf and moved-root caveats recorded in decision 26 and in rule 3's author guidance. Ratified 2026-08-18, decision 26, landed 2026-08-20. | `validation/messages.json` identity cases, `conditions/messages.json` composed-mode cases |
| C24 | the cheap identity assert | none: ASSERT_MY_PUZZLEHASH reads the one identity field, and no derive-versus-read split exists because a puzzle hash is a plain tree hash | ASSERT_MY_TAPTREE, a self assert over the control block's internal key and merkle root at the generic cost, the transaction view's identity widened to a triple. ASSERT_MY_TAPROOT, the derivation assert, stays beside it pending the puzzle rework | Taproot's identity is a tweak preimage the control block reveals and base consensus authenticates, so the assert reads it at 200 where the derivation assert re-derives it at a point multiplication, the largest single cost in both landed puzzles. Internal key read by self asserts only: decision 26's attacker-satisfiable objection concerns a counterpart's key, not the spending input's own. Ratified 2026-08-22, decision 28. | `validation/self-asserts.json` taptree cases, `conditions/self-asserts.json` and `conditions/costs.json` taptree cases |
| C24 | the cheap identity assert | none: ASSERT_MY_PUZZLEHASH reads the one identity field, and no derive-versus-read split exists because a puzzle hash is a plain tree hash | ASSERT_MY_TAPTREE, a self assert over the control block's internal key and merkle root at the generic cost, the transaction view's identity widened to a triple. ASSERT_MY_TAPROOT, the derivation assert it subsumes, removed once the puzzle rework landed (decision 29) | Taproot's identity is a tweak preimage the control block reveals and base consensus authenticates, so the assert reads it at 200 where the derivation assert re-derives it at a point multiplication, the largest single cost in both landed puzzles. Internal key read by self asserts only: decision 26's attacker-satisfiable objection concerns a counterpart's key, not the spending input's own. Ratified 2026-08-22, decision 28. | `validation/self-asserts.json` taptree cases, `conditions/self-asserts.json` and `conditions/costs.json` taptree cases |

## 2. Reference provenance

Expand Down Expand Up @@ -1591,6 +1591,24 @@ Section 4 registers the rules that have no external reference at all.
PR, once the measured saving is recorded (decision by Evan,
2026-08-22).

29. **ASSERT_MY_TAPROOT removed.** RATIFIED (decision by Evan,
2026-08-23, at the puzzle rework PR's review, the venue
decision 28 scheduled). The derivation assert at 0x37 leaves
the vocabulary. ASSERT_MY_TAPTREE subsumes it on every input
base consensus admits, the tweak-collision exemption aside,
and the puzzle rework removed its last caller, so the entry
would have carried review burden with no user. The two
capabilities removed with it are unreachable: the empty-root
form asserts a treeless output on a spend that by definition
executes a leaf, and exploiting the collision tolerance
requires a discrete log. 0x37 joins 0x34 to 0x36 as a visible
gap in the self assert block, invalid rather than reserved,
pinned by a gap vector. The taptree assert's oracle substitute
becomes the BIP341 tweak derivation directly, through the
derived-scriptPubKey agreement invariant over honest inputs,
with no intermediate assert. CREATE_OUTPUT_TAPROOT and the
derivation machinery are untouched.

## 4. Novel-layer register

The validation rules have no external reference: no deployed system
Expand All @@ -1600,10 +1618,10 @@ for an oracle, per ground rule 4:
| rule | status | oracle substitute |
| --- | --- | --- |
| 1. Injective multiset output matching | normative | hypothesis invariant suite (injectivity, reorder invariance, monotonicity, metamorphic mutations) plus the adversarial corpus in `vectors/validation/`, opening with the duplicate-CREATE_COIN theft vector |
| 2. Mixed-transaction rule | normative | `vectors/validation/mixed-transaction.json`: five acceptance vectors (mixed, plain-only, unclaimed slots, merge, surplus capture) and one rule 1 boundary rejection, plus the addition-monotonicity, merge, and plain-only invariants. The time assert family checks under this rule's assert clause: `vectors/validation/time-asserts.json` with BIP 65 and BIP 68 field semantics as the double reference, plus the operand-monotonicity and boundary-flip invariants. The self assert family checks under the same clause: `vectors/validation/self-asserts.json` with the probe corpus translated to prevout equality cases, the BIP341 tweak derivation shared with CREATE_OUTPUT_TAPROOT as the taproot assert's oracle, the taproot assert in turn as the taptree assert's oracle through the agreement invariant over honest inputs, plus the outpoint-implies-txid, recombination-invariance, and scriptPubKey-indifference invariants. The seal family checks under the same clause with no Chia reference at all (divergence C20): `vectors/validation/seals.json` with the grafted-output interception regression pair, the sealed-merge rejection case, and the fee-input-addition acceptance pinning what SEAL_OUTPUTS permits, the vendored Bitcoin Core framework as the serialization oracle for the txid and outputs-hash derivations, plus the operand byte-flip, sealed-merge, SEAL-implies-SEAL_OUTPUTS, and outputs-only-dependence invariants |
| 2. Mixed-transaction rule | normative | `vectors/validation/mixed-transaction.json`: five acceptance vectors (mixed, plain-only, unclaimed slots, merge, surplus capture) and one rule 1 boundary rejection, plus the addition-monotonicity, merge, and plain-only invariants. The time assert family checks under this rule's assert clause: `vectors/validation/time-asserts.json` with BIP 65 and BIP 68 field semantics as the double reference, plus the operand-monotonicity and boundary-flip invariants. The self assert family checks under the same clause: `vectors/validation/self-asserts.json` with the probe corpus translated to prevout equality cases, the BIP341 tweak derivation shared with CREATE_OUTPUT_TAPROOT as the taptree assert's oracle through the derived-scriptPubKey agreement invariant over honest inputs, plus the outpoint-implies-txid, recombination-invariance, and scriptPubKey-indifference invariants. The seal family checks under the same clause with no Chia reference at all (divergence C20): `vectors/validation/seals.json` with the grafted-output interception regression pair, the sealed-merge rejection case, and the fee-input-addition acceptance pinning what SEAL_OUTPUTS permits, the vendored Bitcoin Core framework as the serialization oracle for the txid and outputs-hash derivations, plus the operand byte-flip, sealed-merge, SEAL-implies-SEAL_OUTPUTS, and outputs-only-dependence invariants |
| 3. Message scoping | normative | `vectors/validation/messages.json` and `vectors/validation/announcements.json`: the probe corpus translated from the chia_rs oracle (balance, multiplicity, mode-key, self-send, order cases) plus adversarial wrong-address and forgery cases, and the balanced-pair, announcement-monotonicity, and byte-flip invariants |
| 4. Duplicates and multiplicity | normative | `vectors/validation/duplicates.json`: the strictest-wins oracle tests translated to identical and differing time asserts within one input, identical asserts across two and three inputs including the diverging final-sequence counterexample, ANNOUNCE duplication within an input and copies across inputs including the new-fact flip, duplicated announcement asserts at loose and script commitments, and duplicated reserved conditions on both sides of the cost floor, plus the identical-signature-triple and copied-triple-across-inputs cases from the signature assert unit, plus the in-place seal duplication and copied-seal-across-inputs cases from the seal unit, plus the in-place duplication-invariance invariant. The counted-sort boundaries stay pinned where they landed: duplicate claims in `vectors/validation/create-output.json`, duplicate message halves in `vectors/validation/messages.json`. Chia's remaining dedup tests are mempool spend-dedup machinery, declined in decision 19 |
| 5. Per-condition costing | normative | `vectors/conditions/costs.json`: every assigned opcode pinned individually at its cost line plus the all-opcodes sum with its boundary twin, exact-budget boundary pairs for every tier (the inclusive budget passing at equality, bursting one below), the charge-order cases (encoding defects win over cost_exceeded within a condition under a zero budget, an earlier condition's charge precedes a later condition's checks and the tail's shape check, width defects of both derivation entries win under a zero budget, derivation defects of both entries reported only when the charge is covered), reserved declared-cost accounting with the floor check winning over the budget, per-occurrence charging of identical conditions, the mixed-family total, and the COSTS.md worked example, plus the cost-conservation, reorder-invariance, append-additivity, per-occurrence, and inclusive-boundary invariants. No oracle: the deployed CHIP-0049 cost table anchors the magnitudes (section 2) and every constant, all PROVISIONAL, is re-priced by the Phase 4 measurement pass |
| 5. Per-condition costing | normative | `vectors/conditions/costs.json`: every assigned opcode pinned individually at its cost line plus the all-opcodes sum with its boundary twin, exact-budget boundary pairs for every tier (the inclusive budget passing at equality, bursting one below), the charge-order cases (encoding defects win over cost_exceeded within a condition under a zero budget, an earlier condition's charge precedes a later condition's checks and the tail's shape check, the derivation entry's width defect winning under a zero budget and its derivation defect reported only when the charge is covered), reserved declared-cost accounting with the floor check winning over the budget, per-occurrence charging of identical conditions, the mixed-family total, and the COSTS.md worked example, plus the cost-conservation, reorder-invariance, append-additivity, per-occurrence, and inclusive-boundary invariants. No oracle: the deployed CHIP-0049 cost table anchors the magnitudes (section 2) and every constant, all PROVISIONAL, is re-priced by the Phase 4 measurement pass |
| 6. Reserved conditions | normative | encoding vectors in `vectors/conditions/`, every error path pinned |
| 7. The fee reserve | normative | `vectors/validation/reserve-fee.json`: the probe corpus translated from the chia_rs oracle (within-spend and cross-input accumulation, boundary equality, one-short rejection, zero reserve, a reserve stack no fee can reach) plus the fee-theft grafted-output regression vector, the surplus-capture acceptance vector pinning what the reserve does not protect, the above-2^32 and off-boundary separating cases from the review's mutation pass, and the operand-monotonicity, split, and boundary invariants |
| 8. Signature asserts | normative | `vectors/validation/signature-asserts.json`: satisfied and failing triples for every variant with signatures produced by the vendored Bitcoin Core framework signer (the recorded `secp_verify` signing oracle), the fixed-message rewrite regression pair pinning the decision 23 footgun, variant-separation cases pinning txid against outpoint, raw against bound in both directions, and each single-field variant against the two-field variant extending it (exhaustive pair separation lives in the hypothesis invariant), raw-mode replay acceptance pinning what RAW does not protect, plus the own-data-only, operand byte-flip, and variant-separation invariants. The BIP340 official vectors bind the verification relation itself through the shared `secp_verify` implementation |
Expand Down
2 changes: 1 addition & 1 deletion docs/execution-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ descriptions, and commit messages*
**Done 2026-08-09:** 184 tests, 984 vector cases, lint and diff harness clean at a fresh seed. Owed forward: the fresh-reader predictability exercise transfers to Phase 5 hostile-review preparation.

- [x] **Amendment, execution-identity commitment (2026-08-18, decision by Evan, skeleton change under ground rule 6):** landed 2026-08-20. The rule 3 specifier table gains two execution-identity fields, the executing leaf's tapleaf hash and the spending path's merkle root, carried on the transaction view's BitLisp input. Commitment values widen to 5 bits, bit 3 composing the tapleaf and bit 4 the merkle root onto values 0 to 7, the mode repacking as assurer times 32 plus requirer, announcements sharing the table. Taproot splits Chia's puzzle-hash identity into the coin's script commitment and the executing program, and the C9 mapping carried only the first. Internal-key addressing is declined on soundness: the control block proves no possession of the internal key, so an IPK specifier is attacker-satisfiable. Landed with the same-PR rename of the addressed pair to ASSURE and REQUIRE, the halves following as assurer and requirer (decision by Evan, 2026-08-20). Decisions 26 and 27 plus the grafted-leaf and moved-root caveats recorded in `docs/condition-record.md`, divergence row C23, packed-mode constants re-encoded corpus-wide including the vault's, whose instances re-pinned.
- [x] **Amendment, the cheap identity assert (2026-08-22, decision by Evan, skeleton change under ground rule 6):** `ASSERT_MY_TAPTREE internal_key merkle_root`, a self assert at the generic condition cost reading the internal key and merkle root base consensus authenticated from the control block, the transaction view's execution identity gaining the internal key for self asserts only. It proves what ASSERT_MY_TAPROOT proves at 200 instead of 1,300,200, the largest single cost in every puzzle spend. The execution-identity amendment's objection to internal-key addressing (attacker-satisfiable) does not apply to an assert over the spending input's own key, to be stated in the condition record. Acceptance: the vault and the singleton reworked onto it, re-pinned, the saving measured in their docs. Sequenced first after PR 59. Spec, implementation, vectors, and decision 28 landed 2026-08-22 at opcode 0x38 (internal key operand width-checked only, the root never empty, the view's identity a triple), the rework and the fate of ASSERT_MY_TAPROOT following in their own PR (decision by Evan, 2026-08-22). Rework landed 2026-08-23: both puzzles and their corpus on 0x38, the saving measured at 1,300,000 per spend in the puzzle docs, the fate of 0x37 put to Evan at the rework PR's review.
- [x] **Amendment, the cheap identity assert (2026-08-22, decision by Evan, skeleton change under ground rule 6):** `ASSERT_MY_TAPTREE internal_key merkle_root`, a self assert at the generic condition cost reading the internal key and merkle root base consensus authenticated from the control block, the transaction view's execution identity gaining the internal key for self asserts only. It proves what ASSERT_MY_TAPROOT proves at 200 instead of 1,300,200, the largest single cost in every puzzle spend. The execution-identity amendment's objection to internal-key addressing (attacker-satisfiable) does not apply to an assert over the spending input's own key, to be stated in the condition record. Acceptance: the vault and the singleton reworked onto it, re-pinned, the saving measured in their docs. Sequenced first after PR 59. Spec, implementation, vectors, and decision 28 landed 2026-08-22 at opcode 0x38 (internal key operand width-checked only, the root never empty, the view's identity a triple), the rework and the fate of ASSERT_MY_TAPROOT following in their own PR (decision by Evan, 2026-08-22). Rework landed 2026-08-23: both puzzles and their corpus on 0x38, the saving measured at 1,300,000 per spend in the puzzle docs, the fate of 0x37 put to Evan at the rework PR's review and decided there: ASSERT_MY_TAPROOT removed in its own PR (decision by Evan, 2026-08-23, condition-record decision 29).

**Claude Code fit:** strong. Design decisions stay in Fable 5 sessions and land in spec prose first; Claude Code implements and generates vectors.

Expand Down
Loading