wickra_verify_core/verdict.rs
1//! [`Verdict`] — the reproducible answer: does the claimed report hold up?
2
3use serde::{Deserialize, Serialize};
4
5/// A single field where the claimed report disagrees with the recomputed one,
6/// beyond tolerance. `field` is a dotted/indexed path (`metrics.sharpe`,
7/// `trades[3].pnl`, `trades[len]`). `delta` is `actual - claimed`, rounded to the
8/// 1e-8 display grid — human-facing only, never part of a hash.
9#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
10pub struct Mismatch {
11 /// Dotted/indexed path to the disagreeing field.
12 pub field: String,
13 /// The value the claim asserted.
14 pub claimed: f64,
15 /// The value recomputation produced.
16 pub actual: f64,
17 /// `actual - claimed`, rounded for display.
18 pub delta: f64,
19}
20
21/// The result of verifying a claim. Deterministic and self-contained: the same
22/// `(claim, data)` yields a byte-identical verdict in every language, and the
23/// three hashes let a verdict be cross-checked against a `wickra-proof` proof of
24/// the same inputs.
25#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
26pub struct Verdict {
27 /// `true` iff every numeric field of the claimed report agrees with the
28 /// recomputed one within tolerance (`mismatches` is empty).
29 pub matches: bool,
30 /// Every field that disagreed, stably sorted by `field`.
31 pub mismatches: Vec<Mismatch>,
32 /// The exact backtest engine version that recomputed the report.
33 pub engine_version: String,
34 /// blake3 hex of the canonicalized claimed report.
35 pub claimed_report_hash: String,
36 /// blake3 hex of the canonicalized recomputed report.
37 pub actual_report_hash: String,
38 /// blake3 hex of `canonicalize({strategy, dataset_ref, candles,
39 /// engine_version})` — the same inputs hash `wickra-proof` produces.
40 pub inputs_hash: String,
41}