Skip to content

Commit

Permalink
feat: solve fixed_base_scalar_mul black box functions in rust (#3153)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Oct 16, 2023
1 parent fc73a9e commit 1c1afbc
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 117 deletions.
15 changes: 14 additions & 1 deletion Cargo.lock

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

4 changes: 4 additions & 0 deletions acvm-repo/acir_field/src/generic_ark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ impl<F: PrimeField> FieldElement<F> {
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 {
Expand Down
6 changes: 2 additions & 4 deletions acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use acir::{
circuit::opcodes::FunctionInput,
native_types::{Witness, WitnessMap},
};
use acvm_blackbox_solver::BlackBoxFunctionSolver;

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,
Expand Down
8 changes: 6 additions & 2 deletions acvm-repo/barretenberg_blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@ 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",
"interpolate-folder-path",
"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",
Expand Down
115 changes: 115 additions & 0 deletions acvm-repo/barretenberg_blackbox_solver/src/fixed_base_scalar_mul.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use ark_ec::AffineRepr;
use ark_ff::MontConfig;
use num_bigint::BigUint;

use acir::{BlackBoxFunc, FieldElement};

use crate::BlackBoxResolutionError;

pub fn fixed_base_scalar_mul(
low: &FieldElement,
high: &FieldElement,
) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> {
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 ark_ff::BigInteger;

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() {
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()
))
);
}
}
9 changes: 4 additions & 5 deletions acvm-repo/barretenberg_blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
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, ScalarMul, SchnorrSig};
use self::wasm::{Pedersen, SchnorrSig};

#[deprecated = "The `BarretenbergSolver` is a temporary solution and will be removed in future."]
pub struct BarretenbergSolver {
Expand Down Expand Up @@ -77,9 +79,6 @@ impl BlackBoxFunctionSolver for BarretenbergSolver {
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())
})
fixed_base_scalar_mul(low, high)
}
}
6 changes: 0 additions & 6 deletions acvm-repo/barretenberg_blackbox_solver/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand All @@ -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")]
Expand Down
98 changes: 0 additions & 98 deletions acvm-repo/barretenberg_blackbox_solver/src/wasm/scalar_mul.rs

This file was deleted.

1 change: 1 addition & 0 deletions acvm-repo/blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ p256 = { version = "0.11.0", features = [
"arithmetic",
] }


[features]
default = ["bn254"]
bn254 = ["acir/bn254"]
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"fxhash",
"getrandom",
"gloo",
"grumpkin",
"Guillaume",
"hasher",
"hexdigit",
Expand Down
5 changes: 4 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]

0 comments on commit 1c1afbc

Please sign in to comment.