From 2ebfc3c249a355e9dcb3f8bfb390e9c914c5745e Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:32 -0700 Subject: [PATCH 01/12] Spec: condition-list encoding and the CREATE_COIN entry CONDITIONS.md section 1 makes the encoding normative: proper-list shape, one-byte opcodes, the three-tier code space (assigned, invalid, reserved 0x80 to 0xff), strict arity and minimal integer encodings for assigned conditions, and the family-block layout with intra-block gaps invalid. Every condition-layer error code is named at the rule that raises it, so the spec stays self-contained. Section 2 opens the vocabulary with CREATE_COIN (0x01): full script bytes plus amount, matched injectively under MATCHING.md rule 1. Chia's puzzle-hash argument and optional memo argument are both deliberately diverged from, rationale in the curation note and in the condition record landing later in this PR. Decisions ratified by Evan, 2026-07-29. --- spec/CONDITIONS.md | 104 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/spec/CONDITIONS.md b/spec/CONDITIONS.md index 774af53..0b769e6 100644 --- a/spec/CONDITIONS.md +++ b/spec/CONDITIONS.md @@ -1,7 +1,9 @@ # BitLisp Conditions -Status: stub. Vocabulary v0 lands in Phase 2. Curation rationale per -design obligation 4 accompanies every entry. +Status: in progress. Section 1 and the CREATE_COIN entry are +normative. The remaining vocabulary v0 entries land across Phase 2, +each with semantics, arguments, cost, matching rule reference, and a +curation note per design obligation 4. A successful puzzle evaluation yields a condition list. This document specifies the encoding of that list and the meaning of each condition. @@ -10,25 +12,91 @@ How conditions are matched against the transaction is specified in ## 1. Condition list encoding -TODO: list shape, opcode encoding, argument arity and range rules, -unknown-opcode policy. +A successful puzzle evaluation yields a value that must satisfy every +rule in this section. Any violation invalidates the spend with the +error code named in parentheses. Every condition-layer error code is +named in this document or in MATCHING.md at the rule that raises it. -## 2. Vocabulary v0 (planned) +The result must be a proper nil-terminated list (`bad_condition_list`). +Each element is one condition and must itself be a proper list with at +least one element (`bad_condition_list`). -Ported set: +The first element of a condition is its opcode. The opcode must be an +atom of exactly one byte (`bad_condition_opcode`). The opcode's value +selects one of three tiers: -- `CREATE_COIN` -- `AGG_SIG` family (secp, program-composed messages) -- `ASSERT_HEIGHT_ABSOLUTE`, `ASSERT_HEIGHT_RELATIVE` -- `ASSERT_SECONDS_ABSOLUTE`, `ASSERT_SECONDS_RELATIVE` -- `ASSERT_MY_*` family -- `SEND_MESSAGE`, `RECV_MESSAGE` (transaction-scoped) -- `RESERVE_FEE` +| value | tier | +| --- | --- | +| `0x00` | invalid | +| `0x01` to `0x7f`, listed in the vocabulary table (section 2) | assigned | +| `0x01` to `0x7f`, not listed in the vocabulary table | invalid | +| `0x80` to `0xff` | reserved | -Universal asserts: +An invalid opcode invalidates the spend (`bad_condition_opcode`). -- `ASSERT_OUTPUT_COUNT` -- `ASSERT_FEE_LE` +An assigned condition must have exactly the argument count its +vocabulary entry states (`bad_condition_arity`), and every argument +must satisfy its entry's type, encoding, and range rules +(`bad_condition_arg`). Arguments are atoms unless the entry states +otherwise. Integer arguments use the minimal integer encoding of +VM.md section 1 and are rejected if non-minimal (`bad_condition_arg`). -Each entry gets: semantics, arguments, cost, matching rule reference, -curation note (why it is in v0, what was declined and why). +A reserved condition is accepted without enforcing any semantics, +under the shape rules of MATCHING.md rule 6. + +The vocabulary is laid out in family blocks. Codes inside a family +block without a vocabulary entry are invalid, not reserved: + +| range | family | +| --- | --- | +| `0x01` to `0x0f` | output creation | +| `0x10` to `0x1f` | signatures | +| `0x20` to `0x2f` | time asserts | +| `0x30` to `0x3f` | self asserts | +| `0x40` to `0x4f` | messages | +| `0x50` to `0x5f` | fees and universal asserts | +| `0x60` to `0x7f` | unallocated, invalid | + +## 2. Vocabulary v0 + +| opcode | condition | +| --- | --- | +| `0x01` | `CREATE_COIN` | + +Planned entries, unassigned and invalid until their sections land: +`CREATE_COIN_TAPROOT`, the secp `AGG_SIG` family with program-composed +messages, `ASSERT_HEIGHT_ABSOLUTE`, `ASSERT_HEIGHT_RELATIVE`, +`ASSERT_SECONDS_ABSOLUTE`, `ASSERT_SECONDS_RELATIVE`, the `ASSERT_MY_*` +family, `SEND_MESSAGE` and `RECV_MESSAGE` (transaction-scoped), +`RESERVE_FEE`, `ASSERT_OUTPUT_COUNT`, and `ASSERT_FEE_LE`. + +### CREATE_COIN (`0x01`) + +`(0x01 scriptPubKey amount)` + +**Semantics.** Asserts that the containing transaction has one output +slot whose content is exactly (`scriptPubKey`, `amount`), and claims +that slot. Claims are matched injectively across the whole transaction +under MATCHING.md rule 1: k conditions carrying identical content +require k distinct output slots. Two identical CREATE_COIN conditions +from one input are two claims. + +**Arguments.** `scriptPubKey` is an atom of 1 to 10,000 bytes. The +empty atom is rejected (`bad_condition_arg`). `amount` is a minimally +encoded integer with 0 <= amount <= 2,100,000,000,000,000 (MAX_MONEY, +in satoshis). Exactly two arguments, both atoms. + +**Cost.** Assigned when MATCHING.md rule 5 lands. + +**Matching rule.** MATCHING.md rule 1. + +**Curation note.** Ported from Chia with two deliberate changes, +recorded as divergences C1 and C2 in the condition record +(`docs/condition-record.md`). First, the argument is full script bytes +rather than a puzzle hash, because a Bitcoin output may carry any +scriptPubKey and exits to non-BitLisp outputs are ordinary. Second, +Chia's optional memo argument is declined in v0: its wallet-discovery +job does not exist under output-script scanning, and consensus-carried +bytes with no consensus meaning are a deliberate non-affordance +(design obligation 4). A memo-bearing variant remains reachable +through the reserved tier if evidence of need emerges. From 1566a8157077fb25001230e6580ee37b8bf767c4 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:32 -0700 Subject: [PATCH 02/12] Spec: transaction view, matching rule 1, reserved conditions MATCHING.md gains its normative core. The transaction view fixes what matching can see, enumerates the base-rule subset the model enforces (including no duplicate outpoints), and states that no rule beyond base consensus applies, in particular no output scriptPubKey size bound. Rule 1 states injective multiset output matching as multiset containment, with the equality-only matching predicate as binding normative text, so any future relaxation must amend visible prose. Rule 6 fixes the reserved-condition tier: declared cost counting against the spend total under rule 5's accounting, a floor of 500, arguments after the cost unconstrained forever, and the non-consensus policy note discouraging unassigned use. The invariants section is rewritten while being made normative, and every change to the Phase 0 stub text is flagged here for review: 1. Direction correction: the stub said removing a condition never turns an invalid transaction valid, which is false under rule 1 (removing one of two over-claims restores validity). The true monotonicity is the reverse and is now stated in both halves: removing a condition never invalidates, adding one never validates. 2. Value conservation moves from a suite-enforced invariant to a model precondition, since matching never sees a transaction that violates it. 3. The output-removal bullet narrows to the exactly-covered form, because removing a slot whose content still has surplus slots leaves every claim satisfied under multiset semantics. The metamorphic bullet narrows identically. Decisions ratified by Evan, 2026-07-29. --- spec/MATCHING.md | 132 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 27 deletions(-) diff --git a/spec/MATCHING.md b/spec/MATCHING.md index 3421007..33c4f4f 100644 --- a/spec/MATCHING.md +++ b/spec/MATCHING.md @@ -1,9 +1,10 @@ # BitLisp Transaction Matching -Status: stub. This is the novel consensus layer with no external -reference. Rules are designed in architecture sessions, land here as -prose first, and only then get implemented. Ground rule 4: this layer -gets invariants and adversarial vectors before any feature work. +Status: in progress. The transaction view, rule 1, and rule 6 are +normative. Rules 2 to 5 are designed in architecture sessions, land +here as prose first, and only then get implemented. Ground rule 4: +this layer gets invariants and adversarial vectors before any feature +work. This document specifies how a validated spend's condition list is checked against the containing Bitcoin transaction. @@ -11,13 +12,66 @@ against the containing Bitcoin transaction. Target property: a reviewer who has read only this document can predict the outcome of every vector in `vectors/matching/`. +## Transaction view + +Matching is a pure function of the transaction below. No other data +influences any rule in this document. Contextual asserts (height, +time) compare against fields of this view and the validation context +in which the transaction is evaluated, in the manner of Bitcoin's +locktime rules, and are specified with their conditions. + +A transaction is: + +- `version`, a 32-bit integer +- `locktime`, a 32-bit unsigned integer +- `inputs`, an ordered list. Each input carries the outpoint it + consumes (a 32-byte txid and a 32-bit index), the consumed output's + `scriptPubKey` and `amount`, and a 32-bit `sequence`. A BitLisp + input additionally carries the condition list its evaluation + produced. +- `outputs`, an ordered list of slots. Each slot's content is the + pair (`scriptPubKey`, `amount`). Slots are addressed by index. + +Matching is defined only over transactions that satisfy Bitcoin's +base consensus rules. The reference transaction model enforces the +subset it represents: at least one input and one output, no outpoint +consumed by two inputs, every amount within 0 to MAX_MONEY, and the +sum of outputs not exceeding the sum of inputs. It enforces nothing +base consensus does not: in particular, an output slot's +scriptPubKey has no size bound, and a slot larger than any claimable +script is simply an unmatched slot. + ## Rules (in landing order) ### 1. Injective multiset output matching -TODO. k identical `CREATE_COIN` conditions must consume k distinct output -slots. No output satisfies two conditions. The duplicate-output theft -case is regression vector #1 in `vectors/matching/`. +An **output claim** is a pair (`scriptPubKey`, `amount`) demanded of +the transaction's outputs. Each vocabulary entry states whether it +produces a claim. CREATE_COIN produces exactly one claim, its own +argument pair. + +Let C be the multiset of all output claims produced by all BitLisp +inputs of the transaction, and let O be the multiset of all output +slot contents. The transaction is valid under this rule if and only +if C is contained in O as a multiset: for every distinct pair p, the +number of claims equal to p is at most the number of slots whose +content equals p. Violation is the error `unsatisfied_output_claim`. + +Equivalently: there must exist an assignment of claims to output +slots such that every claim maps to a slot with equal content and no +slot is assigned twice. Multiset containment and the existence of +such an injective assignment are the same condition here because a +claim matches a slot only by equality. + +A claim matches a slot only by byte-exact equality of `scriptPubKey` +and numeric equality of `amount`. No rule in this document may +introduce a claim that matches by range, prefix, or any predicate +other than equality. Relaxing this sentence is a change to the +validator's algorithmic class and requires a recorded design +decision. + +Slots not consumed by any claim are unconstrained by this rule. +Rule 2 states the coexistence consequences. ### 2. Mixed-transaction rule @@ -42,26 +96,50 @@ obligation 2). Tuning is data-driven in Phase 3. ### 6. Reserved conditions -TODO. Condition codes outside the assigned vocabulary. This rule is -the designated forward-compatibility mechanism for already-deployed -coins (the D3 ratification in -[docs/vm-record.md](../docs/vm-record.md)): a reserved code is -accepted unenforced at a fixed cost so a later soft fork can assign -it real semantics, the OP_NOP path. The rule must fix which code -ranges are reserved versus invalid, the cost old and new validators -agree on forever, the unconstrained argument shape, and the policy -stance toward reserved conditions before assignment. +Opcodes `0x80` to `0xff` are reserved. A reserved condition is +`(opcode cost arg...)`: the opcode, a declared cost, then zero or +more further arguments. A reserved condition with no arguments is +rejected (`bad_condition_arity`). + +The declared cost must be an atom carrying a minimally encoded +non-negative integer (`bad_condition_arg`) with +cost >= RESERVED_COST_FLOOR, where RESERVED_COST_FLOOR is 500 +(`reserved_cost_too_low`). The declared cost counts against the +spend's cost total under the accounting rule 5 defines, and vectors +pin the charge when that rule lands. Arguments after the cost are +unconstrained: any count, any shapes, including pairs. + +No semantics are enforced. A reserved condition constrains nothing +about the transaction. + +A future assignment of a reserved opcode must only tighten validity, +must keep charging exactly the declared cost, and must require the +declared cost to be at least the assigned operation's cost-table +entry. These constraints are what keep validators that predate the +assignment in consensus with validators that enforce it. + +**Policy note (not consensus).** Implementations should treat +transactions containing unassigned reserved conditions as +non-standard for relay and mining, in the manner of Bitcoin's +upgradable NOPs, so that future assignments do not confiscate +in-flight spends. ## Invariants -The `hypothesis` suite in `python/tests/` must enforce, over generated -transactions: - -- Value conservation on every accepted transaction. -- No output satisfies two conditions (matching injectivity). -- Validation is invariant under input reordering and condition-list - reordering. -- Removing a condition from a spend never turns an invalid transaction - valid. Removing an output never leaves a matched condition matched. -- Metamorphic: mutating any matched output (amount off by one, script - byte flip) causes rejection. +The `hypothesis` suite in `python/tests/` must enforce the following +over generated transactions. Each invariant names the rule that makes +it enforceable, and lands with that rule: + +- Value conservation on every accepted transaction (transaction view, + enforced as a model precondition). +- No output satisfies two conditions, k identical claims require k + distinct slots (rule 1). +- Validation is invariant under input reordering, output reordering, + and condition-list reordering (rule 1). +- Removing a condition from a valid transaction never turns it + invalid, and adding a condition to an invalid transaction never + turns it valid: constraints only tighten (rule 1). +- Removing a claimed output from a transaction whose claims exactly + cover that output's content turns it invalid (rule 1). +- Metamorphic: mutating the content of any exactly-claimed output + (amount off by one, script byte flip) causes rejection (rule 1). From c67c522638c93c857246958fcd1275e942277ae6 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:51 -0700 Subject: [PATCH 03/12] Docs: the condition and matching record docs/condition-record.md is the Phase 2 counterpart of the VM record: the divergence-from-Chia table (C1 script bytes, C2 memo decline, C3 duplicate claims allowed, C4 the three-tier code space against Chia's ignore-with-cost-table behavior, verified in chia_rs source), reference provenance (CHIP-0025, CHIP-0049, the bllsh reading of 2026-07-29), the design decision record for everything ratified in the 2026-07-29 design session, and the novel-layer register naming the oracle substitute for each matching rule. CLAUDE.md ground rule 3 now names both records. docs/README.md gains the pointer. --- CLAUDE.md | 4 +- docs/README.md | 4 ++ docs/condition-record.md | 137 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 docs/condition-record.md diff --git a/CLAUDE.md b/CLAUDE.md index 0f80712..1481331 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,7 +68,9 @@ In practice this means: a vector in `vectors/` the same day. 3. **Divergence is documented, never silent.** Anywhere BitLisp differs from CLVM, the divergence table in `docs/vm-record.md` says so and - why. + why. Anywhere the condition layer differs from Chia's deployed + condition semantics, the table in `docs/condition-record.md` says + so and why. 4. **The novel layer gets adversarial treatment first.** The matching rules (`spec/MATCHING.md`) have no external reference. They get property-based invariants and theft-bug regression vectors before any diff --git a/docs/README.md b/docs/README.md index 4f579d4..5124888 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,10 @@ - [vm-record.md](vm-record.md): the VM record behind spec/VM.md, the divergence table, the oracle provenance, and the design decision record. Cited by CLAUDE.md ground rule 3. +- [condition-record.md](condition-record.md): the Phase 2 counterpart + behind spec/CONDITIONS.md and spec/MATCHING.md, the + divergence-from-Chia table, reference provenance, decision record, + and the novel-layer register. Cited by CLAUDE.md ground rule 3. - [opcode-comparison.md](opcode-comparison.md): informative side-by-side of the CLVM, bllsh, and BitLisp operator sets. - Essay drafts land here in Phase 4. diff --git a/docs/condition-record.md b/docs/condition-record.md new file mode 100644 index 0000000..a18e03d --- /dev/null +++ b/docs/condition-record.md @@ -0,0 +1,137 @@ +# Condition and matching record + +The rationale, reference provenance, and decision record for the +condition layer (`spec/CONDITIONS.md`) and the matching layer +(`spec/MATCHING.md`). The specs state behavior only. This record says +why, and what the evidence was. It is the Phase 2 counterpart of the +VM record (`docs/vm-record.md`), with one structural difference: the +VM record's divergence rows are each diff-tested against a consensus +binary, while the rows here are established against Chia's deployed +condition semantics by translated consensus tests and source reading, +because the transaction models differ and no binary diff is possible. +Section 4 registers the rules that have no external reference at all. + +## 1. Divergence from Chia conditions + +| id | area | Chia (deployed) | BitLisp | rationale | vectors | +| --- | --- | --- | --- | --- | --- | +| C1 | CREATE_COIN target | 32-byte puzzle hash | full scriptPubKey bytes, 1 to 10,000 | A Bitcoin output carries any script, and exits to non-BitLisp outputs are ordinary. A hash would also block the validator from comparing against the transaction's actual outputs without a reveal. Ratified 2026-07-29. | `matching/create-coin.json` | +| C2 | CREATE_COIN memos | optional third argument, wallet-discovery hints | declined, strict arity two | The discovery job does not exist under output-script scanning. Consensus-carried bytes with no consensus meaning are a deliberate non-affordance (design obligation 4, inscription counterargument recorded there). A memo-bearing variant stays reachable through the reserved tier. Ratified 2026-07-29. | `conditions/encoding.json` arity cases | +| C3 | duplicate CREATE_COIN within one spend | rejected (child coin ids would collide) | valid, two claims requiring two distinct slots | Chia's rejection exists because its content-derived coin ids make identical children the same coin. Bitcoin output identity is positional, so identical slots are meaningful and routine (batch payouts). Counting under rule 1 handles them. Ratified 2026-07-29. | `matching/create-coin.json` duplicate cases | +| C4 | unknown condition opcodes | ignored and unenforced, zero cost for one-byte opcodes, a computed cost table for larger opcodes (verified in chia_rs `compute_unknown_condition_cost`, 2026-07-29) | three tiers: assigned, invalid, reserved 0x80 to 0xff with declared cost and a floor | Invalid-by-default matches the consensus mindset (reject the ambiguous case). The reserved tier is the deliberate forward-compatibility hatch, priced so old and new validators agree forever. Ratified 2026-07-29, four sub-decisions in section 3. | `conditions/encoding.json` tier cases | + +## 2. Reference provenance + +- **Chia condition semantics.** Established from the deployed + behavior of the pinned oracle wheels where portable, and from + translated Chia consensus tests for semantics that overlap + (the cross-check subset lands with the timelock family). No + binary diffing: the transaction models differ. +- **CHIP-0025 (message conditions)** and **CHIP-0049 (Chia 3.0 + cost revisions)** are the recorded costing precedents for + matching rule 5. CHIP-0049's per-condition base cost of 500 is + the provisional value of RESERVED_COST_FLOOR in rule 6, to be + revisited when rule 5 lands. Two decisions are pre-registered as + deliberate rather than inherited: whether a per-spend free tier + is acceptable, and which precedent prices tx-scoped + SEND_MESSAGE and RECV_MESSAGE (the CHIP-0049 precedent is split, + see `docs/execution-plan.md` Phase 2 notes). +- **bllsh** (AJ Towns' introspection Lisp) was cloned into + git-ignored `references/` on 2026-07-29 and read for the + CREATE_COIN_TAPROOT evaluation, under the reading guardrails + (no code copied, spec statements established by our own + evidence, influence disclosed). Findings recorded in the D-CC2 + entry below. `tools/fetch-references.sh` clones it alongside the + Chia repos. + +## 3. Design decision record + +1. **Condition-list encoding (decision zero).** RATIFIED (decisions + by Evan, 2026-07-29). Five parts: + - Chia-shaped lists: a proper list of conditions, each a proper + list with a one-byte opcode atom first. No Chia opcode-value + compatibility (the code space is laid out fresh, C4). + - Strict arity and minimal integer encodings for assigned + conditions, every deviation rejected. Strictness is the + loosenable direction post-deployment. + - Reserved tier with declared cost: the first argument is the + cost, charged as declared by validators before and after any + future assignment, which is what keeps them in consensus. The + cost argument itself is strict. Everything after it is + unconstrained forever, because the future assignment defines + the shape and old validators must not reject what it needs. + RESERVED_COST_FLOOR prevents free spam. + - Code-space layout: 0x00 invalid, family blocks 0x01 to 0x5f + with intra-block gaps invalid (typos near real opcodes fail + loudly), 0x60 to 0x7f unallocated invalid, 0x80 to 0xff + reserved. More than 128 future conditions means a new leaf + version, accepted deliberately. + - Policy stance: reserved conditions are consensus-valid and + policy-discouraged until assigned, the upgradable-NOP + precedent. The spec marks the policy note as non-consensus. +2. **CREATE_COIN shape.** RATIFIED (decisions by Evan, 2026-07-29). + Script bytes not hash (C1), memos declined (C2), duplicates + allowed as distinct claims (C3), empty script rejected as + burn-or-bug material, amount 0 to MAX_MONEY with zero-amount + outputs left to policy exactly as Bitcoin base rules leave them. +3. **CREATE_COIN_TAPROOT (D-CC2).** RATIFIED (decision by Evan, + 2026-07-29). Covenant recursion needs successor scriptPubKeys of + the form taproot(internal key, tree root), and the BIP341 tweak + is elliptic-curve arithmetic the VM deliberately lacks (the D2 + curation in `docs/vm-record.md`). Resolved as a condition: + `CREATE_COIN_TAPROOT(internal_key, merkle_root, amount)`, strict + arity three, the validator computes the tweak natively and the + condition then matches as an ordinary rule 1 claim. Two + alternatives declined: + - `secp256k1_muladd` (bllsh's general linear-combination + assert). Reading bllsh's examples on 2026-07-29 found three + usage patterns: re-implementing BIP340 (covered by + `secp_verify` and the AGG_SIG family), verifying the current + input's own taproot construction (impossible as a VM operator + in a pure VM, flagged as ASSERT_MY_TAPROOT for the ASSERT_MY_* + design), and covenant recursion (test-flexmarks), which is + exactly the computation the condition form performs. The + honest residual: muladd also enables adaptor-signature-class + and Pedersen-class equation verification. That capability is + named here, not silently dropped, and the reserved tier is its + priced future path. + - A narrow `taptweak` VM operator. Strictly weaker than the + condition form in this architecture: a pure VM has no + transaction access, so the operator could only check + solution-supplied claims, while costing a VM operator slot, a + no-oracle divergence row, an extra witness element (the + claimed key plus a parity bit that compute-mode never needs), + and the first exception to "the VM's only curve door is + signature verification." + The condition enters the v0 vocabulary in its own PR immediately + after the opening one. Its commit discloses the bllsh reading. +4. **Rule 1 equality-only matching.** RATIFIED (decision by Evan, + 2026-07-29, as part of the rule 1 draft). Claims match slots by + exact content equality only, which collapses injective matching + to multiset containment (counting) and keeps graph algorithms + out of consensus. The spec makes the restriction normative text + so relaxing it requires amending visible prose plus a recorded + decision here. +5. **Invariant direction correction.** The Phase 0 stub stated that + removing a condition never turns an invalid transaction valid. + Under rule 1 that is false (removing one of two over-claims + restores validity) and the true property is the reverse + monotonicity: constraints only tighten, so removing a condition + never invalidates a valid transaction. Corrected in the spec + commit that made the invariants normative, 2026-07-29, flagged + in that PR for review. + +## 4. Novel-layer register + +The matching rules have no external reference: no deployed system +checks a condition list against a Bitcoin transaction. What stands in +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/matching/`, opening with the duplicate-CREATE_COIN theft vector | +| 2. Mixed-transaction rule | pending | same treatment on landing | +| 3. Message scoping | pending | same treatment on landing | +| 4. Dedup and multiplicity | pending | same treatment, plus translated Chia dedup tests where semantics overlap | +| 5. Per-condition costing | pending | CHIP-0049 precedent comparison plus cost-conservation properties | +| 6. Reserved conditions | normative | encoding vectors in `vectors/conditions/`, every error path pinned | From d0b4c7390d725748af5c8acf2cc02faaab9642d9 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:51 -0700 Subject: [PATCH 04/12] Tools: fetch bllsh alongside the Chia references bllsh was read on 2026-07-29 for the CREATE_COIN_TAPROOT decision (the D-CC2 entry in docs/condition-record.md). The fetch script now clones it so the checkout is reproducible. --- tools/fetch-references.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/fetch-references.sh b/tools/fetch-references.sh index 7093f5a..e2a94b7 100755 --- a/tools/fetch-references.sh +++ b/tools/fetch-references.sh @@ -20,6 +20,7 @@ clone() { clone https://github.com/Chia-Network/clvm.git clvm clone https://github.com/Chia-Network/clvm_rs.git clvm_rs clone https://github.com/Chia-Network/chia_rs.git chia_rs +clone https://github.com/ajtowns/bllsh.git bllsh echo echo "Done. These checkouts are git-ignored and are not a build input." From b63b9f7c5641541996bf904aec5e17704767ca10 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:51 -0700 Subject: [PATCH 05/12] Conditions: parse and validate condition lists Implements CONDITIONS.md section 1 and the CREATE_COIN entry, and the shape rules of MATCHING.md rule 6: proper-list structure, one-byte opcodes in three tiers, strict arity and minimal integer encodings for CREATE_COIN, and the reserved tier with its declared cost and floor. Six new error codes, one per distinct rejection reason, so every error path can be pinned by its own vector. The errors module docstring now states the split evidence standard: oracle parity for VM codes, the named spec rule for condition and matching codes. --- python/bitlisp/conditions.py | 128 +++++++++++++++++++++++++++++++++++ python/bitlisp/errors.py | 11 ++- 2 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 python/bitlisp/conditions.py diff --git a/python/bitlisp/conditions.py b/python/bitlisp/conditions.py new file mode 100644 index 0000000..ff22843 --- /dev/null +++ b/python/bitlisp/conditions.py @@ -0,0 +1,128 @@ +"""Condition-list parsing and validation. + +A successful puzzle evaluation yields a condition list: a proper list +of conditions, each a proper list opening with a one-byte opcode atom. +Opcode values fall in three tiers. Assigned values carry the +vocabulary's semantics under strict arity and minimal integer +encodings. Values 0x80 and above are reserved: accepted with a +declared cost and no enforced semantics, the forward-compatibility +hatch a later soft fork can tighten into real conditions. Everything +else is invalid, so a typo near a real opcode fails loudly instead of +becoming an accidental no-op. +""" + +from dataclasses import dataclass + +from .errors import BitLispError +from .sexp import NIL, atom_to_int, int_to_atom, is_atom, is_pair + +MAX_MONEY = 2_100_000_000_000_000 +MAX_SCRIPT_PUBKEY_SIZE = 10_000 +RESERVED_COST_FLOOR = 500 + +CREATE_COIN = 0x01 +_RESERVED_START = 0x80 + + +@dataclass(frozen=True) +class CreateCoin: + """Claims one output slot with exactly this content.""" + + script_pubkey: bytes + amount: int + + opcode = CREATE_COIN + + +@dataclass(frozen=True) +class Reserved: + """No enforced semantics, only the declared cost. args holds the + raw argument nodes after the cost, unconstrained by design.""" + + opcode: int + cost: int + args: tuple + + +def _iter_conditions(node, what): + """Yields the elements of a proper list, else bad_condition_list.""" + while node != NIL: + if not is_pair(node): + raise BitLispError("bad_condition_list", f"{what} is an improper list") + yield node[0] + node = node[1] + + +def _parse_int(atom, what): + if not is_atom(atom): + raise BitLispError("bad_condition_arg", f"{what} must be an atom") + value = atom_to_int(atom) + if int_to_atom(value) != atom: + raise BitLispError("bad_condition_arg", f"{what} not minimally encoded") + return value + + +def _parse_create_coin(args): + if len(args) != 2: + raise BitLispError( + "bad_condition_arity", f"CREATE_COIN takes 2 arguments, got {len(args)}" + ) + script_pubkey, amount_atom = args + if not is_atom(script_pubkey): + raise BitLispError("bad_condition_arg", "scriptPubKey must be an atom") + if not 1 <= len(script_pubkey) <= MAX_SCRIPT_PUBKEY_SIZE: + raise BitLispError( + "bad_condition_arg", + f"scriptPubKey must be 1 to {MAX_SCRIPT_PUBKEY_SIZE} bytes, " + f"got {len(script_pubkey)}", + ) + amount = _parse_int(amount_atom, "CREATE_COIN amount") + if not 0 <= amount <= MAX_MONEY: + raise BitLispError("bad_condition_arg", f"amount out of range: {amount}") + return CreateCoin(script_pubkey, amount) + + +def _parse_reserved(opcode, args): + if not args: + raise BitLispError( + "bad_condition_arity", "reserved condition missing its declared cost" + ) + cost = _parse_int(args[0], "declared cost") + if cost < 0: + raise BitLispError("bad_condition_arg", f"declared cost negative: {cost}") + if cost < RESERVED_COST_FLOOR: + raise BitLispError( + "reserved_cost_too_low", + f"declared cost {cost} below floor {RESERVED_COST_FLOOR}", + ) + return Reserved(opcode, cost, tuple(args[1:])) + + +def _parse_condition(node): + if not is_pair(node): + raise BitLispError("bad_condition_list", "condition is not a list") + items = list(_iter_conditions(node, "condition")) + opcode_atom = items[0] + if not is_atom(opcode_atom) or len(opcode_atom) != 1: + raise BitLispError( + "bad_condition_opcode", "opcode must be an atom of exactly one byte" + ) + opcode = opcode_atom[0] + args = items[1:] + if opcode >= _RESERVED_START: + return _parse_reserved(opcode, args) + if opcode == CREATE_COIN: + return _parse_create_coin(args) + raise BitLispError("bad_condition_opcode", f"invalid opcode {opcode:#04x}") + + +def parse_conditions(node): + """Parses an evaluation result into a tuple of conditions. + + Raises BitLispError on any encoding violation. Order is the + emitted order. + """ + return tuple( + _parse_condition(element) + for element in _iter_conditions(node, "condition list") + ) diff --git a/python/bitlisp/errors.py b/python/bitlisp/errors.py index 0df9ee7..99b459c 100644 --- a/python/bitlisp/errors.py +++ b/python/bitlisp/errors.py @@ -1,8 +1,9 @@ """Error taxonomy. Errors are consensus-relevant only as "the spend is invalid". The -classes exist so vectors and the diff harness can assert that BitLisp -fails for the same reason as the oracles. +classes exist so vectors can pin the reason a spend fails: oracle +parity for the VM codes, the named rejection rule for the condition +and matching codes, which have no oracle. """ CODES = frozenset( @@ -24,6 +25,12 @@ "secp_verify_failed", "user_raise", "cost_exceeded", + "bad_condition_list", + "bad_condition_opcode", + "bad_condition_arity", + "bad_condition_arg", + "reserved_cost_too_low", + "unsatisfied_output_claim", } ) From 6a85ffe4604f19d9961ce610de8cdf79221ff6fb Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:53:51 -0700 Subject: [PATCH 06/12] Matching: transaction view and rule 1 The transaction model carries exactly what MATCHING.md's transaction view names and enforces the base-rule subset it represents (value conservation, ranges, no duplicate outpoints) at construction, so matching never sees a transaction Bitcoin base consensus would reject. It deliberately enforces nothing base consensus does not: output scriptPubKeys carry no size bound, since the 10,000-byte rule is CREATE_COIN's claim-argument rule, not a slot rule. Model misuse is ValueError, never a spend failure. Rule 1 is multiset containment by counting: claims from all BitLisp inputs jointly, slots from the outputs, reject when any content is claimed more times than slots carry it. The equality-only matching predicate that makes counting sufficient is normative in the spec. The package exports for the whole condition layer land here, with the modules they name, so every commit imports standalone. --- python/bitlisp/__init__.py | 16 +++++- python/bitlisp/matching.py | 45 +++++++++++++++ python/bitlisp/tx.py | 112 +++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 python/bitlisp/matching.py create mode 100644 python/bitlisp/tx.py diff --git a/python/bitlisp/__init__.py b/python/bitlisp/__init__.py index 387cc89..bf5b1fb 100644 --- a/python/bitlisp/__init__.py +++ b/python/bitlisp/__init__.py @@ -1,28 +1,40 @@ """BitLisp reference implementation. This package is the executable specification: small, boring, and -readable whole. Behavior is pinned by the vector corpus and by -differential testing against the consensus oracle. +readable whole. Behavior is pinned by the vector corpus, by +differential testing against the consensus oracle where one exists, +and by property-based invariants where none does. """ +from .conditions import MAX_MONEY, CreateCoin, Reserved, parse_conditions from .errors import CODES, BitLispError from .machine import run, run_serialized +from .matching import validate_transaction from .serialize import deserialize, serialize from .sexp import NIL, TRUE, atom_to_int, int_to_atom, is_atom, is_pair +from .tx import Transaction, TxInput, TxOutput __version__ = "0.0.1" __all__ = [ "BitLispError", "CODES", + "CreateCoin", + "MAX_MONEY", "NIL", + "Reserved", "TRUE", + "Transaction", + "TxInput", + "TxOutput", "atom_to_int", "deserialize", "int_to_atom", "is_atom", "is_pair", + "parse_conditions", "run", "run_serialized", "serialize", + "validate_transaction", ] diff --git a/python/bitlisp/matching.py b/python/bitlisp/matching.py new file mode 100644 index 0000000..086f739 --- /dev/null +++ b/python/bitlisp/matching.py @@ -0,0 +1,45 @@ +"""Transaction matching, rule by rule. + +Rule 1, injective multiset output matching: every output claim maps +to a distinct output slot with byte-exact content. Because a claim +matches a slot only by exact equality, the injective-assignment +question collapses to multiset containment and the check is counting. +That equality-only restriction is what keeps this a counting problem +rather than bipartite matching. Relaxing it is a recorded design +decision, never an implementation choice. +""" + +from collections import Counter + +from .conditions import CreateCoin +from .errors import BitLispError + + +def output_claims(conditions): + """The (scriptPubKey, amount) claims a condition list produces.""" + return [ + (c.script_pubkey, c.amount) for c in conditions if isinstance(c, CreateCoin) + ] + + +def check_output_claims(tx): + """Rule 1. Raises unsatisfied_output_claim unless every claim in + the transaction can consume its own distinct output slot.""" + claims = Counter() + for tx_input in tx.inputs: + if tx_input.conditions is not None: + claims.update(output_claims(tx_input.conditions)) + slots = Counter(output.content for output in tx.outputs) + for content, count in claims.items(): + script_pubkey, amount = content + if count > slots[content]: + raise BitLispError( + "unsatisfied_output_claim", + f"{count} claim(s) on ({script_pubkey.hex()}, {amount}) but " + f"{slots[content]} matching output slot(s)", + ) + + +def validate_transaction(tx): + """Every matching rule that has landed so far.""" + check_output_claims(tx) diff --git a/python/bitlisp/tx.py b/python/bitlisp/tx.py new file mode 100644 index 0000000..4d626e5 --- /dev/null +++ b/python/bitlisp/tx.py @@ -0,0 +1,112 @@ +"""Minimal Bitcoin transaction view for matching. + +Just enough structure to validate condition lists against: inputs +carrying their consumed output's content, outputs as (scriptPubKey, +amount) slots addressed by index. Construction enforces the base-rule +subset the model represents, so matching only ever sees transactions +that conserve value. Violations here raise ValueError: a malformed +model is a harness bug, never a spend failure. +""" + +from dataclasses import dataclass + +from .conditions import MAX_MONEY + +_UINT32_MAX = 0xFFFFFFFF +_INT32_MIN, _INT32_MAX = -(2**31), 2**31 - 1 + + +def _check_amount(amount, what): + if not isinstance(amount, int) or not 0 <= amount <= MAX_MONEY: + raise ValueError(f"{what} amount out of range: {amount!r}") + + +def _check_script(script, what): + # No size bound on purpose: Bitcoin base consensus places none on + # a created output's scriptPubKey, and the model must represent + # every transaction base consensus accepts. The 10,000-byte bound + # is conditions.MAX_SCRIPT_PUBKEY_SIZE, a claim-argument rule, not + # a slot rule. + if not isinstance(script, bytes): + raise ValueError(f"{what} scriptPubKey must be bytes") + + +@dataclass(frozen=True) +class TxInput: + """One input: the outpoint it consumes, that output's content, and + the sequence. conditions is None for a non-BitLisp input, else the + parsed condition list its puzzle evaluation produced.""" + + txid: bytes + index: int + script_pubkey: bytes + amount: int + sequence: int + conditions: tuple | None = None + + def __post_init__(self): + if not isinstance(self.txid, bytes) or len(self.txid) != 32: + raise ValueError("txid must be 32 bytes") + if not isinstance(self.index, int) or not 0 <= self.index <= _UINT32_MAX: + raise ValueError(f"input index out of range: {self.index!r}") + if not isinstance(self.sequence, int) or not 0 <= self.sequence <= _UINT32_MAX: + raise ValueError(f"sequence out of range: {self.sequence!r}") + _check_script(self.script_pubkey, "input") + _check_amount(self.amount, "input") + if self.conditions is not None and not isinstance(self.conditions, tuple): + raise ValueError("conditions must be a tuple or None") + + @property + def outpoint(self): + return (self.txid, self.index) + + +@dataclass(frozen=True) +class TxOutput: + """One output slot. Content is the (scriptPubKey, amount) pair.""" + + script_pubkey: bytes + amount: int + + def __post_init__(self): + _check_script(self.script_pubkey, "output") + _check_amount(self.amount, "output") + + @property + def content(self): + return (self.script_pubkey, self.amount) + + +@dataclass(frozen=True) +class Transaction: + version: int + locktime: int + inputs: tuple + outputs: tuple + + def __post_init__(self): + if not isinstance(self.version, int) or not ( + _INT32_MIN <= self.version <= _INT32_MAX + ): + raise ValueError(f"version out of range: {self.version!r}") + if not isinstance(self.locktime, int) or not ( + 0 <= self.locktime <= _UINT32_MAX + ): + raise ValueError(f"locktime out of range: {self.locktime!r}") + if not isinstance(self.inputs, tuple) or not self.inputs: + raise ValueError("inputs must be a non-empty tuple") + if not isinstance(self.outputs, tuple) or not self.outputs: + raise ValueError("outputs must be a non-empty tuple") + if not all(isinstance(i, TxInput) for i in self.inputs): + raise ValueError("inputs must all be TxInput") + if not all(isinstance(o, TxOutput) for o in self.outputs): + raise ValueError("outputs must all be TxOutput") + outpoints = [i.outpoint for i in self.inputs] + if len(set(outpoints)) != len(outpoints): + raise ValueError("duplicate input outpoint") + in_total = sum(i.amount for i in self.inputs) + out_total = sum(o.amount for o in self.outputs) + if out_total > in_total: + raise ValueError( + f"outputs {out_total} exceed inputs {in_total}, value not conserved" + ) From d7eec2beda394043afaef3874caa7ab576a895b3 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:54:08 -0700 Subject: [PATCH 07/12] Tools: conditions and matching suite runners Both runners keep the vm suite's discipline: closed case keys on every object including output entries, closed expect shapes, unknown error codes rejected, duplicate case names rejected. The per-suite loop is factored into one helper and the vm suite now uses it too. The conditions runner parses a serialized condition-list node and pins either the parsed form or the error code. The matching runner builds the transaction model from JSON. A condition-list parse failure is a case outcome (an invalid spend), but a conditions field that does not deserialize is a malformed vector, because the matching stage receives already-materialized evaluation results and a serialization failure is not a possible outcome there. A model ValueError is likewise a malformed vector, since the model only represents transactions Bitcoin base rules accept. --- tools/run_vectors.py | 219 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 202 insertions(+), 17 deletions(-) diff --git a/tools/run_vectors.py b/tools/run_vectors.py index 387d480..9bb33cf 100755 --- a/tools/run_vectors.py +++ b/tools/run_vectors.py @@ -121,25 +121,210 @@ def run_vm_case(case): raise VectorError(f"expected {expect}, got {outcome}") -def run_vm(envelope, path): - names = set() - for index, case in enumerate(envelope["cases"]): - name = case.get("name", f"case {index}") - if name in names: - raise VectorError(f"{path}: duplicate case name {name!r}") - names.add(name) - try: - run_vm_case(case) - except VectorError as exc: - raise VectorError(f"{path}: {name}: {exc}") from None - except (KeyError, ValueError) as exc: - raise VectorError(f"{path}: {name}: malformed case: {exc!r}") from None +def _condition_json(cond): + """The pinned JSON form of one parsed condition.""" + from bitlisp import serialize + from bitlisp.conditions import CreateCoin + + if isinstance(cond, CreateCoin): + return { + "opcode": cond.opcode, + "script_pubkey": cond.script_pubkey.hex(), + "amount": cond.amount, + } + return { + "opcode": cond.opcode, + "cost": cond.cost, + "args": [serialize(arg).hex() for arg in cond.args], + } + + +def run_conditions_case(case): + """One conditions case: parse a serialized condition-list node. + + Case shape, closed like the envelope: + { + "name": "", + "conditions": "", + "expect": {"parsed": []} + or {"error": ""} + } + + Condition JSON is {"opcode", "script_pubkey", "amount"} for + CREATE_COIN and {"opcode", "cost", "args": []} for + reserved conditions. + """ + from bitlisp import BitLispError, deserialize, parse_conditions + from bitlisp.errors import CODES + + required = {"name", "conditions", "expect"} + keys = set(case) + if missing := required - keys: + raise VectorError(f"missing keys {sorted(missing)}") + if extra := keys - required: + raise VectorError(f"unknown keys {sorted(extra)}") + expect = case["expect"] + if not isinstance(expect, dict) or set(expect) not in ({"parsed"}, {"error"}): + raise VectorError("expect must be exactly {parsed} or {error}") + if "error" in expect and expect["error"] not in CODES: + raise VectorError(f"unknown expected error code {expect['error']!r}") + try: + node = deserialize(bytes.fromhex(case["conditions"])) + except BitLispError as exc: + raise VectorError(f"conditions field does not deserialize: {exc}") from None + try: + parsed = parse_conditions(node) + outcome = {"parsed": [_condition_json(c) for c in parsed]} + except BitLispError as exc: + outcome = {"error": exc.code} + if outcome != expect: + raise VectorError(f"expected {expect}, got {outcome}") + + +def _tx_from_json(obj): + """Builds the transaction model from a matching case's tx object. + + Parses each input's optional serialized condition list. A + BitLispError from condition parsing is a case outcome (the spend + is invalid), so it propagates to the caller. Everything else + wrong with the tx object is a malformed vector: unknown or + missing keys, a conditions field that does not deserialize (the + matching stage receives already-materialized evaluation results, + so a serialization failure is not a possible outcome here), and + ValueError from any model constructor.""" + from bitlisp import ( + BitLispError, + Transaction, + TxInput, + TxOutput, + deserialize, + parse_conditions, + ) + + required = {"version", "locktime", "inputs", "outputs"} + keys = set(obj) + if missing := required - keys: + raise VectorError(f"tx missing keys {sorted(missing)}") + if extra := keys - required: + raise VectorError(f"tx unknown keys {sorted(extra)}") + decoded_inputs = [] + for entry in obj["inputs"]: + entry_required = {"txid", "index", "script_pubkey", "amount"} + entry_keys = set(entry) + if missing := entry_required - entry_keys: + raise VectorError(f"input missing keys {sorted(missing)}") + if extra := entry_keys - entry_required - {"sequence", "conditions"}: + raise VectorError(f"input unknown keys {sorted(extra)}") + conditions = None + if "conditions" in entry: + try: + node = deserialize(bytes.fromhex(entry["conditions"])) + except BitLispError as exc: + raise VectorError( + f"conditions field does not deserialize: {exc}" + ) from None + conditions = parse_conditions(node) + decoded_inputs.append((entry, conditions)) + for entry in obj["outputs"]: + entry_keys = set(entry) + if missing := {"script_pubkey", "amount"} - entry_keys: + raise VectorError(f"output missing keys {sorted(missing)}") + if extra := entry_keys - {"script_pubkey", "amount"}: + raise VectorError(f"output unknown keys {sorted(extra)}") + try: + return Transaction( + version=obj["version"], + locktime=obj["locktime"], + inputs=tuple( + TxInput( + txid=bytes.fromhex(entry["txid"]), + index=entry["index"], + script_pubkey=bytes.fromhex(entry["script_pubkey"]), + amount=entry["amount"], + sequence=entry.get("sequence", 0xFFFFFFFF), + conditions=conditions, + ) + for entry, conditions in decoded_inputs + ), + outputs=tuple( + TxOutput(bytes.fromhex(o["script_pubkey"]), o["amount"]) + for o in obj["outputs"] + ), + ) + except ValueError as exc: + raise VectorError(f"tx violates the model's base rules: {exc}") from None + + +def run_matching_case(case): + """One matching case: validate a transaction's condition lists. + + Case shape, closed like the envelope: + { + "name": "", + "tx": { + "version": , "locktime": , + "inputs": [{"txid": "", "index": , + "script_pubkey": "", "amount": , + "sequence": , + "conditions": ""}], + "outputs": [{"script_pubkey": "", "amount": }] + }, + "expect": {"valid": true} or {"error": ""} + } + + An input without a conditions key is a non-BitLisp input. An + input with one is a BitLisp input whose puzzle evaluation + produced that condition list. + """ + from bitlisp import BitLispError, validate_transaction + from bitlisp.errors import CODES + + required = {"name", "tx", "expect"} + keys = set(case) + if missing := required - keys: + raise VectorError(f"missing keys {sorted(missing)}") + if extra := keys - required: + raise VectorError(f"unknown keys {sorted(extra)}") + expect = case["expect"] + if not isinstance(expect, dict) or set(expect) not in ({"valid"}, {"error"}): + raise VectorError("expect must be exactly {valid} or {error}") + if "valid" in expect and expect["valid"] is not True: + raise VectorError("expect.valid must be true, invalidity pins an error code") + if "error" in expect and expect["error"] not in CODES: + raise VectorError(f"unknown expected error code {expect['error']!r}") + try: + tx = _tx_from_json(case["tx"]) + validate_transaction(tx) + outcome = {"valid": True} + except BitLispError as exc: + outcome = {"error": exc.code} + if outcome != expect: + raise VectorError(f"expected {expect}, got {outcome}") + + +def _make_suite_runner(case_runner): + def run_suite(envelope, path): + names = set() + for index, case in enumerate(envelope["cases"]): + name = case.get("name", f"case {index}") + if name in names: + raise VectorError(f"{path}: duplicate case name {name!r}") + names.add(name) + try: + case_runner(case) + except VectorError as exc: + raise VectorError(f"{path}: {name}: {exc}") from None + except (KeyError, ValueError) as exc: + raise VectorError(f"{path}: {name}: malformed case: {exc!r}") from None + + return run_suite -# Suite runners land with their implementations: conditions and -# matching in Phase 2. Each takes (envelope, path) and raises -# VectorError on the first failing case. -RUNNERS = {"vm": run_vm} +RUNNERS = { + "vm": _make_suite_runner(run_vm_case), + "conditions": _make_suite_runner(run_conditions_case), + "matching": _make_suite_runner(run_matching_case), +} def run_file(path): From 6c53e087881f71daa763b742709ee0404c443ea0 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:54:08 -0700 Subject: [PATCH 08/12] Vectors: condition encoding corpus and the rule 1 corpus vectors/conditions/encoding.json pins CONDITIONS.md section 1 and MATCHING.md rule 6: 35 cases covering every rejection rule (structure, opcode tiers, CREATE_COIN arity and argument strictness, reserved declared-cost rules) plus the acceptance boundaries (zero amount, MAX_MONEY, the 10,000-byte script, the cost floor, shapeless reserved arguments). vectors/matching/create-coin.json pins MATCHING.md rule 1 with the duplicate-CREATE_COIN theft case as vector #1, the honest batching counterpart, batching-wallet shapes at three inputs, mixed transactions with non-BitLisp inputs and unmatched outputs, the C3 divergence cases (duplicate claims from one input), metamorphic neighbors (amount off by one, script byte flip), and the oversized-unclaimed-slot case pinning that output slots carry no size bound. vectors/README.md documents both case shapes. --- vectors/README.md | 52 ++- vectors/conditions/encoding.json | 314 ++++++++++++++++ vectors/matching/create-coin.json | 580 ++++++++++++++++++++++++++++++ 3 files changed, 945 insertions(+), 1 deletion(-) create mode 100644 vectors/conditions/encoding.json create mode 100644 vectors/matching/create-coin.json diff --git a/vectors/README.md b/vectors/README.md index 32c9c48..067fc23 100644 --- a/vectors/README.md +++ b/vectors/README.md @@ -29,7 +29,7 @@ Every file outside `upstream/` is one JSON object in the ``` The `spec` field cites the spec section the cases pin. Case shapes are -suite-specific (`conditions` and `matching` land in Phase 2). +suite-specific. ## vm case shape @@ -57,5 +57,55 @@ cases were cross-checked against the same wheel with its sha256tree release flag enabled) pin BitLisp behavior that intentionally differs, each cites its divergence row. +## conditions case shape + +```json +{ + "name": "unique within the file", + "conditions": "", + "expect": {"parsed": []} +} +``` + +`expect` is either `{"parsed": [...]}` with one JSON object per parsed +condition (`{"opcode", "script_pubkey", "amount"}` for CREATE_COIN, +`{"opcode", "cost", "args": [""]}` for reserved conditions) +or `{"error": ""}`. Every rejection rule in CONDITIONS.md +section 1 and MATCHING.md rule 6 has at least one case. + +## matching case shape + +```json +{ + "name": "unique within the file", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "", + "index": 0, + "script_pubkey": "", + "amount": 60000, + "sequence": 4294967295, + "conditions": "" + } + ], + "outputs": [{"script_pubkey": "", "amount": 50000}] + }, + "expect": {"valid": true} +} +``` + +`sequence` is optional and defaults to 4294967295. An input without a +`conditions` key is a non-BitLisp input, one with the key is a BitLisp +input whose puzzle evaluation produced that condition list. `expect` +is `{"valid": true}` or `{"error": ""}`. The transaction must +satisfy the model's base rules (value conservation, ranges, distinct +outpoints): a case violating them is a malformed vector, not an +invalid spend. The adversarial regression corpus opens with the +duplicate-CREATE_COIN theft case as vector #1 in +`matching/create-coin.json`, per MATCHING.md rule 1. + Run the corpus with `python3 tools/run_vectors.py`. A vector file whose suite has no runner yet fails loudly rather than being skipped. diff --git a/vectors/conditions/encoding.json b/vectors/conditions/encoding.json new file mode 100644 index 0000000..1eec1ac --- /dev/null +++ b/vectors/conditions/encoding.json @@ -0,0 +1,314 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "conditions", + "spec": "CONDITIONS.md section 1, MATCHING.md rule 6", + "cases": [ + { + "name": "empty_list", + "conditions": "80", + "expect": { + "parsed": [] + } + }, + { + "name": "single_create_coin", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080", + "expect": { + "parsed": [ + { + "opcode": 1, + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + } + ] + } + }, + { + "name": "create_coin_zero_amount", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff808080", + "expect": { + "parsed": [ + { + "opcode": 1, + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 0 + } + ] + } + }, + { + "name": "create_coin_max_money", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff870775f05a0740008080", + "expect": { + "parsed": [ + { + "opcode": 1, + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 2100000000000000 + } + ] + } + }, + { + "name": "create_coin_script_max_size", + "conditions": "ffff01ffe02710000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000000000000000000000000ff018080", + "expect": { + "parsed": [ + { + "opcode": 1, + "script_pubkey": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00000000000000000000000000000000", + "amount": 1 + } + ] + } + }, + { + "name": "reserved_at_floor", + "conditions": "ffff8180ff8201f48080", + "expect": { + "parsed": [ + { + "opcode": 128, + "cost": 500, + "args": [] + } + ] + } + }, + { + "name": "reserved_top_opcode_shapeless_args", + "conditions": "ffff81ffff820258ff80ffff827a7a827979ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8080", + "expect": { + "parsed": [ + { + "opcode": 255, + "cost": 600, + "args": [ + "80", + "ff827a7a827979", + "a25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ] + } + ] + } + }, + { + "name": "reserved_large_cost", + "conditions": "ffff8190ff890100000000000000008080", + "expect": { + "parsed": [ + { + "opcode": 144, + "cost": 18446744073709551616, + "args": [] + } + ] + } + }, + { + "name": "mixed_list_order_preserved", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff0180ffff8181ff8201f480ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabff028080", + "expect": { + "parsed": [ + { + "opcode": 1, + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 1 + }, + { + "opcode": 129, + "cost": 500, + "args": [] + }, + { + "opcode": 1, + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", + "amount": 2 + } + ] + } + }, + { + "name": "top_level_atom", + "conditions": "01", + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "top_level_improper", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018001", + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "condition_is_atom", + "conditions": "ff0180", + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "condition_improper_args", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0180", + "expect": { + "error": "bad_condition_list" + } + }, + { + "name": "opcode_empty_atom", + "conditions": "ffff80ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "opcode_two_bytes", + "conditions": "ffff820001ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "opcode_is_pair", + "conditions": "ffffff0180ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "opcode_zero", + "conditions": "ffff00ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "opcode_family_gap", + "conditions": "ffff02ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "opcode_unallocated", + "conditions": "ffff7fffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080", + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "create_coin_one_arg", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8080", + "expect": { + "error": "bad_condition_arity" + } + }, + { + "name": "create_coin_three_args", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff01ff808080", + "expect": { + "error": "bad_condition_arity" + } + }, + { + "name": "script_empty", + "conditions": "ffff01ff80ff018080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "script_too_long", + "conditions": "ffff01ffe02711000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0000000000000000000000000000000000ff018080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "script_is_pair", + "conditions": "ffff01ffffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa80ff018080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "amount_non_minimal_zero", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff008080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "amount_non_minimal_leading", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8200018080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "amount_negative", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff81ff8080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "amount_over_max_money", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff870775f05a0740018080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "amount_is_pair", + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaffff01808080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "reserved_no_args", + "conditions": "ffff81808080", + "expect": { + "error": "bad_condition_arity" + } + }, + { + "name": "reserved_cost_below_floor", + "conditions": "ffff8180ff8201f38080", + "expect": { + "error": "reserved_cost_too_low" + } + }, + { + "name": "reserved_cost_zero", + "conditions": "ffff8180ff808080", + "expect": { + "error": "reserved_cost_too_low" + } + }, + { + "name": "reserved_cost_negative", + "conditions": "ffff8180ff82fe0c8080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "reserved_cost_non_minimal", + "conditions": "ffff8180ff830001f48080", + "expect": { + "error": "bad_condition_arg" + } + }, + { + "name": "reserved_cost_is_pair", + "conditions": "ffff8180ffff8201f4808080", + "expect": { + "error": "bad_condition_arg" + } + } + ] +} diff --git a/vectors/matching/create-coin.json b/vectors/matching/create-coin.json new file mode 100644 index 0000000..936df2f --- /dev/null +++ b/vectors/matching/create-coin.json @@ -0,0 +1,580 @@ +{ + "schema": "bitlisp-vector-v0", + "suite": "matching", + "spec": "MATCHING.md rule 1", + "cases": [ + { + "name": "duplicate_create_coin_theft", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + }, + { + "txid": "0202020202020202020202020202020202020202020202020202020202020202", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 38000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "duplicate_create_coin_honest_batch", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + }, + { + "txid": "0202020202020202020202020202020202020202020202020202020202020202", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 18000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "single_claim_satisfied", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 8000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "claim_without_matching_output", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 50000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "amount_off_by_one", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 49999 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "script_byte_flip", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", + "amount": 50000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "unmatched_outputs_permitted", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 100000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 20000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", + "amount": 20000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "one_input_duplicate_claims_two_slots", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 110000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c35080ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "one_input_duplicate_claims_one_slot", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 110000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c35080ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 50000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "plain_inputs_contribute_no_claims", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + }, + { + "txid": "0202020202020202020202020202020202020202020202020202020202020202", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 30000 + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 38000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "empty_condition_list_valid", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "80" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 59000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "reserved_condition_constrains_nothing", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff819cff8202bcffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa8080" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 59000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "two_distinct_claims_two_slots", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 110000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c35080ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", + "amount": 50000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "distinct_claims_colliding_on_one_content", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 110000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c35080ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "same_script_different_amounts_are_distinct_contents", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 110000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c35080ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff83009c408080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 40000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "zero_amount_claim", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff808080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 0 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 59000 + } + ] + }, + "expect": { + "valid": true + } + }, + { + "name": "three_input_batch_one_slot_short", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + }, + { + "txid": "0202020202020202020202020202020202020202020202020202020202020202", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + }, + { + "txid": "0303030303030303030303030303030303030303030303030303030303030303", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 70000 + } + ] + }, + "expect": { + "error": "unsatisfied_output_claim" + } + }, + { + "name": "encoding_error_surfaces_through_matching", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff02ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff018080" + } + ], + "outputs": [ + { + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 59000 + } + ] + }, + "expect": { + "error": "bad_condition_opcode" + } + }, + { + "name": "oversized_unclaimed_slot_permitted", + "tx": { + "version": 2, + "locktime": 0, + "inputs": [ + { + "txid": "0101010101010101010101010101010101010101010101010101010101010101", + "index": 0, + "script_pubkey": "0014bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "amount": 60000, + "conditions": "ffff01ffa25120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff8300c3508080" + } + ], + "outputs": [ + { + "script_pubkey": "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "amount": 50000 + }, + { + "script_pubkey": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0000000000000000000000000000000000", + "amount": 1000 + } + ] + }, + "expect": { + "valid": true + } + } + ] +} From 2d8ead867c192f6647bac87c048d82f55b0cec0f Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 20:54:08 -0700 Subject: [PATCH 09/12] Tests: hypothesis invariants for matching rule 1 One property per invariant the spec names, over a small content pool chosen for dense claim and slot collisions: the containment statement restated independently, reorder invariance across inputs, outputs, and condition lists, monotonicity in both directions (removing a claim never invalidates, adding one never validates), the unmatchable-claim rejection, the exactly-claimed-output removal and mutation metamorphics, and the generalized theft property (k identical claims never fit k minus one identical slots). Model preconditions (value conservation, duplicate outpoints, empty sides, amount ranges) are pinned as ValueError, distinct from spend invalidity. --- python/tests/test_matching_invariants.py | 214 +++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 python/tests/test_matching_invariants.py diff --git a/python/tests/test_matching_invariants.py b/python/tests/test_matching_invariants.py new file mode 100644 index 0000000..45e3d10 --- /dev/null +++ b/python/tests/test_matching_invariants.py @@ -0,0 +1,214 @@ +"""Property-based invariants for the matching layer. + +The matching rules have no external oracle, so property-based +invariants and the adversarial vector corpus stand in for one. + +Transactions are generated over a small content pool (three scripts, +four amounts) so claim and slot collisions are dense, which is where +injective matching earns its keep. +""" + +from collections import Counter + +import pytest +from bitlisp import ( + BitLispError, + CreateCoin, + Transaction, + TxInput, + TxOutput, + validate_transaction, +) +from hypothesis import given +from hypothesis import strategies as st + +SCRIPTS = (b"\x51", b"\x52", b"\x53") +AMOUNTS = (0, 1, 2, 3) +UNMATCHABLE = b"\xff" # never appears in generated outputs + +contents = st.tuples(st.sampled_from(SCRIPTS), st.sampled_from(AMOUNTS)) +claim_lists = st.lists(contents, max_size=3) +output_lists = st.lists(contents, min_size=1, max_size=6) +# None is a non-BitLisp input, a list is a BitLisp input's claims. +input_specs = st.lists(st.one_of(st.none(), claim_lists), min_size=1, max_size=3) + + +def build_tx(input_claims, outputs): + """A transaction whose first input funds all outputs.""" + out_total = sum(amount for _, amount in outputs) + inputs = [] + for n, claims in enumerate(input_claims): + conditions = ( + None + if claims is None + else tuple(CreateCoin(script, amount) for script, amount in claims) + ) + inputs.append( + TxInput( + txid=bytes([n + 1]) * 32, + index=0, + script_pubkey=b"\x51", + amount=out_total if n == 0 else 0, + sequence=0xFFFFFFFF, + conditions=conditions, + ) + ) + return Transaction( + version=2, + locktime=0, + inputs=tuple(inputs), + outputs=tuple(TxOutput(script, amount) for script, amount in outputs), + ) + + +def is_valid(tx): + try: + validate_transaction(tx) + return True + except BitLispError as exc: + assert exc.code == "unsatisfied_output_claim" + return False + + +def all_claims(input_claims): + return [c for claims in input_claims if claims is not None for c in claims] + + +@given(input_specs, output_lists) +def test_validity_is_multiset_containment(input_claims, outputs): + """Rule 1's spec statement, restated independently: valid exactly + when no content is claimed more times than slots carry it.""" + tx = build_tx(input_claims, outputs) + claimed = Counter(all_claims(input_claims)) + slots = Counter(outputs) + expected = all(count <= slots[content] for content, count in claimed.items()) + assert is_valid(tx) == expected + + +@given(input_specs, output_lists, st.randoms(use_true_random=False)) +def test_reordering_never_changes_the_outcome(input_claims, outputs, rng): + tx = build_tx(input_claims, outputs) + shuffled_inputs = list(input_claims) + rng.shuffle(shuffled_inputs) + shuffled_inputs = [ + (None if claims is None else rng.sample(claims, len(claims))) + for claims in shuffled_inputs + ] + shuffled_outputs = rng.sample(outputs, len(outputs)) + shuffled = build_tx(shuffled_inputs, shuffled_outputs) + assert is_valid(tx) == is_valid(shuffled) + + +@given(input_specs, output_lists) +def test_removing_a_condition_never_invalidates(input_claims, outputs): + """Constraints only tighten. Dropping any one claim from a valid + transaction leaves it valid.""" + tx = build_tx(input_claims, outputs) + if not is_valid(tx): + return + for i, claims in enumerate(input_claims): + if not claims: + continue + for j in range(len(claims)): + reduced = list(input_claims) + reduced[i] = claims[:j] + claims[j + 1 :] + assert is_valid(build_tx(reduced, outputs)) + + +@given(input_specs, output_lists) +def test_adding_an_unmatchable_claim_always_invalidates(input_claims, outputs): + augmented = list(input_claims) + augmented.append([(UNMATCHABLE, 1)]) + assert not is_valid(build_tx(augmented, outputs)) + + +@given(input_specs, output_lists, contents) +def test_adding_a_condition_never_validates(input_claims, outputs, extra_claim): + """The other half of monotonicity: an invalid transaction stays + invalid under any added claim.""" + if is_valid(build_tx(input_claims, outputs)): + return + augmented = list(input_claims) + augmented.append([extra_claim]) + assert not is_valid(build_tx(augmented, outputs)) + + +@given(input_specs, output_lists) +def test_removing_an_exactly_claimed_output_invalidates(input_claims, outputs): + tx = build_tx(input_claims, outputs) + if not is_valid(tx) or len(outputs) < 2: + return + claimed = Counter(all_claims(input_claims)) + slots = Counter(outputs) + for content, count in claimed.items(): + if count == slots[content]: + reduced = list(outputs) + reduced.remove(content) + assert not is_valid(build_tx(input_claims, reduced)) + break + + +@given(input_specs, output_lists, st.sampled_from(["amount", "script"])) +def test_mutating_an_exactly_claimed_output_invalidates( + input_claims, outputs, mutation +): + """Metamorphic: bump the amount or flip a script byte on a slot + whose content is exactly covered by claims.""" + tx = build_tx(input_claims, outputs) + if not is_valid(tx): + return + claimed = Counter(all_claims(input_claims)) + slots = Counter(outputs) + for content, count in claimed.items(): + if count == slots[content] and count > 0: + script, amount = content + if mutation == "amount": + mutated_content = (script, amount + 1) + else: + mutated_content = (bytes([script[0] ^ 0x01]), amount) + mutated = list(outputs) + mutated[mutated.index(content)] = mutated_content + assert not is_valid(build_tx(input_claims, mutated)) + break + + +@given(st.integers(min_value=2, max_value=5), contents) +def test_k_claims_never_fit_k_minus_1_slots(k, content): + """The theft property, generalized: k identical claims are never + satisfied by k - 1 identical slots.""" + input_claims = [[content] for _ in range(k)] + outputs = [content] * (k - 1) + assert not is_valid(build_tx(input_claims, outputs)) + assert is_valid(build_tx(input_claims, outputs + [content])) + + +# --- transaction-model preconditions --------------------------------------- +# Value conservation is enforced at construction, so matching never +# sees a transaction that creates value out of nothing. + + +def test_model_rejects_value_creation(): + tx_input = TxInput(b"\x01" * 32, 0, b"\x51", 4, 0) + with pytest.raises(ValueError, match="value not conserved"): + Transaction(2, 0, (tx_input,), (TxOutput(b"\x51", 5),)) + + +def test_model_rejects_duplicate_outpoints(): + tx_input = TxInput(b"\x01" * 32, 0, b"\x51", 1, 0) + with pytest.raises(ValueError, match="duplicate input outpoint"): + Transaction(2, 0, (tx_input, tx_input), (TxOutput(b"\x51", 1),)) + + +def test_model_rejects_empty_sides(): + tx_input = TxInput(b"\x01" * 32, 0, b"\x51", 1, 0) + with pytest.raises(ValueError, match="non-empty"): + Transaction(2, 0, (), (TxOutput(b"\x51", 1),)) + with pytest.raises(ValueError, match="non-empty"): + Transaction(2, 0, (tx_input,), ()) + + +def test_model_rejects_out_of_range_amounts(): + with pytest.raises(ValueError, match="amount out of range"): + TxOutput(b"\x51", -1) + with pytest.raises(ValueError, match="amount out of range"): + TxOutput(b"\x51", 2_100_000_000_000_001) From a0ca1d36dd35ada7cec307538e473b00188ac2aa Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 21:47:47 -0700 Subject: [PATCH 10/12] Docs: record the curation-note and cost-floor ratifications Two open items from the opening PR's review are now decided by Evan (2026-07-29). Curation notes stay in spec/CONDITIONS.md, resolving the conflict between the Phase 0 stub's plan and the spec-purity rule, with the exception recorded in ground rule 1. The reserved cost floor stays at 500 per the CHIP-0049 precedent, revisited when matching rule 5 lands. --- CLAUDE.md | 6 +++++- docs/condition-record.md | 13 ++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1481331..1b1f424 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,7 +62,11 @@ In practice this means: touching semantics references its spec section. The spec states behavior only, and stays complete enough on its own to predict every vector's outcome. Rationale, oracle provenance, and decision - records live in `docs/` (for the VM, `docs/vm-record.md`). + records live in `docs/` (for the VM, `docs/vm-record.md`). One + recorded exception (decision by Evan, 2026-07-29): vocabulary + entries in `spec/CONDITIONS.md` carry a brief curation note, why + the entry is in v0 and what was declined, with the full rationale + still in `docs/condition-record.md`. 2. **Vectors are the source of truth between sessions.** Sessions are stateless, the vector corpus is not. Any behavior worth keeping becomes a vector in `vectors/` the same day. diff --git a/docs/condition-record.md b/docs/condition-record.md index a18e03d..86f0bbf 100644 --- a/docs/condition-record.md +++ b/docs/condition-record.md @@ -112,7 +112,18 @@ Section 4 registers the rules that have no external reference at all. out of consensus. The spec makes the restriction normative text so relaxing it requires amending visible prose plus a recorded decision here. -5. **Invariant direction correction.** The Phase 0 stub stated that +5. **Curation notes stay in the spec.** RATIFIED (decision by Evan, + 2026-07-29). The Phase 0 stub planned a curation note on every + vocabulary entry, and the later spec-purity rule (spec states + behavior only, rationale in docs) arguably forbade it. Resolved + in favor of the notes: obligation 4 wants the curation visible + where the vocabulary is, so entries keep a brief note and this + record keeps the full rationale. CLAUDE.md ground rule 1 records + the exception. +6. **RESERVED_COST_FLOOR stays at 500.** RATIFIED (decision by Evan, + 2026-07-29). The CHIP-0049 per-condition base cost stands as the + provisional floor, revisited when rule 5's costing design lands. +7. **Invariant direction correction.** The Phase 0 stub stated that removing a condition never turns an invalid transaction valid. Under rule 1 that is false (removing one of two over-claims restores validity) and the true property is the reverse From 112e805b797d3f4ddb30d0588bb9c6e3ee1c0eb9 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 21:54:20 -0700 Subject: [PATCH 11/12] Tests: independent assignment-search oracle for rule 1 The containment property restates the matcher's own counting, so it pins the implementation against drift but cannot judge the algorithm. The new property implements rule 1's other formulation, a naive backtracking search for an injective claim-to-slot assignment, and asserts the two formulations never disagree. If counting is ever the wrong reduction of injective matching, this is the test that says so. --- python/tests/test_matching_invariants.py | 34 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/python/tests/test_matching_invariants.py b/python/tests/test_matching_invariants.py index 45e3d10..d89d5ed 100644 --- a/python/tests/test_matching_invariants.py +++ b/python/tests/test_matching_invariants.py @@ -76,8 +76,10 @@ def all_claims(input_claims): @given(input_specs, output_lists) def test_validity_is_multiset_containment(input_claims, outputs): - """Rule 1's spec statement, restated independently: valid exactly - when no content is claimed more times than slots carry it.""" + """Rule 1's counting formulation, restated. This restates the + matcher's own algorithm, so it pins the implementation against + drift but cannot judge the algorithm. The assignment-search test + below is the independent judge.""" tx = build_tx(input_claims, outputs) claimed = Counter(all_claims(input_claims)) slots = Counter(outputs) @@ -85,6 +87,34 @@ def test_validity_is_multiset_containment(input_claims, outputs): assert is_valid(tx) == expected +def _injective_assignment_exists(claims, slots): + """Literal backtracking search for an injective claim-to-slot + assignment, trying assignments one at a time. Deliberately naive + and deliberately sharing no code or idea with the matcher's + counting: this is the other formulation of rule 1, implemented as + written.""" + if not claims: + return True + first, rest = claims[0], claims[1:] + for i, slot in enumerate(slots): + if slot == first: + if _injective_assignment_exists(rest, slots[:i] + slots[i + 1 :]): + return True + return False + + +@given(input_specs, output_lists) +def test_counting_agrees_with_assignment_search(input_claims, outputs): + """Rule 1 states two formulations and calls them equivalent: + multiset containment (what the matcher computes) and the + existence of an injective assignment (what this search computes). + They must never disagree.""" + tx = build_tx(input_claims, outputs) + assert is_valid(tx) == _injective_assignment_exists( + all_claims(input_claims), list(outputs) + ) + + @given(input_specs, output_lists, st.randoms(use_true_random=False)) def test_reordering_never_changes_the_outcome(input_claims, outputs, rng): tx = build_tx(input_claims, outputs) From 8379ee807aa842856727b5acb9ce702fc207f139 Mon Sep 17 00:00:00 2001 From: Evan Date: Wed, 29 Jul 2026 22:02:15 -0700 Subject: [PATCH 12/12] Spec: claim amounts are content, not value flow A cold-reader exercise on the rule 1 vectors (Evan, 2026-07-29) surfaced the natural misreading: CREATE_COIN's amount taken as the spending input's value, pulling value conservation into matching where it does not belong. The entry now states what the amount is not: no debit from the input, no per-input value tracking, and conservation stays with Bitcoin's base rules transaction-wide. --- spec/CONDITIONS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/CONDITIONS.md b/spec/CONDITIONS.md index 0b769e6..36873bc 100644 --- a/spec/CONDITIONS.md +++ b/spec/CONDITIONS.md @@ -81,6 +81,12 @@ under MATCHING.md rule 1: k conditions carrying identical content require k distinct output slots. Two identical CREATE_COIN conditions from one input are two claims. +The `amount` is part of the demanded content, not a debit from the +spending input. Matching never tracks which input's value funds which +slot. Value conservation is enforced transaction-wide by Bitcoin's +base rules, and an input's own value is unrelated to the amounts its +conditions claim. + **Arguments.** `scriptPubKey` is an atom of 1 to 10,000 bytes. The empty atom is rejected (`bad_condition_arg`). `amount` is a minimally encoded integer with 0 <= amount <= 2,100,000,000,000,000 (MAX_MONEY,