From 64bfa7de1b896d312d0dd848f27369c89e6ee276 Mon Sep 17 00:00:00 2001 From: enitrat Date: Mon, 23 Sep 2024 12:11:18 +0200 Subject: [PATCH 1/3] fix: ec_add --- crates/evm/src/precompiles/ec_add.cairo | 40 ++++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/crates/evm/src/precompiles/ec_add.cairo b/crates/evm/src/precompiles/ec_add.cairo index ff604c8b5..090407a2e 100644 --- a/crates/evm/src/precompiles/ec_add.cairo +++ b/crates/evm/src/precompiles/ec_add.cairo @@ -13,10 +13,12 @@ use evm::precompiles::Precompile; use garaga::core::circuit::AddInputResultTrait2; use utils::helpers::ToBytes; use utils::helpers::{load_word, U8SpanExTrait}; +use core::circuit::u96; 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)] @@ -45,7 +47,8 @@ pub impl EcAdd of Precompile { let (x, y) = match ec_add(x1, y1, x2, y2) { Option::Some((x, y)) => { (x, y) }, Option::None => { - return Result::Err(EVMError::InvalidParameter('invalid ec_add parameters')); + let fmtstring: ByteArray = format!("x1:{},y1:{},x2:{},y2:{}", x1, y1, x2, y2); + return Result::Err(EVMError::InvalidParameter(fmtstring.pending_word)); }, }; @@ -145,16 +148,16 @@ 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]) + >::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (check,).new_inputs(); @@ -189,7 +192,7 @@ fn add_ec_point_unchecked(xP: u384, yP: u384, xQ: u384, yQ: u384) -> (u384, u384 let modulus = TryInto::< _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + >::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -219,11 +222,11 @@ 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]) + >::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -245,7 +248,7 @@ fn eq_mod_p(a: u384, b: u384) -> bool { let modulus = TryInto::< _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + >::try_into(PRIME) .unwrap(); // BN254 prime field modulus let outputs = (sub,).new_inputs().next_2(a).next_2(b).done_2().eval(modulus).unwrap(); @@ -261,10 +264,25 @@ fn eq_neg_mod_p(a: u384, b: u384) -> bool { let modulus = TryInto::< _, CircuitModulus - >::try_into([0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]) + >::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); + } +} From 8a45c9c1f00b6da29a46d80dc5ce869407bd3d86 Mon Sep 17 00:00:00 2001 From: enitrat Date: Mon, 23 Sep 2024 13:25:13 +0200 Subject: [PATCH 2/3] fix: ec_mul --- crates/evm/src/precompiles/ec_mul.cairo | 39 +++++++++++++++++-------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/crates/evm/src/precompiles/ec_mul.cairo b/crates/evm/src/precompiles/ec_mul.cairo index 955d77fbc..8d7c0b801 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); + } } From 9b20c5759289fd5d37d4d60f1243ea5692d4e2f5 Mon Sep 17 00:00:00 2001 From: enitrat Date: Mon, 23 Sep 2024 13:25:32 +0200 Subject: [PATCH 3/3] fmt --- crates/evm/src/precompiles/ec_add.cairo | 33 ++++++++++--------------- crates/evm/src/precompiles/ec_mul.cairo | 2 +- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/crates/evm/src/precompiles/ec_add.cairo b/crates/evm/src/precompiles/ec_add.cairo index 090407a2e..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, @@ -13,12 +14,15 @@ use evm::precompiles::Precompile; use garaga::core::circuit::AddInputResultTrait2; use utils::helpers::ToBytes; use utils::helpers::{load_word, U8SpanExTrait}; -use core::circuit::u96; const BASE_COST: u64 = 150; const U256_BYTES_LEN: usize = 32; -const PRIME: [u96; 4] = [0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0]; +const PRIME: [ + u96 + ; 4] = [ + 0x6871ca8d3c208c16d87cfd47, 0xb85045b68181585d97816a91, 0x30644e72e131a029, 0x0 +]; pub impl EcAdd of Precompile { #[inline(always)] @@ -47,8 +51,7 @@ pub impl EcAdd of Precompile { let (x, y) = match ec_add(x1, y1, x2, y2) { Option::Some((x, y)) => { (x, y) }, Option::None => { - let fmtstring: ByteArray = format!("x1:{},y1:{},x2:{},y2:{}", x1, y1, x2, y2); - return Result::Err(EVMError::InvalidParameter(fmtstring.pending_word)); + return Result::Err(EVMError::InvalidParameter('invalid ec_add parameters')); }, }; @@ -155,9 +158,7 @@ pub fn is_on_curve(x: u384, y: u384) -> bool { let rhs = circuit_add(x3, b); let check = circuit_sub(y2, rhs); - let modulus = TryInto::< - _, CircuitModulus - >::try_into(PRIME) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (check,).new_inputs(); @@ -190,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(PRIME) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -224,9 +223,7 @@ pub fn double_ec_point_unchecked(x: u384, y: u384) -> (u384, u384) { let nx = circuit_sub(circuit_sub(slope_sqr, _x), _x); let ny = circuit_sub(circuit_mul(slope, circuit_sub(_x, nx)), _y); - let modulus = TryInto::< - _, CircuitModulus - >::try_into(PRIME) + let modulus = TryInto::<_, CircuitModulus>::try_into(PRIME) .unwrap(); // BN254 prime field modulus let mut circuit_inputs = (nx, ny,).new_inputs(); @@ -246,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(PRIME) + 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(); @@ -262,9 +257,7 @@ 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(PRIME) + 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(); @@ -273,7 +266,7 @@ fn eq_neg_mod_p(a: u384, b: u384) -> bool { } #[cfg(test)] -mod tests{ +mod tests { use super::ec_add; #[test] fn test_ec_add() { diff --git a/crates/evm/src/precompiles/ec_mul.cairo b/crates/evm/src/precompiles/ec_mul.cairo index 8d7c0b801..110d69591 100644 --- a/crates/evm/src/precompiles/ec_mul.cairo +++ b/crates/evm/src/precompiles/ec_mul.cairo @@ -135,7 +135,7 @@ mod tests { #[test] fn test_ec_mul() { - let (x1,y1,s) = (1,2,2); + 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);