Skip to content

Commit

Permalink
Merge branch 'main' of github.com:lambdaclass/cairo-vm.go into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
toni-calvin committed Oct 25, 2023
2 parents 101dc93 + 432dd89 commit 32a892a
Show file tree
Hide file tree
Showing 44 changed files with 2,626 additions and 199 deletions.
129 changes: 129 additions & 0 deletions cairo_programs/div_mod_n.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
%builtins range_check

from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul
from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2

// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/signature.cairo

// Computes a * b^(-1) modulo the size of the elliptic curve (N).
//
// Prover assumptions:
// * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99).
// * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99).
// * b is in the range [0, 2 ** 256).
//
// Soundness assumptions:
// * The limbs of a are in the range (-2 ** 249, 2 ** 249).
// * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83).
func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
%{
from starkware.cairo.common.cairo_secp.secp_utils import N, pack
from starkware.python.math_utils import div_mod, safe_div
a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
value = res = div_mod(a, b, N)
%}
let (res) = nondet_bigint3();

%{ value = k_plus_one = safe_div(res * b - a, N) + 1 %}
let (k_plus_one) = nondet_bigint3();
let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);

let (res_b) = bigint_mul(res, b);
let n = BigInt3(N0, N1, N2);
let (k_n) = bigint_mul(k, n);

// We should now have res_b = k_n + a. Since the numbers are in unreduced form,
// we should handle the carry.

tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
assert [range_check_ptr + 0] = carry1 + 2 ** 127;

tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
assert [range_check_ptr + 1] = carry2 + 2 ** 127;

tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
assert [range_check_ptr + 2] = carry3 + 2 ** 127;

tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
assert [range_check_ptr + 3] = carry4 + 2 ** 127;

assert res_b.d4 - k_n.d4 + carry4 = 0;

let range_check_ptr = range_check_ptr + 4;

return (res=res);
}

func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
// just used to import N
%{
from starkware.cairo.common.cairo_secp.secp_utils import N, pack
from starkware.python.math_utils import div_mod, safe_div
a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
value = res = div_mod(a, b, N)
%}

%{
from starkware.cairo.common.cairo_secp.secp_utils import pack
from starkware.python.math_utils import div_mod, safe_div
a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
value = res = div_mod(a, b, N)
%}
let (res) = nondet_bigint3();

%{ value = k_plus_one = safe_div(res * b - a, N) + 1 %}
let (k_plus_one) = nondet_bigint3();
let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);

let (res_b) = bigint_mul(res, b);
let n = BigInt3(N0, N1, N2);
let (k_n) = bigint_mul(k, n);

tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
assert [range_check_ptr + 0] = carry1 + 2 ** 127;

tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
assert [range_check_ptr + 1] = carry2 + 2 ** 127;

tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
assert [range_check_ptr + 2] = carry3 + 2 ** 127;

tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
assert [range_check_ptr + 3] = carry4 + 2 ** 127;

assert res_b.d4 - k_n.d4 + carry4 = 0;

let range_check_ptr = range_check_ptr + 4;

return (res=res);
}

func test_div_mod_n{range_check_ptr: felt}() {
let a: BigInt3 = BigInt3(100, 99, 98);
let b: BigInt3 = BigInt3(10, 9, 8);

let (res) = div_mod_n(a, b);

assert res = BigInt3(
3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135
);

// test alternative hint
let (res_alt) = div_mod_n_alt(a, b);

assert res_alt = res;

return ();
}

func main{range_check_ptr: felt}() {
test_div_mod_n();

return ();
}
115 changes: 115 additions & 0 deletions cairo_programs/uint256.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
%builtins range_check

from starkware.cairo.common.uint256 import (
Uint256,
uint256_add,
split_64,
uint256_sqrt,
uint256_signed_nn,
uint256_unsigned_div_rem,
uint256_mul,
uint256_mul_div_mod
)
from starkware.cairo.common.alloc import alloc

func fill_array{range_check_ptr: felt}(
array: Uint256*, base: Uint256, step: Uint256, array_length: felt, iterator: felt
) {
if (iterator == array_length) {
return ();
}
let (res, carry_high) = uint256_add(step, base);
let (sqrt) = uint256_sqrt(res);

assert array[iterator] = sqrt;
return fill_array(array, base, array[iterator], array_length, iterator + 1);
}

func main{range_check_ptr: felt}() {
let x: Uint256 = Uint256(5, 2);
let y = Uint256(3, 7);
let (res, carry_high) = uint256_add(x, y);
assert res.low = 8;
assert res.high = 9;
assert carry_high = 0;

let (low, high) = split_64(850981239023189021389081239089023);
assert low = 7249717543555297151;
assert high = 46131785404667;

let (root) = uint256_sqrt(Uint256(17, 7));
assert root = Uint256(48805497317890012913, 0);

let (signed_nn) = uint256_signed_nn(Uint256(5, 2));
assert signed_nn = 1;
let (p) = uint256_signed_nn(Uint256(1, 170141183460469231731687303715884105728));
assert p = 0;
let (q) = uint256_signed_nn(Uint256(1, 170141183460469231731687303715884105727));
assert q = 1;

let (a_quotient, a_remainder) = uint256_unsigned_div_rem(Uint256(89, 72), Uint256(3, 7));
assert a_quotient = Uint256(10, 0);
assert a_remainder = Uint256(59, 2);

let (b_quotient, b_remainder) = uint256_unsigned_div_rem(
Uint256(-3618502788666131213697322783095070105282824848410658236509717448704103809099, 2),
Uint256(5, 2),
);
assert b_quotient = Uint256(1, 0);
assert b_remainder = Uint256(340282366920938463463374607431768211377, 0);

let (c_quotient, c_remainder) = uint256_unsigned_div_rem(
Uint256(340282366920938463463374607431768211455, 340282366920938463463374607431768211455),
Uint256(1, 0),
);

assert c_quotient = Uint256(340282366920938463463374607431768211455, 340282366920938463463374607431768211455);
assert c_remainder = Uint256(0, 0);

let (a_quotient_low, a_quotient_high, a_remainder) = uint256_mul_div_mod(
Uint256(89, 72),
Uint256(3, 7),
Uint256(107, 114),
);
assert a_quotient_low = Uint256(143276786071974089879315624181797141668, 4);
assert a_quotient_high = Uint256(0, 0);
assert a_remainder = Uint256(322372768661941702228460154409043568767, 101);

let (b_quotient_low, b_quotient_high, b_remainder) = uint256_mul_div_mod(
Uint256(-3618502788666131213697322783095070105282824848410658236509717448704103809099, 2),
Uint256(1, 1),
Uint256(5, 2),
);
assert b_quotient_low = Uint256(170141183460469231731687303715884105688, 1);
assert b_quotient_high = Uint256(0, 0);
assert b_remainder = Uint256(170141183460469231731687303715884105854, 1);

let (c_quotient_low, c_quotient_high, c_remainder) = uint256_mul_div_mod(
Uint256(340281070833283907490476236129005105807, 340282366920938463463374607431768211455),
Uint256(2447157533618445569039502, 0),
Uint256(0, 1),
);

assert c_quotient_low = Uint256(340282366920938463454053728725133866491, 2447157533618445569039501);
assert c_quotient_high = Uint256(0, 0);
assert c_remainder = Uint256(326588112914912836985603897252688572242, 0);

let (mult_low_a, mult_high_a) = uint256_mul(Uint256(59, 2), Uint256(10, 0));
assert mult_low_a = Uint256(590, 20);
assert mult_high_a = Uint256(0, 0);

let (mult_low_b: Uint256, mult_high_b: Uint256) = uint256_mul(
Uint256(271442546951262198976322048597925888860, 0),
Uint256(271442546951262198976322048597925888860, 0),
);
assert mult_low_b = Uint256(
42047520920204780886066537579778623760, 216529163594619381764978757921136443390
);
assert mult_high_b = Uint256(0, 0);

let array_length = 100;
let (sum_array: Uint256*) = alloc();
fill_array(sum_array, Uint256(57, 8), Uint256(17, 7), array_length, 0);

return ();
}
151 changes: 151 additions & 0 deletions cairo_programs/uint256_integration_tests.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
%builtins range_check bitwise

from starkware.cairo.common.uint256 import (
Uint256,
uint256_add,
split_64,
uint256_sqrt,
uint256_signed_nn,
uint256_unsigned_div_rem,
uint256_mul,
uint256_or,
uint256_reverse_endian,
)
from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin

func fill_array(array_start: felt*, base: felt, step: felt, iter: felt, last: felt) -> () {
if (iter == last) {
return ();
}
assert array_start[iter] = base + step;
return fill_array(array_start, base + step, step, iter + 1, last);
}

func fill_uint256_array{range_check_ptr: felt}(
array: Uint256*, base: Uint256, step: Uint256, array_len: felt, iterator: felt
) {
if (iterator == array_len) {
return ();
}
let (res: Uint256, carry_high: felt) = uint256_add(step, base);

assert array[iterator] = res;
return fill_uint256_array(array, base, array[iterator], array_len, iterator + 1);
}

func test_sqrt{range_check_ptr}(
base_array: Uint256*, new_array: Uint256*, iter: felt, last: felt
) -> () {
alloc_locals;

if (iter == last) {
return ();
}

let res: Uint256 = uint256_sqrt(base_array[iter]);
assert new_array[iter] = res;

return test_sqrt(base_array, new_array, iter + 1, last);
}

func test_signed_nn{range_check_ptr}(
base_array: Uint256*, new_array: felt*, iter: felt, last: felt
) -> () {
alloc_locals;

if (iter == last) {
return ();
}

let res: felt = uint256_signed_nn(base_array[iter]);
assert res = 1;
assert new_array[iter] = res;

return test_signed_nn(base_array, new_array, iter + 1, last);
}

func test_unsigned_div_rem{range_check_ptr}(
base_array: Uint256*, new_array: Uint256*, iter: felt, last: felt
) -> () {
alloc_locals;

if (iter == last) {
return ();
}

let (quotient: Uint256, remainder: Uint256) = uint256_unsigned_div_rem(
base_array[iter], Uint256(7, 8)
);
assert new_array[(iter * 2)] = quotient;
assert new_array[(iter * 2) + 1] = remainder;

return test_unsigned_div_rem(base_array, new_array, iter + 1, last);
}

func test_split_64{range_check_ptr}(
base_array: felt*, new_array: felt*, iter: felt, last: felt
) -> () {
alloc_locals;

if (iter == last) {
return ();
}

let (low: felt, high: felt) = split_64(base_array[iter]);
assert new_array[(iter * 2)] = low;
assert new_array[(iter * 2) + 1] = high;
return test_split_64(base_array, new_array, iter + 1, last);
}

func test_integration{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(
base_array: Uint256*, new_array: Uint256*, iter: felt, last: felt
) -> () {
alloc_locals;

if (iter == last) {
return ();
}

let (add: Uint256, carry_high: felt) = uint256_add(base_array[iter], base_array[iter + 1]);
let (quotient: Uint256, remainder: Uint256) = uint256_unsigned_div_rem(add, Uint256(5, 3));
let (low: Uint256, high: Uint256) = uint256_mul(quotient, remainder);
let (bitwise_or: Uint256) = uint256_or(low, high);
let (reverse_endian: Uint256) = uint256_reverse_endian(bitwise_or);
let (result: Uint256) = uint256_sqrt(reverse_endian);

assert new_array[iter] = result;
return test_integration(base_array, new_array, iter + 1, last);
}

func run_tests{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(array_len: felt) -> () {
alloc_locals;
let (uint256_array: Uint256*) = alloc();
fill_uint256_array(uint256_array, Uint256(57, 8), Uint256(57, 101), array_len, 0);

let (array_sqrt: Uint256*) = alloc();
test_sqrt(uint256_array, array_sqrt, 0, array_len);

let (array_signed_nn: felt*) = alloc();
test_signed_nn(uint256_array, array_signed_nn, 0, array_len);

let (array_unsigned_div_rem: Uint256*) = alloc();
test_unsigned_div_rem(uint256_array, array_unsigned_div_rem, 0, array_len);

let (felt_array: felt*) = alloc();
fill_array(felt_array, 0, 3, 0, array_len);

let (array_split_64: felt*) = alloc();
test_split_64(felt_array, array_split_64, 0, array_len);

let (array_test_integration: Uint256*) = alloc();
test_integration(uint256_array, array_test_integration, 0, array_len - 1);

return ();
}

func main{range_check_ptr: felt, bitwise_ptr: BitwiseBuiltin*}() {
run_tests(10);

return ();
}
Loading

0 comments on commit 32a892a

Please sign in to comment.