Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (push) Successful in 4s
standards workspaces build + test / jouleclaw-rs (push) Successful in 1m50s
standards workspaces build + test / eoc-rs (push) Successful in 1m54s
standards workspaces build + test / arl-rs (push) Successful in 2m10s
standards workspaces build + test / aac-rs (push) Successful in 40s
standards workspaces build + test / joule-code-rs (push) Successful in 38s
standards workspaces build + test / jcp-rs (push) Successful in 1m18s
standards workspaces build + test / joulecontract-rs (push) Successful in 30s
standards workspaces build + test / map-rs (push) Successful in 30s
standards workspaces build + test / proof-rs (push) Successful in 1m11s
standards workspaces build + test / mesh-rs (push) Successful in 26s
standards workspaces build + test / joule-ui-rs (push) Successful in 2m32s
standards workspaces build + test / openpay (push) Successful in 1m21s
standards workspaces build + test / sandbox-rs (push) Successful in 2m12s
WAI conformance / cargo-class corpora · linux-arm64 (push) Successful in 51s
WAI conformance / cross-arch byte-equality · linux-arm64 (push) Successful in 18s
standards workspaces build + test / jouledesk-rs (push) Successful in 2m39s
standards workspaces build + test / smart-byte-rs (push) Successful in 2m30s
WAI conformance / cargo-class corpora · linux (push) Successful in 1m11s
WAI conformance / cross-arch byte-equality · linux (push) Successful in 15s
standards workspaces build + test / joulehook-rs (push) Successful in 3m48s
WAI conformance / C2PA manifest emission · signed, read back, validated (push) Successful in 40s
standards workspaces build + test / sense-rs (push) Successful in 2m22s
standards workspaces build + test / macOS energy backend (jcp-energy) (push) Successful in 2m32s
WAI conformance / cargo-class corpora · macos (push) Successful in 55s
WAI conformance / cross-arch byte-equality · macos (push) Successful in 14s
WAI conformance / cargo-class corpora · windows (push) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (push) Has been cancelled
Departures from OER/2 draft 0.1, each in extensions/oer-receipts.md §9: - decisions are named oer.decision.*, not wai.settle.* (WAI's namespace is for payload formats) - the stage list behind bundle.provenance_root is serialised exactly as the body is, pinned by a non-ASCII fixture - the number profile is normative: I-JSON integers, decimal strings in JSON's number grammar (<=34 digits), anything else malformed - a document outside the document profile is refused whole: a number whose nearest binary64 is infinite, NaN/Infinity, an unpaired surrogate, a repeated member name, nesting past 64 - every composition check is exact (num-bigint / exact decimal context), ln 2 pinned as a decimal, every tolerance scaled by the figure's magnitude - the order of the reasons reported alone, and every member judged on its value, are stated, so each mistyped member has one named reason - published Ed25519 keys are decoded strictly: canonical encoding, not small order - abstention is its own outcome (abstain, no answer, no record), held by a new reason, abstention_settled; escalate is a verdict returned from upstream Four rounds of adversarial review with differential fuzzing drove this; the last fuzz found one remaining divergence (repeated member names), now refused by both. The edge corpus grows to 99 hand-declared vectors plus unreadable/ (11 documents every verifier must refuse); each rule was falsified in both verifiers. serde_json gains float_roundtrip under the oer feature so Rust rounds as Python does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
98 lines
8.7 KiB
Python
98 lines
8.7 KiB
Python
import json, hashlib, copy, sys, os
|
|
|
|
# Resolve everything against this script's own directory, so the README's
|
|
# instructions work wherever the pack is checked out. Previously hardcoded to
|
|
# /mnt/user-data/outputs/oer2, the sandbox it was first generated in.
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0, HERE)
|
|
import oer2_verify as V
|
|
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
from cryptography.hazmat.primitives import serialization
|
|
from decimal import Decimal
|
|
|
|
data = json.load(open(os.path.join(HERE, "sw_export.json")))
|
|
seed = hashlib.sha256(b"settlement world node ledger vector key").digest()
|
|
priv = ed25519.Ed25519PrivateKey.from_private_bytes(seed)
|
|
pub = priv.public_key().public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw).hex()
|
|
SIGNER = "ed25519:corridor-ledger-01"
|
|
def D(x): return "%.6e" % float(x)
|
|
RULES = "sha256:" + hashlib.sha256(b"rules@1").hexdigest()
|
|
exported = data["log"]; records = data["records"]
|
|
prior_sum = 0.0
|
|
|
|
def seal(r, prev):
|
|
r = copy.deepcopy(r); r.pop("receipt_id", None); r["chain"] = {"prev_hash": prev, "receipt_hash": "", "signer": SIGNER, "signature": ""}
|
|
body = V.canonical_bytes(r)
|
|
r["receipt_id"] = V.h("sha-256", body)
|
|
r["chain"]["receipt_hash"] = V.h("sha-256", prev.encode() + body)
|
|
r["chain"]["signature"] = priv.sign(r["chain"]["receipt_hash"].encode()).hex()
|
|
return r
|
|
|
|
def convert(b):
|
|
served = b["settlement"]["served_from_record"]
|
|
s = b["settlement"]; rec = records.get(s["record_id"]) if s.get("record_id") else None
|
|
r = {"oer": "2.0", "kind": "decision",
|
|
"capability": "oer.decision." + b["workload"]["name"], "intent": "replicate" if served else "create",
|
|
"subject": {"inputs": ["sha256:" + s["question_key"], RULES], "output": b["workload"]["output"] if b["workload"]["output"] is not None else ""},
|
|
"work": {"status": b["status"], "outcome": b["outcome"], "latency_s": D(b["workload"]["latency_s"])},
|
|
"energy": {"joules_total": D(b["energy"]["joules_total"]), "boundary": b["energy"]["boundary"],
|
|
"breakdown": {k: D(v) for k, v in b["energy"]["breakdown"].items()}, "method": b["energy"]["method"], "temperature_k": D(data["fl_temp"])},
|
|
"provenance": {"how": b["provenance"]["how"], "device": b["provenance"]["device"], "weakest_input": {"how": b["provenance"]["weakest_input"]["how"], "input": str(b["provenance"]["weakest_input"]["input"])}},
|
|
"settlement": {"question_key": "sha256:" + s["question_key"], "served_from_record": served, "record_id": s["record_id"] or "", "record_hash": ("sha256:" + s["record_hash"]) if s["record_hash"] else "", "reuse_count": s["reuse_count"], "derivation_j": D(s["derivation_j"]), "valid_until": int(rec["valid_until"]) if rec else 0},
|
|
"floor": {"bits_committed": b["floor"]["bits_destroyed"], "bits_delivered": D(b["floor"]["bits_resolved"]), "floor_j": D(b["floor"]["floor_j"]), "decades_above_floor": D(b["floor"]["decades_above_floor"] or 0)},
|
|
"hash_alg": "sha-256", "sig_alg": "ed25519"}
|
|
# total must equal the breakdown exactly in decimal strings
|
|
r["energy"]["joules_total"] = str(sum(Decimal(v) for v in r["energy"]["breakdown"].values()))
|
|
return r
|
|
|
|
chain, prev = [], "sha256:" + "0" * 64
|
|
for b in exported:
|
|
r = seal(convert(b["body"]), prev); chain.append(r); prev = r["chain"]["receipt_hash"]
|
|
exported_sum = sum(Decimal(r["energy"]["joules_total"]) for r in chain)
|
|
carried = Decimal(repr(data["receiptJ"])) - sum(Decimal(repr(b["body"]["energy"]["joules_total"])) for b in exported)
|
|
ledger = {"meter_joules": D(data["meter"]), "unallocated_joules": D(data["pending"]), "carried_forward_joules": str(Decimal(D(data["meter"])) - exported_sum - Decimal(D(data["pending"])))}
|
|
records_v = {rid: rec for rid, rec in records.items()}
|
|
|
|
stages = [{"kind": r["kind"], "receipt_hash": r["chain"]["receipt_hash"], "joules": r["energy"]["joules_total"]} for r in chain]
|
|
root = V.h("sha-256", V.stage_list_bytes(stages))
|
|
completed = sum(1 for r in chain if r["work"]["status"] == 1); wasted = len(chain) - completed
|
|
wasted_j = sum(Decimal(r["energy"]["joules_total"]) for r in chain if r["work"]["status"] != 1)
|
|
bundle = {"oer": "2.0", "kind": "bundle", "capability": "oer.bundle.hour", "intent": "replicate",
|
|
"subject": {"inputs": [r["chain"]["receipt_hash"] for r in chain], "output": root},
|
|
"work": {"status": 1, "outcome": "ledger", "latency_s": "0.000000e+00"},
|
|
"energy": {"joules_total": str(exported_sum), "boundary": "sum of the hour's decision receipts, refusals included", "breakdown": {"compute_j": str(exported_sum), "movement_j": "0.000000e+00", "idle_alloc_j": "0.000000e+00", "shared_alloc_j": "0.000000e+00", "upstream_j": "0.000000e+00"}, "method": "model_estimated", "temperature_k": D(data["fl_temp"])},
|
|
"provenance": {"how": "projected", "device": "simulation", "weakest_input": {"how": "projected", "input": "wire_w"}},
|
|
"efficiency": {"completed_units": completed, "wasted_units": wasted, "joules_per_completed": D(exported_sum / completed), "waste_fraction": D(wasted_j / exported_sum), "value_per_joule": None},
|
|
"bundle": {"stages": stages, "provenance_root": root},
|
|
"floor": {"bits_committed": data["fl_bits"] * len(chain), "bits_delivered": D(1.585 * len(chain)), "floor_j": D(data["fl_bits"] * len(chain) * 1.380649e-23 * data["fl_temp"] * 0.6931471805599453), "decades_above_floor": D(0)},
|
|
"hash_alg": "sha-256", "sig_alg": "ed25519"}
|
|
bundle = seal(bundle, prev)
|
|
anchor = seal({"oer": "2.0", "kind": "anchor", "capability": "oer.anchor.iridium_imt", "intent": "replicate",
|
|
"subject": {"inputs": [bundle["chain"]["receipt_hash"]], "output": root},
|
|
"work": {"status": 1, "outcome": "delivered", "latency_s": "1.000000e+01"},
|
|
"energy": {"joules_total": "2.560000e-01", "boundary": "gateway satellite modem, one message", "breakdown": {"compute_j": "0.000000e+00", "movement_j": "2.560000e-01", "idle_alloc_j": "0.000000e+00", "shared_alloc_j": "0.000000e+00", "upstream_j": "0.000000e+00"}, "method": "model_estimated", "temperature_k": D(data["fl_temp"])},
|
|
"provenance": {"how": "measured", "device": "simulation", "weakest_input": {"how": "projected", "input": "iri_wake_s"}},
|
|
"floor": {"bits_committed": 512, "bits_delivered": "2.560000e+02", "floor_j": D(512 * 1.380649e-23 * data["fl_temp"] * 0.6931471805599453), "decades_above_floor": "1.500000e+01"},
|
|
"hash_alg": "sha-256", "sig_alg": "ed25519"}, bundle["chain"]["receipt_hash"])
|
|
|
|
vectors = []
|
|
vectors.append({"name": "v01 valid chain, records and ledger", "receipts": chain, "records": records_v, "ledger": ledger, "expected": []})
|
|
t = copy.deepcopy(records_v); cited = next(r["settlement"]["record_id"] for r in chain if r["settlement"]["served_from_record"]); t[cited]["answer"] += "_altered"
|
|
vectors.append({"name": "v02 a served record altered after the fact", "receipts": chain, "records": t, "expected": ["record_mismatch"]})
|
|
vectors.append({"name": "v03 valid bundle and anchor", "receipts": chain + [bundle, anchor], "expected": []})
|
|
tb = copy.deepcopy(bundle); tb["bundle"]["stages"] = tb["bundle"]["stages"][::-1]; tb = seal(tb, prev)
|
|
vectors.append({"name": "v04 bundle stages reordered", "receipts": chain + [tb], "expected": ["bundle_root_mismatch"]})
|
|
tm = copy.deepcopy(chain); tm[5]["oer"] = "3.0"
|
|
vectors.append({"name": "v05 unknown major version", "receipts": tm, "expected": ["unknown_major"]})
|
|
ts = copy.deepcopy(chain); x = ts[7]; x["energy"]["breakdown"]["compute_j"] = D(Decimal(x["energy"]["breakdown"]["compute_j"]) * 2); ts[7] = seal(x, ts[6]["chain"]["receipt_hash"]); ts[8] = seal(ts[8], ts[7]["chain"]["receipt_hash"])
|
|
vectors.append({"name": "v06 breakdown edited without the total, re-signed", "receipts": ts[:9], "expected": ["sum_mismatch"]})
|
|
tg = copy.deepcopy(chain); sig = bytearray(bytes.fromhex(tg[3]["chain"]["signature"])); sig[0] ^= 1; tg[3]["chain"]["signature"] = sig.hex()
|
|
vectors.append({"name": "v07 signature altered", "receipts": tg, "expected": ["signature_invalid"]})
|
|
tl = copy.deepcopy(ledger); tl["meter_joules"] = D(Decimal(tl["meter_joules"]) * Decimal("0.9"))
|
|
vectors.append({"name": "v08 meter figure does not match the receipts", "receipts": chain, "ledger": tl, "expected": ["ledger_mismatch"]})
|
|
tc = copy.deepcopy(chain); tc[10]["chain"]["prev_hash"] = "sha256:" + "f" * 64
|
|
vectors.append({"name": "v09 chain link broken", "receipts": tc, "expected": ["chain_break", "receipt_hash_mismatch"]})
|
|
|
|
out = {"oer": "2.0", "draft": "0.1", "source": "Settlement World v0.11, gatewayless corridor, one simulated day, last 150 receipts", "keys": {SIGNER: pub}, "vectors": vectors}
|
|
json.dump(out, open(os.path.join(HERE, "vectors.json"), "w"), indent=0)
|
|
print("receipts", len(chain), "bundle stages", len(stages), "completed", completed, "wasted", wasted, "hour joules", float(exported_sum))
|