1use std::sync::Arc;
2
3use openvm_circuit::{
4 arch::{
5 instructions::{
6 exe::VmExe, instruction::Instruction, program::Program, LocalOpcode,
7 SystemOpcode::TERMINATE,
8 },
9 ContinuationVmProof, SingleSegmentVmExecutor, VirtualMachine, VmComplexTraceHeights,
10 VmConfig, VmExecutor,
11 },
12 system::program::trace::VmCommittedExe,
13 utils::next_power_of_two_or_zero,
14};
15use openvm_continuations::verifier::{
16 internal::types::InternalVmVerifierInput,
17 leaf::{types::LeafVmVerifierInput, LeafVmVerifierConfig},
18 root::types::RootVmVerifierInput,
19};
20use openvm_native_circuit::NativeConfig;
21use openvm_native_compiler::ir::DIGEST_SIZE;
22use openvm_native_recursion::hints::Hintable;
23use openvm_rv32im_circuit::Rv32ImConfig;
24use openvm_stark_sdk::{
25 config::{
26 baby_bear_poseidon2::BabyBearPoseidon2Engine,
27 fri_params::standard_fri_params_with_100_bits_conjectured_security, FriParameters,
28 },
29 engine::StarkFriEngine,
30 openvm_stark_backend::{
31 config::StarkGenericConfig, p3_field::FieldAlgebra, proof::Proof, Chip,
32 },
33};
34
35use crate::{
36 prover::vm::{
37 local::VmLocalProver, types::VmProvingKey, ContinuationVmProver, SingleSegmentVmProver,
38 },
39 NonRootCommittedExe, F, SC,
40};
41
42pub(super) fn compute_root_proof_heights(
48 root_vm_config: NativeConfig,
49 root_exe: VmExe<F>,
50 dummy_internal_proof: &Proof<SC>,
51) -> (Vec<usize>, VmComplexTraceHeights) {
52 let num_user_public_values = root_vm_config.system.num_public_values - 2 * DIGEST_SIZE;
53 let root_input = RootVmVerifierInput {
54 proofs: vec![dummy_internal_proof.clone()],
55 public_values: vec![F::ZERO; num_user_public_values],
56 };
57 let vm = SingleSegmentVmExecutor::new(root_vm_config);
58 let res = vm
59 .execute_and_compute_heights(root_exe, root_input.write())
60 .unwrap();
61 let air_heights: Vec<_> = res
62 .air_heights
63 .into_iter()
64 .map(next_power_of_two_or_zero)
65 .collect();
66 let mut vm_heights = res.vm_heights;
67 vm_heights.round_to_next_power_of_two_or_zero();
68 (air_heights, vm_heights)
69}
70
71pub(super) fn dummy_internal_proof(
72 internal_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
73 internal_exe: Arc<NonRootCommittedExe>,
74 leaf_proof: Proof<SC>,
75) -> Proof<SC> {
76 let mut internal_inputs = InternalVmVerifierInput::chunk_leaf_or_internal_proofs(
77 internal_exe.get_program_commit().into(),
78 &[leaf_proof],
79 1,
80 );
81 let internal_input = internal_inputs.pop().unwrap();
82 let internal_prover = VmLocalProver::<SC, NativeConfig, BabyBearPoseidon2Engine>::new(
83 internal_vm_pk,
84 internal_exe,
85 );
86 SingleSegmentVmProver::prove(&internal_prover, internal_input.write())
87}
88
89pub(super) fn dummy_internal_proof_riscv_app_vm(
90 leaf_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
91 internal_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
92 internal_exe: Arc<NonRootCommittedExe>,
93 num_public_values: usize,
94) -> Proof<SC> {
95 let fri_params = standard_fri_params_with_100_bits_conjectured_security(1);
96 let leaf_proof = dummy_leaf_proof_riscv_app_vm(leaf_vm_pk, num_public_values, fri_params);
97 dummy_internal_proof(internal_vm_pk, internal_exe, leaf_proof)
98}
99
100#[allow(dead_code)]
101pub fn dummy_leaf_proof<VC: VmConfig<F>>(
102 leaf_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
103 app_vm_pk: Arc<VmProvingKey<SC, VC>>,
104 overridden_heights: Option<VmComplexTraceHeights>,
105) -> Proof<SC>
106where
107 VC::Executor: Chip<SC>,
108 VC::Periphery: Chip<SC>,
109{
110 let app_proof = dummy_app_proof_impl(app_vm_pk.clone(), overridden_heights);
111 dummy_leaf_proof_impl(leaf_vm_pk, app_vm_pk, &app_proof)
112}
113
114pub(super) fn dummy_leaf_proof_riscv_app_vm(
115 leaf_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
116 num_public_values: usize,
117 app_fri_params: FriParameters,
118) -> Proof<SC> {
119 let app_vm_pk = Arc::new(dummy_riscv_app_vm_pk(num_public_values, app_fri_params));
120 let app_proof = dummy_app_proof_impl(app_vm_pk.clone(), None);
121 dummy_leaf_proof_impl(leaf_vm_pk, app_vm_pk, &app_proof)
122}
123
124fn dummy_leaf_proof_impl<VC: VmConfig<F>>(
125 leaf_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
126 app_vm_pk: Arc<VmProvingKey<SC, VC>>,
127 app_proof: &ContinuationVmProof<SC>,
128) -> Proof<SC> {
129 let leaf_program = LeafVmVerifierConfig {
130 app_fri_params: app_vm_pk.fri_params,
131 app_system_config: app_vm_pk.vm_config.system().clone(),
132 compiler_options: Default::default(),
133 }
134 .build_program(&app_vm_pk.vm_pk.get_vk());
135 assert_eq!(
136 app_proof.per_segment.len(),
137 1,
138 "Dummy proof should only have 1 segment"
139 );
140 let e = BabyBearPoseidon2Engine::new(leaf_vm_pk.fri_params);
141 let leaf_exe = Arc::new(VmCommittedExe::<SC>::commit(
142 leaf_program.into(),
143 e.config.pcs(),
144 ));
145 let leaf_prover =
146 VmLocalProver::<SC, NativeConfig, BabyBearPoseidon2Engine>::new(leaf_vm_pk, leaf_exe);
147 let mut leaf_inputs = LeafVmVerifierInput::chunk_continuation_vm_proof(app_proof, 1);
148 let leaf_input = leaf_inputs.pop().unwrap();
149 SingleSegmentVmProver::prove(&leaf_prover, leaf_input.write_to_stream())
150}
151
152fn dummy_riscv_app_vm_pk(
153 num_public_values: usize,
154 fri_params: FriParameters,
155) -> VmProvingKey<SC, Rv32ImConfig> {
156 let vm_config = Rv32ImConfig::with_public_values(num_public_values);
157 let vm = VirtualMachine::new(BabyBearPoseidon2Engine::new(fri_params), vm_config.clone());
158 let vm_pk = vm.keygen();
159 VmProvingKey {
160 fri_params,
161 vm_config,
162 vm_pk,
163 }
164}
165
166fn dummy_app_proof_impl<VC: VmConfig<F>>(
167 app_vm_pk: Arc<VmProvingKey<SC, VC>>,
168 overridden_heights: Option<VmComplexTraceHeights>,
169) -> ContinuationVmProof<SC>
170where
171 VC::Executor: Chip<SC>,
172 VC::Periphery: Chip<SC>,
173{
174 let fri_params = app_vm_pk.fri_params;
175 let dummy_exe = dummy_app_committed_exe(fri_params);
176 let overridden_heights = if let Some(overridden_heights) = overridden_heights {
178 overridden_heights
179 } else {
180 let executor = VmExecutor::new(app_vm_pk.vm_config.clone());
182 let mut results = executor
183 .execute_segments(dummy_exe.exe.clone(), vec![])
184 .unwrap();
185 assert_eq!(results.len(), 1, "dummy exe should have only 1 segment");
187 let mut result = results.pop().unwrap();
188 result.chip_complex.finalize_memory();
189 let mut vm_heights = result.chip_complex.get_internal_trace_heights();
190 vm_heights.round_to_next_power_of_two();
191 vm_heights
192 };
193 let app_prover =
195 VmLocalProver::<SC, VC, BabyBearPoseidon2Engine>::new_with_overridden_trace_heights(
196 app_vm_pk,
197 dummy_exe,
198 Some(overridden_heights),
199 );
200 ContinuationVmProver::prove(&app_prover, vec![])
201}
202
203fn dummy_app_committed_exe(fri_params: FriParameters) -> Arc<NonRootCommittedExe> {
204 let program = dummy_app_program();
205 let e = BabyBearPoseidon2Engine::new(fri_params);
206 Arc::new(VmCommittedExe::<SC>::commit(program.into(), e.config.pcs()))
207}
208
209fn dummy_app_program() -> Program<F> {
210 let mut ret = Program::from_instructions(&[Instruction::from_isize(
211 TERMINATE.global_opcode(),
212 0,
213 0,
214 0,
215 0,
216 0,
217 )]);
218 ret.max_num_public_values = 0;
219 ret
220}