Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ProjectivePoint from types-rs in ec_op builtin impl #1532

Merged
merged 15 commits into from
Jan 5, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: Use `ProjectivePoint` from types-rs in ec_op builtin impl [#1532](https://github.com/lambdaclass/cairo-vm/pull/1532)

* feat(BREAKING): Replace `cairo-felt` crate with `starknet-types-core` (0.0.5) [#1408](https://github.com/lambdaclass/cairo-vm/pull/1408)

* feat(BREAKING): Add Cairo 1 proof mode compilation and execution [#1517] (https://github.com/lambdaclass/cairo-vm/pull/1517)
11 changes: 7 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 27 additions & 4 deletions fuzzer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ keccak = { workspace = true }
hashbrown = { workspace = true }
anyhow = { workspace = true }
thiserror-no-std = { workspace = true }
starknet-types-core = { version = "0.0.5", default-features = false, features = ["serde"] }
starknet-types-core = { version = "0.0.6", default-features = false, features = ["serde", "curve", "num-traits"] }

# only for std
num-prime = { version = "0.4.3", features = ["big-int"], optional = true }
11 changes: 6 additions & 5 deletions vm/src/math_utils/mod.rs
Original file line number Diff line number Diff line change
@@ -48,12 +48,13 @@ pub fn pow2_const_nz(n: u32) -> &'static NonZeroFelt {
/// # Examples
///
/// ```
/// # use crate::Felt252;
/// let positive = Felt252::new(5);
/// assert_eq!(signed_felt(positive), Felt252::from(5));
/// # use cairo_vm::{Felt252, math_utils::signed_felt};
/// # use num_bigint::BigInt;
/// let positive = Felt252::from(5);
/// assert_eq!(signed_felt(positive), BigInt::from(5));
///
/// let negative = Felt252::max_value();
/// assert_eq!(signed_felt(negative), Felt252::from(-1));
/// let negative = Felt252::MAX;
/// assert_eq!(signed_felt(negative), BigInt::from(-1));
/// ```

pub fn signed_felt(felt: Felt252) -> BigInt {
3 changes: 2 additions & 1 deletion vm/src/vm/errors/runner_errors.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@
#![allow(clippy::explicit_auto_deref)]

use crate::stdlib::{collections::HashSet, prelude::*};

use thiserror_no_std::Error;

use super::{memory_errors::MemoryError, trace_errors::TraceError};
@@ -101,6 +100,8 @@ pub enum RunnerError {
StrippedProgramNoMain,
#[error(transparent)]
Trace(#[from] TraceError),
#[error("EcOp builtin: Invalid Point")]
InvalidPoint,
}

#[cfg(test)]
89 changes: 38 additions & 51 deletions vm/src/vm/runners/builtin_runner/ec_op.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use crate::math_utils::{ec_add, ec_double};
use crate::stdlib::{borrow::Cow, prelude::*};
use crate::stdlib::{cell::RefCell, collections::HashMap};
use crate::types::instance_definitions::ec_op_instance_def::{
EcOpInstanceDef, CELLS_PER_EC_OP, INPUT_CELLS_PER_EC_OP,
};
use crate::types::relocatable::{MaybeRelocatable, Relocatable};
use crate::utils::{bigint_to_felt, felt_to_bigint, CAIRO_PRIME};
use crate::vm::errors::memory_errors::MemoryError;
use crate::vm::errors::runner_errors::RunnerError;
use crate::vm::vm_memory::memory::Memory;
use crate::vm::vm_memory::memory_segments::MemorySegmentManager;
use crate::Felt252;
use num_bigint::{BigInt, ToBigInt};
use num_bigint::BigInt;
use num_integer::{div_ceil, Integer};
use num_traits::{One, Zero};
use starknet_types_core::curve::ProjectivePoint;

use super::EC_OP_BUILTIN_NAME;

@@ -51,7 +50,6 @@ impl EcOpBuiltinRunner {
y.pow(2_u32) == (x.pow(3_u32) + alpha * x) + beta
}

#[allow(deprecated)]
///Returns the result of the EC operation P + m * Q.
/// where P = (p_x, p_y), Q = (q_x, q_y) are points on the elliptic curve defined as
/// y^2 = x^3 + alpha * x + beta (mod prime).
@@ -62,31 +60,30 @@ impl EcOpBuiltinRunner {
partial_sum: (Felt252, Felt252),
doubled_point: (Felt252, Felt252),
m: &Felt252,
alpha: &BigInt,
prime: &BigInt,
height: u32,
) -> Result<(BigInt, BigInt), RunnerError> {
let mut slope = felt_to_bigint(*m);
let mut partial_sum_b = (felt_to_bigint(partial_sum.0), felt_to_bigint(partial_sum.1));
let mut doubled_point_b = (
felt_to_bigint(doubled_point.0),
felt_to_bigint(doubled_point.1),
);
) -> Result<(Felt252, Felt252), RunnerError> {
let mut slope = m.to_bigint();
let mut partial_sum_b = ProjectivePoint::from_affine(partial_sum.0, partial_sum.1)
Oppen marked this conversation as resolved.
Show resolved Hide resolved
.map_err(|_| RunnerError::PointNotOnCurve(Box::new(partial_sum)))?;
let mut doubled_point_b = ProjectivePoint::from_affine(doubled_point.0, doubled_point.1)
.map_err(|_| RunnerError::PointNotOnCurve(Box::new(doubled_point)))?;
for _ in 0..height {
if (doubled_point_b.0.clone() - partial_sum_b.0.clone()).is_zero() {
#[allow(deprecated)]
if partial_sum_b.x() * doubled_point_b.z() == partial_sum_b.z() * doubled_point_b.x() {
return Err(RunnerError::EcOpSameXCoordinate(
Self::format_ec_op_error(partial_sum_b, slope, doubled_point_b)
.into_boxed_str(),
));
};
if !(slope.clone() & &BigInt::one()).is_zero() {
partial_sum_b = ec_add(partial_sum_b, doubled_point_b.clone(), prime)?;
Oppen marked this conversation as resolved.
Show resolved Hide resolved
partial_sum_b += &doubled_point_b;
}
doubled_point_b = ec_double(doubled_point_b, alpha, prime)?;
doubled_point_b = doubled_point_b.double();
slope = slope.clone() >> 1_u32;
}
Ok(partial_sum_b)
partial_sum_b
.to_affine()
.map(|p| (p.x(), p.y()))
.map_err(|_| RunnerError::InvalidPoint)
}

pub fn initialize_segments(&mut self, segments: &mut MemorySegmentManager) {
@@ -179,17 +176,12 @@ impl EcOpBuiltinRunner {
))));
};
}
let prime = CAIRO_PRIME.to_bigint().unwrap();
let result = EcOpBuiltinRunner::ec_op_impl(
(input_cells[0].to_owned(), input_cells[1].to_owned()),
(input_cells[2].to_owned(), input_cells[3].to_owned()),
input_cells[4],
#[allow(deprecated)]
&felt_to_bigint(alpha),
&prime,
self.ec_op_builtin.scalar_height,
)?;
let result = (bigint_to_felt(&result.0)?, bigint_to_felt(&result.1)?);
self.cache.borrow_mut().insert(x_addr, result.0);
self.cache.borrow_mut().insert(
(x_addr + 1usize)
@@ -259,10 +251,12 @@ impl EcOpBuiltinRunner {
}

pub fn format_ec_op_error(
p: (num_bigint::BigInt, num_bigint::BigInt),
p: ProjectivePoint,
m: num_bigint::BigInt,
q: (num_bigint::BigInt, num_bigint::BigInt),
q: ProjectivePoint,
) -> String {
let p = p.to_affine().map(|p| (p.x(), p.y())).unwrap_or_default();
let q = q.to_affine().map(|q| (q.x(), q.y())).unwrap_or_default();
format!("Cannot apply EC operation: computation reached two points with the same x coordinate. \n
Attempting to compute P + m * Q where:\n
P = {p:?} \n
@@ -278,7 +272,7 @@ mod tests {
use crate::serde::deserialize_program::BuiltinName;
use crate::stdlib::collections::HashMap;
use crate::types::program::Program;
use crate::utils::{test_utils::*, CAIRO_PRIME};
use crate::utils::test_utils::*;
use crate::vm::errors::cairo_run_errors::CairoRunError;
use crate::vm::errors::vm_errors::VirtualMachineError;
use crate::vm::runners::cairo_runner::CairoRunner;
@@ -548,18 +542,15 @@ mod tests {
felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"),
);
let m = Felt252::from(34);
let alpha = bigint!(1);
let height = 256;
let prime = (*CAIRO_PRIME).clone().into();
let result =
EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, &alpha, &prime, height);
let result = EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, height);
assert_eq!(
result,
Ok((
bigint_str!(
felt_str!(
"1977874238339000383330315148209250828062304908491266318460063803060754089297"
),
bigint_str!(
felt_str!(
"2969386888251099938335087541720168257053975603483053253007176033556822156706"
)
))
@@ -578,18 +569,15 @@ mod tests {
felt_hex!("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f"),
);
let m = Felt252::from(34);
let alpha = bigint!(1);
let height = 256;
let prime = (*CAIRO_PRIME).clone().into();
let result =
EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, &alpha, &prime, height);
let result = EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, height);
assert_eq!(
result,
Ok((
bigint_str!(
felt_str!(
"2778063437308421278851140253538604815869848682781135193774472480292420096757"
),
bigint_str!(
felt_str!(
"3598390311618116577316045819420613574162151407434885460365915347732568210029"
)
))
@@ -598,26 +586,25 @@ mod tests {

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
#[allow(deprecated)]
fn compute_ec_op_invalid_same_x_coordinate() {
let partial_sum = (Felt252::ONE, Felt252::from(9));
let doubled_point = (Felt252::ONE, Felt252::from(12));
let partial_sum = (
felt_hex!("0x6f0a1ddaf19c44781c8946db396f494a10ffab183c2d8cf6c4cd321a8d87fd9"),
felt_hex!("0x4afa52a9ef8c023d3385fddb6e1d78d57b0693b9b02d45d0f939b526d474c39"),
);
let doubled_point = (
felt_hex!("0x6f0a1ddaf19c44781c8946db396f494a10ffab183c2d8cf6c4cd321a8d87fd9"),
felt_hex!("0x4afa52a9ef8c023d3385fddb6e1d78d57b0693b9b02d45d0f939b526d474c39"),
);
let m = Felt252::from(34);
let alpha = bigint!(1);
let height = 256;
let prime = (*CAIRO_PRIME).clone().into();
let result =
EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, &alpha, &prime, height);
let result = EcOpBuiltinRunner::ec_op_impl(partial_sum, doubled_point, &m, height);
assert_eq!(
result,
Err(RunnerError::EcOpSameXCoordinate(
EcOpBuiltinRunner::format_ec_op_error(
(felt_to_bigint(partial_sum.0), felt_to_bigint(partial_sum.1)),
felt_to_bigint(m),
(
felt_to_bigint(doubled_point.0),
felt_to_bigint(doubled_point.1)
)
ProjectivePoint::from_affine(partial_sum.0, partial_sum.1).unwrap(),
m.to_bigint(),
ProjectivePoint::from_affine(doubled_point.0, doubled_point.1).unwrap(),
)
.into_boxed_str()
))
Loading