Proof Envelope + Transcript Commitments v1¶
Status: frozen for TKT-P3-38
Goal: lock one canonical PBv1 envelope and transcript commitment policy so backend, wallet, and covenant paths commit the same bytes.
1. Scope¶
This freeze covers:
PBv1envelope byte layout and section rules- transcript commitment rules that consume
PBv1 - transport chunk and hints commitment rules used by the rich wallet path
- malformed/reject behavior expectations
This freeze does not define prover internals. It only defines what bytes are committed and how they are validated.
2. Canonical PBv1 envelope¶
Normative implementation:
packages/zk-boundary/src/proof_blob_v1.ts
Normative vectors/tests:
packages/zk-boundary/test-vectors/pbv1_vectors.jsonpackages/zk-boundary/test-vectors/pbv1_reject.jsonpackages/zk-boundary/src/tests/proof_blob_v1.test.ts
2.1 Header and section table¶
- magic: ASCII
PBV1 - version:
0x01 - flags:
0x00(reserved) - backend id:
u32le - section count:
u8(bounded byMAX_SECTIONS) - reserved bytes: zero
Section entries are fixed-width and include:
section_id(u16le)- reserved fields (must be zero)
length(u32le)sha256(section_bytes)
2.2 Section policy¶
Stable section IDs:
0x0001PROOF(required, exactly once, must be first)0x0002ENCRYPTED_PAYLOAD(optional)0x0003HINTS(optional)
Unknown stable IDs are rejected. Experimental IDs (>= 0x8000) are allowed with size caps.
2.3 Canonical PB commitments¶
hashPBv1(bytes) = HASH256(bytes)sectionsRootPBv1(bytes)is an ordered fold over section entries in table order
No sorting or canonicalization-by-reordering is allowed.
2.4 Mock-backend neutrality¶
PBv1 carries only generic envelope fields (backendId, section IDs/bytes/digests).
There are no mock-backend-only fields in the envelope schema.
3. Transcript policy v1 commitments¶
Normative implementation:
packages/zk-boundary/src/transcript_policy_v1.ts
Normative vectors/tests:
packages/zk-boundary/test-vectors/tpv1_vectors.jsonpackages/zk-boundary/src/tests/transcript_policy_v1.test.ts
3.1 PB transcript binds¶
tpv1_proofBlobBind32(pbv1Bytes)bindshashPBv1tpv1_proofBlobSectionsBind32(pbv1Bytes)bindssectionsRootPBv1
These functions must reject malformed PBv1 inputs.
3.2 Transport chunk commitments¶
For rich wallet transport:
- encrypted payload is split into exactly two ordered chunks
- each chunk gets a chunk bind (
index,length,HASH256(chunk)) - payload root is an ordered fold over chunk binds
- hints bind is
tagHash(HINTS_HASH, HASH256(hints_bytes)) - transport bind is
tagHash(TRANSPORT_BIND, payloadRoot32 || hintsBind32)
4. Reject policy (frozen)¶
At minimum, malformed PB inputs must be rejected for:
- bad magic/version/flags/reserved bytes
- too-large section count
- section table out of bounds
- duplicate section IDs
- unknown stable section ID
- missing
PROOFor wrong section order - section too large
- digest mismatch
- length mismatch / trailing bytes
These reject conditions are pinned in pbv1_reject.json and consumed by both PB parser tests and TPv1 PB-bind tests.
5. On-chain/off-chain parity notes¶
- Off-chain strict parsing/commitments are implemented in
@bch-stealth/zk-boundary. - Host-side parity checks are exercised in
packages/pool-shards/tests/host_v1_eval.test.js. - Any mutation that changes PB bytes must either reject or alter PB commitments.