Skip to content

Commit

Permalink
add circle points
Browse files Browse the repository at this point in the history
  • Loading branch information
schouhy committed Jul 15, 2024
1 parent a6a5aa0 commit f49d75c
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
120 changes: 120 additions & 0 deletions stwo_cairo_verifier/src/circle.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use stwo_cairo_verifier::fields::m31::{M31, m31};

pub const M31_CIRCLE_GEN: CirclePointM31 =
CirclePointM31 { x: M31 { inner: 2 }, y: M31 { inner: 1268011823 }, };

#[derive(Drop, Copy, Debug, PartialEq, Eq)]
pub struct CirclePointM31 {
pub x: M31,
pub y: M31,
}

#[generate_trait]
pub impl CirclePointM31Impl of CirclePointM31Trait {
// Returns the neutral element of the circle.
fn zero() -> CirclePointM31 {
CirclePointM31 { x: m31(1), y: m31(0) }
}

fn mul(self: @CirclePointM31, mut scalar: u32) -> CirclePointM31 {
let mut result = Self::zero();
let mut cur = *self;
while scalar > 0 {
if scalar & 1 == 1 {
result = result + cur;
}
cur = cur + cur;
scalar = scalar / 2;
};
result
}
}

impl CirclePointM31Add of Add<CirclePointM31> {
// The operation of the circle as a group with additive notation.
fn add(lhs: CirclePointM31, rhs: CirclePointM31) -> CirclePointM31 {
CirclePointM31 { x: lhs.x * rhs.x - lhs.y * rhs.y, y: lhs.x * rhs.y + lhs.y * rhs.x }
}
}

#[cfg(test)]
mod tests {
use super::{M31_CIRCLE_GEN, CirclePointM31, CirclePointM31Impl};
use stwo_cairo_verifier::fields::m31::m31;
use stwo_cairo_verifier::utils::pow;

#[test]
fn test_add_1() {
let i = CirclePointM31 { x: m31(0), y: m31(1) };
let result = i + i;
let expected_result = CirclePointM31 { x: -m31(1), y: m31(0) };

assert_eq!(result, expected_result);
}

#[test]
fn test_add_2() {
let point_1 = CirclePointM31 { x: m31(750649172), y: m31(1991648574) };
let point_2 = CirclePointM31 { x: m31(1737427771), y: m31(309481134) };
let result = point_1 + point_2;
let expected_result = CirclePointM31 { x: m31(1476625263), y: m31(1040927458) };

assert_eq!(result, expected_result);
}

#[test]
fn test_zero_1() {
let result = CirclePointM31Impl::zero();
let expected_result = CirclePointM31 { x: m31(1), y: m31(0) };
assert_eq!(result, expected_result);
}

#[test]
fn test_zero_2() {
let point_1 = CirclePointM31 { x: m31(750649172), y: m31(1991648574) };
let point_2 = CirclePointM31Impl::zero();
let expected_result = point_1.clone();
let result = point_1 + point_2;

assert_eq!(result, expected_result);
}

#[test]
fn test_mul_1() {
let point_1 = CirclePointM31 { x: m31(750649172), y: m31(1991648574) };
let result = point_1.mul(5);
let expected_result = point_1 + point_1 + point_1 + point_1 + point_1;

assert_eq!(result, expected_result);
}

#[test]
fn test_mul_2() {
let point_1 = CirclePointM31 { x: m31(750649172), y: m31(1991648574) };
let result = point_1.mul(8);
let mut expected_result = point_1 + point_1;
expected_result = expected_result + expected_result;
expected_result = expected_result + expected_result;

assert_eq!(result, expected_result);
}

#[test]
fn test_mul_3() {
let point_1 = CirclePointM31 { x: m31(750649172), y: m31(1991648574) };
let result = point_1.mul(418776494);
let expected_result = CirclePointM31 { x: m31(1987283985), y: m31(1500510905) };

assert_eq!(result, expected_result);
}

#[test]
fn test_generator_order() {
let mut result = M31_CIRCLE_GEN.mul(pow(2, 30).try_into().unwrap());
let expected_result = CirclePointM31 { x: -m31(1), y: m31(0) };

// Assert `M31_CIRCLE_GEN^{2^30}` equals `-1`.
assert_eq!(expected_result, result);
}
}

1 change: 1 addition & 0 deletions stwo_cairo_verifier/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod channel;
mod circle;
mod fields;
mod utils;
mod vcs;
Expand Down
31 changes: 31 additions & 0 deletions stwo_cairo_verifier/src/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,34 @@ pub fn pack4(cur: felt252, values: [BaseField; 4]) -> felt252 {
(((cur * M31_SHIFT + x0.into()) * M31_SHIFT + x1.into()) * M31_SHIFT + x2.into()) * M31_SHIFT
+ x3.into()
}

pub fn pow(base: u32, mut exponent: u32) -> u32 {
let mut result = 1;
let mut base_power = base;
loop {
if exponent & 1 == 1 {
result *= base_power;
}
exponent = exponent / 2;
if exponent == 0 {
break;
}
base_power = base_power * base_power;
};
result
}

#[cfg(test)]
mod tests {
use super::pow;

#[test]
fn test_pow() {
assert_eq!(25, pow(5, 2));
assert_eq!(16, pow(2, 4));
assert_eq!(1024, pow(2, 10));
assert_eq!(4096, pow(2, 12));
assert_eq!(1048576, pow(2, 20));
}
}

0 comments on commit f49d75c

Please sign in to comment.