diff --git a/crates/evm/src/precompiles/ec_add.cairo b/crates/evm/src/precompiles/ec_add.cairo index ff604c8b5..5af4a1fa7 100644 --- a/crates/evm/src/precompiles/ec_add.cairo +++ b/crates/evm/src/precompiles/ec_add.cairo @@ -1,5 +1,6 @@ use core::circuit::CircuitElement as CE; use core::circuit::CircuitInput as CI; +use core::circuit::u96; use core::circuit::{ u384, CircuitElement, CircuitInput, circuit_add, circuit_sub, circuit_mul, circuit_inverse, @@ -17,6 +18,11 @@ use utils::helpers::{load_word, U8SpanExTrait}; const BASE_COST: u64 = 150; const U256_BYTES_LEN: usize = 32; +const PRIME: [ + u96 + ; 4] = [ + 0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0 +]; pub impl EcAdd of Precompile { #[inline(always)] @@ -145,16 +151,14 @@ pub fn ec_safe_add(x1: u384, y1: u384, x2: u384, y2: u384) -> Option<(u384, u384 pub fn is_on_curve(x: u384, y: u384) -> bool { let (b, _x, _y) = (CE::> {}, CE::> {}, CE::> {}); - // Compute (y^2 - (x^2 + b)) % p_bn254 + // Compute (y^2 - (x^3 + b)) % p_bn254 let x2 = circuit_mul(_x, _x); + let x3 = circuit_mul(x2, _x); let y2 = circuit_mul(_y, _y); - let y3 = circuit_mul(_y, y2); - let rhs = circuit_add(x2, b); - let check = circuit_sub(y3, rhs); + let rhs = circuit_add(x3, b); + let check = circuit_sub(y2, rhs); - let modulus = TryInto::< - _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (check,).new_inputs(); @@ -187,9 +191,7 @@ fn add_ec_point_unchecked(xP: u384, yP: u384, xQ: u384, yQ: u384) -> (u384, u384 let nx = circuit_sub(circuit_sub(slope_sqr, _xP), _xQ); let ny = circuit_sub(circuit_mul(slope, circuit_sub(_xP, nx)), _yP); - let modulus = TryInto::< - _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -219,11 +221,9 @@ pub fn double_ec_point_unchecked(x: u384, y: u384) -> (u384, u384) { let slope_sqr = circuit_mul(slope, slope); let nx = circuit_sub(circuit_sub(slope_sqr, _x), _x); - let ny = circuit_sub(_y, circuit_mul(slope, circuit_sub(_x, nx))); + let ny = circuit_sub(circuit_mul(slope, circuit_sub(_x, nx)), _y); - let modulus = TryInto::< - _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -243,9 +243,7 @@ fn eq_mod_p(a: u384, b: u384) -> bool { let in2 = CircuitElement::> {}; let sub = circuit_sub(in1, in2); - let modulus = TryInto::< - _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let outputs = (sub,).new_inputs().next_2(a).next_2(b).done_2().eval(modulus).unwrap(); @@ -259,12 +257,25 @@ fn eq_neg_mod_p(a: u384, b: u384) -> bool { let _b = CE::> {}; let check = circuit_add(_a, _b); - let modulus = TryInto::< - _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let outputs = (check,).new_inputs().next_2(a).next_2(b).done_2().eval(modulus).unwrap(); return outputs.get_output(check).is_zero(); } + +#[cfg(test)] +mod tests { + use super::ec_add; + #[test] + fn test_ec_add() { + let x1 = 1; + let y1 = 2; + let x2 = 1; + let y2 = 2; + let (x, y) = ec_add(x1, y1, x2, y2).expect('ec_add failed'); + assert_eq!(x, 0x030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3); + assert_eq!(y, 0x15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4); + } +} diff --git a/crates/evm/src/precompiles/ec_mul.cairo b/crates/evm/src/precompiles/ec_mul.cairo index 955d77fbc..110d69591 100644 --- a/crates/evm/src/precompiles/ec_mul.cairo +++ b/crates/evm/src/precompiles/ec_mul.cairo @@ -94,7 +94,11 @@ fn get_bits_little(s: u256) -> Array { s_low = q; }; let mut s_high = s.high; - + if s_high != 0 { + while bits.len() != 128 { + bits.append(0); + } + } while s_high != 0 { let (q, r) = core::traits::DivRem::div_rem(s_high, 2); bits.append(r.into()); @@ -108,21 +112,32 @@ fn get_bits_little(s: u256) -> Array { // Returns Option::None in case of point at infinity. // The size of bits array must be at minimum 2 and the point must be on the curve. fn ec_mul_inner(pt: (u384, u384), mut bits: Array) -> Option<(u384, u384)> { - let (x_o, y_o) = pt; - let mut pt = Option::Some(pt); + let (mut temp_x, mut temp_y) = pt; + let mut result: Option<(u384, u384)> = Option::None; while let Option::Some(bit) = bits.pop_front() { - match pt { - Option::Some((xt, yt)) => pt = Option::Some(double_ec_point_unchecked(xt, yt)), - Option::None => pt = Option::None, - } - if bit != 0 { - match pt { - Option::Some((xt, yt)) => pt = ec_safe_add(x_o, y_o, xt, yt), - Option::None => pt = Option::Some((x_o, y_o)), + match result { + Option::Some((xr, yr)) => result = ec_safe_add(temp_x, temp_y, xr, yr), + Option::None => result = Option::Some((temp_x, temp_y)), }; }; + let (_temp_x, _temp_y) = double_ec_point_unchecked(temp_x, temp_y); + temp_x = _temp_x; + temp_y = _temp_y; }; - pt + return result; +} + +#[cfg(test)] +mod tests { + use super::ec_mul; + + #[test] + fn test_ec_mul() { + let (x1, y1, s) = (1, 2, 2); + let (x, y) = ec_mul(x1, y1, s).expect('ec_mul failed'); + assert_eq!(x, 0x030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3); + assert_eq!(y, 0x15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4); + } }