open-standards/wai/extensions/energy-binding.md
Transaction Science d009db9087
Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m48s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m16s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m7s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m29s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 22s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 2m7s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 22s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 42s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 39s
wai formal verification (integer core) / kani (pull_request) Successful in 4m59s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 52s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Failing after 1m7s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 6m49s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 24s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 2m28s
standards workspaces build + test / aac-rs (pull_request) Successful in 3m25s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 3m46s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 1m22s
standards workspaces build + test / map-rs (pull_request) Successful in 2m16s
standards workspaces build + test / mesh-rs (pull_request) Successful in 2m3s
standards workspaces build + test / openpay (pull_request) Successful in 18m29s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 1m58s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Failing after 7s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Failing after 7s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Failing after 8s
standards workspaces build + test / arl-rs (pull_request) Successful in 3m49s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 3m19s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 3m45s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 3m17s
standards workspaces build + test / sense-rs (pull_request) Successful in 4m0s
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Successful in 3m42s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 27s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 2m43s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 28s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 1m14s
wai cross-architecture byte-equality / windows-x86_64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · windows (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (pull_request) Has been cancelled
wai: on-chip counters and calibrated instruments are separate energy classes, and every joule-carrying receipt can say which
The single `HwShunt` acquisition class covered both an on-chip vendor
counter (RAPL, NVML, SMC, IOReport) and an external calibrated shunt. They
are different evidence: a calibrated instrument's uncertainty is traceable to
a calibration, while a counter is a vendor's reading whose error the vendor
states (RAPL readings are deliberately noised when SGX or TDX is enabled,
per security advisory INTEL-SA-00389).

- extensions/energy-measurement.md §2 splits hardware evidence into
  `OnChipCounter` and `CalibratedInstrument`, each with a required declared
  uncertainty (relative error and integration window). IOReport is an
  on-chip counter, like RAPL and NVML. `HwShunt` stays readable as the legacy
  class, ranked below both, and is not sealed into a new WAI receipt.
- Every receipt family that carries joules — video, world, film, reel,
  haptic, score, splat4d, audio scene, ternary, provenance and the wai-quantum
  receipts — can carry its class. The label is additive: every committed
  signed vector still verifies, and the signed bytes of unlabelled and
  legacy-labelled receipts are pinned by tests. A sealed figure declares its
  1 µJ resolution, and the floor is stated as the rule verified (0.5/√3 µJ).
- The acquisition rules are scoped to the receipt profiles WAI defines, and
  the text says what enforces each one.
- Meters open their window from rest, report an all-zero power reader as
  unusable rather than clean, and state the running-window count model as
  conservative.
- oer-receipts.md maps OER's evidential grade onto the refined classes. The
  rule that a producer must not grade `measured` a figure whose class is
  `Estimator` is kept as settled on main.
- wai-quantum verifies a receipt in either form on every in-tree verify
  path, including wai-quantum-serve's POST /verify.
- CI: wai-energy-receipts.yml runs the energy-class, label and legacy-pin
  tests for wai-rs, wai-quantum and wai-quantum-serve, which no workflow
  enabled before.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-29 01:27:37 -04:00

15 KiB
Raw Permalink Blame History

WAI Extension: Energy Binding

Status: Draft. Binds the energy a reconstruction cost to that reconstruction, as a companion to C2PA 2.4's c2pa.environmental-sustainability assertion — supplying the acquisition class, the coverage, and the outcome binding the standard assertion has no field for. Reference impl: the energy_binding module of wai-rs (feature provenance), emitted into a real signed manifest by c2pa_emit (feature c2pa_emit). Companion to Reproducible-Reconstruction Binding and the acquisition protocol in Energy Measurement. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

1. Why a companion assertion

C2PA 2.4 defines c2pa.environmental-sustainability, carrying energy_kwh (per ISO/IEC TR 20226:2025) alongside carbon and water figures. The dominant signed-provenance container in media now has a place to put joules.

Three properties it does not have, and this extension supplies:

  1. It is self-declared. measurementMethod is optional, and an unattributed number cannot be compared with any other number. In practice the optional field is the one that stays empty.
  2. It carries no acquisition class. A hardware counter reading and a modelled constant occupy the same field and are indistinguishable to a reader, though they are different claims about the world.
  3. It is not bound to any reproducible output. The assertion is about an asset; a validator can check every signature in a manifest and still not know what the figure was measured over.

The third is the load-bearing one. A signature proves who said a number, never that the number is about anything checkable.

2. What the binding is

An energy binding is the tuple

{ reconstructionHash, alg, microjoules, acquisition, [evidence], coverage, workUnits, method }

where [evidence] is present exactly when acquisition is a refined hardware class, OnChipCounter or CalibratedInstrument (energy-measurement §2.3–§2.5); legacy HwShunt carries none:

field present for meaning
uncertainty OnChipCounter, CalibratedInstrument { relativePpm, windowUs } — the declared standard (k = 1) relative uncertainty in ppm and the integration window in µs
counterFiltering OnChipCounter On / Off / Unknown
calibrationRef CalibratedInstrument identifier of the calibration certificate

carried as a third-party C2PA assertion under the reverse-domain label science.transaction.wai.energy.reconstruction, alongside — never instead of — the standard c2pa.environmental-sustainability assertion.

reconstructionHash is the SHA-256 of the canonical decoded pixels, the same digest reconstruction-binding commits to. Both assertions in one manifest therefore name the same decode by construction, and a manifest whose two digests disagree is self-refuting.

3. What this makes checkable, and what it does not

Where the reconstruction is at decode-equivalence — reproducible byte for byte on every conforming sink (determinism-tiers §2) — a verifier holding the codestream can do the following with any conforming decoder, and over wai.image.jpegai's exact-decoder reconstruction only with that decoder under the conditions in determinism-tiers §5 (reconstruction-binding §2):

  • re-decode under the pinned descriptor,
  • hash the pixels and confirm the energy figure is about those bytes,
  • recompute workUnits from the descriptor rather than trusting it,
  • and re-derive the rate.

What remains is exactly one unverifiable term: the joules. That is the point of the construction, and the honest limit of it. An energy claim about an output nobody can reproduce is not checkable at all. An energy claim about an output anyone can reproduce is checkable except for one number — and knowing precisely which number is the difference between a measurement and an assertion.

An implementation MUST NOT describe an energy binding as proving the energy figure. It binds the figure to a reproducible outcome; it does not attest the measurement.

4. Normative rules

  • The binding MUST carry an acquisition class (CalibratedInstrument / OnChipCounter / ModelBased / Estimator, per energy-measurement §2) and a coverage statement (Whole / Partial, §5 there). A refined hardware class MUST carry its evidence as above, and a new binding MUST NOT use the legacy HwShunt label.
  • A refined hardware class's declared uncertainty MUST cover the figure's own rounding (energy-measurement §2.3): microjoules is a whole number of microjoules, so it is uncertain by at least 0.5/√3 µJ (≈ 0.289 µJ), and microjoules × uncertainty.relativePpm MUST be at least 288 676.
  • A verifier reading a binding MUST accept HwShunt — it is what bindings signed before the hardware class was refined say, and it carries no evidence fields — and MUST reject a refined hardware class without its uncertainty, a refined hardware class whose microjoules × relativePpm is below 288 676, a CalibratedInstrument without its calibrationRef, and evidence fields beside a class that carries none. The floor needs nothing but the body and is computed in integers, so every verifier reaches the same verdict. A C2PA validator checks the signature over the body; these rules are about what the body says, and no validator applies them on the implementation's behalf.
  • method MUST be present and name the published protocol the figure was obtained under. This is deliberately stricter than the standard assertion's optional measurementMethod.
  • A figure of zero MUST NOT be recorded. A reconstruction that measured 0 µJ did not consume nothing; it failed to measure, and the honest artifact is the absence of an energy assertion rather than a zero in one.
  • microjoules is an integer and is authoritative. energy_kwh in the standard assertion MUST be treated as a derived interop value: one microjoule is 2.8 × 10⁻¹³ kWh, so a whole image decode lands near 10⁻⁹ kWh, where the trailing digits of the float are artifacts of the conversion rather than of the measurement.
  • An implementation MUST NOT populate carbon_kgco2e or water_litres from an energy figure and a grid-average factor while presenting the result as measured. Those are modelled quantities; emitting them beside a measured joule figure, in the same assertion, with no per-field provenance, is how a model comes to be read as a measurement.
  • A Partial figure MUST NOT be presented as the reconstruction's total.

5. Relationship to the standard assertion

Interoperability is the reason both are emitted. A validator that understands only C2PA 2.4 reads energy_kwh and a populated measurementMethod, which is already better than the common case. A validator that understands this extension additionally learns how the figure was acquired, how much of the work it covers, and which reconstruction it describes — and can check the last of those itself.

6. Emitting a manifest

The assertion shapes above are emitted into an actual signed C2PA manifest by the c2pa_emit module of wai-rs. Four decisions in that emitter are normative for anyone writing their own, because each is a place where the obvious implementation produces a manifest that validators reject, or that overstates what a decoder knows.

6.1 The inception action is c2pa.opened, not c2pa.created

A manifest MUST NOT describe a reconstruction with c2pa.created.

C2PA 2.x requires every c2pa.created action to carry a digitalSourceType, and that vocabulary describes how the content came to exist — captured, drawn by a human, generated by a model. A decoder does not know that. It reconstructed pixels from a codestream, and whatever was encoded could have been any of them. Selecting trainedAlgorithmicMedia because a codec has a neural stage would assert that a compressed photograph is AI-generated content, which is false, and the vocabulary has no member meaning "decoded; origin not visible from here".

A decode is in any case not a creation. It is a conversion of an existing asset into another representation, which C2PA already models: the codestream is a parentOf ingredient, the manifest opens it, and c2pa.converted records what was done. No action asserts a digitalSourceType, so no claim about the original's origin is made anywhere — which is precisely the position a decoder is in.

6.2 The codestream is carried as the parent ingredient

An emitted manifest MUST carry the codestream as a parentOf ingredient.

§3 turns on a verifier being able to re-decode. A manifest that carries the reconstruction digest but does not name what produces it hands the verifier a digest and no way to reach it. The digest says which decode the joules were measured over; the parent ingredient says what to decode to get there. Both halves, or the check §3 describes is not actually available.

6.3 The bindings are created assertions, not gathered

The bindings MUST be marked as attributed to the signer.

C2PA distinguishes assertions the signer stands behind from material gathered elsewhere and carried along — the same distinction between a claim and hearsay that the acquisition ladder draws inside the figure itself. These are first-party statements: the signer measured the joules and hashed the pixels.

This is load-bearing rather than editorial. A validator looks for the inception action among the created assertions, so an actions assertion left gathered yields a manifest that signs without complaint and every validator then rejects as assertion.action.malformed — a failure that surfaces only on the far side of a signature.

6.4 What a signature does not settle

An emitted manifest signed by an untrusted certificate reaches ValidationState::Valid — well-formed, signature intact, asset unmodified — and not ValidationState::Trusted, which additionally requires a certificate chaining to a known authority. An implementation MUST NOT present the first as though it were the second.

The gap between them is the whole of who says so, and it is orthogonal to everything §3 makes checkable: a perfectly reproducible reconstruction signed by nobody in particular is still a claim from nobody in particular.

7. The operating point, and why a joule figure alone is not enough

7.1 Degradation-blindness

A receipt that records the joules a decode spent, and nothing about how much work it was asked to do, is degradation-blind. A sink can always spend fewer joules by decoding worse, and a figure that cannot distinguish efficient from degraded rewards the wrong behaviour precisely where the number is meant to carry weight.

This is not hypothetical. ISO/IEC 23001-11 defines a decoding operation reduction request (DOR-Req) with which a receiving device asks the remote encoder for a less complex bitstream, so that its own decoder does less, and notes that its metadata can save more energy "at the expense of some QoE degradation". Its energy quantities are expected or potential savings stated in advance, not energy that was spent (determinism-tiers §2), and a WAI receipt without §7.2's fields records only what was spent, with nothing about the operating point it was spent at. energy-measurement.md §5's recomputable-work-unit rule blocks the substitution at the byte-exact tier, but not at entropy-consistency, and not for the conventional codecs WAI already carries.

The rules below make the operating point part of the claim, so the joule figure is scored against something rather than merely reported.

7.2 Request, commitment, delivery

Where one party requests an operating point and another acts on it, the receipt MUST seal all three of:

field meaning
op_requested the operating point the requesting party asked for
op_committed the operating point the acting party said it would use
op_delivered the operating point actually used

In the 23001-11 case in §7.1 the receiver requests and the sender acts: a receiving device sends a DOR-Req, and the remote encoder answers with a DOR-Resp saying how it decided to answer.

An operating point is a class-scoped descriptor — frame rate, spatial resolution, a complexity target — and this extension does not define its vocabulary. What it fixes is that the three are distinct fields, because the interesting cases are exactly the ones where they differ.

  • A receipt MUST NOT carry op_delivered alone. A delivered figure with nothing to score it against is the degradation-blind case §7.1 describes.
  • op_committed MUST be recorded as what the acting party stated, even where it differs from the request. A commitment that silently becomes the request is not a commitment.
  • Where op_delivered differs from op_committed, the receipt MUST record both and MUST NOT claim the commitment was met.
  • A receipt over a payload that an encoder altered to save energy, whether at a receiver's request (such as a decoding-operation-reduction or attenuated-video request) or on its own account, covers that payload, and MUST NOT be presented as covering the payload it stands in for — see determinism-tiers §2, What a tier covers.

This converts a recorded number into a number measured against a promise. Neither the prescriptive standards nor the measurement standards provide that pair: one says what should be spent, the other what was, and nobody scores the second against the first.

7.3 The residual

When a declared complexity or operating-point descriptor and a measured energy binding both cover the same reconstruction, the receipt MUST carry the residual — the signed difference between the energy the descriptor implies and the energy measured.

  • The residual MUST be computed over the same work unit as the measurement (energy-measurement.md §5), or it compares two different things and means nothing.
  • A residual MUST NOT be reported without the acquisition class of the measured term. A residual against an Estimator figure is a difference between two predictions.
  • An implementation MUST NOT suppress a residual because it is large. The large ones are the informative ones; suppression converts a falsifiable claim into an unfalsifiable one.

The residual is what makes the predictive half checkable. A complexity descriptor is a prediction about energy, and until something records what actually happened against it, the prediction is never wrong. This closes that loop in the artifact rather than in a report.

7.4 Companion capability

Green-metadata semantics are registered the way wai.meta.hdr10plus and wai.meta.dovi are: the capability names the descriptor class — complexity metrics, quality recovery, display adaptation — and the sink supplies the decoder. No carriage is adopted: ISOBMFF and DASH carriage of green metadata is somebody else's layer, and WAI naming a descriptor does not make WAI responsible for moving it.