openvm_continuations/verifier/common/
non_leaf.rs1use std::{array, borrow::Borrow};
2
3use openvm_circuit::arch::PUBLIC_VALUES_AIR_ID;
4use openvm_native_compiler::ir::{Array, Builder, Config, Felt, RVar, DIGEST_SIZE};
5use openvm_native_recursion::{
6 challenger::duplex::DuplexChallengerVariable, fri::TwoAdicFriPcsVariable, stark::StarkVerifier,
7 types::MultiStarkVerificationAdvice, vars::StarkProofVariable,
8};
9use openvm_stark_sdk::openvm_stark_backend::p3_field::PrimeField32;
10
11use crate::verifier::{
12 common::{
13 assert_or_assign_connector_pvs, assert_or_assign_memory_pvs,
14 assert_required_air_for_agg_vm_present, assert_single_segment_vm_exit_successfully,
15 get_program_commit, types::VmVerifierPvs,
16 },
17 internal::types::InternalVmVerifierPvs,
18 utils::{assign_array_to_slice, eq_felt_slice},
19};
20
21pub struct NonLeafVerifierVariables<C: Config> {
22 pub internal_program_commit: [Felt<C::F>; DIGEST_SIZE],
23 pub leaf_pcs: TwoAdicFriPcsVariable<C>,
24 pub leaf_advice: MultiStarkVerificationAdvice<C>,
25 pub internal_pcs: TwoAdicFriPcsVariable<C>,
26 pub internal_advice: MultiStarkVerificationAdvice<C>,
27}
28
29impl<C: Config> NonLeafVerifierVariables<C> {
30 #[allow(clippy::type_complexity)]
33 pub fn verify_internal_or_leaf_verifier_proofs(
34 &self,
35 builder: &mut Builder<C>,
36 proofs: &Array<C, StarkProofVariable<C>>,
37 ) -> (VmVerifierPvs<Felt<C::F>>, [Felt<C::F>; DIGEST_SIZE])
38 where
39 C::F: PrimeField32,
40 {
41 builder.assert_nonzero(&proofs.len());
43 let pvs = VmVerifierPvs::<Felt<C::F>>::uninit(builder);
44 let leaf_verifier_commit = array::from_fn(|_| builder.uninit());
45
46 builder.range(0, proofs.len()).for_each(|i_vec, builder| {
47 let i = i_vec[0];
48 let proof = builder.get(proofs, i);
49 assert_required_air_for_agg_vm_present(builder, &proof);
50 let proof_vm_pvs = self.verify_internal_or_leaf_verifier_proof(builder, &proof);
51
52 assert_single_segment_vm_exit_successfully(builder, &proof);
53 builder.if_eq(i, RVar::zero()).then_or_else(
54 |builder| {
55 builder.assign(&pvs.app_commit, proof_vm_pvs.vm_verifier_pvs.app_commit);
56 builder.assign(
57 &leaf_verifier_commit,
58 proof_vm_pvs.extra_pvs.leaf_verifier_commit,
59 );
60 },
61 |builder| {
62 builder.assert_eq::<[_; DIGEST_SIZE]>(
63 pvs.app_commit,
64 proof_vm_pvs.vm_verifier_pvs.app_commit,
65 );
66 builder.assert_eq::<[_; DIGEST_SIZE]>(
67 leaf_verifier_commit,
68 proof_vm_pvs.extra_pvs.leaf_verifier_commit,
69 );
70 },
71 );
72 assert_or_assign_connector_pvs(
73 builder,
74 &pvs.connector,
75 i,
76 &proof_vm_pvs.vm_verifier_pvs.connector,
77 );
78 assert_or_assign_memory_pvs(
79 builder,
80 &pvs.memory,
81 i,
82 &proof_vm_pvs.vm_verifier_pvs.memory,
83 );
84 builder.assign(
87 &pvs.public_values_commit,
88 proof_vm_pvs.vm_verifier_pvs.public_values_commit,
89 );
90 });
91 (pvs, leaf_verifier_commit)
92 }
93 fn verify_internal_or_leaf_verifier_proof(
94 &self,
95 builder: &mut Builder<C>,
96 proof: &StarkProofVariable<C>,
97 ) -> InternalVmVerifierPvs<Felt<C::F>>
98 where
99 C::F: PrimeField32,
100 {
101 let flatten_proof_vm_pvs = InternalVmVerifierPvs::<Felt<C::F>>::uninit(builder).flatten();
102 let proof_vm_pvs_arr = builder
103 .get(&proof.per_air, PUBLIC_VALUES_AIR_ID)
104 .public_values;
105
106 let program_commit = get_program_commit(builder, proof);
107 let is_self_program =
108 eq_felt_slice(builder, &self.internal_program_commit, &program_commit);
109
110 builder.if_eq(is_self_program, RVar::one()).then_or_else(
111 |builder| {
112 StarkVerifier::verify::<DuplexChallengerVariable<C>>(
113 builder,
114 &self.internal_pcs,
115 &self.internal_advice,
116 proof,
117 );
118 assign_array_to_slice(builder, &flatten_proof_vm_pvs, &proof_vm_pvs_arr, 0);
119 let proof_vm_pvs: &InternalVmVerifierPvs<_> =
120 flatten_proof_vm_pvs.as_slice().borrow();
121 builder.assert_eq::<[_; DIGEST_SIZE]>(
124 proof_vm_pvs.extra_pvs.internal_program_commit,
125 program_commit,
126 );
127 },
128 |builder| {
129 StarkVerifier::verify::<DuplexChallengerVariable<C>>(
130 builder,
131 &self.leaf_pcs,
132 &self.leaf_advice,
133 proof,
134 );
135 assign_array_to_slice(
137 builder,
138 &flatten_proof_vm_pvs[..VmVerifierPvs::<u8>::width()],
139 &proof_vm_pvs_arr,
140 0,
141 );
142 let proof_vm_pvs: &InternalVmVerifierPvs<_> =
143 flatten_proof_vm_pvs.as_slice().borrow();
144 builder.assign(&proof_vm_pvs.extra_pvs.leaf_verifier_commit, program_commit);
145 },
146 );
147 *flatten_proof_vm_pvs.as_slice().borrow()
148 }
149}