WAI Extension: Exact Upscale
Mirrored from the canonical text at commit b1681667 ().
Status: Draft. Registers the record
wai.media.upscale: super-resolution as an exact derivation, and an account of which pixels a viewer saw were sent and which the sink made. A sink that receives a picture at a low resolution and presents it at a higher one runswai-upscale:sr2(orwai-upscale:sr4): the pinned upscale of integer-operators §5E E11 plus a detail an integer network computes from the picture, every operation one ofwai-ops/1, under a prior the sink holds by its SHA-256 (SPEC §3.1). Every sink computes the same bytes, so the high-resolution picture is a function of the transmitted bytes and the prior, and anyone holding both recomputes it. Since the sink’s upscale is known exactly, an origin can send a residual against it, aWIR1payload of staged-delivery Appendix A, and sign an upscale record stating the picture it aimed at and how far the sink’s output may lie from it: no sample at all, or a stated bound. A prior overfitted to one title, a per-title prior, is carried by its digest like any other. A sink’s presentation statement says, for a span of what it presented, which pictures were transmitted, which it derived exactly, which it edited by a step no one can recompute and which it generated, with the pixels and frames of each; each sink-made picture carries an origin claim of synthesis, and a generated picture names the model that made it. No new transport. The reference implementation is theint_srmodule ofwai-rs(featureneural_int), for the derivations, and itsexact_upscalemodule (featureexact_upscale), for the records; the corpus islive-conformance/upscale/, and its second implementation islive-conformance/upscale_verify.py. The tool that trains priors istools/wai_int_sr_train.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.Texts read for this revision: the WAI texts this one cites, and RFC 8032 and RFC 8785.
1. Scope
In scope: the prior and the two derivations, their arithmetic, colour, edges and limits, and their graph in the integer operator set (§3); the residual and the upscale record (§4); per-title priors (§5); the categories of presented pictures, their origin claims and the presentation statement (§6); verification (§7).
Out of scope: a transport; how a prior is trained, which is not part of the derivation (§5); how a sink schedules a derivation; generating a picture between two others, whose arithmetic is the generator’s and whose claim is synthesis’s (§6.1); and the presentation of anything that is not a picture.
Relationship to the core spec: wai.media.upscale is a record (SPEC §5): a
signed record a WAI tool emits and verifies. It names no payload format and is not dispatchable.
A prior is a parameter set of one file, pinned by SHA-256 as SPEC §3.1 pins any other (§3.5).
Relationship to synthesis: wai-upscale:sr2 and wai-upscale:sr4 are pinned
integer derivations of synthesis §4.3, and an assistive claim over one is proved by recomputation
from the input’s decoded samples and the prior (synthesis §4.4). A picture a sink presents and
does not publish is named in a claim by the digest of its samples (synthesis §3.1).
Relationship to determinism-tiers: the derivations are integer
throughout, so their output is a pure function of the input’s samples and the prior’s bytes, and
a sink that presents it holds the tier of the decode it ran on (determinism-tiers §2, What a
tier covers): decode-equivalence over an input at decode-equivalence.
2. Records
The records of this extension are JSON objects under the encodings of synthesis §2: byte strings
in lowercase hexadecimal, unsigned integers of at most 2^53 − 1 in plain decimal, no other number,
no boolean, terms and date-times as jwp-receipts §2.4.3 defines them, no member named twice, at
most 32 levels of nesting, exactly the members a section lists at every level, and a kind
naming the record; one that does not is record_malformed.
Every record carries signer_pubkey (32 bytes) and sig (64 bytes):
sig = Ed25519(signer_key, "wai:upscale\x01" || JCS(record without "sig"))
link_hash = BLAKE3("wai:upscale-link\x01" || JCS(record))
The signature is verified strictly (SPEC §7 Signatures): a key that fails step 1
or 2 is bad_key, and a signature that fails a later step bad_signature. A record is named by
its link hash. A picture’s samples are its RGB8 buffer (rows top to bottom, pixels left to
right, three bytes a pixel, no padding), and its digest is SHA-256 (FIPS 180-4) over them, as
synthesis §2 has it. A picture of w × h has w · h pixels.
3. The derivations
3.1 The prior: WSR1
A prior is one file. Every multi-byte field is little-endian.
| off | size | field | rule |
|---|---|---|---|
| 0 | 4 | magic WSR1 | |
| 4 | 1 | version | 1 |
| 5 | 1 | n_layers | 1 to 8 |
| 6 | 2 | act_hi | 1 to 32767: the ceiling of every hidden activation |
| 8 | … | the layers | n_layers layers, one after another; nothing follows the last |
A layer:
| size | field | rule |
|---|---|---|
| 1 | k | 1, 3 or 5: the kernel’s side |
| 1 | shift | 0 to 31 |
| 2 | cout | 1 to 64; the last layer’s is 12 |
cout · cin · k · k | weights | signed bytes, in the order [cout][cin][k][k] |
4 · cout | biases | signed 32-bit integers |
2 · cout | multipliers | unsigned 16-bit integers, each at least 1 |
cin is 3 for the first layer and the previous layer’s cout for every other.
A reader checks, in this order, and the first that fails names the refusal: the magic
(bad_magic); the version, present and 1 (version); n_layers and act_hi (field_range);
then each layer in turn: its four bytes present (truncated), its k, shift and cout
(field_range), its arrays present (truncated), each multiplier at least 1 (field_range);
then nothing after the last layer (trailing). A field missing from the 8-byte header is
truncated. A file that fails any of these is not a prior; a record that rests on it is refused
with the record’s own reason (§7.2).
3.2 wai-upscale:sr2
wai-upscale:sr2 under a prior P maps a w × h picture in to a 2w × 2h picture out.
All values are integers; no formula wraps or saturates unless it says so.
-
The base.
baseisup2_predict(integer-operators §5E E11) ofin, channel by channel, at 2h × 2w: the arithmetic ofwai-synthesis:upscale2(synthesis §4.1), the last row and column repeated. -
Centring. x₀[c][y][x] =
in(x, y)[c] − 128, for c the red, green and blue bytes in that order: a tensor of 3 channels, h rows and w columns. -
The layers. For each layer i of P, in order, with input xᵢ of
cinchannels:a[o][y][x] = Σ W[o][ci][ky][kx] · x̃ᵢ[ci][y + ky − ⌊k/2⌋][x + kx − ⌊k/2⌋],
the sum over ci <
cin, ky < k, kx < k, with x̃ᵢ equal to xᵢ inside the picture and 0 outside it; then v = R_half_up((a +bias[o]) ·mult[o],shift) (integer-operators §2). For every layer but the last, xᵢ₊₁ = clamp(v, 0,act_hi). The last layer’s v, of 12 channels, is the detail d. -
Sub-positions. detail[c][2y + i][2x + j] = d[4c + 2i + j][y][x], for i, j ∈ {0, 1}:
pixel_shufflewith factor 2 (integer-operators §5.10). -
The output.
out(x, y)[c] = clamp(base(x, y)[c] + detail[c][y][x], 0, 255).
A prior whose last layer’s weights and biases are all 0 gives out = base.
3.3 Colour, edges, scale and limits
- Colour. The derivation reads and writes
RGB8samples, the three channels together: each layer mixes all of its input’s channels. It states no colour space and converts none: its output is in its input’s. - Edges. The base repeats the last row and column (§3.2 step 1). The network reads zero outside the picture after centring (step 3), which is the sample value 128 before it.
- Scale.
wai-upscale:sr2doubles each side.wai-upscale:sr4under P iswai-upscale:sr2under P ofwai-upscale:sr2under P: a 4w × 4h output. No other factor is registered. - Limits. A derivation is defined for a picture of at least one pixel whose every tensor, in
either pass of
sr4, holds at most 2^26 elements (integer-operators §3): forsr2, w · h times the largestcoutof P, and 12 · w · h, are at most 2^26. A picture past that has no output under P.
3.4 Through the integer operator set
The derivation is one WHG1 graph (integer-operators §10) and one stage operator. The lowering
sr2/1 writes, for a prior P:
- two data inputs, sizes set per decode: tensor 0, the picture
[3, h, w], and tensor 1, its base[3, 2h, 2w], each with the policycheckover [0, 255]; - then the operators, each one’s output taking the next tensor index, every tensor
derivedwith no exponent:rescaleof tensor 0 with no multiplier, shift 0 and aprebias of −128 on each channel; for each layer,convwith itscout, kernelk×k, stride 1, zero padding ⌊k/2⌋ on each side, one group, its weights at one byte, and anrqwith one multiplier per channel at four bytes, its oneshift, aprebias per channel at four bytes and the roundinghalf_up; after each layer but the last,clamp(0, act_hi); thenpixel_shuffle(2);addof tensor 1 and the detail;clamp(0, 255), the graph’s one output.
The driver computes the base with up2_predict (§5E E11), supplies both inputs, and reads the
output back as RGB8. A sink loads the graph from its canonical bytes under acc64 with its
bounds certificate (integer-operators §8): a prior that reads (§3.1) always meets acc64, since
no value it forms passes 2^63. Where the certificate also meets acc32, a fabric of
wai-ops/1-i32 (integer-operators §9.1) runs it, and every operator of the graph is in that
subset. The outputs are the same integers on every fabric (integer-operators §4).
3.5 Pinning a prior
A prior is a parameter set of one file, sr.wsr, and SPEC §3.1 pins it: sha256 is the SHA-256
of the file’s bytes, with no form. Its determinism is int-sr2 and its tier, where stated,
decode-equivalence. Nothing but the digest names a prior: not an id, not a title, not a
network that compares equal after reading. A sink that runs a derivation under a prior it does
not hold by that digest has run another derivation.
4. The residual and the upscale record
4.1 The residual
A residual is a WIR1 payload (staged-delivery Appendix A) of the
RGB8 unit kind with predictor 0 (identity), n_units 1, d0 and d1 the output’s height
and width, and d2 3. Its decode is Appendix A.4’s, with the upscaled picture as the unit’s
current output: each sample becomes clamp(u + r · q, 0, 255), u the upscaled sample and
r the decoded residual. A residual whose every r is the target’s sample less u, divided by
q and rounded to the nearest integer, halves away from zero (staged-delivery A.4’s rdiv),
brings every sample within ⌊q/2⌋ of the target’s, and to it exactly when q is 1.
4.2 The upscale record
An upscale record, kind "wai-upscale", signed by the party that sends the picture (the
origin), says what a sink presents for one picture:
| member | type | meaning |
|---|---|---|
kind | string | "wai-upscale" |
object | 32 B hex | the content hash (jwp-receipts §2.1) of the object whose decode is the input picture |
input | object | {"width", "height", "samples"}: the input picture’s size, each at least 1, and digest |
derivation | string | wai-upscale:sr2 or wai-upscale:sr4 |
prior | 32 B hex | the SHA-256 of the prior (§3.5) |
upscaled | 32 B hex | the digest of the derivation’s output |
residual | object or null | {"sha256", "q"}: the SHA-256 of the residual’s bytes and its q, 1 to 65535; null for none |
output | 32 B hex | the digest of the picture a sink presents: upscaled with no residual; the residual’s decode over the upscaled picture otherwise |
target | object or null | with a residual, {"samples", "bound"}: the digest of the picture the origin aimed at, and the largest difference it states between any sample of the output and the target’s, 0 to 255; null exactly when residual is |
issued_at | date-time | when the signer signed it |
signer_pubkey, sig | §2 |
A record whose output would pass 2^26 bytes (4 · w · h · 3 for sr2, 16 · w · h · 3 for
sr4), whose residual and target are not both null or both objects, or with no residual
whose output is not its upscaled, is record_malformed.
A record with a bound of 0 says the sink presents the target, byte for byte. A record with a residual and a larger bound says the sink presents a picture no sample of which lies further than the bound from the target’s: the target is the origin’s, and what reaches the viewer is within the bound of it.
5. Per-title priors
A per-title prior is a prior an origin made for one title: a set of frames, a programme, a
game’s art. It is a WSR1 file like any other (§3.1), pinned by its digest (§3.5), carried to a
sink as any parameter set is (prior-carriage), and named by the records over
the title’s pictures. Nothing in a sink’s derivation depends on how the prior was made.
How a prior is trained is not part of this extension. A prior trained in floating point and
quantised to WSR1 is exact all the same: the derivation is the integer arithmetic of §3.2 over
the prior’s bytes. A tool that trains priors SHOULD record its seeds and inputs, and say
whether its training regenerates the same bytes; where it does not, the prior’s bytes, pinned by
their digest, are what is reproducible. The reference tool, tools/wai_int_sr_train.py, trains
in floating point from fixed seeds, and its training is not claimed to regenerate the same bytes
on another machine.
An origin SHOULD send a per-title prior only where the bytes it saves over the title, at the
quality the origin delivers (its residuals’ q and the bounds it states), exceed the prior’s own
bytes plus the bytes of the records that name it. A prior that saves less costs every sink that
fetches it more than it returns.
6. Accounting for sink-made pictures
6.1 Categories and their claims
Every picture a sink presents is in one category:
| category | what the picture is | its origin claim (synthesis §3) |
|---|---|---|
transmitted | the decode of an object the sink received, or that decode upscaled and refined by a residual to the target of an upscale record (§4.2) | the object’s own claim; for a refined picture, a convert claim whose subject is the picture’s samples and whose one input is the object the record names |
derived | wai-upscale:sr2 or wai-upscale:sr4 of a transmitted picture, with no residual | an assist claim whose subject is the picture’s samples, with replicate evidence naming the derivation and its prior |
asserted | an edit of a transmitted picture by a step no verifier recomputes: an upscale or an enhancement in floating point | an assist claim whose subject is the picture’s samples, with attest evidence |
synthesized | a picture a model made: a frame generated between two transmitted frames, a frame that replaces a lost one | a generate claim whose subject is the picture’s samples and whose models include the model that made it |
The sink signs the claim of each picture it made, as the party that performed the step (synthesis
§3.1); the origin signs the claim of a refined picture, whose samples its record fixes. A
derived picture is proved by recomputation from the input’s samples and the prior (synthesis
§4.4); an asserted one is the sink’s statement and nothing more; a synthesized one is never
labelled lower than synthesized (synthesis §3.2).
6.2 The presentation statement
A sink signs a presentation statement, kind "wai-presentation", for a span of a viewing
session, under a key of that session (no identity of the viewer or the device):
| member | type | meaning |
|---|---|---|
kind | string | "wai-presentation" |
session | 32 B hex | fresh random bytes of the session |
from, to | integer | the span, in microseconds of the session’s clock, from < to |
frames | array | 1 to 4096 entries, one for each picture presented in the span, in presentation order |
totals | object | {"frames", "pixels"}, each a count: {"transmitted", "derived", "asserted", "synthesized"} of integers |
issued_at | date-time | when it signed it |
signer_pubkey, sig | §2 |
An entry:
| member | type | meaning |
|---|---|---|
at | integer | when it was presented: from ≤ at < to, and greater than the entry before it’s |
made | string | its category (§6.1) |
width, height | integer | its size, each at least 1, their product at most 2^40 |
samples | 32 B hex | its digest |
object | 32 B hex or null | the content hash of the object it was decoded from or computed from; null exactly for synthesized |
claim | 32 B hex | the link hash of its origin claim (synthesis §2) |
upscale | 32 B hex or null | the link hash of the upscale record it follows, where it follows one; null for asserted and synthesized |
made_by | 32 B hex or null | for derived, the prior’s SHA-256; for asserted and synthesized, the digest of the model that made it, which for asserted may be null; null for transmitted. For synthesized, this is the slot made_by of the contribution record wai.media.contribution, which names the party, here the sink’s model, that made a part of the media. |
pixels | object | a count (above): how many of its pixels are in each category (§6.3) |
A statement that breaks a rule of this table is record_malformed.
6.3 Counting pixels and frames
An entry’s pixels are counted by its category, with W · H its own pixels and n the pixels of the picture it was computed from:
transmitted: all W · H aretransmitted;derived: n aretransmittedand W · H − nderived;asserted: min(n, W · H) aretransmittedand the restasserted;synthesized: all W · H aresynthesized.
n is the input size the claim’s evidence states. So a picture upscaled twice on each side counts a quarter of its pixels as transmitted, whatever it shows: the transmitted bytes carried that many. A refined picture counts all of its pixels as transmitted: the origin fixed every one of them, within its stated bound.
The statement’s totals.frames counts the entries of each category, and totals.pixels adds the
entries’ pixels. The fraction of the span’s pixels, or frames, in a category is its count over
the sum of the four. A statement whose totals are not these sums is fractions_mismatch.
7. Verification
7.1 Inputs
A verifier is given, each in a list: origin claims (synthesis §3.1); upscale records; presentation statements; the envelopes of the objects it holds, each named by its content hash; the decoded samples it holds, each with the content hash of the object decoded; the priors it holds, each named by its SHA-256; the residuals it holds, each named by its SHA-256; the targets it holds, each a picture named by its digest; and a policy of synthesis §11.1’s members and one more:
| member | values | default | meaning |
|---|---|---|---|
upscale | accept-unrecomputed, require-proof | accept-unrecomputed | require-proof: §7.2 step 4.6 applies (upscale_not_proved) |
7.2 Steps
The verifier runs these steps and stops at the first refusal, which it reports with the reason
and where: a record by its list and index (["upscale", i], ["presentation", i]), an entry of a
statement by both (["presentation", i, "frame", j]), or synthesis’s own place in the claims
(["synthesis", …]).
-
Reading. Each upscale record, then each presentation statement, reads (§2, §4.2, §6.2) and its signature verifies:
record_malformed,bad_key,bad_signature. -
Origin claims. Synthesis §11.2 steps 1 and 2 over the claims, with the objects, the decoded samples, the priors and the policy: a refusal there is this verification’s, at
["synthesis", ["claim", i]]. -
Priors. Nothing yet: a prior is read where a record names it (step 4).
-
Upscale records, in order, each by these checks in order:
- Its prior, where the verifier holds one by
prior: it reads (§3.1) (prior_invalid). - Its input, where the verifier holds the decoded samples of
object: they arewidth·height· 3 bytes and their digest isinput.samples(input_samples_mismatch). - With the prior and the input held: the derivation’s output (§3.2, §3.3) has the digest
upscaled(upscale_mismatch). An input past §3.3’s limits under the prior has no output, and is refused here too. - Its residual, where the verifier holds one by
residual.sha256: it reads as §4.1’s payload for the output’s size with the record’sq, and decodes to its end (staged-delivery A.3, A.4 steps 2 and 3) (residual_invalid); with the upscaled picture recomputed, its decode over that picture has the digestoutput(output_mismatch). - Its target: with a bound of 0,
outputistarget.samples; with the output recomputed and the target held, no sample of the output lies further from the target’s than the bound (residual_short). - Under
upscalerequire-proof, a record whose output was not recomputed in steps 3 and 4 (with no residual, step 3; with one, steps 3 and 4):upscale_not_proved.
A record whose output was recomputed is proved; otherwise it is not recomputed.
- Its prior, where the verifier holds one by
-
Presentation statements, in order, each entry in order, by these checks in order:
- Its claim is a claim the verifier holds (
claim_unknown), and, where it names one, its upscale record is one it holds (upscale_unknown). - The claim is about the entry’s picture: an object claim of the entry’s
object, for atransmittedentry with no upscale record; a claim whose subject is the entry’ssamples, for every other (frame_subject_mismatch). - The claim’s class is not below the category’s (§6.1):
assistiveforderivedandasserted,synthesizedforsynthesized(made_understated). A sink’s upscaled picture claimedcapturedorreconstructed, and a generated picture claimedassistive, are refused here. - The claim is the category’s (§6.1) (
made_mismatch):transmittedwith an upscale record: the record has a residual, itsobjectis the entry’s, itsoutputis the entry’ssamples, and the claim is aconvertwhose one input is that object;derived: the claim is anassistwhose evidence isreplicateand nameswai-upscale:sr2orwai-upscale:sr4, whose one input is the entry’sobject, and whose output, the evidence’s size scaled by the derivation’s factor, is the entry’s size; where the entry names an upscale record, the record’sobjectandderivationare the evidence’s and itsupscaledis the entry’ssamples;asserted: the claim is anassistwhose evidence isattest, whose one input is the entry’sobject;synthesized: the claim is agenerate.
- For
derived,made_byis the evidence’s prior, and the upscale record’s prior where the entry names one (prior_mismatch). Forassertedandsynthesized, amade_bythat is notnullis one of the claim’s models, and forsynthesizedit is notnull(made_by_mismatch). - Where the verifier holds the decoded samples of a
transmittedentry’s object and the entry names no upscale record: their digest is the entry’ssamples(presented_samples_mismatch). - Its
pixelsare §6.3’s (pixels_mismatch).
Then the statement’s totals (§6.3,
fractions_mismatch). - Its claim is a claim the verifier holds (
7.3 What an accepted case states
- the synthesis statements of the claims: for each, in order, its link hash, class and, for an
assist claim, whether it is
proved,not-recomputedorasserted(synthesis §11.3); - for each upscale record, in order: its link hash,
provedornot-recomputed, and, where the output was recomputed and the target held, the largest difference of any sample of the output from the target’s, ornull; - for each presentation statement, in order: its link hash and its totals.
8. Reasons
The codes this extension adds, each with where it is raised:
| reason | raised at |
|---|---|
record_malformed | §2, §4.2, §6.2, §7.2 step 1 |
bad_key | §2 |
bad_signature | §2 |
prior_invalid | §3.1, §7.2 step 4.1 |
input_samples_mismatch | §7.2 step 4.2 |
upscale_mismatch | §7.2 step 4.3 |
residual_invalid | §4.1, §7.2 step 4.4 |
output_mismatch | §7.2 step 4.4 |
residual_short | §4.2, §7.2 step 4.5 |
upscale_not_proved | §7.2 step 4.6 |
claim_unknown | §7.2 step 5.1 |
upscale_unknown | §7.2 step 5.1 |
frame_subject_mismatch | §7.2 step 5.2 |
made_understated | §6.1, §7.2 step 5.3 |
made_mismatch | §6.1, §7.2 step 5.4 |
prior_mismatch | §3.5, §7.2 step 5.5 |
made_by_mismatch | §6.2, §7.2 step 5.5 |
presented_samples_mismatch | §7.2 step 5.6 |
pixels_mismatch | §6.3, §7.2 step 5.7 |
fractions_mismatch | §6.3 |
A verifier also raises every code synthesis raises over the claims (synthesis §12), at
["synthesis", …]: assistive_recompute_mismatch among them, for a sink’s upscale whose claim
states an output its derivation does not give.
9. Conformance
live-conformance/upscale/ holds the corpus: vectors.json,
written from fixed seeds by wai_upscale_vectors gen, the priors it reads in priors/, each
pinned by its SHA-256 in the generator, and sha256.json, the digest of every derivation’s
output in the corpus. It has:
- Accepted:
sr2of a picture under a prior trained on generated pictures, proved by recomputation in its upscale record and in the sink’s assist claim;sr4under a seeded prior; a residual that brings the output to its target exactly, and one to a bound of 2;sr2under a per-title prior; and a presentation statement over a span that holds a transmitted picture, a derived one, an asserted float upscale and a frame generated between two others, with its totals. - Refused: each reason of §8 at least once, each a control of one defect: among them an
output that does not recompute (
upscale_mismatch, and synthesis’sassistive_recompute_mismatch), a prior other than the one the claim names (prior_mismatch), a residual that does not reach its target (residual_short), an upscaled picture claimed captured and a generated picture claimed assistive (made_understated), and a statement whose totals do not add up (fractions_mismatch).
A conforming verifier gives every vector the outcome, the reason, the place and the statements the
corpus states. wai_upscale_vectors verify and the test tests/exact_upscale.rs check that the
corpus regenerates byte for byte, that wai-rs gives every vector its outcome, and that §8 lists
exactly the reference’s codes. live-conformance/upscale_verify.py is the second
implementation, written from this text: it shares no code with wai-rs; it runs the derivations
from §3.2 in integer arithmetic of its own, verifies the claims with the synthesis corpus’s second
implementation (synthesis_verify.py), decodes residuals with the staged-delivery corpus’s
(staged_verify.py), reads §8’s codes from this text, and mutates copies of the corpus and
requires every copy to be refused.
10. Security and privacy considerations
- A derived picture is a function of the transmitted bytes and the prior, and nothing else: it can be checked, and it can be no more faithful than they are. What the prior adds is what it learned from the pictures it was trained on; a proved claim says the sink ran the derivation, not that the detail it added was in the scene.
- A prior’s bytes are fetched by digest from whoever serves them. A sink that holds a prior under
a digest has the bytes the origin pinned; it trusts no name, title or
id. - A residual’s target is the origin’s statement. A verifier that does not hold the target checks only a bound of 0, against the target’s digest; the bound of a larger one rests on the origin’s signature until a verifier holds the target.
- A presentation statement shows what the session’s key reports. It is not evidence that a person watched, and it names no viewer, no device and no account. Its digests name pictures, which a party that holds the pictures can recognise.
- A sink can leave pictures out of its statement. A statement covers the entries it lists; a gap
in
ator a span with fewer frames than the content’s rate is visible to a verifier that knows the rate.