Expand description
Bao verified-range helpers for deCDN: align a byte range to bao chunk groups, encode a verified range for the wire, and size that encoding.
deCDN streams every blob as bao’s interleaved verified encoding, so a
receiver checks each chunk group against the blob’s BLAKE3 root as it lands
(ADR 038 § Wire format). This crate holds the range arithmetic both sides
share. It depends on bao-tree and not on iroh-blobs, so the client SDK
and the decdn CLI link no blob store.
§Entry points
| You want to | Use |
|---|---|
Snap a [offset, +len) request to whole chunk groups | align_range, align_range_clamped, AlignedRange |
| Encode a verified range from raw bytes and an untrusted outboard | encode_verified_range |
| Know how many wire bytes a range costs, proof included | bao_encoded_size, AlignedRange::wire_len |
| Encode a whole blob as a stream, without buffering it | streaming |
| Implement a range-aware blob backend | RangedStore |
| Write or find a blob’s outboard in a filesystem origin | encode_outboard, OBAO4_SUFFIX, shard_prefix |
§Verifying an origin range
An origin backend (S3, R2, B2, HTTP, or a filesystem) serves raw bytes by
hash, with no bao tree. When the origin also stores the blob’s pre-order
bao outboard at the sibling key {H}.obao4, a node fetches only the range
[a, b) it wants and verifies it against the root H with that outboard
(ADR 037 § Origin-tier pull-through). The result is the bao interleaved
encoding, which the node imports as a verified partial blob.
The outboard needs no trust. Every leaf must hash to its parent, and the
spine must combine to the root H the node asked for. A tampered range, a
tampered outboard, or a wrong root fails with RangeVerifyError. The
origin stays a plain byte store.
Re-exports§
pub use origin_seed::EncodedOutboard;pub use origin_seed::OBAO4_SUFFIX;pub use origin_seed::encode_outboard;pub use origin_seed::shard_prefix;pub use ranged_store::RangedFuture;pub use ranged_store::RangedStore;pub use ranged_store::RangedStoreError;
Modules§
- origin_
seed - Filesystem-origin layout contract and outboard seeding.
- ranged_
store - The
(hash, total_bytes)blob view every range-aware backend implements. - streaming
- Streaming, header-less whole-blob bao encoder (issue #1130’s stream-while-
store seam): produces the same interleaved proof+data bytes as
crate::encode_verified_rangeoverChunkRanges::all(), but reads a sequentialstd::io::Readsource instead of requiring the whole blob already buffered in memory, and omits the 8-byte LE size header that helper prepends (the tee this feeds already carries the size out-of-band, in the signedStreamResponse).
Structs§
- Aligned
Range - The chunk-group-aligned byte span a node must fetch from origin to serve a
requested
[byte_offset, byte_offset + byte_len), plus the chunk ranges to import. A bao proof covers whole 16 KiB groups, so the fetch widens to the enclosing group boundaries (the extra bytes are paid origin egress but never re-served as client bytes — the request is still scoped, not whole-blob). Fields are private and the only constructor isalign_range, so holding anAlignedRangeguarantees its invariants:fetch_start <= fetch_end, both group-aligned (orfetch_end == blob_sizefor the final partial group), andchunk_rangesexactly covers[fetch_start, fetch_end).
Enums§
- Range
Verify Error - Errors from preparing a verified origin range pull.
Constants§
- CHUNK_
GROUP_ BYTES - Bytes per chunk group, derived from
IROH_BLOCK_SIZE(2^chunk_log1 KiB chunks) — the granularity an origin range must snap to, because a bao proof anchors whole chunk groups to the root. - IROH_
BLOCK_ SIZE iroh-blobs’ canonical on-disk block size (16 KiB chunk groups,from_chunk_log(4)). Declared from thebao-treeprimitive rather than re-exported fromiroh-blobs, because this crate must stay iroh-blobs-free so the CLI’s pull path can link it. The value is identical by construction toiroh_blobs::store::IROH_BLOCK_SIZE(which is alsoBlockSize::from_chunk_log(4));decdn-cachecarries a lock-step test asserting the two stay equal, so a divergence across an iroh-blobs bump — which ADR 038 treats as a protocol-contract change — fails the build there.
Functions§
- align_
range - Compute the chunk-group-aligned fetch span for a
[byte_offset, +byte_len)request against ablob_size-byte blob.byte_len == 0means “to end”. - align_
range_ clamped align_range, but an end past the blob clamps to the blob’s end instead of being refused: a claimed size is a hint, and the planner’s bound can overshoot it. Onlybyte_offset >= blob_size(for a non-empty blob) is refused, withRangeVerifyError::RangeOutOfBounds: a start past the end has no chunk group to anchor, clamped or not.(0, 0)means the whole blob, and the empty blob is addressable only as(0, 0), exactly as inalign_range.- bao_
encoded_ size - Exact byte length of the header-less bao interleaved encoding a serving
node emits for
chunk_rangesof atotal_bytes-byte blob — the sum of every proof node (64 bytes each) and data leaf (≤ chunk-group bytes) in response (pre-order) order (ADR 038 §Wire format). - encode_
verified_ range - Verify
range_data(coveringaligned.fetch_start..aligned.fetch_end) and the supplied pre-orderoutboardagainst the wanted rootroot, returning the bao interleaved encoding foraligned.chunk_ranges— ready forBlobs::import_bao_bytes(root, aligned.chunk_ranges, _).