Skip to content

Commit 3fb0344

Browse files
JulianGCalderonAlon-TiyuvalswOmriEshhar1pefontana
authored
Missing dynamic layout features (#1838)
* Fix Zero segment location. * Fixed has_zero_segment naming * Fix prover input. * Fixed version reading when no version is supplied * Added change to changelog. * fix test_from_serializable() * fix panic_impl error * fix cairo version * Add dummy changelog * Pin wasm-bindgen * Register change in CHANGELOG * Update Cargo.lock * Remove changes from CHANGELOG * Add argument parsing for layout params file * Add dynamic support (no implement) * Add cairo_layout_params_file.example.json * Implement dynamic layout creation * Update CHANGELOG * Add cli dynamic support for cairo 1 * Make wasm compatible * Use public_memory_fraction = 4 vy default * Deserialize bool from int * Add comparison with python-vm (failing) * Rebuild .rs files in makefile * Use 8 as dynamic public_memory_fraction The same value is used in python-vm * Use None ratio for dynamic unused builtins * Add rangecheck96 to private inputs * Make dyn py files depend on params_file * Use cpu_component_step=1 by default * Fix typo in private inputs * Add range check value to air private input test * Fix zero segment location * Use zero builtin instead of None * Add debug scripts * Remove dup makefile recipes * remove outdated test * Enable ensure-no_std on test * Fix tests * Add correct test * Rename tset * Add comment * Add debugging document * Update cairo layout params file * Remove duplicated range check * Remove dup * Add support for dynamic memory units per step * Add changelog * Add support for negative log units per step * Add LowRatio struct to RangeCheck and Mod builtins * Fix test * Use ratio_den in get_allocated_instances * Remove debugging and scrippts (moveed to another branch) * Add comment * Add tests * Add dynamic test to cairo-vm-cli * Add parse test * Remove compare all dynamic * Add script for comparing with dynamic layouts * Add tests to workflow * Delete logic changes They are going to be moved to another branch * Delete more logic changes * Reorder fields * Remove ref * Add modulo tests with all_cairo * Add tests * Update rust.yml * Rename compare_outputs_dynamic_layout.sh to compare_outputs_dynamic_layouts.sh * Update test script * Remove tests * Enforce prover constraints in add, sub, and mul * Remove debug prints * Add tests * Update CHANGELOG.md * Fix serialization * Comment failing test * Uncomment test * Add fractional units per step test * Change safe_div for div_ceil (bug) * Add ratio_den tests * Fix tests * Remove operation struct and use builtin type instead * Add unit tests to modulo builtin operations * Fix security error message * Add mod_builtin to coverage * Test custom serde impl * Upload mod_builtin coverage * Test custom serde impl * Upload mod_builtin coverage * Add Debug scripts (#1839) * Add debug scripts * Add debugging document * Add changelog * Revert changelog * Improve script usage code blocks * Remove extra space * Add cpu_component_step * Add comments * Add cairo pie tests * Restore zip * Use .rs.pie.zip * Update Changelog * Add dynamic layout documentation * Update CHANGELOG.md --------- Co-authored-by: Alon Titelman <[email protected]> Co-authored-by: Yuval Goldberg <[email protected]> Co-authored-by: Omri Eshhar <[email protected]> Co-authored-by: Pedro Fontana <[email protected]>
1 parent 7d19956 commit 3fb0344

File tree

14 files changed

+443
-72
lines changed

14 files changed

+443
-72
lines changed

.github/workflows/rust.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ jobs:
757757

758758
compare-outputs-dynamic-layouts:
759759
name: Compare outputs with dynamic layouts
760-
needs: [ build-programs, build-release ]
760+
needs: [ build-programs, build-release, run-cairo-release ]
761761
runs-on: ubuntu-22.04
762762
steps:
763763
- name: Checkout
@@ -791,6 +791,18 @@ jobs:
791791
key: cairo_proof_programs-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }}
792792
fail-on-cache-miss: true
793793

794+
- name: Fetch pie
795+
uses: actions/cache/restore@v3
796+
with:
797+
path: |
798+
cairo_programs/**/*.memory
799+
cairo_programs/**/*.trace
800+
cairo_programs/**/*.air_public_input
801+
cairo_programs/**/*.air_private_input
802+
cairo_programs/**/*.pie.zip
803+
key: cairo_test_programs-release-trace-cache-${{ github.sha }}
804+
fail-on-cache-miss: true
805+
794806
- name: Run script
795807
run: ./vm/src/tests/compare_outputs_dynamic_layouts.sh
796808

CHANGELOG.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
#### Upcoming Changes
44

5-
* fix: [#1841](https://github.com/lambdaclass/cairo-vm/pull/1841):
6-
* Fix modulo builtin to comply with prover constraints
7-
8-
* feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824):
5+
* feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824)[#1838](https://github.com/lambdaclass/cairo-vm/pull/1838):
96
* Add support for dynamic layout
107
* CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout.
118
* Signature change(BREAKING): Both `CairoRunner::new` and `CairoRunner::new_v2` now receive an `Option<CairoLayoutParams>`, used only with dynamic layout.
129

10+
* fix: [#1841](https://github.com/lambdaclass/cairo-vm/pull/1841):
11+
* Fix modulo builtin to comply with prover constraints
12+
1313
* chore: bump pip `cairo-lang` 0.13.2 [#1827](https://github.com/lambdaclass/cairo-vm/pull/1827)
1414

1515
* chore: bump `cairo-lang-` dependencies to 2.8.0 [#1833](https://github.com/lambdaclass/cairo-vm/pull/1833/files)

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ Now that you have the dependencies necessary to run the test suite you can run:
266266
make test
267267
```
268268

269+
### Using a Dynamic Layout
270+
271+
A dynamic layout must be specified with a dynamic params file. You can find an example in: `vm/src/tests/cairo_layout_params_file.json`.
272+
273+
To run cairo 0 or 1 programs with a dynamic layout, you must use `--layout dynamic` and the `--cairo_layout_params_file` flag pointing a dynamic params file. For example, run:
274+
```bash
275+
cargo run --bin cairo-vm-cli cairo_programs/fibonacci.json --layout dynamic --cairo_layout_params_file vm/src/tests/cairo_layout_params_file.json
276+
```
277+
269278
### Tracer
270279

271280
Cairo-vm offers a tracer which gives you a visualization of how your memory and registers change line after line as the VM executes the code. You can read more about it [here](./docs/tracer/README.md)

vm/src/tests/compare_outputs_dynamic_layouts.sh

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,70 @@ cat <<EOF > "$TEMP_FOLDER/double_all_cairo.json"
6868
}
6969
EOF
7070

71+
cat <<EOF > "$TEMP_FOLDER/fractional_units_per_step.json"
72+
{
73+
"rc_units": 4,
74+
"log_diluted_units_per_step": -2,
75+
"cpu_component_step": 8,
76+
"memory_units_per_step": 8,
77+
"uses_pedersen_builtin": false,
78+
"pedersen_ratio": 0,
79+
"uses_range_check_builtin": false,
80+
"range_check_ratio": 0,
81+
"uses_ecdsa_builtin": false,
82+
"ecdsa_ratio": 0,
83+
"uses_bitwise_builtin": false,
84+
"bitwise_ratio": 0,
85+
"uses_ec_op_builtin": false,
86+
"ec_op_ratio": 0,
87+
"uses_keccak_builtin": false,
88+
"keccak_ratio": 0,
89+
"uses_poseidon_builtin": false,
90+
"poseidon_ratio": 0,
91+
"uses_range_check96_builtin": false,
92+
"range_check96_ratio": 0,
93+
"range_check96_ratio_den": 1,
94+
"uses_add_mod_builtin": false,
95+
"add_mod_ratio": 0,
96+
"add_mod_ratio_den": 1,
97+
"uses_mul_mod_builtin": false,
98+
"mul_mod_ratio": 0,
99+
"mul_mod_ratio_den": 1
100+
}
101+
EOF
102+
103+
cat <<EOF > "$TEMP_FOLDER/ratio_den.json"
104+
{
105+
"rc_units": 4,
106+
"log_diluted_units_per_step": 4,
107+
"cpu_component_step": 8,
108+
"memory_units_per_step": 512,
109+
"uses_pedersen_builtin": false,
110+
"pedersen_ratio": 0,
111+
"uses_range_check_builtin": false,
112+
"range_check_ratio": 0,
113+
"uses_ecdsa_builtin": false,
114+
"ecdsa_ratio": 0,
115+
"uses_bitwise_builtin": false,
116+
"bitwise_ratio": 0,
117+
"uses_ec_op_builtin": false,
118+
"ec_op_ratio": 0,
119+
"uses_keccak_builtin": false,
120+
"keccak_ratio": 0,
121+
"uses_poseidon_builtin": false,
122+
"poseidon_ratio": 0,
123+
"uses_range_check96_builtin": true,
124+
"range_check96_ratio": 1,
125+
"range_check96_ratio_den": 2,
126+
"uses_add_mod_builtin": true,
127+
"add_mod_ratio": 1,
128+
"add_mod_ratio_den": 2,
129+
"uses_mul_mod_builtin": true,
130+
"mul_mod_ratio": 1,
131+
"mul_mod_ratio_den": 2
132+
}
133+
EOF
134+
71135
# Build cases to execute
72136
CASES=(
73137
"cairo_programs/proof_programs/factorial.json;all_cairo"
@@ -82,9 +146,33 @@ CASES=(
82146
"cairo_programs/proof_programs/sha256.json;double_all_cairo"
83147
"cairo_programs/proof_programs/keccak.json;all_cairo"
84148
"cairo_programs/proof_programs/keccak.json;double_all_cairo"
149+
# Mod builtin feature
85150
"cairo_programs/mod_builtin_feature/proof/mod_builtin.json;all_cairo"
86151
"cairo_programs/mod_builtin_feature/proof/mod_builtin_failure.json;all_cairo"
87152
"cairo_programs/mod_builtin_feature/proof/apply_poly.json;all_cairo"
153+
# Fractional units per step
154+
"cairo_programs/proof_programs/factorial.json;fractional_units_per_step"
155+
"cairo_programs/proof_programs/fibonacci.json;fractional_units_per_step"
156+
# Ratio den
157+
"cairo_programs/mod_builtin_feature/proof/mod_builtin.json;ratio_den"
158+
"cairo_programs/mod_builtin_feature/proof/mod_builtin_failure.json;ratio_den"
159+
"cairo_programs/mod_builtin_feature/proof/apply_poly.json;ratio_den"
160+
)
161+
162+
# Build pie cases to execute
163+
PIE_CASES=(
164+
"cairo_programs/fibonacci.rs.pie.zip;all_cairo"
165+
"cairo_programs/fibonacci.rs.pie.zip;double_all_cairo"
166+
"cairo_programs/factorial.rs.pie.zip;all_cairo"
167+
"cairo_programs/factorial.rs.pie.zip;double_all_cairo"
168+
"cairo_programs/bigint.rs.pie.zip;all_cairo"
169+
"cairo_programs/bigint.rs.pie.zip;double_all_cairo"
170+
"cairo_programs/dict.rs.pie.zip;all_cairo"
171+
"cairo_programs/dict.rs.pie.zip;double_all_cairo"
172+
"cairo_programs/sha256.rs.pie.zip;all_cairo"
173+
"cairo_programs/sha256.rs.pie.zip;double_all_cairo"
174+
"cairo_programs/keccak.rs.pie.zip;all_cairo"
175+
"cairo_programs/keccak.rs.pie.zip;double_all_cairo"
88176
)
89177

90178
passed_tests=0
@@ -155,6 +243,51 @@ for case in "${CASES[@]}"; do
155243
rm program_py.*
156244
done
157245

246+
247+
for case in "${PIE_CASES[@]}"; do
248+
IFS=";" read -r program layout <<< "$case"
249+
250+
full_program="$program"
251+
full_layout="$TEMP_FOLDER/$layout.json"
252+
253+
# Run cairo-vm
254+
echo "Running cairo-vm with case: $case"
255+
cargo run -p cairo-vm-cli --features mod_builtin --release -- "$full_program" \
256+
--layout "dynamic" --cairo_layout_params_file "$full_layout" --run_from_cairo_pie \
257+
--trace_file program_rs.trace --memory_file program_rs.memory
258+
259+
# Run cairo-lang
260+
echo "Running cairo-lang with case: $case"
261+
cairo-run --run_from_cairo_pie "$full_program" \
262+
--layout "dynamic" --cairo_layout_params_file "$full_layout" \
263+
--trace_file program_py.trace --memory_file program_py.memory
264+
265+
# Compare trace
266+
echo "Running trace comparison for case: $case"
267+
if ! diff -q program_rs.trace program_py.trace; then
268+
echo "Trace differs for case: $case"
269+
exit_code=1
270+
failed_tests=$((failed_tests + 1))
271+
else
272+
passed_tests=$((passed_tests + 1))
273+
fi
274+
275+
# Compare memory
276+
echo "Running memory comparison for case: $case"
277+
if ! ./vm/src/tests/memory_comparator.py program_rs.memory program_py.memory; then
278+
echo "Memory differs for case: $case"
279+
exit_code=1
280+
failed_tests=$((failed_tests + 1))
281+
else
282+
passed_tests=$((passed_tests + 1))
283+
fi
284+
285+
# Clean files generated by the script
286+
echo "Cleaning files"
287+
rm program_rs.*
288+
rm program_py.*
289+
done
290+
158291
if test $failed_tests != 0; then
159292
echo "Comparisons: $failed_tests failed, $passed_tests passed, $((failed_tests + passed_tests)) total"
160293
elif test $passed_tests = 0; then

vm/src/types/instance_definitions/builtins_instance_def.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::types::layout::CairoLayoutParams;
22

33
use super::mod_instance_def::ModInstanceDef;
4+
use super::LowRatio;
45
use super::{
56
bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef,
67
ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef,
@@ -199,7 +200,7 @@ impl BuiltinsInstanceDef {
199200
ratio: Some(params.pedersen_ratio),
200201
});
201202
let range_check = Some(RangeCheckInstanceDef {
202-
ratio: Some(params.range_check_ratio),
203+
ratio: Some(LowRatio::new_int(params.range_check_ratio)),
203204
});
204205
let ecdsa = Some(EcdsaInstanceDef {
205206
ratio: Some(params.ecdsa_ratio),
@@ -217,17 +218,26 @@ impl BuiltinsInstanceDef {
217218
ratio: Some(params.poseidon_ratio),
218219
});
219220
let range_check96 = Some(RangeCheckInstanceDef {
220-
ratio: Some(params.range_check96_ratio),
221+
ratio: Some(LowRatio::new(
222+
params.range_check96_ratio,
223+
params.range_check96_ratio_den,
224+
)),
221225
});
222226
#[cfg(feature = "mod_builtin")]
223227
let add_mod = Some(ModInstanceDef {
224-
ratio: Some(params.add_mod_ratio),
228+
ratio: Some(LowRatio::new(
229+
params.add_mod_ratio,
230+
params.add_mod_ratio_den,
231+
)),
225232
word_bit_len: 96,
226233
batch_size: 1,
227234
});
228235
#[cfg(feature = "mod_builtin")]
229236
let mul_mod = Some(ModInstanceDef {
230-
ratio: Some(params.mul_mod_ratio),
237+
ratio: Some(LowRatio::new(
238+
params.mul_mod_ratio,
239+
params.mul_mod_ratio_den,
240+
)),
231241
word_bit_len: 96,
232242
batch_size: 1,
233243
});

vm/src/types/instance_definitions/diluted_pool_instance_def.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use serde::Serialize;
33
#[derive(Serialize, Debug, PartialEq)]
44
pub(crate) struct DilutedPoolInstanceDef {
55
pub(crate) units_per_step: u32, // 2 ^ log_units_per_step (for cairo_lang comparison)
6+
pub(crate) fractional_units_per_step: bool, // true when log_units_per_step is negative
67
pub(crate) spacing: u32,
78
pub(crate) n_bits: u32,
89
}
@@ -11,6 +12,7 @@ impl DilutedPoolInstanceDef {
1112
pub(crate) fn default() -> Self {
1213
DilutedPoolInstanceDef {
1314
units_per_step: 16,
15+
fractional_units_per_step: false,
1416
spacing: 4,
1517
n_bits: 16,
1618
}
@@ -21,6 +23,15 @@ impl DilutedPoolInstanceDef {
2123
units_per_step,
2224
spacing,
2325
n_bits,
26+
..Self::default()
27+
}
28+
}
29+
30+
pub(crate) fn from_log_units_per_step(log_units_per_step: i32) -> Self {
31+
DilutedPoolInstanceDef {
32+
units_per_step: 2_u32.pow(log_units_per_step.unsigned_abs()),
33+
fractional_units_per_step: log_units_per_step.is_negative(),
34+
..DilutedPoolInstanceDef::default()
2435
}
2536
}
2637
}

vm/src/types/instance_definitions/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use serde::Serialize;
2+
13
pub mod bitwise_instance_def;
24
pub mod builtins_instance_def;
35
pub mod diluted_pool_instance_def;
@@ -9,3 +11,25 @@ pub mod mod_instance_def;
911
pub mod pedersen_instance_def;
1012
pub mod poseidon_instance_def;
1113
pub mod range_check_instance_def;
14+
15+
#[derive(Serialize, Debug, PartialEq, Copy, Clone)]
16+
pub struct LowRatio {
17+
pub numerator: u32,
18+
pub denominator: u32,
19+
}
20+
21+
impl LowRatio {
22+
pub fn new(numerator: u32, denominator: u32) -> Self {
23+
Self {
24+
numerator,
25+
denominator,
26+
}
27+
}
28+
29+
pub fn new_int(numerator: u32) -> Self {
30+
Self {
31+
numerator,
32+
denominator: 1,
33+
}
34+
}
35+
}
Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,43 @@
11
use serde::Serialize;
22

3+
use super::LowRatio;
4+
35
pub(crate) const N_WORDS: usize = 4;
46

57
pub(crate) const CELLS_PER_MOD: u32 = 7;
68

79
#[derive(Serialize, Debug, PartialEq, Clone)]
810
pub(crate) struct ModInstanceDef {
9-
pub(crate) ratio: Option<u32>,
11+
pub(crate) ratio: Option<LowRatio>,
1012
pub(crate) word_bit_len: u32,
1113
pub(crate) batch_size: usize,
1214
}
1315

1416
impl ModInstanceDef {
1517
pub(crate) fn new(ratio: Option<u32>, batch_size: usize, word_bit_len: u32) -> Self {
1618
ModInstanceDef {
17-
ratio,
19+
ratio: ratio.map(LowRatio::new_int),
1820
word_bit_len,
1921
batch_size,
2022
}
2123
}
2224
}
25+
26+
#[cfg(test)]
27+
mod tests {
28+
use super::*;
29+
30+
#[cfg(target_arch = "wasm32")]
31+
use wasm_bindgen_test::*;
32+
33+
#[test]
34+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
35+
fn test_new() {
36+
let builtin_instance = ModInstanceDef {
37+
ratio: Some(LowRatio::new_int(10)),
38+
word_bit_len: 3,
39+
batch_size: 3,
40+
};
41+
assert_eq!(ModInstanceDef::new(Some(10), 3, 3), builtin_instance);
42+
}
43+
}

0 commit comments

Comments
 (0)