Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: solve fixed_base_scalar_mul black box functions in rust #3153

Merged
merged 11 commits into from
Oct 16, 2023
16 changes: 14 additions & 2 deletions 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
8 changes: 2 additions & 6 deletions acvm-repo/acvm/src/pwg/blackbox/fixed_base_scalar_mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)?;
Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/acvm/src/pwg/blackbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 0 additions & 7 deletions acvm-repo/acvm/tests/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 0 additions & 2 deletions acvm-repo/barretenberg_blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 1 addition & 12 deletions acvm-repo/barretenberg_blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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())
})
}
}
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.

3 changes: 3 additions & 0 deletions acvm-repo/blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -33,6 +34,8 @@ p256 = { version = "0.11.0", features = [
"digest",
"arithmetic",
] }
grumpkin = { git = "https://github.com/noir-lang/grumpkin", features = ["std"] }
TomAFrench marked this conversation as resolved.
Show resolved Hide resolved
ark-ec = { version = "^0.4.0", default-features = false }

[features]
default = ["bn254"]
Expand Down
89 changes: 84 additions & 5 deletions acvm-repo/blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand All @@ -66,6 +62,89 @@ pub fn hash_to_field_128_security(inputs: &[u8]) -> Result<FieldElement, BlackBo
.map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::HashToField128Security, err))
}

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;

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],
Expand Down
Loading