openvm_verify_stark_circuit/
extension.rs

1use 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
33///////////////////////////////////////////////////////////////////////////////
34/// DEFERRAL FN IMPLEMENTATION
35///////////////////////////////////////////////////////////////////////////////
36pub 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    // get (app_exe_commit, app_vm_commit, public values)
43    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
75///////////////////////////////////////////////////////////////////////////////
76/// DEFERRAL STATE GENERATION
77///////////////////////////////////////////////////////////////////////////////
78pub 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}