openvm_continuations/circuit/root/verifier/
trace.rs1use std::borrow::{Borrow, BorrowMut};
2
3use openvm_cpu_backend::CpuBackend;
4use openvm_poseidon2_air::Permutation;
5use openvm_stark_backend::{proof::Proof, prover::AirProvingContext, StarkProtocolConfig};
6use openvm_stark_sdk::config::baby_bear_poseidon2::{
7 poseidon2_compress_with_capacity, poseidon2_perm, BabyBearPoseidon2Config, DIGEST_SIZE, F,
8};
9use openvm_verify_stark_host::pvs::{
10 DeferralPvs, VerifierBasePvs, VerifierDefPvs, VmPvs, DEF_PVS_AIR_ID, VERIFIER_PVS_AIR_ID,
11 VM_PVS_AIR_ID,
12};
13use p3_field::{Field, PrimeCharacteristicRing, PrimeField32};
14use p3_matrix::dense::RowMajorMatrix;
15
16use crate::{
17 circuit::{
18 root::{
19 verifier::air::{RootDefVerifierCols, RootVerifierPvsCols},
20 RootVerifierPvs,
21 },
22 subair::hash_slice_trace,
23 SingleAirTraceData,
24 },
25 utils::pad_slice_to_poseidon2_input,
26};
27
28pub fn generate_proving_ctx<SC: StarkProtocolConfig<F = F>>(
29 proof: &Proof<BabyBearPoseidon2Config>,
30 deferral_enabled: bool,
31) -> SingleAirTraceData<CpuBackend<SC>> {
32 let base_width = RootVerifierPvsCols::<u8>::width();
33 let def_width = RootDefVerifierCols::<u8>::width();
34 let width = base_width + if deferral_enabled { def_width } else { 0 };
35 let mut trace = vec![F::ZERO; width];
36
37 let (base_cols_slice, def_cols_slice) = trace.as_mut_slice().split_at_mut(base_width);
38 let cols: &mut RootVerifierPvsCols<F> = base_cols_slice.borrow_mut();
39
40 let (base_pvs_slice, def_pvs_slice) = proof.public_values[VERIFIER_PVS_AIR_ID]
41 .as_slice()
42 .split_at(VerifierBasePvs::<u8>::width());
43 let child_verifier_pvs: &VerifierBasePvs<F> = base_pvs_slice.borrow();
44 let child_vm_pvs: &VmPvs<F> = proof.public_values[VM_PVS_AIR_ID].as_slice().borrow();
45
46 cols.child_verifier_pvs = *child_verifier_pvs;
47 cols.child_vm_pvs = *child_vm_pvs;
48 let depth_minus_one = child_verifier_pvs.recursion_depth - F::ONE;
49 cols.recursion_depth_minus_one_inv = if depth_minus_one == F::ZERO {
50 F::ZERO
51 } else {
52 depth_minus_one.inverse()
53 };
54 let range_check_inputs = vec![depth_minus_one.as_canonical_u32() as usize];
55
56 let padded_program_commit = pad_slice_to_poseidon2_input(&child_vm_pvs.program_commit, F::ZERO);
57 let padded_initial_root = pad_slice_to_poseidon2_input(&child_vm_pvs.initial_root, F::ZERO);
58 let padded_initial_pc = pad_slice_to_poseidon2_input(&[child_vm_pvs.initial_pc], F::ZERO);
59
60 let perm = poseidon2_perm();
61 cols.program_commit_hash = perm.permute(padded_program_commit)[..DIGEST_SIZE]
62 .try_into()
63 .unwrap();
64 cols.initial_root_hash = perm.permute(padded_initial_root)[..DIGEST_SIZE]
65 .try_into()
66 .unwrap();
67 cols.initial_pc_hash = perm.permute(padded_initial_pc)[..DIGEST_SIZE]
68 .try_into()
69 .unwrap();
70
71 let mut poseidon2_compress_inputs = Vec::with_capacity(5);
72 let mut poseidon2_permute_inputs = Vec::new();
73
74 poseidon2_compress_inputs.extend_from_slice(&[
75 padded_program_commit,
76 padded_initial_root,
77 padded_initial_pc,
78 ]);
79
80 cols.intermediate_exe_commit =
81 poseidon2_compress_with_capacity(cols.program_commit_hash, cols.initial_root_hash).0;
82 poseidon2_compress_inputs.push(crate::utils::digests_to_poseidon2_input(
83 cols.program_commit_hash,
84 cols.initial_root_hash,
85 ));
86
87 let vk_elements = [
88 child_verifier_pvs.app_vk_commit.cached_commit,
89 child_verifier_pvs.app_vk_commit.vk_pre_hash,
90 child_verifier_pvs.leaf_vk_commit.cached_commit,
91 child_verifier_pvs.leaf_vk_commit.vk_pre_hash,
92 child_verifier_pvs.internal_for_leaf_vk_commit.cached_commit,
93 child_verifier_pvs.internal_for_leaf_vk_commit.vk_pre_hash,
94 ];
95 let (intermediate_vk_states, app_vm_commit) = hash_slice_trace(
96 &vk_elements,
97 Some(&mut poseidon2_permute_inputs),
98 Some(&mut poseidon2_compress_inputs),
99 );
100 cols.intermediate_vk_states = intermediate_vk_states.try_into().unwrap();
101
102 let mut public_values = vec![F::ZERO; RootVerifierPvs::<u8>::width()];
103 let root_pvs: &mut RootVerifierPvs<F> = public_values.as_mut_slice().borrow_mut();
104
105 root_pvs.app_exe_commit =
106 poseidon2_compress_with_capacity(cols.intermediate_exe_commit, cols.initial_pc_hash).0;
107 poseidon2_compress_inputs.push(crate::utils::digests_to_poseidon2_input(
108 cols.intermediate_exe_commit,
109 cols.initial_pc_hash,
110 ));
111
112 root_pvs.app_vm_commit = app_vm_commit;
113
114 if deferral_enabled {
115 let def_verifier_pvs: &VerifierDefPvs<F> = def_pvs_slice.borrow();
116 let def_pvs: &DeferralPvs<F> = proof.public_values[DEF_PVS_AIR_ID].as_slice().borrow();
117 let def_cols: &mut RootDefVerifierCols<F> = def_cols_slice.borrow_mut();
118 def_cols.child_def_verifier_pvs = *def_verifier_pvs;
119 def_cols.child_def_pvs = *def_pvs;
120 }
121
122 SingleAirTraceData {
123 air_proving_ctx: AirProvingContext {
124 cached_mains: vec![],
125 common_main: RowMajorMatrix::new(trace, width),
126 public_values,
127 },
128 poseidon2_compress_inputs,
129 poseidon2_permute_inputs,
130 range_check_inputs,
131 }
132}