Skip to content

Commit

Permalink
chore: add documentation to to_be_bytes, etc. (noir-lang/noir#5843)
Browse files Browse the repository at this point in the history
feat: simplify constant calls to `poseidon2_permutation`, `schnorr_verify` and `embedded_curve_add` (noir-lang/noir#5140)
chore: don't require empty `Prover.toml` for programs with zero arguments but a return value (noir-lang/noir#5845)
fix!: Check unused generics are bound (noir-lang/noir#5840)
chore(perf): Simplify poseidon2 algorithm  (noir-lang/noir#5811)
chore: redo typo PR by nnsW3 (noir-lang/noir#5834)
fix(sha256): Perform compression per block and utilize ROM instead of RAM when setting up the message block (noir-lang/noir#5760)
chore(perf): Update to stdlib keccak for reduced Brillig code size (noir-lang/noir#5827)
  • Loading branch information
AztecBot committed Aug 28, 2024
2 parents 65549e4 + c7d5ee9 commit 919020d
Show file tree
Hide file tree
Showing 27 changed files with 432 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
86c151aa43ba990a0e900995064a88fc2ae6637d
c7473c6fcc6cbfd118b0352229ff86001cde3a64
1 change: 1 addition & 0 deletions noir/noir-repo/Cargo.lock

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

2 changes: 1 addition & 1 deletion noir/noir-repo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ criterion = "0.5.0"
# https://github.com/tikv/pprof-rs/pull/172
pprof = { version = "0.13", features = ["flamegraph", "criterion"] }


cfg-if = "1.0.0"
dirs = "4"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion noir/noir-repo/acvm-repo/acir_field/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ ark-bn254.workspace = true
ark-bls12-381 = { workspace = true, optional = true }
ark-ff.workspace = true

cfg-if = "1.0.0"
cfg-if.workspace = true

[dev-dependencies]
proptest.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions noir/noir-repo/compiler/noirc_driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ rust-embed.workspace = true
tracing.workspace = true

aztec_macros = { path = "../../aztec_macros" }

[features]
bn254 = ["noirc_frontend/bn254", "noirc_evaluator/bn254"]
bls12_381 = ["noirc_frontend/bls12_381", "noirc_evaluator/bls12_381"]
5 changes: 0 additions & 5 deletions noir/noir-repo/compiler/noirc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,6 @@ pub struct CompileOptions {
/// This check should always be run on production code.
#[arg(long)]
pub skip_underconstrained_check: bool,

/// A workspace is compiled in parallel by default. This flag will compile it sequentially.
/// This flag is useful to reduce memory consumption or to avoid using rayon threads for compilation (which don't have dynamic stacks).
#[arg(long)]
pub sequential: bool,
}

pub fn parse_expression_width(input: &str) -> Result<ExpressionWidth, std::io::Error> {
Expand Down
7 changes: 6 additions & 1 deletion noir/noir-repo/compiler/noirc_evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ serde_json.workspace = true
serde_with = "3.2.0"
tracing.workspace = true
chrono = "0.4.37"
cfg-if.workspace = true

[dev-dependencies]
proptest.workspace = true
proptest.workspace = true

[features]
bn254 = ["noirc_frontend/bn254"]
bls12_381= []
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::ssa::ir::{instruction::Endian, types::NumericType};
use acvm::acir::circuit::brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs};
use acvm::acir::circuit::opcodes::{AcirFunctionId, BlockId, BlockType, MemOp};
use acvm::acir::circuit::{AssertionPayload, ExpressionOrMemory, ExpressionWidth, Opcode};
use acvm::blackbox_solver;
use acvm::brillig_vm::{MemoryValue, VMStatus, VM};
use acvm::{
acir::AcirField,
Expand Down Expand Up @@ -2152,7 +2151,11 @@ fn execute_brillig<F: AcirField>(
}

// Instantiate a Brillig VM given the solved input registers and memory, along with the Brillig bytecode.
let mut vm = VM::new(calldata, code, Vec::new(), &blackbox_solver::StubbedBlackBoxSolver);
//
// We pass a stubbed solver here as a concrete solver implies a field choice which conflicts with this function
// being generic.
let solver = acvm::blackbox_solver::StubbedBlackBoxSolver;
let mut vm = VM::new(calldata, code, Vec::new(), &solver);

// Run the Brillig VM on these inputs, bytecode, etc!
let vm_status = vm.process_opcodes();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use fxhash::FxHashMap as HashMap;
use std::{collections::VecDeque, rc::Rc};

use acvm::{acir::AcirField, acir::BlackBoxFunc, BlackBoxResolutionError, FieldElement};
use acvm::{
acir::{AcirField, BlackBoxFunc},
BlackBoxResolutionError, FieldElement,
};
use bn254_blackbox_solver::derive_generators;
use iter_extended::vecmap;
use num_bigint::BigUint;
Expand All @@ -20,6 +23,8 @@ use crate::ssa::{

use super::{Binary, BinaryOp, Endian, Instruction, SimplifyResult};

mod blackbox;

/// Try to simplify this call instruction. If the instruction can be simplified to a known value,
/// that value is returned. Otherwise None is returned.
///
Expand Down Expand Up @@ -468,11 +473,17 @@ fn simplify_black_box_func(
arguments: &[ValueId],
dfg: &mut DataFlowGraph,
) -> SimplifyResult {
cfg_if::cfg_if! {
if #[cfg(feature = "bn254")] {
let solver = bn254_blackbox_solver::Bn254BlackBoxSolver;
} else {
let solver = acvm::blackbox_solver::StubbedBlackBoxSolver;
}
};
match bb_func {
BlackBoxFunc::SHA256 => simplify_hash(dfg, arguments, acvm::blackbox_solver::sha256),
BlackBoxFunc::Blake2s => simplify_hash(dfg, arguments, acvm::blackbox_solver::blake2s),
BlackBoxFunc::Blake3 => simplify_hash(dfg, arguments, acvm::blackbox_solver::blake3),
BlackBoxFunc::PedersenCommitment | BlackBoxFunc::PedersenHash => SimplifyResult::None,
BlackBoxFunc::Keccakf1600 => {
if let Some((array_input, _)) = dfg.get_array_constant(arguments[0]) {
if array_is_constant(dfg, &array_input) {
Expand Down Expand Up @@ -503,20 +514,26 @@ fn simplify_black_box_func(
BlackBoxFunc::Keccak256 => {
unreachable!("Keccak256 should have been replaced by calls to Keccakf1600")
}
BlackBoxFunc::Poseidon2Permutation => SimplifyResult::None, //TODO(Guillaume)
BlackBoxFunc::EcdsaSecp256k1 => {
simplify_signature(dfg, arguments, acvm::blackbox_solver::ecdsa_secp256k1_verify)
}
BlackBoxFunc::EcdsaSecp256r1 => {
simplify_signature(dfg, arguments, acvm::blackbox_solver::ecdsa_secp256r1_verify)
BlackBoxFunc::Poseidon2Permutation => {
blackbox::simplify_poseidon2_permutation(dfg, solver, arguments)
}
BlackBoxFunc::EcdsaSecp256k1 => blackbox::simplify_signature(
dfg,
arguments,
acvm::blackbox_solver::ecdsa_secp256k1_verify,
),
BlackBoxFunc::EcdsaSecp256r1 => blackbox::simplify_signature(
dfg,
arguments,
acvm::blackbox_solver::ecdsa_secp256r1_verify,
),

BlackBoxFunc::PedersenCommitment
| BlackBoxFunc::PedersenHash
| BlackBoxFunc::MultiScalarMul => SimplifyResult::None,
BlackBoxFunc::EmbeddedCurveAdd => blackbox::simplify_ec_add(dfg, solver, arguments),
BlackBoxFunc::SchnorrVerify => blackbox::simplify_schnorr_verify(dfg, solver, arguments),

BlackBoxFunc::MultiScalarMul
| BlackBoxFunc::SchnorrVerify
| BlackBoxFunc::EmbeddedCurveAdd => {
// Currently unsolvable here as we rely on an implementation in the backend.
SimplifyResult::None
}
BlackBoxFunc::BigIntAdd
| BlackBoxFunc::BigIntSub
| BlackBoxFunc::BigIntMul
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
use std::rc::Rc;

use acvm::{acir::AcirField, BlackBoxFunctionSolver, BlackBoxResolutionError, FieldElement};
use iter_extended::vecmap;

use crate::ssa::ir::{
dfg::DataFlowGraph, instruction::SimplifyResult, types::Type, value::ValueId,
};

use super::{array_is_constant, make_constant_array, to_u8_vec};

pub(super) fn simplify_ec_add(
dfg: &mut DataFlowGraph,
solver: impl BlackBoxFunctionSolver<FieldElement>,
arguments: &[ValueId],
) -> SimplifyResult {
match (
dfg.get_numeric_constant(arguments[0]),
dfg.get_numeric_constant(arguments[1]),
dfg.get_numeric_constant(arguments[2]),
dfg.get_numeric_constant(arguments[3]),
dfg.get_numeric_constant(arguments[4]),
dfg.get_numeric_constant(arguments[5]),
) {
(
Some(point1_x),
Some(point1_y),
Some(point1_is_infinity),
Some(point2_x),
Some(point2_y),
Some(point2_is_infinity),
) => {
let Ok((result_x, result_y, result_is_infinity)) = solver.ec_add(
&point1_x,
&point1_y,
&point1_is_infinity,
&point2_x,
&point2_y,
&point2_is_infinity,
) else {
return SimplifyResult::None;
};

let result_x = dfg.make_constant(result_x, Type::field());
let result_y = dfg.make_constant(result_y, Type::field());
let result_is_infinity = dfg.make_constant(result_is_infinity, Type::bool());

let typ = Type::Array(Rc::new(vec![Type::field()]), 3);
let result_array =
dfg.make_array(im::vector![result_x, result_y, result_is_infinity], typ);

SimplifyResult::SimplifiedTo(result_array)
}
_ => SimplifyResult::None,
}
}

pub(super) fn simplify_poseidon2_permutation(
dfg: &mut DataFlowGraph,
solver: impl BlackBoxFunctionSolver<FieldElement>,
arguments: &[ValueId],
) -> SimplifyResult {
match (dfg.get_array_constant(arguments[0]), dfg.get_numeric_constant(arguments[1])) {
(Some((state, _)), Some(state_length)) if array_is_constant(dfg, &state) => {
let state: Vec<FieldElement> = state
.iter()
.map(|id| {
dfg.get_numeric_constant(*id)
.expect("value id from array should point at constant")
})
.collect();

let Some(state_length) = state_length.try_to_u32() else {
return SimplifyResult::None;
};

let Ok(new_state) = solver.poseidon2_permutation(&state, state_length) else {
return SimplifyResult::None;
};

let result_array = make_constant_array(dfg, new_state, Type::field());

SimplifyResult::SimplifiedTo(result_array)
}
_ => SimplifyResult::None,
}
}

pub(super) fn simplify_schnorr_verify(
dfg: &mut DataFlowGraph,
solver: impl BlackBoxFunctionSolver<FieldElement>,
arguments: &[ValueId],
) -> SimplifyResult {
match (
dfg.get_numeric_constant(arguments[0]),
dfg.get_numeric_constant(arguments[1]),
dfg.get_array_constant(arguments[2]),
dfg.get_array_constant(arguments[3]),
) {
(Some(public_key_x), Some(public_key_y), Some((signature, _)), Some((message, _)))
if array_is_constant(dfg, &signature) && array_is_constant(dfg, &message) =>
{
let signature = to_u8_vec(dfg, signature);
let signature: [u8; 64] =
signature.try_into().expect("Compiler should produce correctly sized signature");

let message = to_u8_vec(dfg, message);

let Ok(valid_signature) =
solver.schnorr_verify(&public_key_x, &public_key_y, &signature, &message)
else {
return SimplifyResult::None;
};

let valid_signature = dfg.make_constant(valid_signature.into(), Type::bool());
SimplifyResult::SimplifiedTo(valid_signature)
}
_ => SimplifyResult::None,
}
}

pub(super) fn simplify_hash(
dfg: &mut DataFlowGraph,
arguments: &[ValueId],
hash_function: fn(&[u8]) -> Result<[u8; 32], BlackBoxResolutionError>,
) -> SimplifyResult {
match dfg.get_array_constant(arguments[0]) {
Some((input, _)) if array_is_constant(dfg, &input) => {
let input_bytes: Vec<u8> = to_u8_vec(dfg, input);

let hash = hash_function(&input_bytes)
.expect("Rust solvable black box function should not fail");

let hash_values = vecmap(hash, |byte| FieldElement::from_be_bytes_reduce(&[byte]));

let result_array = make_constant_array(dfg, hash_values, Type::unsigned(8));
SimplifyResult::SimplifiedTo(result_array)
}
_ => SimplifyResult::None,
}
}

type ECDSASignatureVerifier = fn(
hashed_msg: &[u8],
public_key_x: &[u8; 32],
public_key_y: &[u8; 32],
signature: &[u8; 64],
) -> Result<bool, BlackBoxResolutionError>;

pub(super) fn simplify_signature(
dfg: &mut DataFlowGraph,
arguments: &[ValueId],
signature_verifier: ECDSASignatureVerifier,
) -> SimplifyResult {
match (
dfg.get_array_constant(arguments[0]),
dfg.get_array_constant(arguments[1]),
dfg.get_array_constant(arguments[2]),
dfg.get_array_constant(arguments[3]),
) {
(
Some((public_key_x, _)),
Some((public_key_y, _)),
Some((signature, _)),
Some((hashed_message, _)),
) if array_is_constant(dfg, &public_key_x)
&& array_is_constant(dfg, &public_key_y)
&& array_is_constant(dfg, &signature)
&& array_is_constant(dfg, &hashed_message) =>
{
let public_key_x: [u8; 32] = to_u8_vec(dfg, public_key_x)
.try_into()
.expect("ECDSA public key fields are 32 bytes");
let public_key_y: [u8; 32] = to_u8_vec(dfg, public_key_y)
.try_into()
.expect("ECDSA public key fields are 32 bytes");
let signature: [u8; 64] =
to_u8_vec(dfg, signature).try_into().expect("ECDSA signatures are 64 bytes");
let hashed_message: Vec<u8> = to_u8_vec(dfg, hashed_message);

let valid_signature =
signature_verifier(&hashed_message, &public_key_x, &public_key_y, &signature)
.expect("Rust solvable black box function should not fail");

let valid_signature = dfg.make_constant(valid_signature.into(), Type::bool());
SimplifyResult::SimplifiedTo(valid_signature)
}
_ => SimplifyResult::None,
}
}
2 changes: 1 addition & 1 deletion noir/noir-repo/compiler/noirc_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ num-traits.workspace = true
rustc-hash = "1.1.0"
small-ord-set = "0.1.3"
regex = "1.9.1"
cfg-if = "1.0.0"
cfg-if.workspace = true
tracing.workspace = true
petgraph = "0.6"
rangemap = "1.4.0"
Expand Down
1 change: 1 addition & 0 deletions noir/noir-repo/noir_stdlib/src/array.nr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::option::Option;
use crate::convert::From;

impl<T, let N: u32> [T; N] {
/// Returns the length of the slice.
#[builtin(array_len)]
pub fn len(self) -> u32 {}

Expand Down
Loading

0 comments on commit 919020d

Please sign in to comment.