diff --git a/noir-projects/noir-protocol-circuits/crates/types/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/types/Nargo.toml index e8a6e8f2949..ffe4254dd99 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/types/Nargo.toml @@ -5,5 +5,4 @@ authors = [""] compiler_version = ">=0.18.0" [dependencies] -ec = { tag = "v0.1.2", git = "https://github.com/noir-lang/ec" } sha256 = { tag = "v0.1.2", git = "https://github.com/noir-lang/sha256" } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index eeb33844923..656aef3b12c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -10,13 +10,13 @@ use crate::{ hash::poseidon2_hash_with_separator, public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM}, traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField}, + utils::field::{pow, sqrt}, }; // We do below because `use crate::point::Point;` does not work use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; use crate::public_keys::AddressPoint; -use ec::{pow, sqrt}; use std::{ embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key}, ops::Add, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr index 91ddbe290b7..5f396de8d1c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr @@ -51,6 +51,51 @@ pub fn min(f1: Field, f2: Field) -> Field { } } +global C1: u32 = 28; +global C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055; +global C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904; + +pub(crate) fn pow(x: Field, y: Field) -> Field { + let mut r = 1 as Field; + let b: [u1; 254] = y.to_le_bits(); + + for i in 0..254 { + r *= r; + r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field); + } + + r +} + +// Tonelli-Shanks algorithm for computing the square root of a Field element. +// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field +// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1), +// and C5 = ZETA^C2, where ZETA is a non-square element of Field. +// These are pre-computed above as globals. +pub(crate) fn sqrt(x: Field) -> Field { + let mut z = pow(x, C3); + let mut t = z * z * x; + z *= x; + let mut b = t; + let mut c = C5; + + for i in 0..(C1 - 1) { + for _j in 1..(C1 - i - 1) { + b *= b; + } + + z *= if b == 1 { 1 } else { c }; + + c *= c; + + t *= if b == 1 { 1 } else { c }; + + b = t; + } + + z +} + #[test] unconstrained fn bytes_field_test() { // Tests correctness of field_from_bytes_32_trunc against existing methods