no fabricated readings: every figure sealed as a reading was read #212

Merged
dcharlot merged 21 commits from fix/no-fabricated-readings into main 2026-10-10 22:24:51 -04:00
48 changed files with 1703 additions and 298 deletions

View file

@ -99,7 +99,12 @@ jobs:
- { name: proof-rs, dir: proof/proof-rs, runner: linux, z3: true, conformance: proof-conformance }
- { name: joulehook-rs, dir: joulehook/joulehook-rs, runner: linux }
- { name: eoc-rs, dir: eoc/eoc-rs, runner: linux, feature_tests: "-p eoc-meter --features cuda" }
- { name: mesh-rs, dir: mesh/mesh-rs, runner: linux-arm64, feature_tests: "-p mesh-engine-gguf --features gguf" }
# mesh-openai's `serve_example` test (the reference server seals what
# its meter read, never a fixture's figure) has required-features
# `server`, so `cargo test --workspace` builds none of it; naming the
# package here is what runs it. Selecting mesh-engine-gguf alone
# compiles mesh-openai with `server` but runs none of its tests.
- { name: mesh-rs, dir: mesh/mesh-rs, runner: linux-arm64, feature_tests: "-p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server" }
- { name: joule-ui-rs, dir: joule-ui/joule-ui-rs, runner: linux }
# jouleclaw-rs is the one entry whose runner IS a correctness choice.
# It reaches candle → ug → gemm, which uses inline aarch64 assembly
@ -234,7 +239,8 @@ jobs:
# The NVML backends sit behind features no workspace member enables
# (jcp-energy `nvml`, eoc-meter `cuda`, jouleclaw-energy `nvml`), so the
# step above never compiles them, let alone runs their tests. Here they
# build and their tests run. The container has no GPU and Docker masks
# build and their tests run, as do mesh-rs's feature-gated tests (the
# gguf engines; mesh-openai's `server` and its serve_example test). The container has no GPU and Docker masks
# powercap, so the hardware tests take their "unavailable, and the
# oracle agrees" branch; the rule's unit tests run in full.
- name: Feature-gated energy tests

View file

@ -51,7 +51,7 @@ jcp/
- **`jcp-threshold`** — threshold actors (SPEC §2.2): a `did:key` whose private key is split k-of-n with FROST (RFC 9591); the group key is an ordinary Ed25519 key, so a 2-of-3 team issues, holds, and signs wire requests with nothing else in JCP changing. Shares come from a trusted dealer or **distributed key generation** — with DKG the group's private key never exists anywhere, not even momentarily. The two-agent rule for irreversible actions, refused by arithmetic rather than policy.
- **`jcp-channel`** — receipt-settled budget channels (SPEC §4.5, the OPTIONAL profile): N enforcement points spend optimistically against one grant and settle by exchanging signed statements of cumulative spend — forged, stale, and regressing statements refused; between settlements the exposure is bounded by the window, and after settlement any overdraft is provable from the signed statements. Where bounded overdraft is unacceptable, `shard()` remains the baseline.
- **`jcp-conformance`** — C1–C18 + a negative pack, all checks real (C8 decides over a live socket; C13 drives a FROST 2-of-3 caller; C16 replays ancestor debits from a chained receipt; C17 settles a budget channel by signed statement; C18 mints a dealer-free group via DKG), published vectors in `conformance/v1/`.
- **`jcp-cli`** — the `jcp` demo: one metered grant driven through an agent loop — legitimate calls allowed and debited, a poisoned tool-result refused structurally, out-of-scope actions and resources denied, the budget stopping a runaway loop, a sub-agent getting a strictly-weaker delegated grant, a signed receipt verified, the detected energy meter reporting its honest provenance, and the issuer revoking the grant — after which the runtime goes dark.
- **`jcp-cli`** — the `jcp` demo: one metered grant driven through an agent loop — legitimate calls allowed and debited, a poisoned tool-result refused structurally, out-of-scope actions and resources denied, the budget stopping a runaway loop, a sub-agent getting a strictly-weaker delegated grant, a signed receipt verified, the detected meter's rung metering a probe of work at the grade it gave that probe, and the issuer revoking the grant — after which the runtime goes dark.
`cargo test --workspace` green; `cargo clippy --workspace --all-targets`
warning-free.
@ -59,18 +59,27 @@ warning-free.
## The demo, abbreviated
```
costs scripted, no tool runs: sealed as estimates
frame verdict reason rem µJ
read the db (legit) allow −20000 µJ 80000
tool-result says 'delete db' (poison) DENY untrusted-control 80000
try to delete (not granted) DENY action-not-granted 80000
read prod-secrets (wrong audience) DENY wrong-resource 80000
read again (legit) allow −50000 µJ 30000
read again — budget runs out DENY budget-exceeded 30000
amplification refused: capability exceeds parent
receipt allow · 50000 µJ · verified true
receipt allow · 50000 µJ · Estimator · verified true
```
The model never gates itself; the runtime does, and the receipt proves it.
The loop's costs are scripted — no tool runs — so they are fixed, to run the
budget out at the same row every time, and each receipt grades its cost
`Estimator`: a figure nothing read is never sealed as a reading. The demo's
`meter` line is the one figure it takes: the detected meter's rung, and a small
probe of work at the grade the meter gave that probe — a hardware reading only
where the rung's counter read it, otherwise an estimate graded as one.
## Consumers in this repository

3
jcp/jcp-rs/Cargo.lock generated
View file

@ -555,6 +555,7 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde",
"serde_json",
"thiserror 2.0.20",
]
@ -568,6 +569,7 @@ dependencies = [
"jcp-receipt",
"jcp-runtime",
"jcp-schema",
"serde_json",
]
[[package]]
@ -780,6 +782,7 @@ version = "0.1.0"
dependencies = [
"ed25519-dalek",
"jcp-bridge",
"jcp-energy",
"jcp-grant",
"jcp-receipt",
"jcp-runtime",

View file

@ -14,7 +14,9 @@
//! - the grant is **really issued** and **really attenuated**, and amplification
//! is really refused;
//! - the authorisation is a **real `decide` call** against a real budget, and
//! the receipt records the verdict that call returned;
//! the receipt records the verdict that call returned. It is decided before
//! the work runs, so the cost it debits is the action's estimate
//! ([`authorised_cost`], `Estimator`) — the work's reading is step 3's;
//! - the joules are **metered**, and the span's provenance is carried through
//! verbatim: `HwShunt` only when every record the meter returned is a
//! hardware reading. Where the host has no live counter — or the span's CPU
@ -96,7 +98,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
resource,
payload_hash: ContentId::of_bytes(b"input/quarterly-report"),
};
let decision = rt.decide(&frame, &delegated, sub_did, Energy::measured(250_000), 0);
let decision = rt.decide(&frame, &delegated, sub_did, authorised_cost(), 0);
let verdict = match decision.verdict {
Verdict::Allow => "allow",
Verdict::Deny(_) => "deny",
@ -250,3 +252,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
Ok(())
}
/// The cost the authorisation debits: decided before the work runs, it is
/// the action's estimate, 0.25 J, graded `Estimator` with no measured figure.
/// Sealed as a reading, the authority receipt would claim a meter read work
/// that had not yet happened; the joules a meter did read are the work
/// receipt's, and the action receipt's.
pub fn authorised_cost() -> Energy {
Energy::estimator(250_000)
}

View file

@ -0,0 +1,21 @@
//! The `end_to_end` example authorises its action before the work runs, so
//! the cost that decision debits and the authority receipt seals is an
//! estimate — never a hardware reading of work that had not happened. (The
//! work's own energy is metered, at the meter's grade, in step 3.) Checked on
//! the cost the example uses (the example file is compiled in here as a
//! module).
#[allow(dead_code)]
#[path = "../examples/end_to_end.rs"]
mod end_to_end;
use jcp_schema::Provenance;
#[test]
fn the_authorisation_is_debited_an_estimate() {
let cost = end_to_end::authorised_cost();
eprintln!("authorised cost: {} µJ [{}] measured {:?}", cost.uj(), cost.provenance.jcr1_label(), cost.measured_uj);
assert_eq!(cost.provenance, Provenance::Estimator, "a pre-run cost graded {:?}", cost.provenance);
assert_eq!(cost.measured_uj, None, "a measured figure for work that had not run");
assert!(cost.check_provenance().is_ok(), "{cost:?}");
}

View file

@ -16,5 +16,8 @@ ed25519-dalek = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
[dev-dependencies]
serde_json = { workspace = true }
[lints]
workspace = true

View file

@ -6,6 +6,11 @@
//! ```text
//! cargo run -p jcp-cite --example cite
//! ```
//!
//! The retrieval is illustrative: no document is fetched, so the energy the
//! citation records is a chosen figure, and the decision it is debited under
//! seals it as an estimate ([`retrieval_cost`]) — never as a hardware reading
//! of work no meter saw.
use ed25519_dalek::SigningKey;
use jcp_cite::{verify, Citation, Source};
@ -37,10 +42,14 @@ fn main() {
Source::new(ContentId::of_bytes(doc_a), g_finance).at("/finance/q3-report"),
Source::new(ContentId::of_bytes(doc_b), g_people).at("/people/q4-plan"),
],
4_200, // µJ the retrieval consumed
4_200, // µJ the retrieval is put at: illustrative, nothing read it
[7; 16],
);
println!("agent read {} sources → answer, {} µJ", citation.sources.len(), citation.energy_uj);
println!(
"agent read {} sources → answer, {} µJ (illustrative: sealed as an estimate)",
citation.sources.len(),
citation.energy_uj
);
// The retrieval is decided and metered under a real grant, and the receipt
// commits the citation by content id.
@ -58,7 +67,7 @@ fn main() {
};
let sg = issue(&issuer, grant.clone()).unwrap();
let frame = citation.frame(grant.id(), corpus).unwrap();
let decision = Runtime::new().decide(&frame, &sg, agent_did, Energy::measured(citation.energy_uj), 1);
let decision = Runtime::new().decide(&frame, &sg, agent_did, retrieval_cost(&citation), 1);
let steward = SigningKey::from_bytes(&[9u8; 32]);
let receipt = seal(&frame, &grant, &decision, &steward, "did:example:steward").unwrap();
let core = extract(&receipt, "did:example:steward", &steward.verifying_key().to_bytes()).unwrap();
@ -93,3 +102,10 @@ fn main() {
}
}
}
/// The cost the retrieval is debited and sealed at: the citation's recorded
/// figure, graded `Estimator` with no measured figure, because nothing in
/// this example read it.
pub fn retrieval_cost(citation: &Citation) -> Energy {
Energy::estimator(citation.energy_uj)
}

View file

@ -0,0 +1,57 @@
//! The `cite` example's retrieval is illustrative — no document is fetched —
//! so the cost it is decided and sealed at must be an estimate, never a
//! hardware reading. Checked on the cost the example builds (the example
//! file is compiled in here as a module) and on the `jcp` receipt sealed
//! over it, decoded from the signed core.
#[allow(dead_code)]
#[path = "../examples/cite.rs"]
mod cite;
use ed25519_dalek::SigningKey;
use jcp_cite::{Citation, Source};
use jcp_grant::issue;
use jcp_runtime::Runtime;
use jcp_schema::{Capability, ContentId, Did, Grant, Provenance};
#[test]
fn the_cite_examples_retrieval_is_sealed_as_an_estimate() {
let issuer = SigningKey::from_bytes(&[1u8; 32]);
let agent = Did::from_verifying_key(&SigningKey::from_bytes(&[2u8; 32]).verifying_key());
let corpus = ContentId::of_bytes(b"acme-workspace");
let citation = Citation::new(
agent,
ContentId::of_bytes(b"answer"),
vec![Source::new(ContentId::of_bytes(b"doc"), ContentId::of_bytes(b"grant:finance"))],
4_200,
[7; 16],
);
let cost = cite::retrieval_cost(&citation);
eprintln!("retrieval cost: {} µJ [{}] measured {:?}", cost.uj(), cost.provenance.jcr1_label(), cost.measured_uj);
assert_eq!(cost.provenance, Provenance::Estimator, "an illustrative retrieval graded {:?}", cost.provenance);
assert_eq!(cost.measured_uj, None, "a measured figure nothing read");
assert_eq!(cost.uj(), citation.energy_uj, "the receipt's cost is the citation's figure");
let grant = Grant {
issuer: Did::from_verifying_key(&issuer.verifying_key()),
subject: agent,
capability: Capability::new(corpus, ["retrieve"]),
budget_uj: 1_000_000,
budget_funds: None,
caveats: Vec::new(),
expiry: 0,
parent: None,
delegate_depth: None,
nonce: [0; 16],
};
let sg = issue(&issuer, grant.clone()).expect("issue");
let frame = citation.frame(grant.id(), corpus).expect("frame");
let decision = Runtime::new().decide(&frame, &sg, agent, cost, 1);
assert!(decision.is_allow(), "{:?}", decision.verdict);
let steward = SigningKey::from_bytes(&[9u8; 32]);
let env = jcp_receipt::seal(&frame, &grant, &decision, &steward, "did:example:steward").expect("seal");
let core = jcp_receipt::jcr1::verify_cose_sign1(&env, "did:example:steward", &steward.verifying_key().to_bytes()).expect("verifies");
let sealed: serde_json::Value = jcp_schema::from_canonical_cbor(&core).expect("decodes");
eprintln!("sealed: cost_uj {} [{}]", sealed["cost_uj"], sealed["energy_provenance"]);
assert_eq!(sealed["energy_provenance"].as_str(), Some("Estimator"), "{sealed}");
}

View file

@ -18,5 +18,8 @@ jcp-receipt = { workspace = true }
jcp-energy = { workspace = true }
ed25519-dalek = { workspace = true }
[dev-dependencies]
serde_json = { workspace = true }
[lints]
workspace = true

View file

@ -5,9 +5,17 @@
//! calls are allowed and debited; a poisoned tool-result is refused structurally;
//! out-of-scope actions and resources are denied by capability and audience
//! binding; the budget stops a runaway loop; and a sub-agent gets a strictly
//! weaker delegated grant. The energy figure comes from the detected meter
//! ladder; the issuer then revokes the grant and the runtime goes dark. Every
//! decision seals as a signed JCR-1 receipt.
//! weaker delegated grant. The issuer then revokes the grant and the runtime
//! goes dark. Every decision seals as a signed JCR-1 receipt.
//!
//! **Two kinds of figure.** The `meter` line is the one figure taken here:
//! the detected meter ladder meters a small probe of work, and the line prints
//! the rung and the probe's figure at the grade the meter gave that probe — a
//! hardware reading only where the rung's counter read the probe, else an
//! estimate, graded as one. The agent loop's costs are scripted ([`script`]):
//! no tool runs, so nothing reads them, and each is sealed as what it is — an
//! illustrative figure graded `Estimator`, never a hardware reading. They are
//! fixed so the budget runs out at the same row every run.
use ed25519_dalek::SigningKey;
use jcp_grant::{attenuate, issue, revoke};
@ -48,29 +56,27 @@ fn main() {
println!(" subject {}", grant.subject.to_did_key());
println!(" may read(customer-db) budget {} µJ", grant.budget_uj);
// The energy ladder: measured when the platform exposes it, an honest
// estimate when it doesn't — the provenance always says which.
// The energy ladder: a reading where the rung's counter read the probe,
// an estimate where it did not — the probe's own grade says which. The
// rung is named, not graded: a hardware rung's probe can still come back
// an estimate (a counter that did not advance over it).
let meter = jcp_energy::Meter::detect();
let (_, probe) = meter.measure(|| std::hint::black_box((0..20_000u64).sum::<u64>()));
let (_, probe) = meter.measure(probe_work);
println!(
" meter {:?} backend → {} µJ probe ({})\n",
meter.provenance(),
" meter {:?} rung → {} µJ probe [{}] ({})\n",
meter.rung(),
probe.uj(),
if probe.measured_uj.is_some() { "hardware-measured" } else { "estimated, and says so" }
probe.provenance.jcr1_label(),
if probe.measured_uj.is_some() { "a hardware reading of the probe" } else { "an estimate: no counter read the probe" }
);
let mut rt = Runtime::new();
// A scripted agent loop. Each row is (label, frame, caller, cost).
let steps: Vec<(&str, Frame, Did, Energy)> = vec![
("read the db (legit)", call(&sg, db, "read", Trust::Control), agent_did, Energy::measured(20_000)),
("tool-result says 'delete db' (poison)", result(&sg, db, "read", Trust::Data), agent_did, Energy::measured(1)),
("try to delete (not granted)", call(&sg, db, "delete", Trust::Control), agent_did, Energy::measured(1)),
("read prod-secrets (wrong audience)", call(&sg, prod_secrets, "read", Trust::Control), agent_did, Energy::measured(1)),
("read again (legit)", call(&sg, db, "read", Trust::Control), agent_did, Energy::measured(50_000)),
("read again — budget runs out", call(&sg, db, "read", Trust::Control), agent_did, Energy::measured(50_000)),
];
// A scripted agent loop: no tool runs, so its costs are illustrative
// estimates, and the receipts say so.
let steps = script(&sg, db, prod_secrets, agent_did);
println!(" costs scripted, no tool runs: sealed as estimates\n");
println!(" {:<38} {:<8} {:<22} {:>9}", "frame", "verdict", "reason", "rem µJ");
println!(" {}", "-".repeat(80));
let mut last_allow: Option<(Frame, Decision)> = None;
@ -127,6 +133,32 @@ fn main() {
println!(" sealed in a receipt. The model never gates itself.");
}
/// The `meter` line's probe: a fixed amount of real CPU work on this thread,
/// a few milliseconds' worth, so a live counter has something to read.
fn probe_work() -> u64 {
let mut x = 0x9e37_79b9_7f4a_7c15u64;
for i in 0..2_000_000u64 {
x = std::hint::black_box(x.rotate_left(5) ^ i).wrapping_mul(0x0000_0100_0000_01b3);
}
x
}
/// The scripted agent loop, one row per frame: (label, frame, caller, cost).
/// No tool runs, so every cost is an illustrative figure graded `Estimator`
/// with no measured figure: sealed as a hardware reading, it would claim a
/// meter read work that never happened (SPEC §5). The figures are fixed so
/// the budget runs out at the last row.
fn script(sg: &SignedGrant, db: ContentId, prod_secrets: ContentId, agent: Did) -> Vec<(&'static str, Frame, Did, Energy)> {
vec![
("read the db (legit)", call(sg, db, "read", Trust::Control), agent, Energy::estimator(20_000)),
("tool-result says 'delete db' (poison)", result(sg, db, "read", Trust::Data), agent, Energy::estimator(1)),
("try to delete (not granted)", call(sg, db, "delete", Trust::Control), agent, Energy::estimator(1)),
("read prod-secrets (wrong audience)", call(sg, prod_secrets, "read", Trust::Control), agent, Energy::estimator(1)),
("read again (legit)", call(sg, db, "read", Trust::Control), agent, Energy::estimator(50_000)),
("read again — budget runs out", call(sg, db, "read", Trust::Control), agent, Energy::estimator(50_000)),
]
}
fn call(sg: &SignedGrant, resource: ContentId, action: &str, trust: Trust) -> Frame {
Frame { kind: FrameKind::ToolCall, trust, grant_id: sg.grant.id(), action: action.into(), resource, payload_hash: ContentId::of_bytes(b"q") }
}
@ -143,3 +175,53 @@ fn truncate(s: &str, n: usize) -> String {
t
}
}
#[cfg(test)]
mod tests {
use super::*;
use jcp_schema::Provenance;
use serde_json::Value;
/// Every scripted cost is an estimate, and so is what the receipt of the
/// last allowed row seals — decoded from the signed core itself.
#[test]
fn the_scripted_costs_are_sealed_as_estimates() {
let issuer = SigningKey::from_bytes(&[1u8; 32]);
let agent = Did::from_verifying_key(&SigningKey::from_bytes(&[2u8; 32]).verifying_key());
let db = ContentId::of_bytes(b"customer-db");
let grant = Grant {
issuer: Did::from_verifying_key(&issuer.verifying_key()),
subject: agent,
capability: Capability::new(db, ["read"]),
budget_uj: 100_000,
budget_funds: None,
caveats: Vec::new(),
expiry: 0,
parent: None,
delegate_depth: None,
nonce: [9; 16],
};
let sg = issue(&issuer, grant.clone()).expect("issue");
let steps = script(&sg, db, ContentId::of_bytes(b"prod-secrets"), agent);
let mut rt = Runtime::new();
let mut last_allow = None;
for (label, frame, caller, cost) in steps {
eprintln!("{label}: {} µJ [{}] measured {:?}", cost.uj(), cost.provenance.jcr1_label(), cost.measured_uj);
assert_eq!(cost.provenance, Provenance::Estimator, "{label}: a scripted cost graded {:?}", cost.provenance);
assert_eq!(cost.measured_uj, None, "{label}: a measured figure nothing read");
let d = rt.decide(&frame, &sg, caller, cost, 0);
if d.is_allow() {
last_allow = Some((frame, d));
}
}
let (frame, d) = last_allow.expect("the script allows a read");
let steward_sk = SigningKey::from_bytes(&[7u8; 32]);
let steward = "did:example:jcp-runtime";
let env = jcp_receipt::seal(&frame, &grant, &d, &steward_sk, steward).expect("seal");
let core = jcp_receipt::jcr1::verify_cose_sign1(&env, steward, &steward_sk.verifying_key().to_bytes()).expect("verifies");
let sealed: Value = jcp_schema::from_canonical_cbor(&core).expect("decodes");
eprintln!("sealed: cost_uj {} [{}]", sealed["cost_uj"], sealed["energy_provenance"]);
assert_eq!(sealed["energy_provenance"].as_str(), Some("Estimator"), "{sealed}");
assert_eq!(sealed["cost_uj"].as_u64(), Some(50_000), "{sealed}");
}
}

View file

@ -0,0 +1,37 @@
//! The `jcp` demo, run as a user runs it: the receipt it seals for its last
//! allowed row is over a scripted cost no tool spent, so the line it prints
//! for that receipt must grade it `Estimator`, never `HwShunt`.
use std::process::Command;
#[test]
fn the_demo_receipt_is_graded_an_estimate() {
let out = Command::new(env!("CARGO_BIN_EXE_jcp")).output().expect("run the jcp binary");
assert!(out.status.success(), "jcp failed: {}", String::from_utf8_lossy(&out.stderr));
let stdout = String::from_utf8(out.stdout).expect("utf-8 output");
eprintln!("{stdout}");
let receipt = stdout.lines().find(|l| l.trim_start().starts_with("receipt")).expect("a receipt line");
assert!(receipt.contains("· Estimator ·"), "the scripted cost's receipt is not graded an estimate: {receipt}");
assert!(!receipt.contains("HwShunt"), "the scripted cost's receipt claims a hardware reading: {receipt}");
assert!(receipt.ends_with("verified true"), "{receipt}");
assert!(stdout.contains("budget-exceeded"), "the script no longer runs the budget out:\n{stdout}");
}
/// The `meter` line prints the probe's figure at the grade the meter gave
/// that probe, and no other grade beside it: a hardware rung whose probe came
/// back an estimate must not be labelled with the rung's best grade.
#[test]
fn the_meter_line_names_only_the_probes_grade() {
let out = Command::new(env!("CARGO_BIN_EXE_jcp")).output().expect("run the jcp binary");
assert!(out.status.success(), "jcp failed: {}", String::from_utf8_lossy(&out.stderr));
let stdout = String::from_utf8(out.stdout).expect("utf-8 output");
let line = stdout.lines().find(|l| l.trim_start().starts_with("meter")).expect("a meter line");
eprintln!("{line}");
let grades: Vec<&str> = ["HwShunt", "ModelBased", "Estimator"].into_iter().filter(|g| line.contains(g)).collect();
assert_eq!(grades.len(), 1, "the meter line names {grades:?}: {line}");
let grade = grades[0];
assert!(line.contains(&format!("[{grade}]")), "the grade printed is not the probe's: {line}");
if grade != "HwShunt" {
assert!(!line.contains("hardware-measured") && !line.contains("reading,"), "an estimate called a reading: {line}");
}
}

View file

@ -157,8 +157,15 @@ attestation via `sandbox-tee::energy` to derive the honest trust level; (4) conf
the attested energy equals `energy_uj`. The receipt never asserts a level it cannot
prove. The whole loop is a runnable demo:
`sandbox-tee/examples/attested_efficiency.rs` (`cargo run -p sandbox-tee --example
attested_efficiency`) attests a reading, commits it into an `efficiency/1` receipt,
re-verifies both from scratch, and derives `IntegrityAttested`.
attested_efficiency`) runs a small task, attests the figure this host's meter
gave it under the counter class that obtained it, commits it into an
`efficiency/1` receipt at the same grade, re-verifies both from scratch, and
derives `IntegrityAttested`. Where a vendor counter read the task's CPU work
(the kernel's per-process count on macOS, a RAPL package on Linux) the
statement names that counter and the receipt seals `HwShunt`; where none did,
the figure is the meter's estimate, attested as `Estimator` and sealed
`Estimator` — the report binds the figure as it was obtained and does not make
an estimate a reading.
**What `PhysicallyRooted` actually requires (an honest clarification).** It is *not*
reached by standing up a cloud confidential VM. A cloud SEV-SNP/TDX instance gives a

View file

@ -1,14 +1,23 @@
//! A live agentic-fleet efficiency demo: five coding tasks, each sealed as an
//! An agentic-fleet efficiency demo: five coding tasks, each sealed as an
//! `efficiency/1` receipt, then verified and aggregated — surfacing the waste a
//! "cost per token" number is designed to hide.
//!
//! cargo run -p jcp-efficiency --example session
//!
//! The fleet is illustrative: no task runs here, so its token counts, wall
//! times and energy figures are chosen, not read. Each energy figure is
//! sealed as what it is, an estimate (`Estimator`, no measured figure) —
//! never a hardware reading, which would claim a meter read work that never
//! happened. A binding that meters real work seals its meter's figure at the
//! meter's grade.
use ed25519_dalek::SigningKey;
use jcp_efficiency::{aggregate, verify_chain, Efficiency, EfficiencyLog};
use jcp_schema::Energy;
fn task(
/// One illustrative task's `efficiency/1` record: its energy figure is an
/// estimate, since no task runs here.
pub fn task(
id: &str,
completed: bool,
tokens_out: u64,
@ -22,7 +31,7 @@ fn task(
verdict: if completed { "tests-pass".into() } else { "gate-failed".into() },
tokens_in: tokens_out * 8, // agentic loops: accumulated context dwarfs output
tokens_out,
energy: Energy::measured(uj), // a HwShunt reading in this demo
energy: Energy::estimator(uj), // illustrative: nothing ran, nothing was read
wall_ns,
value_uusd,
energy_attestation: None,
@ -42,7 +51,7 @@ fn main() {
task("migrate-schema", false, 3_800, 8_200_000, 95_000_000_000, None), // wrong → reverted
];
println!("sealing {} efficiency/1 receipts…\n", tasks.len());
println!("sealing {} efficiency/1 receipts (illustrative tasks: energy sealed as estimates)…\n", tasks.len());
for t in &tasks {
log.append(t);
let mark = if t.completed { "✓" } else { "✗ spend bought nothing" };

View file

@ -0,0 +1,31 @@
//! The `session` example's fleet is illustrative — no task runs — so every
//! energy figure it seals must be an estimate, never a hardware reading.
//! Checked on the record the example builds (the example file is compiled in
//! here as a module) and on the `efficiency/1` receipt sealed from it,
//! recovered through the signature check.
#[allow(dead_code)]
#[path = "../examples/session.rs"]
mod session;
use ed25519_dalek::SigningKey;
use jcp_efficiency::{verify_chain, EfficiencyLog};
use jcp_schema::Provenance;
#[test]
fn the_session_examples_figures_are_sealed_as_estimates() {
let sk = SigningKey::from_bytes(&[0xed; 32]);
let mut log = EfficiencyLog::new(sk, "did:jcp:efficiency-demo");
for (id, completed) in [("fix-auth-bug", true), ("refactor-parser", false)] {
let t = session::task(id, completed, 1_200, 3_500_000, 42_000_000_000, completed.then_some(5_000_000));
eprintln!("{id}: {} µJ [{}] measured {:?}", t.energy.uj(), t.energy.provenance.jcr1_label(), t.energy.measured_uj);
assert_eq!(t.energy.provenance, Provenance::Estimator, "{id}: an illustrative figure graded {:?}", t.energy.provenance);
assert_eq!(t.energy.measured_uj, None, "{id}: a measured figure nothing read");
log.append(&t);
}
let recs = verify_chain(log.receipts(), log.steward(), &log.steward_pubkey()).expect("chain verifies");
for r in &recs {
eprintln!("sealed {}: {} µJ [{}]", r.task, r.energy_uj, r.provenance);
assert_eq!(r.provenance, "Estimator", "{}: sealed as {}", r.task, r.provenance);
}
}

View file

@ -31,6 +31,17 @@ impl Decision {
}
}
/// The cost [`Runtime::authorize`] puts on its decisions: zero, because no
/// call has run yet — a refusal never runs, and an authorization only lets
/// it. The zero is exact, but nothing read it, so it is graded `Estimator`
/// with no measured figure: sealed as `HwShunt`, every refusal's receipt
/// would claim a hardware reading of a call that never happened, and a
/// ledger's "all readings" floor would count it as one (SPEC §5: a figure
/// never claims better provenance than how it was obtained).
fn nothing_ran() -> Energy {
Energy::estimator(0)
}
/// A price for one action, in a currency's minor units (SPEC §4.8).
///
/// The money dual of [`Energy`] — with one deliberate difference: energy carries
@ -496,7 +507,8 @@ impl Runtime {
/// because for a metered gateway the true cost is unknown until the call
/// runs. Gate with this, run the tool, measure the joules, then
/// [`charge`](Self::charge) the measured figure. The returned `Decision`
/// carries the budget remaining and zero cost (nothing was debited).
/// carries the budget remaining and zero cost (nothing was debited, and
/// nothing has run), graded `Estimator`: no meter read that zero.
pub fn authorize(&mut self, frame: &Frame, sg: &SignedGrant, caller: Did, now: u64) -> Decision {
let g = &sg.grant;
let gid = g.id();
@ -506,20 +518,20 @@ impl Runtime {
{
return Decision {
verdict: Verdict::Deny(r),
cost: Energy::measured(0),
cost: nothing_ran(),
budget_remaining_uj: remaining,
};
}
if remaining == 0 {
return Decision {
verdict: Verdict::Deny(DenyReason::BudgetExceeded),
cost: Energy::measured(0),
cost: nothing_ran(),
budget_remaining_uj: 0,
};
}
Decision {
verdict: Verdict::Allow,
cost: Energy::measured(0),
cost: nothing_ran(),
budget_remaining_uj: remaining,
}
}
@ -571,7 +583,7 @@ impl Runtime {
let remaining = g.budget_uj.saturating_sub(self.spent(&gid));
let deny = |r: DenyReason| Decision {
verdict: Verdict::Deny(r),
cost: Energy::measured(0),
cost: nothing_ran(),
budget_remaining_uj: remaining,
};
if let Some(r) = self
@ -583,7 +595,7 @@ impl Runtime {
if remaining == 0 {
return Decision {
verdict: Verdict::Deny(DenyReason::BudgetExceeded),
cost: Energy::measured(0),
cost: nothing_ran(),
budget_remaining_uj: 0,
};
}
@ -597,7 +609,7 @@ impl Runtime {
}
}
}
Decision { verdict: Verdict::Allow, cost: Energy::measured(0), budget_remaining_uj: remaining }
Decision { verdict: Verdict::Allow, cost: nothing_ran(), budget_remaining_uj: remaining }
}
/// The flow-aware [`charge`](Self::charge): debit the measured tool joules as
@ -1493,4 +1505,29 @@ mod tests {
.decide_chained_flow(&f, &[root_sg], did(&holder), Energy::measured(10), 10, &FlowFacts::bottom())
.is_allow());
}
/// `authorize` puts a zero on every decision it returns — allow and each
/// refusal — because nothing has run. Nothing read that zero either, so
/// it must be graded `Estimator`, never a hardware reading: a refusal's
/// receipt seals this cost.
#[test]
fn an_authorizations_zero_is_never_a_reading() {
let (sg, holder, r) = setup();
let mut rt = Runtime::new();
let cases = [
("allow", rt.authorize(&frame(&sg, r, "read", Trust::Control), &sg, holder, 10)),
("untrusted control", rt.authorize(&frame(&sg, r, "read", Trust::Data), &sg, holder, 10)),
("action not granted", rt.authorize(&frame(&sg, r, "delete", Trust::Control), &sg, holder, 10)),
("flow allow", rt.authorize_flow(&frame(&sg, r, "read", Trust::Control), &sg, holder, 10, &FlowFacts::bottom())),
];
rt.charge(&sg.grant, Energy::measured(100));
let exhausted = rt.authorize(&frame(&sg, r, "read", Trust::Control), &sg, holder, 10);
let exhausted_flow = rt.authorize_flow(&frame(&sg, r, "read", Trust::Control), &sg, holder, 10, &FlowFacts::bottom());
for (what, d) in cases.into_iter().chain([("budget spent", exhausted), ("flow, budget spent", exhausted_flow)]) {
eprintln!("{what}: {:?} cost {} µJ [{}] measured {:?}", d.verdict, d.cost.uj(), d.cost.provenance.jcr1_label(), d.cost.measured_uj);
assert_eq!(d.cost.uj(), 0, "{what}: authorize debits nothing");
assert_eq!(d.cost.provenance, jcp_schema::Provenance::Estimator, "{what}: a zero nothing read graded {:?}", d.cost.provenance);
assert_eq!(d.cost.measured_uj, None, "{what}: a measured zero nothing read");
}
}
}

View file

@ -17,5 +17,9 @@ ed25519-dalek = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
# The pay example meters its paid compute with this host's meter.
[dev-dependencies]
jcp-energy = { workspace = true }
[lints]
workspace = true

View file

@ -65,29 +65,42 @@ fn main() {
println!("charge in EURC (grant is USDC) → {}", verdict(&profile.authorize(&eurc, 1)));
// 6. THE COUPLING. The host settles the authorized charge on chain and gets
// back a transaction; the meter reports what the paid compute actually
// consumed. Sealing them together produces the artifact neither side has:
// the payment rail knows the transaction but not the energy, an energy
// meter knows the joules but not the transaction.
// back a transaction; its meter reports what the paid compute consumed,
// at the grade it read it. Sealing them together produces the artifact
// neither side has: the payment rail knows the transaction but not the
// energy, an energy meter knows the joules but not the transaction.
// Here no transaction settles (its hash is illustrative). The paid
// compute is a small workload run here, metered by this host's meter as
// it ran, and committed at the grade the meter gave it: a hardware
// reading only where a live counter read the work, else the estimate,
// which the record names as one.
let settled = X402Settlement {
transaction: Some("0xdeadbeefcafe".into()),
network: "base".into(),
payer: Some("0xAgentWallet".into()),
};
let measured_uj = 5_812; // what the meter read, not the 6000 µJ estimate
let g = profile.seal_settlement(&req, &settled, measured_uj);
println!("\nsettled {} → sealed {}", settled.transaction.as_deref().unwrap_or("-"), verdict(&g));
let meter = jcp_energy::Meter::detect();
let (_, energy) = meter.measure(paid_compute);
let g = profile.seal_settlement(&req, &settled, energy);
println!("\nsettled {} (illustrative tx) → sealed {}", settled.transaction.as_deref().unwrap_or("-"), verdict(&g));
println!(
" paid compute: {} µJ [{}], metered here by the {:?} rung",
energy.uj(),
energy.provenance.jcr1_label(),
meter.rung()
);
// A third party verifies the binding without trusting the gateway: it
// recomputes the coupling id from the settlement record it holds and
// checks it against the receipt's payload_hash (jcp/2, SPEC §8).
let core = jcp_receipt::extract(&g.receipt, profile.steward(), &profile.steward_pubkey())
.expect("settlement receipt verifies");
let expected = settled.coupling_id(&req.resource, measured_uj).to_hex();
let expected = settled.coupling_id(&req.resource, &energy).to_hex();
println!(
" coupling verified: {} (tx + {} µJ bound into payload_hash {}…)",
" coupling verified: {} (tx + {} µJ [{}], bound into payload_hash {}…)",
core.payload_hash.as_deref() == Some(expected.as_str()),
measured_uj,
energy.uj(),
energy.provenance.jcr1_label(),
&expected[..16]
);
@ -96,7 +109,7 @@ fn main() {
let other = X402Settlement { transaction: Some("0xfeed".into()), ..settled.clone() };
println!(
" re-point to another tx → id matches: {}",
core.payload_hash.as_deref() == Some(other.coupling_id(&req.resource, measured_uj).to_hex().as_str())
core.payload_hash.as_deref() == Some(other.coupling_id(&req.resource, &energy).to_hex().as_str())
);
// 7. Every decision sealed a JCR-1 receipt that verifies under the steward
@ -120,6 +133,16 @@ fn main() {
);
}
/// The paid compute: a fixed amount of real CPU work on this thread, so the
/// meter has something to read.
fn paid_compute() -> u64 {
let mut x = 0x9e37_79b9_7f4a_7c15u64;
for i in 0..5_000_000u64 {
x = std::hint::black_box(x.rotate_left(5) ^ i).wrapping_mul(0x0000_0100_0000_01b3);
}
x
}
/// Read the verdict the way a verifier would — off the sealed decision.
fn verdict(g: &Gated) -> String {
match g.decision.verdict {

View file

@ -32,8 +32,8 @@
//!
//! - After the host settles on chain, [`X402Profile::seal_settlement`] seals a
//! receipt whose `payload_hash` commits to the **settled transaction hash and
//! the measured joules the paid compute consumed** — the coupling neither side
//! produces alone. The payment rail knows the transaction but not the energy;
//! the joules the paid compute consumed, at the grade of the meter that
//! produced them** — the coupling neither side produces alone. The payment rail knows the transaction but not the energy;
//! an energy meter knows the joules but not the transaction. A verifier holding
//! the settlement record recomputes its content id and checks it against the
//! receipt, so the binding is cryptographic, not asserted.
@ -194,20 +194,33 @@ pub struct X402Settlement {
impl X402Settlement {
/// The canonical coupling record: the settled transaction, the resource paid
/// for, and the **measured** joules the paid compute consumed.
/// for, and the joules the paid compute consumed **with the grade of the
/// meter that produced them** (`energy_provenance`, and `energy_coverage`
/// for how much of the compute the figure accounts for).
///
/// The grade is part of the record so the figure cannot claim more than how
/// it was obtained: an estimate is committed as an estimate, and a verifier
/// reads a hardware reading only where the record says `HwShunt`. A figure
/// whose grade does not hold together ([`Energy::check_provenance`]: a
/// `HwShunt` with no measured figure, an `Estimator` with one) is committed
/// as an estimate of its debit figure.
///
/// A receipt sealed over this commits to its content id (`payload_hash`,
/// SPEC §8), so a verifier holding the record can recompute the hash and
/// confirm the receipt binds *this* transaction to *this* energy figure.
/// Use [`coupling_id`](Self::coupling_id) to compute that id independently.
pub fn coupling_record(&self, resource: &str, joules_uj: u64) -> Vec<u8> {
/// confirm the receipt binds *this* transaction to *this* energy figure at
/// *this* grade. Use [`coupling_id`](Self::coupling_id) to compute that id
/// independently.
pub fn coupling_record(&self, resource: &str, energy: &Energy) -> Vec<u8> {
let energy = if energy.check_provenance().is_ok() { *energy } else { Energy::estimator(energy.uj()) };
let record = json!({
"x402_settlement": {
"network": self.network,
"transaction": self.transaction,
"payer": self.payer,
"resource": resource,
"joules_uj": joules_uj,
"joules_uj": energy.uj(),
"energy_provenance": energy.provenance.jcr1_label(),
"energy_coverage": energy.coverage.label(),
}
});
serde_json::to_vec(&record).unwrap_or_default()
@ -215,8 +228,8 @@ impl X402Settlement {
/// The content id a settlement receipt's `payload_hash` must equal — the
/// check a third party runs to verify the coupling.
pub fn coupling_id(&self, resource: &str, joules_uj: u64) -> ContentId {
ContentId::of_bytes(&self.coupling_record(resource, joules_uj))
pub fn coupling_id(&self, resource: &str, energy: &Energy) -> ContentId {
ContentId::of_bytes(&self.coupling_record(resource, energy))
}
}
@ -341,7 +354,8 @@ impl X402Profile {
/// **Seal the settlement** — after the host settles an authorized charge on
/// chain, seal a receipt whose `payload_hash` commits to the on-chain
/// transaction and the **measured** joules the paid compute consumed.
/// transaction and the joules the paid compute consumed, at the grade of
/// the meter that produced them ([`X402Settlement::coupling_record`]).
///
/// This is the artifact neither side produces alone: the payment rail knows
/// the transaction but not the energy; an energy meter knows the joules but
@ -350,20 +364,27 @@ impl X402Profile {
/// that carries the record. A verifier checks it by recomputing
/// [`X402Settlement::coupling_id`] and comparing it to the receipt's
/// `payload_hash`.
///
/// The receipt's own cost is the zero it debits, graded `Estimator`: the
/// zero is an accounting fact, not a reading, and sealed `HwShunt` it
/// would claim a hardware reading of 0 µJ beside a record whose joules are
/// the host's. `energy` is the host's figure for the paid compute, as its
/// meter graded it, committed with that grade: a host with only an
/// estimate passes an estimate, and the record says so.
pub fn seal_settlement(
&mut self,
req: &X402Requirements,
settlement: &X402Settlement,
measured_uj: u64,
energy: Energy,
) -> Gated {
let payload = settlement.coupling_record(&req.resource, measured_uj);
let payload = settlement.coupling_record(&req.resource, &energy);
let gated = self.bridge.call_x402_priced(
&self.grant,
self.caller,
&req.network,
&req.pay_to,
&payload,
Energy::measured(0), // records the coupling; does not re-debit
Energy::estimator(0), // records the coupling; debits nothing, reads nothing
&Price::new(&req.asset, 0),
self.now,
);
@ -511,8 +532,8 @@ mod tests {
}
/// THE coupling: the settlement receipt cryptographically binds the settled
/// on-chain transaction to the measured joules. Possible only because the
/// `jcp/2` profile commits `payload_hash` (SPEC §8).
/// on-chain transaction to the paid compute's joules at their grade.
/// Possible only because the `jcp/2` profile commits `payload_hash` (SPEC §8).
#[test]
fn settlement_receipt_binds_tx_to_measured_joules() {
let req = ingest_requirements(&sample_req()).unwrap();
@ -532,33 +553,66 @@ mod tests {
network: "base".into(),
payer: Some("0xAgentWallet".into()),
};
let g = profile.seal_settlement(&req, &settled, 4_200);
let read = Energy::measured(4_200);
let g = profile.seal_settlement(&req, &settled, read);
assert!(g.allowed());
// A third party recomputes the coupling id and checks the receipt.
let core = jcp_receipt::extract(&g.receipt, profile.steward(), &profile.steward_pubkey()).unwrap();
assert_eq!(
core.payload_hash.as_deref(),
Some(settled.coupling_id(&req.resource, 4_200).to_hex().as_str()),
Some(settled.coupling_id(&req.resource, &read).to_hex().as_str()),
"the receipt must bind THIS transaction to THIS energy figure"
);
// A different tx hash — or different joules — yields a different id, so
// the receipt cannot be re-pointed at another settlement.
// A different tx hash, different joules, or the same joules at another
// grade yields a different id, so the receipt cannot be re-pointed at
// another settlement, nor its figure re-graded.
let other_tx = X402Settlement { transaction: Some("0xfeed".into()), ..settled.clone() };
assert_ne!(
core.payload_hash.as_deref(),
Some(other_tx.coupling_id(&req.resource, 4_200).to_hex().as_str())
);
assert_ne!(
core.payload_hash.as_deref(),
Some(settled.coupling_id(&req.resource, 9_999).to_hex().as_str())
);
for (what, other) in [
("another tx", other_tx.coupling_id(&req.resource, &read)),
("other joules", settled.coupling_id(&req.resource, &Energy::measured(9_999))),
("an estimate of the same joules", settled.coupling_id(&req.resource, &Energy::estimator(4_200))),
("a partial reading", settled.coupling_id(&req.resource, &Energy::measured_partial(4_200))),
] {
assert_ne!(core.payload_hash.as_deref(), Some(other.to_hex().as_str()), "{what}");
}
// Two receipts on the ledger: the authorize and the settlement.
assert_eq!(profile.receipts().len(), 2);
// The settlement did not re-debit; only the authorize estimate counted.
assert_eq!(profile.spent_uj(), 4_200);
// Its own cost is the zero it debits, which nothing read: sealed as an
// estimate, never as a hardware reading of 0 µJ.
let sealed = jcp_receipt::jcr1::verify_cose_sign1(&g.receipt, profile.steward(), &profile.steward_pubkey())
.expect("the settlement receipt verifies");
let sealed: Value = jcp_schema::from_canonical_cbor(&sealed).expect("decodes");
eprintln!("settlement receipt: cost_uj {} [{}]", sealed["cost_uj"], sealed["energy_provenance"]);
assert_eq!(sealed["cost_uj"].as_u64(), Some(0), "{sealed}");
assert_eq!(sealed["energy_provenance"].as_str(), Some("Estimator"), "a zero nothing read sealed as: {sealed}");
}
/// The coupling record states its figure's grade, so a verifier reads a
/// hardware reading only where the host's meter read one; a figure whose
/// grade does not hold together is committed as an estimate.
#[test]
fn the_coupling_record_carries_the_figures_grade() {
let settled = X402Settlement { transaction: Some("0xabc".into()), network: "base".into(), payer: None };
let record = |e: Energy| -> Value {
serde_json::from_slice::<Value>(&settled.coupling_record("/r", &e)).unwrap()["x402_settlement"].clone()
};
let read = record(Energy::measured(4_200));
assert_eq!((read["joules_uj"].as_u64(), read["energy_provenance"].as_str()), (Some(4_200), Some("HwShunt")));
assert_eq!(read["energy_coverage"].as_str(), Some("Whole"));
let est = record(Energy::estimator(4_200));
assert_eq!(est["energy_provenance"].as_str(), Some("Estimator"));
assert_eq!(record(Energy::modeled(4_200))["energy_provenance"].as_str(), Some("ModelBased"));
assert_eq!(record(Energy::measured_partial(4_200))["energy_coverage"].as_str(), Some("Partial"));
// A HwShunt grade with no measured figure is not a reading.
let forged = Energy { measured_uj: None, ..Energy::measured(4_200) };
let forged = record(forged);
assert_eq!((forged["joules_uj"].as_u64(), forged["energy_provenance"].as_str()), (Some(4_200), Some("Estimator")));
}
/// A charge to a merchant the grant is not scoped to is denied on audience.

View file

@ -6,14 +6,17 @@
//!
//! The output file is directly loadable by an EOC router trainer's JSONL
//! loader. This example stands in a synthetic ledger for the receipts a
//! real deployment would read off disk.
//! real deployment would read off disk. Its figures are chosen, not read,
//! so every stand-in receipt is graded `Estimator`: the corpus carries the
//! grade as a feature, and a real deployment's receipts carry their own.
use jouleclaw_corpus::{CorpusBuilder, write_jsonl};
use jouleclaw_energy::Provenance;
use jouleclaw_intent::{IntentVerdict, QueryIntent};
use jouleclaw_prov::{CascadeTier, Receipt};
fn receipt(tier: CascadeTier, uj: u64, intent: QueryIntent, confidence: f64) -> Receipt {
/// One stand-in receipt of the synthetic ledger, its figure an estimate.
pub fn receipt(tier: CascadeTier, uj: u64, intent: QueryIntent, confidence: f64) -> Receipt {
Receipt {
context: None,
jc_receipt: "1".into(),
@ -22,7 +25,11 @@ fn receipt(tier: CascadeTier, uj: u64, intent: QueryIntent, confidence: f64) ->
input_hash: "a".repeat(64),
tier,
joules_uj: uj,
energy_provenance: Provenance::HwShunt,
// A stand-in: nothing ran and no meter read `uj`, so it is graded
// what it is, an estimate. The corpus encodes the grade as a feature
// (its provenance one-hot); a stand-in graded `HwShunt` would teach a
// router that these figures were hardware readings.
energy_provenance: Provenance::Estimator,
tools_touched: Vec::new(),
claims: Vec::new(),
eoc_stage: None,

View file

@ -12,7 +12,8 @@
//! is why this example is behind the `candle` feature and asks for the network
//! once. The `build_with_text` join — pairing each receipt with the query that
//! produced it — is exactly what a real deployment does from its own logs; here
//! we stand in a small labelled ledger.
//! we stand in a small labelled ledger, its figures chosen, not read, and so
//! graded `Estimator`.
use jouleclaw_corpus::{CandleTextEmbedder, CorpusBuilder, TextEmbedder, write_jsonl};
use jouleclaw_embed_candle::{CandleEmbedder, EmbedderConfig};
@ -30,7 +31,11 @@ fn receipt(tier: CascadeTier, uj: u64, intent: QueryIntent) -> Receipt {
input_hash: "a".repeat(64),
tier,
joules_uj: uj,
energy_provenance: Provenance::HwShunt,
// A stand-in: nothing ran and no meter read `uj`, so it is graded
// what it is, an estimate. The corpus encodes the grade as a feature
// (its provenance one-hot); a stand-in graded `HwShunt` would teach a
// router that these figures were hardware readings.
energy_provenance: Provenance::Estimator,
tools_touched: Vec::new(),
claims: Vec::new(),
eoc_stage: None,

View file

@ -0,0 +1,36 @@
//! The `emit_corpus` example stands in a synthetic ledger: its figures are
//! chosen, not read, so every stand-in receipt must be graded `Estimator`,
//! and the corpus rows built from them must carry that grade in their
//! provenance one-hot (dims 7–9: HwShunt / ModelBased / Estimator) — never
//! the hardware-reading slot. The example file is compiled in here as a
//! module, so its own `receipt` builds what is checked.
#[allow(dead_code)]
#[path = "../examples/emit_corpus.rs"]
mod emit_corpus;
use jouleclaw_corpus::CorpusBuilder;
use jouleclaw_energy::Provenance;
use jouleclaw_intent::QueryIntent;
use jouleclaw_prov::CascadeTier;
#[test]
fn the_synthetic_ledger_is_graded_an_estimate() {
let ledger = vec![
emit_corpus::receipt(CascadeTier::L0Cache, 12, QueryIntent::Comprehension, 0.91),
emit_corpus::receipt(CascadeTier::L2Embed, 4_100, QueryIntent::Comprehension, 0.72),
emit_corpus::receipt(CascadeTier::L3Model, 2_400_000, QueryIntent::Generation, 0.94),
emit_corpus::receipt(CascadeTier::L4Wire, 61_000_000, QueryIntent::Generation, 0.97),
];
for r in &ledger {
eprintln!("{}: {} µJ [{:?}]", r.id, r.joules_uj, r.energy_provenance);
assert_eq!(r.energy_provenance, Provenance::Estimator, "{}: a stand-in figure graded {:?}", r.id, r.energy_provenance);
}
let (rows, stats) = CorpusBuilder::default().with_monotone_negatives(true).build(&ledger);
eprintln!("{} rows from {} receipts", rows.len(), stats.receipts_seen);
assert!(!rows.is_empty(), "the corpus built no rows");
for row in &rows {
let one_hot = &row.embedding[7..10];
assert_eq!(one_hot, &[0.0, 0.0, 1.0], "a row's provenance one-hot is not Estimator's: {one_hot:?}");
}
}

View file

@ -202,7 +202,9 @@ pub struct EconReport {
pub joules_per_verified_fix: f64,
/// **Headline: dollars per verified fix** (`f64::INFINITY` if none verified).
pub usd_per_verified_fix: f64,
/// Worst energy provenance observed — the honesty floor of the joule figures.
/// Worst energy provenance observed — the honesty floor of the joule
/// figures. `Estimator` while cascade answers carry no grade of their own:
/// every tier's joules are the figure the tier reported, not a reading.
pub energy_provenance: Provenance,
}
@ -494,14 +496,18 @@ impl Tier for FixedModelTier {
}
}
/// Honest provenance of a tier's accounted joules. Local deterministic tiers
/// (cache / skill) are exact by construction; model tiers are estimates unless
/// the tier itself carries a hardware figure (which this v0 cannot see).
fn provenance_of(tier: TierId) -> Provenance {
match tier {
TierId::L0 | TierId::L0_5ToolCompute => Provenance::HwShunt,
_ => Provenance::Estimator,
}
/// The grade of a tier's accounted joules, as far as this harness can know
/// it. A cascade answer carries the joules its tier reported and no grade: a
/// compiled skill's constant (`jouleclaw_skill::SKILL_JOULES`, 20 nJ a
/// resolution), a cache's estimate of a lookup, a model tier's own figure. No
/// tier's figure is a reading this harness took or can see the grade of, so
/// every one is graded `Estimator` — a cache or skill hit included: its figure
/// is exact only as a constant is, and sealed `HwShunt` it would claim a
/// hardware reading nothing took. A run whose model dispatches are metered
/// reports each dispatch's own grade beside the report ([`window_joules`],
/// [`span_joules`]); the report's floor stays an estimate's.
fn provenance_of(_tier: TierId) -> Provenance {
Provenance::Estimator
}
/// Degrade to the worse of two provenances (same floor rule as `jouleclaw-prov`).
@ -642,6 +648,52 @@ mod tests {
assert_eq!(joules_obtained(Provenance::ModelBased), "measured");
}
/// A run that only ever hits a compiled skill is billed the skill's
/// constant (`SKILL_JOULES` a resolution): a figure nothing read, so the
/// report's floor must say `Estimator`, never `HwShunt`.
#[test]
fn a_skill_only_run_is_reported_as_an_estimate() {
let prompt = "generate getter for field user_id";
let answer = "fn user_id(&self) -> &str { &self.user_id }";
let tasks = vec![Task::text(
"getter-user_id",
"getter",
q(prompt),
move |o| matches!(o, AnswerOutput::Text(t) if t == answer),
)];
let harness = EconHarness::new(Box::new(ConstantSkillInducer), 3);
let report = harness.run(
move |store| {
// The class is compiled before the first round, so no round
// reaches a model: every answer is the skill's.
let skill = ConstantSkillInducer
.induce(prompt, answer, TierId::L0_5ToolCompute)
.expect("a constant skill");
store.lock().unwrap().register(skill);
let mut casc = Cascade::new();
casc.register(Box::new(SkillTier::new(store)));
Runtime::new_without_l0(casc)
},
&tasks,
3,
);
eprintln!(
"skill-only run: {} rows on tiers {:?}, {} J, floor {:?}",
report.rows.len(),
report.rows.iter().map(|r| r.tier_tag.as_str()).collect::<Vec<_>>(),
report.total_joules,
report.energy_provenance
);
assert_eq!(report.verified, 3, "every round resolves through the skill");
assert!(report.rows.iter().all(|r| r.hit_skill), "a row missed the skill: {:?}", report.rows);
assert!(
(report.total_joules - 3.0 * SKILL_JOULES).abs() < 1e-15,
"billed {} J, not the skill's constant ×3",
report.total_joules
);
assert_eq!(report.energy_provenance, Provenance::Estimator, "a skill's constant reported as a reading");
}
#[test]
fn an_estimate_is_never_reported_as_measured() {
assert_eq!(joules_obtained(Provenance::Estimator), "estimated");

View file

@ -322,9 +322,32 @@ func viol(parent NodeShape, p PropertyShape, msg string) Violation {
// TransportResponse is what a Transport returns to the client.
type TransportResponse struct {
Status int
Body interface{}
Status int
Body interface{}
// JoulesUJ is the transport's figure for the dispatch's energy, if it
// has one. nil: none, and the client emits a zero graded "Estimator".
JoulesUJ *uint64
// JoulesProvenance is the grade of the meter that produced JoulesUJ:
// "HwShunt" only for a hardware reading, "ModelBased", or "Estimator".
// Empty (or any other value) is sealed "Estimator": the client cannot
// tell how a transport obtained a figure, and a figure must not claim
// better provenance than how it was obtained.
JoulesProvenance string
}
// GradedJoules is the figure and grade the client seals: the transport's
// figure at its stated grade, an ungraded figure as an estimate, and no
// figure as a zero estimate. Matches TransportResponse::graded_joules.
func (r *TransportResponse) GradedJoules() (uint64, string) {
if r.JoulesUJ == nil {
return 0, "Estimator"
}
switch r.JoulesProvenance {
case "HwShunt", "ModelBased", "Estimator":
return *r.JoulesUJ, r.JoulesProvenance
default:
return *r.JoulesUJ, "Estimator"
}
}
// Transport pluggable transport interface.
@ -458,12 +481,7 @@ func (c *HydraClient) Call(opName string, input interface{}, transport Transport
break
}
}
provenance := "Estimator"
joules := uint64(0)
if resp.JoulesUJ != nil {
provenance = "HwShunt"
joules = *resp.JoulesUJ
}
joules, provenance := resp.GradedJoules()
return &CallReport{
ToolID: toolID,
Status: resp.Status,

View file

@ -119,3 +119,46 @@ func TestValidationConformance(t *testing.T) {
}
}
}
// A transport's joule figure says nothing of how it was obtained: an
// ungraded figure is sealed as an estimate, never as a hardware reading.
func TestUngradedJoulesAreSealedAsEstimates(t *testing.T) {
doc := loadConformance(t)
apiBytes, _ := json.Marshal(doc["api"])
api, err := ParseAPI(apiBytes)
if err != nil {
t.Fatalf("parse api: %v", err)
}
client := NewClient(api, shapeGraphForTests())
reports := doc["call_reports"].([]interface{})
v := reports[0].(map[string]interface{})
op := v["operation"].(string)
opID := client.FindOperation(op).ID
seven := uint64(7)
transport := NewMockTransport().Respond(opID, &TransportResponse{Status: 200, Body: map[string]interface{}{}, JoulesUJ: &seven})
got, err := client.Call(op, v["input"], transport)
if err != nil {
t.Fatalf("call: %v", err)
}
if got.Touch["joules_uj"] != uint64(7) || got.Touch["energy_provenance"] != "Estimator" {
t.Errorf("an ungraded figure sealed as %v", got.Touch)
}
}
// A graded figure keeps the grade the transport gave it.
func TestGradedJoulesKeepTheirGrade(t *testing.T) {
nine := uint64(9)
for _, grade := range []string{"HwShunt", "ModelBased", "Estimator"} {
r := &TransportResponse{JoulesUJ: &nine, JoulesProvenance: grade}
if uj, p := r.GradedJoules(); uj != 9 || p != grade {
t.Errorf("%s: sealed %d %s", grade, uj, p)
}
}
if _, p := (&TransportResponse{JoulesUJ: &nine, JoulesProvenance: "Measured"}).GradedJoules(); p != "Estimator" {
t.Errorf("an unknown grade sealed as %s", p)
}
if uj, p := (&TransportResponse{JoulesProvenance: "HwShunt"}).GradedJoules(); uj != 0 || p != "Estimator" {
t.Errorf("no figure sealed as %d %s", uj, p)
}
}

View file

@ -35,11 +35,32 @@ class InputInvalid(ClientError):
self.report = report
GRADES = ("HwShunt", "ModelBased", "Estimator")
@dataclass
class TransportResponse:
status: int
body: Any
# The transport's figure for the dispatch's energy, if it has one.
# None: none, and the client emits a zero graded "Estimator".
joules_uj: Optional[int] = None
# The grade of the meter that produced `joules_uj`: "HwShunt" only for a
# hardware reading, "ModelBased", or "Estimator". None (or any other
# value) is sealed "Estimator": the client cannot tell how a transport
# obtained a figure, and a figure must not claim better provenance than
# how it was obtained.
joules_provenance: Optional[str] = None
def graded_joules(self) -> "tuple[int, str]":
"""The figure and grade the client seals: the transport's figure at
its stated grade, an ungraded figure as an estimate, and no figure as
a zero estimate. Matches `TransportResponse::graded_joules` (Rust)."""
if self.joules_uj is None:
return 0, "Estimator"
if self.joules_provenance in GRADES:
return self.joules_uj, self.joules_provenance
return self.joules_uj, "Estimator"
class Transport(Protocol):
@ -138,8 +159,7 @@ class HydraClient:
status_matches = any(
s.get("code") == response.status for s in op.status_codes
)
provenance = "HwShunt" if response.joules_uj is not None else "Estimator"
joules_uj = response.joules_uj or 0
joules_uj, provenance = response.graded_joules()
return CallReport(
tool_id=tool_id,
status=response.status,

View file

@ -0,0 +1,48 @@
"""A transport's joule figure says nothing of how it was obtained: the
client seals an ungraded figure as an estimate, never as a hardware
reading, and a graded one at the grade the transport gave it. Matches
`TransportResponse::graded_joules` in the Rust client and
`GradedJoules` in the Go one.
Run: `python -m pytest tests/` (requires `blake3`).
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
from test_conformance import VECTORS, shapes # noqa: E402
from jclaw_hydra import HydraClient, MockTransport, TransportResponse, parse_api # noqa: E402
def _call(response: TransportResponse) -> dict:
doc = json.loads(VECTORS.read_text())
client = HydraClient(parse_api(doc["api"]), shapes=shapes())
vector = doc["call_reports"][0]
op = client.find_operation(vector["operation"])
transport = MockTransport().respond(op.id, response)
return client.call(vector["operation"], vector["input"], transport).touch
def test_an_ungraded_figure_is_sealed_as_an_estimate() -> None:
touch = _call(TransportResponse(status=200, body={}, joules_uj=7))
assert (touch["joules_uj"], touch["energy_provenance"]) == (7, "Estimator"), touch
def test_a_graded_figure_keeps_its_grade() -> None:
for grade in ("HwShunt", "ModelBased", "Estimator"):
touch = _call(TransportResponse(status=200, body={}, joules_uj=9, joules_provenance=grade))
assert (touch["joules_uj"], touch["energy_provenance"]) == (9, grade), touch
def test_an_unknown_grade_or_no_figure_is_an_estimate() -> None:
touch = _call(TransportResponse(status=200, body={}, joules_uj=9, joules_provenance="Measured"))
assert touch["energy_provenance"] == "Estimator", touch
touch = _call(TransportResponse(status=200, body={}, joules_provenance="HwShunt"))
assert (touch["joules_uj"], touch["energy_provenance"]) == (0, "Estimator"), touch

View file

@ -36,8 +36,9 @@ The three implementations live at:
# Rust (regenerator; also the oracle)
cargo run -p jouleclaw-hydra-client --example gen_conformance_vectors
# Python (requires `pip install blake3`)
# Python (requires `pip install blake3`; the energy-grade tests also pytest)
python3 crates/jouleclaw-hydra-client/clients/python/tests/test_conformance.py
python3 -m pytest crates/jouleclaw-hydra-client/clients/python/tests/
# Go (uses lukechampine.com/blake3 via go.mod)
cd crates/jouleclaw-hydra-client/clients/go && go test -v ./...

View file

@ -121,10 +121,16 @@ pub struct TransportResponse {
pub status: u16,
/// Response payload — typically JSON; opaque bytes welcome too.
pub body: Value,
/// Joules spent in the inner dispatch, if the transport measured
/// them. `None` means the transport did not observe energy; the
/// client emits a `Provenance::Estimator` receipt entry.
/// Joules spent in the inner dispatch, if the transport has a figure
/// for them. `None` means it has none; the client emits a zero graded
/// `Provenance::Estimator`.
pub joules_uj: Option<u64>,
/// The grade of the meter that produced `joules_uj`, as the transport
/// knows it: `HwShunt` only for a hardware reading. `None` — a figure
/// with no grade — is sealed `Provenance::Estimator`: the client cannot
/// tell how a transport obtained a figure, and a figure must not claim
/// better provenance than how it was obtained.
pub joules_provenance: Option<Provenance>,
}
impl TransportResponse {
@ -133,6 +139,25 @@ impl TransportResponse {
status: 200,
body,
joules_uj: None,
joules_provenance: None,
}
}
/// This response with a joule figure and the grade of the meter that
/// produced it.
pub fn with_joules(mut self, uj: u64, provenance: Provenance) -> Self {
self.joules_uj = Some(uj);
self.joules_provenance = Some(provenance);
self
}
/// The figure and grade the client seals: the transport's figure at its
/// stated grade, an ungraded figure as an estimate, and no figure as a
/// zero estimate.
pub fn graded_joules(&self) -> (u64, Provenance) {
match self.joules_uj {
Some(uj) => (uj, self.joules_provenance.unwrap_or(Provenance::Estimator)),
None => (0, Provenance::Estimator),
}
}
}
@ -180,6 +205,7 @@ impl Transport for MockTransport {
status: 200,
body: serde_json::json!({ "echo": input }),
joules_uj: None,
joules_provenance: None,
})
}
}
@ -326,14 +352,11 @@ impl HydraClient {
.iter()
.any(|s| s.code == response.status);
let (joules_uj, energy_provenance) = response.graded_joules();
let touch = ToolTouch {
tool_id: tool_id.clone(),
joules_uj: response.joules_uj.unwrap_or(0),
energy_provenance: if response.joules_uj.is_some() {
Provenance::HwShunt
} else {
Provenance::Estimator
},
joules_uj,
energy_provenance,
};
Ok(CallReport {
@ -693,6 +716,7 @@ mod tests {
status: 201,
body: json!({ "ok": true, "id": "n1.x" }),
joules_uj: Some(7),
joules_provenance: Some(Provenance::HwShunt),
},
);
let report = c
@ -766,6 +790,41 @@ mod tests {
assert_eq!(report.body["echo"], json!({ "completed": true }));
}
/// A transport's figure says nothing of how it was obtained, so an
/// ungraded figure is sealed as an estimate, never as a hardware reading.
#[tokio::test]
async fn an_ungraded_transport_figure_is_sealed_as_an_estimate() {
let c = client();
let t = MockTransport::new().respond(
"_:op_jouleclaw_list_nodes",
TransportResponse {
status: 200,
body: json!([]),
joules_uj: Some(7),
joules_provenance: None,
},
);
let report = c.call("jouleclaw:list_nodes", json!({}), &t).await.unwrap();
assert_eq!(report.touch.joules_uj, 7);
assert!(
matches!(report.touch.energy_provenance, Provenance::Estimator),
"an ungraded figure sealed as {:?}",
report.touch.energy_provenance
);
}
/// A graded figure keeps the grade the transport gave it, whatever it is.
#[tokio::test]
async fn a_graded_transport_figure_keeps_its_grade() {
let c = client();
for grade in [Provenance::HwShunt, Provenance::ModelBased, Provenance::Estimator] {
let t = MockTransport::new()
.respond("_:op_jouleclaw_list_nodes", TransportResponse::ok(json!([])).with_joules(9, grade));
let report = c.call("jouleclaw:list_nodes", json!({}), &t).await.unwrap();
assert_eq!((report.touch.joules_uj, report.touch.energy_provenance), (9, grade));
}
}
#[tokio::test]
async fn call_records_estimator_provenance_when_transport_skips_energy() {
let c = client();
@ -845,6 +904,7 @@ mod tests {
status: 200,
body: json!([]),
joules_uj: None,
joules_provenance: None,
},
);
let r = c

View file

@ -8,6 +8,11 @@
//!
//! Run with:
//! cargo run -p jouleclaw-stack --example ledger_breakdown
//!
//! The workload is simulated: no tier runs and no meter reads a figure, so
//! every tool touch is graded `Estimator` ([`simulated_touch`]), and the
//! summary's provenance floor says so. A deployment's receipts carry the
//! grade of whatever metered each touch.
use jouleclaw_energy::Provenance;
use jouleclaw_intent::{HeuristicClassifier, IntentClassifier};
@ -37,15 +42,7 @@ fn main() {
let mut b = ReceiptBuilder::new()
.input_hash(input_hash(q))
.tier(*tier)
.account_tool(ToolTouch {
tool_id: tool_id.to_string(),
joules_uj: *joules_uj,
energy_provenance: if matches!(tier, CascadeTier::L3Model) {
Provenance::ModelBased
} else {
Provenance::HwShunt
},
})
.account_tool(simulated_touch(tool_id, *joules_uj))
.intent(intent);
if let Some(m) = model_id {
b = b.model_id(m);
@ -71,6 +68,14 @@ fn main() {
print_rows("by intent", &summary.by_intent);
}
/// A simulated tool touch: its figure is chosen, not read, so it is graded
/// `Estimator` at every tier. Graded `HwShunt` (as the cheap tiers were) it
/// would claim a hardware reading, and `ModelBased` (as the model tier was) an
/// energy model's figure, of work that never ran.
pub fn simulated_touch(tool_id: &str, joules_uj: u64) -> ToolTouch {
ToolTouch { tool_id: tool_id.to_string(), joules_uj, energy_provenance: Provenance::Estimator }
}
fn print_rows(label: &str, rows: &[jouleclaw_ledger::CostRow]) {
if rows.is_empty() {
return;

View file

@ -0,0 +1,36 @@
//! The `ledger_breakdown` example simulates its workload: no tier runs and
//! no meter reads a figure, so every tool touch it seals must be graded
//! `Estimator`, and so must the ledger summary's provenance floor and every
//! row of it — at the model tier as at the cheap ones. The example file is
//! compiled in here as a module, so its own `simulated_touch` builds what is
//! sealed.
#[allow(dead_code)]
#[path = "../examples/ledger_breakdown.rs"]
mod ledger_breakdown;
use jouleclaw_energy::Provenance;
use jouleclaw_ledger::{InMemoryLedger, Ledger, LedgerStore, ProvenanceFloor, Window};
use jouleclaw_prov::{input_hash, CascadeTier, ReceiptBuilder};
#[test]
fn the_simulated_workload_is_sealed_as_estimates() {
let mut ledger = InMemoryLedger::new();
for (q, tier, uj, tool) in [
("explain the cascade", CascadeTier::L0Cache, 5, "cache.lookup"),
("what does jouleclaw-prov do?", CascadeTier::L1Lawful, 12, "iac:lawful.lookup"),
("write a hello-world fn", CascadeTier::L3Model, 1_200_000, "model:any"),
] {
let touch = ledger_breakdown::simulated_touch(tool, uj);
eprintln!("{tool}: {} µJ [{:?}]", touch.joules_uj, touch.energy_provenance);
assert_eq!(touch.energy_provenance, Provenance::Estimator, "{tool}: a simulated figure graded {:?}", touch.energy_provenance);
let receipt = ReceiptBuilder::new().input_hash(input_hash(q)).tier(tier).account_tool(touch).seal().expect("seal");
ledger.append(receipt).expect("append");
}
let summary = Ledger::new(&ledger).summary(&Window::any());
eprintln!("summary floor {:?} over {} receipts", summary.provenance_floor, summary.receipt_count);
assert_eq!(summary.provenance_floor, ProvenanceFloor::Estimator, "the simulated ledger's floor");
for r in summary.by_tier.iter().chain(&summary.by_tool) {
assert_eq!(r.provenance_floor, ProvenanceFloor::Estimator, "row {}: {:?}", r.key, r.provenance_floor);
}
}

View file

@ -131,7 +131,10 @@ tasks that ran but never completed against the results actually delivered*. That
the number a "tasks handled" count hides. Where a skill's work is itself token-based
(an LLM skill), the receipt also carries the per-token figures (µJ per accepted token,
tokens per completed unit, waste fraction); for a general task, joules-per-completed-
unit is the honest headline. The teammate's contribution is *measured*, not asserted.
unit is the honest headline. The teammate's contribution is *metered*, not asserted:
each task's figure carries the grade of the meter that produced it — a hardware
reading only where a live counter read the task, otherwise an estimate, graded as
one — and a rollup is no better than the weakest figure it sums.
---

View file

@ -61,7 +61,7 @@ fn main() {
Err(i) => println!(" ledger FAILED to verify at receipt {i}"),
}
let s = joule.energy_summary();
println!(" the teammate's measured contribution (§6):");
println!(" the teammate's contribution (§6), each figure at the grade of the meter that produced it:");
println!(" completed units : {}", s.completed_units);
println!(" wasted units : {} (ran, produced no result)", s.wasted_units);
println!(

View file

@ -30,7 +30,7 @@ fn main() {
if call.gate_turn(cap, est) {
call.meter(tin, tout, est); // the boundary reports the real usage
call.complete_turn();
println!(" {who:>5} │ {said}\n └─ ✓ {cap} — served, metered {est} µJ");
println!(" {who:>5} │ {said}\n └─ ✓ {cap} — served, an estimated {est} µJ");
} else {
println!(
" {who:>5} │ {said}\n └─ ✗ {cap} refused (unheld, or over the session ceiling) — decided outside the model"
@ -59,7 +59,7 @@ fn main() {
println!(
"\n The 'answer' turn about risks was refused — 5.5 mJ already committed, +3 mJ would\n \
break the 8 mJ ceiling. 'delete_recording' was refused: no such grant. What sealed is\n \
exactly the authorised conversation, at its measured energy — a receipt of what @joule\n \
did in the call that anyone in the room can verify."
exactly the authorised conversation, at its estimated energy (sealed `Estimator`) — a\n \
receipt of what @joule did in the call that anyone in the room can verify."
);
}

View file

@ -238,11 +238,17 @@ impl Teammate {
/// teammate authorises it against its grants **outside the model**, runs it, and
/// seals the decision. Returns the outcome.
///
/// The task's `efficiency/1` receipt carries its energy as a hardware reading
/// ([`EnergyProvenance::HwShunt`]). A binding whose figure came from anything
/// else — an energy model, an estimator — uses [`Self::tag_with_provenance`].
/// The task's `efficiency/1` receipt carries the cost the dispatch's last
/// decision receipt sealed: the spend the skill reported, else the cost it
/// committed before it ran. Nothing here says how the skill obtained that
/// figure — the reference [`Skill`] reports a constant — so it is sealed as
/// an estimate ([`EnergyProvenance::Estimator`]), the grade the decision
/// receipt already gives it. Sealed as a hardware reading it would claim a
/// meter read work no meter saw (SPEC §6: energy "at honest provenance").
/// A binding whose skill meters its work passes its meter's grade with
/// [`Self::tag_with_provenance`].
pub fn tag(&mut self, kind: &str, intent: &str) -> TagOutcome {
self.tag_with_provenance(kind, intent, EnergyProvenance::HwShunt)
self.tag_with_provenance(kind, intent, EnergyProvenance::Estimator)
}
/// [`Self::tag`], sealing the task's `efficiency/1` energy at `provenance`: how
@ -343,9 +349,12 @@ impl Teammate {
self.eff.receipts()
}
/// The teammate's measured contribution rolled up (SPEC §6): completed vs wasted
/// The teammate's contribution rolled up (SPEC §6): completed vs wasted
/// units, joules per completed unit, and the **waste fraction** — the ROI a
/// "tasks handled" count hides. Verifies the energy ledger before aggregating.
/// Each receipt's figure carries the grade of the meter that produced it; the
/// totals carry none of their own, so they are no better than the weakest
/// receipt they sum — a total over estimates is an estimate.
pub fn energy_summary(&self) -> Totals {
let recs = jcp_efficiency::verify_chain(
self.eff.receipts(),
@ -483,11 +492,20 @@ mod tests {
assert_eq!(t.tag_with_provenance("summarize", "the Q3 thread", provenance), TagOutcome::Done);
assert_eq!(sealed_provenance(&t), label, "an energy figure obtained as {provenance:?}");
}
// Plain `tag` is unchanged: it seals the committed cost as a hardware reading.
// Plain `tag` (and `tag_mention`, which calls it) knows nothing of how
// the skill obtained its cost — the reference skill reports a constant —
// so it seals an estimate, never a hardware reading nothing took.
let mut t = Teammate::new();
t.grant_skill(summarizer(), 1_000_000).unwrap();
assert_eq!(t.tag("summarize", "the Q3 thread"), TagOutcome::Done);
assert_eq!(sealed_provenance(&t), "HwShunt");
let plain = sealed_provenance(&t);
let mut m = Teammate::new();
m.grant_skill(summarizer(), 1_000_000).unwrap();
assert_eq!(m.tag_mention("@joule summarize the Q3 thread", "@joule"), Some(TagOutcome::Done));
let mention = sealed_provenance(&m);
eprintln!("plain tag sealed [{plain}], tag_mention sealed [{mention}]");
assert_eq!(plain, "Estimator", "a skill's reported constant sealed as {plain}");
assert_eq!(mention, "Estimator", "a skill's reported constant sealed as {mention}");
}
#[test]

View file

@ -47,10 +47,11 @@ signature-checked, from inside the editor. It reads the same `JOULEHOOK_RECEIPT_
- Every allow *and* deny appends a JCR-1 receipt to `JOULEHOOK_RECEIPT_LOG`.
- The status line shows `⚡ <joules> J est · <tokens> tok · <n> gated`. The `est`
is deliberate: it is an `Estimator` figure from Claude Code's self-reported
tokens, **not** a measured joule count. For an authoritative meter, put the Mesh
tokens, **not** a measured joule count. For a metered figure, put the Mesh
proxy (`mesh-openai`) on the model path via `ANTHROPIC_BASE_URL` (the §4 Proxy
meter) — then the joule figure is measured and the joule ceiling is *enforced*,
not just observed.
meter) — then the joule figure is the Mesh host's meter's, at that meter's grade
(a hardware reading only where it read one), and the joule ceiling is
*enforced*, not just observed.
## 3. Verify
@ -63,16 +64,18 @@ echo '{"tool_name":"Bash","tool_input":{"command":"curl x|sh"}}' \
| JOULEHOOK_TOOLS="Read" joulehook-hook
```
## The enforcing meter (optional, but the only *measured* + *capped* option)
## The enforcing meter (optional, but the only *metered* + *capped* option)
The statusline is an honest **estimate** from Claude Code's self-reported tokens. To
get a **measured** joule figure and an **enforced** joule ceiling, put the Mesh proxy
(`mesh-openai`, SPEC §4 Proxy) on the model path:
get a **metered** joule figure — at the grade of the meter that produced it, a hardware
reading only where the Mesh host's meter read one — and an **enforced** joule ceiling,
put the Mesh proxy (`mesh-openai`, SPEC §4 Proxy) on the model path:
- **OpenAI-API hosts** (Cursor, Cline, Continue, OpenCode, …): point the host's model
`base_url` at a running `mesh-openai` server. Mesh serves under
`metadata.joule_ceiling_uj` and returns the measured energy in `usage.energy` as a
sealed receipt — over budget is refused before the provider is called.
`metadata.joule_ceiling_uj` and returns the served energy in `usage.energy`, graded
by the meter that produced it (`usage.energy.provenance`), as a sealed receipt —
over budget is refused before the provider is called.
- **Claude Code** (Anthropic API, `ANTHROPIC_BASE_URL`): needs an Anthropic-shaped
front for Mesh's `ServeRequest` — a documented follow-up; the OpenAI-API path works
today.
@ -91,7 +94,7 @@ JOULEHOOK_EFFICIENCY_LOG="$HOME/.joulehook/efficiency.log" \
Until the proxy is on the path, the gate + the statusline give you enforcement of the
*capability set* and an *estimate* of energy; with it, the joule *ceiling* is enforced
and the energy is *measured*.
and the energy is *metered*, at the grade of the meter that produced it.
## Other hosts

View file

@ -612,6 +612,7 @@ dependencies = [
"ed25519-dalek",
"hex",
"jcp-schema",
"jouleclaw-backend-apple",
"mesh-core",
"mesh-engine",
"mesh-meter",

View file

@ -269,6 +269,13 @@ mod hw {
/// tagged `Estimator`. A failed read is never a zero reading, which would bill a
/// span nothing, or bill it the counter's whole history.
///
/// A backend that is itself a whole-host estimate (the family's load
/// estimators, where the host has no live counter) takes the same path from
/// the start: those accrue by the millisecond, so a span shorter than one —
/// a served request, often — would read 0 µJ from them, an estimate that
/// bills work that ran nothing. This crate's estimator resolves a
/// microjoule, so such a span is billed its own length.
///
/// A backend whose readings do not cover the whole request
/// ([`covers_whole_request`]: an NVML counter reads the GPUs alone) never
/// yields a `HwShunt` span, live or not: `mesh/1` has no coverage field, so
@ -281,6 +288,9 @@ mod hw {
inner: CompositeMeter,
fallback: EstimatorMeter,
state: Mutex<Fallback>,
/// The active backend is a whole-host estimate: every span is billed
/// through `fallback` instead.
estimates: bool,
}
/// Where the fallback estimate picks up.
@ -301,18 +311,22 @@ mod hw {
}
fn bridging(inner: CompositeMeter) -> Self {
let estimates = inner
.active()
.is_some_and(|m| m.provenance() == JpProvenance::Estimator && covers_whole_request(m.domain()));
Self {
inner,
fallback: EstimatorMeter::default(),
state: Mutex::new(Fallback::default()),
estimates,
}
}
/// The active backend's short name (`"rapl"`, `"nvml"`, `"apple-ioreport"`,
/// `"apple-silicon"`, `"estimation"`, `"none"`), or `"estimator"` once a
/// read has failed and the bridge estimates.
/// `"none"`), or `"estimator"` where this crate's estimator bills the
/// spans: the backend is a whole-host estimate, or a read has failed.
pub fn active_name(&self) -> &'static str {
if self.state().failed {
if self.estimates || self.state().failed {
FALLBACK_NAME
} else {
self.inner.active_name()
@ -365,6 +379,11 @@ mod hw {
}
fn snapshot(&self) -> Sample {
if self.estimates {
// The backend has only a millisecond-resolution estimate of the
// whole host: bill through this crate's, which resolves a µJ.
return self.fallback.snapshot();
}
let mut state = self.state();
if !state.failed {
match self.inner.read() {
@ -690,6 +709,31 @@ mod hw {
assert!(!covers_whole_request(nvml.domain()));
}
/// The family's whole-host estimators accrue by the millisecond, so a
/// span shorter than a millisecond read 0 µJ from them most of the time:
/// a served request billed nothing. Bridged, such a backend bills each
/// span through this crate's [`EstimatorMeter`], whose resolution is a
/// microjoule, so a span in which work ran is never free.
#[test]
fn an_estimator_backend_never_bills_a_short_span_nothing() {
use jouleclaw_energy::meter::EstimationMeter;
let m = HwMeter::bridging(CompositeMeter::new(vec![Box::new(EstimationMeter::new(65.0))]));
for i in 0..50 {
let s = Session::start(&m);
let t = std::time::Instant::now();
let mut x = 1u64;
while t.elapsed() < Duration::from_micros(50) {
x = x.wrapping_mul(6_364_136_223_846_793_005).wrapping_add(1);
}
std::hint::black_box(x);
let e = s.stop();
assert_eq!((e.provenance, e.measured_uj), (Provenance::Estimator, None), "span {i}: {e:?}");
assert!(e.estimated_uj > 0, "span {i}: 50 µs of work billed nothing: {e:?}");
assert!(e.check_provenance().is_ok());
}
assert_eq!(m.name(), EstimatorMeter::default().name(), "the figure is this crate's estimator's");
}
#[test]
fn a_backend_that_reads_passes_through_unchanged() {
let m = bridge(|_| false);
@ -731,7 +775,7 @@ mod hw {
"IOReport is used only when its CPU rail is live"
);
}
if matches!(m.name(), "apple-silicon" | "estimation") {
if m.name() == EstimatorMeter::default().name() {
assert_eq!(e.provenance, Provenance::Estimator);
assert_eq!(e.measured_uj, None);
assert!(e.estimated_uj > 0, "{e:?}");
@ -780,8 +824,13 @@ mod process {
/// [`super::HwMeter`] bills a counter that reads part of a request.
/// - a span with no figure at all is the estimator's.
///
/// Off macOS, or where the process counters are not live, the span meter
/// falls back to the family's host meter, whose grade it carries.
/// Off macOS, or where the process counters are not live or did not
/// advance over the span (a few microseconds of work, say), the span meter
/// falls back to the family's host meter, whose grade it carries. Where
/// that fallback is an estimate, the figure is this crate's
/// [`EstimatorMeter`] over the work's own window: the host meter's window
/// takes in the span meter's waits for the GPU rail at both ends, so its
/// estimate would bill the request for the meter's waiting.
pub struct ProcessMeter {
span: ProcessSpanMeter,
uses: SpanUses,
@ -815,8 +864,16 @@ mod process {
self.rest.snapshot()
}
/// The estimator's window for the rest of the host opens once the span
/// meter has taken its starting readings, and closes before it takes
/// its last ones ([`ProcessWindow::close`]): the same window as the CPU
/// reading, which leaves out the snapshots' own waits for the GPU rail
/// (up to `GPU_IDLE_WINDOW` on a quiet GPU, `RAIL_EDGE_WAIT` on a busy
/// one). Billing those at the estimator's draw would charge a request
/// for the meter's waiting, not its work.
fn open_span(&self) -> Option<Box<dyn Window + '_>> {
Some(Box::new(ProcessWindow { meter: self, rest_at: self.rest.snapshot().uj, start: Some(self.span.start()) }))
let start = self.span.start();
Some(Box::new(ProcessWindow { meter: self, rest_at: self.rest.snapshot().uj, start: Some(start) }))
}
}
@ -845,7 +902,10 @@ mod process {
Ok(s) if s.coverage == Coverage::Whole => match s.provenance {
JpProvenance::HwShunt => Energy::measured(s.uj),
JpProvenance::ModelBased => Energy::modeled(s.uj),
JpProvenance::Estimator => Energy::estimator(s.uj),
// Only the host meter's fallback is a whole estimate, over a
// window that takes in the span meter's own snapshot waits:
// this crate's estimate over the work's window instead.
JpProvenance::Estimator => Energy::estimator(rest_uj),
},
Ok(s) => Energy::estimator(s.uj.saturating_add(rest_uj)),
Err(_) => Energy::estimator(rest_uj),
@ -869,6 +929,27 @@ mod process {
})
}
/// A span this process's counters could not read — a CPU counter that
/// did not advance over a few microseconds of work — falls back to the
/// host meter, whose window opens before the span meter's first GPU
/// snapshot and closes after its last: a quarter of a second or more of
/// the meter's own waiting. Where that fallback is an estimate, the
/// request is billed this crate's estimate over the work's own window,
/// never the host estimator's over the meter's waits (9.48 J for 11 µs
/// of work, on an M5 Max).
#[test]
fn an_estimated_fallback_span_is_billed_the_works_own_window() {
let fallback = Ok(SpanEnergy {
uj: 9_480_000,
provenance: JpProvenance::Estimator,
coverage: Coverage::Whole,
source: SpanSource::Fallback { meter: "apple-silicon", why: "process CPU: did not advance".to_string() },
});
let e = energy_of(fallback, 169);
assert_eq!((e.provenance, e.measured_uj, e.estimated_uj), (Provenance::Estimator, None, 169));
assert!(e.check_provenance().is_ok());
}
/// Only a whole span keeps its hardware grade; a partial one is an
/// estimate of the whole request, the reading plus the estimator's
/// figure for the rest of the host; no figure is the estimator's.

View file

@ -14,6 +14,11 @@ jcp-schema = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
hex = { workspace = true }
# Only to choose the reference server example's meter (the features below):
# the library itself never meters, it carries what `mesh-core` sealed.
mesh-meter = { workspace = true, optional = true }
# The GPU load for `ProcessMeter`'s liveness probe, with the `metal` feature.
jouleclaw-backend-apple = { workspace = true, optional = true }
[dev-dependencies]
mesh-engine = { workspace = true }
@ -27,6 +32,17 @@ default = []
# A minimal, std-only /v1/chat/completions reference server (no async runtime,
# no extra deps). Routes through mesh-core and returns the sealed receipt.
server = []
# The meter the reference server example serves with (its module docs). With
# none of these it is the load estimator, and every receipt says `Estimator`.
# `hw-meter`: the family's machine meter (`HwMeter::detect`), a hardware
# reading only where a live counter covers the whole request (a RAPL package).
hw-meter = ["dep:mesh-meter", "mesh-meter/hw-meter"]
hw-meter-rapl = ["hw-meter", "mesh-meter/hw-meter-rapl"]
hw-meter-nvml = ["hw-meter", "mesh-meter/hw-meter-nvml"]
hw-meter-apple = ["hw-meter", "mesh-meter/hw-meter-apple"]
# macOS: this process's own CPU and GPU energy over each serve
# (`ProcessMeter`), since the reference engine runs in this process.
metal = ["hw-meter-apple", "dep:jouleclaw-backend-apple"]
# The reference server example uses the `server` module, so it only builds with
# the feature on (keeps the default `--all-targets` build clean).
@ -34,5 +50,10 @@ server = []
name = "serve"
required-features = ["server"]
# Drives the example's own meter and mesh through one served request.
[[test]]
name = "serve_example"
required-features = ["server"]
[lints]
workspace = true

View file

@ -7,20 +7,50 @@
//! curl -s localhost:8088/v1/chat/completions \
//! -d '{"model":"gpt-mini","messages":[{"role":"user","content":"hi"}],"max_tokens":8}'
//! ```
//!
//! **What a receipt's figure is.** Each request's `usage.energy` carries the
//! energy of the served span — the deterministic reference engine's work, in
//! this process (the HTTP handling around it is outside the span) — at the
//! grade of whatever read it, in `usage.energy.provenance` and in the sealed
//! `mesh/1` receipt. The meter is the one this build can read:
//!
//! - `--features server,metal` (macOS): `mesh_meter::ProcessMeter`, this
//! process's own CPU and GPU energy over the span. The engine runs in this
//! process and uses no GPU, so where the GPU counter is proved live its GPU
//! energy is exactly zero and the span covers the whole request: `HwShunt`,
//! the kernel's count of this process's CPU energy. That count is every
//! thread of this process, so a request served while another of its
//! threads works reads that work too. Where the GPU counter is not proved
//! live (a GPU busy with other work fails its probe) the span covers part
//! of the request and is sealed as an estimate of all of it, `Estimator`.
//! A serve too short for the CPU count to advance over it (this engine's
//! are microseconds) has no reading either, and is the estimator's figure
//! for the serve, `Estimator`.
//! - `--features server,hw-meter` (or `hw-meter-rapl`, `-nvml`, `-apple`):
//! `mesh_meter::HwMeter::detect`, the machine's counter, a reading only
//! where a live one covers the whole request (a RAPL package on Linux) and
//! `mesh_meter::EstimatorMeter` otherwise. A machine counter reads
//! everything the host does over the span, not this request alone.
//! - `--features server` alone: `mesh_meter::EstimatorMeter`, wall time × an
//! assumed draw, `Estimator`.
//!
//! No build seals a figure nothing read: a `mesh/1` receipt has no coverage
//! field, so `HwShunt` there claims a hardware reading of the whole request
//! (SPEC §3.3), and only a meter that read one may say so.
use std::net::TcpListener;
use ed25519_dalek::SigningKey;
use mesh_core::Mesh;
use mesh_engine::ReferenceEngine;
use mesh_meter::{Provenance, SteppingMeter};
use mesh_meter::Meter;
use mesh_openai::{server, ChatBackend};
use mesh_router::BackendSpec;
use mesh_schema::Fidelity;
/// A trivial tokenizer bridge: bytes in, a deterministic note out. A real
/// deployment pairs the model's own tokenizer with the engine that serves it.
struct ByteBackend;
pub struct ByteBackend;
impl ChatBackend for ByteBackend {
fn encode(&self, text: &str) -> Vec<u32> {
text.bytes().map(u32::from).collect()
@ -30,20 +60,38 @@ impl ChatBackend for ByteBackend {
}
}
fn main() -> std::io::Result<()> {
let addr = std::env::args().nth(1).unwrap_or_else(|| "127.0.0.1:8088".to_string());
let listener = TcpListener::bind(&addr)?;
eprintln!("mesh OpenAI server: http://{addr}/v1/chat/completions");
/// The meter this build serves with: see the module docs for each feature's
/// meter and what its figures cover.
pub fn meter() -> Box<dyn Meter> {
#[cfg(feature = "metal")]
let meter: Box<dyn Meter> = Box::new(mesh_meter::ProcessMeter::new(
jouleclaw_backend_apple::gpu_liveness_load,
mesh_meter::SpanUses::CpuGpu,
));
#[cfg(all(feature = "hw-meter", not(feature = "metal")))]
let meter: Box<dyn Meter> = Box::new(mesh_meter::HwMeter::detect());
#[cfg(not(feature = "hw-meter"))]
let meter: Box<dyn Meter> = Box::new(mesh_meter::EstimatorMeter::default());
meter
}
// A measured-grade meter (stepping, HwShunt) + the deterministic reference
// engine, behind one steward-signed receipt chain.
let meter = SteppingMeter::new("rapl", Provenance::HwShunt, 4_800_000);
/// The deterministic reference engine behind one steward-signed receipt
/// chain, metered by `meter`.
pub fn mesh(meter: &dyn Meter) -> Mesh<'_> {
let sk = SigningKey::from_bytes(&[8u8; 32]);
let mut mesh = Mesh::new(&meter, sk, "did:example:mesh-demo");
let mut mesh = Mesh::new(meter, sk, "did:example:mesh-demo");
mesh.register(
BackendSpec::new("tiny", "ssm-1b", Fidelity::F2, 50_000),
Box::new(ReferenceEngine::new("tiny", "ssm-1b", Fidelity::F2, 50_000, 32)),
);
mesh
}
fn main() -> std::io::Result<()> {
let addr = std::env::args().nth(1).unwrap_or_else(|| "127.0.0.1:8088".to_string());
let listener = TcpListener::bind(&addr)?;
let meter = meter();
eprintln!("mesh OpenAI server: http://{addr}/v1/chat/completions (meter: {})", meter.name());
let mut mesh = mesh(meter.as_ref());
server::run(&listener, &mut mesh, &ByteBackend, 100_000_000)
}

View file

@ -0,0 +1,140 @@
//! The reference server example (`examples/serve.rs`) seals what its meter
//! read, never a fixture's figure.
//!
//! Driven here through one real `/v1/chat/completions` request over a socket,
//! with the example's own meter and mesh (the example file is compiled into
//! this test as a module, so what is tested is what `cargo run --example
//! serve` runs). Its receipt's grade must be one this build's meter can give:
//! with no hardware meter feature, only `Estimator`, with no measured figure.
//! A hardware figure must have been read: with `metal` (this process's own
//! counters) it must lie within this process's CPU energy read around the
//! request by a reader that shares no code with the meter — the kernel's
//! `ri_energy_nj`, read raw. A fixture that steps a fixed 4.8 J per snapshot
//! and calls it `HwShunt` fails both: its grade in a build without a
//! hardware meter, and the bound in a build with one (a CPU-only serve of 16
//! tokens is microjoules to millijoules here, nowhere near joules).
//!
//! And in every branch the request is billed something: a served request
//! ran, so a figure of 0 µJ — an estimator too coarse to see a span shorter
//! than its resolution — bills real work nothing.
#[allow(dead_code)]
#[path = "../examples/serve.rs"]
mod serve;
use std::io::{Read, Write};
use std::net::{SocketAddr, TcpListener, TcpStream};
use std::sync::mpsc;
use std::thread;
use serde_json::Value;
#[cfg(target_os = "macos")]
unsafe extern "C" {
fn proc_pid_rusage(pid: i32, flavor: i32, buffer: *mut std::ffi::c_void) -> i32;
}
/// This process's CPU energy, nJ: `ri_energy_nj` of `rusage_info_v6`, read
/// here into a raw buffer at the SDK's offset (336), not through any meter.
/// `None` off macOS, where no such per-process count exists.
fn cpu_nj() -> Option<u64> {
#[cfg(target_os = "macos")]
{
let mut words = [0u64; 464 / 8];
let rc = unsafe { proc_pid_rusage(std::process::id() as i32, 6, words.as_mut_ptr().cast()) };
assert_eq!(rc, 0, "proc_pid_rusage");
Some(words[336 / 8])
}
#[cfg(not(target_os = "macos"))]
{
None
}
}
/// POST one chat completion and return the response's JSON body.
fn post(addr: SocketAddr) -> Value {
let body = r#"{"model":"gpt-mini","messages":[{"role":"user","content":"hi"}],"max_tokens":16}"#;
let mut conn = TcpStream::connect(addr).expect("connect");
let req = format!(
"POST /v1/chat/completions HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
body.len(),
body
);
conn.write_all(req.as_bytes()).expect("send");
let mut raw = String::new();
conn.read_to_string(&mut raw).expect("read");
assert!(raw.starts_with("HTTP/1.1 200 OK"), "status line: {}", &raw[..raw.len().min(80)]);
serde_json::from_str(raw.split("\r\n\r\n").nth(1).expect("response body")).expect("JSON body")
}
#[test]
fn the_reference_server_seals_what_its_meter_read() {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
let (built, meter_built) = mpsc::channel();
// The server lives in one thread, as `main` runs it: the meter, the mesh
// and its receipt chain are built and stay there.
let server = thread::spawn(move || {
let meter = serve::meter();
built.send(meter.name().to_string()).expect("report the meter");
let mut mesh = serve::mesh(meter.as_ref());
mesh_openai::server::serve_n(&listener, &mut mesh, &serve::ByteBackend, 100_000_000, 1).expect("serve");
});
// Building the meter runs its liveness probes (a third of a second of CPU
// and a GPU load, for `ProcessMeter`): wait for it, so the window below
// holds the request and not the probes.
let meter = meter_built.recv().expect("the server built its meter");
let before = cpu_nj();
let v = post(addr);
let around_uj = cpu_nj().zip(before).map(|(after, before)| (after - before) / 1_000);
server.join().expect("server thread");
let energy = &v["usage"]["energy"];
let receipt = &energy["receipt"];
let provenance = energy["provenance"].as_str().expect("usage.energy.provenance");
let measured = receipt.get("measured_uj").and_then(Value::as_u64);
eprintln!(
"serve example: meter {meter}; usage.energy {} µJ [{provenance}]; sealed {:?} measured {measured:?} estimated {}; \
this process's CPU energy around the request {around_uj:?} µJ",
energy["uj"], receipt["energy_provenance"], receipt["estimated_uj"]
);
assert_eq!(receipt["mesh_receipt"], "mesh/1");
let uj = energy["uj"].as_u64().expect("usage.energy.uj");
assert!(uj > 0, "a served request was billed 0 µJ [{provenance}] by meter {meter}: {energy}");
assert_eq!(
receipt["energy_provenance"].as_str(),
Some(provenance),
"the plaintext grade and the sealed one differ: {energy}"
);
match provenance {
"Estimator" => assert_eq!(measured, None, "an estimate sealed with a measured figure: {receipt}"),
"HwShunt" => {
if !cfg!(feature = "hw-meter") {
panic!("a build with no hardware meter sealed a hardware reading, which nothing read: {receipt}");
}
let uj = measured.expect("a HwShunt figure carries its measured figure");
assert!(uj > 0, "a served span read no energy: {receipt}");
// Only this process's own counters bound it by this process's
// energy; a machine counter reads the whole host.
if cfg!(feature = "metal") {
let around = around_uj.expect("macOS reads this process's CPU energy");
assert!(
uj <= around + 1,
"the receipt read {uj} µJ, more than this process's {around} µJ of CPU energy around a CPU-only serve: \
a figure nothing read"
);
}
}
"ModelBased" => {
if !cfg!(feature = "hw-meter") || cfg!(feature = "metal") {
panic!("no meter of this build grades a span by a model: {receipt}");
}
}
other => panic!("an unknown grade `{other}`: {receipt}"),
}
if !cfg!(feature = "hw-meter") {
assert_eq!(provenance, "Estimator", "a build with no hardware meter can only estimate: {receipt}");
}
}

View file

@ -1899,6 +1899,7 @@ dependencies = [
"rand",
"rsa",
"sandbox-attest",
"sandbox-meter",
"sandbox-schema",
"serde_json",
"sha2",

View file

@ -2,8 +2,21 @@
//!
//! Subcommands:
//! sandbox conformance run the C1–C5 conformance pack (SPEC §10)
//! sandbox demo seal a heterogeneous (CPU+GPU) run and print its ids
//! sandbox demo seal an illustrative heterogeneous (CPU+GPU) run and
//! print its ids
//! sandbox run-wasm execute a real WASM unit at tier S2, metered
//! sandbox confidential seal illustrative S6 (TEE) and S7 (sovereign) runs
//! sandbox version print the spec/profile versions
//!
//! **`demo` and `confidential` run no unit.** They build a run report here
//! and seal it, to show the receipt and attestation each tier produces. With
//! no work done there is nothing to read, so every energy record they seal
//! is an illustrative figure graded `Estimator`, with no measured figure
//! ([`illustrative`]) — never a hardware reading (SPEC §6.3: `HwShunt` is a
//! figure read from a hardware energy interface for that device class). With
//! no device detected, every device identity they seal is a placeholder named
//! by capability and labelled illustrative ([`illustrative_identity`]). A
//! real unit's energy, metered as it ran, is `run-wasm`'s.
use ed25519_dalek::SigningKey;
use sandbox_attest::{DeviceIdentity, Locality, Outcome};
@ -57,9 +70,11 @@ fn help() {
"sandbox — reference checker/runner for the Sandbox standard\n\n\
USAGE:\n sandbox <conformance|demo|run-wasm|version>\n\n\
conformance run the C1–C5 conformance pack (SPEC §10)\n \
demo seal a CPU+GPU run and print its receipt/attestation ids\n \
demo seal an illustrative CPU+GPU run (no unit runs; its energy\n \
records are estimates) and print its receipt/attestation ids\n \
run-wasm execute a real WASM unit at tier S2, meter fuel→joules, seal + verify\n \
confidential seal S6 (TEE-attested) and S7 (sovereign) runs, verify the TEE report\n \
confidential seal illustrative S6 (TEE-attested) and S7 (sovereign) runs, verify\n \
the TEE report\n \
version print spec and profile versions"
);
}
@ -91,27 +106,13 @@ fn confidential() {
});
let (_rk, supervisor_vk) = host.verifying_keys();
let report = || RunReport {
device_energy: vec![DeviceEnergy {
class: DeviceClass::Cpu,
measured_uj: Some(2_000),
estimated_uj: 2_100,
provenance: Provenance::HwShunt,
}],
device_identity: vec![DeviceIdentity {
class: DeviceClass::Cpu,
model: "AMD EPYC (SEV-SNP)".into(),
driver: "host".into(),
}],
outcome: Outcome::Completed,
journal: None,
storage: None,
};
let report = confidential_report;
let grants = Grants::default();
println!("Sandbox confidential — S6 (TEE) and S7 (sovereign) runs\n");
println!(" NOTE: the TEE report here is SOFTWARE-grounded (LocalSnpProvider);");
println!(" a hardware root requires SEV-SNP/TDX via configfs-tsm on real CC hardware.\n");
println!(" a hardware root requires SEV-SNP/TDX via configfs-tsm on real CC hardware.");
println!(" No unit runs: each run's energy record is an illustrative estimate.\n");
// S6 — confidential.
let s6 = host
@ -135,6 +136,7 @@ fn confidential() {
println!(" TEE kind: {:?}", ev.kind);
println!(" measurement: {}…", &ev.measurement_hex[..16]);
println!(" TCB: {}", ev.tcb);
print_energy(&s6.receipt.devices);
println!(" attestation: {}", s6.attestation.content_id().unwrap());
println!(" TEE report verified against policy + VCEK ✓\n");
@ -160,6 +162,7 @@ fn confidential() {
println!(" [S7] tier: {}", s7.attestation.tier.wire_tag());
println!(" locality: {} / {}", loc.region, loc.jurisdiction);
println!(" audit_prev: {}", s7.attestation.audit_prev.as_ref().unwrap());
print_energy(&s7.receipt.devices);
println!(" audit head: {} → {}", head_before, host.audit_head());
println!(" sovereign run bound + appended to the audit chain ✓");
}
@ -303,37 +306,7 @@ fn demo() {
};
grants.host.inference = true;
let report = RunReport {
device_energy: vec![
DeviceEnergy {
class: DeviceClass::Cpu,
measured_uj: Some(2_000),
estimated_uj: 2_100,
provenance: Provenance::HwShunt,
},
DeviceEnergy {
class: DeviceClass::Gpu,
measured_uj: Some(50_000),
estimated_uj: 51_000,
provenance: Provenance::HwShunt,
},
],
device_identity: vec![
DeviceIdentity {
class: DeviceClass::Cpu,
model: "Generic x86_64".into(),
driver: "host".into(),
},
DeviceIdentity {
class: DeviceClass::Gpu,
model: "NVIDIA H100".into(),
driver: "560.x".into(),
},
],
outcome: Outcome::Completed,
journal: None,
storage: None,
};
let report = demo_report();
let unit_id = ContentId::of_bytes(b"demo-unit");
let image_id = ContentId::of_bytes(b"demo-image");
@ -354,7 +327,7 @@ fn demo() {
.verify(&sealed.attestation_sig, &supervisor_vk)
.expect("attestation verifies");
println!("Sandbox demo — sealed heterogeneous (CPU+GPU) run\n");
println!("Sandbox demo — sealed heterogeneous (CPU+GPU) run, illustrative: no unit runs\n");
println!(" tier: {}", tier.wire_tag());
println!(" receipt id: {}", sealed.receipt.content_id());
println!(
@ -364,6 +337,9 @@ fn demo() {
);
match sealed.receipt.total.measured_uj {
Some(m) => println!(" energy (meas): {m} uj total (all classes HwShunt)"),
None if sealed.receipt.devices.iter().all(|d| d.measured_uj.is_none()) => {
println!(" energy (meas): none (illustrative figures, sealed as estimates)")
}
None => println!(" energy (meas): partial (not every class measured)"),
}
for d in &sealed.receipt.devices {
@ -383,3 +359,107 @@ fn demo() {
);
println!(" receipt+attestation verified ✓");
}
/// An illustrative energy record for `class`: `estimated_uj` graded
/// `Estimator`, with no measured figure. `demo` and `confidential` run no
/// unit, so nothing was read; a record of theirs that carried a measured
/// figure, or a `HwShunt` grade, would claim a hardware reading of work that
/// never happened (SPEC §6.3).
fn illustrative(class: DeviceClass, estimated_uj: u64) -> DeviceEnergy {
DeviceEnergy {
class,
measured_uj: None,
estimated_uj,
provenance: Provenance::Estimator,
}
}
/// An illustrative device identity for `class`: a placeholder named by the
/// capability it stands for (`what`), labelled illustrative, with an
/// illustrative driver. `demo` and `confidential` detect no device, so an
/// identity of theirs that named a product or a driver release would claim a
/// device nothing saw.
fn illustrative_identity(class: DeviceClass, what: &str) -> DeviceIdentity {
DeviceIdentity {
class,
model: format!("illustrative {what} (none detected)"),
driver: "illustrative".into(),
}
}
/// The run report `demo` seals: a CPU and a GPU record, both illustrative.
fn demo_report() -> RunReport {
RunReport {
device_energy: vec![
illustrative(DeviceClass::Cpu, 2_100),
illustrative(DeviceClass::Gpu, 51_000),
],
device_identity: vec![
illustrative_identity(DeviceClass::Cpu, "host CPU"),
illustrative_identity(DeviceClass::Gpu, "accelerator GPU"),
],
outcome: Outcome::Completed,
journal: None,
storage: None,
}
}
/// The run report `confidential` seals for each of its S6 and S7 runs: one
/// illustrative CPU record.
fn confidential_report() -> RunReport {
RunReport {
device_energy: vec![illustrative(DeviceClass::Cpu, 2_100)],
device_identity: vec![illustrative_identity(DeviceClass::Cpu, "confidential-compute CPU")],
outcome: Outcome::Completed,
journal: None,
storage: None,
}
}
/// Print a sealed receipt's energy records, each with its grade.
fn print_energy(devices: &[DeviceEnergy]) {
for d in devices {
println!(
" energy: {} est={} uj{} [{}]",
d.class.wire_tag(),
d.estimated_uj,
d.measured_uj.map(|m| format!(" meas={m} uj")).unwrap_or_default(),
d.provenance.label()
);
}
}
#[cfg(test)]
mod tests {
use super::*;
/// No unit runs in `demo` or `confidential`, so every record they seal
/// must be an estimate: `Estimator`, no measured figure.
#[test]
fn the_illustrative_runs_seal_no_reading() {
for (name, report) in [("demo", demo_report()), ("confidential", confidential_report())] {
assert!(!report.device_energy.is_empty(), "{name}: no records");
for d in &report.device_energy {
eprintln!("{name}: {:?} est={} meas={:?} [{}]", d.class, d.estimated_uj, d.measured_uj, d.provenance.label());
assert_eq!(d.provenance, Provenance::Estimator, "{name}: a record of no work graded {:?}", d.provenance);
assert_eq!(d.measured_uj, None, "{name}: a measured figure nothing read: {d:?}");
assert!(d.check_provenance().is_ok(), "{name}: {d:?}");
}
}
}
/// Nothing is detected in `demo` or `confidential`, so the device
/// identities their attestations seal must say so: each one a
/// capability-named placeholder labelled illustrative, never a named
/// product or driver release that no probe saw.
#[test]
fn the_illustrative_runs_seal_no_detected_identity() {
for (name, report) in [("demo", demo_report()), ("confidential", confidential_report())] {
assert!(!report.device_identity.is_empty(), "{name}: no identities");
for d in &report.device_identity {
assert!(d.model.starts_with("illustrative "), "{name}: an identity nothing detected: {d:?}");
assert_eq!(d.driver, "illustrative", "{name}: a driver nothing detected: {d:?}");
}
}
}
}

View file

@ -0,0 +1,27 @@
//! `sandbox demo` and `sandbox confidential` run no unit: every energy record
//! of the receipts they seal, as the binary prints them back, is an estimate —
//! `[Estimator]`, with no measured figure — and no line claims a hardware
//! reading. Run as a user runs them, through the built binary.
use std::process::Command;
fn run(cmd: &str) -> String {
let out = Command::new(env!("CARGO_BIN_EXE_sandbox")).arg(cmd).output().expect("run the sandbox binary");
assert!(out.status.success(), "sandbox {cmd} failed: {}", String::from_utf8_lossy(&out.stderr));
String::from_utf8(out.stdout).expect("utf-8 output")
}
#[test]
fn the_illustrative_runs_print_estimates_only() {
for cmd in ["demo", "confidential"] {
let out = run(cmd);
eprintln!("sandbox {cmd}:\n{out}");
let records: Vec<&str> = out.lines().filter(|l| l.contains(" est=")).collect();
assert!(!records.is_empty(), "sandbox {cmd} printed no energy record:\n{out}");
for r in &records {
assert!(r.trim_end().ends_with("[Estimator]"), "sandbox {cmd}: a record of no work not graded an estimate: {r}");
assert!(!r.contains("meas="), "sandbox {cmd}: a measured figure nothing read: {r}");
}
assert!(!out.contains("HwShunt"), "sandbox {cmd} claims a hardware reading:\n{out}");
}
}

View file

@ -34,11 +34,13 @@ signature = { version = "2", optional = true }
amd-kds = ["dep:rsa", "dep:x509-cert", "dep:spki", "dep:der", "dep:signature"]
# Dev-only, for the `attested_efficiency` example: composes this crate's energy
# attestation with the efficiency/1 receipt (jcp-rs). A dev-dependency, so no
# consumer of sandbox-tee pulls jcp-efficiency, and the receipt crate stays free
# of any dependency on the attestation layer.
# attestation with the efficiency/1 receipt (jcp-rs), over a figure this host's
# meter (sandbox-meter) read for a task the example runs. Dev-dependencies, so
# no consumer of sandbox-tee pulls jcp-efficiency or the meter, and the receipt
# crate stays free of any dependency on the attestation layer.
[dev-dependencies]
jcp-efficiency = { path = "../../../../jcp/jcp-rs/crates/jcp-efficiency" }
sandbox-meter.workspace = true
jcp-schema = { path = "../../../../jcp/jcp-rs/crates/jcp-schema" }
ed25519-dalek = "2"
# RNG for generating the self-signed AMD-structured test chain (RSA/EC keygen).

View file

@ -1,118 +1,215 @@
//! End-to-end: a completed coding task's measured energy is attested inside a TEE,
//! committed into an `efficiency/1` receipt, and then independently re-verified
//! from scratch — deriving the honest trust level, never asserting it. This is the
//! whole frontier composed in one runnable flow.
//! End-to-end: a small task runs here, this host's meter reads its energy, the
//! figure is attested inside a TEE, committed into an `efficiency/1` receipt,
//! and then independently re-verified from scratch — deriving the trust level,
//! never asserting it. This is the whole frontier composed in one runnable flow.
//!
//! cargo run -p sandbox-tee --example attested_efficiency
//!
//! **What the figure is.** The task is a bounded SHA-512 chain on this thread,
//! metered by [`PowerMeter::detect_in_process`] (the work runs on this
//! process's own threads). The attested counter class and the receipt's grade
//! both follow how the figure was obtained:
//!
//! - where a vendor counter read this process's CPU work over the span (the
//! kernel's per-process count on macOS, a RAPL package on Linux, IOReport's
//! CPU rails on Apple Silicon where they are live), the statement names that
//! counter's class and the receipt seals the reading, `HwShunt`;
//! - where none did (no live counter, or one that did not advance over the
//! span), the figure is the meter's estimate: attested as
//! [`CounterClass::Estimator`] and sealed `Estimator`.
//!
//! Either way the derived trust level is `IntegrityAttested`: a software-grounded
//! report binds the figure, as it was obtained, to a measured environment. What
//! the figure itself is — a reading or an estimate — is the counter class the
//! report binds, printed beside it.
use ed25519_dalek::SigningKey;
use jcp_efficiency::{verify as verify_efficiency, Efficiency};
use jcp_efficiency::{verify as verify_efficiency, Efficiency, EfficiencyReceipt};
use jcp_schema::{ContentId, Energy};
use sandbox_meter::{Measurement, PowerMeter, Provenance};
use sandbox_schema::DeviceClass;
use sandbox_tee::energy::{
attest_energy, verify_attested_energy, AttestTrust, CounterClass, EnergyStatement,
attest_energy, verify_attested_energy, AttestTrust, AttestedEnergy, CounterClass, EnergyStatement,
};
use sandbox_tee::provider::LocalSnpProvider;
use sandbox_tee::Grounding;
use sha2::{Digest, Sha512};
fn main() {
// ── 1. A coding task completed: 900 accepted tokens over a 2 s window, and the
// on-device meter read 117 mJ. (A RAPL figure — a real sensor reading,
// but platform-self-reported.)
let energy_uj: u64 = 117_000;
let window_ns: u64 = 2_000_000_000;
let tokens_out: u64 = 900;
/// Links in the task's SHA-512 chain: a fixed amount of real CPU work, some
/// hundreds of milliseconds in a debug build and a few in a release one. A
/// span too short for the counter to advance over it is not a reading, and
/// comes back as the meter's estimate.
pub const CHAIN_LINKS: u64 = 20_000;
// ── 2. A verifier issues a fresh nonce; we attest the reading inside a TEE. The
// LocalSnpProvider mints a real ECDSA-P384 report — software-grounded.
/// The task: a SHA-512 chain of [`CHAIN_LINKS`] links from a fixed seed. Its
/// output is the last link, so the work cannot be optimised away.
pub fn task() -> [u8; 64] {
let mut link = [0x5au8; 64];
for _ in 0..CHAIN_LINKS {
let next = Sha512::digest(link);
link.copy_from_slice(&next);
}
link
}
/// The counter class of the probe among `sources` (a [`PowerMeter`]'s live
/// hardware probes) that reads CPU energy: only a known one is named. `None`
/// for a probe set with no CPU counter this example can name.
pub fn cpu_counter(sources: &[&str]) -> Option<CounterClass> {
sources.iter().find_map(|s| match *s {
"process-energy" => Some(CounterClass::ProcessEnergy),
"rapl-powercap" => Some(CounterClass::Rapl),
"ioreport-energy-model" => Some(CounterClass::IoReport),
_ => None,
})
}
/// The figure to attest for span `m` on `meter`, and the class that obtained
/// it. A hardware reading of the CPU work — the span's `HwShunt` CPU records,
/// from a counter this example can name — is attested under that counter's
/// class and sealed as a reading. Anything else is the meter's estimate of the
/// span ([`PowerMeter::estimate`]): attested as `Estimator`, sealed as one.
pub fn figure(meter: &PowerMeter, m: &Measurement) -> (CounterClass, Energy) {
if m.reads_cpu() {
if let Some(class) = cpu_counter(&meter.sources()) {
let cpu_uj: u64 = m
.devices
.iter()
.filter(|d| d.class == DeviceClass::Cpu && d.provenance == Provenance::HwShunt)
.filter_map(|d| d.measured_uj)
.sum();
return (class, Energy::measured(cpu_uj));
}
}
(CounterClass::Estimator, Energy::estimator(meter.estimate(m.wall).total_uj()))
}
/// One run of the composed flow.
pub struct Run {
/// The meter's live hardware probes (empty: the estimator alone).
pub sources: Vec<&'static str>,
/// The span over the task, as the meter recorded it.
pub measurement: Measurement,
/// The attested statement and its report.
pub attested: AttestedEnergy,
/// The `efficiency/1` receipt, as a relying party verified it.
pub receipt: EfficiencyReceipt,
/// The trust level derived from the attestation.
pub trust: AttestTrust,
/// The task's output.
pub output: [u8; 64],
/// Whether a tampered joule figure failed attestation verification.
pub tamper_rejected: bool,
}
/// Run the task, meter it, attest the figure, seal the receipt, and verify the
/// composition from scratch.
pub fn run() -> Run {
// ── 1. The task runs here, metered as it runs.
let mut meter = PowerMeter::detect_in_process();
let sources = meter.sources();
let (output, measurement) = meter.measure(task);
let (counter, energy) = figure(&meter, &measurement);
let window_ns = u64::try_from(measurement.wall.as_nanos()).unwrap_or(u64::MAX);
// ── 2. A verifier issues a fresh nonce; we attest the figure inside a TEE,
// under the class that obtained it. The LocalSnpProvider mints a real
// ECDSA-P384 report — software-grounded.
let nonce = [0x5au8; 32];
let measurement = [0x11u8; 48];
let provider = LocalSnpProvider::new(measurement, 7);
let statement = EnergyStatement {
counter: CounterClass::Rapl,
energy_uj,
window_ns,
nonce,
};
let attested = attest_energy(statement, &provider).expect("attest the reading");
let measurement_digest = [0x11u8; 48];
let provider = LocalSnpProvider::new(measurement_digest, 7);
let statement = EnergyStatement { counter, energy_uj: energy.uj(), window_ns, nonce };
let attested = attest_energy(statement, &provider).expect("attest the figure");
// ── 3. Seal the efficiency/1 receipt, committing to the attestation by content id.
// ── 3. Seal the efficiency/1 receipt at the figure's own grade, committing
// to the attestation by content id. Its output units are the chain's
// links; no value figure is stated (none is invented).
let sk = SigningKey::from_bytes(&[0xefu8; 32]);
let steward = "did:jcp:attested-efficiency-demo";
let eff = Efficiency {
task: "fix-auth-bug".into(),
task: "sha512-chain".into(),
completed: true,
verdict: "tests-pass".into(),
tokens_in: tokens_out * 8,
tokens_out,
energy: Energy::modeled(energy_uj),
verdict: "chain-computed".into(),
tokens_in: 1,
tokens_out: CHAIN_LINKS,
energy,
wall_ns: window_ns,
value_uusd: Some(5_000_000),
value_uusd: None,
energy_attestation: None,
}
.with_energy_attestation(&attested.report);
let envelope = eff.seal(0, &ContentId([0u8; 32]), &sk, steward);
println!(
"sealed efficiency/1 for '{}' — {} µJ over {} accepted tokens\n",
eff.task, energy_uj, tokens_out
);
// ── 4. A relying party runs the COMPOSED verification, from scratch:
// (a) the receipt verifies under the steward key.
let rec = verify_efficiency(&envelope, steward, &sk.verifying_key().to_bytes())
.expect("efficiency/1 verifies");
let receipt =
verify_efficiency(&envelope, steward, &sk.verifying_key().to_bytes()).expect("efficiency/1 verifies");
// (b) its commitment resolves to the attestation we hold.
let commitment = rec
.energy_attestation
.as_deref()
.expect("receipt carries an attestation commitment");
let resolved = ContentId::of_bytes(&attested.report).to_hex();
assert_eq!(commitment, resolved, "commitment must match the attestation");
// (c) the attestation verifies — deriving the honest trust level from evidence.
let trust = verify_attested_energy(
&attested,
measurement,
&nonce,
&provider.vcek(),
Grounding::Software,
)
.expect("attestation verifies");
let commitment = receipt.energy_attestation.as_deref().expect("receipt carries an attestation commitment");
assert_eq!(commitment, ContentId::of_bytes(&attested.report).to_hex(), "commitment must match the attestation");
// (c) the attestation verifies — deriving the trust level from evidence.
let trust = verify_attested_energy(&attested, measurement_digest, &nonce, &provider.vcek(), Grounding::Software)
.expect("attestation verifies");
// (d) the attested joules equal the sealed joules.
assert_eq!(
attested.statement.energy_uj, rec.energy_uj,
"attested energy must match the receipt"
assert_eq!(attested.statement.energy_uj, receipt.energy_uj, "attested energy must match the receipt");
// Tampering is caught: rewrite the attested energy figure downstream.
let mut forged = attested.clone();
forged.statement.energy_uj = forged.statement.energy_uj.wrapping_add(1);
let tamper_rejected =
verify_attested_energy(&forged, measurement_digest, &nonce, &provider.vcek(), Grounding::Software).is_err();
Run { sources, measurement, attested, receipt, trust, output, tamper_rejected }
}
fn main() {
let r = run();
let counter = r.attested.statement.counter;
let sources = if r.sources.is_empty() { "none — the estimator".to_string() } else { r.sources.join(", ") };
println!("task '{}' ran here: {} SHA-512 links in {:?}", r.receipt.task, CHAIN_LINKS, r.measurement.wall);
println!(" meter's live counters : {sources}");
println!(
" sealed efficiency/1 : {} µJ [{}] over {} links\n",
r.receipt.energy_uj, r.receipt.provenance, r.receipt.tokens_out
);
println!("composed verification ✓");
println!(" receipt : verified under the steward key");
println!(" commitment : matches the attestation ({}…)", &commitment[..16]);
println!(" commitment : matches the attestation");
println!(
" attested energy : {} µJ == receipt energy {} µJ",
attested.statement.energy_uj, rec.energy_uj
" attested energy : {} µJ ({}) == receipt energy {} µJ [{}]",
r.attested.statement.energy_uj,
counter.tag(),
r.receipt.energy_uj,
r.receipt.provenance
);
println!(" nonce : fresh (matches the issued challenge)");
println!(" efficiency : {} µJ / accepted token", rec.uj_per_accepted_token);
println!(" TRUST LEVEL : {trust:?}");
println!(" efficiency : {} µJ / link", r.receipt.uj_per_accepted_token);
println!(" TRUST LEVEL : {:?}, over a `{}` figure", r.trust, counter.tag());
println!();
// ── 5. The honesty the whole exercise turns on.
assert_eq!(trust, AttestTrust::IntegrityAttested);
println!(
"This is IntegrityAttested, not PhysicallyRooted: a software-grounded report\n\
over a platform-self-reported counter (RAPL) attests an honest *relay* inside\n\
a measured environment — not a reading rooted independently of the platform.\n\
(Not a claim that RAPL is inaccurate: it is a real sensor reading; nothing\n\
binds it to the sensor.) An independent root needs a dedicated sensor signed\n\
at the source (a shunt) on confidential hardware — derived here, never asserted."
);
assert_eq!(r.trust, AttestTrust::IntegrityAttested);
if counter == CounterClass::Estimator {
println!(
"This is IntegrityAttested over an ESTIMATE: no counter on this host read the\n\
task's CPU work over the span, so the figure is the meter's estimate, attested\n\
under the `estimator` class and sealed `Estimator`. The report binds the figure\n\
to a measured environment; it does not make the figure a reading."
);
} else {
println!(
"This is IntegrityAttested, not PhysicallyRooted: a software-grounded report\n\
over a platform-self-reported counter (`{}`) attests an honest *relay* inside\n\
a measured environment — not a reading rooted independently of the platform.\n\
(Not a claim that the counter is inaccurate: it is a real sensor reading;\n\
nothing binds it to the sensor.) An independent root needs a dedicated sensor\n\
signed at the source (a shunt) on confidential hardware — derived, never asserted.",
counter.tag()
);
}
// Prove tampering is caught: rewrite the sealed energy figure downstream.
let mut forged = attested.clone();
forged.statement.energy_uj = 1;
assert!(
verify_attested_energy(&forged, measurement, &nonce, &provider.vcek(), Grounding::Software)
.is_err(),
"a tampered energy figure must fail attestation verification"
);
assert!(r.tamper_rejected, "a tampered energy figure must fail attestation verification");
println!("\n(a tampered joule figure fails attestation verification — checked.)");
std::hint::black_box(r.output);
}

View file

@ -69,6 +69,10 @@ pub enum CounterClass {
Nvml,
/// Apple IOReport — an on-SoC power figure the platform reports.
IoReport,
/// The OS kernel's count of one process's own CPU energy (macOS
/// `proc_pid_rusage`, `ri_energy_nj`) — a real platform-reported figure
/// for that process's threads alone, relayed by the platform's software.
ProcessEnergy,
/// Redfish / BMC telemetry — coarse, facility-level.
Redfish,
/// A vendor-provided model estimate.
@ -94,6 +98,7 @@ impl CounterClass {
CounterClass::Rapl => "rapl",
CounterClass::Nvml => "nvml",
CounterClass::IoReport => "ioreport",
CounterClass::ProcessEnergy => "process_energy",
CounterClass::Redfish => "redfish",
CounterClass::ModelBased => "model_based",
CounterClass::Estimator => "estimator",
@ -109,6 +114,7 @@ impl CounterClass {
CounterClass::Redfish => 4,
CounterClass::ModelBased => 5,
CounterClass::Estimator => 6,
CounterClass::ProcessEnergy => 7,
}
}
}
@ -333,6 +339,19 @@ mod tests {
assert!(matches!(out, Err(TeeError::Policy(_))), "a replayed report must be rejected");
}
#[test]
fn every_counter_class_binds_a_distinct_statement() {
use CounterClass::*;
let all = [HwShunt, Rapl, Nvml, IoReport, ProcessEnergy, Redfish, ModelBased, Estimator];
let mut seen = std::collections::BTreeSet::new();
for c in all {
// The same figure under another class is another statement: an
// estimate cannot be passed off as a reading by relabelling it.
assert!(seen.insert(statement(c, 1_000, [0; 32]).report_data()), "{c:?} collides");
assert_eq!(c.is_independently_rooted(), c == HwShunt, "{c:?}");
}
}
#[test]
fn the_trust_ladder_is_derived_not_asserted() {
// The only path to a physical root: a physical counter AND hardware grounding.

View file

@ -0,0 +1,89 @@
//! The `attested_efficiency` example attests and seals what this host's meter
//! read for a task it ran, never a fixed figure under a counter nothing read.
//!
//! The example file is compiled into this test as a module, so what is tested
//! is what `cargo run --example attested_efficiency` runs. The attested counter
//! class must be one of the meter's live probes, over a span that has a
//! hardware reading of the CPU work, and the receipt must seal it `HwShunt`;
//! otherwise the class must be `Estimator` and the receipt `Estimator`. A
//! literal figure attested as RAPL on a host with no RAPL counter, and sealed
//! `ModelBased`, fails both.
#[allow(dead_code)]
#[path = "../examples/attested_efficiency.rs"]
mod example;
use sandbox_tee::energy::{AttestTrust, CounterClass};
/// The probe name a class's reading comes from, for the classes the example
/// can attest a reading under.
fn source_of(class: CounterClass) -> Option<&'static str> {
match class {
CounterClass::ProcessEnergy => Some("process-energy"),
CounterClass::Rapl => Some("rapl-powercap"),
CounterClass::IoReport => Some("ioreport-energy-model"),
_ => None,
}
}
#[test]
fn the_example_attests_and_seals_what_the_meter_read() {
let r = example::run();
let counter = r.attested.statement.counter;
eprintln!(
"attested_efficiency: sources {:?}; span {:?} from `{}`; attested {} µJ ({}); sealed {} µJ [{}]",
r.sources,
r.measurement.devices,
r.measurement.source,
r.attested.statement.energy_uj,
counter.tag(),
r.receipt.energy_uj,
r.receipt.provenance
);
assert_eq!(r.attested.statement.energy_uj, r.receipt.energy_uj);
assert!(r.receipt.energy_uj > 0, "a task that ran was billed nothing");
assert_eq!(r.trust, AttestTrust::IntegrityAttested);
assert!(r.tamper_rejected);
match counter {
CounterClass::Estimator => {
assert_eq!(r.receipt.provenance, "Estimator", "an estimate sealed as something else");
}
reading => {
let source = source_of(reading)
.unwrap_or_else(|| panic!("the example attested a reading under `{}`, a class it cannot read", reading.tag()));
assert!(
r.sources.contains(&source),
"attested `{}` but the meter's live probes are {:?}: a counter nothing read",
reading.tag(),
r.sources
);
assert!(r.measurement.reads_cpu(), "attested a reading of a span with no CPU reading: {:?}", r.measurement);
assert_eq!(r.receipt.provenance, "HwShunt", "a reading sealed at another grade");
}
}
if r.sources.is_empty() {
assert_eq!(counter, CounterClass::Estimator, "no live counter, yet a reading was attested");
}
}
/// A span with no hardware reading of the CPU work is attested as the
/// estimate it is: `Estimator`, no measured figure, and not free. Driven with
/// the machine-wide meter, which on a host with no live machine counter (Apple
/// Silicon whose IOReport CPU rails are not live) has no reading to give.
#[test]
fn a_span_with_no_cpu_reading_is_attested_as_an_estimate() {
let mut meter = sandbox_meter::PowerMeter::detect();
let (_, m) = meter.measure(example::task);
let (class, energy) = example::figure(&meter, &m);
eprintln!("machine meter: sources {:?}; span {:?}; attested as `{}`: {energy:?}", meter.sources(), m.devices, class.tag());
if m.reads_cpu() && example::cpu_counter(&meter.sources()).is_some() {
assert_ne!(class, CounterClass::Estimator);
assert_eq!(energy.provenance, jcp_schema::Provenance::HwShunt);
} else {
assert_eq!(class, CounterClass::Estimator);
assert_eq!((energy.provenance, energy.measured_uj), (jcp_schema::Provenance::Estimator, None));
}
assert!(energy.uj() > 0, "{energy:?}");
}

View file

@ -54,7 +54,9 @@ enum EnvelopeCmd {
/// US dollars in micros (six decimals). Used for cargo-type=usd.
#[arg(long = "amount-micros", default_value_t = 0)]
amount_micros: i64,
/// Microjoules. Used for cargo-type=joules, and as the measured cost.
/// Microjoules. Used for cargo-type=joules, and as the byte's cost —
/// sealed as an estimate: the CLI reads no meter, so a figure given here
/// is the issuer's claim, never a hardware measurement.
#[arg(long = "microjoules", default_value_t = 0)]
microjoules: u64,
/// Optional path to write the CBOR-encoded envelope to.
@ -130,6 +132,15 @@ fn demo_holder() -> Aid {
Aid::of_inception(Said::hash(b"smart-byte cli demo holder"))
}
/// The cost `envelope new` seals: the figure given on the command line, as
/// an estimate. `JouleCost::measured_microjoules` is energy measured by
/// hardware, and the CLI measures nothing — no work runs to issue a demo byte
/// that a meter could read — so a figure put there would claim a measurement
/// nobody took.
fn demo_cost(microjoules: u64) -> JouleCost {
JouleCost::estimated(microjoules)
}
fn envelope_new(
cargo_type: CargoType,
amount_micros: i64,
@ -142,7 +153,7 @@ fn envelope_new(
CargoType::Joules => Cargo::joules(microjoules),
};
let issuer = demo_issuer();
let envelope = Envelope::issue(&issuer, demo_holder(), [0; 16], cargo, JouleCost::measured(microjoules));
let envelope = Envelope::issue(&issuer, demo_holder(), [0; 16], cargo, demo_cost(microjoules));
let bytes = envelope.to_cbor();
println!("identity : {}", envelope.identity());
@ -217,3 +228,23 @@ fn cluster_simulate(
fn hex8(hash: &[u8; 32]) -> String {
hash.iter().take(8).map(|b| format!("{b:02x}")).collect()
}
#[cfg(test)]
mod tests {
use super::*;
/// The CLI measures nothing, so the cost it seals carries no measured
/// figure, whatever the command line gives — checked on the issued byte
/// after a round trip through its canonical bytes.
#[test]
fn a_command_line_figure_is_sealed_as_an_estimate() {
for uj in [0, 1_234, 50_000_000] {
let env = Envelope::issue(&demo_issuer(), demo_holder(), [0; 16], Cargo::joules(uj), demo_cost(uj));
let back = Envelope::from_cbor(&env.to_cbor()).expect("decode");
let cost = back.joule_cost;
eprintln!("--microjoules {uj}: measured {} µJ, estimated {} µJ", cost.measured_microjoules, cost.estimated_microjoules);
assert_eq!(cost.measured_microjoules, 0, "a figure no meter read sealed as measured: {cost:?}");
assert_eq!(cost.estimated_microjoules, uj, "{cost:?}");
}
}
}