Skip to content

Commit

Permalink
feat: remove embedded barretenberg wasm from bn254_blackbox_solver
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed May 18, 2024
1 parent 1888892 commit 94fa251
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 1,164 deletions.
654 changes: 2 additions & 652 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 6 additions & 14 deletions acvm-repo/acvm_js/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver);

impl WasmBlackBoxFunctionSolver {
async fn initialize() -> WasmBlackBoxFunctionSolver {
WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver::initialize().await)
WasmBlackBoxFunctionSolver(Bn254BlackBoxSolver::default())
}
}

Expand All @@ -47,10 +47,7 @@ pub async fn execute_circuit(
) -> Result<JsWitnessMap, Error> {
console_error_panic_hook::set_once();

let solver = WasmBlackBoxFunctionSolver::initialize().await;

let mut witness_stack = execute_program_with_native_type_return(
&solver,
program,
initial_witness,
&foreign_call_handler,
Expand All @@ -71,7 +68,7 @@ pub async fn execute_circuit(
/// @returns {SolvedAndReturnWitness} The solved witness calculated by executing the circuit on the provided inputs, as well as the return witness indices as specified by the circuit.
#[wasm_bindgen(js_name = executeCircuitWithReturnWitness, skip_jsdoc)]
pub async fn execute_circuit_with_return_witness(
solver: &WasmBlackBoxFunctionSolver,
_solver: &WasmBlackBoxFunctionSolver,
program: Vec<u8>,
initial_witness: JsWitnessMap,
foreign_call_handler: ForeignCallHandler,
Expand All @@ -82,7 +79,6 @@ pub async fn execute_circuit_with_return_witness(
.map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None, None))?;

let mut witness_stack = execute_program_with_native_program_and_return(
solver,
&program,
initial_witness,
&foreign_call_handler,
Expand All @@ -108,15 +104,14 @@ pub async fn execute_circuit_with_return_witness(
/// @returns {WitnessMap} The solved witness calculated by executing the circuit on the provided inputs.
#[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)]
pub async fn execute_circuit_with_black_box_solver(
solver: &WasmBlackBoxFunctionSolver,
_solver: &WasmBlackBoxFunctionSolver,
program: Vec<u8>,
initial_witness: JsWitnessMap,
foreign_call_handler: ForeignCallHandler,
) -> Result<JsWitnessMap, Error> {
console_error_panic_hook::set_once();

let mut witness_stack = execute_program_with_native_type_return(
solver,
program,
initial_witness,
&foreign_call_handler,
Expand All @@ -143,13 +138,12 @@ pub async fn execute_program(

#[wasm_bindgen(js_name = executeProgramWithBlackBoxSolver, skip_jsdoc)]
pub async fn execute_program_with_black_box_solver(
solver: &WasmBlackBoxFunctionSolver,
_solver: &WasmBlackBoxFunctionSolver,
program: Vec<u8>,
initial_witness: JsWitnessMap,
foreign_call_executor: &ForeignCallHandler,
) -> Result<JsWitnessStack, Error> {
let witness_stack = execute_program_with_native_type_return(
solver,
program,
initial_witness,
foreign_call_executor,
Expand All @@ -160,7 +154,6 @@ pub async fn execute_program_with_black_box_solver(
}

async fn execute_program_with_native_type_return(
solver: &WasmBlackBoxFunctionSolver,
program: Vec<u8>,
initial_witness: JsWitnessMap,
foreign_call_executor: &ForeignCallHandler,
Expand All @@ -172,7 +165,6 @@ async fn execute_program_with_native_type_return(
None))?;

execute_program_with_native_program_and_return(
solver,
&program,
initial_witness,
foreign_call_executor,
Expand All @@ -181,15 +173,15 @@ async fn execute_program_with_native_type_return(
}

async fn execute_program_with_native_program_and_return(
solver: &WasmBlackBoxFunctionSolver,
program: &Program,
initial_witness: JsWitnessMap,
foreign_call_executor: &ForeignCallHandler,
) -> Result<WitnessStack, Error> {
let blackbox_solver = Bn254BlackBoxSolver::default();
let executor = ProgramExecutor::new(
&program.functions,
&program.unconstrained_functions,
&solver.0,
&blackbox_solver,
foreign_call_executor,
);
let witness_stack = executor.execute(initial_witness.into()).await?;
Expand Down
15 changes: 0 additions & 15 deletions acvm-repo/bn254_blackbox_solver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ repository.workspace = true
[dependencies]
acir.workspace = true
acvm_blackbox_solver.workspace = true
thiserror.workspace = true
cfg-if = "1.0.0"
hex.workspace = true
lazy_static = "1.4"

Expand All @@ -26,19 +24,6 @@ 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 = "4.2.6", default-features = false, features = [
"js-default",
] }

getrandom = { workspace = true, features = ["js"] }
wasm-bindgen-futures.workspace = true
js-sys.workspace = true

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
getrandom.workspace = true
wasmer = "4.2.6"

[dev-dependencies]
ark-std = { version = "^0.4.0", default-features = false }
criterion = "0.5.0"
Expand Down
48 changes: 6 additions & 42 deletions acvm-repo/bn254_blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,22 @@
#![warn(clippy::semicolon_if_nothing_returned)]
#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))]

use acir::{BlackBoxFunc, FieldElement};
use acir::FieldElement;
use acvm_blackbox_solver::{BlackBoxFunctionSolver, BlackBoxResolutionError};

mod embedded_curve_ops;
mod generator;
mod pedersen;
mod poseidon2;
mod wasm;
mod schnorr;

use ark_ec::AffineRepr;
pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul};
pub use poseidon2::poseidon2_permutation;
use wasm::Barretenberg;

use self::wasm::SchnorrSig;

pub struct Bn254BlackBoxSolver {
blackbox_vendor: Barretenberg,
}

impl Bn254BlackBoxSolver {
pub async fn initialize() -> Bn254BlackBoxSolver {
// We fallback to the sync initialization of barretenberg on non-wasm targets.
// This ensures that wasm packages consuming this still build on the default target (useful for linting, etc.)
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
let blackbox_vendor = Barretenberg::initialize().await;
Bn254BlackBoxSolver { blackbox_vendor }
} else {
Bn254BlackBoxSolver::new()
}
}
}

#[cfg(not(target_arch = "wasm32"))]
pub fn new() -> Bn254BlackBoxSolver {
let blackbox_vendor = Barretenberg::new();
Bn254BlackBoxSolver { blackbox_vendor }
}
}

#[cfg(not(target_arch = "wasm32"))]
impl Default for Bn254BlackBoxSolver {
fn default() -> Self {
Self::new()
}
}
#[derive(Default)]
pub struct Bn254BlackBoxSolver;

impl BlackBoxFunctionSolver for Bn254BlackBoxSolver {
fn schnorr_verify(
Expand All @@ -58,16 +27,11 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver {
signature: &[u8; 64],
message: &[u8],
) -> Result<bool, BlackBoxResolutionError> {
let pub_key_bytes: Vec<u8> =
public_key_x.to_be_bytes().iter().copied().chain(public_key_y.to_be_bytes()).collect();

let pub_key: [u8; 64] = pub_key_bytes.try_into().unwrap();
let sig_s: [u8; 32] = signature[0..32].try_into().unwrap();
let sig_e: [u8; 32] = signature[32..64].try_into().unwrap();

self.blackbox_vendor.verify_signature(pub_key, sig_s, sig_e, message).map_err(|err| {
BlackBoxResolutionError::Failed(BlackBoxFunc::SchnorrVerify, err.to_string())
})
Ok(schnorr::verify_signature(public_key_x.into_repr(),
public_key_y.into_repr(), sig_s, sig_e, message))
}

fn pedersen_commitment(
Expand Down
62 changes: 62 additions & 0 deletions acvm-repo/bn254_blackbox_solver/src/schnorr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use acvm_blackbox_solver::blake2s;
use ark_ec::{
short_weierstrass::{Affine, SWCurveConfig},
AffineRepr, CurveConfig, CurveGroup,
};
use ark_ff::{PrimeField, Zero, BigInteger};
use grumpkin::{Fq, GrumpkinParameters};

pub(crate) fn verify_signature(
pub_key_x: Fq,
pub_key_y: Fq,
sig_s_bytes: [u8; 32],
sig_e_bytes: [u8; 32],
message: &[u8],
) -> bool {
let pub_key = Affine::<GrumpkinParameters>::new_unchecked(pub_key_x, pub_key_y);

// TODO: Check for correct subgroup isn't done in Barretenberg, is it necessary?
if !pub_key.is_on_curve() || !pub_key.is_in_correct_subgroup_assuming_on_curve() || pub_key.is_zero() {
return false;
}

let sig_s = <GrumpkinParameters as CurveConfig>::ScalarField::from_be_bytes_mod_order(&sig_s_bytes);
let sig_e = <GrumpkinParameters as CurveConfig>::ScalarField::from_be_bytes_mod_order(&sig_e_bytes);

if sig_s.is_zero() || sig_e.is_zero() {
return false;
}

// R = g^{sig.s} • pub^{sig.e}
let r = pub_key * sig_e + GrumpkinParameters::GENERATOR * sig_s;
if r.is_zero() {
// this result implies k == 0, which would be catastrophic for the prover.
// it is a cheap check that ensures this doesn't happen.
return false;
}

// compare the _hashes_ rather than field elements modulo r
// e = H(pedersen(r, pk.x, pk.y), m), where r = x(R)
let target_e_bytes = schnorr_generate_challenge(message, pub_key, r.into_affine());

sig_e_bytes == target_e_bytes
}

fn schnorr_generate_challenge(
message: &[u8],
pubkey: Affine<GrumpkinParameters>,
r: Affine<GrumpkinParameters>,
) -> [u8; 32] {
// create challenge message pedersen_commitment(R.x, pubkey)

let pedersen_hash = crate::pedersen::hash::hash_with_index(
&[*r.x().unwrap(), *pubkey.x().unwrap(), *pubkey.y().unwrap()],
0,
);

let mut hash_input: Vec<u8> = pedersen_hash.into_bigint().to_bytes_be();
hash_input.extend(message);

let hash = blake2s(&hash_input).unwrap();
hash
}
Binary file not shown.
Loading

0 comments on commit 94fa251

Please sign in to comment.