Skip to content

spec: define the IssuanceTerms transport in CoinProof bundles - #89

Merged
TaprootFreak merged 1 commit into
developfrom
spec/issuance-terms-transport
Jul 17, 2026
Merged

spec: define the IssuanceTerms transport in CoinProof bundles#89
TaprootFreak merged 1 commit into
developfrom
spec/issuance-terms-transport

Conversation

@TaprootFreak

@TaprootFreak TaprootFreak commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Problem

The spec asserts in three places that an asset's human-readable name and decimals travel only inside bundles (§2.3.1, §6.5, §4.5) — but no bundle field carries them. asset_id is a Poseidon digest; without the preimage {creator_pubkey, name, decimals, issuance_version} a holder can neither display the asset nor evaluate §2.3.3 step 6 ("asset_id is well-formed"), and the IssuanceTerms message reserved in the §1.1 domain-separation catalogue had no wire home. The binding itself is fine (the terms are self-authenticating by recomputing asset_id); only the transport was undefined.

Changes (docs/specification.md only)

  • §1.5 — optional asset_terms? = {creator_pubkey, name, decimals, issuance_version} in the CoinProof plaintext (name is a raw byte string, max 255 bytes; UTF-8 validity is display-only). It rides exclusively inside the ZBE-encrypted blob under K_tx: no new public object. Self-authenticating — name enters the asset_id preimage as name_hash = H(name), so the receiver verifies by recomputing asset_id.
  • §2.3.1 / §2.3.2 — senders SHOULD attach asset_terms; a sender that holds verified terms MUST attach them on the terms' own first hop to a recipient. A holder without verified terms MAY forward, and the recipient then tracks the asset opaquely.
  • §4.2.1kb MUST encrypt at most one plaintext (a bundle is never re-encrypted under the same K_tx, which would repeat (kb, nonce) against a different plaintext and two-time-pad-leak asset_terms); the resulting blob-size side channel is documented as an accepted residual leak.
  • §2.3.3 step 6 — fail-closed: if asset_terms is present, the recipient MUST recompute asset_id and reject the bundle on mismatch. Absent (or non-UTF-8) terms, the coin stays valid but the wallet MUST track the asset as an opaque asset_id.
  • §6.5 — new IssuanceTerms transport subsection + explicit non-goal: no global asset registry; wallets key assets by asset_id, never by name.
  • §7.1 — canonical binary layout for the optional asset_terms? field: a presence byte (0x00 absent / 0x01 present) plus the sub-layout creator_pubkey (32) ‖ decimals (1) ‖ issuance_version (1) ‖ u32-be len(name) ‖ name, so serialize(CoinProof) stays unambiguous and the blob_id determinism of §4.2.1 holds.
  • §1.7.3 / §4.5 / glossary — u8 version-space note; recovery path updated (the name is external and never recoverable from the chain — only from a recovered bundle's asset_terms or the issuer); new asset_terms entry and IssuanceTerms / Bundle (CoinProof) entries synced.

No circuit clauses, proof-system parameters, on-chain formats, or test vectors are touched.

Rebased onto the post-#97 develop: the terms ride the current CoinProof (with creating_nullifier / nav_opening); there is no anchor_hint field in this model.

@TaprootFreak

Copy link
Copy Markdown
Contributor Author

Holding this as draft: the branch base predates #97 (the accumulator-model change to on-chain half-aggregated nullifiers). The content is largely model-independent, but the section anchors and surrounding text shifted substantially in #97. Parking this until the new model settles on develop, then rebasing and re-checking anchors in one pass.

@joshuakrueger-dfx
joshuakrueger-dfx force-pushed the spec/issuance-terms-transport branch from c322965 to 889ca5c Compare July 15, 2026 14:44
@joshuakrueger-dfx

Copy link
Copy Markdown
Collaborator

Finalization pass complete — reviewed (correctness + conformance) to zero findings.

This branch predated #97 and previously conflicted against develop. Rebased onto develop (the V3 on-chain half-aggregated nullifier model) and reconciled the asset_terms / IssuanceTerms transport onto it:

  • The CoinProof bundle keeps its V3 fields (creating_nullifier, nav_opening) with the optional asset_terms? added; the retired pre-spec: revert accumulator to on-chain half-aggregated nullifiers (implements research#16) #97 fields (anchor_hint, anchors_opening) are gone.
  • §2.3.3 receive keeps the V3 steps (first-occurrence anchoring via creating_nullifier, per-account replay guard) and adds step 6's asset_terms recompute (asset_id == Hc("AssetId", …), §1.4).
  • §7.1 encodes asset_terms as the sole optional field (presence byte + byte layout, 255-byte name bound, UTF-8 display-only); no retired BatchBundle serialization remains.
  • Dropped the now-dangling anchor_hint reference from the §4.2.1 ZBE key-reuse note.

Build and CodeQL green on the latest commit. Ready for review.

@joshuakrueger-dfx
joshuakrueger-dfx marked this pull request as ready for review July 15, 2026 15:00
@TaprootFreak TaprootFreak mentioned this pull request Jul 17, 2026
3 tasks
Adds the optional asset_terms field to CoinProof (the only defined carrier of
an asset's plaintext issuance terms), fail-closed recompute in receive step 6,
the §7.1 wire layout, the §6.5 transport subsection, and glossary sync.
@TaprootFreak
TaprootFreak force-pushed the spec/issuance-terms-transport branch from 889ca5c to c36f919 Compare July 17, 2026 21:18
@TaprootFreak
TaprootFreak merged commit 5e1a1f9 into develop Jul 17, 2026
5 checks passed
TaprootFreak added a commit that referenced this pull request Jul 20, 2026
Collapses the IssuanceTerms_v2 auditable-supply-cap work (genesis-anchored
single mint; cap_total + terms_salt bound into asset_id via the AssetIdV2
tag; fail-closed issuance-version dispatch in clause 3) onto the current
develop after #89, #102 and #107 merged. Conflict resolution: the asset_terms
transport paragraph takes the version-dependent form, the mint first-occurrence
comment its expanded wording; develop's serialize(Coin) paragraph and the
6-confirmation finality directive are preserved unchanged.

Original v2 design by joshuakrueger-dfx; fail-closed dispatch fix follows.
TaprootFreak added a commit that referenced this pull request Jul 20, 2026
…#100)

* spec: rebase the IssuanceTerms_v2 supply cap onto develop

Collapses the IssuanceTerms_v2 auditable-supply-cap work (genesis-anchored
single mint; cap_total + terms_salt bound into asset_id via the AssetIdV2
tag; fail-closed issuance-version dispatch in clause 3) onto the current
develop after #89, #102 and #107 merged. Conflict resolution: the asset_terms
transport paragraph takes the version-dependent form, the mint first-occurrence
comment its expanded wording; develop's serialize(Coin) paragraph and the
6-confirmation finality directive are preserved unchanged.

Original v2 design by joshuakrueger-dfx; fail-closed dispatch fix follows.

* spec: fix v2 review nits (v1 clause-a branch scope, v1-and-v2 version dispatch)

* spec: apply pr-ready review consistency fixes (v1 clause-a branch scope, clause-8 v2 self-mint carve-out, risks mitigation tense, first-occurrence naming)

* spec: complete the v2 self-mint deferral across balances (clause 7) and the §501 invariant, and name clause 7 in clause (g)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants