Skip to main content

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 stwo_no_ecop_instance() -> CairoLayout {
148        CairoLayout {
149            name: LayoutName::stwo_no_ecop,
150            rc_units: 4,
151            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
152            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
153            builtins: BuiltinsInstanceDef::stwo_no_ecop(),
154            public_memory_fraction: 8,
155            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
156        }
157    }
158
159    pub(crate) fn all_solidity_instance() -> CairoLayout {
160        CairoLayout {
161            name: LayoutName::all_solidity,
162            rc_units: 8,
163            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
164            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
165            builtins: BuiltinsInstanceDef::all_solidity(),
166            public_memory_fraction: 8,
167            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()),
168        }
169    }
170
171    pub(crate) fn dynamic_instance(params: CairoLayoutParams) -> Result<CairoLayout, RunnerError> {
172        let diluted_pool =
173            DilutedPoolInstanceDef::from_log_units_per_step(params.log_diluted_units_per_step)?;
174        Ok(CairoLayout {
175            name: LayoutName::dynamic,
176            rc_units: params.rc_units,
177            cpu_component_step: params.cpu_component_step,
178            memory_units_per_step: params.memory_units_per_step,
179            public_memory_fraction: 8,
180            diluted_pool_instance_def: Some(diluted_pool),
181            builtins: BuiltinsInstanceDef::dynamic(params),
182        })
183    }
184
185    pub(crate) fn perpetual_instance() -> CairoLayout {
186        CairoLayout {
187            name: LayoutName::perpetual,
188            rc_units: 4,
189            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
190            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
191            builtins: BuiltinsInstanceDef::perpetual(),
192            public_memory_fraction: 4,
193            diluted_pool_instance_def: None,
194        }
195    }
196
197    pub(crate) fn dex_with_bitwise_instance() -> CairoLayout {
198        CairoLayout {
199            name: LayoutName::dex_with_bitwise,
200            rc_units: 4,
201            cpu_component_step: DEFAULT_CPU_COMPONENT_STEP,
202            memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP,
203            builtins: BuiltinsInstanceDef::dex_with_bitwise(),
204            public_memory_fraction: 4,
205            diluted_pool_instance_def: Some(DilutedPoolInstanceDef::new(2, 4, 16)),
206        }
207    }
208}
209
210#[cfg(feature = "test_utils")]
211use arbitrary::{self, Arbitrary};
212
213#[cfg_attr(feature = "test_utils", derive(Arbitrary))]
214#[derive(Deserialize, Debug, Clone, Default)]
215#[serde(try_from = "RawCairoLayoutParams")]
216pub struct CairoLayoutParams {
217    pub rc_units: u32,
218    pub cpu_component_step: u32,
219    pub memory_units_per_step: u32,
220    pub log_diluted_units_per_step: i32,
221    pub pedersen_ratio: u32,
222    pub range_check_ratio: u32,
223    pub ecdsa_ratio: u32,
224    pub bitwise_ratio: u32,
225    pub ec_op_ratio: u32,
226    pub keccak_ratio: u32,
227    pub poseidon_ratio: u32,
228    pub range_check96_ratio: u32,
229    pub range_check96_ratio_den: u32,
230    pub add_mod_ratio: u32,
231    pub add_mod_ratio_den: u32,
232    pub mul_mod_ratio: u32,
233    pub mul_mod_ratio_den: u32,
234}
235
236impl CairoLayoutParams {
237    pub fn from_file(params_path: &std::path::Path) -> std::io::Result<Self> {
238        let params_file = std::fs::File::open(params_path)?;
239        let params = serde_json::from_reader(params_file)?;
240        Ok(params)
241    }
242}
243
244// The CairoLayoutParams contains aditional constraints that can't be validated by serde alone.
245// To work around this. we use an aditional structure `RawCairoLayoutParams` that gets deserialized by serde
246// and then its tranformed into `CairoLayoutParams`.
247
248#[derive(Deserialize, Debug, Default, Clone)]
249pub struct RawCairoLayoutParams {
250    pub rc_units: u32,
251    pub cpu_component_step: u32,
252    pub memory_units_per_step: u32,
253    pub log_diluted_units_per_step: i32,
254    #[serde(deserialize_with = "bool_from_int_or_bool")]
255    pub uses_pedersen_builtin: bool,
256    pub pedersen_ratio: u32,
257    #[serde(deserialize_with = "bool_from_int_or_bool")]
258    pub uses_range_check_builtin: bool,
259    pub range_check_ratio: u32,
260    #[serde(deserialize_with = "bool_from_int_or_bool")]
261    pub uses_ecdsa_builtin: bool,
262    pub ecdsa_ratio: u32,
263    #[serde(deserialize_with = "bool_from_int_or_bool")]
264    pub uses_bitwise_builtin: bool,
265    pub bitwise_ratio: u32,
266    #[serde(deserialize_with = "bool_from_int_or_bool")]
267    pub uses_ec_op_builtin: bool,
268    pub ec_op_ratio: u32,
269    #[serde(deserialize_with = "bool_from_int_or_bool")]
270    pub uses_keccak_builtin: bool,
271    pub keccak_ratio: u32,
272    #[serde(deserialize_with = "bool_from_int_or_bool")]
273    pub uses_poseidon_builtin: bool,
274    pub poseidon_ratio: u32,
275    #[serde(deserialize_with = "bool_from_int_or_bool")]
276    pub uses_range_check96_builtin: bool,
277    pub range_check96_ratio: u32,
278    pub range_check96_ratio_den: u32,
279    #[serde(deserialize_with = "bool_from_int_or_bool")]
280    pub uses_add_mod_builtin: bool,
281    pub add_mod_ratio: u32,
282    pub add_mod_ratio_den: u32,
283    #[serde(deserialize_with = "bool_from_int_or_bool")]
284    pub uses_mul_mod_builtin: bool,
285    pub mul_mod_ratio: u32,
286    pub mul_mod_ratio_den: u32,
287}
288
289impl TryFrom<RawCairoLayoutParams> for CairoLayoutParams {
290    type Error = RunnerError;
291
292    fn try_from(value: RawCairoLayoutParams) -> Result<Self, Self::Error> {
293        if !value.uses_pedersen_builtin && value.pedersen_ratio != 0 {
294            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
295                BuiltinName::pedersen,
296            ));
297        }
298        if !value.uses_range_check_builtin && value.range_check_ratio != 0 {
299            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
300                BuiltinName::range_check,
301            ));
302        }
303        if !value.uses_ecdsa_builtin && value.ecdsa_ratio != 0 {
304            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
305                BuiltinName::ecdsa,
306            ));
307        }
308        if !value.uses_bitwise_builtin && value.bitwise_ratio != 0 {
309            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
310                BuiltinName::bitwise,
311            ));
312        }
313        if !value.uses_ec_op_builtin && value.ec_op_ratio != 0 {
314            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
315                BuiltinName::ec_op,
316            ));
317        }
318        if !value.uses_keccak_builtin && value.keccak_ratio != 0 {
319            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
320                BuiltinName::keccak,
321            ));
322        }
323        if !value.uses_poseidon_builtin && value.poseidon_ratio != 0 {
324            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
325                BuiltinName::poseidon,
326            ));
327        }
328        if !value.uses_range_check96_builtin && value.range_check96_ratio != 0 {
329            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
330                BuiltinName::range_check96,
331            ));
332        }
333        if !value.uses_add_mod_builtin && value.add_mod_ratio != 0 {
334            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
335                BuiltinName::add_mod,
336            ));
337        }
338        if !value.uses_mul_mod_builtin && value.mul_mod_ratio != 0 {
339            return Err(RunnerError::BadDynamicLayoutBuiltinRatio(
340                BuiltinName::mul_mod,
341            ));
342        }
343
344        Ok(CairoLayoutParams {
345            rc_units: value.rc_units,
346            log_diluted_units_per_step: value.log_diluted_units_per_step,
347            cpu_component_step: value.cpu_component_step,
348            memory_units_per_step: value.memory_units_per_step,
349            range_check96_ratio_den: value.range_check96_ratio_den,
350            mul_mod_ratio_den: value.mul_mod_ratio_den,
351            add_mod_ratio_den: value.add_mod_ratio_den,
352            pedersen_ratio: value.pedersen_ratio,
353            range_check_ratio: value.range_check_ratio,
354            ecdsa_ratio: value.ecdsa_ratio,
355            bitwise_ratio: value.bitwise_ratio,
356            ec_op_ratio: value.ec_op_ratio,
357            keccak_ratio: value.keccak_ratio,
358            poseidon_ratio: value.poseidon_ratio,
359            range_check96_ratio: value.range_check96_ratio,
360            add_mod_ratio: value.add_mod_ratio,
361            mul_mod_ratio: value.mul_mod_ratio,
362        })
363    }
364}
365
366fn bool_from_int_or_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
367where
368    D: Deserializer<'de>,
369{
370    #[derive(Deserialize)]
371    #[serde(untagged)]
372    enum IntOrBool {
373        Int(i64),
374        Boolean(bool),
375    }
376
377    match IntOrBool::deserialize(deserializer)? {
378        IntOrBool::Int(0) => Ok(false),
379        IntOrBool::Int(_) => Ok(true),
380        IntOrBool::Boolean(v) => Ok(v),
381    }
382}
383
384#[cfg(test)]
385mod tests {
386    use super::*;
387    #[cfg(feature = "mod_builtin")]
388    use crate::types::instance_definitions::mod_instance_def::ModInstanceDef;
389
390    use crate::types::instance_definitions::{
391        bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef,
392        ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef,
393        pedersen_instance_def::PedersenInstanceDef, poseidon_instance_def::PoseidonInstanceDef,
394        range_check_instance_def::RangeCheckInstanceDef, LowRatio,
395    };
396
397    #[test]
398    fn get_plain_instance() {
399        let layout = CairoLayout::plain_instance();
400        let builtins = BuiltinsInstanceDef::plain();
401        assert_eq!(layout.name, LayoutName::plain);
402        assert_eq!(layout.rc_units, 16);
403        assert_eq!(layout.builtins, builtins);
404        assert_eq!(layout.public_memory_fraction, 4);
405        assert_eq!(layout.diluted_pool_instance_def, None);
406    }
407
408    #[test]
409    fn get_small_instance() {
410        let layout = CairoLayout::small_instance();
411        let builtins = BuiltinsInstanceDef::small();
412        assert_eq!(layout.name, LayoutName::small);
413        assert_eq!(layout.rc_units, 16);
414        assert_eq!(layout.builtins, builtins);
415        assert_eq!(layout.public_memory_fraction, 4);
416        assert_eq!(layout.diluted_pool_instance_def, None);
417    }
418
419    #[test]
420    fn get_dex_instance() {
421        let layout = CairoLayout::dex_instance();
422        let builtins = BuiltinsInstanceDef::dex();
423        assert_eq!(layout.name, LayoutName::dex);
424        assert_eq!(layout.rc_units, 4);
425        assert_eq!(layout.builtins, builtins);
426        assert_eq!(layout.public_memory_fraction, 4);
427        assert_eq!(layout.diluted_pool_instance_def, None);
428    }
429
430    #[test]
431    fn get_recursive_instance() {
432        let layout = CairoLayout::recursive_instance();
433        let builtins = BuiltinsInstanceDef::recursive();
434        assert_eq!(layout.name, LayoutName::recursive);
435        assert_eq!(layout.rc_units, 4);
436        assert_eq!(layout.builtins, builtins);
437        assert_eq!(layout.public_memory_fraction, 8);
438        assert_eq!(
439            layout.diluted_pool_instance_def,
440            Some(DilutedPoolInstanceDef::default())
441        );
442    }
443
444    #[test]
445    fn get_starknet_instance() {
446        let layout = CairoLayout::starknet_instance();
447        let builtins = BuiltinsInstanceDef::starknet();
448        assert_eq!(layout.name, LayoutName::starknet);
449        assert_eq!(layout.rc_units, 4);
450        assert_eq!(layout.builtins, builtins);
451        assert_eq!(layout.public_memory_fraction, 8);
452        assert_eq!(
453            layout.diluted_pool_instance_def,
454            Some(DilutedPoolInstanceDef::new(2, 4, 16))
455        );
456    }
457
458    #[test]
459    fn get_starknet_with_keccak_instance() {
460        let layout = CairoLayout::starknet_with_keccak_instance();
461        let builtins = BuiltinsInstanceDef::starknet_with_keccak();
462        assert_eq!(layout.name, LayoutName::starknet_with_keccak);
463        assert_eq!(layout.rc_units, 4);
464        assert_eq!(layout.builtins, builtins);
465        assert_eq!(layout.public_memory_fraction, 8);
466        assert_eq!(
467            layout.diluted_pool_instance_def,
468            Some(DilutedPoolInstanceDef::default())
469        );
470    }
471
472    #[test]
473    fn get_recursive_large_output_instance() {
474        let layout = CairoLayout::recursive_large_output_instance();
475        let builtins = BuiltinsInstanceDef::recursive_large_output();
476        assert_eq!(layout.name, LayoutName::recursive_large_output);
477        assert_eq!(layout.rc_units, 4);
478        assert_eq!(layout.builtins, builtins);
479        assert_eq!(layout.public_memory_fraction, 8);
480        assert_eq!(
481            layout.diluted_pool_instance_def,
482            Some(DilutedPoolInstanceDef::default())
483        );
484    }
485
486    #[test]
487    fn get_all_cairo_instance() {
488        let layout = CairoLayout::all_cairo_instance();
489        let builtins = BuiltinsInstanceDef::all_cairo();
490        assert_eq!(layout.name, LayoutName::all_cairo);
491        assert_eq!(layout.rc_units, 4);
492        assert_eq!(layout.builtins, builtins);
493        assert_eq!(layout.public_memory_fraction, 8);
494        assert_eq!(
495            layout.diluted_pool_instance_def,
496            Some(DilutedPoolInstanceDef::default())
497        );
498    }
499
500    #[test]
501    fn get_all_cairo_stwo_instance() {
502        let layout = CairoLayout::all_cairo_stwo_instance();
503        let builtins = BuiltinsInstanceDef::all_cairo_stwo();
504        assert_eq!(layout.name, LayoutName::all_cairo_stwo);
505        assert_eq!(layout.rc_units, 4);
506        assert_eq!(layout.builtins, builtins);
507        assert_eq!(layout.public_memory_fraction, 8);
508        assert_eq!(
509            layout.diluted_pool_instance_def,
510            Some(DilutedPoolInstanceDef::default())
511        );
512    }
513
514    #[test]
515    fn get_stwo_no_ecop_instance() {
516        let layout = CairoLayout::stwo_no_ecop_instance();
517        let builtins = BuiltinsInstanceDef::stwo_no_ecop();
518        assert_eq!(layout.name, LayoutName::stwo_no_ecop);
519        assert_eq!(layout.rc_units, 4);
520        assert_eq!(layout.builtins, builtins);
521        assert_eq!(layout.public_memory_fraction, 8);
522        assert_eq!(
523            layout.diluted_pool_instance_def,
524            Some(DilutedPoolInstanceDef::default())
525        );
526    }
527
528    #[test]
529    fn get_all_solidity_instance() {
530        let layout = CairoLayout::all_solidity_instance();
531        let builtins = BuiltinsInstanceDef::all_solidity();
532        assert_eq!(layout.name, LayoutName::all_solidity);
533        assert_eq!(layout.rc_units, 8);
534        assert_eq!(layout.builtins, builtins);
535        assert_eq!(layout.public_memory_fraction, 8);
536        assert_eq!(
537            layout.diluted_pool_instance_def,
538            Some(DilutedPoolInstanceDef::default())
539        );
540    }
541
542    #[test]
543    fn get_perpetual_instance() {
544        let layout = CairoLayout::perpetual_instance();
545        let builtins = BuiltinsInstanceDef::perpetual();
546        assert_eq!(layout.name, LayoutName::perpetual);
547        assert_eq!(layout.rc_units, 4);
548        assert_eq!(layout.builtins, builtins);
549        assert_eq!(layout.public_memory_fraction, 4);
550        assert_eq!(layout.diluted_pool_instance_def, None);
551    }
552
553    #[test]
554    fn get_dex_with_bitwise_instance() {
555        let layout = CairoLayout::dex_with_bitwise_instance();
556        let builtins = BuiltinsInstanceDef::dex_with_bitwise();
557        assert_eq!(layout.name, LayoutName::dex_with_bitwise);
558        assert_eq!(layout.rc_units, 4);
559        assert_eq!(layout.builtins, builtins);
560        assert_eq!(layout.public_memory_fraction, 4);
561        assert_eq!(
562            layout.diluted_pool_instance_def,
563            Some(DilutedPoolInstanceDef::new(2, 4, 16))
564        );
565    }
566
567    #[test]
568    fn get_dynamic_instance() {
569        // dummy cairo layout params
570        let params = CairoLayoutParams {
571            rc_units: 32,
572            cpu_component_step: 8,
573            memory_units_per_step: 16,
574            log_diluted_units_per_step: 5,
575            pedersen_ratio: 32,
576            range_check_ratio: 32,
577            ecdsa_ratio: 32,
578            bitwise_ratio: 32,
579            ec_op_ratio: 32,
580            keccak_ratio: 32,
581            poseidon_ratio: 0,
582            range_check96_ratio: 8,
583            range_check96_ratio_den: 16,
584            add_mod_ratio: 8,
585            add_mod_ratio_den: 16,
586            mul_mod_ratio: 32,
587            mul_mod_ratio_den: 16,
588        };
589
590        let layout = CairoLayout::dynamic_instance(params).unwrap();
591
592        assert_eq!(layout.name, LayoutName::dynamic);
593        assert_eq!(layout.rc_units, 32);
594        assert_eq!(layout.cpu_component_step, 8);
595        assert_eq!(layout.memory_units_per_step, 16);
596        assert_eq!(layout.public_memory_fraction, 8); // hardcoded
597        assert_eq!(
598            layout.diluted_pool_instance_def,
599            Some(DilutedPoolInstanceDef {
600                units_per_step: 32,
601                ..DilutedPoolInstanceDef::default() // hardcoded
602            })
603        );
604
605        assert!(layout.builtins.output);
606        assert_eq!(
607            layout.builtins.pedersen,
608            Some(PedersenInstanceDef { ratio: Some(32) })
609        );
610        assert_eq!(
611            layout.builtins.range_check,
612            Some(RangeCheckInstanceDef {
613                ratio: Some(LowRatio::new_int(32))
614            })
615        );
616        assert_eq!(
617            layout.builtins.ecdsa,
618            Some(EcdsaInstanceDef { ratio: Some(32) })
619        );
620        assert_eq!(
621            layout.builtins.bitwise,
622            Some(BitwiseInstanceDef { ratio: Some(32) })
623        );
624        assert_eq!(
625            layout.builtins.ec_op,
626            Some(EcOpInstanceDef { ratio: Some(32) })
627        );
628        assert_eq!(
629            layout.builtins.keccak,
630            Some(KeccakInstanceDef { ratio: Some(32) })
631        );
632        assert_eq!(
633            layout.builtins.poseidon,
634            Some(PoseidonInstanceDef { ratio: Some(0) }),
635        );
636        assert_eq!(
637            layout.builtins.range_check96,
638            Some(RangeCheckInstanceDef {
639                ratio: Some(LowRatio::new(8, 16))
640            })
641        );
642        #[cfg(feature = "mod_builtin")]
643        {
644            assert_eq!(
645                layout.builtins.mul_mod,
646                Some(ModInstanceDef {
647                    ratio: Some(LowRatio {
648                        numerator: 32,
649                        denominator: 16
650                    }),
651                    word_bit_len: 96, // hardcoded
652                    batch_size: 1     // hardcoded
653                }),
654            );
655            assert_eq!(
656                layout.builtins.add_mod,
657                Some(ModInstanceDef {
658                    ratio: Some(LowRatio {
659                        numerator: 8,
660                        denominator: 16
661                    }),
662                    word_bit_len: 96, // hardcoded
663                    batch_size: 1     // hardcoded
664                })
665            );
666        }
667        #[cfg(not(feature = "mod_builtin"))]
668        {
669            assert_eq!(layout.builtins.mul_mod, None,);
670            assert_eq!(layout.builtins.add_mod, None,);
671        }
672    }
673
674    #[test]
675    fn parse_dynamic_instance() {
676        let cairo_layout_params_json = "{\n\
677            \"rc_units\": 4,\n\
678            \"log_diluted_units_per_step\": 4,\n\
679            \"cpu_component_step\": 8,\n\
680            \"memory_units_per_step\": 8,\n\
681            \"uses_pedersen_builtin\": true,\n\
682            \"pedersen_ratio\": 256,\n\
683            \"uses_range_check_builtin\": true,\n\
684            \"range_check_ratio\": 8,\n\
685            \"uses_ecdsa_builtin\": true,\n\
686            \"ecdsa_ratio\": 2048,\n\
687            \"uses_bitwise_builtin\": true,\n\
688            \"bitwise_ratio\": 16,\n\
689            \"uses_ec_op_builtin\": true,\n\
690            \"ec_op_ratio\": 1024,\n\
691            \"uses_keccak_builtin\": true,\n\
692            \"keccak_ratio\": 2048,\n\
693            \"uses_poseidon_builtin\": true,\n\
694            \"poseidon_ratio\": 256,\n\
695            \"uses_range_check96_builtin\": true,\n\
696            \"range_check96_ratio\": 8,\n\
697            \"range_check96_ratio_den\": 1,\n\
698            \"uses_add_mod_builtin\": true,\n\
699            \"add_mod_ratio\": 128,\n\
700            \"add_mod_ratio_den\": 1,\n\
701            \"uses_mul_mod_builtin\": true,\n\
702            \"mul_mod_ratio\": 256,\n\
703            \"mul_mod_ratio_den\": 1\n\
704        }\n\
705        ";
706
707        serde_json::from_str::<CairoLayoutParams>(cairo_layout_params_json).unwrap();
708    }
709}