Skip to content

Commit 4963c6c

Browse files
benesjanMaddiaa0
andauthored
feat: compute_note_hash_and_nullifier check (#3216)
Co-authored-by: Maddiaa <47148561+Maddiaa0@users.noreply.github.com>
1 parent 5cfd156 commit 4963c6c

2 files changed

Lines changed: 83 additions & 21 deletions

File tree

compiler/noirc_frontend/src/hir/aztec_library.rs

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,9 @@ pub(crate) fn transform(
170170

171171
// Covers all functions in the ast
172172
for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) {
173-
let storage_defined = check_for_storage_definition(&submodule.contents);
174-
175-
if transform_module(&mut submodule.contents, storage_defined) {
176-
match check_for_aztec_dependency(crate_id, context) {
177-
Ok(()) => include_relevant_imports(&mut submodule.contents),
178-
Err(file_id) => {
179-
return Err((DefCollectorErrorKind::AztecNotFound {}, file_id));
180-
}
181-
}
173+
if transform_module(&mut submodule.contents, crate_id, context)? {
174+
check_for_aztec_dependency(crate_id, context)?;
175+
include_relevant_imports(&mut submodule.contents);
182176
}
183177
}
184178
Ok(ast)
@@ -209,19 +203,59 @@ fn include_relevant_imports(ast: &mut SortedModule) {
209203
}
210204

211205
/// Creates an error alerting the user that they have not downloaded the Aztec-noir library
212-
fn check_for_aztec_dependency(crate_id: &CrateId, context: &Context) -> Result<(), FileId> {
206+
fn check_for_aztec_dependency(
207+
crate_id: &CrateId,
208+
context: &Context,
209+
) -> Result<(), (DefCollectorErrorKind, FileId)> {
213210
let crate_graph = &context.crate_graph[crate_id];
214211
let has_aztec_dependency = crate_graph.dependencies.iter().any(|dep| dep.as_name() == "aztec");
215212
if has_aztec_dependency {
216213
Ok(())
217214
} else {
218-
Err(crate_graph.root_file_id)
215+
Err((DefCollectorErrorKind::AztecNotFound {}, crate_graph.root_file_id))
219216
}
220217
}
221218

222219
// Check to see if the user has defined a storage struct
223220
fn check_for_storage_definition(module: &SortedModule) -> bool {
224-
module.types.iter().any(|function| function.name.0.contents == "Storage")
221+
module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage")
222+
}
223+
224+
// Check if "compute_note_hash_and_nullifier(Field,Field,Field,[Field; N]) -> [Field; 4]" is defined
225+
fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -> bool {
226+
module.functions.iter().any(|func| {
227+
func.def.name.0.contents == "compute_note_hash_and_nullifier"
228+
&& func.def.parameters.len() == 4
229+
&& func.def.parameters[0].1.typ == UnresolvedTypeData::FieldElement
230+
&& func.def.parameters[1].1.typ == UnresolvedTypeData::FieldElement
231+
&& func.def.parameters[2].1.typ == UnresolvedTypeData::FieldElement
232+
// checks if the 4th parameter is an array and the Box<UnresolvedType> in
233+
// Array(Option<UnresolvedTypeExpression>, Box<UnresolvedType>) contains only fields
234+
&& match &func.def.parameters[3].1.typ {
235+
UnresolvedTypeData::Array(_, inner_type) => {
236+
match inner_type.typ {
237+
UnresolvedTypeData::FieldElement => true,
238+
_ => false,
239+
}
240+
},
241+
_ => false,
242+
}
243+
// We check the return type the same way as we did the 4th parameter
244+
&& match &func.def.return_type {
245+
FunctionReturnType::Default(_) => false,
246+
FunctionReturnType::Ty(unresolved_type) => {
247+
match &unresolved_type.typ {
248+
UnresolvedTypeData::Array(_, inner_type) => {
249+
match inner_type.typ {
250+
UnresolvedTypeData::FieldElement => true,
251+
_ => false,
252+
}
253+
},
254+
_ => false,
255+
}
256+
}
257+
}
258+
})
225259
}
226260

227261
/// Checks if an attribute is a custom attribute with a specific name
@@ -236,9 +270,26 @@ fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool
236270
/// Determines if ast nodes are annotated with aztec attributes.
237271
/// For annotated functions it calls the `transform` function which will perform the required transformations.
238272
/// Returns true if an annotated node is found, false otherwise
239-
fn transform_module(module: &mut SortedModule, storage_defined: bool) -> bool {
273+
fn transform_module(
274+
module: &mut SortedModule,
275+
crate_id: &CrateId,
276+
context: &Context,
277+
) -> Result<bool, (DefCollectorErrorKind, FileId)> {
240278
let mut has_transformed_module = false;
241279

280+
// Check for a user defined storage struct
281+
let storage_defined = check_for_storage_definition(&module);
282+
283+
if storage_defined && check_for_compute_note_hash_and_nullifier_definition(&module) {
284+
let crate_graph = &context.crate_graph[crate_id];
285+
return Err((
286+
DefCollectorErrorKind::AztecComputeNoteHashAndNullifierNotFound {
287+
span: Span::default(), // Add a default span so we know which contract file the error originates from
288+
},
289+
crate_graph.root_file_id,
290+
));
291+
}
292+
242293
for structure in module.types.iter() {
243294
if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) {
244295
module.impls.push(generate_selector_impl(structure));
@@ -262,7 +313,7 @@ fn transform_module(module: &mut SortedModule, storage_defined: bool) -> bool {
262313
has_transformed_module = true;
263314
}
264315
}
265-
has_transformed_module
316+
Ok(has_transformed_module)
266317
}
267318

268319
/// If it does, it will insert the following things:

compiler/noirc_frontend/src/hir/def_collector/errors.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,18 @@ pub enum DefCollectorErrorKind {
5757
ModuleAlreadyPartOfCrate { mod_name: Ident, span: Span },
5858
#[error("Module was originally declared here")]
5959
ModuleOriginallyDefined { mod_name: Ident, span: Span },
60-
#[cfg(feature = "aztec")]
61-
#[error("Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml")]
62-
AztecNotFound {},
6360
#[error(
6461
"Either the type or the trait must be from the same crate as the trait implementation"
6562
)]
6663
TraitImplOrphaned { span: Span },
64+
65+
// Aztec feature flag errors
66+
#[cfg(feature = "aztec")]
67+
#[error("Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml")]
68+
AztecNotFound {},
69+
#[cfg(feature = "aztec")]
70+
#[error("compute_note_hash_and_nullifier function not found. Define it in your contract.")]
71+
AztecComputeNoteHashAndNullifierNotFound { span: Span },
6772
}
6873

6974
impl DefCollectorErrorKind {
@@ -194,15 +199,21 @@ impl From<DefCollectorErrorKind> for Diagnostic {
194199
let secondary = String::new();
195200
Diagnostic::simple_error(message, secondary, span)
196201
}
197-
#[cfg(feature = "aztec")]
198-
DefCollectorErrorKind::AztecNotFound {} => Diagnostic::from_message(
199-
"Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml",
200-
),
201202
DefCollectorErrorKind::TraitImplOrphaned { span } => Diagnostic::simple_error(
202203
"Orphaned trait implementation".into(),
203204
"Either the type or the trait must be from the same crate as the trait implementation".into(),
204205
span,
205206
),
207+
#[cfg(feature = "aztec")]
208+
DefCollectorErrorKind::AztecNotFound {} => Diagnostic::from_message(
209+
"Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml",
210+
),
211+
#[cfg(feature = "aztec")]
212+
DefCollectorErrorKind::AztecComputeNoteHashAndNullifierNotFound {span} => Diagnostic::simple_error(
213+
"compute_note_hash_and_nullifier function not found. Define it in your contract.".into(),
214+
"".into(),
215+
span
216+
),
206217
}
207218
}
208219
}

0 commit comments

Comments
 (0)