open-standards/smart-byte/spec/envelope_wire_format.md
Transaction Science 31f5d6bba4 smart-byte spec: governance, burns, and transfers between clusters
cluster_state.md, rewritten. The state gains the cluster's identifier, its
peers, its governance (delay, sequence number, pending changes), and the
retired, exported and imported records.
- Governance proposals change the registry and the peers. Each is
  sequence-numbered, needs approval from floor(2m/3)+1 of its electorate,
  and is time-locked by the cluster's delay.
- A burn retires a byte for good.
- A transition may name a destination cluster. The source's committing nodes
  certify the byte's state as it left. The destination checks the
  certificate and verifies the byte's full history itself.

envelope_wire_format.md: the destination member, covered by the signature
and the history hash. Frames rise within a cluster; a move to another
cluster starts that cluster's count.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 11:10:54 -04:00

172 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Envelope Wire Format
*Smart Byte Substrate — Spec, Section: Envelope Wire Format. v1.0-draft.*
---
## 1. What this section fixes
Treatise [§8](./treatise_v1_parts_I_II_III_combined.md) says what a smart byte carries and why. This section fixes how it is written: member names and types, the messages its signatures cover, how its history hash advances, and how it is verified. Everything is canonical CBOR as [identity spec §2.3](./identity_and_key_rotation.md) defines it. Where the treatise's prose leaves a choice open, this section makes it.
---
## 2. The envelope
```
{
"d": SAID of this envelope as it stands (§4),
"provenance": the origin attestation (§3),
"ownership_chain": [transition, ...] (§5), oldest first,
"joule_cost": {"measured_microjoules": uint, "estimated_microjoules": uint}
}
```
An envelope has exactly these members, and so does every map inside it: a member this section does not define makes the envelope malformed. `joule_cost` is the two-part energy accounting of treatise §8.6.
An envelope carries two SAIDs. The provenance's `d` is the byte's **identity** (treatise §8.2): fixed when the byte is issued, never changed by anything that happens to it afterwards. The envelope's own `d` addresses this **snapshot** of the byte — its chain and joule cost as they stand now.
---
## 3. Provenance: the origin attestation
```
{
"d": SAID: the byte's identity,
"issuer": the issuer's controller AID (identity spec §3.1),
"recipient": the first owner's controller AID,
"nonce": 16 bytes,
"cargo": cargo (§6),
"signature": the issuer's controller signature (§7)
}
```
- The issuer signs the canonical encoding of the four attested fields (treatise §8.3): the map `{"cargo", "issuer", "nonce", "recipient"}` holding the provenance's own values.
- `d` is the SAID of the provenance map (identity spec §2.1). It covers the signature, so the identity binds the issuer, the cargo, the recipient, the nonce, and the issuer's signature (treatise §8.2).
- The nonce keeps two otherwise-identical issuances distinct.
Parties are named by controller AIDs, which identity spec §3.1 makes authoritative over the treatise's raw public keys. A signature is checked against the key state the signer's key-event log establishes (§7), so a byte stays verifiable across its owners' key rotations.
---
## 4. The snapshot SAID
The envelope's `d` is the SAID of the whole envelope map, computed per identity spec §2.1 with the provenance's `d` already in place. Each transfer and each joule-cost update produces a new snapshot, and so a new snapshot SAID; none changes the identity. The gossip overlay deduplicates and serves snapshots by this SAID (identity spec §2.6).
---
## 5. The ownership chain
```
{
"previous_history_hash": 32 bytes,
"from": the current owner's AID,
"to": the new owner's AID,
"frame": uint: the lockstep frame the transfer is applied in,
"destination": SAID: the cluster the byte moves to — only on a transfer between clusters,
"signature": from's controller signature (§7)
}
```
- `from` signs the canonical encoding of `{"byte", "previous_history_hash", "from", "to", "frame"}`, where `byte` is the identity's SAID text (treatise §8.4). A transfer between clusters also has `"destination"` in the map it signs. The signature is therefore scoped to exactly one transition, of exactly one byte, at exactly one point in its history, and to where the byte goes.
- The **history hash** (treatise §10.1) starts as the identity's 32 digest bytes. Each transition advances it: `next = BLAKE3(previous ‖ payload)`. The `payload` is the canonical encoding of the transition's `{"from", "to", "frame", "signature"}`, with `"destination"` included when the transition has one.
- `destination` is present only on a transition that moves the byte to another cluster (treatise §11.3.3; cluster state spec §5). A transition within a cluster has no such member.
- **Frames rise strictly within a cluster:** a byte is transferred at most once per frame (treatise §8.4). Each cluster counts its own frames, so the transition after one with a `destination` is in another cluster's count and is not compared with it.
---
## 6. Cargo
```
{"type": uint, "bytes": bytes}
```
`type` is a small-integer tag from the registry below, and `bytes` is opaque to the substrate (treatise §8.5). A registered type fixes what its bytes hold; the substrate transports them unchanged.
| type | name | bytes |
| ---- | ----------------------- | ------------------------------------------------------------ |
| 0 | `opaque` | application-defined |
| 1 | `usd` | canonical CBOR `{"micros": int}`: dollars, six decimals |
| 2 | `joules` | canonical CBOR `{"microjoules": uint}` |
| 16 | `verifiable-credential` | the credential's JCS encoding (RFC 8785) |
| 17 | `bbs-credential` | canonical CBOR of the BBS+ credential body |
| 18 | `bbs-presentation` | canonical CBOR of the BBS+ presentation body |
| 19 | `crdt-snapshot` | canonical CBOR of a CRDT document snapshot |
| 20 | `crdt-delta` | canonical CBOR of a CRDT op batch |
| 21 | `mdoc` | the mobile document's CBOR, as its issuer signed it |
Tags 3–15 are reserved for the substrate's own cargo classes. New types are added to this table.
---
## 7. Controller signatures
```
{
"establishment": uint,
"signatures": [{"index": uint, "signature": bytes}, ...]
}
```
- `establishment` is the sequence number of the signer's establishment event — inception or rotation — whose key set made the signatures.
- Each signature is by key `index` of that set: the key's one-byte algorithm identifier, then the signature. For Ed25519 that is `0x01` followed by 64 bytes.
A controller signature is valid if and only if all of the following hold:
1. The named establishment event is in the signer's verified key-event log (identity spec §4).
2. Every listed signature verifies. One bad signature refuses the whole set, so a set means one thing however it is relayed.
3. No index appears twice.
4. At least the event's threshold `kt` of keys signed.
Ed25519 is verified strictly. A key whose encoded `y` is not below the field prime is refused (RFC 8032 §5.1.3), as is a scalar `S` outside `[0, L)` (§5.1.7). So is any small-order key or commitment.
---
## 8. Verification
A verifier holding an envelope's bytes and its parties' key-event logs runs treatise §10.2's procedure:
1. **Decode.** The bytes are canonical, and exactly the encoding of an envelope: every member is defined by this section and written in the type and form it gives — a byte string, not an array of integers, where bytes belong. Both SAIDs check: the envelope's `d` against the envelope, then the provenance's `d` against the provenance.
2. **Provenance.** The issuer's signature is valid over the attested fields (§3, §7).
3. **Chain.** For each transition in order:
- its `previous_history_hash` equals the running history hash;
- its `from` is the current owner (the recipient, for the first transition);
- its frame exceeds the previous transition's, unless the previous transition named a `destination`;
- its signature is valid.
The running hash then advances, and `to` becomes the owner.
4. **Result.** The identity, the issuer, the current owner and the current history hash.
Each failure has an error class, shared with the conformance pack:
- `said_mismatch` — a SAID does not check.
- `not_an_envelope` — an undefined member, or a member of the wrong type or form.
- `unknown_key_state` — the named establishment event is not in the verifier's logs.
- `signature_invalid`, `below_threshold`, `duplicate_key_index`, `key_index_out_of_range`, `algorithm_mismatch`, `unsupported_algorithm`, `malformed_signature`, `malformed_verifying_key` — a signature rule fails.
- `broken_history_chain` — a transition does not continue the history it follows.
- `not_current_owner` — a transition is not signed away by the current owner.
- `frame_not_increasing` — two transitions in one cluster share a frame, or frames go backwards.
- A canonical-encoding class (identity spec §2.3) — the bytes are not canonical.
---
## 9. What the cluster decides
Four questions depend on cluster state rather than on the envelope:
- whether the issuer is registered for the cargo type (treatise §10.2 step 3, §15);
- whether a signer's establishment event was the one in force at a transition's frame;
- whether the byte may enter or leave the cluster — a destination it peers with, a source it trusts (treatise §11.3.3);
- how nodes account the joule cost (treatise §8.6).
The cluster answers these when it applies a mint, import or transfer (treatise §9.4 step 5). The [cluster state](./cluster_state.md) section fixes how:
- the registry lists the issuers for each cargo type;
- a signature must name the establishment event in force when it is applied;
- a byte moves only between peer clusters, on a certificate from the source cluster's nodes;
- joule cost is reported beside the cluster state, not in it.
---
## 10. Implementation and vectors
`smart-byte-rs/crates/smart-byte-core` implements this section: `envelope.rs`, `provenance.rs`, `ownership.rs` and `cargo.rs`, with signatures in `keys.rs`. Key-event logs are replayed by `smart-byte-rs/crates/smart-byte-keri-witness`. The conformance vectors are `../conformance/v1/envelope_vectors.json`, built on the key-event logs of `../conformance/v1/kel_vectors.json`.