Skip to content

Commit

Permalink
Merge pull request #16 from HerodotusDev/feat/fri
Browse files Browse the repository at this point in the history
Implementation of Fast Reed-Solomon Interactive Proof of Proximity (FRIPoP)
  • Loading branch information
Okm165 authored Dec 29, 2023
2 parents c02f915 + 64405d9 commit 986deb9
Show file tree
Hide file tree
Showing 31 changed files with 2,821 additions and 58 deletions.
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[package]
name = "cairo_verifier"
version = "0.1.0"
version = "0.1.0"
41 changes: 22 additions & 19 deletions src/channel/channel.cairo
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
use cairo_verifier::common::{
flip_endianness::FlipEndiannessTrait, array_append::ArrayAppendTrait, blake2s::blake2s
flip_endianness::FlipEndiannessTrait, array_append::ArrayAppendTrait, blake2s::blake2s,
consts::{
C_PRIME_AS_UINT256_LOW, C_PRIME_AS_UINT256_HIGH, STARK_PRIME, MONTGOMERY_R,
MONTGOMERY_R_INVERSE
}
};
use poseidon::poseidon_hash_span;
use core::integer::BoundedU128;

const C_PRIME_AS_UINT256_LOW: u128 = 31;
const C_PRIME_AS_UINT256_HIGH: u128 =
329648542954659146201578277794459156480; // 31 * 0x8000000000000110000000000000000;
const STARK_PRIME: u256 =
3618502788666131213697322783095070105623107215331596699973092056135872020481;
const MONTGOMERY_R: felt252 =
3618502788666127798953978732740734578953660990361066340291730267701097005025; // 2**256 % STARK_PRIME
const MONTGOMERY_R_INVERSE: felt252 =
113078212145816603762751633895895194930089271709401121343797004406777446400;

#[derive(Drop)]
struct Channel {
digest: u256,
Expand All @@ -34,21 +28,30 @@ impl ChannelImpl of ChannelTrait {
blake2s(hash_data).flip_endianness()
}

fn random_felts_to_prover(ref self: Channel, mut n: felt252) -> Array<felt252> {
let mut res = ArrayTrait::<felt252>::new();
fn random_felt_to_prover(ref self: Channel) -> felt252 {
let mut res: felt252 = 0;

// To ensure a uniform distribution over field elements, if the generated 256-bit number x is in
// range [0, C * PRIME), take x % PRIME. Otherwise, regenerate.
// The maximal possible C is 2**256//PRIME = 31.

loop {
let rand = self.random_uint256_to_prover();
if (rand < u256 { low: C_PRIME_AS_UINT256_LOW, high: C_PRIME_AS_UINT256_HIGH }) {
let to_append = (rand % STARK_PRIME).try_into().unwrap();
res = to_append * MONTGOMERY_R_INVERSE;
break;
}
};
res
}

fn random_felts_to_prover(ref self: Channel, mut n: felt252) -> Array<felt252> {
let mut res = ArrayTrait::<felt252>::new();
loop {
if n != 0 {
let rand = self.random_uint256_to_prover();
if (rand < u256 { low: C_PRIME_AS_UINT256_LOW, high: C_PRIME_AS_UINT256_HIGH }) {
n -= 1;
let to_append = (rand % STARK_PRIME).try_into().unwrap();
res.append(to_append * MONTGOMERY_R_INVERSE);
}
res.append(self.random_felt_to_prover());
n -= 1;
} else {
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/common.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ mod flip_endianness;
mod from_span;
mod horner_eval;
mod array_append;
mod math;
mod array_print;
mod array_extend;
mod consts;

#[cfg(test)]
mod tests;
13 changes: 13 additions & 0 deletions src/common/array_extend.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[generate_trait]
impl ArrayExtend<T, +Copy<T>, +Drop<T>> of ArrayExtendTrait<T> {
fn extend(ref self: Array<T>, span: Span<T>) {
let mut i = 0;
loop {
if i == span.len() {
break;
};
self.append(*span.at(i));
i += 1;
};
}
}
17 changes: 17 additions & 0 deletions src/common/consts.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const STARK_PRIME: u256 =
3618502788666131213697322783095070105623107215331596699973092056135872020481;
const STARK_PRIME_MINUS_TWO: felt252 =
3618502788666131213697322783095070105623107215331596699973092056135872020479;

const FIELD_GENERATOR: felt252 = 3;
const FIELD_GENERATOR_INVERSE: felt252 =
1206167596222043737899107594365023368541035738443865566657697352045290673494;

const MONTGOMERY_R: felt252 =
3618502788666127798953978732740734578953660990361066340291730267701097005025; // 2**256 % STARK_PRIME
const MONTGOMERY_R_INVERSE: felt252 =
113078212145816603762751633895895194930089271709401121343797004406777446400;

const C_PRIME_AS_UINT256_LOW: u128 = 31;
const C_PRIME_AS_UINT256_HIGH: u128 =
329648542954659146201578277794459156480; // 31 * 0x8000000000000110000000000000000;
2 changes: 1 addition & 1 deletion src/common/horner_eval.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// `point` is the value at which the polynomial will be evaluated.
// The function returns the polynomial evaluation as `felt252`.

fn horner_eval(coefs: Array<felt252>, point: felt252) -> felt252 {
fn horner_eval(coefs: Span<felt252>, point: felt252) -> felt252 {
let mut res = 0;
let mut i = coefs.len();
loop {
Expand Down
29 changes: 29 additions & 0 deletions src/common/math.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use cairo_verifier::common::consts::STARK_PRIME_MINUS_TWO;

fn pow(base: felt252, exp: felt252) -> felt252 {
if exp == 0 {
return 1;
}
let mut exp: u256 = exp.into();
let mut res = 1;
let mut curr_base = base;

loop {
if exp == 0 {
break;
} else {
if exp % 2 == 1 {
res = res * curr_base;
}
curr_base = curr_base * curr_base;
exp = exp / 2;
}
};
res
}

fn mul_inverse(x: felt252) -> felt252 {
// From Fermat's little theorem, a ^ (p - 1) = 1 when p is prime and a != 0. Since a ^ (p - 1) = a · a ^ (p - 2) we have that
// a ^ (p - 2) is the multiplicative inverse of a modulo p.
pow(x, STARK_PRIME_MINUS_TWO)
}
1 change: 1 addition & 0 deletions src/common/tests.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ mod test_flip_endianness;
mod test_from_span;
mod test_horner_eval;
mod test_array_append;
mod test_math;
9 changes: 5 additions & 4 deletions src/common/tests/test_horner_eval.cairo
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use core::array::ArrayTrait;
use cairo_verifier::common::horner_eval::horner_eval;

#[test]
#[available_gas(9999999999)]
fn test_horner_eval_0() {
let mut coefs = ArrayTrait::<felt252>::new();
let eval = horner_eval(coefs, 1);
let eval = horner_eval(coefs.span(), 1);
assert(eval == 0, 'invalid evaluation result');
}

Expand All @@ -13,7 +14,7 @@ fn test_horner_eval_0() {
fn test_horner_eval_1() {
let mut coefs = ArrayTrait::<felt252>::new();
coefs.append(1);
let eval = horner_eval(coefs, 7);
let eval = horner_eval(coefs.span(), 7);
assert(eval == 1, 'invalid evaluation result');
}

Expand All @@ -26,7 +27,7 @@ fn test_horner_eval_2() {
coefs.append(19);
coefs.append(1);
coefs.append(9);
let eval = horner_eval(coefs, 13);
let eval = horner_eval(coefs.span(), 13);
assert(eval == 262591, 'invalid evaluation result');
}

Expand All @@ -48,6 +49,6 @@ fn test_horner_eval_3() {
coefs.append(7);
coefs.append(111);
coefs.append(1);
let eval = horner_eval(coefs, 19);
let eval = horner_eval(coefs.span(), 19);
assert(eval == 288577899334361215, 'invalid evaluation result');
}
79 changes: 79 additions & 0 deletions src/common/tests/test_math.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use cairo_verifier::common::math::{pow, mul_inverse};

#[test]
#[available_gas(9999999999)]
fn test_pow_1() {
let base = 1934568044210770965733097210694395167600009938751278224656090409051406060084;
let exp = 69439516760000993875127;
assert(
pow(
base, exp
) == 2804690217475462062143361339624939640984649667966511418446363596075299761851,
'Invalid value'
);
}

#[test]
#[available_gas(9999999999)]
fn test_pow_2() {
let base = 193456804421077096570009938751278224656090409051406060084;
let exp = 193456804421077096570009938751278224656090409051406060084;
assert(
pow(
base, exp
) == 2672162222334975109199941471365701890765112108683608796920114577809390903720,
'Invalid value'
);
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_1() {
let x = 9751091999414713;
let inv_x = mul_inverse(x);
assert(x * inv_x == 1, 'Invalid value');
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_2() {
let x = 97199414713;
let inv_x = mul_inverse(x);
assert(x * inv_x == 1, 'Invalid value');
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_3() {
let x = 92011457780;
let inv_x = mul_inverse(x);
assert(x * inv_x == 1, 'Invalid value');
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_4() {
let x = 3;
let inv_x = mul_inverse(x);
assert(
inv_x == 1206167596222043737899107594365023368541035738443865566657697352045290673494,
'Invalid value'
);
assert(x * inv_x == 1, 'Invalid value');
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_5() {
let x = 193456804421077096570009938751278224656090409051406060084;
let inv_inv_x = mul_inverse(mul_inverse(x));
assert(x == inv_inv_x, 'Invalid value');
}

#[test]
#[available_gas(9999999999)]
fn test_mul_inverse_6() {
let x = 19345680409051406060084;
let inv_inv_x = mul_inverse(mul_inverse(x));
assert(x == inv_inv_x, 'Invalid value');
}
10 changes: 10 additions & 0 deletions src/fri.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod fri_formula;
mod fri_group;
mod fri_layer;
mod fri_config;
mod fri_first_layer;
mod fri_last_layer;
mod fri;

#[cfg(test)]
mod tests;
Loading

0 comments on commit 986deb9

Please sign in to comment.