TYPE 0x0A02 · QABIO FAMILY
QABI_SPEND
Batch-spend the primed UTXO. Consumes the next preimage at committed_depth + 1, verifies against auth_tip, and relies on the tx-level aggregated_sig (FALCON-512 over SIGHASH_QABO) to authorise the whole batch atomically. Every primed input in the same tx shares the same aggregated signature — one FALCON verification per tx, not per input. Output set must bit-exact match the QABIBlock’s outputs vector; no coordinator-side skim is possible.
Ladder Diagram
Fields
| Field | Data Type | Size | Side | Description |
|---|---|---|---|---|
| auth_tip | HASH256 | 32 B | Conditions | Tip of the auth chain: H^N(auth_seed). Committed at UTXO creation time. The participant’s single secret is auth_seed; every future priming and spending preimage derives from it. |
| committed_root | HASH256 | 32 B | Conditions | Primed batch root. Zero before priming; set to the coordinator’s batch root by a QABI_PRIME tx. The coordinator’s aggregated sig at QABI_SPEND time is checked against the qabi_block whose SHA256 equals this root. |
| committed_depth | NUMERIC | 1–4 B | Conditions | Depth of the most recently consumed preimage. Monotonically increasing. The witness-revealed spend_preimage must hash to auth_tip after committed_depth + 1 SHA256 iterations. |
| committed_expiry | NUMERIC | 1–4 B | Conditions | Max block height at which the spend may fire. Evaluated against block_height. Prevents stale primed UTXOs from being batch-spent against an old committed batch after the window closes. |
| owner_id | PUBKEY_COMMIT | 32 B | Conditions | SHA256 of the owner’s FALCON public key. Must match one entry in the QABIBlock’s entries list (consensus check 7). Ties the input to its position in the batch. |
| spend_preimage | PREIMAGE | 32 B | Witness | The next preimage in the auth chain, revealed at depth committed_depth + 1. Verified via SHA256^(committed_depth + 1)(spend_preimage) == auth_tip. |
QABI_SPEND carries the QABI_SPEND_WITNESS implicit layout (6 fields total, 1 witness-only). The per-tx qabi_block and aggregated_sig are not part of the block’s field list — they live on the transaction object itself and are shared across all primed inputs.
Evaluation Logic
1.All 6 witness+conditions fields present with correct types and sizes. Otherwise → ERROR
2.Check
block_height <= committed_expiry (expiry window). Otherwise → UNSATISFIED3.Verify
SHA256^(committed_depth + 1)(spend_preimage) == auth_tip. Otherwise → UNSATISFIED4.Tx must carry a non-empty
qabi_block (else UNSATISFIED) and an aggregated_sig with size in [1, QABI_AGGREGATED_SIG_MAX = 666]. v0.14 fix: pre-v0.14 required variable up to 666 B (signers padded shorter sigs with zeros), opening a 0-66 B/tx coordinator-side embedding channel. v0.14 carries the actual FALCON sig length; OQS_SIG_verify validates the encoded length internally.5.Parse qabi_block via ParseQABIBlock; failure populates
ctx.error_message_out with the parse-specific reason and returns UNSATISFIED. parsed.coordinator_pubkey must be exactly QABI_COORDINATOR_PUBKEY_SIZE (897 bytes, FALCON-512).6.Per-input check:
SHA256(qabi_block) == this input's committed_root. Mismatch → UNSATISFIED (cached at tx level so the SHA256 runs once per tx).7.Output-set binding:
tx.conditions_root == parsed.outputs_conditions_root AND tx.output_count == parsed.output_values.size() AND each tx.outputs[i].value == parsed.output_values[i]. Mismatch → UNSATISFIED. The per-output scriptPubKey is structurally 0xDF + tx.conditions_root for any v4 MLSC tx, so binding conditions_root pins every destination SPK without storing them in the qabi_block.8.QABO sighash: compute via ComputeSighashQABO(tx). Verify FALCON-512(
coord_pk, sighash, aggregated_sig) via VerifyPQSignature. Cached per tx (mutex-protected via qabo_sig_cache_mutex; v0.14 hardening): one verify per tx, not per input. Failure → UNSATISFIED9.Per-input check:
parsed.prime_expiry_height == this input's committed_expiry. Mismatch → UNSATISFIED10.Per-input check: this input's
owner_id must appear in the hash-indexed parsed.entries[*].participant_id set (built once per tx during cache miss for O(1) lookups; collapses identity-check work from O(N²) to O(N) per QABIO tx). Missing → UNSATISFIED11.All checks pass → SATISFIED
Return Values
| Condition | Result |
|---|---|
| Field count or types incorrect | ERROR |
| committed_expiry in the past | UNSATISFIED |
| spend_preimage does not hash to auth_tip | UNSATISFIED |
| qabi_block SHA256 != committed_root | UNSATISFIED |
| FALCON-512 verify fails (shared across all inputs) | UNSATISFIED |
| owner_id not in qabi_block.entries | UNSATISFIED |
| tx.conditions_root or per-output values do not match parsed.outputs | UNSATISFIED |
| aggregated_sig_size = 0 or > QABI_AGGREGATED_SIG_MAX (666) | UNSATISFIED |
| coordinator_pubkey size != 897 (FALCON-512) | UNSATISFIED |
| expiry_height mismatch between qabi_block and committed state | UNSATISFIED |
| All 9 checks pass | SATISFIED |
Worked Example
Coordinator finalises a 100-party QABIO batch
100 primed UTXOs, each committed to the same
committed_root = SHA256(qabi_block)Coordinator builds a tx with 100 inputs and
K outputs (the destination list from qabi_block)Each primed input’s witness reveals its own
spend_preimage at its own committed_depth + 1Coordinator computes SIGHASH_QABO and signs once with their FALCON-512 key. Variable-length
aggregated_sig (1-666 B) attached to the tx; OQS_SIG_verify validates the encoded length internally.Consensus verifies the aggregated sig ONCE per tx via the QABO sig cache → shared across all 100 inputs
For each input: check its own preimage, expiry, owner_id → SATISFIED
Tx mined; every participant’s contribution lands at their committed destination atomically, or none of them do
Use Cases
Coordinator-driven batch payments
A payroll service, mixing pool, or L2 exit coordinator collects primed UTXOs from N participants, publishes a single qabi_block listing contributions and destinations, and finalises the whole batch with one FALCON-512 signature. One on-chain tx, N inputs, K outputs, one signature. Consensus-guaranteed atomicity.
Post-quantum multi-party batching
The aggregated signature is FALCON-512 — not Schnorr — so the coordinator authorisation is PQ-safe today, without needing MuSig or threshold schemes. A coordinator wanting Schnorr or another PQ scheme (DILITHIUM3, SPHINCS+) would require a future
QABI_BLOCK_VERSION = 0x02 with scheme dispatch.Atomic swaps at scale
Any multi-party protocol needing “all or nothing” settlement with a small trusted (or semi-trusted) coordinator role: liquidity pool exits, swap commit phases, gas-station batch settlements. The coordinator sees the full tx before signing; participants see the coordinator’s pubkey + batch root before priming.