cairo_vm/types/
layout.rs

1use crate::{types::layout_name::LayoutName, vm::errors::runner_errors::RunnerError};
2
3use super::{
4    builtin_name::BuiltinName,
5    instance_definitions::{
6        builtins_instance_def::BuiltinsInstanceDef,
7        diluted_pool_instance_def::DilutedPoolInstanceDef,
8    },
9};
10
11pub(crate) const DEFAULT_MEMORY_UNITS_PER_STEP: u32 = 8;
12pub(crate) const DEFAULT_CPU_COMPONENT_STEP: u32 = 1;
13
14use serde::{Deserialize, Deserializer, Serialize};
15
16#[derive(Serialize, Debug)]
17pub struct CairoLayout {
18    pub(crate) name: LayoutName,
19    pub(crate) cpu_component_step: u32,
20    pub(crate) rc_units: u32,
21    pub(crate) memory_units_per_step: u32,
22    pub(crate) builtins: BuiltinsInstanceDef,
23    pub(crate) public_memory_fraction: u32,
24    pub(crate) diluted_pool_instance_def: Option<DilutedPoolInstanceDef>,
25}
26
27impl CairoLayout {
28    pub(crate) fn plain_instance() -> CairoLayout {
29        CairoLayout {
30            name: LayoutName::plain,
31            rc_units: 16,
32            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
33            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
34            builtins: BuiltinsInstanceDef::plain(),
35            public_memory_fraction: 4,
36            diluted_pool_instance_def: None,
37        }
38    }
39
40    pub(crate) fn small_instance() -> CairoLayout {
41        CairoLayout {
42            name: LayoutName::small,
43            rc_units: 16,
44            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
45            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
46            builtins: BuiltinsInstanceDef::small(),
47            public_memory_fraction: 4,
48            diluted_pool_instance_def: None,
49        }
50    }
51
52    pub(crate) fn dex_instance() -> CairoLayout {
53        CairoLayout {
54            name: LayoutName::dex,
55            rc_units: 4,
56            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
57            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
58            builtins: BuiltinsInstanceDef::dex(),
59            public_memory_fraction: 4,
60            diluted_pool_instance_def: None,
61        }
62    }
63
64    pub(crate) fn recursive_instance() -> CairoLayout {
65        CairoLayout {
66            name: LayoutName::recursive,
67            rc_units: 4,
68            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
69            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
70            builtins: BuiltinsInstanceDef::recursive(),
71            public_memory_fraction: 8,
72            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
73        }
74    }
75
76    pub(crate) fn starknet_instance() -> CairoLayout {
77        CairoLayout {
78            name: LayoutName::starknet,
79            rc_units: 4,
80            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
81            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
82            builtins: BuiltinsInstanceDef::starknet(),
83            public_memory_fraction: 8,
84            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::new(2, 4, 16)),
85        }
86    }
87
88    pub(crate) fn starknet_with_keccak_instance() -> CairoLayout {
89        CairoLayout {
90            name: LayoutName::starknet_with_keccak,
91            rc_units: 4,
92            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
93            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
94            builtins: BuiltinsInstanceDef::starknet_with_keccak(),
95            public_memory_fraction: 8,
96            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
97        }
98    }
99
100    pub(crate) fn recursive_large_output_instance() -> CairoLayout {
101        CairoLayout {
102            name: LayoutName::recursive_large_output,
103            rc_units: 4,
104            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
105            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
106            builtins: BuiltinsInstanceDef::recursive_large_output(),
107            public_memory_fraction: 8,
108            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
109        }
110    }
111    pub(crate) fn recursive_with_poseidon() -> CairoLayout {
112        CairoLayout {
113            name: LayoutName::recursive_with_poseidon,
114            rc_units: 4,
115            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
116            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
117            builtins: BuiltinsInstanceDef::recursive_with_poseidon(),
118            public_memory_fraction: 8,
119            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::new(8, 4, 16)),
120        }
121    }
122
123    pub(crate) fn all_cairo_instance() -> CairoLayout {
124        CairoLayout {
125            name: LayoutName::all_cairo,
126            rc_units: 4,
127            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
128            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
129            builtins: BuiltinsInstanceDef::all_cairo(),
130            public_memory_fraction: 8,
131            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
132        }
133    }
134
135    pub(crate) fn all_cairo_stwo_instance() -> CairoLayout {
136        CairoLayout {
137            name: LayoutName::all_cairo_stwo,
138            rc_units: 4,
139            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
140            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
141            builtins: BuiltinsInstanceDef::all_cairo_stwo(),
142            public_memory_fraction: 8,
143            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
144        }
145    }
146
147    pub(crate) fn all_solidity_instance() -> CairoLayout {
148        CairoLayout {
149            name: LayoutName::all_solidity,
150            rc_units: 8,
151            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
152            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
153            builtins: BuiltinsInstanceDef::all_solidity(),
154            public_memory_fraction: 8,
155            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
156        }
157    }
158
159    pub(crate) fn dynamic_instance(params: CairoLayoutParams) -> CairoLayout {
160        CairoLayout {
161            name: LayoutName::dynamic,
162            rc_units: params.rc_units,
163            cpu_component_step: params.cpu_component_step,
164            memory_units_per_step: params.memory_units_per_step,
165            public_memory_fraction: 8,
166            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::from_log_units_per_step(
167                params.log_diluted_units_per_step,
168            )),
169            builtins: BuiltinsInstanceDef::dynamic(params),
170        }
171    }
172}
173
174#[cfg(feature = "test_utils")]
175use arbitrary::{self, Arbitrary};
176
177#[cfg_attr(feature = "test_utils", derive(Arbitrary))]
178#[derive(Deserialize, Debug, Clone, Default)]
179#[serde(try_from = "RawCairoLayoutParams")]
180pub struct CairoLayoutParams {
181    pub rc_units: u32,
182    pub cpu_component_step: u32,
183    pub memory_units_per_step: u32,
184    pub log_diluted_units_per_step: i32,
185    pub pedersen_ratio: u32,
186    pub range_check_ratio: u32,
187    pub ecdsa_ratio: u32,
188    pub bitwise_ratio: u32,
189    pub ec_op_ratio: u32,
190    pub keccak_ratio: u32,
191    pub poseidon_ratio: u32,
192    pub range_check96_ratio: u32,
193    pub range_check96_ratio_den: u32,
194    pub add_mod_ratio: u32,
195    pub add_mod_ratio_den: u32,
196    pub mul_mod_ratio: u32,
197    pub mul_mod_ratio_den: u32,
198}
199
200impl CairoLayoutParams {
201    #[cfg(feature = "std")]
202    pub fn from_file(params_path: &std::path::Path) -> std::io::Result<Self> {
203        let params_file = std::fs::File::open(params_path)?;
204        let params = serde_json::from_reader(params_file)?;
205        Ok(params)
206    }
207}
208
209// The CairoLayoutParams contains aditional constraints that can't be validated by serde alone.
210// To work around this. we use an aditional structure `RawCairoLayoutParams` that gets deserialized by serde
211// and then its tranformed into `CairoLayoutParams`.
212
213#[derive(Deserialize, Debug, Default, Clone)]
214pub struct RawCairoLayoutParams {
215    pub rc_units: u32,
216    pub cpu_component_step: u32,
217    pub memory_units_per_step: u32,
218    pub log_diluted_units_per_step: i32,
219    #[serde(deserialize_with = "bool_from_int_or_bool")]
220    pub uses_pedersen_builtin: bool,
221    pub pedersen_ratio: u32,
222    #[serde(deserialize_with = "bool_from_int_or_bool")]
223    pub uses_range_check_builtin: bool,
224    pub range_check_ratio: u32,
225    #[serde(deserialize_with = "bool_from_int_or_bool")]
226    pub uses_ecdsa_builtin: bool,
227    pub ecdsa_ratio: u32,
228    #[serde(deserialize_with = "bool_from_int_or_bool")]
229    pub uses_bitwise_builtin: bool,
230    pub bitwise_ratio: u32,
231    #[serde(deserialize_with = "bool_from_int_or_bool")]
232    pub uses_ec_op_builtin: bool,
233    pub ec_op_ratio: u32,
234    #[serde(deserialize_with = "bool_from_int_or_bool")]
235    pub uses_keccak_builtin: bool,
236    pub keccak_ratio: u32,
237    #[serde(deserialize_with = "bool_from_int_or_bool")]
238    pub uses_poseidon_builtin: bool,
239    pub poseidon_ratio: u32,
240    #[serde(deserialize_with = "bool_from_int_or_bool")]
241    pub uses_range_check96_builtin: bool,
242    pub range_check96_ratio: u32,
243    pub range_check96_ratio_den: u32,
244    #[serde(deserialize_with = "bool_from_int_or_bool")]
245    pub uses_add_mod_builtin: bool,
246    pub add_mod_ratio: u32,
247    pub add_mod_ratio_den: u32,
248    #[serde(deserialize_with = "bool_from_int_or_bool")]
249    pub uses_mul_mod_builtin: bool,
250    pub mul_mod_ratio: u32,
251    pub mul_mod_ratio_den: u32,
252}
253
254impl TryFrom<RawCairoLayoutParams> for CairoLayoutParams {
255    type Error = RunnerError;
256
257    fn try_from(value: RawCairoLayoutParams) -> Result<Self, Self::Error> {
258        if !value.uses_pedersen_builtin && value.pedersen_ratio != 0 {
259            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
260                BuiltinName::pedersen,
261            ));
262        }
263        if !value.uses_range_check_builtin && value.range_check_ratio != 0 {
264            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
265                BuiltinName::range_check,
266            ));
267        }
268        if !value.uses_ecdsa_builtin && value.ecdsa_ratio != 0 {
269            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
270                BuiltinName::ecdsa,
271            ));
272        }
273        if !value.uses_bitwise_builtin && value.bitwise_ratio != 0 {
274            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
275                BuiltinName::bitwise,
276            ));
277        }
278        if !value.uses_ec_op_builtin && value.ec_op_ratio != 0 {
279            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
280                BuiltinName::ec_op,
281            ));
282        }
283        if !value.uses_keccak_builtin && value.keccak_ratio != 0 {
284            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
285                BuiltinName::keccak,
286            ));
287        }
288        if !value.uses_poseidon_builtin && value.poseidon_ratio != 0 {
289            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
290                BuiltinName::poseidon,
291            ));
292        }
293        if !value.uses_range_check96_builtin && value.range_check96_ratio != 0 {
294            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
295                BuiltinName::range_check96,
296            ));
297        }
298        if !value.uses_add_mod_builtin && value.add_mod_ratio != 0 {
299            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
300                BuiltinName::add_mod,
301            ));
302        }
303        if !value.uses_mul_mod_builtin && value.mul_mod_ratio != 0 {
304            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
305                BuiltinName::mul_mod,
306            ));
307        }
308
309        Ok(CairoLayoutParams {
310            rc_units: value.rc_units,
311            log_diluted_units_per_step: value.log_diluted_units_per_step,
312            cpu_component_step: value.cpu_component_step,
313            memory_units_per_step: value.memory_units_per_step,
314            range_check96_ratio_den: value.range_check96_ratio_den,
315            mul_mod_ratio_den: value.mul_mod_ratio_den,
316            add_mod_ratio_den: value.add_mod_ratio_den,
317            pedersen_ratio: value.pedersen_ratio,
318            range_check_ratio: value.range_check_ratio,
319            ecdsa_ratio: value.ecdsa_ratio,
320            bitwise_ratio: value.bitwise_ratio,
321            ec_op_ratio: value.ec_op_ratio,
322            keccak_ratio: value.keccak_ratio,
323            poseidon_ratio: value.poseidon_ratio,
324            range_check96_ratio: value.range_check96_ratio,
325            add_mod_ratio: value.add_mod_ratio,
326            mul_mod_ratio: value.mul_mod_ratio,
327        })
328    }
329}
330
331fn bool_from_int_or_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
332where
333    D: Deserializer<'de>,
334{
335    #[derive(Deserialize)]
336    #[serde(untagged)]
337    enum IntOrBool {
338        Int(i64),
339        Boolean(bool),
340    }
341
342    match IntOrBool::deserialize(deserializer)? {
343        IntOrBool::Int(0) => Ok(false),
344        IntOrBool::Int(_) => Ok(true),
345        IntOrBool::Boolean(v) => Ok(v),
346    }
347}
348
349#[cfg(test)]
350mod tests {
351    use super::*;
352    #[cfg(feature = "mod_builtin")]
353    use crate::types::instance_definitions::mod_instance_def::ModInstanceDef;
354
355    use crate::types::instance_definitions::{
356        bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef,
357        ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef,
358        pedersen_instance_def::PedersenInstanceDef, poseidon_instance_def::PoseidonInstanceDef,
359        range_check_instance_def::RangeCheckInstanceDef, LowRatio,
360    };
361
362    #[cfg(target_arch = "wasm32")]
363    use wasm_bindgen_test::*;
364
365    #[test]
366    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
367    fn get_plain_instance() {
368        let layout = CairoLayout::plain_instance();
369        let builtins = BuiltinsInstanceDef::plain();
370        assert_eq!(layout.name, LayoutName::plain);
371        assert_eq!(layout.rc_units, 16);
372        assert_eq!(layout.builtins, builtins);
373        assert_eq!(layout.public_memory_fraction, 4);
374        assert_eq!(layout.diluted_pool_instance_def, None);
375    }
376
377    #[test]
378    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
379    fn get_small_instance() {
380        let layout = CairoLayout::small_instance();
381        let builtins = BuiltinsInstanceDef::small();
382        assert_eq!(layout.name, LayoutName::small);
383        assert_eq!(layout.rc_units, 16);
384        assert_eq!(layout.builtins, builtins);
385        assert_eq!(layout.public_memory_fraction, 4);
386        assert_eq!(layout.diluted_pool_instance_def, None);
387    }
388
389    #[test]
390    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
391    fn get_dex_instance() {
392        let layout = CairoLayout::dex_instance();
393        let builtins = BuiltinsInstanceDef::dex();
394        assert_eq!(layout.name, LayoutName::dex);
395        assert_eq!(layout.rc_units, 4);
396        assert_eq!(layout.builtins, builtins);
397        assert_eq!(layout.public_memory_fraction, 4);
398        assert_eq!(layout.diluted_pool_instance_def, None);
399    }
400
401    #[test]
402    fn get_recursive_instance() {
403        let layout = CairoLayout::recursive_instance();
404        let builtins = BuiltinsInstanceDef::recursive();
405        assert_eq!(layout.name, LayoutName::recursive);
406        assert_eq!(layout.rc_units, 4);
407        assert_eq!(layout.builtins, builtins);
408        assert_eq!(layout.public_memory_fraction, 8);
409        assert_eq!(
410            layout.diluted_pool_instance_def,
411            Some(DilutedPoolInstanceDef::default())
412        );
413    }
414
415    #[test]
416    fn get_starknet_instance() {
417        let layout = CairoLayout::starknet_instance();
418        let builtins = BuiltinsInstanceDef::starknet();
419        assert_eq!(layout.name, LayoutName::starknet);
420        assert_eq!(layout.rc_units, 4);
421        assert_eq!(layout.builtins, builtins);
422        assert_eq!(layout.public_memory_fraction, 8);
423        assert_eq!(
424            layout.diluted_pool_instance_def,
425            Some(DilutedPoolInstanceDef::new(2, 4, 16))
426        );
427    }
428
429    #[test]
430    fn get_starknet_with_keccak_instance() {
431        let layout = CairoLayout::starknet_with_keccak_instance();
432        let builtins = BuiltinsInstanceDef::starknet_with_keccak();
433        assert_eq!(layout.name, LayoutName::starknet_with_keccak);
434        assert_eq!(layout.rc_units, 4);
435        assert_eq!(layout.builtins, builtins);
436        assert_eq!(layout.public_memory_fraction, 8);
437        assert_eq!(
438            layout.diluted_pool_instance_def,
439            Some(DilutedPoolInstanceDef::default())
440        );
441    }
442
443    #[test]
444    fn get_recursive_large_output_instance() {
445        let layout = CairoLayout::recursive_large_output_instance();
446        let builtins = BuiltinsInstanceDef::recursive_large_output();
447        assert_eq!(layout.name, LayoutName::recursive_large_output);
448        assert_eq!(layout.rc_units, 4);
449        assert_eq!(layout.builtins, builtins);
450        assert_eq!(layout.public_memory_fraction, 8);
451        assert_eq!(
452            layout.diluted_pool_instance_def,
453            Some(DilutedPoolInstanceDef::default())
454        );
455    }
456
457    #[test]
458    fn get_all_cairo_instance() {
459        let layout = CairoLayout::all_cairo_instance();
460        let builtins = BuiltinsInstanceDef::all_cairo();
461        assert_eq!(layout.name, LayoutName::all_cairo);
462        assert_eq!(layout.rc_units, 4);
463        assert_eq!(layout.builtins, builtins);
464        assert_eq!(layout.public_memory_fraction, 8);
465        assert_eq!(
466            layout.diluted_pool_instance_def,
467            Some(DilutedPoolInstanceDef::default())
468        );
469    }
470
471    #[test]
472    fn get_all_cairo_stwo_instance() {
473        let layout = CairoLayout::all_cairo_stwo_instance();
474        let builtins = BuiltinsInstanceDef::all_cairo_stwo();
475        assert_eq!(layout.name, LayoutName::all_cairo_stwo);
476        assert_eq!(layout.rc_units, 4);
477        assert_eq!(layout.builtins, builtins);
478        assert_eq!(layout.public_memory_fraction, 8);
479        assert_eq!(
480            layout.diluted_pool_instance_def,
481            Some(DilutedPoolInstanceDef::default())
482        );
483    }
484
485    #[test]
486    fn get_all_solidity_instance() {
487        let layout = CairoLayout::all_solidity_instance();
488        let builtins = BuiltinsInstanceDef::all_solidity();
489        assert_eq!(layout.name, LayoutName::all_solidity);
490        assert_eq!(layout.rc_units, 8);
491        assert_eq!(layout.builtins, builtins);
492        assert_eq!(layout.public_memory_fraction, 8);
493        assert_eq!(
494            layout.diluted_pool_instance_def,
495            Some(DilutedPoolInstanceDef::default())
496        );
497    }
498
499    #[test]
500    fn get_dynamic_instance() {
501        // dummy cairo layout params
502        let params = CairoLayoutParams {
503            rc_units: 32,
504            cpu_component_step: 8,
505            memory_units_per_step: 16,
506            log_diluted_units_per_step: 5,
507            pedersen_ratio: 32,
508            range_check_ratio: 32,
509            ecdsa_ratio: 32,
510            bitwise_ratio: 32,
511            ec_op_ratio: 32,
512            keccak_ratio: 32,
513            poseidon_ratio: 0,
514            range_check96_ratio: 8,
515            range_check96_ratio_den: 16,
516            add_mod_ratio: 8,
517            add_mod_ratio_den: 16,
518            mul_mod_ratio: 32,
519            mul_mod_ratio_den: 16,
520        };
521
522        let layout = CairoLayout::dynamic_instance(params);
523
524        assert_eq!(layout.name, LayoutName::dynamic);
525        assert_eq!(layout.rc_units, 32);
526        assert_eq!(layout.cpu_component_step, 8);
527        assert_eq!(layout.memory_units_per_step, 16);
528        assert_eq!(layout.public_memory_fraction, 8); // hardcoded
529        assert_eq!(
530            layout.diluted_pool_instance_def,
531            Some(DilutedPoolInstanceDef {
532                units_per_step: 32,
533                ..DilutedPoolInstanceDef::default() // hardcoded
534            })
535        );
536
537        assert!(layout.builtins.output);
538        assert_eq!(
539            layout.builtins.pedersen,
540            Some(PedersenInstanceDef { ratio: Some(32) })
541        );
542        assert_eq!(
543            layout.builtins.range_check,
544            Some(RangeCheckInstanceDef {
545                ratio: Some(LowRatio::new_int(32))
546            })
547        );
548        assert_eq!(
549            layout.builtins.ecdsa,
550            Some(EcdsaInstanceDef { ratio: Some(32) })
551        );
552        assert_eq!(
553            layout.builtins.bitwise,
554            Some(BitwiseInstanceDef { ratio: Some(32) })
555        );
556        assert_eq!(
557            layout.builtins.ec_op,
558            Some(EcOpInstanceDef { ratio: Some(32) })
559        );
560        assert_eq!(
561            layout.builtins.keccak,
562            Some(KeccakInstanceDef { ratio: Some(32) })
563        );
564        assert_eq!(
565            layout.builtins.poseidon,
566            Some(PoseidonInstanceDef { ratio: Some(0) }),
567        );
568        assert_eq!(
569            layout.builtins.range_check96,
570            Some(RangeCheckInstanceDef {
571                ratio: Some(LowRatio::new(8, 16))
572            })
573        );
574        #[cfg(feature = "mod_builtin")]
575        {
576            assert_eq!(
577                layout.builtins.mul_mod,
578                Some(ModInstanceDef {
579                    ratio: Some(LowRatio {
580                        numerator: 32,
581                        denominator: 16
582                    }),
583                    word_bit_len: 96, // hardcoded
584                    batch_size: 1     // hardcoded
585                }),
586            );
587            assert_eq!(
588                layout.builtins.add_mod,
589                Some(ModInstanceDef {
590                    ratio: Some(LowRatio {
591                        numerator: 8,
592                        denominator: 16
593                    }),
594                    word_bit_len: 96, // hardcoded
595                    batch_size: 1     // hardcoded
596                })
597            );
598        }
599        #[cfg(not(feature = "mod_builtin"))]
600        {
601            assert_eq!(layout.builtins.mul_mod, None,);
602            assert_eq!(layout.builtins.add_mod, None,);
603        }
604    }
605
606    #[test]
607    fn parse_dynamic_instance() {
608        let cairo_layout_params_json = "{\n\
609            \"rc_units\": 4,\n\
610            \"log_diluted_units_per_step\": 4,\n\
611            \"cpu_component_step\": 8,\n\
612            \"memory_units_per_step\": 8,\n\
613            \"uses_pedersen_builtin\": true,\n\
614            \"pedersen_ratio\": 256,\n\
615            \"uses_range_check_builtin\": true,\n\
616            \"range_check_ratio\": 8,\n\
617            \"uses_ecdsa_builtin\": true,\n\
618            \"ecdsa_ratio\": 2048,\n\
619            \"uses_bitwise_builtin\": true,\n\
620            \"bitwise_ratio\": 16,\n\
621            \"uses_ec_op_builtin\": true,\n\
622            \"ec_op_ratio\": 1024,\n\
623            \"uses_keccak_builtin\": true,\n\
624            \"keccak_ratio\": 2048,\n\
625            \"uses_poseidon_builtin\": true,\n\
626            \"poseidon_ratio\": 256,\n\
627            \"uses_range_check96_builtin\": true,\n\
628            \"range_check96_ratio\": 8,\n\
629            \"range_check96_ratio_den\": 1,\n\
630            \"uses_add_mod_builtin\": true,\n\
631            \"add_mod_ratio\": 128,\n\
632            \"add_mod_ratio_den\": 1,\n\
633            \"uses_mul_mod_builtin\": true,\n\
634            \"mul_mod_ratio\": 256,\n\
635            \"mul_mod_ratio_den\": 1\n\
636        }\n\
637        ";
638
639        serde_json::from_str::<CairoLayoutParams>(cairo_layout_params_json).unwrap();
640    }
641}