Finding 4: full-trace evidence — reconstructed and re-derived, not summarized

Removes the deferral. Each sampled execution's FULL trace (every graph edge,
count, weight) and delta are persisted as evidence; the independent attestor
reconstructs them, recomputes the canonical trace hash and delta hash, re-derives
the replay-record leaf, and confirms it is among the retained Merkle leaves the
root is built from. The behavior-fingerprint hash is re-derived from features
(not trusted), and f64 divergence is stored bit-exact for an identical hash.

- trace_model: ExecutionTrace::serialize/deserialize (round-trips canonical_hash;
  total on garbage). Test: full_trace_serialize_roundtrips_canonical_hash.
- world_model: WorldDelta::serialize/deserialize (round-trips hash).
- ci_reports: retains TRACE_EVIDENCE_SAMPLE full traces; writes
  evidence/traces.tsv.
- attestation: depends on trace_model/world_model; reconstructs each trace,
  recomputes the leaf, requires it to match the claimed leaf AND be a retained
  leaf. Negative control: tampered_trace_breaks_attestation (corrupting the full
  trace, leaving the claimed leaf, fails attestation).
- merge-gates: requires evidence/traces.tsv; the separate attest step verifies it.

End-to-end (fast profile): 256/256 full traces reconstructed and re-derived to
retained leaves; recomputed root matches the claim over 6600 leaves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 21:22:55 -07:00
co-authored by Claude Opus 4.8
parent 1e50c80627
commit bea076df43
8 changed files with 481 additions and 19 deletions
+22
View File
@@ -59,6 +59,28 @@ fn write_evidence(dir: &Path, r: &CiResults) {
r.provenance.engines_agree,
);
fs::write(ev.join("claims.tsv"), claims).expect("write claims");
// Full-trace evidence (finding 4): each line is
// ws ps cs prs future leaf <TAB> <full trace> <TAB> <full delta>
// The attestor reconstructs the trace + delta, recomputes the canonical
// trace hash and the replay-record leaf, and checks the leaf is among the
// retained leaves. This is the full trace, not a summary.
let mut traces = String::from("# full-trace evidence: header<TAB>trace<TAB>delta\n");
for ev_rec in &r.trace_evidence {
let rr = &ev_rec.replay;
traces.push_str(&format!(
"{:016x} {:016x} {:016x} {:016x} {:016x} {:016x}\t{}\t{}\n",
rr.world_seed,
rr.program_seed,
rr.contract_seed,
rr.perturbation_seed,
rr.future_hash.0,
rr.hash().0,
ev_rec.trace.serialize(),
ev_rec.delta.serialize(),
));
}
fs::write(ev.join("traces.tsv"), traces).expect("write traces");
}
fn build_reports(dir: &Path, r: &CiResults) {