diff --git a/cairo_programs/mod_builtin_feature/apply_poly.cairo b/cairo_programs/mod_builtin_feature/apply_poly.cairo new file mode 100644 index 0000000000..da42bd84c6 --- /dev/null +++ b/cairo_programs/mod_builtin_feature/apply_poly.cairo @@ -0,0 +1,140 @@ +%builtins range_check range_check96 add_mod mul_mod +// TODO: Import directly from common library once released +from cairo_programs.mod_builtin_feature.common.modulo import ModBuiltin, UInt384, run_mod_p_circuit +// from starkware.cairo.common.modulo import run_mod_p_circuit +// from starkware.cairo.common.cairo_builtins import ModBuiltin, UInt384 +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.common.memcpy import memcpy +from starkware.cairo.common.alloc import alloc + +// Computes the polynomial f(x) = x^8 + 5*x^2 + 1. +func apply_poly{ + range_check_ptr, + range_check96_ptr: felt*, + add_mod_ptr: ModBuiltin*, + mul_mod_ptr: ModBuiltin* +}(x: UInt384*, p: UInt384) -> (res: UInt384*) { + + // Copy inputs and constants into the values_ptr segment. + memcpy(dst=range_check96_ptr, src=x, len=UInt384.SIZE); + let (constants_ptr) = get_label_location(constants); + memcpy(dst=range_check96_ptr + UInt384.SIZE, src=constants_ptr, len=2 * UInt384.SIZE); + let values_ptr = cast(range_check96_ptr, UInt384*); + let range_check96_ptr = range_check96_ptr + 36; + + + let (add_mod_offsets_ptr) = get_label_location(add_offsets); + let (mul_mod_offsets_ptr) = get_label_location(mul_offsets); + run_mod_p_circuit( + p=p, + values_ptr=values_ptr, + add_mod_offsets_ptr=add_mod_offsets_ptr, + add_mod_n=2, + mul_mod_offsets_ptr=mul_mod_offsets_ptr, + mul_mod_n=4, + ); + + return (res=values_ptr + 32); + + // values_ptr points to a segment within the range_check96_ptr segment that looks like this: + // + // offset value + // 0 x + // 4 1 + // 8 5 + // 12 x^2 + // 16 x^4 + // 20 x^8 + // 24 5*x^2 + // 28 x^8 + 5*x^2 + // 32 x^8 + 5*x^2 + 1 + + constants: + dw 1; + dw 0; + dw 0; + dw 0; + + dw 5; + dw 0; + dw 0; + dw 0; + + add_offsets: + dw 20; // x^8 + dw 24; // 5*x^2 + dw 28; // x^8 + 5*x^2 + + dw 4; // 1 + dw 28; // x^8 + 5*x^2 + dw 32; // x^8 + 5*x^2 + 1 + + // Placeholders (copies of the first 3 offsets): + dw 20; + dw 24; + dw 28; + dw 20; + dw 24; + dw 28; + dw 20; + dw 24; + dw 28; + dw 20; + dw 24; + dw 28; + dw 20; + dw 24; + dw 28; + dw 20; + dw 24; + dw 28; + + + mul_offsets: + dw 0; // x + dw 0; // x + dw 12; // x^2 + + dw 12; // x^2 + dw 12; // x^2 + dw 16; // x^4 + + dw 16; // x^4 + dw 16; // x^4 + dw 20; // x^8 + + dw 8; // 5 + dw 12; // x^2 + dw 24; // 5*x^2 + + // Placeholders (copies of the first 3 offsets): + dw 0; + dw 0; + dw 12; + dw 0; + dw 0; + dw 12; + dw 0; + dw 0; + dw 12; + dw 0; + dw 0; + dw 12; +} + +func main{range_check_ptr, range_check96_ptr: felt*, add_mod_ptr: ModBuiltin*, mul_mod_ptr: ModBuiltin*}() { + alloc_locals; + + let p = UInt384(d0=0xffff, d1=0xffff, d2=0xffff, d3=0xffff); + let (local inputs: UInt384*) = alloc(); + assert inputs[0] = UInt384(d0=0xbbbb, d1=0xaaaa, d2=0x6666, d3=0xffff); + + let res: UInt384* = apply_poly(inputs, p); + + assert res[0].d0 = 0xdb0030d69941baf9893cd667; + assert res[0].d1 = 0xfffffffffffffffee43128e7; + assert res[0].d2 = 0xfd4c69cdf6010eab465c3055; + assert res[0].d3 = 0xea52; + + return(); +} diff --git a/cairo_programs/mod_builtin_feature/proof/apply_poly.cairo b/cairo_programs/mod_builtin_feature/proof/apply_poly.cairo new file mode 120000 index 0000000000..70d9ba18e4 --- /dev/null +++ b/cairo_programs/mod_builtin_feature/proof/apply_poly.cairo @@ -0,0 +1 @@ +../apply_poly.cairo \ No newline at end of file diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index bf44200dd3..fc1023d23e 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1222,3 +1222,19 @@ fn run_program_with_custom_mod_builtin_params( security_res.unwrap(); } } + +#[test] +#[cfg(feature = "mod_builtin")] +fn cairo_run_apply_poly() { + let program_data = + include_bytes!("../../../cairo_programs/mod_builtin_feature/apply_poly.json"); + run_program(program_data, false, Some("all_cairo"), None, None); +} + +#[test] +#[cfg(feature = "mod_builtin")] +fn cairo_run_apply_poly_proof() { + let program_data = + include_bytes!("../../../cairo_programs/mod_builtin_feature/proof/apply_poly.json"); + run_program(program_data, true, Some("all_cairo"), None, None); +}