From e5828d465aa66d8826f29dc1ebe470bef77ed634 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 13 Oct 2023 19:33:43 +0100 Subject: [PATCH 01/10] feat: solve `fixed_base_scalar_mul` black box functions in rust --- Cargo.lock | 16 ++- acvm-repo/acir_field/src/generic_ark.rs | 4 + .../src/pwg/blackbox/fixed_base_scalar_mul.rs | 8 +- acvm-repo/acvm/src/pwg/blackbox/mod.rs | 2 +- acvm-repo/acvm/tests/solver.rs | 7 -- .../barretenberg_blackbox_solver/Cargo.toml | 2 - .../barretenberg_blackbox_solver/src/lib.rs | 13 +-- .../src/wasm/mod.rs | 6 -- .../src/wasm/scalar_mul.rs | 98 ------------------- acvm-repo/blackbox_solver/Cargo.toml | 3 + acvm-repo/blackbox_solver/src/lib.rs | 89 ++++++++++++++++- acvm-repo/brillig_vm/src/black_box.rs | 6 +- acvm-repo/brillig_vm/src/lib.rs | 7 -- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 7 -- cspell.json | 1 + tooling/lsp/src/lib.rs | 8 -- 16 files changed, 113 insertions(+), 164 deletions(-) delete mode 100644 acvm-repo/barretenberg_blackbox_solver/src/wasm/scalar_mul.rs diff --git a/Cargo.lock b/Cargo.lock index 86df9e1a13b..1a26bcb0a72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,8 +56,11 @@ name = "acvm_blackbox_solver" version = "0.28.0" dependencies = [ "acir", + "ark-ec", "blake2", + "grumpkin", "k256", + "num-bigint", "p256", "sha2", "sha3", @@ -455,9 +458,7 @@ dependencies = [ "acvm_blackbox_solver", "flate2", "getrandom", - "hex", "js-sys", - "num-bigint", "pkg-config", "reqwest", "rust-embed", @@ -1828,6 +1829,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "grumpkin" +version = "0.1.0" +source = "git+https://github.com/noir-lang/grumpkin#56d99799381f79e42148aaef0de2b0cf9a4b9a5d" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-std", +] + [[package]] name = "h2" version = "0.3.20" diff --git a/acvm-repo/acir_field/src/generic_ark.rs b/acvm-repo/acir_field/src/generic_ark.rs index 63e0d3d0d98..0f4be21ad54 100644 --- a/acvm-repo/acir_field/src/generic_ark.rs +++ b/acvm-repo/acir_field/src/generic_ark.rs @@ -248,6 +248,10 @@ impl FieldElement { self.0.inverse_in_place().map(|f| FieldElement(*f)) } + pub fn from_repr(field: F) -> Self { + Self(field) + } + // XXX: This method is used while this field element // implementation is not generic. pub fn into_repr(self) -> F { diff --git a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs b/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs index 975025971dc..b489d997339 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs @@ -3,13 +3,9 @@ use acir::{ native_types::{Witness, WitnessMap}, }; -use crate::{ - pwg::{insert_value, witness_to_value, OpcodeResolutionError}, - BlackBoxFunctionSolver, -}; +use crate::pwg::{insert_value, witness_to_value, OpcodeResolutionError}; pub(super) fn fixed_base_scalar_mul( - backend: &impl BlackBoxFunctionSolver, initial_witness: &mut WitnessMap, low: FunctionInput, high: FunctionInput, @@ -18,7 +14,7 @@ pub(super) fn fixed_base_scalar_mul( let low = witness_to_value(initial_witness, low.witness)?; let high = witness_to_value(initial_witness, high.witness)?; - let (pub_x, pub_y) = backend.fixed_base_scalar_mul(low, high)?; + let (pub_x, pub_y) = crate::blackbox_solver::fixed_base_scalar_mul(low, high)?; insert_value(&outputs.0, pub_x, initial_witness)?; insert_value(&outputs.1, pub_y, initial_witness)?; diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index c4d9d561f46..14ded91707d 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -149,7 +149,7 @@ pub(crate) fn solve( *output, ), BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { - fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) + fixed_base_scalar_mul(initial_witness, *low, *high, *outputs) } BlackBoxFuncCall::RecursiveAggregation { output_aggregation_object, .. } => { // Solve the output of the recursive aggregation to zero to prevent missing assignment errors diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index 1d287d70c1b..a16bb78c81f 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -36,13 +36,6 @@ impl BlackBoxFunctionSolver for StubbedBackend { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { panic!("Path not trodden by this test") } - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - panic!("Path not trodden by this test") - } } // Reenable these test cases once we move the brillig implementation of inversion down into the acvm stdlib. diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index acecb24c142..96bf3e7dcff 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml @@ -16,8 +16,6 @@ repository.workspace = true acir.workspace = true acvm_blackbox_solver.workspace = true thiserror.workspace = true -hex.workspace = true -num-bigint.workspace = true rust-embed = { version = "6.6.0", features = [ "debug-embed", diff --git a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs b/acvm-repo/barretenberg_blackbox_solver/src/lib.rs index c3a1d457897..d5cfc9591f7 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/lib.rs @@ -9,7 +9,7 @@ mod wasm; use wasm::Barretenberg; -use self::wasm::{Pedersen, ScalarMul, SchnorrSig}; +use self::wasm::{Pedersen, SchnorrSig}; #[deprecated = "The `BarretenbergSolver` is a temporary solution and will be removed in future."] pub struct BarretenbergSolver { @@ -71,15 +71,4 @@ impl BlackBoxFunctionSolver for BarretenbergSolver { .encrypt(inputs.to_vec(), domain_separator) .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Pedersen, err.to_string())) } - - fn fixed_base_scalar_mul( - &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - #[allow(deprecated)] - self.blackbox_vendor.fixed_base(low, high).map_err(|err| { - BlackBoxResolutionError::Failed(BlackBoxFunc::FixedBaseScalarMul, err.to_string()) - }) - } } diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs b/acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs index 22520725dca..10b1ab22a8d 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs @@ -6,13 +6,11 @@ mod barretenberg_structures; mod pedersen; -mod scalar_mul; mod schnorr; use barretenberg_structures::Assignments; pub(crate) use pedersen::Pedersen; -pub(crate) use scalar_mul::ScalarMul; pub(crate) use schnorr::SchnorrSig; /// The number of bytes necessary to store a `FieldElement`. @@ -34,10 +32,6 @@ pub(crate) enum FeatureError { NoValue, #[error("Value expected to be i32")] InvalidI32, - #[error("Value {scalar_as_hex} is not a valid grumpkin scalar")] - InvalidGrumpkinScalar { scalar_as_hex: String }, - #[error("Limb {limb_as_hex} is not less than 2^128")] - InvalidGrumpkinScalarLimb { limb_as_hex: String }, #[error("Could not convert value {value} from i32 to u32")] InvalidU32 { value: i32, source: std::num::TryFromIntError }, #[error("Could not convert value {value} from i32 to usize")] diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/scalar_mul.rs b/acvm-repo/barretenberg_blackbox_solver/src/wasm/scalar_mul.rs deleted file mode 100644 index 71e1701bc30..00000000000 --- a/acvm-repo/barretenberg_blackbox_solver/src/wasm/scalar_mul.rs +++ /dev/null @@ -1,98 +0,0 @@ -use acir::FieldElement; -use num_bigint::BigUint; - -use crate::wasm::FeatureError; - -use super::{Barretenberg, Error, FIELD_BYTES}; - -pub(crate) trait ScalarMul { - fn fixed_base( - &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), Error>; -} - -impl ScalarMul for Barretenberg { - fn fixed_base( - &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), Error> { - let lhs_ptr: usize = 0; - let result_ptr: usize = lhs_ptr + FIELD_BYTES; - - let low: u128 = low.try_into_u128().ok_or_else(|| { - Error::FromFeature(FeatureError::InvalidGrumpkinScalarLimb { - limb_as_hex: low.to_hex(), - }) - })?; - - let high: u128 = high.try_into_u128().ok_or_else(|| { - Error::FromFeature(FeatureError::InvalidGrumpkinScalarLimb { - limb_as_hex: high.to_hex(), - }) - })?; - - let mut bytes = high.to_be_bytes().to_vec(); - bytes.extend_from_slice(&low.to_be_bytes()); - - // Check if this is smaller than the grumpkin modulus - let grumpkin_integer = BigUint::from_bytes_be(&bytes); - let grumpkin_modulus = BigUint::from_bytes_be(&[ - 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 151, 129, 106, - 145, 104, 113, 202, 141, 60, 32, 140, 22, 216, 124, 253, 71, - ]); - - if grumpkin_integer >= grumpkin_modulus { - return Err(Error::FromFeature(FeatureError::InvalidGrumpkinScalar { - scalar_as_hex: hex::encode(grumpkin_integer.to_bytes_be()), - })); - } - - self.transfer_to_heap(&bytes, lhs_ptr); - self.call_multiple("compute_public_key", vec![&lhs_ptr.into(), &result_ptr.into()])?; - - let result_bytes: [u8; 2 * FIELD_BYTES] = self.read_memory(result_ptr); - let (pubkey_x_bytes, pubkey_y_bytes) = result_bytes.split_at(FIELD_BYTES); - - assert!(pubkey_x_bytes.len() == FIELD_BYTES); - assert!(pubkey_y_bytes.len() == FIELD_BYTES); - - let pubkey_x = FieldElement::from_be_bytes_reduce(pubkey_x_bytes); - let pubkey_y = FieldElement::from_be_bytes_reduce(pubkey_y_bytes); - Ok((pubkey_x, pubkey_y)) - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn smoke_test() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - let input = FieldElement::one(); - - let res = barretenberg.fixed_base(&input, &FieldElement::zero())?; - let x = "0000000000000000000000000000000000000000000000000000000000000001"; - let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } - #[test] - fn low_high_smoke_test() -> Result<(), Error> { - let barretenberg = Barretenberg::new(); - let low = FieldElement::one(); - let high = FieldElement::from(2u128); - - let res = barretenberg.fixed_base(&low, &high)?; - let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; - let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } -} diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 2e09452c492..e1d55a623ab 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -15,6 +15,7 @@ repository.workspace = true [dependencies] acir.workspace = true thiserror.workspace = true +num-bigint.workspace = true blake2 = "0.10.6" sha2 = "0.10.6" @@ -33,6 +34,8 @@ p256 = { version = "0.11.0", features = [ "digest", "arithmetic", ] } +grumpkin = { git = "https://github.com/noir-lang/grumpkin", features = ["std"] } +ark-ec = { version = "^0.4.0", default-features = false } [features] default = ["bn254"] diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index 0c0fbae2bde..dd3efec6acd 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -10,6 +10,7 @@ use acir::{BlackBoxFunc, FieldElement}; use blake2::digest::generic_array::GenericArray; use blake2::{Blake2s256, Digest}; +use num_bigint::BigUint; use sha2::Sha256; use sha3::Keccak256; use thiserror::Error; @@ -39,11 +40,6 @@ pub trait BlackBoxFunctionSolver { inputs: &[FieldElement], domain_separator: u32, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; - fn fixed_base_scalar_mul( - &self, - low: &FieldElement, - high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; } pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { @@ -66,6 +62,89 @@ pub fn hash_to_field_128_security(inputs: &[u8]) -> Result Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + #[cfg(not(feature = "bn254"))] + return BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "This solver is only defined over the bn254 curve currently".into(), + ); + + use ark_ec::AffineRepr; + + let low: u128 = low.try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("Limb {} is not less than 2^128", low.to_hex()), + ) + })?; + + let high: u128 = high.try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("Limb {} is not less than 2^128", high.to_hex()), + ) + })?; + + let mut bytes = high.to_be_bytes().to_vec(); + bytes.extend_from_slice(&low.to_be_bytes()); + + // Check if this is smaller than the grumpkin modulus + let grumpkin_integer = BigUint::from_bytes_be(&bytes); + let grumpkin_modulus = BigUint::from_bytes_be(&[ + 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 151, 129, 106, 145, + 104, 113, 202, 141, 60, 32, 140, 22, 216, 124, 253, 71, + ]); + + if grumpkin_integer >= grumpkin_modulus { + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), + )); + } + + let result = grumpkin::SWAffine::from( + grumpkin::SWAffine::generator().mul_bigint(grumpkin_integer.to_u64_digits()), + ); + if let Some((res_x, res_y)) = result.xy() { + Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) + } else { + Ok((FieldElement::zero(), FieldElement::zero())) + } +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn smoke_test() -> Result<(), BlackBoxResolutionError> { + let input = FieldElement::one(); + + let res = fixed_base_scalar_mul(&input, &FieldElement::zero())?; + let x = "0000000000000000000000000000000000000000000000000000000000000001"; + let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; + + assert_eq!(x, res.0.to_hex()); + assert_eq!(y, res.1.to_hex()); + Ok(()) + } + #[test] + fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { + let low = FieldElement::one(); + let high = FieldElement::from(2u128); + + let res = fixed_base_scalar_mul(&low, &high)?; + let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; + let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; + + assert_eq!(x, res.0.to_hex()); + assert_eq!(y, res.1.to_hex()); + Ok(()) + } +} + pub fn ecdsa_secp256k1_verify( hashed_msg: &[u8], public_key_x: &[u8; 32], diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index ada8a2f5993..dc789d88b6a 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -1,8 +1,8 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value}; use acir::{BlackBoxFunc, FieldElement}; use acvm_blackbox_solver::{ - blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, hash_to_field_128_security, keccak256, - sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, + blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, fixed_base_scalar_mul, + hash_to_field_128_security, keccak256, sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, }; use crate::{Memory, Registers}; @@ -143,7 +143,7 @@ pub(crate) fn evaluate_black_box( BlackBoxOp::FixedBaseScalarMul { low, high, result } => { let low = registers.get(*low).to_field(); let high = registers.get(*high).to_field(); - let (x, y) = solver.fixed_base_scalar_mul(&low, &high)?; + let (x, y) = fixed_base_scalar_mul(&low, &high)?; memory.write_slice(registers.get(result.pointer).to_usize(), &[x.into(), y.into()]); Ok(()) } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 48f6bf5f1c4..e5239dad021 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -424,13 +424,6 @@ impl BlackBoxFunctionSolver for DummyBlackBoxSolver { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Ok((2_u128.into(), 3_u128.into())) } - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((4_u128.into(), 5_u128.into())) - } } #[cfg(test)] diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index d846ede566f..cf8b35e5822 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1271,13 +1271,6 @@ fn execute_brillig( ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::Pedersen)) } - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::FixedBaseScalarMul)) - } } // Set input values diff --git a/cspell.json b/cspell.json index a667fc6d7aa..ac7953e0653 100644 --- a/cspell.json +++ b/cspell.json @@ -49,6 +49,7 @@ "fxhash", "getrandom", "gloo", + "grumpkin", "Guillaume", "hasher", "hexdigit", diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 48ffefb7f7a..6ee0bc1c6f8 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -65,14 +65,6 @@ impl BlackBoxFunctionSolver for WrapperSolver { ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { self.0.pedersen(inputs, domain_separator) } - - fn fixed_base_scalar_mul( - &self, - low: &acvm::FieldElement, - high: &acvm::FieldElement, - ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { - self.0.fixed_base_scalar_mul(low, high) - } } // State for the LSP gets implemented on this struct and is internal to the implementation From b80de491098db4175275e19a9432f6a6c5782d1e Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 13 Oct 2023 20:09:56 +0100 Subject: [PATCH 02/10] chore: fix compile --- tooling/lsp/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 6ee0bc1c6f8..910efa928b9 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -425,15 +425,6 @@ mod lsp_tests { { unimplemented!() } - - fn fixed_base_scalar_mul( - &self, - _low: &acvm::FieldElement, - _high: &acvm::FieldElement, - ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> - { - unimplemented!() - } } let client = ClientSocket::new_closed(); From d1fa43e0e9a54b851359bdbcc3cb845f4fc20f80 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 13 Oct 2023 23:15:19 +0100 Subject: [PATCH 03/10] chore: fix build --- compiler/noirc_evaluator/src/brillig/brillig_ir.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index a4ea0362f06..46161a86199 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -1039,13 +1039,6 @@ pub(crate) mod tests { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Ok((2_u128.into(), 3_u128.into())) } - fn fixed_base_scalar_mul( - &self, - _low: &FieldElement, - _high: &FieldElement, - ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Ok((4_u128.into(), 5_u128.into())) - } } pub(crate) fn create_context() -> BrilligContext { From a3e34e86bc6bfa47f123b4fe663c776f2637289d Mon Sep 17 00:00:00 2001 From: Tom French Date: Sat, 14 Oct 2023 13:11:53 +0100 Subject: [PATCH 04/10] chore: pull grumpkin modulus from grumpkin crate --- Cargo.lock | 1 + acvm-repo/blackbox_solver/Cargo.toml | 9 ++++++--- acvm-repo/blackbox_solver/src/lib.rs | 7 ++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a26bcb0a72..ab9f37e91c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,6 +57,7 @@ version = "0.28.0" dependencies = [ "acir", "ark-ec", + "ark-ff", "blake2", "grumpkin", "k256", diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index e1d55a623ab..cdff9b9c620 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -34,10 +34,13 @@ p256 = { version = "0.11.0", features = [ "digest", "arithmetic", ] } -grumpkin = { git = "https://github.com/noir-lang/grumpkin", features = ["std"] } -ark-ec = { version = "^0.4.0", default-features = false } + +# BN254 fixed base scalar multiplication solver +grumpkin = { git = "https://github.com/noir-lang/grumpkin", optional = true, features = ["std"] } +ark-ec = { version = "^0.4.0", optional = true, default-features = false } +ark-ff = { version = "^0.4.0", optional = true, default-features = false } [features] default = ["bn254"] -bn254 = ["acir/bn254"] +bn254 = ["acir/bn254", "dep:grumpkin", "dep:ark-ec", "dep:ark-ff"] bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index dd3efec6acd..c269559905c 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -73,6 +73,7 @@ pub fn fixed_base_scalar_mul( ); use ark_ec::AffineRepr; + use ark_ff::MontConfig; let low: u128 = low.try_into_u128().ok_or_else(|| { BlackBoxResolutionError::Failed( @@ -93,12 +94,8 @@ pub fn fixed_base_scalar_mul( // Check if this is smaller than the grumpkin modulus let grumpkin_integer = BigUint::from_bytes_be(&bytes); - let grumpkin_modulus = BigUint::from_bytes_be(&[ - 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 151, 129, 106, 145, - 104, 113, 202, 141, 60, 32, 140, 22, 216, 124, 253, 71, - ]); - if grumpkin_integer >= grumpkin_modulus { + if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { return Err(BlackBoxResolutionError::Failed( BlackBoxFunc::FixedBaseScalarMul, format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), From ffbeefa8aef21c93feee40ded25eddb6c97309a1 Mon Sep 17 00:00:00 2001 From: Tom French Date: Sat, 14 Oct 2023 13:12:13 +0100 Subject: [PATCH 05/10] chore: add tests for fixed base scalar mul failure modes --- acvm-repo/blackbox_solver/src/lib.rs | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index c269559905c..d993224e140 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -140,6 +140,43 @@ mod test { assert_eq!(y, res.1.to_hex()); Ok(()) } + + #[test] + fn rejects_invalid_limbs() { + let max_limb = FieldElement::from(u128::MAX); + let invalid_limb = max_limb + FieldElement::one(); + + let expected_error = Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into() + )); + + let res = fixed_base_scalar_mul(&invalid_limb, &FieldElement::zero()); + assert_eq!(res, expected_error); + + let res = fixed_base_scalar_mul(&FieldElement::zero(), &invalid_limb); + assert_eq!(res, expected_error); + } + + #[test] + fn rejects_grumpkin_modulus() { + use ark_ff::{BigInteger, MontConfig}; + + let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); + + let high = FieldElement::from_be_bytes_reduce(&x[0..16]); + let low = FieldElement::from_be_bytes_reduce(&x[16..32]); + + let res = fixed_base_scalar_mul(&low, &high); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into() + )) + ); + } } pub fn ecdsa_secp256k1_verify( From b02b5d2f629dfea53854bc8da40705125488cc43 Mon Sep 17 00:00:00 2001 From: Tom French Date: Sat, 14 Oct 2023 13:20:49 +0100 Subject: [PATCH 06/10] chore: move fixed base scalar mul solver into a submodule --- .../src/fixed_base_scalar_mul.rs | 121 +++++++++++++++++ acvm-repo/blackbox_solver/src/lib.rs | 122 +----------------- 2 files changed, 125 insertions(+), 118 deletions(-) create mode 100644 acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs diff --git a/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs new file mode 100644 index 00000000000..af1de958880 --- /dev/null +++ b/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs @@ -0,0 +1,121 @@ +use acir::{BlackBoxFunc, FieldElement}; +use num_bigint::BigUint; + +use crate::BlackBoxResolutionError; + +pub fn fixed_base_scalar_mul( + low: &FieldElement, + high: &FieldElement, +) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + #[cfg(not(feature = "bn254"))] + return BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "This solver is only defined over the bn254 curve currently".into(), + ); + + use ark_ec::AffineRepr; + use ark_ff::MontConfig; + + let low: u128 = low.try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("Limb {} is not less than 2^128", low.to_hex()), + ) + })?; + + let high: u128 = high.try_into_u128().ok_or_else(|| { + BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("Limb {} is not less than 2^128", high.to_hex()), + ) + })?; + + let mut bytes = high.to_be_bytes().to_vec(); + bytes.extend_from_slice(&low.to_be_bytes()); + + // Check if this is smaller than the grumpkin modulus + let grumpkin_integer = BigUint::from_bytes_be(&bytes); + + if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { + return Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), + )); + } + + let result = grumpkin::SWAffine::from( + grumpkin::SWAffine::generator().mul_bigint(grumpkin_integer.to_u64_digits()), + ); + if let Some((res_x, res_y)) = result.xy() { + Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) + } else { + Ok((FieldElement::zero(), FieldElement::zero())) + } +} + +#[cfg(test)] +mod grumpkin_fixed_base_scalar_mul { + use super::*; + #[test] + fn smoke_test() -> Result<(), BlackBoxResolutionError> { + let input = FieldElement::one(); + + let res = fixed_base_scalar_mul(&input, &FieldElement::zero())?; + let x = "0000000000000000000000000000000000000000000000000000000000000001"; + let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; + + assert_eq!(x, res.0.to_hex()); + assert_eq!(y, res.1.to_hex()); + Ok(()) + } + #[test] + fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { + let low = FieldElement::one(); + let high = FieldElement::from(2u128); + + let res = fixed_base_scalar_mul(&low, &high)?; + let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; + let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; + + assert_eq!(x, res.0.to_hex()); + assert_eq!(y, res.1.to_hex()); + Ok(()) + } + + #[test] + fn rejects_invalid_limbs() { + let max_limb = FieldElement::from(u128::MAX); + let invalid_limb = max_limb + FieldElement::one(); + + let expected_error = Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into() + )); + + let res = fixed_base_scalar_mul(&invalid_limb, &FieldElement::zero()); + assert_eq!(res, expected_error); + + let res = fixed_base_scalar_mul(&FieldElement::zero(), &invalid_limb); + assert_eq!(res, expected_error); + } + + #[test] + fn rejects_grumpkin_modulus() { + use ark_ff::{BigInteger, MontConfig}; + + let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); + + let high = FieldElement::from_be_bytes_reduce(&x[0..16]); + let low = FieldElement::from_be_bytes_reduce(&x[16..32]); + + let res = fixed_base_scalar_mul(&low, &high); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::FixedBaseScalarMul, + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into() + )) + ); + } +} diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index d993224e140..23ef0aad68d 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -10,11 +10,14 @@ use acir::{BlackBoxFunc, FieldElement}; use blake2::digest::generic_array::GenericArray; use blake2::{Blake2s256, Digest}; -use num_bigint::BigUint; use sha2::Sha256; use sha3::Keccak256; use thiserror::Error; +mod fixed_base_scalar_mul; + +pub use fixed_base_scalar_mul::fixed_base_scalar_mul; + #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum BlackBoxResolutionError { #[error("unsupported blackbox function: {0}")] @@ -62,123 +65,6 @@ pub fn hash_to_field_128_security(inputs: &[u8]) -> Result Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - #[cfg(not(feature = "bn254"))] - return BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "This solver is only defined over the bn254 curve currently".into(), - ); - - use ark_ec::AffineRepr; - use ark_ff::MontConfig; - - let low: u128 = low.try_into_u128().ok_or_else(|| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("Limb {} is not less than 2^128", low.to_hex()), - ) - })?; - - let high: u128 = high.try_into_u128().ok_or_else(|| { - BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("Limb {} is not less than 2^128", high.to_hex()), - ) - })?; - - let mut bytes = high.to_be_bytes().to_vec(); - bytes.extend_from_slice(&low.to_be_bytes()); - - // Check if this is smaller than the grumpkin modulus - let grumpkin_integer = BigUint::from_bytes_be(&bytes); - - if grumpkin_integer >= grumpkin::FrConfig::MODULUS.into() { - return Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - format!("{} is not a valid grumpkin scalar", grumpkin_integer.to_str_radix(16)), - )); - } - - let result = grumpkin::SWAffine::from( - grumpkin::SWAffine::generator().mul_bigint(grumpkin_integer.to_u64_digits()), - ); - if let Some((res_x, res_y)) = result.xy() { - Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) - } else { - Ok((FieldElement::zero(), FieldElement::zero())) - } -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn smoke_test() -> Result<(), BlackBoxResolutionError> { - let input = FieldElement::one(); - - let res = fixed_base_scalar_mul(&input, &FieldElement::zero())?; - let x = "0000000000000000000000000000000000000000000000000000000000000001"; - let y = "0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } - #[test] - fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { - let low = FieldElement::one(); - let high = FieldElement::from(2u128); - - let res = fixed_base_scalar_mul(&low, &high)?; - let x = "0702ab9c7038eeecc179b4f209991bcb68c7cb05bf4c532d804ccac36199c9a9"; - let y = "23f10e9e43a3ae8d75d24154e796aae12ae7af546716e8f81a2564f1b5814130"; - - assert_eq!(x, res.0.to_hex()); - assert_eq!(y, res.1.to_hex()); - Ok(()) - } - - #[test] - fn rejects_invalid_limbs() { - let max_limb = FieldElement::from(u128::MAX); - let invalid_limb = max_limb + FieldElement::one(); - - let expected_error = Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into() - )); - - let res = fixed_base_scalar_mul(&invalid_limb, &FieldElement::zero()); - assert_eq!(res, expected_error); - - let res = fixed_base_scalar_mul(&FieldElement::zero(), &invalid_limb); - assert_eq!(res, expected_error); - } - - #[test] - fn rejects_grumpkin_modulus() { - use ark_ff::{BigInteger, MontConfig}; - - let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); - - let high = FieldElement::from_be_bytes_reduce(&x[0..16]); - let low = FieldElement::from_be_bytes_reduce(&x[16..32]); - - let res = fixed_base_scalar_mul(&low, &high); - - assert_eq!( - res, - Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into() - )) - ); - } -} - pub fn ecdsa_secp256k1_verify( hashed_msg: &[u8], public_key_x: &[u8; 32], From 1375ff9355e9bc5b3ec1512800364289d92c635e Mon Sep 17 00:00:00 2001 From: Tom French Date: Sat, 14 Oct 2023 13:36:00 +0100 Subject: [PATCH 07/10] chore: fix builds for non-bn254 fields --- acvm-repo/blackbox_solver/Cargo.toml | 4 ++-- .../src/fixed_base_scalar_mul.rs | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index cdff9b9c620..9258c82d299 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -15,7 +15,6 @@ repository.workspace = true [dependencies] acir.workspace = true thiserror.workspace = true -num-bigint.workspace = true blake2 = "0.10.6" sha2 = "0.10.6" @@ -39,8 +38,9 @@ p256 = { version = "0.11.0", features = [ grumpkin = { git = "https://github.com/noir-lang/grumpkin", optional = true, features = ["std"] } ark-ec = { version = "^0.4.0", optional = true, default-features = false } ark-ff = { version = "^0.4.0", optional = true, default-features = false } +num-bigint = { workspace = true, optional = true } [features] default = ["bn254"] -bn254 = ["acir/bn254", "dep:grumpkin", "dep:ark-ec", "dep:ark-ff"] +bn254 = ["acir/bn254", "dep:grumpkin", "dep:ark-ec", "dep:ark-ff", "dep:num-bigint"] bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs index af1de958880..5904439d960 100644 --- a/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs +++ b/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs @@ -1,20 +1,26 @@ use acir::{BlackBoxFunc, FieldElement}; -use num_bigint::BigUint; use crate::BlackBoxResolutionError; +#[cfg(not(feature = "bn254"))] pub fn fixed_base_scalar_mul( - low: &FieldElement, - high: &FieldElement, + _low: &FieldElement, + _high: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - #[cfg(not(feature = "bn254"))] - return BlackBoxResolutionError::Failed( + Err(BlackBoxResolutionError::Failed( BlackBoxFunc::FixedBaseScalarMul, "This solver is only defined over the bn254 curve currently".into(), - ); + )) +} +#[cfg(feature = "bn254")] +pub fn fixed_base_scalar_mul( + low: &FieldElement, + high: &FieldElement, +) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { use ark_ec::AffineRepr; use ark_ff::MontConfig; + use num_bigint::BigUint; let low: u128 = low.try_into_u128().ok_or_else(|| { BlackBoxResolutionError::Failed( From 5408704c4a7de81c296b8343635caec167eccac8 Mon Sep 17 00:00:00 2001 From: Tom French Date: Sat, 14 Oct 2023 13:50:08 +0100 Subject: [PATCH 08/10] chore: fix cargo deny --- Cargo.lock | 2 +- acvm-repo/blackbox_solver/Cargo.toml | 2 +- deny.toml | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab9f37e91c5..d932b6d5f53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1833,7 +1833,7 @@ dependencies = [ [[package]] name = "grumpkin" version = "0.1.0" -source = "git+https://github.com/noir-lang/grumpkin#56d99799381f79e42148aaef0de2b0cf9a4b9a5d" +source = "git+https://github.com/noir-lang/grumpkin?rev=56d99799381f79e42148aaef0de2b0cf9a4b9a5d#56d99799381f79e42148aaef0de2b0cf9a4b9a5d" dependencies = [ "ark-bn254", "ark-ec", diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 9258c82d299..ba08393a2b9 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -35,7 +35,7 @@ p256 = { version = "0.11.0", features = [ ] } # BN254 fixed base scalar multiplication solver -grumpkin = { git = "https://github.com/noir-lang/grumpkin", optional = true, features = ["std"] } +grumpkin = { git = "https://github.com/noir-lang/grumpkin", rev = "56d99799381f79e42148aaef0de2b0cf9a4b9a5d", optional = true, features = ["std"] } ark-ec = { version = "^0.4.0", optional = true, default-features = false } ark-ff = { version = "^0.4.0", optional = true, default-features = false } num-bigint = { workspace = true, optional = true } diff --git a/deny.toml b/deny.toml index e19406592d8..fc60154c628 100644 --- a/deny.toml +++ b/deny.toml @@ -99,4 +99,7 @@ unknown-registry = "warn" # Lint level for what to happen when a crate from a git repository that is not # in the allow list is encountered unknown-git = "deny" -allow-git = ["https://github.com/jfecher/chumsky"] +allow-git = [ + "https://github.com/noir-lang/grumpkin", + "https://github.com/jfecher/chumsky" +] From 83cfaac6f87a4dc308b52ba8a1fba9a52d8c3ea9 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 16 Oct 2023 11:17:02 +0100 Subject: [PATCH 09/10] chore: move `fixed_base_scalar_mul` back onto `BlackBoxFunctionSolver` --- Cargo.lock | 8 ++++---- .../src/pwg/blackbox/fixed_base_scalar_mul.rs | 4 +++- acvm-repo/acvm/src/pwg/blackbox/mod.rs | 2 +- acvm-repo/acvm/tests/solver.rs | 7 +++++++ .../barretenberg_blackbox_solver/Cargo.toml | 6 ++++++ .../src/fixed_base_scalar_mul.rs | 12 ------------ .../barretenberg_blackbox_solver/src/lib.rs | 10 ++++++++++ acvm-repo/blackbox_solver/Cargo.toml | 7 +------ acvm-repo/blackbox_solver/src/lib.rs | 9 +++++---- acvm-repo/brillig_vm/src/black_box.rs | 6 +++--- acvm-repo/brillig_vm/src/lib.rs | 7 +++++++ .../noirc_evaluator/src/brillig/brillig_ir.rs | 7 +++++++ .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 7 +++++++ tooling/lsp/src/lib.rs | 17 +++++++++++++++++ 14 files changed, 78 insertions(+), 31 deletions(-) rename acvm-repo/{blackbox_solver => barretenberg_blackbox_solver}/src/fixed_base_scalar_mul.rs (91%) diff --git a/Cargo.lock b/Cargo.lock index d932b6d5f53..7fadf637e31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,12 +56,8 @@ name = "acvm_blackbox_solver" version = "0.28.0" dependencies = [ "acir", - "ark-ec", - "ark-ff", "blake2", - "grumpkin", "k256", - "num-bigint", "p256", "sha2", "sha3", @@ -457,9 +453,13 @@ version = "0.28.0" dependencies = [ "acir", "acvm_blackbox_solver", + "ark-ec", + "ark-ff", "flate2", "getrandom", + "grumpkin", "js-sys", + "num-bigint", "pkg-config", "reqwest", "rust-embed", diff --git a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs b/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs index b489d997339..582ed56584b 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs @@ -2,10 +2,12 @@ use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, }; +use acvm_blackbox_solver::BlackBoxFunctionSolver; use crate::pwg::{insert_value, witness_to_value, OpcodeResolutionError}; pub(super) fn fixed_base_scalar_mul( + backend: &impl BlackBoxFunctionSolver, initial_witness: &mut WitnessMap, low: FunctionInput, high: FunctionInput, @@ -14,7 +16,7 @@ pub(super) fn fixed_base_scalar_mul( let low = witness_to_value(initial_witness, low.witness)?; let high = witness_to_value(initial_witness, high.witness)?; - let (pub_x, pub_y) = crate::blackbox_solver::fixed_base_scalar_mul(low, high)?; + let (pub_x, pub_y) = backend.fixed_base_scalar_mul(low, high)?; insert_value(&outputs.0, pub_x, initial_witness)?; insert_value(&outputs.1, pub_y, initial_witness)?; diff --git a/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 14ded91707d..c4d9d561f46 100644 --- a/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -149,7 +149,7 @@ pub(crate) fn solve( *output, ), BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { - fixed_base_scalar_mul(initial_witness, *low, *high, *outputs) + fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) } BlackBoxFuncCall::RecursiveAggregation { output_aggregation_object, .. } => { // Solve the output of the recursive aggregation to zero to prevent missing assignment errors diff --git a/acvm-repo/acvm/tests/solver.rs b/acvm-repo/acvm/tests/solver.rs index a16bb78c81f..1d287d70c1b 100644 --- a/acvm-repo/acvm/tests/solver.rs +++ b/acvm-repo/acvm/tests/solver.rs @@ -36,6 +36,13 @@ impl BlackBoxFunctionSolver for StubbedBackend { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { panic!("Path not trodden by this test") } + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + panic!("Path not trodden by this test") + } } // Reenable these test cases once we move the brillig implementation of inversion down into the acvm stdlib. diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index 96bf3e7dcff..97e58c2804b 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml @@ -23,6 +23,12 @@ rust-embed = { version = "6.6.0", features = [ "include-exclude", ] } +# BN254 fixed base scalar multiplication solver +grumpkin = { git = "https://github.com/noir-lang/grumpkin", rev = "56d99799381f79e42148aaef0de2b0cf9a4b9a5d", features = ["std"] } +ark-ec = { version = "^0.4.0", default-features = false } +ark-ff = { version = "^0.4.0", default-features = false } +num-bigint.workspace = true + [target.'cfg(target_arch = "wasm32")'.dependencies] wasmer = { version = "3.3", default-features = false, features = [ "js-default", diff --git a/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs similarity index 91% rename from acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs rename to acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs index 5904439d960..f8e53e2b404 100644 --- a/acvm-repo/blackbox_solver/src/fixed_base_scalar_mul.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs @@ -2,18 +2,6 @@ use acir::{BlackBoxFunc, FieldElement}; use crate::BlackBoxResolutionError; -#[cfg(not(feature = "bn254"))] -pub fn fixed_base_scalar_mul( - _low: &FieldElement, - _high: &FieldElement, -) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - Err(BlackBoxResolutionError::Failed( - BlackBoxFunc::FixedBaseScalarMul, - "This solver is only defined over the bn254 curve currently".into(), - )) -} - -#[cfg(feature = "bn254")] pub fn fixed_base_scalar_mul( low: &FieldElement, high: &FieldElement, diff --git a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs b/acvm-repo/barretenberg_blackbox_solver/src/lib.rs index d5cfc9591f7..b9486e97bd9 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/lib.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/lib.rs @@ -5,8 +5,10 @@ use acir::{BlackBoxFunc, FieldElement}; use acvm_blackbox_solver::{BlackBoxFunctionSolver, BlackBoxResolutionError}; +mod fixed_base_scalar_mul; mod wasm; +pub use fixed_base_scalar_mul::fixed_base_scalar_mul; use wasm::Barretenberg; use self::wasm::{Pedersen, SchnorrSig}; @@ -71,4 +73,12 @@ impl BlackBoxFunctionSolver for BarretenbergSolver { .encrypt(inputs.to_vec(), domain_separator) .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Pedersen, err.to_string())) } + + fn fixed_base_scalar_mul( + &self, + low: &FieldElement, + high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + fixed_base_scalar_mul(low, high) + } } diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index ba08393a2b9..f0295456977 100644 --- a/acvm-repo/blackbox_solver/Cargo.toml +++ b/acvm-repo/blackbox_solver/Cargo.toml @@ -34,13 +34,8 @@ p256 = { version = "0.11.0", features = [ "arithmetic", ] } -# BN254 fixed base scalar multiplication solver -grumpkin = { git = "https://github.com/noir-lang/grumpkin", rev = "56d99799381f79e42148aaef0de2b0cf9a4b9a5d", optional = true, features = ["std"] } -ark-ec = { version = "^0.4.0", optional = true, default-features = false } -ark-ff = { version = "^0.4.0", optional = true, default-features = false } -num-bigint = { workspace = true, optional = true } [features] default = ["bn254"] -bn254 = ["acir/bn254", "dep:grumpkin", "dep:ark-ec", "dep:ark-ff", "dep:num-bigint"] +bn254 = ["acir/bn254"] bls12_381 = ["acir/bls12_381"] diff --git a/acvm-repo/blackbox_solver/src/lib.rs b/acvm-repo/blackbox_solver/src/lib.rs index 23ef0aad68d..0c0fbae2bde 100644 --- a/acvm-repo/blackbox_solver/src/lib.rs +++ b/acvm-repo/blackbox_solver/src/lib.rs @@ -14,10 +14,6 @@ use sha2::Sha256; use sha3::Keccak256; use thiserror::Error; -mod fixed_base_scalar_mul; - -pub use fixed_base_scalar_mul::fixed_base_scalar_mul; - #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum BlackBoxResolutionError { #[error("unsupported blackbox function: {0}")] @@ -43,6 +39,11 @@ pub trait BlackBoxFunctionSolver { inputs: &[FieldElement], domain_separator: u32, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; + fn fixed_base_scalar_mul( + &self, + low: &FieldElement, + high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError>; } pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { diff --git a/acvm-repo/brillig_vm/src/black_box.rs b/acvm-repo/brillig_vm/src/black_box.rs index dc789d88b6a..ada8a2f5993 100644 --- a/acvm-repo/brillig_vm/src/black_box.rs +++ b/acvm-repo/brillig_vm/src/black_box.rs @@ -1,8 +1,8 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, Value}; use acir::{BlackBoxFunc, FieldElement}; use acvm_blackbox_solver::{ - blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, fixed_base_scalar_mul, - hash_to_field_128_security, keccak256, sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, + blake2s, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, hash_to_field_128_security, keccak256, + sha256, BlackBoxFunctionSolver, BlackBoxResolutionError, }; use crate::{Memory, Registers}; @@ -143,7 +143,7 @@ pub(crate) fn evaluate_black_box( BlackBoxOp::FixedBaseScalarMul { low, high, result } => { let low = registers.get(*low).to_field(); let high = registers.get(*high).to_field(); - let (x, y) = fixed_base_scalar_mul(&low, &high)?; + let (x, y) = solver.fixed_base_scalar_mul(&low, &high)?; memory.write_slice(registers.get(result.pointer).to_usize(), &[x.into(), y.into()]); Ok(()) } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index e5239dad021..48f6bf5f1c4 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -424,6 +424,13 @@ impl BlackBoxFunctionSolver for DummyBlackBoxSolver { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Ok((2_u128.into(), 3_u128.into())) } + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + Ok((4_u128.into(), 5_u128.into())) + } } #[cfg(test)] diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 46161a86199..a4ea0362f06 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -1039,6 +1039,13 @@ pub(crate) mod tests { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Ok((2_u128.into(), 3_u128.into())) } + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + Ok((4_u128.into(), 5_u128.into())) + } } pub(crate) fn create_context() -> BrilligContext { diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index cf8b35e5822..d846ede566f 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1271,6 +1271,13 @@ fn execute_brillig( ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::Pedersen)) } + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { + Err(BlackBoxResolutionError::Unsupported(BlackBoxFunc::FixedBaseScalarMul)) + } } // Set input values diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 910efa928b9..48ffefb7f7a 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -65,6 +65,14 @@ impl BlackBoxFunctionSolver for WrapperSolver { ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { self.0.pedersen(inputs, domain_separator) } + + fn fixed_base_scalar_mul( + &self, + low: &acvm::FieldElement, + high: &acvm::FieldElement, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> { + self.0.fixed_base_scalar_mul(low, high) + } } // State for the LSP gets implemented on this struct and is internal to the implementation @@ -425,6 +433,15 @@ mod lsp_tests { { unimplemented!() } + + fn fixed_base_scalar_mul( + &self, + _low: &acvm::FieldElement, + _high: &acvm::FieldElement, + ) -> Result<(acvm::FieldElement, acvm::FieldElement), acvm::BlackBoxResolutionError> + { + unimplemented!() + } } let client = ClientSocket::new_closed(); From d64d9c5913ee199811ef387113895ebd2865ed1c Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 16 Oct 2023 11:34:20 +0100 Subject: [PATCH 10/10] chore: rearrange imports --- .../src/fixed_base_scalar_mul.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs b/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs index f8e53e2b404..7f004de0fe9 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs @@ -1,3 +1,7 @@ +use ark_ec::AffineRepr; +use ark_ff::MontConfig; +use num_bigint::BigUint; + use acir::{BlackBoxFunc, FieldElement}; use crate::BlackBoxResolutionError; @@ -6,10 +10,6 @@ pub fn fixed_base_scalar_mul( low: &FieldElement, high: &FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - use ark_ec::AffineRepr; - use ark_ff::MontConfig; - use num_bigint::BigUint; - let low: u128 = low.try_into_u128().ok_or_else(|| { BlackBoxResolutionError::Failed( BlackBoxFunc::FixedBaseScalarMul, @@ -49,6 +49,8 @@ pub fn fixed_base_scalar_mul( #[cfg(test)] mod grumpkin_fixed_base_scalar_mul { + use ark_ff::BigInteger; + use super::*; #[test] fn smoke_test() -> Result<(), BlackBoxResolutionError> { @@ -95,8 +97,6 @@ mod grumpkin_fixed_base_scalar_mul { #[test] fn rejects_grumpkin_modulus() { - use ark_ff::{BigInteger, MontConfig}; - let x = grumpkin::FrConfig::MODULUS.to_bytes_be(); let high = FieldElement::from_be_bytes_reduce(&x[0..16]);