Skip to content

Commit

Permalink
feat!: automatic NoteInterface and NoteGetterOptions auto select (Azt…
Browse files Browse the repository at this point in the history
…ecProtocol/aztec-packages#4508)

Partially addresses:
AztecProtocol/aztec-packages#4519 (moved
autogeneration to the macro, even if not incremental)
Closes: AztecProtocol/aztec-packages#3011

Added the `#[aztec(note)]` attribute, which automatically implements
most of the `NoteInterface` trait in a struct marked as such, plus
several utilities. Even if this adds a fair share of "magic" to the note
implementation logic, it is structured in a way that it's hopefully easy
to follow, including meaningful errors attached to the correct span
during the process.

![Screenshot 2024-03-14 at 14 59
07](https://github.com/AztecProtocol/aztec-packages/assets/5404052/84a3d6e4-e346-4cfe-93eb-ec317632f344)

Hey you! Implement the trait!

![Screenshot 2024-03-14 at 14 46
39](https://github.com/AztecProtocol/aztec-packages/assets/5404052/bebfb3dd-c178-44d0-b9bc-005b5c9f0f38)
But only the meat and potatoes though.

As long as the user doesn't want to do any custom stuff, `get_header`,
`set_header`, `compute_note_content_hash`, `get_note_type_id`,
`serialize_content` and `deserialize_content` get automatically
implemented. Any combination of them can be overridden by the developer
though.

A metadata struct is also added, which takes the following form:

```rust
struct CardNote {
    points: FieldSelector,
    randomness: FieldSelector,
    owner: FieldSelector,
}
```

This is used to implement a `properties()` function, which in turn can
be used in conjunction with the `NoteGetterOptions.select` and `.sort`

<img width="697" alt="Screenshot 2024-03-18 at 15 27 27"
src="https://github.com/AztecProtocol/aztec-packages/assets/5404052/5da531b3-0b7f-4cf9-9908-300ff8d98c6d">
  • Loading branch information
AztecBot committed Mar 19, 2024
1 parent c3c9e19 commit 6b4175e
Show file tree
Hide file tree
Showing 27 changed files with 709 additions and 485 deletions.
2 changes: 1 addition & 1 deletion .aztec-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
82f8cf5eba9deacdab43ad4ef95dbf27dd1c11c7
b2df97907cb63446e9336e87f40f9dbd7a710845
27 changes: 20 additions & 7 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions aztec_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ noirc_frontend.workspace = true
noirc_errors.workspace = true
iter-extended.workspace = true
convert_case = "0.6.0"
regex = "1.10"

58 changes: 28 additions & 30 deletions aztec_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,38 @@ use transforms::{
compute_note_hash_and_nullifier::inject_compute_note_hash_and_nullifier,
events::{generate_selector_impl, transform_events},
functions::{transform_function, transform_unconstrained, transform_vm_function},
note_interface::generate_note_interface_impl,
storage::{
assign_storage_slots, check_for_storage_definition, check_for_storage_implementation,
generate_storage_implementation,
},
};

use noirc_frontend::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl};

use noirc_frontend::macros_api::SortedModule;
use noirc_frontend::macros_api::{CrateId, MacroError};
use noirc_frontend::macros_api::{FileId, MacroProcessor};
use noirc_frontend::macros_api::{HirContext, SecondaryAttribute, Span};
use noirc_frontend::{
hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl},
macros_api::{
CrateId, FileId, HirContext, MacroError, MacroProcessor, SecondaryAttribute, SortedModule,
Span,
},
};

use utils::ast_utils::is_custom_attribute;
use utils::checks::{check_for_aztec_dependency, has_aztec_dependency};
use utils::{constants::MAX_CONTRACT_PRIVATE_FUNCTIONS, errors::AztecMacroError};
use utils::{
ast_utils::is_custom_attribute,
checks::{check_for_aztec_dependency, has_aztec_dependency},
constants::MAX_CONTRACT_PRIVATE_FUNCTIONS,
errors::AztecMacroError,
};
pub struct AztecMacro;

impl MacroProcessor for AztecMacro {
fn process_untyped_ast(
&self,
ast: SortedModule,
crate_id: &CrateId,
file_id: FileId,
context: &HirContext,
) -> Result<SortedModule, (MacroError, FileId)> {
transform(ast, crate_id, context)
transform(ast, crate_id, file_id, context)
}

fn process_collected_defs(
Expand Down Expand Up @@ -61,38 +67,34 @@ impl MacroProcessor for AztecMacro {
fn transform(
mut ast: SortedModule,
crate_id: &CrateId,
file_id: FileId,
context: &HirContext,
) -> Result<SortedModule, (MacroError, FileId)> {
// Usage -> mut ast -> aztec_library::transform(&mut ast)
// Covers all functions in the ast
for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) {
if transform_module(&mut submodule.contents, crate_id, context)
.map_err(|(err, file_id)| (err.into(), file_id))?
{
if transform_module(&mut submodule.contents).map_err(|err| (err.into(), file_id))? {
check_for_aztec_dependency(crate_id, context)?;
}
}

generate_note_interface_impl(&mut ast).map_err(|err| (err.into(), file_id))?;

Ok(ast)
}

/// Determines if ast nodes are annotated with aztec attributes.
/// For annotated functions it calls the `transform` function which will perform the required transformations.
/// Returns true if an annotated node is found, false otherwise
fn transform_module(
module: &mut SortedModule,
crate_id: &CrateId,
context: &HirContext,
) -> Result<bool, (AztecMacroError, FileId)> {
fn transform_module(module: &mut SortedModule) -> Result<bool, AztecMacroError> {
let mut has_transformed_module = false;

// Check for a user defined storage struct
let storage_defined = check_for_storage_definition(module);
let storage_implemented = check_for_storage_implementation(module);

let crate_graph = &context.crate_graph[crate_id];

if storage_defined && !storage_implemented {
generate_storage_implementation(module).map_err(|err| (err, crate_graph.root_file_id))?;
generate_storage_implementation(module)?;
}

for structure in module.types.iter() {
Expand Down Expand Up @@ -144,12 +146,10 @@ fn transform_module(
is_initializer,
insert_init_check,
is_internal,
)
.map_err(|err| (err, crate_graph.root_file_id))?;
)?;
has_transformed_module = true;
} else if is_public_vm {
transform_vm_function(func, storage_defined)
.map_err(|err| (err, crate_graph.root_file_id))?;
transform_vm_function(func, storage_defined)?;
has_transformed_module = true;
} else if storage_defined && func.def.is_unconstrained {
transform_unconstrained(func);
Expand All @@ -173,11 +173,9 @@ fn transform_module(
.count();

if private_functions_count > MAX_CONTRACT_PRIVATE_FUNCTIONS {
let crate_graph = &context.crate_graph[crate_id];
return Err((
AztecMacroError::ContractHasTooManyPrivateFunctions { span: Span::default() },
crate_graph.root_file_id,
));
return Err(AztecMacroError::ContractHasTooManyPrivateFunctions {
span: Span::default(),
});
}
}

Expand Down
1 change: 1 addition & 0 deletions aztec_macros/src/transforms/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod compute_note_hash_and_nullifier;
pub mod events;
pub mod functions;
pub mod note_interface;
pub mod storage;
Loading

0 comments on commit 6b4175e

Please sign in to comment.