Expand description
Partial-disclosure verification: prove and verify that a single path, chunk, or byte range belongs to a commit id, with proof bytes on the order of a few KiB regardless of repository size.
§Trust model
A verified Disclosed proves that its payload bytes are exactly
the content the given commit_id commits to at path — nothing more.
It does not prove:
- that the disclosed path is the only thing at that location (no sibling-completeness claim — see the closure profile, issue #1015 PR 3, for that);
- anything about who the signer is —
signer/signature_validreport whether the embedded Ed25519 signature verifies against the embedded public key; binding that key to an identity or trust level is application policy (trust roots), exactly ascrate::sign::verify_commitalready documents.
Every function in this module verifies against an object id, never
a bare (pre-domain-wrap) inner root or an unauthenticated byte range —
see crate::merkle’s module docs for why that distinction matters.
Wire format, verification algorithm, and bounds are pinned in
docs/specs/SPEC-DISCLOSURE.md; golden vectors live under
rust/tests/golden/disclosure/. See issue #1015 (verifier kit) PR 2.
§Layering
verify_object_id, verify_path, verify_chunk_with_meta,
verify_blob_slice, and verify_blob_len_proof are the small,
independently-useful primitives (each corresponds to one hop of the
authentication chain: commit → tree steps → leaf → chunk/slice).
verify_disclosure decodes a self-contained wire bundle (§ below)
and composes them into one call. build_disclosure_from is the
producer side, generic over any verifying crate::store::ObjectSource
(the on-disk store, an in-memory overlay, or a server-side index or
object CAS); build_disclosure is its thin wrapper over
crate::store::ObjectStore. The builder’s source trait is distinct
from this module’s ObjectSource, the non-verifying
fetch(&mut self) trait the closure walker reads through. Full
disclosure — every reachable object against a commit id — is
verify_closure, verify_closure_streaming,
verify_closure_packs, and verify_closure_manifest, with
verify_closure_store and export_closure as native store-backed
operations (issue #1015 PR 3).
Everything here, the builder included, compiles with
--no-default-features and targets wasm32-unknown-unknown; no
separate feature gate is needed since mkit-core itself is a std
crate (see the crate root docs).
§Wire bundle (verify_disclosure / build_disclosure)
magic = "MKDP" (4 raw bytes)
version: u8 = 2
commit_id: [u8; 32]
commit_bytes: Vec<u8> <= 4 MiB
steps: Vec<Step> <= MAX_TREE_DEPTH (128), root first
Step { name: Vec<u8> (1..=255), mode: u8, child_id: [u8; 32],
inner_root: [u8; 32], position: u32, proof: Proof (max_items = 1) }
payload_kind: u8
0 Object { bytes: Vec<u8> <= MAX_RAW_OBJECT_SIZE }
1 Chunk { total_size: u64, chunk_size: u32, index: u32,
inner_root: [u8; 32], proof: Proof (max_items = 2),
bytes: Vec<u8> }
2 Range { chunk: Option<ChunkHdr>, offset_in_blob: u64, len: u64,
slice: Vec<u8>, chunk_len_proofs: Vec<LenProof> }
ChunkHdr { total_size: u64, chunk_size: u32, index: u32,
inner_root: [u8; 32], chunk_id: [u8; 32],
proof: Proof (max_items = 2) }
LenProof { index: u32, chunk_id: [u8; 32],
proof: Proof (max_items = 1), slice: Vec<u8> }All integers are big-endian, every length is an LEB128 varint, arrays
are raw — commonware-codec conventions (SPEC-CONVENTIONS §3;
crate::transfer’s packlist node is the existing precedent for this
house style). The whole bundle is capped at MAX_BUNDLE_BYTES;
trailing bytes are rejected.
ChunkHdr.chunk_id is not literal to issue #1015’s original design
note, which omitted it: without an explicit chunk id, a verifier
reading a byte-range bundle would have no value to check the Bao slice
against before folding it into the enclosing ChunkedBlob’s multi-proof
(Bao’s SliceDecoder always requires the expected root up front — it
cannot recover an unknown one from the slice, by construction). Adding
this field closes that gap; it is exactly the value
verify_chunk_with_meta’s multi-proof authenticates, so a forged
chunk_id fails to fold to the enclosing ChunkedBlob’s id.
Modules§
- proof_
size - Exact proof wire-size planning from canonical object metadata. Exact MKDP/MKDS lengths from metadata, without constructing Merkle or Bao proofs. Chunk lengths describe canonical Blob content, excluding its ten header bytes. All results enforce the 64 MiB wire cap.
- span
- MKDS v1 multi-chunk range proofs (SPEC-DISCLOSURE §8).
Structs§
- Closure
Export - Encoded closure plus the raw-only packs it indexes.
- Closure
Manifest - Convenience index of a closure export: magic
"MKCL", version 1, root id, mode, and thepack_keyof each pack in order. - Closure
Report - Outcome of walking a supplied object set from
rootinmode. - Disclosed
- A verified partial disclosure:
payloadis exactly the contentcommit_idcommits to atpath, and nothing more. See the module docs for the precise trust model. - Path
Verified - The result of walking and verifying a path from a commit’s
tree_hashdown to a leaf. - Push
Report - What
verify_pushfound. The push is acceptable only whenSelf::is_acceptedholds. - Step
- One authenticated hop of a path: the entry
name/modeproven atpositionunder its parent (a commit’stree_hash, or the previous step’schild_id), via a single-leafProof.
Enums§
- Disclosed
Payload - The disclosed content of a
Disclosedresult. - Selector
- What
build_disclosurediscloses about the leaf itspathreaches. - Verify
Error - Errors verifying (or, natively, building) a disclosure.
Constants§
- MAX_
BUNDLE_ BYTES - Hard cap on a whole encoded disclosure bundle, checked before any
decode work happens.
mkit-wasmadditionally caps decoded objects at 16 MiB; this 64 MiB ceiling is the wasm32-agnostic bound this crate itself enforces. - MAX_
CLOSURE_ PACKS - Hard cap on the number of packs a closure manifest may list.
Traits§
- Object
Source - Provides a pull-based source for canonical object bytes.
Functions§
- build_
disclosure - Build a disclosure bundle proving
selector’s content atpathundercommit_id, reading only fromstore.pathempty withSelector::Objectdiscloses the root tree. - build_
disclosure_ from - Build a disclosure bundle proving
selector’s content atpathundercommit_id, reading only throughsource: anycrate::store::ObjectSource(the on-disk store, ancrate::store::EphemeralSink, or a server-side repository index or object CAS). Not to be confused withObjectSource, this module’s non-verifying closure-walker trait (fetch(&mut self)). - export_
closure - Walk
storeinmode, write raw-only packs of the reachable objects in sorted id order, and return the encoded manifest plus packs. Native-only (ObjectStore). - verify_
blob_ len_ proof - Verify a Bao slice over canonical bytes
0..10of the object whose id isblob_id, and return thele32length field at bytes6..10— the object’s own declared content length, authenticated by the first Bao leaf chunk (Bao’s encoding header is not what is trusted here; the canonical prologue bytes themselves are). - verify_
blob_ slice - Verify a Bao slice proving
lencontent bytes atcontent_offsetbelong to the object (Blob, or oneChunkedBlobchunk) whose canonical-bytes BLAKE3 isblob_id.sliceis expected in the formatbao::encode::SliceExtractorproduces over the object’s canonical bytes (prologue ‖le32(len)‖ data) — so a Bao-authenticated content offsetomaps to Bao offseto + 10, and the returned root equals the object’s own id (SPEC-OBJECTS §3). - verify_
chunk_ with_ meta - Verify that a
ChunkedBlob’s claimedtotal_size/chunk_sizeand the chunkchunk_hashatindexboth belong to theChunkedBlobwhose id ischunked_id, via one multi-proof over BMT positions{0, index + 1}. - verify_
closure - Re-hashes every supplied object and walks from
rootwithchildren(obj, mode). Store-less: the caller provides the object bytes. This compatibility path is implemented by the same pull-based walker asverify_closure_streaming, with an in-memory source keyed by each successfully derived id, followed by the legacy supplied-setunreferencedpass. - verify_
closure_ manifest - Decode the manifest, reject it if its
rootis notexpected_root, check pack count andpack_keyequality in order, thenverify_closure_packs.modecomes from the manifest (it only widens or narrows the walk; the report carries it). The caller supplies the trusted root; the manifest is a locator, never a trust anchor. - verify_
closure_ packs - Iterates each pack with
PackEntries. Any delta or compressed entry is a profile violation — the closure profile is raw-only so a wasm verifier (nopack-zstd) can consume it. Raw payloads are indexed by their derived ids and served as borrowed slices into the original pack buffers. - verify_
closure_ store - Verifies a closure by reading the local
ObjectStoreon demand. - verify_
closure_ streaming - Walks a closure by fetching each requested id only when the BFS reaches it.
Bytes are deserialized, re-hashed, and discarded after their child ids are
extracted, so the walk retains object ids rather than the complete object
set. A fetch-by-id source that returns bytes whose derived id differs from
the requested id reports
corruptunder the requested id; this is intentionally different from the map path’s legacymissing+unreferencedclassification for a parsable bit flip. - verify_
disclosure - Decode and fully verify a disclosure bundle against
commit_id. - verify_
object_ id - verify_
path - Verify a path of
Steps from a commit/remix’stree_hashdown to a leaf id, checking each step’s proof against the previous step’schild_id(the first againsttree_hashitself). - verify_
push - Verify the history a push introduces, before refs move.