openvm_verify_stark_circuit/
extension.rs1use std::borrow::Borrow;
2
3use eyre::Result;
4use itertools::Itertools;
5use openvm_circuit::{
6 arch::{
7 deferral::{DeferralState, OutputRaw},
8 hasher::poseidon2::vm_poseidon2_hasher,
9 },
10 system::program::trace::compute_exe_commit,
11};
12use openvm_continuations::{
13 circuit::utils::vk_commit_components, utils::poseidon2_input_to_digests,
14};
15use openvm_deferral_circuit::{
16 generate_deferral_results, poseidon2::deferral_poseidon2_chip, RawDeferralResult,
17};
18use openvm_recursion_circuit::utils::poseidon2_hash_slice;
19use openvm_stark_backend::{
20 codec::Decode, p3_field::PrimeField32, verifier::verify, TranscriptHistory,
21};
22use openvm_stark_sdk::config::baby_bear_poseidon2::{
23 default_duplex_sponge_recorder, poseidon2_compress_with_capacity,
24 BabyBearPoseidon2Config as SC, Digest, F,
25};
26use openvm_verify_stark_host::{
27 pvs::{VerifierBasePvs, VmPvs, VERIFIER_PVS_AIR_ID, VM_PVS_AIR_ID},
28 verify_vm_stark_proof_pvs,
29 vk::VmStarkVerifyingKey,
30 VmStarkProof,
31};
32
33pub fn verify_stark_deferral_fn(encoded_proof: &[u8]) -> OutputRaw {
37 let proof = VmStarkProof::decode_from_bytes(encoded_proof).unwrap();
38 output_raw_from_proof(&proof)
39}
40
41fn output_raw_from_proof(proof: &VmStarkProof) -> OutputRaw {
42 let (base_pvs_slice, _) = proof.inner.public_values[VERIFIER_PVS_AIR_ID]
44 .as_slice()
45 .split_at(VerifierBasePvs::<u8>::width());
46 let verifier_pvs: &VerifierBasePvs<F> = base_pvs_slice.borrow();
47 let vm_pvs: &VmPvs<F> = proof.inner.public_values[VM_PVS_AIR_ID].as_slice().borrow();
48
49 let app_exe_commit = compute_exe_commit(
50 &vm_poseidon2_hasher(),
51 &vm_pvs.program_commit,
52 &vm_pvs.initial_root,
53 vm_pvs.initial_pc,
54 );
55 let app_vm_commit =
56 poseidon2_hash_slice(&vk_commit_components(verifier_pvs).into_flattened()).0;
57
58 let output_f = app_exe_commit
59 .into_iter()
60 .chain(app_vm_commit)
61 .chain(proof.user_pvs_proof.public_values.iter().copied())
62 .collect_vec();
63 f_slice_to_bytes(&output_f)
64}
65
66fn f_slice_to_bytes(slice: &[F]) -> Vec<u8> {
67 let mut output = Vec::with_capacity(size_of_val(slice));
68 for value in slice {
69 let bytes = value.as_canonical_u32().to_le_bytes();
70 output.extend_from_slice(&bytes);
71 }
72 output
73}
74
75pub fn get_raw_deferral_results(
79 vk: &VmStarkVerifyingKey,
80 proofs: &[VmStarkProof],
81 cached_commit: Digest,
82) -> Result<Vec<RawDeferralResult>> {
83 let config = SC::default_from_params(vk.mvk.inner.params.clone());
84
85 proofs
86 .iter()
87 .map(|proof| {
88 verify_vm_stark_proof_pvs(vk, proof)?;
89
90 let mut ts = default_duplex_sponge_recorder();
91 verify(&config, &vk.mvk, &proof.inner, &mut ts)?;
92
93 let final_ts_state = *ts.into_log().perm_results().last().unwrap();
94 let (left_ts, right_ts) = poseidon2_input_to_digests(final_ts_state);
95 let ts_commit = poseidon2_compress_with_capacity(left_ts, right_ts).0;
96 let input_commit =
97 poseidon2_hash_slice(&vec![ts_commit, cached_commit].into_flattened()).0;
98
99 Ok(RawDeferralResult {
100 input: f_slice_to_bytes(&input_commit),
101 output_raw: output_raw_from_proof(proof),
102 })
103 })
104 .collect()
105}
106
107pub fn get_deferral_state(
108 vk: &VmStarkVerifyingKey,
109 proofs: &[VmStarkProof],
110 cached_commit: Digest,
111 deferral_idx: u32,
112) -> Result<DeferralState> {
113 let raw_results = get_raw_deferral_results(vk, proofs, cached_commit)?;
114 let results =
115 generate_deferral_results(raw_results, deferral_idx, &deferral_poseidon2_chip::<F>());
116 Ok(DeferralState::new(results))
117}