openvm_sdk/config/
global.rs

1use bon::Builder;
2use openvm_algebra_circuit::{
3    AlgebraCpuProverExt, Fp2Extension, Fp2ExtensionExecutor, ModularExtension,
4    ModularExtensionExecutor,
5};
6use openvm_algebra_transpiler::{Fp2TranspilerExtension, ModularTranspilerExtension};
7use openvm_bigint_circuit::{Int256, Int256CpuProverExt, Int256Executor};
8use openvm_bigint_transpiler::Int256TranspilerExtension;
9use openvm_circuit::{
10    arch::{instructions::NATIVE_AS, *},
11    derive::VmConfig,
12    system::{SystemChipInventory, SystemCpuBuilder, SystemExecutor},
13};
14use openvm_ecc_circuit::{
15    EccCpuProverExt, WeierstrassExtension, WeierstrassExtensionExecutor, P256_CONFIG,
16    SECP256K1_CONFIG,
17};
18use openvm_ecc_transpiler::EccTranspilerExtension;
19use openvm_keccak256_circuit::{Keccak256, Keccak256CpuProverExt, Keccak256Executor};
20use openvm_keccak256_transpiler::Keccak256TranspilerExtension;
21use openvm_native_circuit::{
22    CastFExtension, CastFExtensionExecutor, Native, NativeCpuProverExt, NativeExecutor,
23};
24use openvm_native_transpiler::LongFormTranspilerExtension;
25use openvm_pairing_circuit::{
26    PairingCurve, PairingExtension, PairingExtensionExecutor, PairingProverExt,
27    BLS12_381_COMPLEX_STRUCT_NAME, BN254_COMPLEX_STRUCT_NAME,
28};
29use openvm_pairing_transpiler::PairingTranspilerExtension;
30use openvm_rv32im_circuit::{
31    Rv32I, Rv32IExecutor, Rv32ImCpuProverExt, Rv32Io, Rv32IoExecutor, Rv32M, Rv32MExecutor,
32};
33use openvm_rv32im_transpiler::{
34    Rv32ITranspilerExtension, Rv32IoTranspilerExtension, Rv32MTranspilerExtension,
35};
36use openvm_sha256_circuit::{Sha256, Sha256Executor, Sha2CpuProverExt};
37use openvm_sha256_transpiler::Sha256TranspilerExtension;
38use openvm_stark_backend::{
39    config::{StarkGenericConfig, Val},
40    engine::StarkEngine,
41    p3_field::{Field, PrimeField32},
42    prover::cpu::{CpuBackend, CpuDevice},
43};
44use openvm_transpiler::transpiler::Transpiler;
45use serde::{Deserialize, Serialize};
46cfg_if::cfg_if! {
47    if #[cfg(feature = "cuda")] {
48        use openvm_algebra_circuit::AlgebraProverExt;
49        use openvm_bigint_circuit::Int256GpuProverExt;
50        use openvm_circuit::system::cuda::{extensions::SystemGpuBuilder, SystemChipInventoryGPU};
51        use openvm_cuda_backend::{
52            engine::GpuBabyBearPoseidon2Engine, prover_backend::GpuBackend, types::SC,
53        };
54        use openvm_ecc_circuit::EccProverExt;
55        use openvm_keccak256_circuit::Keccak256GpuProverExt;
56        use openvm_native_circuit::NativeGpuProverExt;
57        use openvm_rv32im_circuit::Rv32ImGpuProverExt;
58        use openvm_sha256_circuit::Sha256GpuProverExt;
59        pub use SdkVmGpuBuilder as SdkVmBuilder;
60    } else {
61        pub use SdkVmCpuBuilder as SdkVmBuilder;
62    }
63}
64
65use super::AppFriParams;
66use crate::{
67    config::{AppConfig, TranspilerConfig},
68    F,
69};
70
71/// The recommended way to construct [SdkVmConfig] is using [SdkVmConfig::from_toml].
72///
73/// For construction without reliance on deserialization, you can use [SdkVmConfigBuilder], which
74/// follows a builder pattern. After calling [SdkVmConfigBuilder::build], call
75/// [SdkVmConfig::optimize] to apply some default optimizations to built configuration for best
76/// performance.
77#[derive(Builder, Clone, Debug, Serialize, Deserialize)]
78#[serde(from = "SdkVmConfigWithDefaultDeser")]
79pub struct SdkVmConfig {
80    pub system: SdkSystemConfig,
81    pub rv32i: Option<UnitStruct>,
82    pub io: Option<UnitStruct>,
83    pub keccak: Option<UnitStruct>,
84    pub sha256: Option<UnitStruct>,
85    pub native: Option<UnitStruct>,
86    pub castf: Option<UnitStruct>,
87
88    /// NOTE: if enabling this together with the [Int256] extension, you should set the `rv32m`
89    /// field to have the same `range_tuple_checker_sizes` as the `bigint` field for best
90    /// performance.
91    pub rv32m: Option<Rv32M>,
92    /// NOTE: if enabling this together with the [Rv32M] extension, you should set the `rv32m`
93    /// field to have the same `range_tuple_checker_sizes` as the `bigint` field for best
94    /// performance.
95    pub bigint: Option<Int256>,
96    pub modular: Option<ModularExtension>,
97    pub fp2: Option<Fp2Extension>,
98    pub pairing: Option<PairingExtension>,
99    pub ecc: Option<WeierstrassExtension>,
100}
101
102impl SdkVmConfig {
103    /// Standard configuration with a set of default VM extensions loaded.
104    ///
105    /// **Note**: To use this configuration, your `openvm.toml` must match, including the order of
106    /// the moduli and elliptic curve parameters of the respective extensions:
107    /// The `app_vm_config` field of your `openvm.toml` must exactly match the following:
108    ///
109    /// ```toml
110    #[doc = include_str!("openvm_standard.toml")]
111    /// ```
112    pub fn standard() -> SdkVmConfig {
113        let bn_config = PairingCurve::Bn254.curve_config();
114        let bls_config = PairingCurve::Bls12_381.curve_config();
115        SdkVmConfig::builder()
116            .system(Default::default())
117            .rv32i(Default::default())
118            .rv32m(Default::default())
119            .io(Default::default())
120            .keccak(Default::default())
121            .sha256(Default::default())
122            .bigint(Default::default())
123            .modular(ModularExtension::new(vec![
124                bn_config.modulus.clone(),
125                bn_config.scalar.clone(),
126                SECP256K1_CONFIG.modulus.clone(),
127                SECP256K1_CONFIG.scalar.clone(),
128                P256_CONFIG.modulus.clone(),
129                P256_CONFIG.scalar.clone(),
130                bls_config.modulus.clone(),
131                bls_config.scalar.clone(),
132            ]))
133            .fp2(Fp2Extension::new(vec![
134                (
135                    BN254_COMPLEX_STRUCT_NAME.to_string(),
136                    bn_config.modulus.clone(),
137                ),
138                (
139                    BLS12_381_COMPLEX_STRUCT_NAME.to_string(),
140                    bls_config.modulus.clone(),
141                ),
142            ]))
143            .ecc(WeierstrassExtension::new(vec![
144                bn_config.clone(),
145                SECP256K1_CONFIG.clone(),
146                P256_CONFIG.clone(),
147                bls_config.clone(),
148            ]))
149            .pairing(PairingExtension::new(vec![
150                PairingCurve::Bn254,
151                PairingCurve::Bls12_381,
152            ]))
153            .build()
154            .optimize()
155    }
156
157    /// Configuration with RISC-V RV32IM and IO VM extensions loaded.
158    ///
159    /// **Note**: To use this configuration, your `openvm.toml` must exactly match the following:
160    ///
161    /// ```toml
162    #[doc = include_str!("openvm_riscv32.toml")]
163    /// ```
164    pub fn riscv32() -> Self {
165        SdkVmConfig::builder()
166            .system(Default::default())
167            .rv32i(Default::default())
168            .rv32m(Default::default())
169            .io(Default::default())
170            .build()
171            .optimize()
172    }
173
174    /// `openvm_toml` should be the TOML string read from an openvm.toml file.
175    pub fn from_toml(openvm_toml: &str) -> Result<AppConfig<Self>, toml::de::Error> {
176        toml::from_str(openvm_toml)
177    }
178}
179
180impl AppConfig<SdkVmConfig> {
181    pub fn standard() -> Self {
182        Self::new(AppFriParams::default().fri_params, SdkVmConfig::standard())
183    }
184
185    pub fn riscv32() -> Self {
186        Self::new(AppFriParams::default().fri_params, SdkVmConfig::riscv32())
187    }
188}
189
190impl TranspilerConfig<F> for SdkVmConfig {
191    fn transpiler(&self) -> Transpiler<F> {
192        let mut transpiler = Transpiler::default();
193        if self.rv32i.is_some() {
194            transpiler = transpiler.with_extension(Rv32ITranspilerExtension);
195        }
196        if self.io.is_some() {
197            transpiler = transpiler.with_extension(Rv32IoTranspilerExtension);
198        }
199        if self.keccak.is_some() {
200            transpiler = transpiler.with_extension(Keccak256TranspilerExtension);
201        }
202        if self.sha256.is_some() {
203            transpiler = transpiler.with_extension(Sha256TranspilerExtension);
204        }
205        if self.native.is_some() {
206            transpiler = transpiler.with_extension(LongFormTranspilerExtension);
207        }
208        if self.rv32m.is_some() {
209            transpiler = transpiler.with_extension(Rv32MTranspilerExtension);
210        }
211        if self.bigint.is_some() {
212            transpiler = transpiler.with_extension(Int256TranspilerExtension);
213        }
214        if self.modular.is_some() {
215            transpiler = transpiler.with_extension(ModularTranspilerExtension);
216        }
217        if self.fp2.is_some() {
218            transpiler = transpiler.with_extension(Fp2TranspilerExtension);
219        }
220        if self.pairing.is_some() {
221            transpiler = transpiler.with_extension(PairingTranspilerExtension);
222        }
223        if self.ecc.is_some() {
224            transpiler = transpiler.with_extension(EccTranspilerExtension);
225        }
226        transpiler
227    }
228}
229
230impl AsRef<SystemConfig> for SdkVmConfig {
231    fn as_ref(&self) -> &SystemConfig {
232        &self.system.config
233    }
234}
235
236impl AsMut<SystemConfig> for SdkVmConfig {
237    fn as_mut(&mut self) -> &mut SystemConfig {
238        &mut self.system.config
239    }
240}
241
242impl SdkVmConfig {
243    pub fn optimize(mut self) -> Self {
244        self.apply_optimizations();
245        self
246    }
247
248    /// Apply small optimizations to the configuration.
249    pub fn apply_optimizations(&mut self) {
250        if self.native.is_none() && self.castf.is_none() {
251            // There should be no need to write to native address space if Native extension and
252            // CastF extension are not enabled.
253            self.system.config.memory_config.addr_spaces[NATIVE_AS as usize].num_cells = 0;
254        }
255        let rv32m = self.rv32m.as_mut();
256        let bigint = self.bigint.as_mut();
257        if let (Some(bigint), Some(rv32m)) = (bigint, rv32m) {
258            rv32m.range_tuple_checker_sizes[0] =
259                rv32m.range_tuple_checker_sizes[0].max(bigint.range_tuple_checker_sizes[0]);
260            rv32m.range_tuple_checker_sizes[1] =
261                rv32m.range_tuple_checker_sizes[1].max(bigint.range_tuple_checker_sizes[1]);
262            bigint.range_tuple_checker_sizes = rv32m.range_tuple_checker_sizes;
263        }
264    }
265
266    pub fn to_inner(&self) -> SdkVmConfigInner {
267        let config = self.clone().optimize();
268        let system = config.system.config.clone();
269        let rv32i = config.rv32i.map(|_| Rv32I);
270        let io = config.io.map(|_| Rv32Io);
271        let keccak = config.keccak.map(|_| Keccak256);
272        let sha256 = config.sha256.map(|_| Sha256);
273        let native = config.native.map(|_| Native);
274        let castf = config.castf.map(|_| CastFExtension);
275        let rv32m = config.rv32m;
276        let bigint = config.bigint;
277        let modular = config.modular.clone();
278        let fp2 = config.fp2.clone();
279        let pairing = config.pairing.clone();
280        let ecc = config.ecc.clone();
281
282        SdkVmConfigInner {
283            system,
284            rv32i,
285            io,
286            keccak,
287            sha256,
288            native,
289            castf,
290            rv32m,
291            bigint,
292            modular,
293            fp2,
294            pairing,
295            ecc,
296        }
297    }
298}
299
300// ======================= Implementation of VmConfig and VmBuilder ====================
301
302/// SDK CPU VmBuilder
303#[derive(Copy, Clone, Default)]
304pub struct SdkVmCpuBuilder;
305
306/// Internal struct to use for the VmConfig derive macro.
307/// Can be obtained via [`SdkVmConfig::to_inner`].
308#[derive(Clone, Debug, VmConfig, Serialize, Deserialize)]
309pub struct SdkVmConfigInner {
310    #[config(executor = "SystemExecutor<F>")]
311    pub system: SystemConfig,
312    #[extension(executor = "Rv32IExecutor")]
313    pub rv32i: Option<Rv32I>,
314    #[extension(executor = "Rv32IoExecutor")]
315    pub io: Option<Rv32Io>,
316    #[extension(executor = "Keccak256Executor")]
317    pub keccak: Option<Keccak256>,
318    #[extension(executor = "Sha256Executor")]
319    pub sha256: Option<Sha256>,
320    #[extension(executor = "NativeExecutor<F>")]
321    pub native: Option<Native>,
322    #[extension(executor = "CastFExtensionExecutor")]
323    pub castf: Option<CastFExtension>,
324
325    #[extension(executor = "Rv32MExecutor")]
326    pub rv32m: Option<Rv32M>,
327    #[extension(executor = "Int256Executor")]
328    pub bigint: Option<Int256>,
329    #[extension(executor = "ModularExtensionExecutor")]
330    pub modular: Option<ModularExtension>,
331    #[extension(executor = "Fp2ExtensionExecutor")]
332    pub fp2: Option<Fp2Extension>,
333    #[extension(executor = "PairingExtensionExecutor<F>")]
334    pub pairing: Option<PairingExtension>,
335    #[extension(executor = "WeierstrassExtensionExecutor")]
336    pub ecc: Option<WeierstrassExtension>,
337}
338
339// Generated by macro
340pub type SdkVmConfigExecutor<F> = SdkVmConfigInnerExecutor<F>;
341
342impl<F: Field> VmExecutionConfig<F> for SdkVmConfig
343where
344    SdkVmConfigInner: VmExecutionConfig<F>,
345{
346    type Executor = <SdkVmConfigInner as VmExecutionConfig<F>>::Executor;
347
348    fn create_executors(
349        &self,
350    ) -> Result<ExecutorInventory<Self::Executor>, ExecutorInventoryError> {
351        self.to_inner().create_executors()
352    }
353}
354
355impl<SC: StarkGenericConfig> VmCircuitConfig<SC> for SdkVmConfig
356where
357    SdkVmConfigInner: VmCircuitConfig<SC>,
358{
359    fn create_airs(&self) -> Result<AirInventory<SC>, AirInventoryError> {
360        self.to_inner().create_airs()
361    }
362}
363
364impl<E, SC> VmBuilder<E> for SdkVmCpuBuilder
365where
366    SC: StarkGenericConfig,
367    E: StarkEngine<SC = SC, PB = CpuBackend<SC>, PD = CpuDevice<SC>>,
368    Val<SC>: PrimeField32,
369{
370    type VmConfig = SdkVmConfig;
371    type SystemChipInventory = SystemChipInventory<SC>;
372    type RecordArena = MatrixRecordArena<Val<SC>>;
373
374    fn create_chip_complex(
375        &self,
376        config: &SdkVmConfig,
377        circuit: AirInventory<SC>,
378    ) -> Result<
379        VmChipComplex<SC, Self::RecordArena, E::PB, Self::SystemChipInventory>,
380        ChipInventoryError,
381    > {
382        let config = config.to_inner();
383        let mut chip_complex =
384            VmBuilder::<E>::create_chip_complex(&SystemCpuBuilder, &config.system, circuit)?;
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(sha256) = &config.sha256 {
396            VmProverExtension::<E, _, _>::extend_prover(&Sha2CpuProverExt, sha256, inventory)?;
397        }
398        if let Some(native) = &config.native {
399            VmProverExtension::<E, _, _>::extend_prover(&NativeCpuProverExt, native, inventory)?;
400        }
401        if let Some(castf) = &config.castf {
402            VmProverExtension::<E, _, _>::extend_prover(&NativeCpuProverExt, castf, inventory)?;
403        }
404        if let Some(rv32m) = &config.rv32m {
405            VmProverExtension::<E, _, _>::extend_prover(&Rv32ImCpuProverExt, rv32m, inventory)?;
406        }
407        if let Some(bigint) = &config.bigint {
408            VmProverExtension::<E, _, _>::extend_prover(&Int256CpuProverExt, bigint, inventory)?;
409        }
410        if let Some(modular) = &config.modular {
411            VmProverExtension::<E, _, _>::extend_prover(&AlgebraCpuProverExt, modular, inventory)?;
412        }
413        if let Some(fp2) = &config.fp2 {
414            VmProverExtension::<E, _, _>::extend_prover(&AlgebraCpuProverExt, fp2, inventory)?;
415        }
416        if let Some(pairing) = &config.pairing {
417            VmProverExtension::<E, _, _>::extend_prover(&PairingProverExt, pairing, inventory)?;
418        }
419        if let Some(ecc) = &config.ecc {
420            VmProverExtension::<E, _, _>::extend_prover(&EccCpuProverExt, ecc, inventory)?;
421        }
422        Ok(chip_complex)
423    }
424}
425
426#[cfg(feature = "cuda")]
427#[derive(Copy, Clone, Default)]
428pub struct SdkVmGpuBuilder;
429
430#[cfg(feature = "cuda")]
431impl VmBuilder<GpuBabyBearPoseidon2Engine> for SdkVmGpuBuilder {
432    type VmConfig = SdkVmConfig;
433    type SystemChipInventory = SystemChipInventoryGPU;
434    type RecordArena = DenseRecordArena;
435
436    fn create_chip_complex(
437        &self,
438        config: &SdkVmConfig,
439        circuit: AirInventory<SC>,
440    ) -> Result<
441        VmChipComplex<SC, Self::RecordArena, GpuBackend, Self::SystemChipInventory>,
442        ChipInventoryError,
443    > {
444        type E = GpuBabyBearPoseidon2Engine;
445
446        let config = config.to_inner();
447        let mut chip_complex =
448            VmBuilder::<E>::create_chip_complex(&SystemGpuBuilder, &config.system, circuit)?;
449        let inventory = &mut chip_complex.inventory;
450        if let Some(rv32i) = &config.rv32i {
451            VmProverExtension::<E, _, _>::extend_prover(&Rv32ImGpuProverExt, rv32i, inventory)?;
452        }
453        if let Some(io) = &config.io {
454            VmProverExtension::<E, _, _>::extend_prover(&Rv32ImGpuProverExt, io, inventory)?;
455        }
456        if let Some(keccak) = &config.keccak {
457            VmProverExtension::<E, _, _>::extend_prover(&Keccak256GpuProverExt, keccak, inventory)?;
458        }
459        if let Some(sha256) = &config.sha256 {
460            VmProverExtension::<E, _, _>::extend_prover(&Sha256GpuProverExt, sha256, inventory)?;
461        }
462        if let Some(native) = &config.native {
463            VmProverExtension::<E, _, _>::extend_prover(&NativeGpuProverExt, native, inventory)?;
464        }
465        if let Some(castf) = &config.castf {
466            VmProverExtension::<E, _, _>::extend_prover(&NativeGpuProverExt, castf, 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        Ok(chip_complex)
487    }
488}
489
490// ======================= Boilerplate ====================
491
492impl InitFileGenerator for SdkVmConfig {
493    fn generate_init_file_contents(&self) -> Option<String> {
494        self.to_inner().generate_init_file_contents()
495    }
496}
497impl InitFileGenerator for SdkVmConfigInner {
498    fn generate_init_file_contents(&self) -> Option<String> {
499        if self.modular.is_some() || self.fp2.is_some() || self.ecc.is_some() {
500            let mut contents = String::new();
501            contents.push_str(
502                "// This file is automatically generated by cargo openvm. Do not rename or edit.\n",
503            );
504
505            if let Some(modular_config) = &self.modular {
506                contents.push_str(&modular_config.generate_moduli_init());
507                contents.push('\n');
508            }
509
510            if let Some(fp2_config) = &self.fp2 {
511                assert!(
512                    self.modular.is_some(),
513                    "ModularExtension is required for Fp2Extension"
514                );
515                let modular_config = self.modular.as_ref().unwrap();
516                contents.push_str(&fp2_config.generate_complex_init(modular_config));
517                contents.push('\n');
518            }
519
520            if let Some(ecc_config) = &self.ecc {
521                contents.push_str(&ecc_config.generate_sw_init());
522                contents.push('\n');
523            }
524
525            Some(contents)
526        } else {
527            None
528        }
529    }
530}
531
532#[derive(Clone, Debug, Default, Serialize, Deserialize)]
533pub struct SdkSystemConfig {
534    pub config: SystemConfig,
535}
536
537// Default implementation uses no init file
538impl InitFileGenerator for SdkSystemConfig {}
539
540impl From<SystemConfig> for SdkSystemConfig {
541    fn from(config: SystemConfig) -> Self {
542        Self { config }
543    }
544}
545
546/// A struct that is used to represent a unit struct in the config, used for
547/// serialization and deserialization.
548#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
549pub struct UnitStruct {}
550
551impl From<Rv32I> for UnitStruct {
552    fn from(_: Rv32I) -> Self {
553        UnitStruct {}
554    }
555}
556
557impl From<Rv32Io> for UnitStruct {
558    fn from(_: Rv32Io) -> Self {
559        UnitStruct {}
560    }
561}
562
563impl From<Keccak256> for UnitStruct {
564    fn from(_: Keccak256) -> Self {
565        UnitStruct {}
566    }
567}
568
569impl From<Sha256> for UnitStruct {
570    fn from(_: Sha256) -> Self {
571        UnitStruct {}
572    }
573}
574
575impl From<Native> for UnitStruct {
576    fn from(_: Native) -> Self {
577        UnitStruct {}
578    }
579}
580
581impl From<CastFExtension> for UnitStruct {
582    fn from(_: CastFExtension) -> Self {
583        UnitStruct {}
584    }
585}
586
587#[derive(Deserialize)]
588struct SdkVmConfigWithDefaultDeser {
589    #[serde(default)]
590    pub system: SdkSystemConfig,
591
592    pub rv32i: Option<UnitStruct>,
593    pub io: Option<UnitStruct>,
594    pub keccak: Option<UnitStruct>,
595    pub sha256: Option<UnitStruct>,
596    pub native: Option<UnitStruct>,
597    pub castf: Option<UnitStruct>,
598
599    pub rv32m: Option<Rv32M>,
600    pub bigint: Option<Int256>,
601    pub modular: Option<ModularExtension>,
602    pub fp2: Option<Fp2Extension>,
603    pub pairing: Option<PairingExtension>,
604    pub ecc: Option<WeierstrassExtension>,
605}
606
607impl From<SdkVmConfigWithDefaultDeser> for SdkVmConfig {
608    fn from(config: SdkVmConfigWithDefaultDeser) -> Self {
609        let ret = Self {
610            system: config.system,
611            rv32i: config.rv32i,
612            io: config.io,
613            keccak: config.keccak,
614            sha256: config.sha256,
615            native: config.native,
616            castf: config.castf,
617            rv32m: config.rv32m,
618            bigint: config.bigint,
619            modular: config.modular,
620            fp2: config.fp2,
621            pairing: config.pairing,
622            ecc: config.ecc,
623        };
624        ret.optimize()
625    }
626}
627
628#[cfg(test)]
629mod tests {
630    use itertools::zip_eq;
631
632    use super::*;
633
634    #[test]
635    fn test_app_config_consistency() {
636        let toml_config = SdkVmConfig::from_toml(include_str!("./openvm_standard.toml")).unwrap();
637        for (line1, line2) in zip_eq(
638            toml::to_string_pretty(&AppConfig::standard())
639                .unwrap()
640                .lines(),
641            toml::to_string_pretty(&toml_config).unwrap().lines(),
642        ) {
643            assert_eq!(line1, line2);
644        }
645
646        let toml_config = SdkVmConfig::from_toml(include_str!("./openvm_riscv32.toml")).unwrap();
647        for (line1, line2) in zip_eq(
648            toml::to_string_pretty(&AppConfig::riscv32())
649                .unwrap()
650                .lines(),
651            toml::to_string_pretty(&toml_config).unwrap().lines(),
652        ) {
653            assert_eq!(line1, line2);
654        }
655    }
656}