use agent_scroll::{seal_chain, verify, SignOpts};
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
use serde_json::{json, Value};
fn main() {
let sk = SigningKey::generate(&mut OsRng);
let sign = SignOpts {
privkey: sk.to_bytes(),
pubkey: sk.verifying_key().to_bytes(),
};
let mk = |turn: u64, role: &str, content: &str, ts_offset: u64| {
json!({
"version": "scroll/0.1",
"turn": turn,
"role": role,
"model": { "vendor": "anthropic", "id": "claude-opus-4-7" },
"params": { "temperature": 0, "top_p": 1 },
"messages": [{ "role": role, "content": content }],
"timestamp_ns": 1_700_000_000_000_000_000u64 + ts_offset,
})
};
let turns: Vec<Value> = vec![
mk(0, "user", "What is the capital of France?", 0),
mk(1, "assistant", "Paris.", 1),
mk(2, "user", "Thanks!", 2),
];
let chain = seal_chain(&turns, Some(&sign)).expect("seal_chain");
println!("sealed {} turns, all hashes set", chain.len());
let clean = verify(&chain, Some(&sign.pubkey));
println!("verify clean: ok={}", clean.ok);
let mut tampered = chain.clone();
let h = tampered[1]["hash"].as_str().unwrap().to_string();
let last = h.chars().last().unwrap();
let new_last = if last == '0' { 'f' } else { '0' };
let mut new_h: String = h[..h.len() - 1].to_string();
new_h.push(new_last);
tampered[1]["hash"] = json!(new_h);
let bad = verify(&tampered, Some(&sign.pubkey));
let reason = bad.failures.first().map(|f| f.reason).unwrap_or("none");
println!("verify tampered: ok={} reason={}", bad.ok, reason);
}