1use bon::Builder;
2use openvm_algebra_circuit::*;
3use openvm_algebra_transpiler::{Fp2TranspilerExtension, ModularTranspilerExtension};
4use openvm_bigint_circuit::*;
5use openvm_bigint_transpiler::*;
6use openvm_circuit::{
7 arch::{instructions::DEFERRAL_AS, *},
8 derive::VmConfig,
9 system::{SystemChipInventory, SystemCpuBuilder, SystemExecutor},
10};
11use openvm_cpu_backend::{CpuBackend, CpuDevice};
12use openvm_deferral_circuit::*;
13use openvm_deferral_transpiler::*;
14use openvm_ecc_circuit::*;
15use openvm_ecc_transpiler::*;
16use openvm_keccak256_circuit::*;
17use openvm_keccak256_transpiler::*;
18use openvm_pairing_circuit::*;
19use openvm_pairing_transpiler::*;
20use openvm_rv32im_circuit::*;
21use openvm_rv32im_transpiler::*;
22use openvm_sha2_circuit::*;
23use openvm_sha2_transpiler::*;
24use openvm_stark_backend::{p3_field::Field, StarkEngine, StarkProtocolConfig, Val};
25use openvm_stark_sdk::config::baby_bear_poseidon2::F;
26use openvm_transpiler::transpiler::Transpiler;
27use serde::{Deserialize, Serialize};
28
29pub mod deferral;
30use deferral::DeferralConfig;
31
32cfg_if::cfg_if! {
33 if #[cfg(feature = "cuda")] {
34 use openvm_algebra_circuit::AlgebraProverExt;
35 use openvm_bigint_circuit::Int256GpuProverExt;
36 use openvm_circuit::system::cuda::{extensions::SystemGpuBuilder, SystemChipInventoryGPU};
37 use openvm_cuda_backend::{
38 BabyBearPoseidon2GpuEngine, GpuBackend
39 };
40 use openvm_ecc_circuit::EccProverExt;
41 use openvm_keccak256_circuit::Keccak256GpuProverExt;
42 use openvm_rv32im_circuit::Rv32ImGpuProverExt;
43 use openvm_sha2_circuit::Sha2GpuProverExt;
44 pub use SdkVmGpuBuilder as SdkVmBuilder;
45 } else {
46 pub use SdkVmCpuBuilder as SdkVmBuilder;
47 }
48}
49
50#[derive(Clone, Debug, Serialize, Deserialize)]
51struct SdkVmConfigWrapper {
52 app_vm_config: SdkVmConfig,
53}
54
55#[derive(Builder, Clone, Debug, Serialize, Deserialize)]
62#[serde(from = "SdkVmConfigWithDefaultDeser")]
63pub struct SdkVmConfig {
64 pub system: SdkSystemConfig,
65 pub rv32i: Option<UnitStruct>,
66 pub io: Option<UnitStruct>,
67 pub keccak: Option<UnitStruct>,
68 pub sha2: Option<UnitStruct>,
69
70 pub rv32m: Option<Rv32M>,
74 pub bigint: Option<Int256>,
78 pub modular: Option<ModularExtension>,
79 pub fp2: Option<Fp2Extension>,
80 pub pairing: Option<PairingExtension>,
81 pub ecc: Option<WeierstrassExtension>,
82
83 pub deferral: Option<DeferralConfig>,
87}
88
89impl SdkVmConfig {
90 #[doc = include_str!("openvm_standard.toml")]
98 pub fn standard() -> SdkVmConfig {
100 let bn_config = PairingCurve::Bn254.curve_config();
101 let bls_config = PairingCurve::Bls12_381.curve_config();
102 SdkVmConfig::builder()
103 .system(Default::default())
104 .rv32i(Default::default())
105 .rv32m(Default::default())
106 .io(Default::default())
107 .keccak(Default::default())
108 .sha2(Default::default())
109 .bigint(Default::default())
110 .modular(ModularExtension::new(vec![
111 bn_config.modulus.clone(),
112 bn_config.scalar.clone(),
113 SECP256K1_CONFIG.modulus.clone(),
114 SECP256K1_CONFIG.scalar.clone(),
115 P256_CONFIG.modulus.clone(),
116 P256_CONFIG.scalar.clone(),
117 bls_config.modulus.clone(),
118 bls_config.scalar.clone(),
119 ]))
120 .fp2(Fp2Extension::new(vec![
121 (
122 BN254_COMPLEX_STRUCT_NAME.to_string(),
123 bn_config.modulus.clone(),
124 ),
125 (
126 BLS12_381_COMPLEX_STRUCT_NAME.to_string(),
127 bls_config.modulus.clone(),
128 ),
129 ]))
130 .ecc(WeierstrassExtension::new(vec![
131 bn_config.clone(),
132 SECP256K1_CONFIG.clone(),
133 P256_CONFIG.clone(),
134 bls_config.clone(),
135 ]))
136 .pairing(PairingExtension::new(vec![
137 PairingCurve::Bn254,
138 PairingCurve::Bls12_381,
139 ]))
140 .build()
141 .optimize()
142 }
143
144 #[doc = include_str!("openvm_riscv32.toml")]
150 pub fn riscv32() -> Self {
152 SdkVmConfig::builder()
153 .system(Default::default())
154 .rv32i(Default::default())
155 .rv32m(Default::default())
156 .io(Default::default())
157 .build()
158 .optimize()
159 }
160
161 pub fn from_toml(openvm_toml: &str) -> Result<Self, toml::de::Error> {
163 let wrapper: SdkVmConfigWrapper = toml::from_str(openvm_toml)?;
164 Ok(wrapper.app_vm_config)
165 }
166
167 pub fn to_toml(&self) -> Result<String, toml::ser::Error> {
168 toml::to_string_pretty(&SdkVmConfigWrapper {
169 app_vm_config: self.clone(),
170 })
171 }
172}
173
174pub trait TranspilerConfig<F> {
175 fn transpiler(&self) -> Transpiler<F>;
176}
177
178impl TranspilerConfig<F> for SdkVmConfig {
179 fn transpiler(&self) -> Transpiler<F> {
180 let mut transpiler = Transpiler::default();
181 if self.rv32i.is_some() {
182 transpiler = transpiler.with_extension(Rv32ITranspilerExtension);
183 }
184 if self.io.is_some() {
185 transpiler = transpiler.with_extension(Rv32IoTranspilerExtension);
186 }
187 if self.keccak.is_some() {
188 transpiler = transpiler.with_extension(Keccak256TranspilerExtension);
189 }
190 if self.sha2.is_some() {
191 transpiler = transpiler.with_extension(Sha2TranspilerExtension);
192 }
193 if self.rv32m.is_some() {
194 transpiler = transpiler.with_extension(Rv32MTranspilerExtension);
195 }
196 if self.bigint.is_some() {
197 transpiler = transpiler.with_extension(Int256TranspilerExtension);
198 }
199 if self.modular.is_some() {
200 transpiler = transpiler.with_extension(ModularTranspilerExtension);
201 }
202 if self.fp2.is_some() {
203 transpiler = transpiler.with_extension(Fp2TranspilerExtension);
204 }
205 if self.pairing.is_some() {
206 transpiler = transpiler.with_extension(PairingTranspilerExtension);
207 }
208 if self.ecc.is_some() {
209 transpiler = transpiler.with_extension(EccTranspilerExtension);
210 }
211 if let Some(deferral_config) = &self.deferral {
212 transpiler = transpiler.with_extension(DeferralTranspilerExtension::new(
213 deferral_config.to_extension().def_circuit_commits,
214 ));
215 }
216 transpiler
217 }
218}
219
220impl AsRef<SystemConfig> for SdkVmConfig {
221 fn as_ref(&self) -> &SystemConfig {
222 &self.system.config
223 }
224}
225
226impl AsMut<SystemConfig> for SdkVmConfig {
227 fn as_mut(&mut self) -> &mut SystemConfig {
228 &mut self.system.config
229 }
230}
231
232impl SdkVmConfig {
233 pub fn optimize(mut self) -> Self {
234 self.apply_optimizations();
235 self
236 }
237
238 pub fn apply_optimizations(&mut self) {
240 let rv32m = self.rv32m.as_mut();
241 let bigint = self.bigint.as_mut();
242 if let (Some(bigint), Some(rv32m)) = (bigint, rv32m) {
243 rv32m.range_tuple_checker_sizes[0] =
244 rv32m.range_tuple_checker_sizes[0].max(bigint.range_tuple_checker_sizes[0]);
245 rv32m.range_tuple_checker_sizes[1] =
246 rv32m.range_tuple_checker_sizes[1].max(bigint.range_tuple_checker_sizes[1]);
247 bigint.range_tuple_checker_sizes = rv32m.range_tuple_checker_sizes;
248 }
249
250 const DEFERRAL_AS_USIZE: usize = DEFERRAL_AS as usize;
251 let addr_spaces = &mut self.system.config.memory_config.addr_spaces;
252 let deferral_as_exists = addr_spaces.len() > DEFERRAL_AS_USIZE;
253 if self.deferral.is_some() {
254 assert!(
255 deferral_as_exists,
256 "deferral is enabled but address space DEFERRAL_AS ({DEFERRAL_AS_USIZE}) is missing \
257 from memory_config.addr_spaces; the VM config must allocate it"
258 );
259 } else if deferral_as_exists {
260 addr_spaces[DEFERRAL_AS_USIZE].num_cells = 0;
261 }
262 }
263
264 pub fn to_inner(&self) -> SdkVmConfigInner {
265 let config = self.clone().optimize();
266 let system = config.system.config.clone();
267 let rv32i = config.rv32i.map(|_| Rv32I);
268 let io = config.io.map(|_| Rv32Io);
269 let keccak = config.keccak.map(|_| Keccak256);
270 let sha2 = config.sha2.map(|_| Sha2);
271 let rv32m = config.rv32m;
272 let bigint = config.bigint;
273 let modular = config.modular.clone();
274 let fp2 = config.fp2.clone();
275 let pairing = config.pairing.clone();
276 let ecc = config.ecc.clone();
277 let deferral = config.deferral.as_ref().map(DeferralConfig::to_extension);
278
279 SdkVmConfigInner {
280 system,
281 rv32i,
282 io,
283 keccak,
284 sha2,
285 rv32m,
286 bigint,
287 modular,
288 fp2,
289 pairing,
290 ecc,
291 deferral,
292 }
293 }
294}
295
296#[derive(Copy, Clone, Default)]
300pub struct SdkVmCpuBuilder;
301
302#[derive(Clone, Debug, VmConfig, Serialize, Deserialize)]
305pub struct SdkVmConfigInner {
306 #[config(executor = "SystemExecutor<F>")]
307 pub system: SystemConfig,
308 #[extension(executor = "Rv32IExecutor")]
309 pub rv32i: Option<Rv32I>,
310 #[extension(executor = "Rv32IoExecutor")]
311 pub io: Option<Rv32Io>,
312 #[extension(executor = "Keccak256Executor")]
313 pub keccak: Option<Keccak256>,
314 #[extension(executor = "Sha2Executor")]
315 pub sha2: Option<Sha2>,
316
317 #[extension(executor = "Rv32MExecutor")]
318 pub rv32m: Option<Rv32M>,
319 #[extension(executor = "Int256Executor")]
320 pub bigint: Option<Int256>,
321 #[extension(executor = "ModularExtensionExecutor")]
322 pub modular: Option<ModularExtension>,
323 #[extension(executor = "Fp2ExtensionExecutor")]
324 pub fp2: Option<Fp2Extension>,
325 #[extension(executor = "PairingExtensionExecutor<F>")]
326 pub pairing: Option<PairingExtension>,
327 #[extension(executor = "WeierstrassExtensionExecutor")]
328 pub ecc: Option<WeierstrassExtension>,
329
330 #[extension(executor = "DeferralExecutor")]
331 pub deferral: Option<DeferralExtension>,
332}
333
334pub type SdkVmConfigExecutor<F> = SdkVmConfigInnerExecutor<F>;
336
337impl<F: Field> VmExecutionConfig<F> for SdkVmConfig
338where
339 SdkVmConfigInner: VmExecutionConfig<F>,
340{
341 type Executor = <SdkVmConfigInner as VmExecutionConfig<F>>::Executor;
342
343 fn create_executors(
344 &self,
345 ) -> Result<ExecutorInventory<Self::Executor>, ExecutorInventoryError> {
346 self.to_inner().create_executors()
347 }
348}
349
350impl<SC: StarkProtocolConfig> VmCircuitConfig<SC> for SdkVmConfig
351where
352 SdkVmConfigInner: VmCircuitConfig<SC>,
353{
354 fn create_airs(&self) -> Result<AirInventory<SC>, AirInventoryError> {
355 self.to_inner().create_airs()
356 }
357}
358
359use openvm_stark_sdk::config::baby_bear_poseidon2::BabyBearPoseidon2Config;
360type SC = BabyBearPoseidon2Config;
361impl<E> VmBuilder<E> for SdkVmCpuBuilder
362where
363 E: StarkEngine<SC = SC, PB = CpuBackend<SC>, PD = CpuDevice<SC>>,
364{
365 type VmConfig = SdkVmConfig;
366 type SystemChipInventory = SystemChipInventory<SC>;
367 type RecordArena = MatrixRecordArena<Val<SC>>;
368
369 fn create_chip_complex(
370 &self,
371 config: &SdkVmConfig,
372 circuit: AirInventory<SC>,
373 device_ctx: &openvm_stark_backend::EngineDeviceCtx<E>,
374 ) -> Result<
375 VmChipComplex<SC, Self::RecordArena, E::PB, Self::SystemChipInventory>,
376 ChipInventoryError,
377 > {
378 let config = config.to_inner();
379 let mut chip_complex = VmBuilder::<E>::create_chip_complex(
380 &SystemCpuBuilder,
381 &config.system,
382 circuit,
383 device_ctx,
384 )?;
385 let inventory = &mut chip_complex.inventory;
386 if let Some(rv32i) = &config.rv32i {
387 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImCpuProverExt, rv32i, inventory)?;
388 }
389 if let Some(io) = &config.io {
390 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImCpuProverExt, io, inventory)?;
391 }
392 if let Some(keccak) = &config.keccak {
393 VmProverExtension::<E, _, _>::extend_prover(&Keccak256CpuProverExt, keccak, inventory)?;
394 }
395 if let Some(sha2) = &config.sha2 {
396 VmProverExtension::<E, _, _>::extend_prover(&Sha2CpuProverExt, sha2, inventory)?;
397 }
398 if let Some(rv32m) = &config.rv32m {
399 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImCpuProverExt, rv32m, inventory)?;
400 }
401 if let Some(bigint) = &config.bigint {
402 VmProverExtension::<E, _, _>::extend_prover(&Int256CpuProverExt, bigint, inventory)?;
403 }
404 if let Some(modular) = &config.modular {
405 VmProverExtension::<E, _, _>::extend_prover(&AlgebraCpuProverExt, modular, inventory)?;
406 }
407 if let Some(fp2) = &config.fp2 {
408 VmProverExtension::<E, _, _>::extend_prover(&AlgebraCpuProverExt, fp2, inventory)?;
409 }
410 if let Some(pairing) = &config.pairing {
411 VmProverExtension::<E, _, _>::extend_prover(&PairingProverExt, pairing, inventory)?;
412 }
413 if let Some(ecc) = &config.ecc {
414 VmProverExtension::<E, _, _>::extend_prover(&EccCpuProverExt, ecc, inventory)?;
415 }
416 if let Some(deferral) = &config.deferral {
417 VmProverExtension::<E, _, _>::extend_prover(
418 &DeferralCpuProverExt,
419 deferral,
420 inventory,
421 )?;
422 }
423 Ok(chip_complex)
424 }
425}
426
427#[cfg(feature = "cuda")]
428#[derive(Copy, Clone, Default)]
429pub struct SdkVmGpuBuilder;
430
431#[cfg(feature = "cuda")]
432impl VmBuilder<BabyBearPoseidon2GpuEngine> for SdkVmGpuBuilder {
433 type VmConfig = SdkVmConfig;
434 type SystemChipInventory = SystemChipInventoryGPU;
435 type RecordArena = DenseRecordArena;
436
437 fn create_chip_complex(
438 &self,
439 config: &SdkVmConfig,
440 circuit: AirInventory<SC>,
441 device_ctx: &openvm_stark_backend::EngineDeviceCtx<BabyBearPoseidon2GpuEngine>,
442 ) -> Result<
443 VmChipComplex<SC, Self::RecordArena, GpuBackend, Self::SystemChipInventory>,
444 ChipInventoryError,
445 > {
446 type E = BabyBearPoseidon2GpuEngine;
447
448 let config = config.to_inner();
449 let mut chip_complex = VmBuilder::<E>::create_chip_complex(
450 &SystemGpuBuilder,
451 &config.system,
452 circuit,
453 device_ctx,
454 )?;
455 let inventory = &mut chip_complex.inventory;
456 if let Some(rv32i) = &config.rv32i {
457 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImGpuProverExt, rv32i, inventory)?;
458 }
459 if let Some(io) = &config.io {
460 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImGpuProverExt, io, inventory)?;
461 }
462 if let Some(keccak) = &config.keccak {
463 VmProverExtension::<E, _, _>::extend_prover(&Keccak256GpuProverExt, keccak, inventory)?;
464 }
465 if let Some(sha2) = &config.sha2 {
466 VmProverExtension::<E, _, _>::extend_prover(&Sha2GpuProverExt, sha2, inventory)?;
467 }
468 if let Some(rv32m) = &config.rv32m {
469 VmProverExtension::<E, _, _>::extend_prover(&Rv32ImGpuProverExt, rv32m, inventory)?;
470 }
471 if let Some(bigint) = &config.bigint {
472 VmProverExtension::<E, _, _>::extend_prover(&Int256GpuProverExt, bigint, inventory)?;
473 }
474 if let Some(modular) = &config.modular {
475 VmProverExtension::<E, _, _>::extend_prover(&AlgebraProverExt, modular, inventory)?;
476 }
477 if let Some(fp2) = &config.fp2 {
478 VmProverExtension::<E, _, _>::extend_prover(&AlgebraProverExt, fp2, inventory)?;
479 }
480 if let Some(pairing) = &config.pairing {
481 VmProverExtension::<E, _, _>::extend_prover(&PairingProverExt, pairing, inventory)?;
482 }
483 if let Some(ecc) = &config.ecc {
484 VmProverExtension::<E, _, _>::extend_prover(&EccProverExt, ecc, inventory)?;
485 }
486 if let Some(deferral) = &config.deferral {
487 VmProverExtension::<E, _, _>::extend_prover(&DeferralProverExt, deferral, inventory)?;
488 }
489 Ok(chip_complex)
490 }
491}
492
493impl InitFileGenerator for SdkVmConfig {
496 fn generate_init_file_contents(&self) -> Option<String> {
497 self.to_inner().generate_init_file_contents()
498 }
499}
500impl InitFileGenerator for SdkVmConfigInner {
501 fn generate_init_file_contents(&self) -> Option<String> {
502 if self.modular.is_some() || self.fp2.is_some() || self.ecc.is_some() {
503 let mut contents = String::new();
504 contents.push_str(
505 "// This file is automatically generated by cargo openvm. Do not rename or edit.\n",
506 );
507
508 if let Some(modular_config) = &self.modular {
509 contents.push_str(&modular_config.generate_moduli_init());
510 contents.push('\n');
511 }
512
513 if let Some(fp2_config) = &self.fp2 {
514 assert!(
515 self.modular.is_some(),
516 "ModularExtension is required for Fp2Extension"
517 );
518 let modular_config = self.modular.as_ref().unwrap();
519 contents.push_str(&fp2_config.generate_complex_init(modular_config));
520 contents.push('\n');
521 }
522
523 if let Some(ecc_config) = &self.ecc {
524 contents.push_str(&ecc_config.generate_sw_init());
525 contents.push('\n');
526 }
527
528 Some(contents)
529 } else {
530 None
531 }
532 }
533}
534
535#[derive(Clone, Debug, Default, Serialize, Deserialize)]
536pub struct SdkSystemConfig {
537 pub config: SystemConfig,
538}
539
540impl InitFileGenerator for SdkSystemConfig {}
542
543impl From<SystemConfig> for SdkSystemConfig {
544 fn from(config: SystemConfig) -> Self {
545 Self { config }
546 }
547}
548
549#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
552pub struct UnitStruct {}
553
554impl From<Rv32I> for UnitStruct {
555 fn from(_: Rv32I) -> Self {
556 UnitStruct {}
557 }
558}
559
560impl From<Rv32Io> for UnitStruct {
561 fn from(_: Rv32Io) -> Self {
562 UnitStruct {}
563 }
564}
565
566impl From<Keccak256> for UnitStruct {
567 fn from(_: Keccak256) -> Self {
568 UnitStruct {}
569 }
570}
571
572impl From<Sha2> for UnitStruct {
573 fn from(_: Sha2) -> Self {
574 UnitStruct {}
575 }
576}
577
578#[derive(Deserialize)]
579struct SdkVmConfigWithDefaultDeser {
580 #[serde(default)]
581 pub system: SdkSystemConfig,
582
583 pub rv32i: Option<UnitStruct>,
584 pub io: Option<UnitStruct>,
585 pub keccak: Option<UnitStruct>,
586 pub sha2: Option<UnitStruct>,
587
588 pub rv32m: Option<Rv32M>,
589 pub bigint: Option<Int256>,
590 pub modular: Option<ModularExtension>,
591 pub fp2: Option<Fp2Extension>,
592 pub pairing: Option<PairingExtension>,
593 pub ecc: Option<WeierstrassExtension>,
594
595 pub deferral: Option<DeferralConfig>,
596}
597
598impl From<SdkVmConfigWithDefaultDeser> for SdkVmConfig {
599 fn from(config: SdkVmConfigWithDefaultDeser) -> Self {
600 let ret = Self {
601 system: config.system,
602 rv32i: config.rv32i,
603 io: config.io,
604 keccak: config.keccak,
605 sha2: config.sha2,
606 rv32m: config.rv32m,
607 bigint: config.bigint,
608 modular: config.modular,
609 fp2: config.fp2,
610 pairing: config.pairing,
611 ecc: config.ecc,
612 deferral: config.deferral,
613 };
614 ret.optimize()
615 }
616}