Skip to content

Commit

Permalink
feat: Sync from aztec-packages (#4902)
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#5999)
refactor: using poseidon2 when computing a nullifier
(AztecProtocol/aztec-packages#5906)
feat: Sync from noir
(AztecProtocol/aztec-packages#5955)
feat: Sync from noir
(AztecProtocol/aztec-packages#5935)
chore: redo typo PR by dockercui
(AztecProtocol/aztec-packages#5930)
chore: Improve `compute_note_hash_and_nullifier` autogeneration and
`NoteProcessor` warnings
(AztecProtocol/aztec-packages#5838)
END_COMMIT_OVERRIDE

---------

Co-authored-by: Tom French <tom@tomfren.ch>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 24, 2024
1 parent 5985e42 commit 73e23c8
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 89 deletions.
2 changes: 1 addition & 1 deletion .aztec-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
beab8c93857536e07fa37994213fc664a5864013
2e64428af9525bd8c390931061505f7b48d729a4
22 changes: 11 additions & 11 deletions .github/actions/install-playwright/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ description: Installs Playwright and its dependencies and caches them.
runs:
using: composite
steps:
- name: Query playwright version
shell: bash
run: echo "PLAYWRIGHT_VERSION=$(yarn workspace @noir-lang/noirc_abi info @web/test-runner-playwright --json | jq .children.Version | tr -d '"')" >> $GITHUB_ENV
# - name: Query playwright version
# shell: bash
# run: echo "PLAYWRIGHT_VERSION=$(yarn workspace @noir-lang/noirc_abi info @web/test-runner-playwright --json | jq .children.Version | tr -d '"')" >> $GITHUB_ENV

- name: Cache playwright binaries
uses: actions/cache@v4
id: playwright-cache
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
# - name: Cache playwright binaries
# uses: actions/cache@v4
# id: playwright-cache
# with:
# path: |
# ~/.cache/ms-playwright
# key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}

- name: Install playwright deps
shell: bash
if: steps.playwright-cache.outputs.cache-hit != 'true'
# if: steps.playwright-cache.outputs.cache-hit != 'true'
run: |
# Workaround: https://github.com/microsoft/playwright/issues/30503#issuecomment-2074783821
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
Expand Down
4 changes: 2 additions & 2 deletions acvm-repo/acvm_js/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ BROWSER_WASM=${BROWSER_DIR}/${pname}_bg.wasm
run_or_fail cargo build --lib --release --target $TARGET --package ${pname}
run_or_fail wasm-bindgen $WASM_BINARY --out-dir $NODE_DIR --typescript --target nodejs
run_or_fail wasm-bindgen $WASM_BINARY --out-dir $BROWSER_DIR --typescript --target web
run_or_fail wasm-opt $NODE_WASM -o $NODE_WASM -O
run_or_fail wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O
run_if_available wasm-opt $NODE_WASM -o $NODE_WASM -O
run_if_available wasm-opt $BROWSER_WASM -o $BROWSER_WASM -O
13 changes: 7 additions & 6 deletions aztec_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,18 @@ fn transform_module(
// Check for a user defined storage struct

let maybe_storage_struct_name = check_for_storage_definition(module)?;

let storage_defined = maybe_storage_struct_name.is_some();

if let Some(storage_struct_name) = maybe_storage_struct_name {
if !check_for_storage_implementation(module, &storage_struct_name) {
generate_storage_implementation(module, &storage_struct_name)?;
if let Some(ref storage_struct_name) = maybe_storage_struct_name {
if !check_for_storage_implementation(module, storage_struct_name) {
generate_storage_implementation(module, storage_struct_name)?;
}
// Make sure we're only generating the storage layout for the root crate
// In case we got a contract importing other contracts for their interface, we
// don't want to generate the storage layout for them
if crate_id == context.root_crate_id() {
generate_storage_layout(module, storage_struct_name)?;
generate_storage_layout(module, storage_struct_name.clone())?;
}
}

Expand Down Expand Up @@ -164,14 +165,14 @@ fn transform_module(
transform_function(
fn_type,
func,
storage_defined,
maybe_storage_struct_name.clone(),
is_initializer,
insert_init_check,
is_internal,
)?;
has_transformed_module = true;
} else if storage_defined && func.def.is_unconstrained {
transform_unconstrained(func);
transform_unconstrained(func, maybe_storage_struct_name.clone().unwrap());
has_transformed_module = true;
}
}
Expand Down
94 changes: 81 additions & 13 deletions aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use noirc_frontend::{

use crate::utils::{
errors::AztecMacroError,
hir_utils::{collect_crate_functions, fetch_notes, get_contract_module_data, inject_fn},
hir_utils::{
collect_crate_functions, collect_traits, fetch_notes, get_contract_module_data,
get_global_numberic_const, get_serialized_length, inject_fn,
},
};

// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined
Expand Down Expand Up @@ -60,13 +63,68 @@ pub fn inject_compute_note_hash_and_nullifier(
return Ok(());
}

let traits: Vec<_> = collect_traits(context);

// Get MAX_NOTE_FIELDS_LENGTH global to check if the notes in our contract are too long.
let max_note_length_const = get_global_numberic_const(context, "MAX_NOTE_FIELDS_LENGTH")
.map_err(|err| {
(
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
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
// contract might use. These are the types that are marked as #[aztec(note)].
// contract might use and their serialized lengths. These are the types that are marked as #[aztec(note)].
let mut notes_and_lengths = vec![];

for (path, typ) in fetch_notes(context) {
let serialized_len: u128 = get_serialized_length(
&traits,
"NoteInterface",
&Type::Struct(typ.clone(), vec![]),
&context.def_interner,
)
.map_err(|_err| {
(
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
secondary_message: Some(format!(
"Failed to get serialized length for note type {}",
path
)),
},
file_id,
)
})?
.into();

if serialized_len > max_note_length_const {
return Err((
AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier {
secondary_message: Some(format!(
"Note type {} as {} fields, which is more than the maximum allowed length of {}.",
path,
serialized_len,
max_note_length_const
)),
},
file_id,
));
}

notes_and_lengths.push((path.to_string(), serialized_len));
}

let max_note_length: u128 =
*notes_and_lengths.iter().map(|(_, serialized_len)| serialized_len).max().unwrap_or(&0);

let note_types =
fetch_notes(context).iter().map(|(path, _)| path.to_string()).collect::<Vec<_>>();
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);
let func = generate_compute_note_hash_and_nullifier(&note_types, max_note_length);

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

Expand All @@ -86,8 +144,12 @@ pub fn inject_compute_note_hash_and_nullifier(
Ok(())
}

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

let (function_ast, errors) = parse_program(&function_source);
if !errors.is_empty() {
Expand All @@ -99,25 +161,30 @@ fn generate_compute_note_hash_and_nullifier(note_types: &[String]) -> NoirFuncti
function_ast.functions.remove(0)
}

fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> String {
fn generate_compute_note_hash_and_nullifier_source(
note_types: &[String],
max_note_length: u128,
) -> String {
// TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have.
// For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH.

if note_types.is_empty() {
// Even if the contract does not include any notes, other parts of the stack expect for this function to exist,
// so we include a dummy version.
"
format!(
"
unconstrained fn compute_note_hash_and_nullifier(
contract_address: dep::aztec::protocol_types::address::AztecAddress,
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; 20]
) -> pub [Field; 4] {
serialized_note: [Field; {}]
) -> pub [Field; 4] {{
assert(false, \"This contract does not use private notes\");
[0, 0, 0, 0]
}"
.to_string()
}}",
max_note_length
)
} else {
// For contracts that include notes we do a simple if-else chain comparing note_type_id with the different
// get_note_type_id of each of the note types.
Expand All @@ -142,12 +209,13 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> Str
nonce: Field,
storage_slot: Field,
note_type_id: Field,
serialized_note: [Field; 20]
serialized_note: [Field; {}]
) -> pub [Field; 4] {{
let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot);
{}
}}",
max_note_length,
full_if_statement
)
}
Expand Down
19 changes: 11 additions & 8 deletions aztec_macros/src/transforms/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
pub fn transform_function(
ty: &str,
func: &mut NoirFunction,
storage_defined: bool,
storage_struct_name: Option<String>,
is_initializer: bool,
insert_init_check: bool,
is_internal: bool,
Expand Down Expand Up @@ -57,8 +57,8 @@ pub fn transform_function(
}

// Add access to the storage struct
if storage_defined {
let storage_def = abstract_storage(&ty.to_lowercase(), false);
if let Some(storage_struct_name) = storage_struct_name {
let storage_def = abstract_storage(storage_struct_name, &ty.to_lowercase(), false);
func.def.body.statements.insert(0, storage_def);
}

Expand Down Expand Up @@ -209,8 +209,11 @@ pub fn export_fn_abi(
/// ```
///
/// This will allow developers to access their contract' storage struct in unconstrained functions
pub fn transform_unconstrained(func: &mut NoirFunction) {
func.def.body.statements.insert(0, abstract_storage("Unconstrained", true));
pub fn transform_unconstrained(func: &mut NoirFunction, storage_struct_name: String) {
func.def
.body
.statements
.insert(0, abstract_storage(storage_struct_name, "Unconstrained", true));
}

/// Helper function that returns what the private context would look like in the ast
Expand Down Expand Up @@ -575,7 +578,7 @@ fn abstract_return_values(func: &NoirFunction) -> Result<Option<Vec<Statement>>,
/// unconstrained fn lol() {
/// let storage = Storage::init(Context::none());
/// }
fn abstract_storage(typ: &str, unconstrained: bool) -> Statement {
fn abstract_storage(storage_struct_name: String, typ: &str, unconstrained: bool) -> Statement {
let init_context_call = if unconstrained {
call(
variable_path(chained_dep!("aztec", "context", "Context", "none")), // Path
Expand All @@ -591,8 +594,8 @@ fn abstract_storage(typ: &str, unconstrained: bool) -> Statement {
assignment(
"storage", // Assigned to
call(
variable_path(chained_path!("Storage", "init")), // Path
vec![init_context_call], // args
variable_path(chained_path!(storage_struct_name.as_str(), "init")), // Path
vec![init_context_call], // args
),
)
}
Expand Down
6 changes: 2 additions & 4 deletions aztec_macros/src/transforms/note_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,7 @@ fn generate_note_properties_fn(

// Automatically generate the method to compute the note's content hash as:
// fn compute_note_content_hash(self: NoteType) -> Field {
// // TODO(#1205) Should use a non-zero generator index.
// dep::aztec::hash::pedersen_hash(self.serialize_content(), 0)
// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH)
// }
//
fn generate_compute_note_content_hash(
Expand All @@ -429,8 +428,7 @@ fn generate_compute_note_content_hash(
let function_source = format!(
"
fn compute_note_content_hash(self: {}) -> Field {{
// TODO(#1205) Should use a non-zero generator index.
dep::aztec::hash::pedersen_hash(self.serialize_content(), 0)
dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH)
}}
",
note_type
Expand Down
Loading

0 comments on commit 73e23c8

Please sign in to comment.