On a bearer with no return path a receiver cannot ask for what it missed: it holds an object only if the passes it heard carried enough encoding symbols. bearer-receipts declares the transmission and reconciles it afterwards; nothing stated the plan in between. extensions/carousel.md registers `wai.bearer.carousel` and the jwp-receipts claim class `schedule` (§2.4.16): a publisher's signed plan, beside the group receipt and the instance's transmission claim, naming for each object its forward error correction (RaptorQ, RFC 6330 with its verified erratum 5548; Compact No-Code, RFC 5445) and that code's object transmission information, the repair symbols each pass adds, whether later passes repeat their ESIs or send new ones, and the passes' times and count. Step 4 holds each code's parameters to its bounds and division into source blocks; step 6 holds the entries to the group, its objects' content hashes and, where the bytes are held, their lengths. From it a verifier derives, for a loss bound in parts per million, the pass after which a receiver whose losses stay within it holds each object, for every pattern of loss within the bound: a RaptorQ block at K' + h distinct symbols, the count RFC 6330 §5.8 states its decoding failure bound at, and a symbol a repeating pass missed counted as missed again. It checks a statement that an object or a group is held by an instant, sets aside schedules that contradict each other or whose instance is undeclared or two-way, and a receiver derives the passes it must listen to and how long its radio must be on. The reference is the `carousel` module of wai-rs with the class's body in `claim_receipt::schedule`; the corpus is live-conformance/carousel/ (33 verdicts, 50 claims, 16 plans) with carousel_verify.py as its second implementation and claim_verify.py's new `carousel` mode for steps 1-4. tests/carousel.rs checks K' and Partition[] against an independent RFC 6330 implementation (a dev-dependency) for every block size, and decodes each RaptorQ object a case holds available from what a receiver within the bound holds. A receipt index served over HTTP now checks a schedule claim against its group and listed objects. Co-Authored-By: Claude Opus 5.5 <[email protected]>
49 lines
3.1 KiB
Markdown
49 lines
3.1 KiB
Markdown
# live-conformance/carousel — when each object passes, and when it is held
|
||
|
||
The corpus of [`extensions/carousel.md`](../../extensions/carousel.md) §10, in one file,
|
||
`vectors.json`.
|
||
|
||
**Provenance.** Generated here by `wai_carousel_vectors gen` (`wai-rs`, feature `carousel`),
|
||
from Ed25519 keys on fixed 32-byte seeds, constant times, and envelopes of exact lengths whose
|
||
payloads are opaque test bytes written by the generator; no media and no input from outside this
|
||
repository.
|
||
|
||
`keys` names every key by its role, as 64 lowercase hexadecimal digits: the publisher's
|
||
(`publisher`, `did:web:publisher.example#d1`), a second key of its origin (`publisher_d2`), and a
|
||
sink's (`sink`, signing under its `did:key`).
|
||
|
||
`verdicts` (§6) are each one group of four objects, of 3,200, 896, 288 and 200 octets, as a
|
||
verifier holds it:
|
||
|
||
- `group`: the group receipt (jwp-receipts §2.4.1) and `objects`, each object `receipt` with its
|
||
`envelope` in hexadecimal where the verifier holds the bytes, or `null`;
|
||
- `claims`: the transmission and schedule claims, each in its canonical wire form, each signer's
|
||
in the order of its chain;
|
||
- `loss_ppm` and `overhead`: the loss bound and overhead (§2); `statement`: `null`, or a
|
||
statement offered (§6.4): `{"kind": "object", "bearer_id", "index", "by_ms"}` or
|
||
`{"kind": "group", "bearer_id", "by_ms"}`;
|
||
- `outcome`: `refuse` and its `reason`; or `verdict` with each object's verdict, each claim's
|
||
(`declared`, `stands`, `set-aside reason=…`, or `reject step=… reason=…`), a line for each entry
|
||
of each schedule that stands — its `bearer_id`, `leaf_index`, `pass`, `available_ms`,
|
||
`bytes_sent` and `failure_one_in` — and the statement's result.
|
||
|
||
`claims` are each one schedule claim and its `outcome` through jwp-receipts §3.1 steps 1–4:
|
||
`accept`, or `reject step=… reason=…`. Among them every bound of §5.1, §5.2, §5.4 and §4.2 rule
|
||
3.3 that a schedule can reach, met and passed.
|
||
|
||
`plans` (§7) are each an `entry` of a schedule, the instant `at_ms` a receiver is at, its
|
||
`loss_ppm` and `overhead`, and `held`, the encoding symbols it holds of each source block.
|
||
`outcome`: `plan`, with the `passes` it listens to (each `pass`, `start_ms` and `end_ms`),
|
||
`complete_ms` and `listen_ms`; or `refuse` and its `reason`.
|
||
|
||
Everything is synthetic. Keys attest nothing; bearer instances use the example URN namespace
|
||
(`urn:example:`) and origins a reserved example domain. Each case states the outcome it was
|
||
written to have, declared in the generator, never copied from a verifier.
|
||
|
||
`wai_carousel_vectors verify` and `tests/carousel.rs` check that the file regenerates byte for
|
||
byte and that `wai-rs` reaches every stated outcome; the test also decodes each RaptorQ object a
|
||
case holds available with an independent implementation of RFC 6330, from what a receiver within
|
||
the case's loss bound holds. `../carousel_verify.py` is the second implementation, written from
|
||
the extension's text, which also mutates copies of the corpus and drops each of its own checks
|
||
in turn and requires each to be caught. `../../claim-conformance/claim_verify.py carousel
|
||
vectors.json` reads every claim through jwp-receipts §3.1 steps 1–4.
|