Direct-Spend Commitment Envelope ABI v1 (CEv1)¶
Status: frozen design output for TKT-P4-09A (#206).
Purpose: freeze a 128-byte token commitment envelope ABI that binds to hidden private-lineage transcript semantics without storing readable identity semantics on chain.
1) Core design rule: binding, not storage¶
The token commitment is public on chain. CEv1 therefore treats public bytes as commitments and control metadata, not plaintext lineage storage.
CEv1 MUST:
- bind to hidden transcript components
- keep readable identity semantics off chain
- avoid raw secret disclosure
- remain auditable and migration-ready for locking-script / proofblob32 / protocol-state-cell evolution
CEv1 MUST NOT:
- store readable lineage identity semantics directly
- recreate the same public identity linkage under new labels
2) Candidate layouts considered¶
All candidates below are exactly 128 bytes.
Candidate A: structured multi-subcommit envelope¶
| Offset | Size | Field |
|---|---|---|
| 0 | 32 | lineage_commit32 |
| 32 | 32 | state_commit32 |
| 64 | 32 | recovery_commit32 |
| 96 | 32 | tx_binding_commit32 |
Candidate B: semi-structured envelope with control header and fewer subcommits¶
| Offset | Size | Field |
|---|---|---|
| 0 | 32 | control32 |
| 32 | 32 | lineage_commit32 |
| 64 | 32 | state_commit32 |
| 96 | 32 | recovery_tx_binding_commit32 |
Candidate C: opaque/single-root style envelope¶
| Offset | Size | Field |
|---|---|---|
| 0 | 32 | control32 |
| 32 | 32 | envelope_root32 |
| 64 | 32 | payload_binding32 |
| 96 | 32 | migration_commit32 |
3) Selection result¶
Chosen layout: Candidate B.
Why Candidate B was selected:
- It provides explicit control/version/hash/domain bytes in-band (reviewability).
- It preserves distinct subcommit surfaces for lineage and state without over-fragmenting into too many public fields.
- It keeps enough reserved/control space to evolve toward covenant selector logic and proofblob/state-cell migration.
- It is easier to audit than an opaque root model while still preserving binding-not-storage semantics.
Rejected alternatives and rationale¶
Rejected Candidate A:
- Strong decomposition, but no explicit in-band control header for version/hash/domain/reserved policy.
- Pushes critical policy/version semantics into out-of-band conventions, which weakens protocol reviewability and migration safety.
Rejected Candidate C:
- Most flexible internally, but too opaque for review and closure evaluation.
- Increases risk of accidental relabeling of old public linkage without clear semantic accountability.
- Harder to map incrementally into wallet/recovery and later covenant/state-cell enforcement.
4) Frozen CEv1 ABI (exact 128 bytes)¶
4.1 Top-level layout¶
| Offset | Size | Field | Encoding | Notes |
|---|---|---|---|---|
| 0 | 32 | control32 |
structured bytes | CEv1 control block |
| 32 | 32 | lineage_commit32 |
bytes32 | commitment to hidden lineage semantics |
| 64 | 32 | state_commit32 |
bytes32 | commitment to hidden state reference semantics |
| 96 | 32 | recovery_tx_binding_commit32 |
bytes32 | commitment tying recovery handle + tx binding semantics |
Total: 128 bytes exactly.
4.2 control32 sub-layout¶
| Offset | Size | Field | Encoding | Rule |
|---|---|---|---|---|
| 0 | 1 | ce_major |
u8 | MUST be 0x01 for CEv1 |
| 1 | 1 | ce_minor |
u8 | MUST be 0x00 for CEv1 |
| 2 | 1 | hash_policy_id |
u8 | see Section 5.1 |
| 3 | 1 | domain_policy_id |
u8 | see Section 5.2 |
| 4 | 1 | layout_id |
u8 | MUST be 0x01 for Candidate B layout |
| 5 | 1 | flags |
u8 | all bits reserved in CEv1; MUST be 0x00 |
| 6 | 2 | reserved_u16 |
u16-be | MUST be 0x0000 |
| 8 | 4 | migration_epoch |
u32-be | MUST be 0x00000000 in CEv1 |
| 12 | 4 | reserved_u32 |
u32-be | MUST be 0x00000000 |
| 16 | 16 | reserved_16 |
bytes16 | MUST be all-zero |
Endianness rules:
- Multi-byte integers in
control32are big-endian. bytes32commitment fields are raw digest bytes in canonical order.
4.3 Serialization order¶
CEv1 serialization is the strict concatenation:
control32lineage_commit32state_commit32recovery_tx_binding_commit32
No extra bytes are permitted before or after this 128-byte sequence.
5) Versioning, hash policy, domain tags, and reserved-byte policy¶
5.1 Hash policy id rules¶
hash_policy_id values:
0x01=HASH256(double SHA-256) producing 32-byte digest outputs.
CEv1 writers MUST emit 0x01.
CEv1 parsers MUST reject unknown hash_policy_id values.
5.2 Domain policy id rules¶
domain_policy_id values:
0x01= CEv1 fixed ASCII domain tags:DSCE1:lineage_commit:v1DSCE1:state_commit:v1DSCE1:recovery_tx_binding_commit:v1
CEv1 writers MUST emit 0x01.
CEv1 parsers MUST reject unknown domain_policy_id values.
5.3 Versioning rules¶
- CEv1 writers MUST emit
ce_major=0x01,ce_minor=0x00,layout_id=0x01. - CEv1 parsers MUST reject:
ce_major != 0x01layout_id != 0x01- CEv1 parsers SHOULD reject
ce_minor != 0x00until a reviewed minor-compatibility policy is published.
5.4 Reserved-byte policy¶
All reserved bytes are strict zero in CEv1:
flagsreserved_u16migration_epochreserved_u32reserved_16
Parsers MUST reject non-zero values in any reserved field to prevent covert channel drift.
6) Commitment construction shape (CEv1 boundary)¶
CEv1 freezes envelope bytes and commitment slots. Full transcript-field construction is refined in TKT-P4-09B (#207), but CEv1 requires this shape:
lineage_commit32 = H32(domain_lineage || lineage_components)state_commit32 = H32(domain_state || state_components || lineage_commit32)recovery_tx_binding_commit32 = H32(domain_recovery_tx || recovery_components || tx_binding_components || lineage_commit32)
Where:
H32useshash_policy_id(HASH256for CEv1).- Domain bytes use
domain_policy_id. - Inputs are hidden transcript components; the chain sees only resulting commitments.
7) Hidden/public placement map (required in #206)¶
This map is frozen at placement-class level for CEv1 and is refined field-by-field in #207.
| Component | Wallet-local only | Encrypted payload only | Public commitment input | Notes |
|---|---|---|---|---|
lineage_blind (hidden component) |
Yes | No | Yes | secret blinding input; never plaintext on chain |
lineage_id (hidden component) |
Yes | Optional copy | Yes | committed identity handle, not public plaintext |
state_ref (hidden component) |
Yes | Optional copy | Yes | committed state reference semantics |
recovery_handle (hidden component) |
Yes | Yes | Yes | committed for recovery linkage without plaintext disclosure |
tx_binding_digest (binding component) |
Derived locally | No | Yes | binds commitment semantics to transaction context |
control32 policy bytes |
No | No | Yes | protocol policy and migration controls only |
lineage_commit32 |
No | No | Yes | public commitment output |
state_commit32 |
No | No | Yes | public commitment output |
recovery_tx_binding_commit32 |
No | No | Yes | public commitment output |
8) Migration-readiness notes (for #208 handoff)¶
CEv1 is optimized for migration, not permanence of current shell semantics:
control32provides policy/selector surface for future locking-script role mapping.lineage_commit32provides lineage authority anchor independent of shell category semantics.state_commit32provides a clean bridge to later protocol-state-cell authoritative semantics.recovery_tx_binding_commit32provides tx-bound recovery continuity anchor compatible with later proofblob/state-cell enforcement models.
This supports the Phase 3C direction: public category32 as shell continuity/discovery transport, private lineage authority carried by commitments to hidden transcript semantics.