Skip to content

Commit

Permalink
feat: Sync from aztec-packages (#5242)
Browse files Browse the repository at this point in the history
Automated pull of Noir development from
[aztec-packages](https://github.com/AztecProtocol/aztec-packages).
BEGIN_COMMIT_OVERRIDE
feat: Sync from noir
(AztecProtocol/aztec-packages#6986)
feat: `pxe.addNullifiedNote(...)`
(AztecProtocol/aztec-packages#6948)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <tom@tomfren.ch>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
Co-authored-by: Maxim Vezenov <mvezenov@gmail.com>
  • Loading branch information
4 people committed Jun 17, 2024
1 parent c08799d commit 7de19f5
Show file tree
Hide file tree
Showing 17 changed files with 67 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .aztec-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
86a33140f9a65e518003b3f4c60f97d132f85b89
12af650f0d27c37dca06bb329bf76a5574534d78
4 changes: 2 additions & 2 deletions aztec_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod utils;

use noirc_errors::Location;
use transforms::{
compute_note_hash_and_nullifier::inject_compute_note_hash_and_nullifier,
compute_note_hash_and_optionally_a_nullifier::inject_compute_note_hash_and_optionally_a_nullifier,
contract_interface::{
generate_contract_interface, stub_function, update_fn_signatures_in_contract_interface,
},
Expand Down Expand Up @@ -236,7 +236,7 @@ fn transform_hir(
) -> Result<(), (AztecMacroError, FileId)> {
if has_aztec_dependency(crate_id, context) {
transform_events(crate_id, context)?;
inject_compute_note_hash_and_nullifier(crate_id, context)?;
inject_compute_note_hash_and_optionally_a_nullifier(crate_id, context)?;
assign_storage_slots(crate_id, context)?;
inject_note_exports(crate_id, context)?;
update_fn_signatures_in_contract_interface(crate_id, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@ use crate::utils::{
},
};

// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined
fn check_for_compute_note_hash_and_nullifier_definition(
// Check if "compute_note_hash_and_optionally_a_nullifier(AztecAddress,Field,Field,Field,bool,[Field; N]) -> [Field; 4]" is defined
fn check_for_compute_note_hash_and_optionally_a_nullifier_definition(
crate_id: &CrateId,
context: &HirContext,
) -> bool {
collect_crate_functions(crate_id, context).iter().any(|funct_id| {
let func_data = context.def_interner.function_meta(funct_id);
let func_name = context.def_interner.function_name(funct_id);
func_name == "compute_note_hash_and_nullifier"
&& func_data.parameters.len() == 5
func_name == "compute_note_hash_and_optionally_a_nullifier"
&& func_data.parameters.len() == 6
&& func_data.parameters.0.first().is_some_and(| (_, typ, _) | match typ {
Type::Struct(struct_typ, _) => struct_typ.borrow().name.0.contents == "AztecAddress",
_ => false
})
&& func_data.parameters.0.get(1).is_some_and(|(_, typ, _)| typ.is_field())
&& func_data.parameters.0.get(2).is_some_and(|(_, typ, _)| typ.is_field())
&& func_data.parameters.0.get(3).is_some_and(|(_, typ, _)| typ.is_field())
// checks if the 5th parameter is an array and contains only fields
&& func_data.parameters.0.get(4).is_some_and(|(_, typ, _)| match typ {
&& func_data.parameters.0.get(4).is_some_and(|(_, typ, _)| typ.is_bool())
// checks if the 6th parameter is an array and contains only fields
&& func_data.parameters.0.get(5).is_some_and(|(_, typ, _)| match typ {
Type::Array(_, inner_type) => inner_type.to_owned().is_field(),
_ => false
})
Expand All @@ -49,16 +50,16 @@ fn check_for_compute_note_hash_and_nullifier_definition(
})
}

pub fn inject_compute_note_hash_and_nullifier(
pub fn inject_compute_note_hash_and_optionally_a_nullifier(
crate_id: &CrateId,
context: &mut HirContext,
) -> Result<(), (AztecMacroError, FileId)> {
if let Some((_, module_id, file_id)) = get_contract_module_data(context, crate_id) {
// If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an
// If compute_note_hash_and_optionally_a_nullifier is already defined by the user, we skip auto-generation in order to provide an
// escape hatch for this mechanism.
// TODO(#4647): improve this diagnosis and error messaging.
if context.crate_graph.root_crate_id() != crate_id
|| check_for_compute_note_hash_and_nullifier_definition(crate_id, context)
|| check_for_compute_note_hash_and_optionally_a_nullifier_definition(crate_id, context)
{
return Ok(());
}
Expand All @@ -69,14 +70,14 @@ pub fn inject_compute_note_hash_and_nullifier(
let max_note_length_const = get_global_numberic_const(context, "MAX_NOTE_FIELDS_LENGTH")
.map_err(|err| {
(
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
AztecMacroError::CouldNotImplementComputeNoteHashAndOptionallyANullifier {
secondary_message: Some(err.primary_message),
},
file_id,
)
})?;

// In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the
// In order to implement compute_note_hash_and_optionally_a_nullifier, we need to know all of the different note types the
// contract might use and their serialized lengths. These are the types that are marked as #[aztec(note)].
let mut notes_and_lengths = vec![];

Expand All @@ -89,7 +90,7 @@ pub fn inject_compute_note_hash_and_nullifier(
)
.map_err(|_err| {
(
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
AztecMacroError::CouldNotImplementComputeNoteHashAndOptionallyANullifier {
secondary_message: Some(format!(
"Failed to get serialized length for note type {}",
path
Expand All @@ -102,7 +103,7 @@ pub fn inject_compute_note_hash_and_nullifier(

if serialized_len > max_note_length_const {
return Err((
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
AztecMacroError::CouldNotImplementComputeNoteHashAndOptionallyANullifier {
secondary_message: Some(format!(
"Note type {} as {} fields, which is more than the maximum allowed length of {}.",
path,
Expand All @@ -120,11 +121,12 @@ pub fn inject_compute_note_hash_and_nullifier(
let max_note_length: u128 =
*notes_and_lengths.iter().map(|(_, serialized_len)| serialized_len).max().unwrap_or(&0);

let note_types =
let note_types: Vec<String> =
notes_and_lengths.iter().map(|(note_type, _)| note_type.clone()).collect::<Vec<_>>();

// We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate.
let func = generate_compute_note_hash_and_nullifier(&note_types, max_note_length);
// We can now generate a version of compute_note_hash_and_optionally_a_nullifier tailored for the contract in this crate.
let func =
generate_compute_note_hash_and_optionally_a_nullifier(&note_types, max_note_length);

// And inject the newly created function into the contract.

Expand All @@ -134,7 +136,7 @@ pub fn inject_compute_note_hash_and_nullifier(

inject_fn(crate_id, context, func, location, module_id, file_id).map_err(|err| {
(
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
AztecMacroError::CouldNotImplementComputeNoteHashAndOptionallyANullifier {
secondary_message: err.secondary_message,
},
file_id,
Expand All @@ -144,12 +146,12 @@ pub fn inject_compute_note_hash_and_nullifier(
Ok(())
}

fn generate_compute_note_hash_and_nullifier(
fn generate_compute_note_hash_and_optionally_a_nullifier(
note_types: &[String],
max_note_length: u128,
) -> NoirFunction {
let function_source =
generate_compute_note_hash_and_nullifier_source(note_types, max_note_length);
generate_compute_note_hash_and_optionally_a_nullifier_source(note_types, max_note_length);

let (function_ast, errors) = parse_program(&function_source);
if !errors.is_empty() {
Expand All @@ -161,7 +163,7 @@ fn generate_compute_note_hash_and_nullifier(
function_ast.functions.remove(0)
}

fn generate_compute_note_hash_and_nullifier_source(
fn generate_compute_note_hash_and_optionally_a_nullifier_source(
note_types: &[String],
max_note_length: u128,
) -> String {
Expand All @@ -173,12 +175,13 @@ fn generate_compute_note_hash_and_nullifier_source(
// so we include a dummy version.
format!(
"
unconstrained fn compute_note_hash_and_nullifier(
unconstrained fn compute_note_hash_and_optionally_a_nullifier(
contract_address: dep::aztec::protocol_types::address::AztecAddress,
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; {}]
compute_nullifier: bool,
serialized_note: [Field; {}],
) -> pub [Field; 4] {{
assert(false, \"This contract does not use private notes\");
[0, 0, 0, 0]
Expand All @@ -191,7 +194,7 @@ fn generate_compute_note_hash_and_nullifier_source(

let if_statements: Vec<String> = note_types.iter().map(|note_type| format!(
"if (note_type_id == {0}::get_note_type_id()) {{
dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note)
dep::aztec::note::utils::compute_note_hash_and_optionally_a_nullifier({0}::deserialize_content, note_header, compute_nullifier, serialized_note)
}}"
, note_type)).collect();

Expand All @@ -204,12 +207,13 @@ fn generate_compute_note_hash_and_nullifier_source(

format!(
"
unconstrained fn compute_note_hash_and_nullifier(
unconstrained fn compute_note_hash_and_optionally_a_nullifier(
contract_address: dep::aztec::protocol_types::address::AztecAddress,
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; {}]
compute_nullifier: bool,
serialized_note: [Field; {}],
) -> pub [Field; 4] {{
let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot);
Expand Down
2 changes: 1 addition & 1 deletion aztec_macros/src/transforms/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod compute_note_hash_and_nullifier;
pub mod compute_note_hash_and_optionally_a_nullifier;
pub mod contract_interface;
pub mod events;
pub mod functions;
Expand Down
6 changes: 3 additions & 3 deletions aztec_macros/src/utils/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub enum AztecMacroError {
UnsupportedFunctionReturnType { span: Span, typ: ast::UnresolvedTypeData },
UnsupportedStorageType { span: Option<Span>, typ: ast::UnresolvedTypeData },
CouldNotAssignStorageSlots { secondary_message: Option<String> },
CouldNotImplementComputeNoteHashAndNullifier { secondary_message: Option<String> },
CouldNotImplementComputeNoteHashAndOptionallyANullifier { secondary_message: Option<String> },
CouldNotImplementNoteInterface { span: Option<Span>, secondary_message: Option<String> },
MultipleStorageDefinitions { span: Option<Span> },
CouldNotExportStorageLayout { span: Option<Span>, secondary_message: Option<String> },
Expand Down Expand Up @@ -57,8 +57,8 @@ impl From<AztecMacroError> for MacroError {
secondary_message,
span: None,
},
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { secondary_message } => MacroError {
primary_message: "Could not implement compute_note_hash_and_nullifier automatically, please provide an implementation".to_string(),
AztecMacroError::CouldNotImplementComputeNoteHashAndOptionallyANullifier { secondary_message } => MacroError {
primary_message: "Could not implement compute_note_hash_and_optionally_a_nullifier automatically, please provide an implementation".to_string(),
secondary_message,
span: None,
},
Expand Down
2 changes: 1 addition & 1 deletion compiler/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "echo Integration Test build step",
"test": "yarn test:browser && yarn test:node",
"test:node": "bash ./scripts/setup.sh && hardhat test test/node/**/*",
"test:node": "bash ./scripts/setup.sh && hardhat test test/node/prove_and_verify.test.ts && hardhat test test/node/smart_contract_verifier.test.ts && hardhat test test/node/onchain_recursive_verification.test.ts",
"test:browser": "web-test-runner",
"test:integration:browser": "web-test-runner test/browser/**/*.test.ts",
"test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch",
Expand Down
36 changes: 16 additions & 20 deletions compiler/integration-tests/test/node/prove_and_verify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { CompiledCircuit } from '@noir-lang/types';
const assert_lt_program = assert_lt_json as CompiledCircuit;
const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit;

const backend = new Backend(assert_lt_program);

it('end-to-end proof creation and verification (outer)', async () => {
// Noir.Js part
const inputs = {
Expand All @@ -22,11 +24,10 @@ it('end-to-end proof creation and verification (outer)', async () => {
// bb.js part
//
// Proof creation
const prover = new Backend(assert_lt_program);
const proof = await prover.generateProof(witness);
const proof = await backend.generateProof(witness);

// Proof verification
const isValid = await prover.verifyProof(proof);
const isValid = await backend.verifyProof(proof);
expect(isValid).to.be.true;
});

Expand All @@ -42,10 +43,9 @@ it('end-to-end proof creation and verification (outer) -- Verifier API', async (
const { witness } = await program.execute(inputs);

// Generate proof
const prover = new Backend(assert_lt_program);
const proof = await prover.generateProof(witness);
const proof = await backend.generateProof(witness);

const verificationKey = await prover.getVerificationKey();
const verificationKey = await backend.getVerificationKey();

// Proof verification
const verifier = new Verifier();
Expand All @@ -68,11 +68,10 @@ it('end-to-end proof creation and verification (inner)', async () => {
// bb.js part
//
// Proof creation
const prover = new Backend(assert_lt_program);
const proof = await prover.generateProof(witness);
const proof = await backend.generateProof(witness);

// Proof verification
const isValid = await prover.verifyProof(proof);
const isValid = await backend.verifyProof(proof);
expect(isValid).to.be.true;
});

Expand All @@ -88,9 +87,7 @@ it('end-to-end proving and verification with different instances', async () => {
const { witness } = await program.execute(inputs);

// bb.js part
const prover = new Backend(assert_lt_program);

const proof = await prover.generateProof(witness);
const proof = await backend.generateProof(witness);

const verifier = new Backend(assert_lt_program);
const proof_is_valid = await verifier.verifyProof(proof);
Expand Down Expand Up @@ -119,18 +116,17 @@ it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ',
//
// Proof creation
//
const prover = new Backend(assert_lt_program);
// Create a proof using both proving systems, the majority of the time
// one would only use outer proofs.
const proofOuter = await prover.generateProof(witness);
const _proofInner = await prover.generateProof(witness);
const proofOuter = await backend.generateProof(witness);
const _proofInner = await backend.generateProof(witness);

// Proof verification
//
const isValidOuter = await prover.verifyProof(proofOuter);
const isValidOuter = await backend.verifyProof(proofOuter);
expect(isValidOuter).to.be.true;
// We can also try verifying an inner proof and it will fail.
const isValidInner = await prover.verifyProof(_proofInner);
const isValidInner = await backend.verifyProof(_proofInner);
expect(isValidInner).to.be.true;
});

Expand All @@ -147,10 +143,10 @@ it('end-to-end proof creation and verification for multiple ACIR circuits (inner
// bb.js part
//
// Proof creation
const prover = new Backend(fold_fibonacci_program);
const proof = await prover.generateProof(witness);
const backend = new Backend(fold_fibonacci_program);
const proof = await backend.generateProof(witness);

// Proof verification
const isValid = await prover.verifyProof(proof);
const isValid = await backend.verifyProof(proof);
expect(isValid).to.be.true;
});
15 changes: 10 additions & 5 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ impl<'a> Interpreter<'a> {
let mut scope = Vec::new();
if self.scopes.len() > 1 {
scope = self.scopes.drain(1..).collect();
self.push_scope();
}
self.push_scope();
(std::mem::take(&mut self.in_loop), scope)
}

Expand Down Expand Up @@ -210,10 +210,11 @@ impl<'a> Interpreter<'a> {
}
},
HirPattern::Struct(struct_type, pattern_fields, _) => {
self.push_scope();
self.type_check(typ, &argument, location)?;
self.type_check(struct_type, &argument, location)?;

match argument {
let res = match argument {
Value::Struct(fields, struct_type) if fields.len() == pattern_fields.len() => {
for (field_name, field_pattern) in pattern_fields {
let field = fields.get(&field_name.0.contents).ok_or_else(|| {
Expand All @@ -239,7 +240,9 @@ impl<'a> Interpreter<'a> {
value,
location,
}),
}
};
self.pop_scope();
res
}
}
}
Expand Down Expand Up @@ -358,13 +361,14 @@ impl<'a> Interpreter<'a> {
}
DefinitionKind::Local(_) => self.lookup(&ident),
DefinitionKind::Global(global_id) => {
// Don't need to check let_.comptime, we can evaluate non-comptime globals too.
// Avoid resetting the value if it is already known
if let Ok(value) = self.lookup(&ident) {
Ok(value)
} else {
let let_ = self.interner.get_global_let_statement(*global_id).unwrap();
self.evaluate_let(let_)?;
if let_.comptime {
self.evaluate_let(let_.clone())?;
}
self.lookup(&ident)
}
}
Expand Down Expand Up @@ -1296,6 +1300,7 @@ impl<'a> Interpreter<'a> {
Err(InterpreterError::Continue) => continue,
Err(other) => return Err(other),
}

self.pop_scope();
}

Expand Down
1 change: 0 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ impl<'interner> Interpreter<'interner> {
self.scan_expression(let_.expression)?;
}
}

Ok(())
}

Expand Down
Loading

0 comments on commit 7de19f5

Please sign in to comment.