Some checks failed
joule-moq-agent AI participants / joule-moq-agent · does this change touch it (push) Successful in 1m20s
joule-moq-http live HTTP egress / joule-moq-http · does this change touch it (push) Successful in 1m12s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 1m26s
wai-app and Create / wai-app · does this change touch it (push) Successful in 1m7s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 3m30s
wai-audit collector and player integration / does this change touch it (push) Successful in 1m55s
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 3m44s
wai-ledger service / does this change touch it (push) Failing after 59s
wai-ledger service / service · linux (push) Has been skipped
wai-ledger service / service · macos (push) Has been skipped
wai-quantum studio and desktop / does this change touch it (push) Failing after 5s
wai-sink-android native sink library / does this change touch it (push) Failing after 6s
wai-pack / wai-pack · does this change touch it (push) Failing after 50s
wai-quantum studio and desktop / studio · browser (push) Has been skipped
wai-quantum studio and desktop / desktop app · macos (push) Has been skipped
wai-quantum studio and desktop / desktop app · linux (push) Has been skipped
wai-quantum studio and desktop / desktop app · windows (push) Has been skipped
wai-sink-swift native sink package / does this change touch it (push) Failing after 5s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been skipped
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been skipped
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been skipped
WAI operation catalogue / does this change touch it (push) Successful in 2m40s
wai-pack / wai-pack · linux (push) Has been skipped
wai-quantum for JavaScript / does this change touch it (push) Successful in 1m30s
wai-pack / wai-pack · linux-arm64 (push) Has been skipped
wai-pack / wai-pack · macos (push) Has been skipped
wai-pack / wai-pack · independent verifier (Python) (push) Has been skipped
wai-pack / wai-pack · the floor through a media prober (push) Has been skipped
wai-fleet service / does this change touch it (push) Successful in 2m27s
wai-pack / wai-pack · dependency licences (push) Has been skipped
WAI Studio / does this change touch it (push) Failing after 8s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been skipped
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been skipped
WAI Studio / Studio in WebKit · linux (push) Has been skipped
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 4m6s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 8s
WAI examples / WAI examples · does this change touch them (push) Successful in 11s
wai web player plugins / the browser run's room compiles · linux (push) Successful in 58s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 32s
wai tv web application / the tv application, built to its baseline and checked · linux (push) Successful in 5m12s
wai web player plugins / the plugins' core under Node · linux (push) Successful in 6m56s
wai-audit collector and player integration / collector · linux (push) Successful in 3m3s
wai-fleet service / service · linux (push) Successful in 2m22s
wai-quantum for JavaScript / javascript · linux (push) Successful in 6m54s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 16m49s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 2m25s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 8m44s
joule-code conformance gate / joule-moq-ingest, every target (push) Failing after 6m56s
joule-code conformance gate / joule-moq-relay, every target (push) Failing after 7m31s
WAI examples / WAI examples · portable · linux (push) Successful in 24m14s
joule-moq-agent AI participants / joule-moq-agent, every target (push) Successful in 5m45s
joule-moq-http live HTTP egress / joule-moq-http, every target (push) Successful in 6m55s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 5m28s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 16m10s
joule-moq-room room service / joule-moq-room, every target (push) Failing after 15m19s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 51s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Successful in 52s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m39s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Successful in 8m47s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Failing after 16m25s
wai-fleet service / service · macos (push) Successful in 1m25s
WAI examples / WAI examples · android-app · linux-arm64 (push) Successful in 20m13s
wai tv web application / the tv application in Chromium, Firefox and WebKit · macos (push) Successful in 21m9s
joule-moq-http in browsers / the egress and the protected room in Chromium, Firefox and WebKit · macos (push) Successful in 50m56s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Successful in 20m9s
wai web player plugins / the three players in Chromium, Firefox and WebKit · macos (push) Failing after 34m1s
waiTransport's wt §50.2 and §50.4. An egress signs a per-hop record of role 4 (live-metering §3.12): what it received at the relay and what it answered 200 over HTTP, no subscriber time, no DVR window, its ledger by the grant each request carried; key-log authority live/egress. A room-session receipt of version 2 counts its bytes out beside the relays', so receipt-ledger tariff version 4 bills them at the room's price for bytes out: no new source kind and no new tariff version. Its session at a relay is a subscriber session under its grant, not a hop link. energy-methods places its figure in delivery_relay. The gateway signs its record (Gateway::hop_record), held to its own trace in its test. Metering corpus: room lesson_egress, vector `egress` and seven planted faults; live_metering_verify.py checks them and each of its five egress checks, dropped, is caught. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1756 lines
140 KiB
Markdown
1756 lines
140 KiB
Markdown
# WAI Extension: Receipt Ledger
|
||
|
||
> Status: Draft. Registers the record `wai.delivery.ledger`: invoice lines a customer can
|
||
> recompute from the signed records WAI already defines. A seller and a buyer both sign a
|
||
> **tariff**, `WLT1`: one currency, and one price for each unit those records state, the
|
||
> units of a room session ([live-metering](live-metering.md) §4.4), the acknowledged bytes of
|
||
> each object class ([settlement](settlement.md) §3.3), the packages, entries and stored bytes
|
||
> of a package receipt ([packaging](packaging.md) §9), the counted impressions of a
|
||
> `wai.video.ssai` receipt of the break form ([live-ads](live-ads.md) §8,
|
||
> [ad-presentation](ad-presentation.md) §9.2) and the presentations of ads another party
|
||
> stitched ([stitched-presentation](stitched-presentation.md) §7.4); and the **scope** it
|
||
> covers, the rooms, the delivering parties, the packagers, and the ad deciders and stitchers
|
||
> whose records are billed under it. The
|
||
> ledger verifies each **source** by the extension that defines it, and the seller signs an
|
||
> **invoice**, `WLI1`, for a period: the records it was computed from, one line per source,
|
||
> unit and price, each line citing the records it came from, and the joules those records
|
||
> state, per scope and per acquisition class with their largest declared uncertainty, never
|
||
> summed across classes or scopes. Invoices under one tariff form a chain, and no record is
|
||
> billed in two of them. A verifier given the tariff, the invoice, the invoice before it and
|
||
> the sources recomputes every line and refuses an invoice that does not recompute. Beside the
|
||
> invoice, the ledger states two **reports**: the ad decisions reconciled against the players'
|
||
> presentation claims (for a stitched stream, stitched-presentation §7.5's own statement), and
|
||
> the delivery of each party under the one tariff with the bytes two parties were acknowledged
|
||
> for twice. A tariff of version 2 also prices **media jobs** (§4.5): a job is billed from
|
||
> its route record ([route-record](route-record.md)), its hops' OER/2 receipts and WAI's
|
||
> receipt of its output, in the units those receipts state. A tariff of version 3 prices a
|
||
> job by its capability **and its operation** (§4.6), since an encode and a decode spend
|
||
> different energy, and bills a job's **work** once, its route record and its hops' receipts,
|
||
> its output's receipt being the evidence a re-run may cite again (§6.9). A tariff of version 4
|
||
> also bills what the rest of the work spends (§4.7): a room's bytes out, which a room-session
|
||
> receipt of version 2 states (live-metering §4.4), at a price per 10^9 bytes; a package's work
|
||
> once per run that made it, by the work units it states, its receipt the product each run
|
||
> cites; a package's storage by byte-days for each period it is held; and its invoices state
|
||
> every hop's energy, the hops not billed in a scope of their own (§6.6). A tariff of version 6
|
||
> also prices a job **per endpoint**, and by the **usage** a third party's hop record states
|
||
> ([route-record](route-record.md) §6.2), and bills an upscale and a tone mapping by the subpixels
|
||
> their records state, each re-derived from what it read (§4.9). A tariff of version 7 also
|
||
> prices a **transmission** on a shared bearer (§4.10): the octets and pass time a publisher's
|
||
> schedule plans on a `multicast` or `unidirectional` instance it declared
|
||
> ([carousel](carousel.md) §5.4, [bearer-receipts](bearer-receipts.md) §4), at a price for each
|
||
> bearer class, unit and ceiling of the passes' rate, from a source that is a group with its
|
||
> declarations and its standing schedules or a node's own instance of one; an **aggregated
|
||
> impression** (§4.11), the count of an aggregate receipt ([impression-aggregates](impression-aggregates.md)),
|
||
> in a unit of its own; and an object an **agent consumed** (§4.12), from its consumption claims
|
||
> ([ai-usage](ai-usage.md) §6). A tariff of version 8 also prices **storage held over time**
|
||
> (§4.13), such as a stream's recent window or a clip cut from it, by byte-days, from a holder's
|
||
> **storage record** of a stored set over an interval, `WLH1`, whose byte-seconds the verifier
|
||
> recomputes from the holder's signed **snapshots** of what the set listed, `WLS1`, and refuses
|
||
> when they do not support it. A tariff of version 9 may **follow** another (§4.14): signed by
|
||
> both parties as every tariff is, it names the tariff whose chain it continues, so a scope or a
|
||
> price changed when a party's key is made or retired keeps the chain, the storage of what it
|
||
> holds and what it has billed once. Whatever the version,
|
||
> a job's output receipt is of an object its served hop states it delivered, where its route
|
||
> record states it (§5.1), and a route record's routing figures are never charges. No new transport, no payment
|
||
> and no tax: an invoice is the recomputable figures a payment rests on. The reference implementation is the
|
||
> `receipt_ledger` module of `wai-rs` (feature `receipt_ledger`) and the service
|
||
> `wai/wai-ledger`; the corpus is [`live-conformance/ledger/`](../live-conformance/ledger/),
|
||
> and its second implementation is `live-conformance/receipt_ledger_verify.py`.
|
||
> Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
|
||
>
|
||
> Texts read for this revision: the WAI texts this one cites; ISO 4217 (the alphabetic
|
||
> currency code); RFC 8032; RFC 8259; FIPS 180-4.
|
||
|
||
## 1. Scope
|
||
|
||
In scope: how one tariff prices rooms, packages, HTTP and relayed delivery, ads, and in version 7
|
||
transmissions on shared bearers, aggregated impressions and what agents consume together, and in
|
||
version 8 storage held over time (§3); the tariff, its two signatures and its scope, and in version
|
||
9 a tariff that follows another, its chain continuing that tariff's (§4); the
|
||
snapshot and the storage record a holder signs (§4.13); the sources a ledger is given and what
|
||
each contributes (§5); the invoice, its records, lines, citations and energy, its signature and
|
||
its chain (§6); verification (§7); the two reports (§8); and the reference service (§9).
|
||
|
||
Out of scope: a transport; payment, a payment rail, tax and any contact with a party outside the
|
||
records; how a seller chooses its prices; how a party measures its energy, which
|
||
[energy-measurement](energy-measurement.md) governs; and the records themselves, which their own
|
||
extensions define, verify and leave as they are. The live-metering tariff and the settlement
|
||
statement's tariff keep their meaning: this extension reads them, and changes neither.
|
||
|
||
Relationship to the core spec: `wai.delivery.ledger` is a **record** ([SPEC](../SPEC.md) §5):
|
||
a signed record a WAI tool emits and verifies. It names no payload format and is not
|
||
dispatchable.
|
||
|
||
## 2. Terms
|
||
|
||
- **Seller**, **buyer**: Ed25519 keys (RFC 8032). The seller operates the ledger and signs its
|
||
invoices; the buyer is the customer billed.
|
||
- **Holder** (version 8): an Ed25519 key that keeps objects for the buyer over time and signs what
|
||
it kept (§4.13).
|
||
- **Time**: microseconds since 1970-01-01T00:00:00Z, the unit of a room's `t0` (live-rooms §3.1).
|
||
A **period** is a span of time from its `start` (included) to its `end` (excluded).
|
||
- **Minor unit**: a currency's smallest unit (ISO 4217); an **amount** is an integer of
|
||
millionths of one, as settlement §7.3's amounts are.
|
||
- **Source**: one record a ledger bills from, with what its own verifier is given (§5).
|
||
- **Record identity**: the 32 bytes a record of a kind is named by (§5.2).
|
||
- *u64*, *u32*, *u16*, *u8*: little-endian unsigned integers of that many bits. A **digest** is
|
||
SHA-256 (FIPS 180-4), 32 bytes; **zero** of a key or digest field is 32 zero bytes.
|
||
- **Class**, **tag**, **unmetered marker**: an acquisition class of energy-measurement §2.7, its
|
||
tag byte (2 `ModelBased`, 3 `Estimator`, 4 `OnChipCounter`, 5 `CalibratedInstrument`), and a
|
||
figure of 0 with no class.
|
||
|
||
## 3. One tariff across rooms, packages and HTTP delivery
|
||
|
||
The records a deployment bills from state their units in their own terms. A room-session receipt
|
||
states microseconds and events (live-metering §4.4), and may state a `tariff` of its own, which
|
||
prices the session's grants against their funds ceilings (§4.6 there). A settlement statement
|
||
states acknowledged bytes by object class, whatever carried them: a relay over MOQT, or a cache
|
||
over HTTP whose deliveries were acknowledged as settlement §9.1 maps them; it may state a tariff
|
||
too, which prices its own lines (§7.3 there). A package receipt states entries and bytes
|
||
(packaging §9) and no tariff. An ad decision's receipt states impressions (live-ads §8.2) and
|
||
no tariff of the seller's; so does a stream another party stitched, whose stitcher signs a
|
||
pod-input record, `WSI1`, of the ads it chose and whose players sign a claim, `WSC1`, of each ad
|
||
presented (stitched-presentation §4, §5).
|
||
|
||
A tariff of this extension prices every one of those units in one currency, so one invoice bills
|
||
a buyer's rooms, deliveries, packages and ads together. Three rules keep every figure in it
|
||
consistent with what the records say:
|
||
|
||
1. **A record that states a tariff states this one.** A room-session receipt of a source either
|
||
states no tariff (currency zero) or the tariff's currency and its room prices, in
|
||
live-metering §4.1's order: the thirteen, and the price of bytes out, which a receipt of
|
||
version 1 and a tariff of versions 1 to 3 do not state and read as 0; a settlement statement either states no tariff or the tariff's
|
||
currency and its four delivery prices, in settlement §7.1's order. A record under another
|
||
tariff is refused `tariff_conflict` (§7.2 step 5): the funds its grants were held to, or the
|
||
amount its party stated, were computed at other prices, and an invoice at these prices would
|
||
contradict it.
|
||
2. **One rounding, the same everywhere.** Every amount is a quantity times a price, divided by
|
||
the unit's divisor and rounded down once per invoice line (§6.4), as settlement §7.3 rounds a
|
||
statement's line. A statement's own amount rounds once per payer; the invoice rounds once per
|
||
party and class, so the two can differ by less than one millionth of a minor unit per payer
|
||
line, and the delivery report (§8.2) states both.
|
||
3. **Units are never converted.** A room is billed in its own units (in version 4, its bytes
|
||
out too), a delivery in bytes, a package in packages, entries and stored bytes (in version
|
||
4, in byte-days held), an ad in impressions, a job in jobs or in the subpixels its output's
|
||
receipt states (§4.5), and in version 4 in the work units of the packages it made, and in version
|
||
7 a transmission in the octets and the pass time its schedule states (§4.10), an aggregate
|
||
receipt in its count (§4.11) and an agent's consumption in objects (§4.12), and in version 8 a
|
||
holder's storage in the byte-seconds its records state, in whole byte-days (§4.13). No line turns one unit
|
||
into another, and no line is priced from joules: the energy of an invoice is stated beside
|
||
its lines (§6.6), per class, and is not an amount.
|
||
|
||
So the tariff is the one place prices live: a room receipt's funds verdicts, a statement's
|
||
amount and an invoice's lines all follow from it, and a buyer who holds the tariff and the
|
||
records recomputes all three.
|
||
|
||
## 4. The tariff
|
||
|
||
### 4.1 Layout
|
||
|
||
| field | size | meaning |
|
||
|---|---|---|
|
||
| `magic` | 4 | `WLT1` (ASCII) |
|
||
| `version` | 1 | 1; 2 for a tariff that prices jobs (§4.5); 3 for one that prices them per operation and bills their work (§4.6, §6.9); 4 for one that also prices bytes out, a package's work and its storage by byte-time (§4.7); 5 for one that holds a decode to its frames (§4.8); 6 for one that also prices a job per endpoint and by a third party's usage, and bills an upscale and a tone mapping (§4.9); 7 for one that also prices a transmission per bearer class, unit and ceiling (§4.10), an aggregated impression (§4.11) and a consumed object (§4.12); 8 for one that also prices storage held over time (§4.13); 9 for one that may follow another tariff, its chain continuing that tariff's (§4.14) |
|
||
| `seller` | 32 | the seller's key, which signs the tariff and every invoice under it |
|
||
| `buyer` | 32 | the buyer's key, which accepts the tariff by signing it |
|
||
| `start`, `end` | 8 each | u64: the period the tariff is good for |
|
||
| `currency` | 3 | three capitals `A`–`Z` (ISO 4217) |
|
||
| `room` | 52, in version 4 56 | thirteen u32: millionths of a minor unit per second of `publisher_us`, of `subscriber_us` for each layer class 0 to 8, of `composition_us` and of `recorded_us`, and per event sent (live-metering §4.1's order); in version 4 a fourteenth, per 10^9 bytes of `bytes_out` (§4.7) |
|
||
| `delivery` | 32 | four u64: millionths of a minor unit per 10^9 acknowledged bytes of each object class, in class order (settlement §7.1) |
|
||
| `package` | 24, in version 4 8 | three u64: millionths of a minor unit per package receipt, per entry, and per 10^9 stored bytes; in version 4 one, per 10^9 byte-days held (§4.7) |
|
||
| `ads` | 16 | two u64: millionths of a minor unit per presented impression, and per billable impression |
|
||
| `job` | 2 + Σ (18 + *c*), in versions 3 and 4 2 + Σ (19 + *c* + *o*), in version 6 2 + Σ (21 + *c* + *o* + *e* + *u*) | versions 2 to 4, absent in version 1: a u16 count *j*, then each job price (§4.5, §4.6, §4.9): `cap_len` (u8), `capability` (`cap_len` bytes), in versions 3 and 4 `op_len` (u8) and `operation` (`op_len` bytes), in version 6 `end_len` (u8) and `endpoint` (`end_len` bytes), then `unit` (u8), in version 6 `use_len` (u8) and `usage` (`use_len` bytes), then `divisor` (u64) and `price` (u64) |
|
||
| `transmission` | 1 + 18 × *t* | version 7, absent before: a u8 count *t*, then each transmission price (§4.10): `bearer` (u8), `unit` (u8), `max_bps` (u64) and `price` (u64) |
|
||
| `aggregated` | 8 | version 7, absent before: u64, millionths of a minor unit per aggregated impression (§4.11) |
|
||
| `consumption` | 8 | version 7, absent before: u64, millionths of a minor unit per object an agent consumed (§4.12) |
|
||
| `storage` | 8 | version 8, absent before: u64, millionths of a minor unit per 10^9 byte-days of storage a holder kept (§4.13) |
|
||
| `follows` | 32 | version 9, absent before: the digest of the tariff whose chain this one continues (§4.14), or zero for none |
|
||
| `scope` | 2 + 33 × *n* | a u16 count *n*, then each entry: `kind` (u8) and `id` (32), in strictly ascending order of (`kind`, `id`) |
|
||
| `seller_sig` | 64 | §4.2 |
|
||
| `buyer_sig` | 64 | §4.2 |
|
||
|
||
### 4.2 Digest and signatures
|
||
|
||
The **digest** of a tariff is SHA-256 over its bytes before `seller_sig`, the **body**. Its
|
||
`seller_sig` is Ed25519 by `seller` over the 18 bytes `wai:ledger-tariff` (ASCII) and 0x01,
|
||
followed by the body; its `buyer_sig` is Ed25519 by `buyer` over the 18 bytes `wai:ledger-accept`
|
||
(ASCII) and 0x01, followed by the body. Both are verified strictly, as [SPEC](../SPEC.md) §7
|
||
*Signatures* requires: a key that fails step 1 or 2 is `bad_key`, and a signature that fails a
|
||
later step is `bad_signature`. The buyer's signature is what binds the buyer to the prices: a
|
||
tariff the buyer did not sign bills nobody.
|
||
|
||
### 4.3 Reading and rules
|
||
|
||
A reader reads exactly the bytes it is given as one tariff, in the order of §4.1, and refuses at
|
||
the first of these that holds: fewer than 4 bytes, `truncated`; a magic other than `WLT1`,
|
||
`malformed`; no fifth byte, `truncated`; a version other than 1 to 9, `unknown_version`; the
|
||
bytes end before a field the layout requires, `truncated`; bytes after `buyer_sig`, `malformed`.
|
||
It then refuses as `tariff_invalid` a tariff that breaks any of these:
|
||
|
||
- `start` is below `end`; `currency` is three capitals `A`–`Z`;
|
||
- `seller` and `buyer` are not zero, and not the same key;
|
||
- `scope` has at least one entry, in strictly ascending order of (`kind`, `id`), each `kind` 1 to
|
||
4 (1 to 5 in versions 2 to 6, 1 to 8 in version 7, 1 to 9 in versions 8 and 9) and each `id` not
|
||
zero;
|
||
- in version 2, `job` has at most 255 prices, each as §4.5 requires, in strictly ascending
|
||
order of (`capability`'s bytes, `unit`); in versions 3 and 4, at most 255, each as §4.6
|
||
requires, in strictly ascending order of (`capability`'s bytes, `operation`'s bytes, `unit`);
|
||
each `unit` 1 or 2, and in version 4 1 to 3;
|
||
- in version 6, at most 255, each as §4.9 requires, in strictly ascending order of
|
||
(`capability`'s bytes, `operation`'s bytes, `endpoint`'s bytes, `unit`, `usage`'s bytes), each
|
||
`unit` 1 to 4; and no price of any endpoint beside a price of one for the same `capability`,
|
||
`operation`, `unit` and `usage` (§4.9);
|
||
- in version 7, `transmission` holds prices each as §4.10 requires, in strictly ascending order of
|
||
(`bearer`, `unit`, `max_bps`), and `aggregated` and `consumption` are each at most 2^53 − 1;
|
||
- in versions 8 and 9, `storage` is at most 2^53 − 1.
|
||
|
||
Then the seller's signature, then the buyer's: `bad_key`, `bad_signature`.
|
||
|
||
### 4.4 Scope
|
||
|
||
A scope entry names whose records the tariff bills:
|
||
|
||
| kind | `id` | a source is in scope when |
|
||
|---|---|---|
|
||
| 1 | a room id | a room-session receipt's `room` is the `id` |
|
||
| 2 | a party's key | a settlement statement's `party` is the `id` |
|
||
| 3 | a packager's key | a package receipt's `signer_pubkey` is the `id` |
|
||
| 4 | an ad decider's or a stitcher's key | every receipt of an ads source has `signer_pubkey` the `id` (live-ads §3.4); a stitched source's records are accepted only when their `signer` is such an `id`: the verifier's **signers** (stitched-presentation §7.1) are the scope's entries of kind 4 |
|
||
| 5 | a router's key (versions 2 to 4) | a job source's route record has `signer` the `id` (route-record §5.1) |
|
||
| 6 | a publisher's or a node's key (version 7) | a group source's group receipt has `signer_pubkey` the `id` (jwp-receipts §2.4.1); a cache source's claims do |
|
||
| 7 | a collector's key (version 7) | an aggregated source's receipt has `signer` the `id` (telemetry-aggregation §7.1) |
|
||
| 8 | an agent's key (version 7) | a consumption source's claims have `signer_pubkey` the `id` (ai-usage §6.1) |
|
||
| 9 | a holder's key (version 8) | a storage source's record has `holder` the `id` (§4.13) |
|
||
|
||
The scope is what the buyer agreed to pay for: a record signed by a party the tariff does not name
|
||
is refused `outside_scope` (§7.2 step 5), whoever submits it.
|
||
|
||
### 4.5 Job prices (version 2)
|
||
|
||
A tariff of version 2 prices the media jobs a router routed and a hop served. A **job price**
|
||
is a `capability` (route-record §2: 1 to 128 bytes, lowercase ASCII letters, digits, `_` and
|
||
`.`, beginning `wai.`), a `unit`, a `divisor` of at least 1 and a `price`: millionths of a
|
||
minor unit per `divisor` units of the unit, for a job whose serving hop served that capability.
|
||
The units are the records' own figures, never converted:
|
||
|
||
| `unit` | name | a job's quantity |
|
||
|---|---|---|
|
||
| 1 | `jobs` | 1 |
|
||
| 2 | `subpixels` | the sum of its output receipts' `work_pixel_ops` (integer-payloads §15.1): the subpixels its output decodes to |
|
||
| 3 | `work_units` (version 4) | the sum of its output packages' `work_units` (packaging §9.1, §4.7) |
|
||
| 4 | `usage` (version 6) | what its billed hop's third-party record states the provider bills, in the price's own unit (§4.9) |
|
||
|
||
A job the tariff has no price for, by its serving capability, is billed nothing, and a buyer
|
||
pays for a capability only at a price it signed. A package job stays a package source (§5.1),
|
||
billed by §4.1's package prices.
|
||
|
||
### 4.6 Job prices per operation (version 3)
|
||
|
||
A tariff of version 3 prices jobs as §4.5 does, and each job price also names an `operation`:
|
||
an operation of WAI's catalogue in route-record §2's form (two words joined by `.`, each a
|
||
lowercase ASCII letter and then lowercase letters and digits: `media.encode`, `media.decode`),
|
||
of at most 128 bytes. A job is priced by its serving capability **and** its operation, which is
|
||
its route record's `operation`, the one its request named (route-record §5.1). The reason is the
|
||
work: within one capability, an encode (a motion search, then a codestream written) and a
|
||
decode (a reconstruction) spend different energy and compute for the same output units, so one
|
||
price per capability overprices one of them or underprices the other, and a buyer pays each at
|
||
the price it signed for it. A job the tariff has no price for, by its serving capability and its
|
||
operation, is billed nothing, as a job whose capability a tariff does not price is (§4.5): a
|
||
price for one operation never bills another.
|
||
|
||
Version 3 is a version of its own, not a change to version 2: a reader of version 2 cannot read
|
||
a job price that names an operation, and the buyer of a version-2 tariff signed version 2's
|
||
rules. Version 3 also bills a job's work rather than its output's identity (§5.2, §5.3, §6.9).
|
||
A tariff of version 2, its invoices and its sources read, verify and bill exactly as before.
|
||
|
||
### 4.7 Bytes, work and storage (version 4)
|
||
|
||
A tariff of version 4 prices jobs as version 3 does, and prices three more things by what
|
||
spending on them scales with:
|
||
|
||
1. **A room's bytes out.** Its fourteenth room price is per 10^9 bytes of a room-session
|
||
receipt's `bytes_out`, the payload bytes the hops sent the session's sessions, summed from
|
||
their ledgers (live-metering §4.4, a receipt of version 2). A room's time units price how
|
||
long its sessions ran; what delivering them costs scales with the bytes carried too, and a
|
||
viewer of a high layer and one of a low layer subscribe for the same seconds and are sent
|
||
different bytes. The receipt states the price in its own tariff and counts it in each
|
||
grant's funds (live-metering §4.6), so a receipt that states a tariff states this one's
|
||
fourteen prices (§3). A receipt of version 1 states no bytes, and bills none. An egress
|
||
that serves the room over HTTP is a hop of the room (live-metering §3.12): the bytes it
|
||
answered are in its ledger, so the receipt's `bytes_out` bills them beside the relays', at
|
||
this price, and no source of another kind states them.
|
||
2. **A package's work, per run.** Packaging is deterministic: the same source packed again under
|
||
the same policy gives the same package, under the same receipt, from a run that did the work
|
||
again with new energy (a customer asks for the work to be done and measured again). So a
|
||
package is billed as a job is (§6.9): the **run** that made it is the work, and its receipt is
|
||
the product, which each run that made it cites. Billing once per receipt refused a package
|
||
made again, though the work was done again. A run is a job of the catalogue's operation
|
||
`package.build`, routed and receipted as any job is (route-record §6): a `job` source whose
|
||
output is the package (§5.1), billed at the tariff's job prices for its serving capability
|
||
and `package.build`, per job and per **work unit**: the package receipt's `work_units`, the
|
||
work its figure is expressed against (packaging §9.1, jwp-receipts), one per entry, each a
|
||
base or a refinement the packer coded and wrote, so a price per unit bills what the run
|
||
spent in proportion to its size. The chain bills each run's route record and hop receipts
|
||
once, and a run replayed under a new route record is refused (`record_rebilled`,
|
||
`record_duplicate`), as any job's; the package receipt (kind 5) is not billed once, and is
|
||
cited by each run's line. The run's energy is its hop's figure (§6.6), and the receipt's own
|
||
figure, the same work's, is not stated again. A `package` source is the product held: it
|
||
bills its storage alone (below), never its work, which only a run states.
|
||
3. **A package's storage, by byte-time.** Its one package price is per 10^9 **byte-days**:
|
||
what keeping bytes costs scales with how many are kept and for how long, which a price per
|
||
stored byte once per receipt ignores. A package whose receipt the previous invoice of the
|
||
chain lists is **held** through the invoice's whole period: it was written by the end of
|
||
that invoice's period, at most this one's `start`. The invoice bills it ⌊Σ `stored_bytes` ×
|
||
(`end` − `start`) / 86 400 000 000⌋ byte-days over its packager's held packages, the
|
||
period in microseconds and rounded down once per line, and lists its receipt again. The
|
||
invoice that first lists a package bills no storage for it: no record shows when within that
|
||
period it was written, and a buyer pays only for time a record shows the bytes were kept. The period is read from the chain itself, its invoices'
|
||
`start` and `end`, which the seller signs and the buyer holds (§6.9), and the bytes from
|
||
the package receipt.
|
||
|
||
A version-3 reader cannot read a tariff of version 4 (its room prices are one longer and its
|
||
package prices two shorter, and a job price may be of unit 3) or an invoice of version 4 (§6.1:
|
||
it states a sixth unmetered count), so version 4 is a version of its own. A tariff of versions
|
||
1 to 3, its invoices and its sources read, verify and bill exactly as before.
|
||
|
||
### 4.8 A decode's output (version 5)
|
||
|
||
A tariff of version 5 is version 4's in its layout (§4.1), its rules (§4.3), its scope and its
|
||
prices (§4.4 to §4.7), and an invoice of version 5 is version 4's (§6.1); each bills what
|
||
version 4 bills. Where this text says version 4, or a range of versions ending at 4, version 5
|
||
is included, except as this section says.
|
||
|
||
A decode (a job whose route record's `operation` is `media.decode`) delivers its
|
||
**reconstruction**, not a codestream: the codestream is what it read. Version 4 gives every
|
||
`int_motion` output as its receipt and its `codestream` and holds the codestream to what the hop
|
||
delivered (§5.1), which is true of an encode and false of a decode, whose hop would have to state
|
||
an object it never delivered and commit its receipt to it (route-record §5.2, §6). Under a tariff
|
||
of version 5 a decode's output is held to what it delivered:
|
||
|
||
1. Each output of a decode's job source is an object of exactly `receipt` (the text of a
|
||
`wai.video.int_motion` decode receipt's JSON form, integer-payloads §15.2), `codestream` (the
|
||
`WIV1` payload the decode read, hex) and `frames` (one animated PNG holding its frames, hex).
|
||
The receipt is read by integer-payloads §15.2 and re-derived from the codestream (§15.1 there):
|
||
the codestream is the decode's input, and the receipt is the evidence of what it decodes to.
|
||
2. The animation is read whole first: its chunks as packaging §5 reads a still's (every chunk's
|
||
type four letters and its CRC checked; `IHDR` first, of 8-bit RGB without interlace; an
|
||
optional `PLTE` before the image data; the `IDAT`s consecutive; ancillary chunks read past;
|
||
any other critical chunk refused; `IEND` last, empty, and nothing after it), and the chunks
|
||
of PNG's third edition that make it an animation:
|
||
- one `acTL` of 8 bytes, before any `fcTL` and the image data, counting at least one frame,
|
||
and as many `fcTL`s as it counts;
|
||
- each `fcTL` of 26 bytes, of the whole picture (its width and height `IHDR`'s, its offsets
|
||
0), its dispose operation 0 to 2 and its blend operation 0, any delay;
|
||
- the first `fcTL` before the `IDAT`s, so the default image is the first frame, and every
|
||
other after them, followed by at least one `fdAT` before the next `fcTL` or `IEND`; no
|
||
`IDAT` but the first frame's, and no `fdAT` of it;
|
||
- the sequence numbers of the `fcTL`s and `fdAT`s 0, 1, 2, … in their order, and every
|
||
`fdAT` at least 4 bytes long.
|
||
|
||
It is of the receipt's `w` × `h` and holds as many frames as the receipt has. Then each frame,
|
||
in order: its data (the `IDAT`s' for the first frame, its `fdAT`s' after their sequence
|
||
numbers for each other, concatenated) is read as packaging §5 reads a still's image data, and
|
||
the frame hash of its samples at its index (integer-payloads §15.1: BLAKE3 over
|
||
`wai:video-rframe`, 0x01, the index as a u64 and the RGB8 bytes) is the receipt's frame at
|
||
that index. Otherwise the source is refused `output_invalid`: at `outputs`, the output's
|
||
index and `frames` where the animation breaks a rule above or differs in size or count; at
|
||
`outputs`, the output's index, `frames` and the frame's index where that frame's data is not
|
||
the picture's rows or its samples are not the receipt's; and at `outputs` and the output's
|
||
index when the receipt or the codestream does not hold.
|
||
3. The objects the served attempt states it delivered (route-record §5.2) are exactly the
|
||
decode's animations, by content hash, in the order of its outputs, and nothing else: an
|
||
animation not stated at its place is refused `output_not_delivered` at `outputs`, the
|
||
output's index and `frames`, and an object stated past the last, the codestream among them,
|
||
at `outputs`. Under a route record of version 3 an animation is at its place when its proof
|
||
holds it there (§5.1, its `index` its place), and there is none past the last when the
|
||
attempt's `count` is the number of animations.
|
||
|
||
A decode delivers its frames as one object because a clip's frames are many and repeat: a route
|
||
record states each of a hop's outputs once, and at most 1024 of them (route-record §5.2), while
|
||
a clip runs to thousands of frames and a still scene decodes to the same frame again and again.
|
||
An animated PNG is lossless, one file every browser plays and any tool splits into stills, and
|
||
its default image is its first frame, which packaging §5's reader of a still reads. The frame
|
||
hash, not the PNG's bytes, is what the receipt binds, so any writer's animation of the right
|
||
samples holds; the reference writer is `png_still::encode_animation`. A frame is the whole
|
||
picture and its samples replace the picture's, so they are its data alone: a frame blended over
|
||
the one before, or of part of the picture, would be held to samples its data does not hold.
|
||
|
||
A decode's billed subpixels are its receipts' `work_pixel_ops` (§6.3), as in version 4: the
|
||
receipt states what the frames hold. An encode, and every other job, is held as in version 4.
|
||
A version-4 reader would read a decode's `frames` as an unknown member and refuse the source, and
|
||
a version-4 verdict on a decode must not change under it, so version 5 is a version of its own.
|
||
A tariff of versions 1 to 4, its invoices and its sources read, verify and bill exactly as
|
||
before.
|
||
|
||
### 4.9 An endpoint, a third party's usage, and what re-derives an output (version 6)
|
||
|
||
A tariff of version 6 is version 5's in its layout but for its job prices (§4.1), in its rules
|
||
but for theirs (§4.3), and in its scope and prices (§4.4 to §4.8), and an invoice of version 6 is
|
||
version 5's (§6.1) but for the records it may list; each bills what version 5 bills. Where this
|
||
text says version 4 or 5, or a range of versions ending at either, version 6 is included, except
|
||
as this section says.
|
||
|
||
**A job price names an endpoint.** Its `endpoint` is the endpoint of the attempt it prices, a
|
||
token of route-record §2's form, or empty, which prices every endpoint. Two providers of one
|
||
capability have different list prices, so one price per capability overprices one or underprices
|
||
the other, and a buyer pays each at the price it signed for it. A job is priced as §4.6 prices it
|
||
and, where a price names an endpoint, by its billed hop's. A price of any endpoint beside a price
|
||
of one, for the same capability, operation, unit and usage, would bill one job at both, so a
|
||
tariff that has both is `tariff_invalid`: its seller states one price for every endpoint or a
|
||
price for each.
|
||
|
||
**A third party's usage.** A job price of unit 4 names `usage`, a unit of route-record §2's form,
|
||
and of any other unit none. A job source may give `third_party`, a list of third-party hop
|
||
records' texts, which route-record §7.2 step 9 verifies with the rest of its document, a refusal
|
||
there being the source's. Each record contributes itself (§5.2, kind 17). A job's quantity at a
|
||
price of usage is the `usage.quantity` of its billed hop's record, when that record's `usage.unit`
|
||
is the price's `usage`, and otherwise none:
|
||
|
||
- a job given no record bills nothing at a price of usage, and bills by its other units;
|
||
- a failed hop's record, and a late hop's, state what the provider billed for it, which is what
|
||
the router's operator owes the provider, and no line reads it: only the billed hop's usage
|
||
reaches a line, as §5.1 holds a failed hop's figures from a line;
|
||
- a record's `charge` reaches no line. It is the provider's own figure in its own terms, and a
|
||
line adds jobs, so it cannot be summed. The line cites the record, which states it signed, so a
|
||
buyer reads the two side by side.
|
||
|
||
A third party's output has no WAI receipt, and a job it served gives no output receipt for it: its
|
||
record names the objects, and the route record holds them to the hop (route-record §6.2).
|
||
|
||
**An upscale.** A job whose route record's `operation` is `media.upscale` gives each output as an
|
||
object of exactly `upscale` (the text of an upscale record, exact-upscale §4.2), `object` (the
|
||
input: a `WAI1` of capability `wai.image.png` holding a PNG of 8-bit RGB that packaging §5's reader
|
||
reads, hex), `prior` (the `WSR1` it names, hex) and `picture` (the object the hop delivered: a PNG
|
||
that reader reads, hex). The record is verified by exact-upscale §7 under `require-proof`, holding
|
||
the input, its samples and the prior, and the picture is of the size the record's output is, with
|
||
the samples whose digest is its `output`. So what is billed is what the derivation gives: the
|
||
record's subpixels are the output's width × height × 3, the record contributes itself by its link
|
||
hash (§5.2, kind 18), and the picture is its object (§5.1). No residual is given, so a record that
|
||
names one is not proved here. Otherwise the source is refused `output_invalid`: at `outputs`, the
|
||
output's index and `object` where the input does not read so; at `outputs`, the output's index and
|
||
`picture` where the picture does not read or is not the output; and at `outputs` and the output's
|
||
index where the record does not read or is not proved.
|
||
|
||
**A tone mapping.** A job whose route record's `operation` is `media.tonemap` gives each output as
|
||
an object of exactly `tonemap` (the text of a rendition record, exact-tonemap §7.1), `envelope`
|
||
(the `WAI2` it read, hex) and `renditions` (each picture's rendition, its `RGB16` bytes, exact-tonemap
|
||
§2, in the record's order, hex), and under a route record of version 3 `proofs`, in place of
|
||
`proof`: one inclusion proof for each rendition (route-record §6.1). The record is verified by
|
||
exact-tonemap §8 under `require-proof`, holding the envelope and no decoded frame, so what is proved
|
||
is a still's pictures, and a record of a video's frames is refused. There is one rendition for each
|
||
picture, whose digest is the picture's `output`. So the record's subpixels are its pictures × width
|
||
× height × 3, and it contributes itself by its link hash (§5.2, kind 19). Otherwise the source is
|
||
refused `output_invalid`: at `outputs`, the output's index, `renditions` and the rendition's index
|
||
where a rendition is not its picture's; at `outputs`, the output's index and `renditions` where
|
||
their number is not the record's; and at `outputs` and the output's index where the record does not
|
||
read or is not proved. Each rendition is an object the hop delivered, and none is another output's
|
||
(§5.1): otherwise `output_not_delivered`, at `outputs`, the output's index, `renditions` and the
|
||
rendition's index. Two pictures of one record may render one picture: the hop states that object
|
||
once (route-record §5.2), and both are billed, since the record states and proves both.
|
||
|
||
A job of either operation gives its outputs in that form alone, and any other form is `malformed`.
|
||
A job's `subpixels` (§4.5) sum its output receipts' `work_pixel_ops` and these records' subpixels.
|
||
These records are the evidence of what a job delivered, as an output receipt is (§6.9): the
|
||
derivations are exact, so a run of the same request delivers the same picture, and a later invoice
|
||
may cite a record again for a new hop's work. Each is a record of the signer that made it, and what
|
||
its figure rests on is the derivation, which any holder of the source recomputes.
|
||
|
||
A version-5 reader cannot read a job price that names an endpoint, a job source's `third_party`,
|
||
these outputs or kinds 17 to 19, so version 6 is a version of its own. A tariff of versions 1 to 5,
|
||
its invoices and its sources read, verify and bill exactly as before.
|
||
|
||
### 4.10 A transmission on a shared bearer (version 7)
|
||
|
||
A tariff of version 7 is version 6's in its layout but for three fields after `job` (§4.1), in its
|
||
rules but for those fields' and its scope's (§4.3), and in its prices (§4.4 to §4.9), and an invoice
|
||
of version 7 is version 6's (§6.1) but for its seventh unmetered count and the records, lines and
|
||
rows of this section and §4.11 and §4.12; each bills what version 6 bills. Where this text says version 6, or a range of
|
||
versions ending at 6, version 7 is included, except as this section says.
|
||
|
||
**What it prices.** A publisher that sends a group over a `multicast` or `unidirectional` bearer
|
||
instance sends it once to every receiver that joins, and learns nothing of who received it
|
||
(bearer-receipts §2, §3): what the sending spends scales with the octets its passes carry and the
|
||
time they take, and no record states a quantity per receiver. A tariff of version 7 prices that
|
||
**transmission** in the two units a schedule states (carousel §4.1, §5.4): `bytes_sent`, the octets
|
||
an entry's passes send, per 10^9 octets, and `pass_us`, the microseconds of its passes, `count` ×
|
||
`duration_ms` × 1000, per 10^6 microseconds. They are rung-price §4.3's transmission units, with its
|
||
divisors and bounds.
|
||
|
||
**A price for each bearer class, unit and ceiling.** Its `transmission` field holds at most 255
|
||
**transmission prices**, 18 bytes each: `bearer` (u8), 2 `multicast` or 3 `unidirectional`,
|
||
bearer-receipts §2's classes in their order from 1; `unit` (u8), 1 `bytes_sent` or 2 `pass_us`;
|
||
`max_bps` (u64), the **ceiling**, from 1 to 2^53 − 1 bits per second; and `price` (u64), millionths of
|
||
a minor unit per the unit's divisor, at most 2^53 − 1. They are in strictly ascending order of
|
||
(`bearer`, `unit`, `max_bps`), so a class, a unit and a ceiling have one price. A `bidirectional`
|
||
bearer reaches each receiver over its own path and is priced per receiver, by the room and delivery
|
||
prices, so it has none here. A rung-price list's entry of a transmission unit transcribes into one
|
||
exactly: its bearer, unit, `max_bps` and `price` (rung-price §4.2, §4.3, §7.1).
|
||
|
||
**The tier.** An entry of a standing schedule (carousel §6.2 step 4) has a **pass rate** of ⌈8000 ×
|
||
*P* / `duration_ms`⌉ bits per second, *P* = `bytes_sent` / `count` the octets one pass sends,
|
||
computed in integers wide enough not to overflow (rung-price §7.2). In each unit it is billed at the
|
||
price of its instance's declared class and that unit whose ceiling is the least at or above its
|
||
pass rate: the seller's tier that covers it, which the buyer signed. An entry whose pass rate is
|
||
above every ceiling of its class and a unit has no price in that unit and bills nothing in it, and
|
||
the report states so (§8.3). So a line at another price of the class and unit, whether at a ceiling
|
||
below the rate or at one above the least that covers it, states a quantity no record gives at that
|
||
price, and is refused (§7.2 step 7).
|
||
|
||
**The source.** A `group` source (§5.1) is a group receipt, the object receipts given under it, and
|
||
its publisher's transmission and schedule claims about it (bearer-receipts §4, carousel §4) in their
|
||
chain's order, with `parent`, the text of the claim the first one's `parent_receipt_hash` names, or
|
||
`null` when the first is the head of its chain. A publisher's claims about all its groups are one
|
||
chain (jwp-receipts §2.4.3), so each group's source names the claim before its own. It is verified as
|
||
carousel §6.2 steps 1 to 4 verify a group and its claims: the group by jwp-receipts §3 steps 1 and
|
||
2; each object receipt against it by steps 4 to 6 with its envelope and step 5 without; `parent` by
|
||
jwp-receipts §3.1 steps 1 to 4, then held as its signer's previous claim; each claim by §3.1 steps 1
|
||
to 5, then step 6, a transmission claim by bearer-receipts §4.3 and a schedule by carousel §4.3, a
|
||
claim of another class being `context_mismatch`; then the declarations and the schedules that stand
|
||
(bearer-receipts §6.2 step 4, carousel §6.2 step 4), an instance's schedule being the last of a run
|
||
each of which extends the one before it (carousel §4.5). It is accepted only when all of them are
|
||
and no claim is set aside: otherwise it is refused with the first refusal's reason, at `group`, at
|
||
`objects` and the receipt's index, at `parent`, or at `claims` and the claim's index, and a claim set
|
||
aside with the reason it is set aside for, at the first such claim. A plan set aside is one the
|
||
publisher did not hold to, and a source billed in part would bill what it chose.
|
||
|
||
An entry is billed from the instance's last schedule alone: each schedule that one extends is its
|
||
first passes (carousel §4.5), and is cited beside it. A schedule that extends one a chain has billed
|
||
bills no pass twice, since its first pass is in a period already billed and it is in no later one
|
||
(§5.3). So the passes such a schedule adds are billed by no invoice of the chain, and neither is a
|
||
schedule whose passes cross a period's end: a schedule is billed whole, in the period that holds it,
|
||
and a seller sets its periods to hold the plans it bills.
|
||
|
||
**What it contributes.** Its group receipt (kind 20) by its link hash (jwp-receipts §3 step 3), and
|
||
each transmission claim (kind 21) and schedule claim (kind 22) by its link hash. Each instance it
|
||
declares states its energy once, in scope 7 (§6.6): its declaration's `energy`, the publisher's
|
||
figure of transmitting the group on that instance, every repetition included (bearer-receipts
|
||
§4.1), or the unmetered marker for `null`. Two declarations of one instance with one body are one,
|
||
and state the figure once; a declared instance with no schedule bills nothing and states its
|
||
figure. A bearer instance is one transmission (bearer-receipts §2), so its declaration and its
|
||
schedule are billed once in a chain, no two sources of an invoice declare one instance of a group
|
||
(§5.2), and the group receipt is the evidence each transmission of the group cites, listed again by
|
||
an invoice that bills the group sent on a new instance (§6.9).
|
||
|
||
**A cache's own instance.** A node that re-sends, over an instance of its own, objects it holds of a
|
||
group another key signed declares the instance in a `cache-transmission` claim (cache-authority §5),
|
||
may state its plan in a schedule of its own (§5.6 there), and states the bytes of the sending in a
|
||
declaration of version 2 naming that claim (settlement §4.4). A `cache` source (§5.1) is the group,
|
||
the object receipts given under it, the node's claims in their chain's order with `parent`, and those
|
||
declarations. It is verified as cache-authority §7.2 steps 1, 2 and 4 verify a group and a node's
|
||
claims: each cache-transmission claim by §5.3 there, each schedule by §5.6 there, and the instances
|
||
and schedules that stand as §7.2 step 4 and §5.6 say, every claim the same node's, never the group's
|
||
key, and a claim of another class or key being `context_mismatch`, a group source given such a claim
|
||
refuses it the same way. Each declaration reads (settlement §3.6, with that text's reasons), is of
|
||
version 2, its `upstream` the node and its `instance` the link hash of a claim the source gives,
|
||
otherwise `context_mismatch`, at `declarations` and its index. An instance with an entry to bill and
|
||
no declaration naming its claim is refused `record_missing`, at that claim. A cache-transmission
|
||
claim says what was sent and a schedule what was planned, so an entry is billed only when the
|
||
claim's bit of its `leaf_index` is set (cache-authority §7.2 step 6): an object scheduled and not sent
|
||
bills nothing. It is billed as a publisher's is, at the transmission prices of the instance's class,
|
||
in the octets and pass time its schedule states, on lines whose `source` is the node. No line reads a
|
||
declaration's bytes, which count objects and not their passes: a declaration is the node's statement
|
||
that it made the sending, in a window the period holds, and bounds no quantity. The source
|
||
contributes its claims (kind 23), its schedule claims (kind 22), its declarations (kind 4), each of
|
||
those billed once, and the group receipt (kind 20), which any number of transmissions cite, so a
|
||
publisher's transmission of a group and a node's own instance of it can be on one invoice. The
|
||
claim's `energy` is stated in scope 7 as a declaration's is.
|
||
|
||
**An instance is one party's.** A cache source holds the node's claims alone, so cache-authority §7.2
|
||
step 4's rule that an instance a publisher declared is no node's own reaches what a verifier is given
|
||
beside them: a cache source and a group source of one group that declare one `bearer_id` on one
|
||
invoice are refused `bearer_contradicted` at the later of them, and so are two cache sources of two
|
||
keys that do (§5.2, §7.2 step 6). A verifier given only the node's claims is shown no declaration of
|
||
the publisher's, and accepts them. The reference ledger holds every source of a chain and applies the
|
||
rule across them (§9), and a buyer that holds the publisher's claims runs cache-authority §7.2 over
|
||
both.
|
||
|
||
**Transmission, not delivery.** A transmission line bills what a publisher or a node declared it
|
||
sent, in the octets and the pass time its own schedule planned. It states nothing of any receiver: no
|
||
line reads a reconciliation (bearer-receipts §5) or a count of receivers, and a transmission line
|
||
**MUST NOT** be presented as delivery to anyone (bearer-receipts §6.3, rung-price §7.3).
|
||
|
||
### 4.11 An aggregated impression (version 7)
|
||
|
||
An impression counted over a bearer with no return path is the class **aggregated**
|
||
(impression-aggregates §9): a lower bound of what receivers reported, which no presentation claim
|
||
stands behind. It is priced in a unit of its own, `aggregated_impressions`, at the tariff's
|
||
`aggregated` price per impression, and never under `presented_impressions` or
|
||
`billable_impressions`: an invoice that states such a count under either is refused
|
||
`quantity_not_recorded` (§7.2 step 7), since no source gives that line.
|
||
|
||
An `aggregated` source (§5.1) is one aggregate receipt, `WQA1` (telemetry-aggregation §7). A verifier
|
||
reads it as data, in this order: the receipt reads (§7.2 there, at `receipt`); its `signer` is the
|
||
**collector**, whose signature verifies (`bad_key`, `bad_signature`, at `receipt`); its `task` reads
|
||
through `time_precision` (DAP §4.2), the unit its batch is stated in, which is not 0 (`task_invalid`,
|
||
at `task`); the leader's statement reads whole (`statement_invalid`, at `leader`, §6.1 there), has the
|
||
leader's role, 2 (`wrong_signer`, at `leader`, §8.1 step 5 there), and states a batch of a duration of
|
||
at least 1 (`batch_invalid`, at `leader`, §8.1 step 7 there); and the elements of `result`, summed as
|
||
integers, are its report count (`count_mismatch`, at `result`). Its **count** is that sum. Then, at
|
||
§7.2 step 5, the tariff names the collector in its scope (kind 7), so the buyer chose whose count it
|
||
pays on. A holder of the receipt and its catalogue verifies it further by impression-aggregates §8.1,
|
||
and a verifier of this extension runs no other step of that text: the receipt's count is the
|
||
collector's word to the buyer that named it.
|
||
|
||
The source contributes its receipt (kind 24) by its digest (telemetry-aggregation §7.1), and one
|
||
line of the collector's, its quantity the sum of the counts of its receipts, citing each. A receipt
|
||
is billed in the period that holds its batch (§5.3), and a chain's periods do not overlap, so a chain
|
||
bills it once, and a verifier needs no invoice but the one it is given to see that. Two receipts of
|
||
one task, by their `task` bytes, whose batches share a time unit are refused: DAP collects a bucket
|
||
once, and an impression table sets both aside (impression-aggregates §8.2). On one invoice the later
|
||
is `record_overlap` (§5.3); on two invoices of a chain one of them is `outside_period`, since one
|
||
period alone holds that time unit. A count states no energy (impression-aggregates §9), so the
|
||
source states no figure. Its line is a count of reports: it is no audience, and a party that shows
|
||
an invoice beyond the holders of its receipts holds it to impression-aggregates §8.3, a line being a
|
||
sum over a table's rows.
|
||
|
||
### 4.12 An object an agent consumed (version 7)
|
||
|
||
An agent's use of objects is stated in a consumption claim (ai-usage §6), which the agent signs. A
|
||
tariff of version 7 prices it per object, at its `consumption` price, in the unit `consumed_objects`.
|
||
|
||
A `consumption` source (§5.1) is an agent's claims, at least one, in their chain's order, with
|
||
`parent`, the text of the claim the first one's `parent_receipt_hash` names, or `null`, read as a
|
||
group source's `parent` is. Each claim is verified by jwp-receipts §3.1 steps 1 to 5, at `claims` and
|
||
its index, and held to the chain by step 5; a claim of another class, or of a key another claim of
|
||
the source does not have, is `context_mismatch`. Step 6, ai-usage §6.3, needs the objects, their
|
||
statements and the room, which the ledger does not hold: a holder of them runs it, and its outcome
|
||
bills nothing and refuses nothing here. A claim refused at that step is still its signer's statement
|
||
of what it consumed (ai-usage §6.4). The tariff names the agent in its scope (kind 8), so the buyer
|
||
pays on the word of an agent it named.
|
||
|
||
The source contributes each claim (kind 25) by its link hash, and a line of the agent's, its quantity
|
||
the objects its claims name, one for each object of each claim, an object named by two claims being
|
||
two uses, citing each claim. A chain bills a claim once. A claim states no energy, so the source
|
||
states no figure.
|
||
|
||
A version-6 reader cannot read a tariff with a `transmission`, `aggregated` or `consumption` field or
|
||
a publisher, a collector or an agent in its scope, a `group`, `cache`, `aggregated` or `consumption`
|
||
source, kinds 20 to 25 or an invoice's seventh unmetered count, so version 7 is a version of its own.
|
||
A tariff of versions 1 to 6, its invoices and its sources read, verify and bill exactly as before.
|
||
|
||
### 4.13 Storage held over time (version 8)
|
||
|
||
A tariff of version 8 is version 7's in its layout but for one field after `consumption` (§4.1), in
|
||
its rules but for that field's and its scope's (§4.3), and in its prices (§4.4 to §4.12), and an
|
||
invoice of version 8 is version 7's (§6.1) but for the records, lines and report of this section;
|
||
each bills what version 7 bills. Where this text says version 7, or a range of versions ending at 7,
|
||
version 8 is included, except as this section says.
|
||
|
||
**What it prices.** A holder that keeps objects for a buyer beyond their delivery, a stream's recent
|
||
window a player seeks back into or a clip cut from it and kept, spends on the bytes it keeps and on
|
||
how long it keeps them. No record this text reads states that: a package receipt states a package's
|
||
bytes and no time (§4.7), and a window's objects change with each one admitted and each one evicted.
|
||
A tariff of version 8 prices such storage by **byte-days**, as version 4 prices a package's, at its
|
||
`storage` price: millionths of a minor unit per 10^9 byte-days, at most 2^53 − 1. What it bills
|
||
from is the holder's own statements, signed as they are made, of what a set listed at each instant
|
||
its listing changed, and its record of the bytes the set held over an interval, which the verifier
|
||
recomputes from them.
|
||
|
||
**A stored set** is the objects a holder keeps together and states together: a stream's window,
|
||
which lists the segments a player can reach, or a clip's files. Its **subject** is 32 bytes the
|
||
holder names it by and names no other set by, the digest of a name of its own choosing: a set whose
|
||
objects change keeps its subject, so a window's snapshots over a day, each listing other segments,
|
||
are of one subject. Its **listing** at an instant names each object it lists by its content hash,
|
||
SHA-256 of its bytes, and its length; the listing's digest is SHA-256 over the 19 bytes
|
||
`wai:ledger-listing` (ASCII) and 0x01, followed by each object, in strictly ascending order of
|
||
content hash, as its content hash (32) and its length (u64). So a snapshot binds its bytes to a
|
||
list of objects, which anyone holding them recomputes, and the listing of no objects is SHA-256 over
|
||
those 19 bytes alone.
|
||
|
||
**A snapshot**, `WLS1`, is a holder's statement of what one stored set lists at one instant:
|
||
|
||
| field | size | meaning |
|
||
|---|---|---|
|
||
| `magic` | 4 | `WLS1` (ASCII) |
|
||
| `version` | 1 | 1 |
|
||
| `holder` | 32 | the holder's key, which signs it |
|
||
| `subject` | 32 | the stored set it is of |
|
||
| `at` | 8 | u64: the instant it states, a time (§2) |
|
||
| `objects` | 4 | u32: the objects the set lists at `at` |
|
||
| `bytes` | 8 | u64: their lengths, summed |
|
||
| `listing` | 32 | the digest of its listing at `at` |
|
||
| `sig` | 64 | Ed25519 by `holder` over the 20 bytes `wai:ledger-snapshot` (ASCII) and 0x01, followed by the bytes before `sig` |
|
||
|
||
**A storage record**, `WLH1`, is a holder's statement of the bytes one stored set held over an
|
||
interval:
|
||
|
||
| field | size | meaning |
|
||
|---|---|---|
|
||
| `magic` | 4 | `WLH1` (ASCII) |
|
||
| `version` | 1 | 1 |
|
||
| `holder` | 32 | the holder's key, which signs it |
|
||
| `subject` | 32 | the stored set it is of |
|
||
| `start`, `end` | 8 each | u64: its **interval**, `start` included and `end` excluded |
|
||
| `byte_seconds` | 8 | u64: the bytes the set held over the interval, in byte-seconds (below) |
|
||
| `snapshots` | 4 + 32 × *n* | a u32 count *n*, then the digest of each of its snapshots, in the order of their instants |
|
||
| `sig` | 64 | Ed25519 by `holder` over the 19 bytes `wai:ledger-storage` (ASCII) and 0x01, followed by the bytes before `sig` |
|
||
|
||
The **digest** of a snapshot or a record is SHA-256 over its bytes before `sig`. A reader reads
|
||
exactly the bytes it is given as one snapshot or one record, as §4.3 reads a tariff, with its own
|
||
magic, and a version other than 1 is `unknown_version`. It refuses as `storage_invalid` one that
|
||
breaks any of these: `holder` and `subject` are not zero; of a snapshot, one of no objects states 0
|
||
bytes and the listing of no objects; of a record, `start` is below `end` and it names at least one
|
||
snapshot. Then its signature, verified strictly as [SPEC](../SPEC.md) §7 *Signatures* requires:
|
||
`bad_key`, `bad_signature`.
|
||
|
||
**The rule.** A holder states what a set lists when its listing changes, and the bytes listed at an
|
||
instant are those of the set's latest snapshot at or before it. A record's snapshots therefore
|
||
**cover** its interval: the first is at its `start`, each later one after the one before it, and
|
||
none at or past its `end`. Its byte-seconds are what they state, the sum over its interval of the
|
||
bytes listed at each instant:
|
||
|
||
> `byte_seconds` = ⌊Σ *bytes*ᵢ × (*at*ᵢ₊₁ − *at*ᵢ) / 10^6⌋,
|
||
|
||
over its snapshots in order, *at* in microseconds and *at*ₙ its `end`, computed in integers wide
|
||
enough not to overflow and rounded down once per record. A record that states any other figure is
|
||
refused `storage_mismatch`. One that claims more bills bytes its holder never said it kept; one that
|
||
states a set's bytes as its byte-seconds, a quantity of one unit read as another, states a figure
|
||
its own snapshots contradict, and so does one that states fewer.
|
||
|
||
**The source.** A `storage` source (§5.1) is one record and its snapshots, verified in this order:
|
||
the record reads and its signature verifies, at `record`; as many snapshots are given as it names
|
||
(`snapshot_mismatch`, at `snapshots`); each snapshot, in order, reads and its signature verifies,
|
||
and it is of the record's holder and subject and its digest is the one the record names at its place
|
||
(`snapshot_mismatch`), at `snapshots` and its index; the snapshots cover the interval
|
||
(`outside_interval`, at `snapshots` and the index of the first that does not); and the record's
|
||
`byte_seconds` is what they state (`storage_mismatch`, at `record`). Then, at §7.2 step 5, the
|
||
tariff names the holder in its scope (kind 9), so the buyer chose whose word on storage it pays on,
|
||
and the record's interval lies within the invoice's period (§5.3).
|
||
|
||
**What it contributes.** Its record (kind 26) and each snapshot (kind 27), each by its digest and
|
||
each billed once in a chain (§6.9). Its line is its holder's: the quantity ⌊Σ `byte_seconds` /
|
||
86 400⌋ over the holder's storage sources, byte-seconds into whole byte-days rounded down once per
|
||
line, as version 4 rounds a package's (§4.7), at the tariff's `storage` price per 10^9 byte-days,
|
||
citing each record it counts whose `byte_seconds` is above 0 and the snapshots each names. A
|
||
snapshot states no energy, so the source states no figure. A record is billed in the period that
|
||
holds its interval, and a chain's periods do not overlap, so a set's time is billed once in a chain;
|
||
two records of one holder and one subject whose intervals overlap on one invoice bill one time twice,
|
||
and the later is refused `record_overlap` (§5.3). A holder makes a record of each set for each
|
||
period it is invoiced by, beginning with a snapshot at the period's start: a record whose interval
|
||
crosses a period's end is billed by no invoice, as a schedule crossing one is not (§4.10).
|
||
|
||
**Why the holder's snapshots.** Every other quantity this ledger bills is a figure of a record its
|
||
party signed, which the verifier reads or recomputes, and which it places in a period by the time
|
||
that record states: a room session's microseconds, a statement's period, a batch, a claim's issue.
|
||
Storage over time is a figure of the same kind, and the holder is its party, as a node is of its own
|
||
instance (§4.10). A figure signed only when it is billed would be one the buyer could take or leave.
|
||
Snapshots are signed as the listing changes, each binding its bytes to the objects listed by their
|
||
content hashes, and the record's figure is a pure function of them, so a buyer given the record and
|
||
its snapshots recomputes the line, and a record that claims more than they support is refused by
|
||
any verifier. A package's storage is billed from the chain instead (§4.7): its bytes do not change
|
||
while it is kept, and its receipt states no time. A window's bytes change by the minute, and
|
||
neither its objects' receipts nor the chain state them.
|
||
|
||
**What rests on the holder's word.** The ledger does not read a listing: it holds a record's figure
|
||
to its snapshots and each snapshot to its holder's signature. A holder of the objects, the publisher
|
||
whose segments a window lists, recomputes a snapshot's `bytes` and `listing` from them. Whether the
|
||
holder kept what it listed is its statement, as a package's storage is the seller's (§12).
|
||
|
||
A version-7 reader cannot read a tariff with a `storage` field or a holder in its scope, a `storage`
|
||
source or kinds 26 and 27, so version 8 is a version of its own. A tariff of versions 1 to 7, its
|
||
invoices and its sources read, verify and bill exactly as before.
|
||
|
||
### 4.14 A tariff that follows another (version 9)
|
||
|
||
A tariff of version 9 is version 8's in its layout but for one field after `storage` (§4.1), in its
|
||
rules, its scope and its prices (§4.3 to §4.13), and an invoice of version 9 is version 8's (§6.1);
|
||
each bills what version 8 bills. Where this text says version 8, or a range of versions ending at 7
|
||
or 8, version 9 is included, except as this section says.
|
||
|
||
**Why.** A tariff is one signed document: its scope and its prices are what both parties signed
|
||
(§4.2), and its invoices form one chain (§6.9). The parties a buyer pays for change while it is
|
||
billed: a stitcher's key is made for a new channel or retired with an old one, a packager or a
|
||
holder is added. Each change is a new tariff, which the buyer signs, and before this version each
|
||
new tariff began a chain of its own, its first invoice naming no invoice before it. What a chain
|
||
carries from one invoice to the next then did not cross: a package is billed its storage only by
|
||
an invoice whose previous lists it (§4.7), so the new chain's first invoice billed none; and a
|
||
record billed once is held to the invoice before (§6.9, `record_rebilled`), which the new chain's
|
||
first invoice did not have, so a record the old tariff's chain billed could be billed again.
|
||
|
||
**The field and the rule.** A tariff of version 9 states `follows`: zero, or the digest of the
|
||
tariff whose chain it continues. A tariff that **follows** another continues that tariff's chain:
|
||
|
||
- its first invoice names in `prev` an invoice of the tariff it follows, the last of that chain,
|
||
and each later invoice names the one before it, as in every chain;
|
||
- every rule that reads the invoice before reads that one, across the two tariffs: a package it
|
||
lists is held through the next period (§4.7); a record it lists that the invoice's version bills
|
||
once is billed never again (§6.9); its period ends at or before the next one begins;
|
||
- no invoice of a tariff that follows another names zero: one that did would begin a chain of its
|
||
own and leave behind what the chain holds and has billed, and it is refused `chain_restarted`
|
||
(§7.2 step 4).
|
||
|
||
A tariff whose `follows` is zero begins a chain, as every tariff of versions 1 to 8 does.
|
||
|
||
**Both signatures.** `follows` is in the body both parties sign (§4.2). A buyer that signs a
|
||
following tariff accepts its scope and its prices and that it continues the chain it names, in one
|
||
act, and a seller cannot carry a chain into a tariff the buyer did not sign, nor into one that does
|
||
not name it. A verifier needs no more than it is given: the previous invoice names its tariff by
|
||
digest, which the following tariff names, and the previous invoice's seller and buyer are held to
|
||
the invoice's (§7.2 step 4), so the chain stays one seller's and one buyer's.
|
||
|
||
**What follows the change, and what does not.** The scope and the prices are the following
|
||
tariff's alone, from its first invoice on: each source is held to the scope, the prices and the
|
||
period of the tariff its invoice names (§7.2 steps 3 and 5). A package the previous invoice holds
|
||
whose packager the following tariff does not name is no longer billed. A key the following tariff
|
||
retires bills none of its records under it, whenever they are given; a seller that may still be
|
||
given records of a retired key, a stitched record among them, which states no time (§5.3), bills
|
||
them under the tariff that names the key first, or names the key in the following tariff for as
|
||
long as they may come.
|
||
|
||
**One chain.** A tariff follows one tariff and is followed by one. Two tariffs that follow one, or
|
||
two invoices that name one `prev`, fork a chain; a verifier given an invoice and the one before it
|
||
does not see a fork, and a buyer that holds the chain does (§12). The reference ledger closes a
|
||
tariff when another follows it (§9).
|
||
|
||
**Why a following tariff, not an amendment of a scope** (decision D62). An amendment would be a
|
||
record of its own, signed by both parties, beside the tariff it amends; an invoice's scope would be
|
||
the tariff's with every amendment in force over its period, so a verifier would need every
|
||
amendment of the tariff, and an invoice whose period crossed an amendment's instant a rule to split
|
||
it. A following tariff is a tariff: its scope and its prices are read as every tariff's are, one per
|
||
invoice, and only the chain crosses. A scope that changes with prices that do not is a following
|
||
tariff with the same prices.
|
||
|
||
A version-8 reader cannot read a tariff of version 9, its `follows`, or an invoice of version 9, so
|
||
version 9 is a version of its own. A tariff of versions 1 to 8 follows none: its chain, its invoices
|
||
and its sources read, verify and bill exactly as before, and an invoice whose previous is of another
|
||
tariff is refused `tariff_mismatch` as before.
|
||
|
||
## 5. Sources
|
||
|
||
### 5.1 Kinds and their documents
|
||
|
||
A source is a JSON object (RFC 8259) whose `kind` names its extension, holding exactly what that
|
||
extension's verifier is given. Bytes are lowercase hexadecimal strings.
|
||
|
||
| `kind` | members | verified as |
|
||
|---|---|---|
|
||
| `room` | `room` (`descriptor`, `grants`, `key_log_head` (a string or `null`), `chains`, a list of lists of records), `receipt`, `hops` (each `record` and `ledger`), `descriptors`, `compositions`, `takes`, `logs` (a string or `null`) | live-metering §5.1, its receipt being `receipt` |
|
||
| `delivery` | `statement`, `records` (each `record` and its `items`, one item list per entry), `proofs`, `hops`, `rooms` (each `descriptor` and `grants`) | settlement §8.2 |
|
||
| `package` | `receipt` (the text of `package.receipt.json`), `indexes` (the index files in the receipt's component order) | packaging §9, a receipt of version 2 against its indexes |
|
||
| `ads` | `descriptor`, `grants`, `key_log`, `chains`, `policy`, `pt0_ms`, `receipts` (form-2 receipts in their JSON carriage), `pods`, `claims`, `creatives`, `issuers` | live-ads §9, with ad-presentation §9 under a policy that requires claims |
|
||
| `stitched` | `records` (pod-input records), `claims` (stitched claims), `manifests`, `responses` (VAST and VMAP documents), `receipts` (form-1 receipts in their JSON carriage), `creatives`, `issuers` | stitched-presentation §7, its signers the tariff's (§4.4) |
|
||
| `group` (version 7) | `group` (a group receipt, jwp-receipts §2.4.1), `objects` (each `receipt`, an object receipt, and `envelope`, its envelope or `null`), `claims` (the texts of its publisher's transmission and schedule claims about the group, in their chain's order) and `parent` (the text of the claim the first one follows, or `null`) | §4.10: carousel §6.2 steps 1 to 4, every claim accepted and none set aside |
|
||
| `cache` (version 7) | a `group` source's members, `claims` being the texts of one node's cache-transmission and schedule claims, at least one, and `declarations` (its `WDA1` records of version 2, settlement §4.4) | §4.10: cache-authority §7.2 steps 1, 2 and 4, every claim accepted and none set aside, and each declaration naming a claim given |
|
||
| `aggregated` (version 7) | `receipt` (an aggregate receipt, telemetry-aggregation §7) | §4.11: read as data: its collector's signature, its task's `time_precision`, its leader's statement and its count |
|
||
| `consumption` (version 7) | `claims` (the texts of an agent's consumption claims, at least one, in their chain's order) and `parent` (the text of the claim the first one follows, or `null`) | §4.12: jwp-receipts §3.1 steps 1 to 5 |
|
||
| `storage` (version 8) | `record` (a storage record, `WLH1`) and `snapshots` (the snapshots it names, `WLS1`, in its order) | §4.13: the record, each snapshot it names, their cover of its interval and its byte-seconds |
|
||
| `job` (versions 2 to 4) | `request`, `pricebook`, `policy`, `record`, `receipts`, `keys` (a route record's verification document, route-record §7.1, its `receipts` and `keys` not `null`) and `outputs`, a list of objects of exactly `receipt` (the text of a `wai.video.int_motion` decode receipt's JSON form, integer-payloads §15.2) and `codestream` (the `WIV1` payload it describes: the object the hop delivered, named by its content hash; in version 5 a decode's output also has `frames`, the animation of its frames it delivered, and its codestream is what it read, §4.8), or, in version 4, of exactly `package` (the text of a package receipt of version 2, `package.receipt.json`: the object the hop delivered) and `indexes` (its index files in its component order); under a route record of version 3, each output also has `proof`, its object's inclusion proof (route-record §6.1); in version 6, it may also have `third_party`, and an upscale's and a tone mapping's outputs have their own forms (§4.9) | route-record §7, accepted with its hop receipts checked; then each output receipt read by integer-payloads §15.2 and re-derived from its `codestream` (§15.1 there), each package verified against its indexes by packaging §9, or `output_invalid` at `outputs` and its index, an upscale's and a tone mapping's outputs as §4.9 says; then each output held to what its hop delivered, or `output_not_delivered` there |
|
||
|
||
A source is accepted when its extension's verifier accepts it; for `ads`, when the outcome is
|
||
**accept** (live-ads §9.4), a **gap** being `source_gap`. A `stitched` source is always
|
||
accepted, since its verification refuses nothing as a whole (stitched-presentation §7.5): a
|
||
record it does not accept, of a signer outside the scope among them, bills nothing, and a claim
|
||
it does not find presented counts nothing. A source that is not such an object,
|
||
whose `kind` is none of these, or whose members are not exactly its kind's, each of its form, is
|
||
refused `malformed`. Under a tariff of version 1, a `job` source is not a kind, and is
|
||
`malformed`; under a tariff of versions 1 to 6, nor are `group`, `cache`, `aggregated` and
|
||
`consumption` sources; under a tariff of versions 1 to 7, nor is a `storage` source.
|
||
|
||
A job source's **billed hop** is the attempt of its route record that is billed (route-record
|
||
§5.2), if any; its **serving capability** is that attempt's candidate's `capability`, its
|
||
**operation** is its route record's `operation`, and its **figure** is the figure of that
|
||
attempt's OER/2 receipt: the unmetered marker
|
||
(oer-receipts §3.1), or `energy.joules_total` in microjoules, rounded to the nearest and a
|
||
half to the even one, with the receipt's `energy.class`. A billed hop's receipt whose figure
|
||
has no class, or rounds below 1 µJ or past what a u64 holds, cannot be stated in a row
|
||
(§6.6): the source is refused `job_figure_invalid`, at `receipts` and the receipt's index.
|
||
Under a tariff of version 4 every attempt's figure is stated (§6.6), so the same holds of each
|
||
attempt that is not billed, a failed hop and one that served past the deadline.
|
||
|
||
**A job's output is the object its hop delivered.** An output's **object** is its
|
||
`codestream`, or a package's receipt text, named by its content hash (route-record §2,
|
||
jwp-receipts §2.1). A route record
|
||
of version 2 states the objects its served attempt delivered, by content hash, and holds that
|
||
hop's receipt to them (route-record §5.2, §6). Each output a job source gives is then one of
|
||
those objects, and no two of its outputs are one object: otherwise the source is refused
|
||
`output_not_delivered`, at `outputs` and the output's index. The reason is the subpixels a
|
||
line bills (§6.3): they are read from the output receipts, and an output receipt of an object
|
||
the hop did not deliver bills subpixels nobody delivered for this job, as a receipt given
|
||
twice bills them twice. So the chain closes: the hop's receipt names its outputs, the record
|
||
names the hop's receipt and the outputs, and each output receipt is of one of them. Under a
|
||
tariff of version 5 a decode's object is the animation of the frames it delivered, not the
|
||
codestream it read (§4.8). Under a tariff of version 4, a record that states no outputs (a
|
||
record of version 1, or one no attempt served) holds every output to none, and a job it
|
||
routed is billed by the job alone; under a tariff of version 3, a record of version 1's
|
||
outputs are read as before.
|
||
|
||
A route record of version 3 states what its served attempt delivered by its count and root,
|
||
not by a list (route-record §3.4, §5.2), so a hop may deliver any number of objects. Each
|
||
output of a job source under one gives `proof`, the inclusion proof of its object (route-record
|
||
§6.1), and is one of the objects the hop delivered when its proof holds its object's content
|
||
hash to the served attempt's `count` and `root`; an output under a record of version 1 or 2
|
||
gives none. An output without its proof, or with one under a record of version 1 or 2, or a
|
||
proof that is not an object of exactly an integer `index` and a list of content hashes'
|
||
texts, `siblings`, is `malformed`; a proof that does not hold is `output_not_delivered`, at
|
||
`outputs` and the output's index, as an object a list does not state is; and no two outputs
|
||
are one object, as before. The ledger does not hold the count to the objects, which it is not
|
||
given: the hop's receipt names the root alone (route-record §6). A count stated larger than
|
||
the objects lets the last of an odd level be proved at a second place, and that place is one
|
||
object, which no source bills twice; a decode is held to its places and its count (§4.8).
|
||
Under a record of version 3 no attempt served, the outputs are held to none.
|
||
|
||
**Routing figures are never charges.** A route record's candidates' `cost`, `energy`,
|
||
`expected_cost` and `expected_ttfb_ms`, and its price book's `price` and `failures`, are the
|
||
router's figures for choosing an endpoint (route-record §4.2, §4.4): what a hop costs the
|
||
router, and what the failures it measured cost it, per successful job. No line reads them. A
|
||
job line bills its billed attempt alone, at its list price, the tariff's job price for its
|
||
serving capability and operation, which the buyer signed: a failed attempt, what a provider
|
||
billed for it and the expected cost per successful job never reach a line, however the router
|
||
ranked, and a line that counts a failed hop as a job, or prices one at the router's figures,
|
||
does not recompute.
|
||
|
||
### 5.2 What a source contributes
|
||
|
||
Each source contributes **records**, each named by a kind and an identity. This table is the
|
||
**one registry of record kinds**: every WAI text that names a record by a kind (in a citation
|
||
digest, or in a list of records) takes the kind from here, and a new kind is assigned here, the
|
||
next free one. Kinds 10 to 13 and 28 to 44 are defined by the texts that cite or name them and are no
|
||
ledger source's; the others are the ledger's own:
|
||
|
||
| record kind | record | identity | contributed by |
|
||
|---|---|---|---|
|
||
| 1 | a room-session receipt, `WMR1` | its digest (live-metering §4.2) | a `room` source: its receipt |
|
||
| 2 | a per-hop record, `WMH1` | its digest (live-metering §3.5) | a `room` source: each record its receipt names; a `delivery` source: each record its statement names in `hops` |
|
||
| 3 | a settlement statement, `WSS1` | its digest (settlement §7.4) | a `delivery` source: its statement |
|
||
| 4 | an acknowledgement or declaration, `WDA1` | its digest (settlement §3.5) | a `delivery` source: each record its statement names in `records`; a `cache` source (version 7): each declaration it gives |
|
||
| 5 | a package receipt | its `receipt_hash` (packaging §9) | a `package` source; a `job` source (version 4): each output package |
|
||
| 6 | a `wai.video.ssai` receipt of the break form | its identity (live-ads §8.4) | an `ads` source: each receipt |
|
||
| 7 | a presentation claim, `WPC1` | its digest (ad-presentation §5.3) | an `ads` source: each claim that reads |
|
||
| 8 | a pod-input record, `WSI1` | its digest (stitched-presentation §4.4) | a `stitched` source: each record it accepts |
|
||
| 9 | a stitched claim, `WSC1` | its digest (stitched-presentation §5.3) | a `stitched` source: each claim that reads |
|
||
| 10 | a run of a channel's program-as-run | its identity ([revenue-share](revenue-share.md) §7.4) | no source: cited by revenue-share §7.4 and opportunity-report §7.3 |
|
||
| 11 | an invoice, `WLI1` | its digest (§6.7, as [revenue-share](revenue-share.md) §7.4 cites it) | no source: cited by revenue-share §7.4 |
|
||
| 12 | a cue event | its event digest ([opportunity-report](opportunity-report.md) §7.3, live-events §3.2) | no source: cited by opportunity-report §7.3 |
|
||
| 13 | a room policy | its digest ([opportunity-report](opportunity-report.md) §7.3, live-ads §3.2) | no source: cited by opportunity-report §7.3 |
|
||
| 14 | an OER/2 receipt | the 32 bytes its `receipt_id` names (oer-receipts §5) | a `job` source (versions 2 to 4): the receipt of each attempt of its record |
|
||
| 15 | a `wai.video.int_motion` decode receipt | its receipt hash (integer-payloads §15.1) | a `job` source (versions 2 to 4): each output receipt |
|
||
| 16 | a route record | its digest (route-record §5.3) | a `job` source (versions 2 to 4): its record |
|
||
| 17 | a third-party hop record | its digest (route-record §6.2) | a `job` source (version 6): each record it gives |
|
||
| 18 | an upscale record | its link hash (exact-upscale §2) | a `job` source (version 6): each upscale's record (§4.9) |
|
||
| 19 | a rendition record | its link hash (exact-tonemap §2) | a `job` source (version 6): each tone mapping's record (§4.9) |
|
||
| 20 | a group receipt | its link hash (jwp-receipts §3 step 3) | a `group` or `cache` source (version 7): its group (§4.10) |
|
||
| 21 | a transmission claim | its link hash (jwp-receipts §3.1) | a `group` source (version 7): each declaration it gives |
|
||
| 22 | a schedule claim | its link hash (jwp-receipts §3.1) | a `group` or `cache` source (version 7): each schedule it gives |
|
||
| 23 | a cache-transmission claim | its link hash (jwp-receipts §3.1) | a `cache` source (version 7): each claim it gives |
|
||
| 24 | an aggregate receipt, `WQA1` | its digest (telemetry-aggregation §7.1) | an `aggregated` source (version 7): its receipt (§4.11) |
|
||
| 25 | a consumption claim | its link hash (jwp-receipts §3.1) | a `consumption` source (version 7): each claim it gives (§4.12) |
|
||
| 26 | a storage record, `WLH1` | its digest (§4.13) | a `storage` source (version 8): its record |
|
||
| 27 | a snapshot, `WLS1` | its digest (§4.13) | a `storage` source (version 8): each snapshot its record names |
|
||
| 28 | a sink session receipt | its identity ([sink-energy](sink-energy.md) §3) | no source: cited by energy-methods §7 |
|
||
| 29 | a sink segment receipt | its identity (sink-energy §3) | no source: cited by energy-methods §7 |
|
||
| 30 | a `split-computation` claim | its link hash (jwp-receipts §3.1) | no source: cited by energy-methods §7 |
|
||
| 31 | a factor table | its identity ([energy-methods](energy-methods.md) §6.1) | no source: cited by energy-methods §7 |
|
||
| 32 | a certifier's refusal, `cert-refusal/1` | its digest ([certification](certification.md) §4.2) | no source: cited by certification §4.2 |
|
||
| 33 | a publication's manifest, `cert-publication/1` | its digest (certification §5.3) | no source: cited by certification §5.3 |
|
||
| 34 | an audit entry | its link ([audit-chain](audit-chain.md) §3.2) | no source: cited by audit-chain §3.2 |
|
||
| 35 | an audit checkpoint | its digest (audit-chain §5.2) | no source: cited by audit-chain §5.2 |
|
||
| 36 | a data export | its digest ([data-export](data-export.md) §3.4) | no source: cited by data-export §3.4 |
|
||
| 37 | a deletion record | its digest ([data-deletion](data-deletion.md) §3.2) | no source: cited by data-deletion §3.2 |
|
||
| 38 | a price document | its digest ([price-document](price-document.md) §5.3) | no source: cited by price-document §5.3 |
|
||
| 39 | a window revision, `wai-hls-window` | its identity ([hls-clips](hls-clips.md) §5.1) | no source: cited by hls-clips §9 |
|
||
| 40 | a clip record, `wai-hls-clip` | its identity (hls-clips §6.1) | no source: cited by hls-clips §9 |
|
||
| 41 | an opportunity report, `WOR1` | its digest ([opportunity-report](opportunity-report.md) §7.4) | no source: named so in a data export's record lines ([data-export](data-export.md) §3.2) |
|
||
| 42 | a statement check, `WCK1` | its digest (opportunity-report §10.5) | no source: named so in a data export's record lines (data-export §3.2) |
|
||
| 43 | an origin claim, `wai-origin` | its link hash ([synthesis](synthesis.md) §2) | no source: named so in a data export's record lines (data-export §3.2) |
|
||
| 44 | a marking, `wai-marking` | its link hash (synthesis §2) | no source: named so in a data export's record lines (data-export §3.2) |
|
||
|
||
Kinds 45 to 127 are unassigned. Kinds **128 to 255 are reserved for private and provisional
|
||
use**: an implementation's own records, such as a hosted service's provisional records carried
|
||
beside WAI's until WAI defines them, may name records by them, and no kind WAI assigns later will
|
||
ever be one of them. A WAI record never states one, and a WAI verifier refuses one wherever a WAI
|
||
record states a kind, `private_kind`: in this extension, an invoice's `records` (§6.8). No citation
|
||
digest WAI defines covers one.
|
||
|
||
A source's **head** is its receipt, statement or package receipt; an `ads` source's heads are its
|
||
receipts, a `stitched` source's its accepted records, a `job` source's its route record, a
|
||
`group` source's its transmission and schedule claims, a `cache` source's its cache-transmission and
|
||
schedule claims, an `aggregated` source's its receipt, a `consumption` source's its claims and a
|
||
`storage` source's its record. A head
|
||
of one source that is a head of another source of the invoice is refused `record_duplicate`. A record
|
||
that is no head of a source may be another's: a group receipt is the head of no source (§4.10), and a
|
||
package receipt is none of the run that cites it (§4.7). A per-hop record, which a room receipt and a
|
||
statement can both name, is contributed once.
|
||
|
||
An instance of a group, by the group's link hash and its `bearer_id`, is one party's one transmission
|
||
(§4.10), however many claims state it, and two groups on one `bearer_id`, a broadcast service
|
||
carrying both, are two instances. A `group` or `cache` source that declares an instance an
|
||
earlier source of the invoice declares is refused, whichever claims each gives: `record_duplicate`
|
||
when one key declared both, and `bearer_contradicted` when two did (cache-authority §7.2 step 4). So
|
||
no schedule, entry or energy figure of an instance is stated twice.
|
||
|
||
An OER/2 receipt a `job` source contributes that an earlier `job` source of the
|
||
invoice also contributes is refused `record_duplicate` too: one hop serves one job, so no hop is
|
||
billed for two. Under a tariff of version 2, so is an output receipt: one output is one job's.
|
||
Under a tariff of version 3 or 4 it is not: an output receipt is the evidence of what a job
|
||
delivered, not the work, and the same request run again on a deterministic codec delivers the
|
||
same object, of the same content hash, under the same receipt from a new hop that did the work
|
||
again (§6.9). Two lines of one invoice that cite one output receipt therefore cite different hop
|
||
receipts, whichever lines they are.
|
||
|
||
### 5.3 Placement in time
|
||
|
||
A source is **in** a period when:
|
||
|
||
- `room`: the receipt's session, placed by its room's `t0`, lies within it: `t0` + `start` ≥ the
|
||
period's `start` and `t0` + `end` ≤ its `end`;
|
||
- `delivery`: the statement's period lies within it;
|
||
- `ads`: the `t` of the break each receipt names, placed by the room's `t0`, is within it;
|
||
- `package` and `stitched`: always: a package receipt and a pod-input record state no time, and
|
||
the chain (§6.9) bills each once; under a tariff of version 4, a package's work once and its
|
||
storage for the periods it is held through (§4.7);
|
||
- `job`: its route record's `accepted` is within it;
|
||
- `group`: every pass of every entry of its standing schedules is within it: `first_ms` × 1000 is
|
||
at least the period's `start`, and the end of the last pass, (`first_ms` + (`count` − 1) ×
|
||
`period_ms` + `duration_ms`) × 1000, at most its `end`. A source with no schedule is in every
|
||
period;
|
||
- `cache`: every pass of every entry it bills is within it, as for `group`, an entry its claim does
|
||
not say was sent being no pass of the source (§4.10), and each declaration's window lies within it;
|
||
- `aggregated`: its batch is within it: `start` × `time_precision` × 10^6 is at least the period's
|
||
`start`, and (`start` + `duration`) × `time_precision` × 10^6 at most its `end`, `start` and
|
||
`duration` the leader's statement's and `time_precision` its task's, in integers wide enough not
|
||
to overflow. The period is when the reports were made, not when their count arrived: a batch is
|
||
collected after a hold (impression-aggregates §7.1), so a seller invoices a period once the batches
|
||
it bills are collected, and a batch that crosses a period's end is billed by no invoice;
|
||
- `consumption`: each claim's `issued_at`, in seconds with any fraction dropped, × 10^6, is within
|
||
it: at least its `start` and below its `end`;
|
||
- `storage`: its record's interval lies within it: the record's `start` is at least the period's
|
||
`start`, and its `end` at most the period's `end`.
|
||
|
||
Two room receipts of one room whose sessions overlap, two statements of one party whose periods
|
||
overlap, two receipts of the invoice's ads sources naming one break and one session, two aggregate
|
||
receipts of one task whose batches share a time unit (§4.11), two storage records of one holder and
|
||
one subject whose intervals overlap (§4.13), and, under a tariff of version 2, two
|
||
route records of one router naming one `job`, bill one thing twice: the later is refused
|
||
`record_overlap`. Under a tariff of version 3 or 4, two route records of one
|
||
job are two runs of it, each billed from its own hop, and no hop twice (§5.2): a job's id names what
|
||
was asked, not the work, and a request run again is worked again.
|
||
|
||
## 6. The invoice
|
||
|
||
### 6.1 Layout
|
||
|
||
| field | size | meaning |
|
||
|---|---|---|
|
||
| `magic` | 4 | `WLI1` (ASCII) |
|
||
| `version` | 1 | its tariff's version, 1 to 9 |
|
||
| `seller`, `buyer` | 32 each | the tariff's |
|
||
| `tariff` | 32 | the tariff's digest |
|
||
| `prev` | 32 | the digest of the invoice before it in its chain (§6.9); zero for the first |
|
||
| `start`, `end` | 8 each | u64: the period it bills |
|
||
| `currency` | 3 | the tariff's |
|
||
| `records` | 4 + 33 × *r* | a u32 count, then each record (§5.2): `kind` (u8) and `id` (32), in strictly ascending order of (`kind`, `id`) |
|
||
| `lines` | 2 + 94 × *l* | a u16 count, then each line (§6.3), in strictly ascending order of (`source_kind`, `source`, `unit`) |
|
||
| `energy` | 1 + 18 × *e* | a u8 count, then each row (§6.6): `scope` (u8), `tag` (u8), `figures` (u32), `joules` (u64, µJ), `max_ppm` (u32), in strictly ascending order of (`scope`, `tag`) |
|
||
| `unmetered` | 16, 20, 24 or 28 | four u32: the unmetered figures of scopes 1 to 4 (§6.6); in versions 2 and 3, five, scopes 1 to 5; in version 4, six, scopes 1 to 6; in versions 7 to 9, seven, scopes 1 to 7 |
|
||
| `amount` | 8 | u64: the sum of the lines' amounts |
|
||
| `sig` | 64 | §6.7 |
|
||
|
||
### 6.2 Records
|
||
|
||
`records` lists every record the sources contribute (§5.2), each once. It is what the invoice was
|
||
computed from, and what the next invoice of the chain may not bill again.
|
||
|
||
### 6.3 Lines
|
||
|
||
A line is 94 bytes:
|
||
|
||
| field | size | meaning |
|
||
|---|---|---|
|
||
| `source_kind` | 1 | 1 room, 2 delivery, 3 package, 4 ads, 5 job (versions 2 to 4), and in version 7 6 group, 7 aggregated, 8 consumption, and in version 8 9 storage |
|
||
| `source` | 32 | the room id, the delivering party, the packager, the ad decider, the router, the publisher or node, the collector, the agent or the holder |
|
||
| `unit` | 1 | the unit (below) |
|
||
| `quantity` | 8 | u64: the quantity of the unit the records state |
|
||
| `price` | 8 | u64: the tariff's price for the unit |
|
||
| `amount` | 8 | u64: §6.4 |
|
||
| `cited` | 4 | u32: the records the line cites (§6.5) |
|
||
| `cites` | 32 | their **citation digest** (§6.5) |
|
||
|
||
The units, the quantity each sums over the sources of its `source`, and the price and divisor of
|
||
each:
|
||
|
||
| `source_kind` | `unit` | name | quantity | price | divisor |
|
||
|---|---|---|---|---|---|
|
||
| 1 | 1 | `publisher_us` | the receipts' `publisher_us` | `room` 0 | 10^6 |
|
||
| 1 | 2–10 | `subscriber_us_0`–`subscriber_us_8` | their `subscriber_us` of layer class `unit` − 2 | `room` 1–9 | 10^6 |
|
||
| 1 | 11 | `composition_us` | their `composition_us` | `room` 10 | 10^6 |
|
||
| 1 | 12 | `recorded_us` | their `recorded_us` | `room` 11 | 10^6 |
|
||
| 1 | 13 | `events_sent` | their `events_sent` | `room` 12 | 1 |
|
||
| 1 | 14 | `bytes_out` (version 4) | their `bytes_out`, of receipts of version 2 (§4.7) | `room` 13 | 10^9 |
|
||
| 2 | 1–4 | `live`, `fetch`, `fill`, `ancillary` | the bytes of the statement's delivery lines of that class that are not free (settlement §7.2) | `delivery` `unit` − 1 | 10^9 |
|
||
| 3 | 1 | `packages` | the number of package receipts | `package` 0 | 1 |
|
||
| 3 | 2 | `entries` | their `total_entries` | `package` 1 | 1 |
|
||
| 3 | 3 | `stored_bytes` | their `stored_bytes` | `package` 2 | 10^9 |
|
||
| 3 | 3 | `byte_days` (version 4, its only package unit) | ⌊Σ `stored_bytes` × (`end` − `start`) / 86 400 000 000⌋ over the package receipts the previous invoice lists, which are held (§4.7) | `package` 0 of version 4 | 10^9 |
|
||
| 4 | 1 | `presented_impressions` | under a policy that requires claims, the impressions that count (ad-presentation §9.2); of a stitched source, the presentations of its accepted records' ads (stitched-presentation §7.4), one per session | `ads` 0 | 1 |
|
||
| 4 | 2 | `billable_impressions` | under a policy that does not, the billable impressions (quartile at least 1) | `ads` 1 | 1 |
|
||
| 5 | *k* | the *k*-th job price's unit | over the router's job sources with a billed hop whose serving capability is that price's `capability` (and, in versions 3 and 4, whose operation is its `operation`, and, in version 6, whose endpoint is its `endpoint`, when it names one): one per job (`jobs`), each job's output receipts' `work_pixel_ops` (`subpixels`), in version 6 with its upscale and rendition records' subpixels, or, in version 4, its output packages' `work_units` (`work_units`), or, in version 6, its billed hop's record's usage in the price's unit (`usage`, §4.9) | the *k*-th job price's `price` | its `divisor` |
|
||
| 6 | *k* | the *k*-th transmission price's unit, `bytes_sent` or `pass_us` (version 7) | over the publisher's group sources, or the node's cache sources, each entry of a standing schedule on an instance of that price's `bearer` that §4.10 bills at that price: its `bytes_sent`, or its `pass_us` | the *k*-th transmission price's `price` | 10^9 for `bytes_sent`, 10^6 for `pass_us` |
|
||
| 7 | 1 | `aggregated_impressions` (version 7) | over the collector's aggregated sources, each receipt's count (§4.11) | `aggregated` | 1 |
|
||
| 8 | 1 | `consumed_objects` (version 7) | over the agent's consumption sources, the objects each claim names (§4.12) | `consumption` | 1 |
|
||
| 9 | 1 | `byte_days` (version 8) | ⌊Σ `byte_seconds` / 86 400⌋ over the holder's storage records (§4.13) | `storage` | 10^9 |
|
||
|
||
In version 4 a package source bills only its `byte_days`, and its work is its run's job line.
|
||
There is one line for each source and unit whose
|
||
quantity is above 0, a price of 0 included, and none for a quantity of 0. A delivery line's bytes are those its party's downstream parties signed
|
||
for (settlement §3.7): a declared byte and a free retrieval are never billed, and the delivery
|
||
report states both (§8.2). An ad line counts impressions under one rule or the other, never both:
|
||
a policy that requires claims bills only what the players' own claims show presented, and one that
|
||
does not bills on the decider's beacons, under a unit of its own.
|
||
|
||
### 6.4 Amounts
|
||
|
||
A line's **amount** is ⌊`quantity` × `price` / divisor⌋, computed in integers wide enough not to
|
||
overflow, and the invoice's `amount` is the sum of its lines' amounts. A line amount or a sum past
|
||
what a u64 holds cannot be stated, and a ledger refuses to compute such an invoice.
|
||
|
||
### 6.5 Citations
|
||
|
||
Each line cites the records it came from:
|
||
|
||
- a room line: the receipts of its room whose figure of the unit is above 0;
|
||
- a delivery line: the statements of its party with a delivery line of the class that is not free,
|
||
and each acknowledgement (mode 1) they name with an entry of the class that is not free (a
|
||
retrieval class with a zero `grant` is free);
|
||
- a package line: the package receipts of its packager whose figure of the unit is above 0; in
|
||
version 4, the held receipts its `byte_days` count;
|
||
- an ad line: the receipts of its decider with at least one impression counted under the unit, and,
|
||
for `presented_impressions`, each counted impression's own claim; of a stitched source, its
|
||
stitcher's accepted records, and each presented own claim of their ads;
|
||
- a job line: for each job it counts, its route record and its billed hop's OER/2 receipt, and,
|
||
for `subpixels`, each of its output receipts whose `work_pixel_ops` is above 0. In versions 3
|
||
and 4, an output receipt that two jobs of the line delivered is cited once and its
|
||
`work_pixel_ops` counted for each (§6.9); in version 4, for `work_units`, each of its output
|
||
packages whose `work_units` is above 0, a package that two runs of the line made cited once
|
||
and counted for each; in version 6, for `subpixels`, each of its upscale and rendition records,
|
||
counted as an output receipt is, and for `usage`, its billed hop's third-party record;
|
||
- a transmission line (version 7): for each standing schedule with an entry the line bills, the
|
||
group receipt, the schedule's claims and its instance's transmission claims, or, of a cache source,
|
||
its cache-transmission claims and the declarations naming them (§4.10);
|
||
- an aggregated line (version 7): each receipt it counts (§4.11);
|
||
- a consumption line (version 7): each claim it counts (§4.12);
|
||
- a storage line (version 8): each record it counts whose `byte_seconds` is above 0, and each
|
||
snapshot those records name (§4.13).
|
||
|
||
`cited` is their number, and `cites` is SHA-256 over the 17 bytes `wai:ledger-cites` (ASCII) and
|
||
0x01, followed by each cited record's `kind` and identity, in ascending order of (`kind`,
|
||
identity). Every cited record is in `records`. A buyer recomputes a line from the records it
|
||
cites alone, and shows one line to an auditor with its records and nothing else. One line is
|
||
the exception: a job line of version 3 or 4 two of whose jobs delivered one output receipt names each job
|
||
and that output once, and how many of its jobs delivered the output is stated by their sources,
|
||
each of which pairs its job with its outputs (§5.1).
|
||
|
||
### 6.6 Energy
|
||
|
||
Each record that states an energy figure states it once, in one **scope**:
|
||
|
||
| scope | figures |
|
||
|---|---|
|
||
| 1 `room_hops` | the per-hop records named by the room receipts (each restated by its receipt, live-metering §4.5) |
|
||
| 2 `delivery_hops` | the per-hop records named by the statements and by no room receipt of the invoice |
|
||
| 3 `packaging` | the package receipts' `joules_micro` and class; in version 4 none: a package's figure is its run's, which the run's hop states (§4.7) |
|
||
| 4 `ad_decisions` | the ad receipts' `joules_micro` and class; a pod-input record states no figure |
|
||
| 5 `jobs` (versions 2 to 4) | each job source's billed hop's figure (§5.1): the hop that served the job, in the class its OER/2 receipt states; a job with no billed hop states none |
|
||
| 6 `unbilled_hops` (version 4) | each job source's attempts that are not billed (route-record §5.2): a failed hop and one that served past the deadline, each its OER/2 receipt's figure (§5.1) |
|
||
| 7 `transmissions` (version 7) | each instance a group or cache source declares, its declaration's or claim's figure, once (§4.10): what transmitting on it spent, every repetition included |
|
||
|
||
A failed hop spent energy and delivered nothing, and a hop that served late spent it and
|
||
delivered too late: neither is billed, and before version 4 neither appeared in any row, so an
|
||
invoice's energy for its jobs was less than their hops spent. Version 4 states them in a scope
|
||
of their own, beside the billed hops' and never summed with them: the jobs' energy is scope 5
|
||
and scope 6 together, per class, and what the buyer was billed for is scope 5 alone. No line
|
||
reads scope 6.
|
||
|
||
For each scope, `unmetered` counts its figures that are the unmetered marker, which are in no row
|
||
and **MUST NOT** be presented as zero joules. For each scope and each tag among its metered
|
||
figures there is one **row**: `figures`, their number; `joules`, their sum; and `max_ppm`, the
|
||
largest `relative_ppm` among them for tags 4 and 5, which carry a declared uncertainty, and 0 for
|
||
tags 2 and 3, which do not. When each figure's error is within its declared relative uncertainty,
|
||
the sum's is within `max_ppm` of the sum. A row never sums figures of two classes, and no row sums
|
||
two scopes: a relay's counter reading, a packager's model and a decider's estimate are three rows,
|
||
since a sum of a model and a counter reading is neither. A row whose `tag` is 0 is refused
|
||
`classes_summed`, and so is a row whose `joules` is the sum of the figures of its class and of at
|
||
least one other class of its scope, while not the sum of its own (live-metering §4.5's rule). A
|
||
scope's energy is **whole** when its `unmetered` is 0 and it has a row, **partial** when it has an
|
||
unmetered figure, and **none** when it has no figure; a partial total **MUST NOT** be presented as
|
||
the scope's energy.
|
||
|
||
### 6.7 Digest and signature
|
||
|
||
The **digest** of an invoice is SHA-256 over its bytes before `sig`. Its signature is Ed25519 by
|
||
`seller` over the 19 bytes `wai:ledger-invoice` (ASCII) and 0x01, followed by the bytes the digest
|
||
covers, verified strictly (SPEC §7 *Signatures*).
|
||
|
||
### 6.8 Reading and rules
|
||
|
||
A reader reads exactly the bytes it is given as one invoice, as §4.3 reads a tariff with `WLI1`
|
||
for `WLT1` (`truncated`, `malformed`, `unknown_version`), and refuses as `classes_summed` an
|
||
invoice with a row of tag 0. It refuses as `private_kind` an invoice with a record of a kind 128 to 255 (§5.2), and as
|
||
`invoice_invalid` one that breaks any of these:
|
||
|
||
- `start` is below `end`; `currency` is three capitals `A`–`Z`;
|
||
- each list is in the strictly ascending order §6.1 gives it; each record's `kind` is 1 to 9 (in
|
||
versions 2 to 4, also 14 to 16: kinds 10 to 13 are no ledger source's, §5.2; in version 6, also
|
||
17 to 19; in version 7, also 17 to 25; in versions 8 and 9, also 17 to 27);
|
||
- each line's `source_kind` is 1 to 4 (1 to 5 in versions 2 to 4, 1 to 8 in version 7, 1 to 9 in
|
||
versions 8 and 9), its `unit`
|
||
a unit of its kind in its version (§6.3; for kinds 5 and 6, at least 1), its `quantity` and
|
||
`cited` above 0;
|
||
- each row's `scope` is 1 to 4 (1 to 5 in versions 2 and 3, 1 to 6 in version 4, 1 to 7 in versions
|
||
7 to 9), its `tag` 2 to 5 and its `figures` above 0.
|
||
|
||
Then the signature (§6.7): `bad_key`, `bad_signature`.
|
||
|
||
### 6.9 Chains
|
||
|
||
The invoices of one tariff form a **chain**: each names in `prev` the invoice before it, the first
|
||
names zero, and their periods do not overlap. A tariff of version 9 that follows another (§4.14)
|
||
continues that tariff's chain: its first invoice names the last invoice of the chain it follows, no
|
||
invoice of it names zero, and every rule of this section reads across the two tariffs as within
|
||
one. A ledger keeps one chain per tariff, and a chain a following tariff continues is one chain.
|
||
No record is in
|
||
the `records` of two invoices of a chain, but, under a tariff of version 3 or 4, an output receipt
|
||
(kind 15), under one of version 6 an upscale record and a rendition record (kinds 18 and 19, §4.9),
|
||
under one of version 7 a group receipt (kind 20), which each transmission of the group cites
|
||
(§4.10), and under one of version 4 a package receipt (kind 5), which each run that made it
|
||
cites and each invoice whose period it is held through lists again to bill its storage (§4.7): a record billed once is billed never again, whatever period a later invoice states (a storage record and a snapshot among them, §4.13), and
|
||
a package receipt, which states no time, is billed in the invoice that first holds it.
|
||
|
||
What a chain bills once for a job is its **work**, and its output's receipt is the **evidence**.
|
||
A run of a job is a hop that did it: new energy, and a new OER/2 receipt and route record, new
|
||
on every run. An output receipt is not the work: the codecs are deterministic, so the same request
|
||
run again delivers the same objects, of the same content hashes, under the same receipt. Under a
|
||
tariff of version 3 or 4, therefore:
|
||
|
||
- the records a chain bills once for a job are its route record and its hops' OER/2 receipts,
|
||
the billed hop's among them, and in version 6 its hops' third-party records, each of one hop;
|
||
- an output receipt is cited, and carried in its lines' citation digests, but is not billed once:
|
||
a later invoice may list it again for another job's hop;
|
||
- a re-run whose route record and hop receipt are new is billed, in the invoice that holds it;
|
||
- a source with a hop receipt or a route record the previous invoice holds is refused
|
||
`record_rebilled`, and one with a hop receipt an earlier source of the invoice gives is refused
|
||
`record_duplicate` (§5.2): a replay of either is never billed;
|
||
- two lines of one invoice may cite one output receipt only under different hop receipts.
|
||
|
||
Under a tariff of version 2, an output receipt is billed once as well, and a re-run of a job
|
||
whose output an invoice of the chain holds is refused, as that tariff's buyer signed it. A
|
||
package keeps its rule in versions 1 to 3: it is billed as a delivered product, once per package
|
||
receipt, which is a rule of its own and not a job's. In version 4 it has a job's shape: the run
|
||
that made it is the work, billed once per run, and its receipt the product, cited by each run;
|
||
its storage is billed for each period it is held (§4.7).
|
||
|
||
## 7. Verification
|
||
|
||
### 7.1 Inputs
|
||
|
||
A verifier is given the **tariff**, the **invoice**, the invoice its `prev` names (the
|
||
**previous**, or none), and the **sources**, a list. The ledger's verification document holds them
|
||
as one JSON object: `tariff` and `invoice` (hexadecimal), `previous` (hexadecimal or `null`) and
|
||
`sources` (§5.1).
|
||
|
||
### 7.2 Steps
|
||
|
||
It runs these steps and stops at the first refusal, which it reports with the reason and where:
|
||
|
||
1. **The tariff** (§4.3), at `tariff`, or `tariff` and `seller` or `buyer` for a signature:
|
||
`truncated`, `malformed`, `unknown_version`, `tariff_invalid`, `bad_key`, `bad_signature`.
|
||
2. **The invoice** (§6.8), at `invoice`: `truncated`, `malformed`, `unknown_version`,
|
||
`classes_summed`, `private_kind`, `invoice_invalid`, `bad_key`, `bad_signature`.
|
||
3. **The binding**, at `invoice`: its `tariff` is the tariff's digest, and its `version`,
|
||
`seller`, `buyer` and `currency` the tariff's: otherwise `tariff_mismatch`; its period lies within the tariff's:
|
||
otherwise `outside_tariff`.
|
||
4. **The previous**, at `previous`. Under a tariff that follows another (§4.14), `prev` is not
|
||
zero (`chain_restarted`). When `prev` is not zero: an invoice whose digest is `prev` is given
|
||
(`record_missing`); it reads and its signature verifies (§6.8, with those reasons); its `tariff`
|
||
is the invoice's, or, under a tariff that follows another, the digest it follows, and its
|
||
`seller` and `buyer` are the invoice's (`tariff_mismatch`); and its `end` is at most the
|
||
invoice's `start` (`invoice_overlap`).
|
||
5. **Each source**, in order, at `source` and its index: it is verified as §5.1 says, a refusal
|
||
being that extension's reason with that extension's place after the index (an `ads` gap is
|
||
`source_gap`, a `storage` source's reasons and places §4.13's, and a source that does not read
|
||
`malformed`); then it is in the scope (§4.4, `outside_scope`); a room receipt or a statement
|
||
that states a tariff states this one (§3, `tariff_conflict`); and it is in the invoice's period
|
||
(§5.3, `outside_period`).
|
||
6. **Across sources**, at `source` and the index of the later: a head of two sources
|
||
(`record_duplicate`); an instance of a group that an earlier source declares (§5.2,
|
||
`record_duplicate`, or `bearer_contradicted` when another key declared it); a receipt, statement,
|
||
ad receipt or storage record overlapping an earlier one, or, in
|
||
version 2, a route record of the router and job an earlier one names (§5.3,
|
||
`record_overlap`); and a record that is in the previous invoice's `records`, in versions 3 and
|
||
4 an output receipt excepted, in version 4 a package receipt, in version 6 an upscale or
|
||
rendition record, and in version 7 a group receipt (§6.9, `record_rebilled`).
|
||
7. **The figures**, at `invoice`, recomputed from the sources as §6.2 to §6.6 compute them and
|
||
compared in this order:
|
||
1. a line whose source and unit no source gives, or that states a larger quantity than the
|
||
sources give: `quantity_not_recorded`, a quantity no signed record covers;
|
||
2. a row that §6.6 calls summed across classes: `classes_summed`;
|
||
3. a line whose `cited` or `cites` is not the records it came from: `citation_mismatch`;
|
||
4. any other difference (the records, a line missing, a smaller quantity, a price, an amount, a
|
||
row, `unmetered`, the `amount`): `invoice_mismatch`.
|
||
|
||
A figure that cannot be held in its field is a difference.
|
||
|
||
### 7.3 Outcome
|
||
|
||
- **refuse**: the reason and where.
|
||
- **accept**: the invoice's digest; the tariff's digest, and, under a tariff that follows another,
|
||
the digest it follows (§4.14); the currency and the period; the number of
|
||
records; each line with its source kind, source, unit name (and, for a job line, the job
|
||
price's `capability`, in versions 3 and 4 its `operation`, and in version 6 its `endpoint` and,
|
||
for a usage, its `usage` as `usage_unit`; for a transmission line, its transmission price's
|
||
`bearer` and `max_bps`), quantity, price, amount and its
|
||
cited records; each energy row by scope and class label with its figures, joules and `max_ppm`;
|
||
each scope's unmetered figures and coverage (scopes 1 to 4, in versions 2 and 3 scope 5, in
|
||
version 4 scopes 5 and 6, and in versions 7 to 9 scopes 5 to 7); the
|
||
amount; and the reports of §8, in versions 7 to 9 with §8.3's, and in versions 8 and 9 with
|
||
§8.4's.
|
||
|
||
## 8. Reports
|
||
|
||
The reports are computed from the verified sources, as the lines are, and are stated with every
|
||
accepted invoice. They are not signed: anyone holding the sources computes them, and a verifier
|
||
compares them.
|
||
|
||
### 8.1 Ad decisions against presentation claims
|
||
|
||
For each `ads` source, in order: its room, whether its policy requires claims, and each receipt in
|
||
its list's order, with its identity, decider, `cue` and `session`, and each impression's `slot`,
|
||
`ad_id`, `price_micros` and `quartiles_reached`, whether it is **billable** (the decider's beacons:
|
||
a quartile of at least 1), whether it **counts**, and its **verdict**: under a policy that requires
|
||
claims, `presented` or the reason its own claim did not count, `claim_absent` among them
|
||
(ad-presentation §9.2); under one that does not, `beacons`. Then the receipt's billable impressions
|
||
and their spend, `budget_spent_micros`, the seller's figure; and its counted impressions and their
|
||
spend, the presented spend (ad-presentation §9.3), the buyer's. Then, over the source: the
|
||
billable and the counted impressions, the billable and the counted spend, and, for each verdict
|
||
other than `presented`, the billable impressions that did not count with it.
|
||
|
||
So a seller's receipts and a buyer's claims are reconciled from the same signed bytes: what the
|
||
seller billed, what the players presented, and why each impression that was billed and did not
|
||
count did not.
|
||
|
||
For each `stitched` source, in order, the report is the statement of stitched-presentation §7.5 as
|
||
that extension's verifier gives it, unchanged: each record's verdict, each ad's presentations,
|
||
quartiles and presented spend, and, for a checked form-1 response, the receipt's own quartile and
|
||
spend beside them; each claim's verdict; and the spend by currency, never summed across currencies.
|
||
That statement is the seller-against-buyer reconciliation of a stitched stream, and the ledger
|
||
computes no second one.
|
||
|
||
### 8.2 Delivery by party
|
||
|
||
For the `delivery` sources together, each party in ascending order of key: the digests of its
|
||
statements; their `currency` (the stated one, or `null`); the acknowledged objects and bytes of
|
||
each class; the free retrieval bytes; the declared declarations, objects and bytes (settlement §4),
|
||
never billed; the sum of its statements' own `amount`s; the sum of the invoice's lines of the party;
|
||
and its energy rows and unmetered figures over its per-hop records.
|
||
|
||
Then the **overlaps**: for each pair of acknowledgements (mode 1) of two different parties, signed
|
||
by one downstream key, whose windows overlap, and each content hash that an item of each names with
|
||
byte ranges that share bytes, one overlap. It states the content hash, the downstream key, the bytes
|
||
shared, summed over every such pair of items, and the two parties with their acknowledgements'
|
||
digests, the lower party first. The overlaps are in ascending order of (content hash, downstream,
|
||
first party, first record, second party, second record). An overlap is billed by both parties, since each was acknowledged; it is what a buyer
|
||
using several delivering parties disputes with them, and the report names the signatures it rests
|
||
on.
|
||
|
||
### 8.3 Transmissions (version 7)
|
||
|
||
For each `group` and `cache` source, in order: its group's link hash as `group`, its publisher or
|
||
node as `publisher`, `cache`, whether it is a `cache` source, and each entry billed of each of its
|
||
standing schedules, the schedules in ascending order of `bearer_id` and each schedule's
|
||
entries in its order: its `bearer_id`, its instance's declared `bearer`, its `leaf_index`,
|
||
`bytes_sent` and `pass_us`, its pass rate as `rate_bps` (`null` above 2^53 − 1, every ceiling's
|
||
bound), and, as `bytes_sent_price` and `pass_us_price`, the index from 1 in the tariff's
|
||
`transmission` of the price it is billed at in each unit (§4.10), or `null` where its pass rate is
|
||
above every ceiling of its class and that unit. An entry with no price in a unit was sent and is
|
||
billed nothing in it: the report says which, so a buyer sees what the tiers it signed leave
|
||
unpriced.
|
||
|
||
### 8.4 Storage (version 8)
|
||
|
||
For each `storage` source, in order: its record's `holder` and `subject`, its interval as `start`
|
||
and `end`, the number of its `snapshots`, and its `byte_seconds`. A line sums a holder's records
|
||
into byte-days, rounded down once; the report states each set's own figure, so a buyer sees what
|
||
each window and each clip held, and recomputes the line from them.
|
||
|
||
## 9. The reference ledger service
|
||
|
||
`wai/wai-ledger` runs the ledger as an HTTP service over a directory it owns:
|
||
|
||
| request | does |
|
||
|---|---|
|
||
| `GET /v1` | the service, its seller key, its limits |
|
||
| `GET /v1/health` | `ok` |
|
||
| `POST /v1/tariffs` | `{"tariff": hex}`: a tariff whose seller is the service's key, both signatures verified (§4), kept by its digest; a tariff that follows another (§4.14) continues the chain of a tariff the service holds, of its buyer, that no other follows and whose chain has an invoice (`record_missing` or `tariff_mismatch` at `tariff`, `follows`), and closes it |
|
||
| `POST /v1/sources` | `{"tariff": digest, "source": {...}}`: the source verified (§7.2 steps 5 and 6 against what the tariff's chain holds), kept by its heads |
|
||
| `POST /v1/invoices` | `{"tariff": digest, "start", "end"}`: the invoice of the period over the sources held and not yet billed, chained, signed and kept, with its outcome (§7.3) |
|
||
| `GET /v1/invoices/{digest}` | the invoice, its outcome and its verification document (§7.1) |
|
||
| `POST /v1/verify` | a verification document: its outcome |
|
||
|
||
A tariff that follows another takes over the chain of the tariff it follows: its first invoice names
|
||
that chain's last, the records every invoice of the chain lists are billed (§6.9), and every source
|
||
the closed tariff holds that its next invoice would bill is held under the following one, each
|
||
verified again under it (§7.2 steps 5 and 6). A package that chain holds whose packager the
|
||
following tariff does not name is left behind, billed no more. Any other source the following
|
||
tariff refuses, or one some of whose records it would no longer bill (`outside_scope`), refuses the
|
||
following tariff, at `tariff`, `follows`, `source` and the source's index, so the seller bills it
|
||
under the tariff that names it first. A source or an invoice under a closed tariff is refused
|
||
`tariff_mismatch`.
|
||
|
||
Each refusal names its reason and place. The service writes every file whole (to a temporary name,
|
||
synced, then renamed), holds a lock on its directory so that one process writes it, and recovers
|
||
each tariff's chain and held sources from the directory when it starts. A buyer fetches an
|
||
invoice's verification document and checks it with any verifier of this extension, the service's
|
||
own not among them.
|
||
|
||
## 10. Reasons
|
||
|
||
The codes this extension adds, each with where it is raised:
|
||
|
||
| reason | raised at |
|
||
|---|---|
|
||
| `tariff_invalid` | §4.3, §7.2 step 1 |
|
||
| `invoice_invalid` | §6.8, §7.2 step 2 |
|
||
| `tariff_mismatch` | §7.2 steps 3 and 4 |
|
||
| `outside_tariff` | §7.2 step 3 |
|
||
| `invoice_overlap` | §6.9, §7.2 step 4 |
|
||
| `source_gap` | §5.1, §7.2 step 5 |
|
||
| `outside_scope` | §4.4, §7.2 step 5 |
|
||
| `tariff_conflict` | §3, §7.2 step 5 |
|
||
| `outside_period` | §5.3, §7.2 step 5 |
|
||
| `record_duplicate` | §5.2, §7.2 step 6 |
|
||
| `record_overlap` | §5.3, §7.2 step 6 |
|
||
| `record_rebilled` | §6.9, §7.2 step 6 |
|
||
| `quantity_not_recorded` | §7.2 step 7 |
|
||
| `citation_mismatch` | §6.5, §7.2 step 7 |
|
||
| `invoice_mismatch` | §7.2 step 7 |
|
||
| `private_kind` | §5.2, §6.8, §7.2 step 2 |
|
||
| `output_invalid` | §4.8, §4.9, §5.1, §7.2 step 5 |
|
||
| `job_figure_invalid` | §5.1, §7.2 step 5 |
|
||
| `output_not_delivered` | §4.8, §4.9, §5.1, §7.2 step 5 |
|
||
| `storage_invalid` | §4.13, §7.2 step 5 |
|
||
| `snapshot_mismatch` | §4.13, §7.2 step 5 |
|
||
| `outside_interval` | §4.13, §7.2 step 5 |
|
||
| `storage_mismatch` | §4.13, §7.2 step 5 |
|
||
| `chain_restarted` | §4.14, §6.9, §7.2 step 4 |
|
||
|
||
A verifier of this extension also raises `truncated`, `malformed` and `unknown_version` for a
|
||
tariff, an invoice, a snapshot or a storage record that does not read, and `malformed` for a source that does not read (§5.1); `bad_key` and `bad_signature` for their signatures;
|
||
`record_missing` (live-metering §9) for a previous invoice not given; `classes_summed`
|
||
(live-metering §9) for a row over classes; `bearer_contradicted` (bearer-receipts §10) for an instance
|
||
two keys declare across sources (§5.2); and, at a source, every code its extension's verifier
|
||
raises: live-metering §9 and the codes it lists, settlement §11 and the codes it lists, packaging
|
||
§12, live-ads §10 with ad-presentation §11, at a `job` source, route-record §8 and the
|
||
codes it reuses, at a `group` source, jwp-receipts §3's and §3.1's codes, bearer-receipts §10's and
|
||
carousel §9's, at a `cache` source, those and cache-authority §11's and settlement §3.6's, at an
|
||
`aggregated` source, `statement_invalid`, `task_invalid`, `wrong_signer` and `batch_invalid`
|
||
(telemetry-aggregation §11) and `count_mismatch` (age-assurance §7.3), and, at a `consumption` source, jwp-receipts §3.1's and ai-usage §9's. A `stitched` source raises none: the codes of
|
||
stitched-presentation §9 are the verdicts of its records and claims, stated in its report (§8.1).
|
||
|
||
## 11. Conformance
|
||
|
||
[`live-conformance/ledger/`](../live-conformance/ledger/) holds the corpus, in one file,
|
||
`vectors.json`, written by `wai_receipt_ledger_vectors gen` from fixed seeds and from sources taken
|
||
from the corpora of the extensions it reads (`live-conformance/metering/`,
|
||
`live-conformance/settlement/`, `live-conformance/ads/`, `live-conformance/presentation/`,
|
||
`live-conformance/stitched/`, `live-conformance/routes/` and `pack-conformance/packs/`), with
|
||
delivery statements of two parties signed for it and, for each media job, a sink's
|
||
`wai.video.int_motion` decode receipt of its output over a payload of
|
||
`wai-rs/tests/vectors/int_video/`, and, for version 3, the route records of a decode, a re-run, a
|
||
replayed hop receipt and a claimed one, routed and sealed under the route corpus's own seeds, as
|
||
are jobs routed under the route record's version 2, its price book of version 2 with its
|
||
per-operation entries and measured failures, the served hop stating its outputs, and, for version
|
||
7, a broadcaster's groups with their declarations and carousel schedules, a node's own instance of
|
||
one with its schedule and settlement declaration and an agent's consumption claims, signed for
|
||
them from fixed seeds, and the aggregate receipts of
|
||
[`live-conformance/impressions/`](../live-conformance/impressions/), and, for version 8, a holder's
|
||
snapshots and storage records of a window and a clip over two days, signed for it from fixed seeds. The sources are held once, by name, and each vector is a verification document (§7.1) naming its sources, with the
|
||
outcome §7.3 gives it:
|
||
|
||
- **Accepted**: an invoice of one day billing a lesson room, two delivering parties and a viewer
|
||
that forwarded sealed objects under no tariff of its own, a package, ads under a policy that
|
||
requires claims and under one that does not, with both reports, one viewer acknowledging one
|
||
object from both parties among the overlaps; the next invoice of its chain, billing a relay's
|
||
session whose energy is unmetered, and a second package; and an invoice whose room hops are of
|
||
three classes, one row each; and an invoice of streams stitched by others, one with a form-1
|
||
receipt whose own figures the report states beside the presented ones; and, under a tariff of
|
||
version 2, a month of media jobs one router routed, beside a package: an `int_motion` job billed
|
||
per job and per subpixel of its output's receipt, a failover billed at the fallback's price, a
|
||
job served past its deadline and one every allowed hop failed, which bill nothing, and a job
|
||
whose serving hop was unmetered, counted unmetered in the jobs' scope; and, under a tariff of
|
||
version 3, the same jobs priced per operation with an `int_motion` decode beside the encodes,
|
||
each at its own price; the next invoice of that chain, billing the first job run again, its
|
||
route record and hop receipt new and its output receipt one the first invoice holds; the job
|
||
and its re-run in one invoice, their shared output receipt cited once and its subpixels billed
|
||
for each; and a decode under a tariff that prices only the encode, which bills nothing; jobs
|
||
routed under the route record's version 2 billed under version 3 (an encode, a failover billed
|
||
at the endpoint that served, a decode, a hop past the deadline and three that failed); and,
|
||
under a tariff of version 4, a lesson room's receipt of version 2 billed by its bytes out
|
||
beside its time, a package listed and the run of `package.build` that made it, billed per run
|
||
and per work unit, and those jobs with every hop's energy, the failed and late hops' in their
|
||
own scope, one of them unmetered; and the next invoice of that chain, billing the package it
|
||
holds for the byte-days of its own period and the same package made again by a new run, its
|
||
work billed again and its receipt cited again, beside a second package listed; and, under a
|
||
tariff of version 5, an `int_motion` decode whose served hop states it delivered one animated
|
||
PNG of the clip's frames, its receipt re-derived from the codestream it read, beside an encode
|
||
held to its codestream; and jobs whose route records are of version 3, each output proved
|
||
among what its hop delivered: an encode whose clip is the second of two objects, a decode of
|
||
version 5 whose animation is its one object, and a package's run whose receipt is the first
|
||
of 1,501 objects; and, under a tariff of version 6, a third party's jobs billed per job and by
|
||
what each record states the provider bills, each endpoint at its own price: a served hop,
|
||
another provider's, a failover whose failed hop's billed usage reaches no line, a job with no
|
||
record, a job in another unit at that unit's price, and one in a unit no price names; an encode,
|
||
a decode held to its frames and a package's run, billed as version 5 bills them; an upscale of
|
||
two pictures and two tone mappings, one of whose records states two pictures of one rendering,
|
||
each re-derived from what it read; the next invoice of that chain, billing the upscale run again
|
||
and citing its records again; and an upscale and a tone mapping whose route records are of
|
||
version 2; and, under a tariff of version 7 that prices multicast octets at two ceilings and pass
|
||
time at one and broadcast octets at one ceiling and pass time at two, a month of a broadcaster's
|
||
transmissions in four invoices chained a week apart: a group simulcast on a broadcast and a
|
||
multicast instance, each entry at the least ceiling covering its pass rate, each declaration's
|
||
energy in its class's row; a faster broadcast, one entry above every ceiling of its class's
|
||
octets, billing its pass time alone, beside the first week's group sent again on a new instance,
|
||
its group receipt listed again; a multicast entry above every ceiling of its class, billing
|
||
nothing, and a declaration with no figure; a broadcast beside a relay chain declared and
|
||
scheduled nowhere; and a fifth invoice after the month, billing a broadcast whose schedule a later
|
||
one extends, a node's own multicast instance of that group with an object scheduled and not sent,
|
||
the counts of two aggregate receipts whose aggregators state different `rejected` counts, and an
|
||
agent's two chained consumption claims; two sources of one group on one invoice, each of an
|
||
instance of its own; two groups on one broadcast service; an aggregate receipt in the hour its batch
|
||
fills, and one of statements of version 1; and a node's plan with an
|
||
entry past the period that its claim does not say it sent, billing what it did; and, under a
|
||
tariff of version 8, a day of a holder's storage, a stream's window empty at the day's start and
|
||
then listing three, five and four segments, one snapshot a microsecond after noon so that its
|
||
byte-seconds round down, and a clip cut at 13:00, on one line of byte-days; the next day of its
|
||
chain, each set's record from the day's start and the clip's ending at its deletion; that day at a
|
||
storage price of 0; a record of 1,000 byte-seconds, which bills no line and is listed; and the
|
||
window's day beside an agent's consumption claims and an aggregate receipt's count, each billed as
|
||
version 7 bills it; and, under tariffs of version 9, one buyer's chain across three tariffs, each
|
||
following the one before it: the first day billing signer 1's stitched stream and first listing a
|
||
package, the next day under a tariff that adds signer 2's key billing the storage of the package
|
||
the first day's invoice holds and signer 2's interstitials, and the day after under a tariff that
|
||
retires signer 1's key billing the package's storage again; and the second day's scope under a
|
||
tariff that follows none, whose first invoice bills no storage for the package, as before.
|
||
- **Refused**: each reason of §10 at least once, each vector a control of one defect; a source of
|
||
each kind outside the scope, a room receipt and a statement under other prices, and a source of
|
||
each timed kind outside the period; a refusal of each source kind by its own extension; and, for
|
||
version 2, job prices out of order, a router in a version-1 tariff's scope, a job source under a
|
||
version-1 tariff, a version-1 invoice under a version-2 tariff, a job given twice, routed twice,
|
||
and claiming another job's output, and a job line and a jobs row that do not recompute; and an
|
||
invoice of each version listing a record of a kind reserved for private use, and one listing
|
||
another text's kind; and, for version 3, job prices out of order by operation, a version-2
|
||
invoice under a version-3 tariff, a hop receipt the previous invoice billed brought again
|
||
under a new route record, and one hop receipt claimed by two jobs billed on two lines; and,
|
||
under a tariff of version 2, the same re-run, refused because its output receipt was billed;
|
||
and, for a job routed under the route record's version 2, an output receipt of a clip its hop
|
||
did not deliver and one output given twice (`output_not_delivered`); and, for version 4, a
|
||
price of bytes other than the receipt's and a receipt of version 1 under a price of bytes
|
||
(`tariff_conflict`), bytes out above the receipt's, storage billed for a package first listed,
|
||
a held package's storage over the tariff's period rather than the invoice's, a package's run
|
||
replayed under a new route record in the next invoice (`record_rebilled`) and in the same one
|
||
(`record_duplicate`), a failed hop billed as a job and a job line at the router's list price, the unbilled
|
||
hops' energy left out or added to the billed hops' row, an unbilled hop whose figure states no
|
||
class (`job_figure_invalid`), an output of a route record of version 1, and an invoice of
|
||
version 3 under a tariff of version 4; and, for version 5, a decode whose record states the
|
||
codestream it read, and one whose record states it after the animation
|
||
(`output_not_delivered`), a decode in version 4's form (`malformed`), a frame with one sample
|
||
changed, two frames swapped, a still for the animation, a frame missing, frames of another
|
||
shape holding the same samples, a codestream not the receipt's, and an animation that blends
|
||
a frame over the one before, disposes of one by no defined operation, holds a frame of part of
|
||
the picture, skips a sequence number, keeps its default image apart from its frames, counts a
|
||
frame more than it holds, or has a frame with no data (`output_invalid`), a decode in
|
||
version 5's form under a tariff of version 4, and an invoice of version 4 under a tariff of
|
||
version 5; and, for jobs routed under the route record's version 3, an output without its proof,
|
||
a proof under a record of version 2 and a proof whose index is text (`malformed`), a proof of
|
||
another place, one past the count, one a sibling short, an output its hop did not deliver, one
|
||
output twice, a decode's animation at another place, a decode with an object past its animation,
|
||
and an output of a job no hop served (`output_not_delivered`); and, for version 6, job prices out
|
||
of order by endpoint, a price of any endpoint beside one, a price of usage naming no unit, a
|
||
price per job naming one, an endpoint not of its form and a unit past `usage`
|
||
(`tariff_invalid`); a price of usage under version 5, and an invoice of version 5 listing a
|
||
third-party record (`invoice_invalid`), and an invoice of version 5 under a tariff of version 6;
|
||
a job given third-party records, and an upscale and a tone mapping in version 6's form, under
|
||
version 5 (`malformed`); another job's record (`third_party_mismatch`); a failed hop's usage added to a
|
||
line, a usage line for a job with no record, and subpixels above a record's
|
||
(`quantity_not_recorded`); a usage at another endpoint's price and a record left out of the
|
||
invoice's (`invoice_mismatch`), and a usage line not citing its records (`citation_mismatch`);
|
||
an upscale whose picture is altered, of another shape or not a PNG, under another prior, of
|
||
another input, whose input is not an envelope, of another capability or not RGB, whose record
|
||
states another output, names a residual or does not verify (`output_invalid`), whose picture its
|
||
hop did not deliver or given twice (`output_not_delivered`), in an encode's form (`malformed`);
|
||
and a tone mapping with a rendition altered, one missing, renditions out of order, of another
|
||
envelope, whose record does not verify (`output_invalid`), with a rendition its hop did not
|
||
deliver or given twice (`output_not_delivered`), a proof short, without its proofs, with proofs
|
||
under a list, or in an encode's form (`malformed`); and, for version 7, transmission prices out
|
||
of order, one ceiling priced twice, a price of a bidirectional bearer, a unit past `pass_us`, a
|
||
ceiling of 0, a ceiling and a price past 2^53 − 1, and a publisher in a tariff of version 6
|
||
(`tariff_invalid`); an invoice of version 6 listing a group receipt (`invoice_invalid`) and one
|
||
under a tariff of version 7 (`tariff_mismatch`); a group under version 6 (`malformed`); a line
|
||
at a ceiling below its entry's pass rate, one at a dearer ceiling than the least that covers it,
|
||
and an entry above every ceiling billed (`quantity_not_recorded`); the transmissions' rows left
|
||
out and an unmetered transmission left out (`invoice_mismatch`); a line not citing its
|
||
declaration (`citation_mismatch`); a publisher outside the scope, a group outside the period, a
|
||
group given twice and a declaration billed again; and, by the texts a group source is verified
|
||
by, a schedule contradicted, one with no declaration, one on a relay chain, declarations
|
||
contradicted, a schedule of another group, a chain not held and one broken, a group receipt
|
||
altered, and an object receipt of another group; an aggregated count stated under
|
||
`presented_impressions` and under `billable_impressions`, one above its receipts' count, a node
|
||
billed an object it did not send and a consumption line above its claims (`quantity_not_recorded`);
|
||
a collector and an agent outside the scope, overlapping batches on one invoice and on two of a chain,
|
||
a receipt billed again in the next invoice and two invoices on, a batch a microsecond before and past
|
||
its period and one past any instant, a schedule extended after it was billed, a claim issued at the
|
||
period's end and one in the year 0000, a node's declaration outside the period, and a node's entry past the period that its
|
||
claim says it sent; one schedule and one instance of a node's in two sources, one instance of a
|
||
publisher's in two sources of its group (`record_duplicate`), and a node naming the publisher's
|
||
instance, before and after the group's source, and two nodes naming one
|
||
(`bearer_contradicted`); a node's instance with no declaration, with one of another claim or key, its claims and
|
||
schedules contradicted or undeclared, signed by the publisher or by another key, or given a
|
||
publisher's claim; an aggregate receipt that does not read, of a version not defined, with its
|
||
signature failing or its result not its count; a task cut short and one of no precision
|
||
(`task_invalid`); a leader's statement of another magic, of a version not defined at either version's
|
||
length, of version 2's length stating version 1, of no role, a byte short and a byte over (`statement_invalid`), of the
|
||
helper's role (`wrong_signer`) and of a batch of no time (`batch_invalid`); a consumption source of two agents, of another
|
||
class, of no claim, without its parent or after another claim; each of the three kinds under
|
||
version 6 (`malformed`); and an aggregated and a consumption price past 2^53 − 1
|
||
(`tariff_invalid`); and, for version 8, a record stating a byte-second more than its snapshots
|
||
support and a clip's record stating its bytes as its byte-seconds (`storage_mismatch`); a line a
|
||
byte-day above its records and a clip's bytes billed as byte-days (`quantity_not_recorded`), and a
|
||
storage line of a second unit (`invoice_invalid`); a second record of the window overlapping the
|
||
day's in one invoice (`record_overlap`), and, in the next invoice, a record reaching back into the
|
||
day before, the first day's record again, and that day's records in another day (`outside_period`);
|
||
a snapshot an hour after its record's interval, a first snapshot after its start and two out of
|
||
order (`outside_interval`); a snapshot whose bytes were raised after it was signed, a record whose
|
||
byte-seconds were, and a snapshot signed as a record (`bad_signature`); a snapshot left out,
|
||
another of the set at the instant of the one named, one of another set and one of another holder
|
||
(`snapshot_mismatch`); a record of no time and a snapshot of no objects stating bytes
|
||
(`storage_invalid`); a record a byte short (`truncated`), of a version not defined
|
||
(`unknown_version`), a snapshot given as a record, a snapshot with a byte after its signature
|
||
and a source with no `snapshots` (`malformed`); a record given twice (`record_duplicate`); a
|
||
holder outside the scope; a storage line not citing its snapshots (`citation_mismatch`) and a
|
||
snapshot left out of the invoice's records (`invoice_mismatch`); a storage price past 2^53 − 1
|
||
and a holder in a tariff of version 7 (`tariff_invalid`); a storage source under version 7
|
||
(`malformed`); an invoice of version 7 listing a storage record (`invoice_invalid`); and an
|
||
invoice of version 7 under a tariff of version 8 (`tariff_mismatch`); and, for version 9, an
|
||
invoice of a following tariff that names no invoice before it (`chain_restarted`), one naming an
|
||
invoice of a tariff it does not follow (`tariff_mismatch`), one beginning before the invoice of
|
||
the chain it follows ends (`invoice_overlap`), signer 1's stream billed again under the tariff
|
||
that follows the one whose chain billed it (`record_rebilled`), a retired key's records billed
|
||
under the tariff that retires it (`quantity_not_recorded`), and an invoice of version 8 under a
|
||
tariff of version 9 (`tariff_mismatch`); the control of an undefined invoice version is of
|
||
version 10.
|
||
|
||
`wai_receipt_ledger_vectors verify` and the test `tests/receipt_ledger.rs` check that the file
|
||
regenerates byte for byte, that `wai-rs` gives every vector its outcome, that every reason of §10
|
||
refuses a vector, that §10 lists exactly the reference's codes, and that the month of version 7,
|
||
the two days of version 8 and the chain across three tariffs of version 9 are made again byte for
|
||
byte from their tariffs, the invoices before them and their sources.
|
||
`live-conformance/receipt_ledger_verify.py` is the second implementation, written from this text:
|
||
it shares no code with `wai-rs`, verifies signatures with WAI's strict rule written from RFC 8032
|
||
(`claim-conformance/_ed25519.py`), verifies each source with that corpus's own second
|
||
implementation (`live_metering_verify.py`, `settlement_verify.py`, `live_ads_verify.py` with
|
||
`ad_presentation_verify.py`, `stitched_presentation_verify.py`, `route_record_verify.py`,
|
||
`upscale_verify.py`, `tonemap_verify.py`, `carousel_verify.py` and `cache_authority_verify.py` with
|
||
`jwp-conformance/jwp_verify.py` and `claim-conformance/claim_verify.py`,
|
||
`telemetry_aggregate_verify.py`'s reader of a receipt, and `pack-conformance/pack_verify.py`) and each output receipt by `_int_motion_receipt.py`, written
|
||
from integer-payloads §15, computes each output's content hash with BLAKE3 written from its
|
||
specification (`claim-conformance/_blake3.py`), recomputes every line,
|
||
citation, row and report itself, gives every vector the same outcome, and requires every mutated
|
||
copy of the corpus to fail.
|
||
|
||
## 12. Security and privacy considerations
|
||
|
||
- **Who signs what.** The buyer signs the prices and the scope; each record's own party signs its
|
||
figures; the seller signs the invoice. A seller cannot bill a unit at a price the buyer did not
|
||
sign, a record of a party the buyer did not name, or a quantity no record states: the verifier
|
||
recomputes every line.
|
||
- **Double billing.** A head is billed once in an invoice (`record_duplicate`), so is an instance of
|
||
a group (§5.2), one session, one statement period, one viewer's break and one stored set's time once (`record_overlap`),
|
||
and a record once in a chain (`record_rebilled`), a chain a following tariff continues being one
|
||
chain, whichever of its tariffs billed the record (§4.14). An aggregate receipt and a batch sharing a time
|
||
unit with it are in one invoice of a chain at most, by their period (§5.3). An instance's claims
|
||
are billed once in a chain; a party that declares one instance again in a new claim for a later
|
||
period gives a record no invoice holds, which a verifier given one invoice bills for that period's
|
||
passes alone, its energy figure stated again, and which the reference ledger, holding every source
|
||
of the chain, refuses (§9). A verifier given one invoice checks it against the one before it; a
|
||
buyer holding the chain checks every link.
|
||
- **Work, not identity.** Under a tariff of version 3 a job is billed for the work done, its
|
||
route record and its hops' OER/2 receipts, once per chain, and its output's receipt is the
|
||
evidence of what it delivered (§6.9). A deterministic re-run does the work again, a new hop,
|
||
new energy, a new receipt, and is billed; a replayed hop receipt or route record is refused,
|
||
which is what keeps a job from being billed twice. A seller cannot bill a job again by citing
|
||
its output again: every billing needs a hop receipt no invoice of the chain holds. What a re-run
|
||
rests on is that hop's receipt: a router and a hop that collude can bill a re-run that never
|
||
ran, as a party and a downstream key can bill bytes (settlement §13). Whether a request is
|
||
worked again or answered from outputs still kept is the router's decision, not the ledger's;
|
||
the ledger bills what was worked. A tariff of version 2 keeps billing an output once.
|
||
- **Bytes, work and storage.** Under a tariff of version 4 a room's bytes out rest on its hops'
|
||
ledgers, which each hop signs by their root (live-metering §3.4), as its time rests on their
|
||
records; a package's work rests on the run that made it, its route record and its hop's
|
||
receipt, new on every run, and on its receipt's work units, which its indexes recompute; and
|
||
its storage on the chain: a package is billed a period's storage only when the invoice before lists it,
|
||
so it was written by the start of the period billed, and a buyer holding the chain sees each
|
||
period billed once. Whether the seller kept the bytes through the period is the seller's
|
||
statement, as a delivery is the acknowledging parties' (settlement §13).
|
||
- **A third party's usage.** Under a tariff of version 6 a job may be billed by what a third
|
||
party's record states the provider bills. That figure is the router's statement: no provider
|
||
signs anything, so the record holds what the router read, with the provider's response kept
|
||
where it was JSON and every byte named by digest (route-record §6.2), and a router can state a
|
||
usage the provider did not bill. A buyer holds the price it signed and the record the router
|
||
signed, each line cites that record, and the provider's own `charge` is stated beside it, so a
|
||
dispute is about a signed figure; it is not recomputable, as a re-derived subpixel is.
|
||
- **What re-derives an output.** Under a tariff of version 6 an upscale's and a tone mapping's
|
||
subpixels are recomputed by the verifier from the record, what it read and what the hop
|
||
delivered. That binds the picture to its input, and nothing binds the input to what the buyer
|
||
asked for: the hop's receipt names its inputs by digest, which a holder of them checks.
|
||
- **Transmission, never delivery.** Under a tariff of version 7 a transmission line rests on the
|
||
publisher's own declaration and schedule (bearer-receipts §4, carousel §4): what it planned to
|
||
send and says it sent, which no receiver signs, as a declaration is a party's own word
|
||
(settlement §4.2). The pass rate that picks a price is a pure function of the signed schedule,
|
||
and its octets are recomputed from the schedule's parameters, so a seller cannot bill a faster
|
||
rate's octets at a slower tier's price. What the passes reached is a reconciliation's
|
||
(bearer-receipts §5), which no line reads. A node's line rests on its own claim, plan and
|
||
declaration in the same way, and an object it scheduled and does not say it sent bills nothing. Its
|
||
declaration is evidence that it stated the sending, and no line is held to its bytes (§4.10). An
|
||
invoice holds an instance to one party across its own sources, and what a verifier is not given it
|
||
does not read: a buyer holding the group's other claims runs cache-authority §7.2 over them.
|
||
- **An aggregated count is the collector's word.** Under a tariff of version 7 a line of
|
||
`aggregated_impressions` rests on the signature of a collector the buyer named, on a receipt the
|
||
buyer is given. The ledger holds its result to its count and bills it once; it does not run
|
||
impression-aggregates §8.1, which needs the receipt's catalogue, so a collector that signs a
|
||
receipt no aggregator stood behind is found by a holder running that text, not by this one. That
|
||
check is the buyer's to run, with the receipt the source gives it.
|
||
- **A consumption line is the agent's word.** It rests on a claim an agent the buyer named signed. The
|
||
ledger does not check the claim against the objects and their statements (ai-usage §6.3), so a
|
||
line bills a use whether the governing statements allowed it or not, and says nothing of that.
|
||
- **Storage is the holder's word, held to itself.** Under a tariff of version 8 a storage line rests
|
||
on a holder the buyer named, on snapshots it signed as a set's listing changed and on records it
|
||
signed over intervals. The verifier recomputes every record's byte-seconds from its snapshots, so
|
||
a holder cannot bill more time or more bytes than its own snapshots state, nor bill one set's time
|
||
twice in a chain. It does not see the objects: a holder can sign snapshots of bytes it did not
|
||
keep, or of a listing it did not have, as a seller can state a package kept that it deleted
|
||
(§4.7). A holder of the objects recomputes each snapshot's bytes and listing from them, and a
|
||
dispute is about a signed statement. A holder that signs no snapshot when its listing changes
|
||
bills the bytes of its last one until its next, more or less than it kept: the buyer that names
|
||
it accepts its cadence.
|
||
- **A following tariff.** Under a tariff of version 9, a scope or a price changes only by a tariff
|
||
both parties sign, and the chain crosses only into a tariff that names the one it follows. A seller
|
||
that begins a chain anew under a following tariff is refused (`chain_restarted`), so it cannot
|
||
leave a chain's billed records behind to bill them again. A seller that offers two tariffs
|
||
following one, or issues two invoices after one, forks the chain: a verifier given one invoice
|
||
and the one before it does not see it, and a buyer holding the chain sees two invoices naming one
|
||
`prev`, as within one tariff. A retired key bills nothing under the tariff that retires it, so a
|
||
buyer is not billed for a key it no longer names.
|
||
- **Every hop's energy.** Under a tariff of version 4 an invoice states the energy every hop of
|
||
its jobs spent, the hops the buyer was not billed for in a scope of their own, so a seller
|
||
whose router fails often shows it in the energy it states, and is not paid for it.
|
||
- **What the figures rest on.** An invoice is as true as its records: a delivery line rests on
|
||
acknowledgements, so a party and a downstream key that collude can bill bytes that never moved,
|
||
as settlement §13 says; a room line rests on per-hop records and the room's events; an ad line
|
||
under claims rests on players' session keys. The reports name the signatures each figure rests
|
||
on, so a dispute is about records, not about logs.
|
||
- **Energy.** A row states figures as their parties signed them, with their class: it is
|
||
attributable and its sum recomputable, not true (energy-measurement §5). `max_ppm` bounds the
|
||
declared part of a sum's uncertainty and says nothing of a class's undeclared systematic error.
|
||
- **What an invoice reveals.** Its records list names every record by identity, and its lines name
|
||
rooms, parties, packagers and deciders. A verification document holds the records themselves:
|
||
acknowledgements name downstream keys, and ad receipts name sessions. They travel between the
|
||
seller, the buyer and an auditor they choose; the service serves an invoice's document by its
|
||
digest and lists nothing.
|