From 2b6a3e6677a6331129f04cbeb185d5e5eedac806 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:51:18 +0000 Subject: [PATCH 01/21] feat(attributes): allow for custom attributes --- crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs | 5 ++++- crates/noirc_frontend/src/ast/function.rs | 1 + crates/noirc_frontend/src/lexer/token.rs | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs index cc3a7c02a75..1367b1753af 100644 --- a/crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -130,7 +130,10 @@ impl<'a> FunctionContext<'a> { let slice_contents = self.codegen_array(elements, typ[1].clone()); Tree::Branch(vec![slice_length.into(), slice_contents]) } - _ => unreachable!("ICE: array literal type must be an array or a slice, but got {}", array.typ), + _ => unreachable!( + "ICE: array literal type must be an array or a slice, but got {}", + array.typ + ), } } ast::Literal::Integer(value, typ) => { diff --git a/crates/noirc_frontend/src/ast/function.rs b/crates/noirc_frontend/src/ast/function.rs index 2c418dbefd7..377e6aa77ad 100644 --- a/crates/noirc_frontend/src/ast/function.rs +++ b/crates/noirc_frontend/src/ast/function.rs @@ -86,6 +86,7 @@ impl From for NoirFunction { Some(Attribute::Test) => FunctionKind::Normal, Some(Attribute::Oracle(_)) => FunctionKind::Oracle, Some(Attribute::Deprecated(_)) | None => FunctionKind::Normal, + Some(Attribute::Custom(_)) => FunctionKind::Normal, }; NoirFunction { def: fd, kind } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 3ef1d2a5dde..cb75c681e8e 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -326,6 +326,7 @@ pub enum Attribute { Oracle(String), Deprecated(Option), Test, + Custom(String), } impl fmt::Display for Attribute { @@ -337,6 +338,7 @@ impl fmt::Display for Attribute { Attribute::Test => write!(f, "#[test]"), Attribute::Deprecated(None) => write!(f, "#[deprecated]"), Attribute::Deprecated(Some(ref note)) => write!(f, r#"#[deprecated("{note}")]"#), + Attribute::Custom(ref k) => write!(f, "#[{k}]"), } } } @@ -390,6 +392,10 @@ impl Attribute { Attribute::Deprecated(name.trim_matches('"').to_string().into()) } ["test"] => Attribute::Test, + [name] => { + validate(name)?; + Attribute::Custom(name.to_string()) + } _ => { return Err(LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }) } @@ -429,6 +435,7 @@ impl AsRef for Attribute { Attribute::Oracle(string) => string, Attribute::Deprecated(Some(string)) => string, Attribute::Test | Attribute::Deprecated(None) => "", + Attribute::Custom(string) => string, } } } From 567812e4ca6ea13381fb514f3b8e4f10a7532b24 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:56:14 +0000 Subject: [PATCH 02/21] test: add lexer test --- crates/noirc_frontend/src/lexer/lexer.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/noirc_frontend/src/lexer/lexer.rs b/crates/noirc_frontend/src/lexer/lexer.rs index 8a98d5bfa3c..12f9a50ef12 100644 --- a/crates/noirc_frontend/src/lexer/lexer.rs +++ b/crates/noirc_frontend/src/lexer/lexer.rs @@ -453,6 +453,15 @@ fn deprecated_attribute_with_note() { assert_eq!(token.token(), &Token::Attribute(Attribute::Deprecated("hello".to_string().into()))); } +#[test] +fn custom_attribute() { + let input = r#"#[custom(hello)]"#; + let mut lexer = Lexer::new(input); + + let token = lexer.next().unwrap().unwrap(); + assert_eq!(token.token(), &Token::Attribute(Attribute::Custom("hello".to_string().into()))); +} + #[test] fn test_custom_gate_syntax() { let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; From 90b93b2e671a43038de7391279de94f82d082ba8 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:49:20 +0000 Subject: [PATCH 03/21] fix: update parsing to allow for complex patterns --- crates/noirc_frontend/src/lexer/lexer.rs | 5 ++++- crates/noirc_frontend/src/lexer/token.rs | 9 +++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/noirc_frontend/src/lexer/lexer.rs b/crates/noirc_frontend/src/lexer/lexer.rs index 12f9a50ef12..372b3f3e4d1 100644 --- a/crates/noirc_frontend/src/lexer/lexer.rs +++ b/crates/noirc_frontend/src/lexer/lexer.rs @@ -459,7 +459,10 @@ fn custom_attribute() { let mut lexer = Lexer::new(input); let token = lexer.next().unwrap().unwrap(); - assert_eq!(token.token(), &Token::Attribute(Attribute::Custom("hello".to_string().into()))); + assert_eq!( + token.token(), + &Token::Attribute(Attribute::Custom("custom__hello".to_string().into())) + ); } #[test] diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index cb75c681e8e..c4afa74b116 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -392,12 +392,9 @@ impl Attribute { Attribute::Deprecated(name.trim_matches('"').to_string().into()) } ["test"] => Attribute::Test, - [name] => { - validate(name)?; - Attribute::Custom(name.to_string()) - } - _ => { - return Err(LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }) + tokens => { + tokens.iter().try_for_each(|token| validate(token))?; + Attribute::Custom(tokens.join("__").to_string()) } }; From 8d0dabf51491c3787d39ed1faac2dfc55ac3801c Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 11:51:04 +0000 Subject: [PATCH 04/21] chore: lint --- crates/noirc_frontend/src/lexer/token.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index c4afa74b116..f5a72a2feee 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -394,7 +394,7 @@ impl Attribute { ["test"] => Attribute::Test, tokens => { tokens.iter().try_for_each(|token| validate(token))?; - Attribute::Custom(tokens.join("__").to_string()) + Attribute::Custom(tokens.join("__")) } }; From fe0d533b6ea65334d0bbef32def52918fc05c8eb Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:21:27 +0000 Subject: [PATCH 05/21] fix: no transformation --- crates/noirc_frontend/src/lexer/lexer.rs | 2 +- crates/noirc_frontend/src/lexer/token.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/noirc_frontend/src/lexer/lexer.rs b/crates/noirc_frontend/src/lexer/lexer.rs index 372b3f3e4d1..d0fa475426a 100644 --- a/crates/noirc_frontend/src/lexer/lexer.rs +++ b/crates/noirc_frontend/src/lexer/lexer.rs @@ -461,7 +461,7 @@ fn custom_attribute() { let token = lexer.next().unwrap().unwrap(); assert_eq!( token.token(), - &Token::Attribute(Attribute::Custom("custom__hello".to_string().into())) + &Token::Attribute(Attribute::Custom("custom(hello)".to_string().into())) ); } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index f5a72a2feee..6291ac4de12 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -394,7 +394,7 @@ impl Attribute { ["test"] => Attribute::Test, tokens => { tokens.iter().try_for_each(|token| validate(token))?; - Attribute::Custom(tokens.join("__")) + Attribute::Custom(word.to_owned()) } }; From 651d42ee2bcca0575f0ad7de56a787c04c98aa33 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 12 Aug 2023 19:29:42 +0000 Subject: [PATCH 06/21] feat: hacky aztec private macro --- crates/noirc_driver/src/lib.rs | 3 + crates/noirc_frontend/src/ast/function.rs | 4 + .../src/hir/def_map/aztec_helper.rs | 317 ++++++++++++++++++ crates/noirc_frontend/src/hir/def_map/mod.rs | 11 +- .../src/hir/resolution/resolver.rs | 7 + crates/noirc_frontend/src/hir_def/function.rs | 4 +- crates/noirc_frontend/src/lexer/token.rs | 61 ++++ .../src/monomorphization/mod.rs | 13 + t/Nargo.toml | 9 + t/Prover.toml | 2 + t/src/main.nr | 35 ++ t/src/storage.nr | 26 ++ 12 files changed, 489 insertions(+), 3 deletions(-) create mode 100644 crates/noirc_frontend/src/hir/def_map/aztec_helper.rs create mode 100644 t/Nargo.toml create mode 100644 t/Prover.toml create mode 100644 t/src/main.nr create mode 100644 t/src/storage.nr diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 1192416b98f..5cc7409a670 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -113,6 +113,9 @@ pub fn check_crate( // You can add any crate type to the crate graph // but you cannot depend on Binaries let std_crate = context.crate_graph.add_stdlib(root_file_id); + + // Maybe this is a nice solution eventually + // let aztec_crate = context.crate_graph.add_stdlib(root_file_id); propagate_dep(context, std_crate, &std_crate_name.parse().unwrap()); let mut errors = vec![]; diff --git a/crates/noirc_frontend/src/ast/function.rs b/crates/noirc_frontend/src/ast/function.rs index 377e6aa77ad..693c28ef71a 100644 --- a/crates/noirc_frontend/src/ast/function.rs +++ b/crates/noirc_frontend/src/ast/function.rs @@ -24,6 +24,9 @@ pub enum FunctionKind { Builtin, Normal, Oracle, + + // TODO: not sure i like this being in the function kind, i just want this to be a macro + Aztec, } impl NoirFunction { @@ -85,6 +88,7 @@ impl From for NoirFunction { Some(Attribute::Foreign(_)) => FunctionKind::LowLevel, Some(Attribute::Test) => FunctionKind::Normal, Some(Attribute::Oracle(_)) => FunctionKind::Oracle, + Some(Attribute::Aztec(_)) => FunctionKind::Aztec, Some(Attribute::Deprecated(_)) | None => FunctionKind::Normal, Some(Attribute::Custom(_)) => FunctionKind::Normal, }; diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs new file mode 100644 index 00000000000..35bcbd9163e --- /dev/null +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -0,0 +1,317 @@ +use noirc_errors::Span; + +use crate::{ + hir_def::{function::Parameters, stmt::HirPattern}, + token::{Attribute, AztecAttribute}, + CallExpression, Expression, ExpressionKind, FunctionKind, Ident, LetStatement, + MethodCallExpression, NoirFunction, ParsedModule, Pattern, Statement, UnresolvedType, +}; + +pub fn aztec_contracts_macros(ast: &mut ParsedModule) { + // Usage -> mut ast -> AztecLib.transform(&mut ast) + + // TODO: rm + // loop over all of the functions and print their attributes, to check what attributes look like and if they + // can be added at will + // NOTE: only one attribute can be applied per function at the moment + + // Also do this for each submodule + for func in ast.functions.iter_mut() { + transform_function(func); + } + // Also for each submodule + for submodule in ast.submodules.iter_mut() { + for func in submodule.contents.functions.iter_mut() { + transform_function(func); + } + } +} + +fn transform_function(func: &mut NoirFunction) { + // if func.kind == FunctionKind::Aztec { + // println!("found aztec attribute"); + // } + // TODO: this will need to be added to a later codegen pass + // Write some code to get the aztec attribute out of the attribute type + let aztec_attribute = func.def.attribute.as_ref().and_then(|attr| { + if let Attribute::Aztec(aztec) = attr { + Some(aztec) + } else { + None + } + }); + if aztec_attribute.is_some() { + dbg!(&aztec_attribute); + let t = aztec_attribute.unwrap(); + match t { + AztecAttribute::Private => { + // Edit the ast to inject the private context into the function + // TODO: clean + + // Create the context using the current params + let create_context = create_private_context(&func.def.parameters); + // Insert the context creation as the first action + func.def.body.0.insert(0, create_context); + + // Add the inputs to the params + let private_input = create_private_inputs(); + func.def.parameters.insert(0, private_input); + + // Push the finish method call to the end of the function + let finish_def = create_context_finish(); + // dbg!(&finish_def); + func.def.body.0.push(finish_def); + + let return_type = create_private_return_type(); + func.def.return_type = return_type; + func.def.return_visibility = noirc_abi::AbiVisibility::Public; + func.def.return_distinctness = noirc_abi::AbiDistinctness::Distinct; + } + AztecAttribute::Public => {} + } + dbg!(&func); + } +} + +/// Helper function that returns what the private context would look like in the ast +/// This should make it available to be consumed within aztec private annotated functions. +pub fn create_private_inputs() -> (Pattern, UnresolvedType, noirc_abi::AbiVisibility) { + let context_ident = Ident::new("inputs".to_string(), Span::default()); + let context_patt = Pattern::Identifier(context_ident); + let context_type_ident = Ident::new("PrivateContextInputs".to_string(), Span::default()); + let context_type = UnresolvedType::Named(crate::Path::from_ident(context_type_ident), vec![]); + let visibility = noirc_abi::AbiVisibility::Private; + + (context_patt, context_type, visibility) +} + +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object +pub fn create_private_context( + params: &Vec<(Pattern, UnresolvedType, noirc_abi::AbiVisibility)>, +) -> Statement { + let hash_args = create_hash_args(params); + + let context_ident = Ident::new("context".to_string(), Span::default()); + let context_patt = Pattern::Identifier(context_ident); + let context_mut = Pattern::Mutable(Box::new(context_patt.clone()), Span::default()); + let context_type_ident = Ident::new("PrivateContext".to_string(), Span::default()); + let mut context_path = crate::Path::from_ident(context_type_ident); + let context_type = UnresolvedType::Named(context_path.clone(), vec![]); + let visibility = noirc_abi::AbiVisibility::Private; + + // Create the new context + context_path.segments.push(Ident::new("new".to_string(), Span::default())); + + let inputs_expression = Expression::new( + ExpressionKind::Variable(crate::Path::from_ident(Ident::new( + "inputs".to_string(), + Span::default(), + ))), + Span::default(), + ); + let hash_call = Expression::new(ExpressionKind::Call(Box::new(hash_args)), Span::default()); + let new_context_args = vec![inputs_expression, hash_call]; + + // Call the init of the context + let expression = Expression::new( + ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(Expression::new( + ExpressionKind::Variable(context_path), + Span::default(), + )), + arguments: new_context_args, + })), + Span::default(), + ); + + let let_expression = LetStatement { pattern: context_mut, r#type: context_type, expression }; + Statement::Let(let_expression) +} + +fn create_hash_args( + params: &Vec<(Pattern, UnresolvedType, noirc_abi::AbiVisibility)>, +) -> CallExpression { + let mut hash_path = crate::Path::from_ident(Ident::new("abi".to_string(), Span::default())); + hash_path.segments.push(Ident::new("hash_args".to_string(), Span::default())); + + let param_expressions = params + .iter() + .map(|param| { + let param_pattern = ¶m.0; + match param_pattern { + Pattern::Identifier(ident) => Expression::new( + ExpressionKind::Variable(crate::Path::from_ident(ident.clone())), + Span::default(), + ), + _ => todo!(), + } + }) + .collect::>(); + + let args_array = Expression::new( + ExpressionKind::Literal(crate::Literal::Array(crate::ArrayLiteral::Standard( + param_expressions.clone(), + ))), + Span::default(), + ); + + let call_args = vec![args_array]; + + let call_expression = CallExpression { + func: Box::new(Expression::new(ExpressionKind::Variable(hash_path), Span::default())), + arguments: call_args, + }; + return call_expression; +} + +pub fn create_private_return_type() -> UnresolvedType { + let return_ident_base = Ident::new("abi".to_string(), Span::default()); + let return_ident = Ident::new("PrivateCircuitPublicInputs".to_string(), Span::default()); + let mut return_path = crate::Path::from_ident(return_ident_base); + return_path.segments.push(return_ident); + + UnresolvedType::Named(return_path, vec![]) +} + +pub fn create_context_finish() -> Statement { + let context_ident = Ident::new("context".to_string(), Span::default()); + let method_call_expression = MethodCallExpression { + object: Expression::new( + ExpressionKind::Variable(crate::Path::from_ident(context_ident)), + Span::default(), + ), + method_name: Ident::new("finish".to_string(), Span::default()), + arguments: vec![], + }; + let method_call = ExpressionKind::MethodCall(Box::new(method_call_expression)); + + let expression = Expression::new(method_call, Span::default()); + Statement::Expression(expression) +} + +// Expression( +// Expression { +// kind: MethodCall( +// MethodCallExpression { +// object: Expression { +// kind: Variable( +// Path { +// segments: [ +// Ident( +// Spanned { +// contents: "context", +// span: Span( +// Span { +// start: ByteIndex(248), +// end: ByteIndex(254), +// }, +// ), +// }, +// ), +// ], +// kind: Plain, +// }, +// ), +// span: Span( +// Span { +// start: ByteIndex(248), +// end: ByteIndex(254), +// }, +// ), +// }, +// method_name: Ident( +// Spanned { +// contents: "finish", +// span: Span( +// Span { +// start: ByteIndex(256), +// end: ByteIndex(261), +// }, +// ), +// }, +// ), +// arguments: [], +// }, +// ), +// span: Span( +// Span { +// start: ByteIndex(248), +// end: ByteIndex(263), +// }, +// ), +// }, +// ), + +// Let( +// LetStatement { +// pattern: Identifier( +// Ident( +// Spanned { +// contents: "_x", +// span: Span( +// Span { +// start: ByteIndex(215), +// end: ByteIndex(216), +// }, +// ), +// }, +// ), +// ), +// type: Unspecified, +// expression: Expression { +// kind: MethodCall( +// MethodCallExpression { +// object: Expression { +// kind: Variable( +// Path { +// segments: [ +// Ident( +// Spanned { +// contents: "context", +// span: Span( +// Span { +// start: ByteIndex(220), +// end: ByteIndex(226), +// }, +// ), +// }, +// ), +// ], +// kind: Plain, +// }, +// ), +// span: Span( +// Span { +// start: ByteIndex(220), +// end: ByteIndex(226), +// }, +// ), +// }, +// method_name: Ident( +// Spanned { +// contents: "this_address", +// span: Span( +// Span { +// start: ByteIndex(228), +// end: ByteIndex(239), +// }, +// ), +// }, +// ), +// arguments: [], +// }, +// ), +// span: Span( +// Span { +// start: ByteIndex(220), +// end: ByteIndex(241), +// }, +// ), +// }, +// }, +// ), + +/// Helper function that returns what the public context would look like in the ast +/// This should make it available to be consumed within aztec public annotated functions. +pub fn create_public_context() {} diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 2dc8c5ec96f..73094bd0fc0 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -3,7 +3,8 @@ use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir::Context; use crate::node_interner::{FuncId, NodeInterner}; use crate::parser::{parse_program, ParsedModule}; -use crate::token::Attribute; +use crate::token::{Attribute, AztecAttribute}; +use crate::FunctionKind; use arena::{Arena, Index}; use fm::{FileId, FileManager}; use noirc_errors::{FileDiagnostic, Location}; @@ -18,6 +19,10 @@ pub use module_data::*; mod namespace; pub use namespace::*; +// TODO: transient +mod aztec_helper; +pub use aztec_helper::*; + /// The name that is used for a non-contract program's entry-point function. pub const MAIN_FUNCTION: &str = "main"; @@ -83,7 +88,9 @@ impl CrateDefMap { // First parse the root file. let root_file_id = context.crate_graph[crate_id].root_file_id; - let ast = parse_file(&mut context.file_manager, root_file_id, errors); + let mut ast = parse_file(&mut context.file_manager, root_file_id, errors); + + aztec_contracts_macros(&mut ast); // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index 6ce06d4a1ae..47eb566167b 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -323,6 +323,13 @@ impl<'a> Resolver<'a> { self.interner.push_expr_location(expr_id, func.def.span, self.file); HirFunction::unchecked_from_expr(expr_id) } + // TODO: this is messy, ideally we need to remove this from the function type, it just needs to be annotated to + // do some more codegen + FunctionKind::Aztec => { + let expr_id = self.intern_block(func.def.body); + self.interner.push_expr_location(expr_id, func.def.span, self.file); + HirFunction::unchecked_from_expr(expr_id) + } }; (hir_func, func_meta) diff --git a/crates/noirc_frontend/src/hir_def/function.rs b/crates/noirc_frontend/src/hir_def/function.rs index 5ef2e89d81f..4f9aad81c12 100644 --- a/crates/noirc_frontend/src/hir_def/function.rs +++ b/crates/noirc_frontend/src/hir_def/function.rs @@ -4,6 +4,7 @@ use noirc_errors::{Location, Span}; use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use crate::hir::def_map::ModuleId; +use crate::monomorphization::ast::Function; use crate::node_interner::{ExprId, NodeInterner}; use crate::{token::Attribute, FunctionKind}; use crate::{ContractFunctionType, Distinctness, FunctionReturnType, Type, Visibility}; @@ -140,7 +141,8 @@ impl FuncMeta { pub fn can_ignore_return_type(&self) -> bool { match self.kind { FunctionKind::LowLevel | FunctionKind::Builtin | FunctionKind::Oracle => true, - FunctionKind::Normal => false, + // TODO: double check + FunctionKind::Normal | FunctionKind::Aztec => false, } } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 6291ac4de12..6d25d7fbddd 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -324,17 +324,34 @@ pub enum Attribute { Foreign(String), Builtin(String), Oracle(String), + Aztec(AztecAttribute), Deprecated(Option), Test, Custom(String), } +#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +pub enum AztecAttribute { + Private, + Public, +} + +impl fmt::Display for AztecAttribute { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + AztecAttribute::Private => write!(f, "#[private]"), + AztecAttribute::Public => write!(f, "#[public]"), + } + } +} + impl fmt::Display for Attribute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Attribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), Attribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), Attribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), + Attribute::Aztec(ref k) => write!(f, "#[oracle({k})]"), Attribute::Test => write!(f, "#[test]"), Attribute::Deprecated(None) => write!(f, "#[deprecated]"), Attribute::Deprecated(Some(ref note)) => write!(f, r#"#[deprecated("{note}")]"#), @@ -380,6 +397,23 @@ impl Attribute { validate(name)?; Attribute::Oracle(name.to_string()) } + // TODO: this should then trigger the aztec sub classifier + ["aztec", name] => { + validate(name)?; + // TODO: more idiomatic way to do this; + let aztec_type = match *name { + "private" => AztecAttribute::Private, + "public" => AztecAttribute::Public, + _ => { + // TODO: cleanup + return Err(LexerErrorKind::MalformedFuncAttribute { + span, + found: word.to_owned(), + }); + } + }; + Attribute::Aztec(aztec_type) + } ["deprecated"] => Attribute::Deprecated(None), ["deprecated", name] => { if !name.starts_with('"') && !name.ends_with('"') { @@ -415,21 +449,48 @@ impl Attribute { } } + pub fn aztec(self) -> Option { + match self { + Attribute::Aztec(a_type) => match a_type { + AztecAttribute::Private => Some("private".to_owned()), + AztecAttribute::Public => Some("public".to_owned()), + }, + _ => None, + } + } + pub fn is_foreign(&self) -> bool { matches!(self, Attribute::Foreign(_)) } + // TODO: maybe all of this aztec stuff should be under a feature flag + pub fn is_aztec(&self) -> bool { + matches!(self, Attribute::Aztec(_)) + } + pub fn is_low_level(&self) -> bool { matches!(self, Attribute::Foreign(_) | Attribute::Builtin(_)) } } +// TODO: no idea if this is correct, kinna just vibin wid it +impl AsRef for AztecAttribute { + fn as_ref(&self) -> &str { + match self { + AztecAttribute::Private => "private", + AztecAttribute::Public => "public", + } + } +} + impl AsRef for Attribute { fn as_ref(&self) -> &str { match self { Attribute::Foreign(string) => string, Attribute::Builtin(string) => string, Attribute::Oracle(string) => string, + // TODO: clean + Attribute::Aztec(func_type) => func_type.as_ref(), Attribute::Deprecated(Some(string)) => string, Attribute::Test | Attribute::Deprecated(None) => "", Attribute::Custom(string) => string, diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 0d3297bf8a4..973997735e6 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -157,6 +157,19 @@ impl<'interner> Monomorphizer<'interner> { ); Definition::Builtin(opcode) } + // TODO: This does not fit my mental model, i would expect that we can carry on the normal here and do some funky stuff elsewhere + FunctionKind::Aztec => { + let attribute = meta.attributes.expect("all aztec functions must contain an attribute saying if the function is private or public"); + let opcode = attribute.aztec().expect( + "ice: function marked as aztec, but attribute kind does not match this", + ); + // Not entirely sure what to do with this value when finished + dbg!(opcode); + // NOTE: ive copied the code from a mix of the two definitions here, queuing the function as normal, + // but using the attribute stuff from above. Not sure what this will look like in the finished product. + let id = self.queue_function(id, expr_id, typ); + Definition::Function(id) + } FunctionKind::Normal => { let id = self.queue_function(id, expr_id, typ); Definition::Function(id) diff --git a/t/Nargo.toml b/t/Nargo.toml new file mode 100644 index 00000000000..c491f26617e --- /dev/null +++ b/t/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "t" +type = "bin" +authors = [""] +compiler_version = "0.9.0" + +[dependencies] +aztec = { path = "../../../aztec3-packages/yarn-project/noir-libs/noir-aztec/" } +value_note = { path = "../../../aztec3-packages/yarn-project/noir-libs/value-note/" } \ No newline at end of file diff --git a/t/Prover.toml b/t/Prover.toml new file mode 100644 index 00000000000..e0a68175d07 --- /dev/null +++ b/t/Prover.toml @@ -0,0 +1,2 @@ +x = "" +y = "" diff --git a/t/src/main.nr b/t/src/main.nr new file mode 100644 index 00000000000..d2af5ebd896 --- /dev/null +++ b/t/src/main.nr @@ -0,0 +1,35 @@ +mod storage; + + +contract Tets { + use dep::aztec::context::PrivateContext; + use dep::aztec::abi; + use dep::aztec::abi::PrivateCircuitPublicInputs; + use dep::aztec::abi::PrivateContextInputs; + use dep::aztec::log::emit_unencrypted_log; + + use dep::value_note::{ + utils::{send_note, spend_notes}, + }; + use crate::storage::Storage; + + // Constructs the contract and sets `initial_supply` which is fully owned by `owner`. + #[aztec(private)] + fn constructor( + //*********************************/ + initial_supply: Field, + owner: Field + ) -> distinct pub abi::PrivateCircuitPublicInputs { + + let storage = Storage::init(); + + // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. + let owner_balance = storage.balances.at(owner); + if (initial_supply != 0) { + send_note(&mut context, owner_balance, initial_supply, owner); + emit_unencrypted_log(&mut context, "Balance set in constructor"); + } + + } + +} \ No newline at end of file diff --git a/t/src/storage.nr b/t/src/storage.nr new file mode 100644 index 00000000000..52fcd691490 --- /dev/null +++ b/t/src/storage.nr @@ -0,0 +1,26 @@ +use dep::aztec::state_vars::{ + map::Map, + set::Set +}; +use dep::value_note::value_note::{ + ValueNote, + ValueNoteMethods, + VALUE_NOTE_LEN, +}; + +// docs:start:storage-declaration +// highlight-next-line:storage-declaration +struct Storage { + // maps an aztec address to its balance + balances: Map>, +} + +// highlight-next-line:storage-declaration +impl Storage { + fn init() -> Self { + Storage { + balances: Map::new(1, |slot| Set::new(slot, ValueNoteMethods)), + } + } +} +// docs:end:storage-declaration From b024d532cffade13fe15c48c9ac1343a92413bac Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 12:01:09 +0000 Subject: [PATCH 07/21] fix: rebase and remove aztec clutter --- crates/noirc_frontend/src/ast/function.rs | 4 - .../src/hir/def_map/aztec_helper.rs | 181 +++--------------- crates/noirc_frontend/src/hir/def_map/mod.rs | 8 +- .../src/hir/resolution/resolver.rs | 7 - crates/noirc_frontend/src/hir_def/function.rs | 4 +- crates/noirc_frontend/src/lexer/token.rs | 61 ------ .../src/monomorphization/mod.rs | 13 -- 7 files changed, 27 insertions(+), 251 deletions(-) diff --git a/crates/noirc_frontend/src/ast/function.rs b/crates/noirc_frontend/src/ast/function.rs index 693c28ef71a..377e6aa77ad 100644 --- a/crates/noirc_frontend/src/ast/function.rs +++ b/crates/noirc_frontend/src/ast/function.rs @@ -24,9 +24,6 @@ pub enum FunctionKind { Builtin, Normal, Oracle, - - // TODO: not sure i like this being in the function kind, i just want this to be a macro - Aztec, } impl NoirFunction { @@ -88,7 +85,6 @@ impl From for NoirFunction { Some(Attribute::Foreign(_)) => FunctionKind::LowLevel, Some(Attribute::Test) => FunctionKind::Normal, Some(Attribute::Oracle(_)) => FunctionKind::Oracle, - Some(Attribute::Aztec(_)) => FunctionKind::Aztec, Some(Attribute::Deprecated(_)) | None => FunctionKind::Normal, Some(Attribute::Custom(_)) => FunctionKind::Normal, }; diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index 35bcbd9163e..f2792eba10c 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -1,13 +1,12 @@ use noirc_errors::Span; use crate::{ - hir_def::{function::Parameters, stmt::HirPattern}, - token::{Attribute, AztecAttribute}, - CallExpression, Expression, ExpressionKind, FunctionKind, Ident, LetStatement, - MethodCallExpression, NoirFunction, ParsedModule, Pattern, Statement, UnresolvedType, + token::Attribute, CallExpression, Distinctness, Expression, ExpressionKind, FunctionReturnType, + Ident, LetStatement, MethodCallExpression, NoirFunction, ParsedModule, Pattern, Statement, + UnresolvedType, Visibility, }; -pub fn aztec_contracts_macros(ast: &mut ParsedModule) { +pub(crate) fn aztec_contracts_macros(ast: &mut ParsedModule) { // Usage -> mut ast -> AztecLib.transform(&mut ast) // TODO: rm @@ -28,23 +27,10 @@ pub fn aztec_contracts_macros(ast: &mut ParsedModule) { } fn transform_function(func: &mut NoirFunction) { - // if func.kind == FunctionKind::Aztec { - // println!("found aztec attribute"); - // } - // TODO: this will need to be added to a later codegen pass - // Write some code to get the aztec attribute out of the attribute type - let aztec_attribute = func.def.attribute.as_ref().and_then(|attr| { - if let Attribute::Aztec(aztec) = attr { - Some(aztec) - } else { - None - } - }); - if aztec_attribute.is_some() { - dbg!(&aztec_attribute); - let t = aztec_attribute.unwrap(); - match t { - AztecAttribute::Private => { + dbg!(func.def.attribute.as_ref()); + if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { + match custom_attribute.as_str() { + "aztec(private)" => { // Edit the ast to inject the private context into the function // TODO: clean @@ -64,10 +50,11 @@ fn transform_function(func: &mut NoirFunction) { let return_type = create_private_return_type(); func.def.return_type = return_type; - func.def.return_visibility = noirc_abi::AbiVisibility::Public; - func.def.return_distinctness = noirc_abi::AbiDistinctness::Distinct; + func.def.return_visibility = Visibility::Public; + func.def.return_distinctness = Distinctness::Distinct; } - AztecAttribute::Public => {} + "aztec(public)" => {} + _ => return, } dbg!(&func); } @@ -75,20 +62,20 @@ fn transform_function(func: &mut NoirFunction) { /// Helper function that returns what the private context would look like in the ast /// This should make it available to be consumed within aztec private annotated functions. -pub fn create_private_inputs() -> (Pattern, UnresolvedType, noirc_abi::AbiVisibility) { +pub(crate) fn create_private_inputs() -> (Pattern, UnresolvedType, Visibility) { let context_ident = Ident::new("inputs".to_string(), Span::default()); let context_patt = Pattern::Identifier(context_ident); let context_type_ident = Ident::new("PrivateContextInputs".to_string(), Span::default()); let context_type = UnresolvedType::Named(crate::Path::from_ident(context_type_ident), vec![]); - let visibility = noirc_abi::AbiVisibility::Private; + let visibility = Visibility::Private; (context_patt, context_type, visibility) } /// Creates the private context object to be accessed within the function, the parameters need to be extracted to be /// appended into the args hash object -pub fn create_private_context( - params: &Vec<(Pattern, UnresolvedType, noirc_abi::AbiVisibility)>, +pub(crate) fn create_private_context( + params: &Vec<(Pattern, UnresolvedType, Visibility)>, ) -> Statement { let hash_args = create_hash_args(params); @@ -98,7 +85,6 @@ pub fn create_private_context( let context_type_ident = Ident::new("PrivateContext".to_string(), Span::default()); let mut context_path = crate::Path::from_ident(context_type_ident); let context_type = UnresolvedType::Named(context_path.clone(), vec![]); - let visibility = noirc_abi::AbiVisibility::Private; // Create the new context context_path.segments.push(Ident::new("new".to_string(), Span::default())); @@ -129,9 +115,7 @@ pub fn create_private_context( Statement::Let(let_expression) } -fn create_hash_args( - params: &Vec<(Pattern, UnresolvedType, noirc_abi::AbiVisibility)>, -) -> CallExpression { +fn create_hash_args(params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> CallExpression { let mut hash_path = crate::Path::from_ident(Ident::new("abi".to_string(), Span::default())); hash_path.segments.push(Ident::new("hash_args".to_string(), Span::default())); @@ -165,16 +149,17 @@ fn create_hash_args( return call_expression; } -pub fn create_private_return_type() -> UnresolvedType { +pub(crate) fn create_private_return_type() -> FunctionReturnType { let return_ident_base = Ident::new("abi".to_string(), Span::default()); let return_ident = Ident::new("PrivateCircuitPublicInputs".to_string(), Span::default()); let mut return_path = crate::Path::from_ident(return_ident_base); return_path.segments.push(return_ident); - UnresolvedType::Named(return_path, vec![]) + let ty = UnresolvedType::Named(return_path, vec![]); + FunctionReturnType::Ty(ty, Span::default()) } -pub fn create_context_finish() -> Statement { +pub(crate) fn create_context_finish() -> Statement { let context_ident = Ident::new("context".to_string(), Span::default()); let method_call_expression = MethodCallExpression { object: Expression::new( @@ -190,128 +175,6 @@ pub fn create_context_finish() -> Statement { Statement::Expression(expression) } -// Expression( -// Expression { -// kind: MethodCall( -// MethodCallExpression { -// object: Expression { -// kind: Variable( -// Path { -// segments: [ -// Ident( -// Spanned { -// contents: "context", -// span: Span( -// Span { -// start: ByteIndex(248), -// end: ByteIndex(254), -// }, -// ), -// }, -// ), -// ], -// kind: Plain, -// }, -// ), -// span: Span( -// Span { -// start: ByteIndex(248), -// end: ByteIndex(254), -// }, -// ), -// }, -// method_name: Ident( -// Spanned { -// contents: "finish", -// span: Span( -// Span { -// start: ByteIndex(256), -// end: ByteIndex(261), -// }, -// ), -// }, -// ), -// arguments: [], -// }, -// ), -// span: Span( -// Span { -// start: ByteIndex(248), -// end: ByteIndex(263), -// }, -// ), -// }, -// ), - -// Let( -// LetStatement { -// pattern: Identifier( -// Ident( -// Spanned { -// contents: "_x", -// span: Span( -// Span { -// start: ByteIndex(215), -// end: ByteIndex(216), -// }, -// ), -// }, -// ), -// ), -// type: Unspecified, -// expression: Expression { -// kind: MethodCall( -// MethodCallExpression { -// object: Expression { -// kind: Variable( -// Path { -// segments: [ -// Ident( -// Spanned { -// contents: "context", -// span: Span( -// Span { -// start: ByteIndex(220), -// end: ByteIndex(226), -// }, -// ), -// }, -// ), -// ], -// kind: Plain, -// }, -// ), -// span: Span( -// Span { -// start: ByteIndex(220), -// end: ByteIndex(226), -// }, -// ), -// }, -// method_name: Ident( -// Spanned { -// contents: "this_address", -// span: Span( -// Span { -// start: ByteIndex(228), -// end: ByteIndex(239), -// }, -// ), -// }, -// ), -// arguments: [], -// }, -// ), -// span: Span( -// Span { -// start: ByteIndex(220), -// end: ByteIndex(241), -// }, -// ), -// }, -// }, -// ), - /// Helper function that returns what the public context would look like in the ast /// This should make it available to be consumed within aztec public annotated functions. -pub fn create_public_context() {} +pub(crate) fn create_public_context() {} diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 73094bd0fc0..9c490985254 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -3,8 +3,7 @@ use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir::Context; use crate::node_interner::{FuncId, NodeInterner}; use crate::parser::{parse_program, ParsedModule}; -use crate::token::{Attribute, AztecAttribute}; -use crate::FunctionKind; +use crate::token::Attribute; use arena::{Arena, Index}; use fm::{FileId, FileManager}; use noirc_errors::{FileDiagnostic, Location}; @@ -19,9 +18,9 @@ pub use module_data::*; mod namespace; pub use namespace::*; -// TODO: transient +// TODO: feature_flag mod aztec_helper; -pub use aztec_helper::*; +use aztec_helper::aztec_contracts_macros; /// The name that is used for a non-contract program's entry-point function. pub const MAIN_FUNCTION: &str = "main"; @@ -90,6 +89,7 @@ impl CrateDefMap { let root_file_id = context.crate_graph[crate_id].root_file_id; let mut ast = parse_file(&mut context.file_manager, root_file_id, errors); + // TODO: feature flag aztec_contracts_macros(&mut ast); // Allocate a default Module for the root, giving it a ModuleId diff --git a/crates/noirc_frontend/src/hir/resolution/resolver.rs b/crates/noirc_frontend/src/hir/resolution/resolver.rs index 47eb566167b..6ce06d4a1ae 100644 --- a/crates/noirc_frontend/src/hir/resolution/resolver.rs +++ b/crates/noirc_frontend/src/hir/resolution/resolver.rs @@ -323,13 +323,6 @@ impl<'a> Resolver<'a> { self.interner.push_expr_location(expr_id, func.def.span, self.file); HirFunction::unchecked_from_expr(expr_id) } - // TODO: this is messy, ideally we need to remove this from the function type, it just needs to be annotated to - // do some more codegen - FunctionKind::Aztec => { - let expr_id = self.intern_block(func.def.body); - self.interner.push_expr_location(expr_id, func.def.span, self.file); - HirFunction::unchecked_from_expr(expr_id) - } }; (hir_func, func_meta) diff --git a/crates/noirc_frontend/src/hir_def/function.rs b/crates/noirc_frontend/src/hir_def/function.rs index 4f9aad81c12..5ef2e89d81f 100644 --- a/crates/noirc_frontend/src/hir_def/function.rs +++ b/crates/noirc_frontend/src/hir_def/function.rs @@ -4,7 +4,6 @@ use noirc_errors::{Location, Span}; use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use crate::hir::def_map::ModuleId; -use crate::monomorphization::ast::Function; use crate::node_interner::{ExprId, NodeInterner}; use crate::{token::Attribute, FunctionKind}; use crate::{ContractFunctionType, Distinctness, FunctionReturnType, Type, Visibility}; @@ -141,8 +140,7 @@ impl FuncMeta { pub fn can_ignore_return_type(&self) -> bool { match self.kind { FunctionKind::LowLevel | FunctionKind::Builtin | FunctionKind::Oracle => true, - // TODO: double check - FunctionKind::Normal | FunctionKind::Aztec => false, + FunctionKind::Normal => false, } } diff --git a/crates/noirc_frontend/src/lexer/token.rs b/crates/noirc_frontend/src/lexer/token.rs index 6d25d7fbddd..6291ac4de12 100644 --- a/crates/noirc_frontend/src/lexer/token.rs +++ b/crates/noirc_frontend/src/lexer/token.rs @@ -324,34 +324,17 @@ pub enum Attribute { Foreign(String), Builtin(String), Oracle(String), - Aztec(AztecAttribute), Deprecated(Option), Test, Custom(String), } -#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] -pub enum AztecAttribute { - Private, - Public, -} - -impl fmt::Display for AztecAttribute { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - AztecAttribute::Private => write!(f, "#[private]"), - AztecAttribute::Public => write!(f, "#[public]"), - } - } -} - impl fmt::Display for Attribute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Attribute::Foreign(ref k) => write!(f, "#[foreign({k})]"), Attribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), Attribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), - Attribute::Aztec(ref k) => write!(f, "#[oracle({k})]"), Attribute::Test => write!(f, "#[test]"), Attribute::Deprecated(None) => write!(f, "#[deprecated]"), Attribute::Deprecated(Some(ref note)) => write!(f, r#"#[deprecated("{note}")]"#), @@ -397,23 +380,6 @@ impl Attribute { validate(name)?; Attribute::Oracle(name.to_string()) } - // TODO: this should then trigger the aztec sub classifier - ["aztec", name] => { - validate(name)?; - // TODO: more idiomatic way to do this; - let aztec_type = match *name { - "private" => AztecAttribute::Private, - "public" => AztecAttribute::Public, - _ => { - // TODO: cleanup - return Err(LexerErrorKind::MalformedFuncAttribute { - span, - found: word.to_owned(), - }); - } - }; - Attribute::Aztec(aztec_type) - } ["deprecated"] => Attribute::Deprecated(None), ["deprecated", name] => { if !name.starts_with('"') && !name.ends_with('"') { @@ -449,48 +415,21 @@ impl Attribute { } } - pub fn aztec(self) -> Option { - match self { - Attribute::Aztec(a_type) => match a_type { - AztecAttribute::Private => Some("private".to_owned()), - AztecAttribute::Public => Some("public".to_owned()), - }, - _ => None, - } - } - pub fn is_foreign(&self) -> bool { matches!(self, Attribute::Foreign(_)) } - // TODO: maybe all of this aztec stuff should be under a feature flag - pub fn is_aztec(&self) -> bool { - matches!(self, Attribute::Aztec(_)) - } - pub fn is_low_level(&self) -> bool { matches!(self, Attribute::Foreign(_) | Attribute::Builtin(_)) } } -// TODO: no idea if this is correct, kinna just vibin wid it -impl AsRef for AztecAttribute { - fn as_ref(&self) -> &str { - match self { - AztecAttribute::Private => "private", - AztecAttribute::Public => "public", - } - } -} - impl AsRef for Attribute { fn as_ref(&self) -> &str { match self { Attribute::Foreign(string) => string, Attribute::Builtin(string) => string, Attribute::Oracle(string) => string, - // TODO: clean - Attribute::Aztec(func_type) => func_type.as_ref(), Attribute::Deprecated(Some(string)) => string, Attribute::Test | Attribute::Deprecated(None) => "", Attribute::Custom(string) => string, diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 973997735e6..0d3297bf8a4 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -157,19 +157,6 @@ impl<'interner> Monomorphizer<'interner> { ); Definition::Builtin(opcode) } - // TODO: This does not fit my mental model, i would expect that we can carry on the normal here and do some funky stuff elsewhere - FunctionKind::Aztec => { - let attribute = meta.attributes.expect("all aztec functions must contain an attribute saying if the function is private or public"); - let opcode = attribute.aztec().expect( - "ice: function marked as aztec, but attribute kind does not match this", - ); - // Not entirely sure what to do with this value when finished - dbg!(opcode); - // NOTE: ive copied the code from a mix of the two definitions here, queuing the function as normal, - // but using the attribute stuff from above. Not sure what this will look like in the finished product. - let id = self.queue_function(id, expr_id, typ); - Definition::Function(id) - } FunctionKind::Normal => { let id = self.queue_function(id, expr_id, typ); Definition::Function(id) From 2407dcb8cdbd7f9b9deb59db0ea852bb01e8399d Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 16:40:58 +0000 Subject: [PATCH 08/21] feat: cast hash vars to field --- crates/nargo_cli/Cargo.toml | 1 + .../src/hir/def_map/aztec_helper.rs | 72 ++++++++++++------- crates/noirc_frontend/src/hir/def_map/mod.rs | 14 ++-- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/crates/nargo_cli/Cargo.toml b/crates/nargo_cli/Cargo.toml index af5240aecbf..efe40a3cff5 100644 --- a/crates/nargo_cli/Cargo.toml +++ b/crates/nargo_cli/Cargo.toml @@ -79,3 +79,4 @@ default = ["plonk_bn254"] # The plonk backend can only use bn254, so we do not specify the field plonk_bn254 = ["acvm-backend-barretenberg/native"] plonk_bn254_wasm = ["acvm-backend-barretenberg/wasm"] +aztec = [] diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index f2792eba10c..7293584fa8b 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -14,11 +14,10 @@ pub(crate) fn aztec_contracts_macros(ast: &mut ParsedModule) { // can be added at will // NOTE: only one attribute can be applied per function at the moment - // Also do this for each submodule + // This should cover all functions in the ast for func in ast.functions.iter_mut() { transform_function(func); } - // Also for each submodule for submodule in ast.submodules.iter_mut() { for func in submodule.contents.functions.iter_mut() { transform_function(func); @@ -27,20 +26,19 @@ pub(crate) fn aztec_contracts_macros(ast: &mut ParsedModule) { } fn transform_function(func: &mut NoirFunction) { - dbg!(func.def.attribute.as_ref()); if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { + // TODO: this can just become the one function!!! + // match based on the custom attribute match custom_attribute.as_str() { "aztec(private)" => { // Edit the ast to inject the private context into the function - // TODO: clean - // Create the context using the current params - let create_context = create_private_context(&func.def.parameters); + let create_context = create_context("PrivateContext", &func.def.parameters); // Insert the context creation as the first action func.def.body.0.insert(0, create_context); // Add the inputs to the params - let private_input = create_private_inputs(); + let private_input = create_inputs("PrivateContextInputs"); func.def.parameters.insert(0, private_input); // Push the finish method call to the end of the function @@ -48,12 +46,30 @@ fn transform_function(func: &mut NoirFunction) { // dbg!(&finish_def); func.def.body.0.push(finish_def); - let return_type = create_private_return_type(); + let return_type = create_return_type("PrivateCircuitPublicInputs"); func.def.return_type = return_type; func.def.return_visibility = Visibility::Public; func.def.return_distinctness = Distinctness::Distinct; } - "aztec(public)" => {} + "aztec(public)" => { + let create_context = create_context("PublicContext", &func.def.parameters); + // Insert the context creation as the first action + func.def.body.0.insert(0, create_context); + + // Add the inputs to the params + let private_input = create_inputs("PublicContextInputs"); + func.def.parameters.insert(0, private_input); + + // Push the finish method call to the end of the function + let finish_def = create_context_finish(); + // dbg!(&finish_def); + func.def.body.0.push(finish_def); + + let return_type = create_return_type("PublicCircuitPublicInputs"); + func.def.return_type = return_type; + func.def.return_visibility = Visibility::Public; + // func.def.return_distinctness = Distinctness::Distinct; + } _ => return, } dbg!(&func); @@ -62,19 +78,18 @@ fn transform_function(func: &mut NoirFunction) { /// Helper function that returns what the private context would look like in the ast /// This should make it available to be consumed within aztec private annotated functions. -pub(crate) fn create_private_inputs() -> (Pattern, UnresolvedType, Visibility) { +pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { let context_ident = Ident::new("inputs".to_string(), Span::default()); let context_patt = Pattern::Identifier(context_ident); - let context_type_ident = Ident::new("PrivateContextInputs".to_string(), Span::default()); + let context_type_ident = Ident::new(ty.to_string(), Span::default()); let context_type = UnresolvedType::Named(crate::Path::from_ident(context_type_ident), vec![]); let visibility = Visibility::Private; (context_patt, context_type, visibility) } -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object -pub(crate) fn create_private_context( +pub(crate) fn create_context( + ty: &str, // type params: &Vec<(Pattern, UnresolvedType, Visibility)>, ) -> Statement { let hash_args = create_hash_args(params); @@ -82,7 +97,7 @@ pub(crate) fn create_private_context( let context_ident = Ident::new("context".to_string(), Span::default()); let context_patt = Pattern::Identifier(context_ident); let context_mut = Pattern::Mutable(Box::new(context_patt.clone()), Span::default()); - let context_type_ident = Ident::new("PrivateContext".to_string(), Span::default()); + let context_type_ident = Ident::new(ty.to_string(), Span::default()); let mut context_path = crate::Path::from_ident(context_type_ident); let context_type = UnresolvedType::Named(context_path.clone(), vec![]); @@ -115,6 +130,8 @@ pub(crate) fn create_private_context( Statement::Let(let_expression) } +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object fn create_hash_args(params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> CallExpression { let mut hash_path = crate::Path::from_ident(Ident::new("abi".to_string(), Span::default())); hash_path.segments.push(Ident::new("hash_args".to_string(), Span::default())); @@ -124,10 +141,19 @@ fn create_hash_args(params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Call .map(|param| { let param_pattern = ¶m.0; match param_pattern { - Pattern::Identifier(ident) => Expression::new( - ExpressionKind::Variable(crate::Path::from_ident(ident.clone())), - Span::default(), - ), + Pattern::Identifier(ident) => { + // Converts each type to a Field Element before hashing + let variable = Expression::new( + ExpressionKind::Variable(crate::Path::from_ident(ident.clone())), + Span::default(), + ); + let cast_expression = ExpressionKind::Cast(Box::new(crate::CastExpression { + lhs: variable, + r#type: UnresolvedType::FieldElement, + })); + + Expression::new(cast_expression, Span::default()) + } _ => todo!(), } }) @@ -149,9 +175,9 @@ fn create_hash_args(params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Call return call_expression; } -pub(crate) fn create_private_return_type() -> FunctionReturnType { +pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { let return_ident_base = Ident::new("abi".to_string(), Span::default()); - let return_ident = Ident::new("PrivateCircuitPublicInputs".to_string(), Span::default()); + let return_ident = Ident::new(ty.to_string(), Span::default()); let mut return_path = crate::Path::from_ident(return_ident_base); return_path.segments.push(return_ident); @@ -174,7 +200,3 @@ pub(crate) fn create_context_finish() -> Statement { let expression = Expression::new(method_call, Span::default()); Statement::Expression(expression) } - -/// Helper function that returns what the public context would look like in the ast -/// This should make it available to be consumed within aztec public annotated functions. -pub(crate) fn create_public_context() {} diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 9c490985254..8dda9134584 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -18,8 +18,9 @@ pub use module_data::*; mod namespace; pub use namespace::*; -// TODO: feature_flag +#[cfg(feature = "aztec")] mod aztec_helper; +#[cfg(feature = "aztec")] use aztec_helper::aztec_contracts_macros; /// The name that is used for a non-contract program's entry-point function. @@ -87,10 +88,15 @@ impl CrateDefMap { // First parse the root file. let root_file_id = context.crate_graph[crate_id].root_file_id; - let mut ast = parse_file(&mut context.file_manager, root_file_id, errors); - // TODO: feature flag - aztec_contracts_macros(&mut ast); + #[cfg(not(feature = "aztec"))] + let ast = parse_file(&mut context.file_manager, root_file_id, errors); + + #[cfg(feature = "aztec")] + { + let mut ast = parse_file(&mut context.file_manager, root_file_id, errors); + aztec_contracts_macros(&mut ast); + } // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); From fa34ecc05c8632b5dd786bf20a242a4d1c8d4d72 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Aug 2023 16:44:22 +0000 Subject: [PATCH 09/21] remove: test project --- t/Nargo.toml | 9 --------- t/Prover.toml | 2 -- t/src/main.nr | 35 ----------------------------------- t/src/storage.nr | 26 -------------------------- 4 files changed, 72 deletions(-) delete mode 100644 t/Nargo.toml delete mode 100644 t/Prover.toml delete mode 100644 t/src/main.nr delete mode 100644 t/src/storage.nr diff --git a/t/Nargo.toml b/t/Nargo.toml deleted file mode 100644 index c491f26617e..00000000000 --- a/t/Nargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "t" -type = "bin" -authors = [""] -compiler_version = "0.9.0" - -[dependencies] -aztec = { path = "../../../aztec3-packages/yarn-project/noir-libs/noir-aztec/" } -value_note = { path = "../../../aztec3-packages/yarn-project/noir-libs/value-note/" } \ No newline at end of file diff --git a/t/Prover.toml b/t/Prover.toml deleted file mode 100644 index e0a68175d07..00000000000 --- a/t/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "" -y = "" diff --git a/t/src/main.nr b/t/src/main.nr deleted file mode 100644 index d2af5ebd896..00000000000 --- a/t/src/main.nr +++ /dev/null @@ -1,35 +0,0 @@ -mod storage; - - -contract Tets { - use dep::aztec::context::PrivateContext; - use dep::aztec::abi; - use dep::aztec::abi::PrivateCircuitPublicInputs; - use dep::aztec::abi::PrivateContextInputs; - use dep::aztec::log::emit_unencrypted_log; - - use dep::value_note::{ - utils::{send_note, spend_notes}, - }; - use crate::storage::Storage; - - // Constructs the contract and sets `initial_supply` which is fully owned by `owner`. - #[aztec(private)] - fn constructor( - //*********************************/ - initial_supply: Field, - owner: Field - ) -> distinct pub abi::PrivateCircuitPublicInputs { - - let storage = Storage::init(); - - // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call. - let owner_balance = storage.balances.at(owner); - if (initial_supply != 0) { - send_note(&mut context, owner_balance, initial_supply, owner); - emit_unencrypted_log(&mut context, "Balance set in constructor"); - } - - } - -} \ No newline at end of file diff --git a/t/src/storage.nr b/t/src/storage.nr deleted file mode 100644 index 52fcd691490..00000000000 --- a/t/src/storage.nr +++ /dev/null @@ -1,26 +0,0 @@ -use dep::aztec::state_vars::{ - map::Map, - set::Set -}; -use dep::value_note::value_note::{ - ValueNote, - ValueNoteMethods, - VALUE_NOTE_LEN, -}; - -// docs:start:storage-declaration -// highlight-next-line:storage-declaration -struct Storage { - // maps an aztec address to its balance - balances: Map>, -} - -// highlight-next-line:storage-declaration -impl Storage { - fn init() -> Self { - Storage { - balances: Map::new(1, |slot| Set::new(slot, ValueNoteMethods)), - } - } -} -// docs:end:storage-declaration From b84b05ad3bb91c6849c4b8df8f19690e50f7d601 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:24:14 +0000 Subject: [PATCH 10/21] temp --- Cargo.toml | 2 +- crates/nargo_cli/Cargo.toml | 3 +- crates/noirc_driver/src/lib.rs | 3 - crates/noirc_frontend/Cargo.toml | 3 + .../src/hir/def_map/aztec_helper.rs | 86 +++++++++++++------ crates/noirc_frontend/src/hir/def_map/mod.rs | 12 +-- 6 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 76ec9edfa0d..51a9bf97ada 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,4 +56,4 @@ tower = "0.4" url = "2.2.0" wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] } wasm-bindgen-test = "0.3.33" -base64 = "0.21.2" +base64 = "0.21.2" \ No newline at end of file diff --git a/crates/nargo_cli/Cargo.toml b/crates/nargo_cli/Cargo.toml index efe40a3cff5..ef1cbf70621 100644 --- a/crates/nargo_cli/Cargo.toml +++ b/crates/nargo_cli/Cargo.toml @@ -78,5 +78,4 @@ harness = false default = ["plonk_bn254"] # The plonk backend can only use bn254, so we do not specify the field plonk_bn254 = ["acvm-backend-barretenberg/native"] -plonk_bn254_wasm = ["acvm-backend-barretenberg/wasm"] -aztec = [] +plonk_bn254_wasm = ["acvm-backend-barretenberg/wasm"] \ No newline at end of file diff --git a/crates/noirc_driver/src/lib.rs b/crates/noirc_driver/src/lib.rs index 5cc7409a670..1192416b98f 100644 --- a/crates/noirc_driver/src/lib.rs +++ b/crates/noirc_driver/src/lib.rs @@ -113,9 +113,6 @@ pub fn check_crate( // You can add any crate type to the crate graph // but you cannot depend on Binaries let std_crate = context.crate_graph.add_stdlib(root_file_id); - - // Maybe this is a nice solution eventually - // let aztec_crate = context.crate_graph.add_stdlib(root_file_id); propagate_dep(context, std_crate, &std_crate_name.parse().unwrap()); let mut errors = vec![]; diff --git a/crates/noirc_frontend/Cargo.toml b/crates/noirc_frontend/Cargo.toml index c2d6e579c2c..fa3814b9279 100644 --- a/crates/noirc_frontend/Cargo.toml +++ b/crates/noirc_frontend/Cargo.toml @@ -24,3 +24,6 @@ regex = "1.9.1" [dev-dependencies] strum = "0.24" strum_macros = "0.24" + +[features] +aztec = [] \ No newline at end of file diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index 7293584fa8b..592b388eb0a 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -6,26 +6,24 @@ use crate::{ UnresolvedType, Visibility, }; -pub(crate) fn aztec_contracts_macros(ast: &mut ParsedModule) { +pub(crate) fn aztec_contracts_macros(mut ast: ParsedModule) -> ParsedModule { // Usage -> mut ast -> AztecLib.transform(&mut ast) - // TODO: rm - // loop over all of the functions and print their attributes, to check what attributes look like and if they - // can be added at will - // NOTE: only one attribute can be applied per function at the moment - - // This should cover all functions in the ast + let ast_copy = ast.clone(); + // Covers all functions in the ast for func in ast.functions.iter_mut() { - transform_function(func); + transform_function(&ast_copy, func); } for submodule in ast.submodules.iter_mut() { for func in submodule.contents.functions.iter_mut() { - transform_function(func); + transform_function(&ast_copy, func); } } + ast } -fn transform_function(func: &mut NoirFunction) { +// TODO: might be worth making this a struct to prevent passing the ast around +fn transform_function(ast: &ParsedModule, func: &mut NoirFunction) { if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { // TODO: this can just become the one function!!! // match based on the custom attribute @@ -33,17 +31,16 @@ fn transform_function(func: &mut NoirFunction) { "aztec(private)" => { // Edit the ast to inject the private context into the function // Create the context using the current params - let create_context = create_context("PrivateContext", &func.def.parameters); + let create_context = create_context(ast, "PrivateContext", &func.def.parameters); // Insert the context creation as the first action func.def.body.0.insert(0, create_context); // Add the inputs to the params - let private_input = create_inputs("PrivateContextInputs"); - func.def.parameters.insert(0, private_input); + let input = create_inputs("PrivateContextInputs"); + func.def.parameters.insert(0, input); // Push the finish method call to the end of the function let finish_def = create_context_finish(); - // dbg!(&finish_def); func.def.body.0.push(finish_def); let return_type = create_return_type("PrivateCircuitPublicInputs"); @@ -52,17 +49,16 @@ fn transform_function(func: &mut NoirFunction) { func.def.return_distinctness = Distinctness::Distinct; } "aztec(public)" => { - let create_context = create_context("PublicContext", &func.def.parameters); + let create_context = create_context(ast, "PublicContext", &func.def.parameters); // Insert the context creation as the first action func.def.body.0.insert(0, create_context); // Add the inputs to the params - let private_input = create_inputs("PublicContextInputs"); - func.def.parameters.insert(0, private_input); + let input = create_inputs("PublicContextInputs"); + func.def.parameters.insert(0, input); // Push the finish method call to the end of the function let finish_def = create_context_finish(); - // dbg!(&finish_def); func.def.body.0.push(finish_def); let return_type = create_return_type("PublicCircuitPublicInputs"); @@ -72,7 +68,7 @@ fn transform_function(func: &mut NoirFunction) { } _ => return, } - dbg!(&func); + // dbg!(&func); } } @@ -80,23 +76,24 @@ fn transform_function(func: &mut NoirFunction) { /// This should make it available to be consumed within aztec private annotated functions. pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { let context_ident = Ident::new("inputs".to_string(), Span::default()); - let context_patt = Pattern::Identifier(context_ident); + let context_pattern = Pattern::Identifier(context_ident); let context_type_ident = Ident::new(ty.to_string(), Span::default()); let context_type = UnresolvedType::Named(crate::Path::from_ident(context_type_ident), vec![]); let visibility = Visibility::Private; - (context_patt, context_type, visibility) + (context_pattern, context_type, visibility) } pub(crate) fn create_context( + ast: &ParsedModule, ty: &str, // type params: &Vec<(Pattern, UnresolvedType, Visibility)>, ) -> Statement { - let hash_args = create_hash_args(params); + let hash_args = create_hash_args(ast, params); let context_ident = Ident::new("context".to_string(), Span::default()); - let context_patt = Pattern::Identifier(context_ident); - let context_mut = Pattern::Mutable(Box::new(context_patt.clone()), Span::default()); + let context_pattern = Pattern::Identifier(context_ident); + let context_mut = Pattern::Mutable(Box::new(context_pattern.clone()), Span::default()); let context_type_ident = Ident::new(ty.to_string(), Span::default()); let mut context_path = crate::Path::from_ident(context_type_ident); let context_type = UnresolvedType::Named(context_path.clone(), vec![]); @@ -132,16 +129,49 @@ pub(crate) fn create_context( /// Creates the private context object to be accessed within the function, the parameters need to be extracted to be /// appended into the args hash object -fn create_hash_args(params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> CallExpression { +fn create_hash_args( + ast: &ParsedModule, + params: &Vec<(Pattern, UnresolvedType, Visibility)>, +) -> CallExpression { + dbg!(&ast.types); let mut hash_path = crate::Path::from_ident(Ident::new("abi".to_string(), Span::default())); hash_path.segments.push(Ident::new("hash_args".to_string(), Span::default())); let param_expressions = params .iter() - .map(|param| { - let param_pattern = ¶m.0; - match param_pattern { + .map(|(pattern, ty, _vis)| { + match pattern { Pattern::Identifier(ident) => { + dbg!(ident); + dbg!(ty); + + // Match the type to determine the padding to do + match ty { + UnresolvedType::Named(path, unresolved_type) => { + // Find the type definition in the ast + // TODO: look for methods where the type is resolved elsewhere + + let last_index = path.segments.len() - 1; + let last_item = path.segments[last_index].0.contents.clone(); + let type_def = ast + .types + .iter() + .find(|type_def| type_def.name.0.contents == last_item); + let type_def_2 = ast.submodules.iter().map(|submodule| { + submodule + .contents + .types + .iter() + .find(|type_def| type_def.name.0.contents == last_item) + }); + dbg!(type_def); + dbg!(type_def_2); + // dbg!(path); + // dbg!(unresolved_type); + } + _ => println!("todo"), + } + // Converts each type to a Field Element before hashing let variable = Expression::new( ExpressionKind::Variable(crate::Path::from_ident(ident.clone())), diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 8dda9134584..bf5a77bf0fd 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -18,9 +18,9 @@ pub use module_data::*; mod namespace; pub use namespace::*; -#[cfg(feature = "aztec")] +// #[cfg(feature = "aztec")] mod aztec_helper; -#[cfg(feature = "aztec")] +// #[cfg(feature = "aztec")] use aztec_helper::aztec_contracts_macros; /// The name that is used for a non-contract program's entry-point function. @@ -89,14 +89,10 @@ impl CrateDefMap { // First parse the root file. let root_file_id = context.crate_graph[crate_id].root_file_id; - #[cfg(not(feature = "aztec"))] let ast = parse_file(&mut context.file_manager, root_file_id, errors); - #[cfg(feature = "aztec")] - { - let mut ast = parse_file(&mut context.file_manager, root_file_id, errors); - aztec_contracts_macros(&mut ast); - } + // #[cfg(feature = "aztec")] + let ast = aztec_contracts_macros(ast); // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); From 8b5d9a67699660e18c9c55ccec4f357fdee79bff Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:03:57 +0000 Subject: [PATCH 11/21] fix: code cleanup with macros --- .../src/hir/def_map/aztec_helper.rs | 372 +++++++++++------- 1 file changed, 236 insertions(+), 136 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index 592b388eb0a..5189c259d6f 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -1,39 +1,94 @@ +use acvm::FieldElement; use noirc_errors::Span; use crate::{ - token::Attribute, CallExpression, Distinctness, Expression, ExpressionKind, FunctionReturnType, - Ident, LetStatement, MethodCallExpression, NoirFunction, ParsedModule, Pattern, Statement, + token::Attribute, BlockExpression, CallExpression, CastExpression, Distinctness, Expression, + ExpressionKind, ForExpression, FunctionReturnType, Ident, IndexExpression, LetStatement, + Literal, MethodCallExpression, NoirFunction, ParsedModule, Path, Pattern, Statement, UnresolvedType, Visibility, }; +///////////////////////////////////////////////////////////////////////// +/// Helper macros for creating noir ast nodes /// +///////////////////////////////////////////////////////////////////////// +macro_rules! ident { + ($name:expr) => { + Ident::new($name.to_string(), Span::default()) + }; +} + +macro_rules! ident_path { + ($name:expr) => { + Path::from_ident(ident!($name)) + }; +} + +macro_rules! expression { + ($kind:expr) => { + Expression::new($kind, Span::default()) + }; +} + +macro_rules! variable { + ($name:expr) => { + expression!(ExpressionKind::Variable(ident_path!($name))) + }; +} + +macro_rules! variable_path { + ($path:expr) => { + expression!(ExpressionKind::Variable($path)) + }; +} + +macro_rules! method_call { + ($object:expr, $method_name:expr, $arguments:expr) => { + expression!(ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: $object, + method_name: ident!($method_name), + arguments: $arguments, + }))) + }; +} + +macro_rules! call { + ($func:expr, $arguments:expr) => { + expression!(ExpressionKind::Call(Box::new(CallExpression { + func: Box::new($func), + arguments: $arguments, + }))) + }; +} + pub(crate) fn aztec_contracts_macros(mut ast: ParsedModule) -> ParsedModule { // Usage -> mut ast -> AztecLib.transform(&mut ast) - let ast_copy = ast.clone(); // Covers all functions in the ast for func in ast.functions.iter_mut() { - transform_function(&ast_copy, func); + transform_function(func); } for submodule in ast.submodules.iter_mut() { for func in submodule.contents.functions.iter_mut() { - transform_function(&ast_copy, func); + transform_function(func); } } ast } // TODO: might be worth making this a struct to prevent passing the ast around -fn transform_function(ast: &ParsedModule, func: &mut NoirFunction) { +fn transform_function(func: &mut NoirFunction) { if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { // TODO: this can just become the one function!!! // match based on the custom attribute match custom_attribute.as_str() { "aztec(private)" => { + // temp: if the name = entrypoint then print it out + // Edit the ast to inject the private context into the function // Create the context using the current params - let create_context = create_context(ast, "PrivateContext", &func.def.parameters); + let create_context = create_context("PrivateContext", &func.def.parameters); // Insert the context creation as the first action - func.def.body.0.insert(0, create_context); + func.def.body.0.splice(0..0, (&create_context).iter().cloned()); // Add the inputs to the params let input = create_inputs("PrivateContextInputs"); @@ -47,11 +102,15 @@ fn transform_function(ast: &ParsedModule, func: &mut NoirFunction) { func.def.return_type = return_type; func.def.return_visibility = Visibility::Public; func.def.return_distinctness = Distinctness::Distinct; + + if func.name() == "entrypoint" { + // dbg!(&func); + } } "aztec(public)" => { - let create_context = create_context(ast, "PublicContext", &func.def.parameters); + let create_context = create_context("PublicContext", &func.def.parameters); // Insert the context creation as the first action - func.def.body.0.insert(0, create_context); + func.def.body.0.splice(0..0, (&create_context).iter().cloned()); // Add the inputs to the params let input = create_inputs("PublicContextInputs"); @@ -75,140 +134,188 @@ fn transform_function(ast: &ParsedModule, func: &mut NoirFunction) { /// Helper function that returns what the private context would look like in the ast /// This should make it available to be consumed within aztec private annotated functions. pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { - let context_ident = Ident::new("inputs".to_string(), Span::default()); + let context_ident = ident!("inputs"); let context_pattern = Pattern::Identifier(context_ident); - let context_type_ident = Ident::new(ty.to_string(), Span::default()); - let context_type = UnresolvedType::Named(crate::Path::from_ident(context_type_ident), vec![]); + let context_type = UnresolvedType::Named(ident_path!(ty), vec![]); let visibility = Visibility::Private; (context_pattern, context_type, visibility) } -pub(crate) fn create_context( - ast: &ParsedModule, - ty: &str, // type - params: &Vec<(Pattern, UnresolvedType, Visibility)>, -) -> Statement { - let hash_args = create_hash_args(ast, params); +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object +fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Vec { + let mut injected_expressions: Vec = vec![]; - let context_ident = Ident::new("context".to_string(), Span::default()); - let context_pattern = Pattern::Identifier(context_ident); - let context_mut = Pattern::Mutable(Box::new(context_pattern.clone()), Span::default()); - let context_type_ident = Ident::new(ty.to_string(), Span::default()); - let mut context_path = crate::Path::from_ident(context_type_ident); - let context_type = UnresolvedType::Named(context_path.clone(), vec![]); + let mut hash_path = ident_path!("abi"); + hash_path.segments.push(ident!("hash_args")); - // Create the new context - context_path.segments.push(Ident::new("new".to_string(), Span::default())); - - let inputs_expression = Expression::new( - ExpressionKind::Variable(crate::Path::from_ident(Ident::new( - "inputs".to_string(), - Span::default(), - ))), - Span::default(), - ); - let hash_call = Expression::new(ExpressionKind::Call(Box::new(hash_args)), Span::default()); - let new_context_args = vec![inputs_expression, hash_call]; + // Create hasher structure + let mut hasher_path = ident_path!("abi"); + hasher_path.segments.push(ident!("Hasher")); - // Call the init of the context - let expression = Expression::new( - ExpressionKind::Call(Box::new(CallExpression { - func: Box::new(Expression::new( - ExpressionKind::Variable(context_path), - Span::default(), - )), - arguments: new_context_args, - })), - Span::default(), - ); + // Assign the hasher to a variable + let hasher_ident = ident!("hasher"); + let hasher_pattern = Pattern::Identifier(hasher_ident.clone()); + let hasher_mut = Pattern::Mutable(Box::new(hasher_pattern.clone()), Span::default()); + let mut hasher_path = ident_path!("Hasher"); + let context_type = UnresolvedType::Named(hasher_path.clone(), vec![]); - let let_expression = LetStatement { pattern: context_mut, r#type: context_type, expression }; - Statement::Let(let_expression) -} + // Create the new hasher + hasher_path.segments.push(ident!("new")); -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object -fn create_hash_args( - ast: &ParsedModule, - params: &Vec<(Pattern, UnresolvedType, Visibility)>, -) -> CallExpression { - dbg!(&ast.types); - let mut hash_path = crate::Path::from_ident(Ident::new("abi".to_string(), Span::default())); - hash_path.segments.push(Ident::new("hash_args".to_string(), Span::default())); - - let param_expressions = params - .iter() - .map(|(pattern, ty, _vis)| { - match pattern { - Pattern::Identifier(ident) => { - dbg!(ident); - dbg!(ty); - - // Match the type to determine the padding to do - match ty { - UnresolvedType::Named(path, unresolved_type) => { - // Find the type definition in the ast - // TODO: look for methods where the type is resolved elsewhere - - let last_index = path.segments.len() - 1; - let last_item = path.segments[last_index].0.contents.clone(); - let type_def = ast - .types - .iter() - .find(|type_def| type_def.name.0.contents == last_item); - let type_def_2 = ast.submodules.iter().map(|submodule| { - submodule - .contents - .types - .iter() - .find(|type_def| type_def.name.0.contents == last_item) - }); - dbg!(type_def); - dbg!(type_def_2); - // dbg!(path); - // dbg!(unresolved_type); - } - _ => println!("todo"), + // Hasher object for each variable to call + let hasher_variable = variable!("hasher"); + + // Define the hasher with a let expression + let let_hasher = Statement::Let(LetStatement { + pattern: hasher_mut, + r#type: context_type, + expression: expression!(ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(variable_path!(hasher_path)), + arguments: vec![], + }))), + }); + + // Completes: `let hasher = Hasher::new();` + injected_expressions.push(let_hasher); + + params.iter().for_each(|(pattern, ty, _vis)| { + match pattern { + Pattern::Identifier(ident) => { + // Match the type to determine the padding to do + match ty { + // If we get an unresolved type, then we call serialise on it anf add it to our hasher object + UnresolvedType::Named(..) => { + // dbg!("Named"); + // Find the type definition in the ast + + // If the type is unresolved, then call serialise on it + // Create a path calling serialize on ident + let serialised_call = method_call!( + variable_path!(ident_path!(ident.clone())), // variable + "serialize", // method name + vec![] // args + ); + + let add_multi = Statement::Semi(method_call!( + hasher_variable.clone(), // variable + "add_multiple", // method name + vec![serialised_call] // args + )); + + // Add this to the return expressions. + injected_expressions.push(add_multi); } + UnresolvedType::Array(..) => { + // Note if this is an array of structs, call the above method on each of them + // If this is an array of primitives, then cast them to fields + + // Create an array pushing the value as fields to the hasher + let end_range_expression = method_call!( + variable_path!(ident_path!(ident.clone())), // variable + "len", // method name + vec![] // args + ); - // Converts each type to a Field Element before hashing - let variable = Expression::new( - ExpressionKind::Variable(crate::Path::from_ident(ident.clone())), - Span::default(), - ); - let cast_expression = ExpressionKind::Cast(Box::new(crate::CastExpression { - lhs: variable, - r#type: UnresolvedType::FieldElement, - })); - - Expression::new(cast_expression, Span::default()) + // Wrap in the semi thing - does that mean ended with semi colon? + let for_loop_block = + ExpressionKind::Block(BlockExpression(vec![Statement::Semi( + method_call!( + hasher_variable.clone(), // variable + "add", // method name + vec![expression!(ExpressionKind::Cast(Box::new( + CastExpression { + lhs: expression!(ExpressionKind::Index(Box::new( + IndexExpression { + collection: variable_path!(ident_path!( + ident.clone() + )), + index: variable!("i"), + } + ))), + r#type: UnresolvedType::FieldElement, + } + )))] + ), + )])); + + let for_loop = Statement::Expression(expression!(ExpressionKind::For( + Box::new(ForExpression { + identifier: ident!("i"), + start_range: expression!(ExpressionKind::Literal( + Literal::Integer(FieldElement::from(i128::from(0))) + )), + end_range: end_range_expression, + block: expression!(for_loop_block), + }) + ))); + + // Add the for loop to our list of return expressions + injected_expressions.push(for_loop); + } + UnresolvedType::FieldElement => { + // dbg!("Field"); + let add_field = Statement::Semi(method_call!( + hasher_variable.clone(), // variable + "add", // method name + vec![variable_path!(ident_path!(ident.clone()))] // args + )); + injected_expressions.push(add_field); + } + UnresolvedType::Integer(_, __) => { + // dbg!("Integer"); + // Add the integer to the hasher, casted + let add_casted_integer = Statement::Semi(method_call!( + hasher_variable.clone(), // variable + "add", // method name + vec![expression!(ExpressionKind::Cast(Box::new(CastExpression { + lhs: variable_path!(ident_path!(ident.clone())), + r#type: UnresolvedType::FieldElement, + })))] + )); + injected_expressions.push(add_casted_integer); + } + _ => println!("todo"), } - _ => todo!(), } - }) - .collect::>(); - - let args_array = Expression::new( - ExpressionKind::Literal(crate::Literal::Array(crate::ArrayLiteral::Standard( - param_expressions.clone(), - ))), - Span::default(), + _ => todo!(), + } + }); + + // Create the context from the hasher + let context_ident = ident!("context"); + let context_pattern = Pattern::Identifier(context_ident); + let context_mut = Pattern::Mutable(Box::new(context_pattern.clone()), Span::default()); + let context_type_ident = ident!(ty); + let mut context_path = Path::from_ident(context_type_ident); + let context_type = UnresolvedType::Named(context_path.clone(), vec![]); + + // Create the new context + context_path.segments.push(ident!("new")); + + let inputs_expression = variable!("inputs"); + let hash_call = method_call!( + variable!("hasher"), // variable + "hash", // method name + vec![] // args ); + let new_context_args = vec![inputs_expression, hash_call]; - let call_args = vec![args_array]; + // Call the init of the context + let expression = call!(variable_path!(context_path), new_context_args); - let call_expression = CallExpression { - func: Box::new(Expression::new(ExpressionKind::Variable(hash_path), Span::default())), - arguments: call_args, - }; - return call_expression; + let let_expression = + Statement::Let(LetStatement { pattern: context_mut, r#type: context_type, expression }); + injected_expressions.push(let_expression); + + // Return all expressions that will be injected by the hasher + return injected_expressions; } pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { - let return_ident_base = Ident::new("abi".to_string(), Span::default()); - let return_ident = Ident::new(ty.to_string(), Span::default()); - let mut return_path = crate::Path::from_ident(return_ident_base); + let return_ident = ident!(ty); + let mut return_path = ident_path!("abi"); return_path.segments.push(return_ident); let ty = UnresolvedType::Named(return_path, vec![]); @@ -216,17 +323,10 @@ pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { } pub(crate) fn create_context_finish() -> Statement { - let context_ident = Ident::new("context".to_string(), Span::default()); - let method_call_expression = MethodCallExpression { - object: Expression::new( - ExpressionKind::Variable(crate::Path::from_ident(context_ident)), - Span::default(), - ), - method_name: Ident::new("finish".to_string(), Span::default()), - arguments: vec![], - }; - let method_call = ExpressionKind::MethodCall(Box::new(method_call_expression)); - - let expression = Expression::new(method_call, Span::default()); - Statement::Expression(expression) + let method_call = method_call!( + variable!("context"), // variable + ident!("finish"), // method name + vec![] // args + ); + Statement::Expression(method_call) } From a5b88c2b57fd64e4c8ee2a90e4ee623c5676b557 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:07:59 +0000 Subject: [PATCH 12/21] fmt --- crates/noirc_frontend/src/monomorphization/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/noirc_frontend/src/monomorphization/mod.rs b/crates/noirc_frontend/src/monomorphization/mod.rs index 2ef980176d3..fb441a1bc17 100644 --- a/crates/noirc_frontend/src/monomorphization/mod.rs +++ b/crates/noirc_frontend/src/monomorphization/mod.rs @@ -882,8 +882,8 @@ impl<'interner> Monomorphizer<'interner> { } } let printable_type: PrintableType = typ.into(); - let abi_as_string = - serde_json::to_string(&printable_type).expect("ICE: expected PrintableType to serialize"); + let abi_as_string = serde_json::to_string(&printable_type) + .expect("ICE: expected PrintableType to serialize"); arguments.push(ast::Expression::Literal(ast::Literal::Str(abi_as_string))); } From 56f217b9814c0f4da40b886b73e0d290b227e391 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:08:55 +0000 Subject: [PATCH 13/21] fix: turn flags back on --- crates/noirc_frontend/src/hir/def_map/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index bf5a77bf0fd..8ed224935a1 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -18,9 +18,9 @@ pub use module_data::*; mod namespace; pub use namespace::*; -// #[cfg(feature = "aztec")] +#[cfg(feature = "aztec")] mod aztec_helper; -// #[cfg(feature = "aztec")] +#[cfg(feature = "aztec")] use aztec_helper::aztec_contracts_macros; /// The name that is used for a non-contract program's entry-point function. @@ -91,7 +91,7 @@ impl CrateDefMap { let ast = parse_file(&mut context.file_manager, root_file_id, errors); - // #[cfg(feature = "aztec")] + #[cfg(feature = "aztec")] let ast = aztec_contracts_macros(ast); // Allocate a default Module for the root, giving it a ModuleId From df05bfdcf13bd336adf3585532911f0310129ebf Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:45:21 +0000 Subject: [PATCH 14/21] feat: further cleanup --- .../src/hir/def_map/aztec_helper.rs | 282 ++++++++++-------- 1 file changed, 151 insertions(+), 131 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index 5189c259d6f..023e30ab1dd 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -60,6 +60,55 @@ macro_rules! call { }; } +macro_rules! mutable { + ( $name:expr ) => { + Pattern::Mutable(Box::new(Pattern::Identifier(ident!($name))), Span::default()) + }; // let mut hasher_path = ident_path!("Hasher"); + // let context_type = UnresolvedType::Named(hasher_path.clone(), vec![]); +} + +macro_rules! mutable_assignment { + ( $name:expr, $assigned_to:expr ) => { + Statement::Let(LetStatement { + pattern: mutable!($name), + r#type: UnresolvedType::Unspecified, + expression: $assigned_to, + }) + }; +} + +macro_rules! chained_path { + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path!($base); + $( + base_path.segments.push(ident!($tail)); + )* + base_path + } + } +} + +macro_rules! cast { + ( $lhs:expr, $rhs:expr ) => { + expression!(ExpressionKind::Cast(Box::new(CastExpression { lhs: $lhs, r#type: $rhs }))) + }; +} + +macro_rules! index_array { + ( $array:expr, $index:expr ) => { + expression!(ExpressionKind::Index(Box::new(IndexExpression { + collection: variable_path!(ident_path!($array)), + index: variable!($index), + }))) + }; +} +///////////////////////////////////////////////////////////////////////// +/// Create AST Nodes for Aztec /// +///////////////////////////////////////////////////////////////////////// + +/// Traverses every function in the ast, calling `transform_function` which +/// determines if further processing is required pub(crate) fn aztec_contracts_macros(mut ast: ParsedModule) -> ParsedModule { // Usage -> mut ast -> AztecLib.transform(&mut ast) @@ -75,59 +124,46 @@ pub(crate) fn aztec_contracts_macros(mut ast: ParsedModule) -> ParsedModule { ast } -// TODO: might be worth making this a struct to prevent passing the ast around +/// Determines if the function is annotated with `aztec(private)` or `aztec(public)` +/// If it is, it calls the `transform` function which will perform the required transformations. fn transform_function(func: &mut NoirFunction) { if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { - // TODO: this can just become the one function!!! - // match based on the custom attribute match custom_attribute.as_str() { - "aztec(private)" => { - // temp: if the name = entrypoint then print it out - - // Edit the ast to inject the private context into the function - // Create the context using the current params - let create_context = create_context("PrivateContext", &func.def.parameters); - // Insert the context creation as the first action - func.def.body.0.splice(0..0, (&create_context).iter().cloned()); - - // Add the inputs to the params - let input = create_inputs("PrivateContextInputs"); - func.def.parameters.insert(0, input); - - // Push the finish method call to the end of the function - let finish_def = create_context_finish(); - func.def.body.0.push(finish_def); - - let return_type = create_return_type("PrivateCircuitPublicInputs"); - func.def.return_type = return_type; - func.def.return_visibility = Visibility::Public; - func.def.return_distinctness = Distinctness::Distinct; - - if func.name() == "entrypoint" { - // dbg!(&func); - } - } - "aztec(public)" => { - let create_context = create_context("PublicContext", &func.def.parameters); - // Insert the context creation as the first action - func.def.body.0.splice(0..0, (&create_context).iter().cloned()); - - // Add the inputs to the params - let input = create_inputs("PublicContextInputs"); - func.def.parameters.insert(0, input); - - // Push the finish method call to the end of the function - let finish_def = create_context_finish(); - func.def.body.0.push(finish_def); - - let return_type = create_return_type("PublicCircuitPublicInputs"); - func.def.return_type = return_type; - func.def.return_visibility = Visibility::Public; - // func.def.return_distinctness = Distinctness::Distinct; - } + "aztec(private)" => transform("Private", func), + "aztec(public)" => transform("Public", func), _ => return, } - // dbg!(&func); + } +} + +/// If it does, it will insert the following things: +/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs +/// - Hashes all of the function input variables +/// - This instantiates a helper function +fn transform(ty: &str, func: &mut NoirFunction) { + let context_name = format!("{}Context", ty); + let inputs_name = format!("{}ContextInputs", ty); + let return_type_name = format!("{}CircuitPublicInputs", ty); + + let create_context = create_context(&context_name, &func.def.parameters); + // Insert the context creation as the first action + func.def.body.0.splice(0..0, (&create_context).iter().cloned()); + + // Add the inputs to the params + let input = create_inputs(&inputs_name); + func.def.parameters.insert(0, input); + + // Push the finish method call to the end of the function + let finish_def = create_context_finish(); + func.def.body.0.push(finish_def); + + let return_type = create_return_type(&return_type_name); + func.def.return_type = return_type; + func.def.return_visibility = Visibility::Public; + + // Distinct return types are only required for private functions + if ty.eq("Private") { + func.def.return_distinctness = Distinctness::Distinct; } } @@ -147,37 +183,19 @@ pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Vec { let mut injected_expressions: Vec = vec![]; - let mut hash_path = ident_path!("abi"); - hash_path.segments.push(ident!("hash_args")); - - // Create hasher structure - let mut hasher_path = ident_path!("abi"); - hasher_path.segments.push(ident!("Hasher")); - - // Assign the hasher to a variable - let hasher_ident = ident!("hasher"); - let hasher_pattern = Pattern::Identifier(hasher_ident.clone()); - let hasher_mut = Pattern::Mutable(Box::new(hasher_pattern.clone()), Span::default()); - let mut hasher_path = ident_path!("Hasher"); - let context_type = UnresolvedType::Named(hasher_path.clone(), vec![]); - - // Create the new hasher - hasher_path.segments.push(ident!("new")); - // Hasher object for each variable to call let hasher_variable = variable!("hasher"); - // Define the hasher with a let expression - let let_hasher = Statement::Let(LetStatement { - pattern: hasher_mut, - r#type: context_type, - expression: expression!(ExpressionKind::Call(Box::new(CallExpression { - func: Box::new(variable_path!(hasher_path)), - arguments: vec![], - }))), - }); + // `let mut hasher = Hasher::new();` + let let_hasher = mutable_assignment!( + "hasher", // Assigned to + call!( + variable_path!(chained_path!("Hasher", "new")), // Path + vec![] // args + ) + ); - // Completes: `let hasher = Hasher::new();` + // Completes: `let mut hasher = Hasher::new();` injected_expressions.push(let_hasher); params.iter().for_each(|(pattern, ty, _vis)| { @@ -185,33 +203,30 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) Pattern::Identifier(ident) => { // Match the type to determine the padding to do match ty { - // If we get an unresolved type, then we call serialise on it anf add it to our hasher object + // `hasher.add_multiple({ident}.serialize())` UnresolvedType::Named(..) => { - // dbg!("Named"); - // Find the type definition in the ast - - // If the type is unresolved, then call serialise on it - // Create a path calling serialize on ident + // If this is a struct, we call serialize and add the array to the hasher let serialised_call = method_call!( variable_path!(ident_path!(ident.clone())), // variable "serialize", // method name vec![] // args ); - let add_multi = Statement::Semi(method_call!( + let add_multiple = Statement::Semi(method_call!( hasher_variable.clone(), // variable "add_multiple", // method name vec![serialised_call] // args )); // Add this to the return expressions. - injected_expressions.push(add_multi); + injected_expressions.push(add_multiple); } UnresolvedType::Array(..) => { - // Note if this is an array of structs, call the above method on each of them - // If this is an array of primitives, then cast them to fields + // TODO: if this is an array of structs, we should call serialise on each of them + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field - // Create an array pushing the value as fields to the hasher + // `array.len()` let end_range_expression = method_call!( variable_path!(ident_path!(ident.clone())), // variable "len", // method name @@ -219,27 +234,23 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) ); // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + let cast_expression = cast!( + index_array!(ident.clone(), "i"), // lhs - `ident[i]` + UnresolvedType::FieldElement // cast to - `as Field` + ); + // What will be looped over + // - `hasher.add({ident}[i] as Field)` let for_loop_block = - ExpressionKind::Block(BlockExpression(vec![Statement::Semi( - method_call!( + expression!(ExpressionKind::Block(BlockExpression(vec![ + Statement::Semi(method_call!( hasher_variable.clone(), // variable "add", // method name - vec![expression!(ExpressionKind::Cast(Box::new( - CastExpression { - lhs: expression!(ExpressionKind::Index(Box::new( - IndexExpression { - collection: variable_path!(ident_path!( - ident.clone() - )), - index: variable!("i"), - } - ))), - r#type: UnresolvedType::FieldElement, - } - )))] - ), - )])); + vec![cast_expression] + ),) + ]))); + // `for i in 0..{ident}.len()` let for_loop = Statement::Expression(expression!(ExpressionKind::For( Box::new(ForExpression { identifier: ident!("i"), @@ -247,15 +258,15 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) Literal::Integer(FieldElement::from(i128::from(0))) )), end_range: end_range_expression, - block: expression!(for_loop_block), + block: for_loop_block, }) ))); // Add the for loop to our list of return expressions injected_expressions.push(for_loop); } + // `hasher.add({ident})` UnresolvedType::FieldElement => { - // dbg!("Field"); let add_field = Statement::Semi(method_call!( hasher_variable.clone(), // variable "add", // method name @@ -263,56 +274,61 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) )); injected_expressions.push(add_field); } - UnresolvedType::Integer(_, __) => { - // dbg!("Integer"); - // Add the integer to the hasher, casted + // Add the integer to the hasher, casted to a field + // `hasher.add({ident} as Field)` + UnresolvedType::Integer(..) => { + // `{ident} as Field` + let cast_operation = cast!( + variable_path!(ident_path!(ident.clone())), // lhs + UnresolvedType::FieldElement // rhs + ); + + // `hasher.add({ident} as Field)` let add_casted_integer = Statement::Semi(method_call!( hasher_variable.clone(), // variable "add", // method name - vec![expression!(ExpressionKind::Cast(Box::new(CastExpression { - lhs: variable_path!(ident_path!(ident.clone())), - r#type: UnresolvedType::FieldElement, - })))] + vec![cast_operation] // args )); injected_expressions.push(add_casted_integer); } _ => println!("todo"), } } - _ => todo!(), + _ => todo!(), // Maybe unreachable? } }); - // Create the context from the hasher - let context_ident = ident!("context"); - let context_pattern = Pattern::Identifier(context_ident); - let context_mut = Pattern::Mutable(Box::new(context_pattern.clone()), Span::default()); - let context_type_ident = ident!(ty); - let mut context_path = Path::from_ident(context_type_ident); - let context_type = UnresolvedType::Named(context_path.clone(), vec![]); - - // Create the new context - context_path.segments.push(ident!("new")); - + // Create the inputs to the context let inputs_expression = variable!("inputs"); + // `hasher.hash()` let hash_call = method_call!( variable!("hasher"), // variable "hash", // method name vec![] // args ); - let new_context_args = vec![inputs_expression, hash_call]; - // Call the init of the context - let expression = call!(variable_path!(context_path), new_context_args); - - let let_expression = - Statement::Let(LetStatement { pattern: context_mut, r#type: context_type, expression }); - injected_expressions.push(let_expression); + // let mut context = {ty}::new(inputs, hash); + let let_context = mutable_assignment!( + "context", // Assigned to + call!( + variable_path!(chained_path!(ty, "new")), // Path + vec![inputs_expression, hash_call] // args + ) + ); + injected_expressions.push(let_context); // Return all expressions that will be injected by the hasher return injected_expressions; } +/// Create Return Type +/// +/// Public functions return abi::PublicCircuitPublicInputs while +/// private functions return abi::PrivateCircuitPublicInputs +/// +/// This call constructs an ast token referencing the above types +/// The name is set in the function above `transform`, hence the +/// whole token name is passed in pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { let return_ident = ident!(ty); let mut return_path = ident_path!("abi"); @@ -322,6 +338,10 @@ pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { FunctionReturnType::Ty(ty, Span::default()) } +/// Create Context Finish +/// +/// Each aztec function calls `context.finish()` at the end of a function +/// to return values required by the kernel. pub(crate) fn create_context_finish() -> Statement { let method_call = method_call!( variable!("context"), // variable From 836ea65838c4518948555325f30b80d5aad41518 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:58:22 +0000 Subject: [PATCH 15/21] chore: documentation pass --- .../src/hir/def_map/aztec_helper.rs | 81 ++++++++++++++++--- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs index 023e30ab1dd..25ba602d374 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs @@ -63,8 +63,7 @@ macro_rules! call { macro_rules! mutable { ( $name:expr ) => { Pattern::Mutable(Box::new(Pattern::Identifier(ident!($name))), Span::default()) - }; // let mut hasher_path = ident_path!("Hasher"); - // let context_type = UnresolvedType::Named(hasher_path.clone(), vec![]); + }; } macro_rules! mutable_assignment { @@ -103,6 +102,7 @@ macro_rules! index_array { }))) }; } + ///////////////////////////////////////////////////////////////////////// /// Create AST Nodes for Aztec /// ///////////////////////////////////////////////////////////////////////// @@ -145,8 +145,8 @@ fn transform(ty: &str, func: &mut NoirFunction) { let inputs_name = format!("{}ContextInputs", ty); let return_type_name = format!("{}CircuitPublicInputs", ty); - let create_context = create_context(&context_name, &func.def.parameters); // Insert the context creation as the first action + let create_context = create_context(&context_name, &func.def.parameters); func.def.body.0.splice(0..0, (&create_context).iter().cloned()); // Add the inputs to the params @@ -169,6 +169,19 @@ fn transform(ty: &str, func: &mut NoirFunction) { /// Helper function that returns what the private context would look like in the ast /// This should make it available to be consumed within aztec private annotated functions. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo(inputs: PrivateContextInputs) { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { let context_ident = ident!("inputs"); let context_pattern = Pattern::Identifier(context_ident); @@ -179,7 +192,30 @@ pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { } /// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object +/// appended into the args hash object. +/// +/// The replaced code: +/// ```noir +/// #[aztec(private)] +/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { +/// // Create the hasher object +/// let mut hasher = Hasher::new(); +/// +/// // struct inputs call serialize on them to add an array of fields +/// hasher.add_multiple(structInput.serialize()); +/// +/// // Array inputs are iterated over and each element is added to the hasher (as a field) +/// for i in 0..arrayInput.len() { +/// hasher.add(arrayInput[i] as Field); +/// } +/// // Field inputs are added to the hasher +/// hasher.add({ident}); +/// +/// // Create the context +/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context +/// let mut context = PrivateContext::new(inputs, hasher.hash()); +/// } +/// ``` fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Vec { let mut injected_expressions: Vec = vec![]; @@ -198,6 +234,7 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) // Completes: `let mut hasher = Hasher::new();` injected_expressions.push(let_hasher); + // Iterate over each of the function parameters, adding to them to the hasher params.iter().for_each(|(pattern, ty, _vis)| { match pattern { Pattern::Identifier(ident) => { @@ -222,7 +259,7 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) injected_expressions.push(add_multiple); } UnresolvedType::Array(..) => { - // TODO: if this is an array of structs, we should call serialise on each of them + // TODO: if this is an array of structs, we should call serialise on each of them (no methods currently do this yet) // If this is an array of primitive types (integers / fields) we can add them each to the hasher // casted to a field @@ -291,7 +328,7 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) )); injected_expressions.push(add_casted_integer); } - _ => println!("todo"), + _ => println!("todo"), // Maybe unreachable? } } _ => todo!(), // Maybe unreachable? @@ -329,10 +366,22 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) /// This call constructs an ast token referencing the above types /// The name is set in the function above `transform`, hence the /// whole token name is passed in +/// +/// The replaced code: +/// ```noir +/// +/// /// Before +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { - let return_ident = ident!(ty); - let mut return_path = ident_path!("abi"); - return_path.segments.push(return_ident); + let return_path = chained_path!("abi", ty); let ty = UnresolvedType::Named(return_path, vec![]); FunctionReturnType::Ty(ty, Span::default()) @@ -342,6 +391,20 @@ pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { /// /// Each aztec function calls `context.finish()` at the end of a function /// to return values required by the kernel. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// context.finish() +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } pub(crate) fn create_context_finish() -> Statement { let method_call = method_call!( variable!("context"), // variable From 011a8895f75e8092d39fdbfca2994ecfbde0c2f6 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:26:19 +0000 Subject: [PATCH 16/21] chore: final cookup --- .../{aztec_helper.rs => aztec_library.rs} | 213 +++++++++--------- crates/noirc_frontend/src/hir/def_map/mod.rs | 7 +- 2 files changed, 108 insertions(+), 112 deletions(-) rename crates/noirc_frontend/src/hir/def_map/{aztec_helper.rs => aztec_library.rs} (62%) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs similarity index 62% rename from crates/noirc_frontend/src/hir/def_map/aztec_helper.rs rename to crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 25ba602d374..57194def7a9 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_helper.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -89,8 +89,8 @@ macro_rules! chained_path { } macro_rules! cast { - ( $lhs:expr, $rhs:expr ) => { - expression!(ExpressionKind::Cast(Box::new(CastExpression { lhs: $lhs, r#type: $rhs }))) + ( $lhs:expr, $ty:expr ) => { + expression!(ExpressionKind::Cast(Box::new(CastExpression { lhs: $lhs, r#type: $ty }))) }; } @@ -109,29 +109,27 @@ macro_rules! index_array { /// Traverses every function in the ast, calling `transform_function` which /// determines if further processing is required -pub(crate) fn aztec_contracts_macros(mut ast: ParsedModule) -> ParsedModule { - // Usage -> mut ast -> AztecLib.transform(&mut ast) +pub(crate) fn transform(mut ast: ParsedModule) -> ParsedModule { + // Usage -> mut ast -> aztec_library::transform(&mut ast) // Covers all functions in the ast - for func in ast.functions.iter_mut() { - transform_function(func); - } + transform_module(&mut ast.functions); for submodule in ast.submodules.iter_mut() { - for func in submodule.contents.functions.iter_mut() { - transform_function(func); - } + transform_module(&mut submodule.contents.functions); } ast } /// Determines if the function is annotated with `aztec(private)` or `aztec(public)` /// If it is, it calls the `transform` function which will perform the required transformations. -fn transform_function(func: &mut NoirFunction) { - if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { - match custom_attribute.as_str() { - "aztec(private)" => transform("Private", func), - "aztec(public)" => transform("Public", func), - _ => return, +fn transform_module(functions: &mut Vec) { + for func in functions.iter_mut() { + if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { + match custom_attribute.as_str() { + "aztec(private)" => transform_function("Private", func), + "aztec(public)" => transform_function("Public", func), + _ => return, + } } } } @@ -140,7 +138,7 @@ fn transform_function(func: &mut NoirFunction) { /// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs /// - Hashes all of the function input variables /// - This instantiates a helper function -fn transform(ty: &str, func: &mut NoirFunction) { +fn transform_function(ty: &str, func: &mut NoirFunction) { let context_name = format!("{}Context", ty); let inputs_name = format!("{}ContextInputs", ty); let return_type_name = format!("{}CircuitPublicInputs", ty); @@ -219,9 +217,6 @@ pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Vec { let mut injected_expressions: Vec = vec![]; - // Hasher object for each variable to call - let hasher_variable = variable!("hasher"); - // `let mut hasher = Hasher::new();` let let_hasher = mutable_assignment!( "hasher", // Assigned to @@ -239,97 +234,19 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) match pattern { Pattern::Identifier(ident) => { // Match the type to determine the padding to do - match ty { + let expression = match ty { // `hasher.add_multiple({ident}.serialize())` - UnresolvedType::Named(..) => { - // If this is a struct, we call serialize and add the array to the hasher - let serialised_call = method_call!( - variable_path!(ident_path!(ident.clone())), // variable - "serialize", // method name - vec![] // args - ); - - let add_multiple = Statement::Semi(method_call!( - hasher_variable.clone(), // variable - "add_multiple", // method name - vec![serialised_call] // args - )); - - // Add this to the return expressions. - injected_expressions.push(add_multiple); - } - UnresolvedType::Array(..) => { - // TODO: if this is an array of structs, we should call serialise on each of them (no methods currently do this yet) - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - - // `array.len()` - let end_range_expression = method_call!( - variable_path!(ident_path!(ident.clone())), // variable - "len", // method name - vec![] // args - ); - - // Wrap in the semi thing - does that mean ended with semi colon? - // `hasher.add({ident}[i] as Field)` - let cast_expression = cast!( - index_array!(ident.clone(), "i"), // lhs - `ident[i]` - UnresolvedType::FieldElement // cast to - `as Field` - ); - // What will be looped over - // - `hasher.add({ident}[i] as Field)` - let for_loop_block = - expression!(ExpressionKind::Block(BlockExpression(vec![ - Statement::Semi(method_call!( - hasher_variable.clone(), // variable - "add", // method name - vec![cast_expression] - ),) - ]))); - - // `for i in 0..{ident}.len()` - let for_loop = Statement::Expression(expression!(ExpressionKind::For( - Box::new(ForExpression { - identifier: ident!("i"), - start_range: expression!(ExpressionKind::Literal( - Literal::Integer(FieldElement::from(i128::from(0))) - )), - end_range: end_range_expression, - block: for_loop_block, - }) - ))); - - // Add the for loop to our list of return expressions - injected_expressions.push(for_loop); - } + UnresolvedType::Named(..) => add_struct_to_hasher(ident), + // TODO: if this is an array of structs, we should call serialise on each of them (no methods currently do this yet) + UnresolvedType::Array(..) => add_array_to_hasher(ident), // `hasher.add({ident})` - UnresolvedType::FieldElement => { - let add_field = Statement::Semi(method_call!( - hasher_variable.clone(), // variable - "add", // method name - vec![variable_path!(ident_path!(ident.clone()))] // args - )); - injected_expressions.push(add_field); - } + UnresolvedType::FieldElement => add_field_to_hasher(ident), // Add the integer to the hasher, casted to a field // `hasher.add({ident} as Field)` - UnresolvedType::Integer(..) => { - // `{ident} as Field` - let cast_operation = cast!( - variable_path!(ident_path!(ident.clone())), // lhs - UnresolvedType::FieldElement // rhs - ); - - // `hasher.add({ident} as Field)` - let add_casted_integer = Statement::Semi(method_call!( - hasher_variable.clone(), // variable - "add", // method name - vec![cast_operation] // args - )); - injected_expressions.push(add_casted_integer); - } - _ => println!("todo"), // Maybe unreachable? - } + UnresolvedType::Integer(..) => add_int_to_hasher(ident), + _ => unreachable!("[Aztec Noir] Provided parameter type is not supported"), + }; + injected_expressions.push(expression); } _ => todo!(), // Maybe unreachable? } @@ -413,3 +330,85 @@ pub(crate) fn create_context_finish() -> Statement { ); Statement::Expression(method_call) } + +///////////////////////////////////////////////////////////////////////// +/// Methods to create hasher inputs /// +///////////////////////////////////////////////////////////////////////// + +fn add_struct_to_hasher(ident: &Ident) -> Statement { + // If this is a struct, we call serialize and add the array to the hasher + let serialised_call = method_call!( + variable_path!(ident_path!(ident.clone())), // variable + "serialize", // method name + vec![] // args + ); + + Statement::Semi(method_call!( + variable!("hasher"), // variable + "add_multiple", // method name + vec![serialised_call] // args + )) +} + +fn add_array_to_hasher(ident: &Ident) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + + // `array.len()` + let end_range_expression = method_call!( + variable_path!(ident_path!(ident.clone())), // variable + "len", // method name + vec![] // args + ); + + // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + let cast_expression = cast!( + index_array!(ident.clone(), "i"), // lhs - `ident[i]` + UnresolvedType::FieldElement // cast to - `as Field` + ); + // What will be looped over + // - `hasher.add({ident}[i] as Field)` + let for_loop_block = + expression!(ExpressionKind::Block(BlockExpression(vec![Statement::Semi(method_call!( + variable!("hasher"), // variable + "add", // method name + vec![cast_expression] + ),)]))); + + // `for i in 0..{ident}.len()` + Statement::Expression(expression!(ExpressionKind::For(Box::new(ForExpression { + identifier: ident!("i"), + start_range: expression!(ExpressionKind::Literal(Literal::Integer(FieldElement::from( + i128::from(0) + )))), + end_range: end_range_expression, + block: for_loop_block, + })))) +} + +fn add_field_to_hasher(ident: &Ident) -> Statement { + // `hasher.add({ident})` + let iden = variable_path!(ident_path!(ident.clone())); + Statement::Semi(method_call!( + variable!("hasher"), // variable + "add", // method name + vec![iden] // args + )) +} + +fn add_int_to_hasher(ident: &Ident) -> Statement { + // `hasher.add({ident} as Field)` + // `{ident} as Field` + let cast_operation = cast!( + variable_path!(ident_path!(ident.clone())), // lhs + UnresolvedType::FieldElement // rhs + ); + + // `hasher.add({ident} as Field)` + Statement::Semi(method_call!( + variable!("hasher"), // variable + "add", // method name + vec![cast_operation] // args + )) +} diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 8ed224935a1..bd196ba5ef0 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -19,9 +19,7 @@ mod namespace; pub use namespace::*; #[cfg(feature = "aztec")] -mod aztec_helper; -#[cfg(feature = "aztec")] -use aztec_helper::aztec_contracts_macros; +mod aztec_library; /// The name that is used for a non-contract program's entry-point function. pub const MAIN_FUNCTION: &str = "main"; @@ -88,11 +86,10 @@ impl CrateDefMap { // First parse the root file. let root_file_id = context.crate_graph[crate_id].root_file_id; - let ast = parse_file(&mut context.file_manager, root_file_id, errors); #[cfg(feature = "aztec")] - let ast = aztec_contracts_macros(ast); + let ast = aztec_library::transform(ast); // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); From c3f1ff4f29f26108a95acb2b6986c65995be7816 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:43:53 +0000 Subject: [PATCH 17/21] fix: merge refactor --- .../src/hir/def_map/aztec_library.rs | 34 +++++--- crates/noirc_frontend/src/hir/def_map/mod.rs | 4 +- crates/noirc_frontend/src/lexer/lexer.rs | 82 ++++++++++--------- 3 files changed, 67 insertions(+), 53 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 57194def7a9..942e5a60584 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -5,7 +5,7 @@ use crate::{ token::Attribute, BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, ForExpression, FunctionReturnType, Ident, IndexExpression, LetStatement, Literal, MethodCallExpression, NoirFunction, ParsedModule, Path, Pattern, Statement, - UnresolvedType, Visibility, + UnresolvedType, UnresolvedTypeData, Visibility, }; ///////////////////////////////////////////////////////////////////////// @@ -70,7 +70,7 @@ macro_rules! mutable_assignment { ( $name:expr, $assigned_to:expr ) => { Statement::Let(LetStatement { pattern: mutable!($name), - r#type: UnresolvedType::Unspecified, + r#type: make_type!(UnresolvedTypeData::Unspecified), expression: $assigned_to, }) }; @@ -90,7 +90,16 @@ macro_rules! chained_path { macro_rules! cast { ( $lhs:expr, $ty:expr ) => { - expression!(ExpressionKind::Cast(Box::new(CastExpression { lhs: $lhs, r#type: $ty }))) + expression!(ExpressionKind::Cast(Box::new(CastExpression { + lhs: $lhs, + r#type: make_type!($ty) + }))) + }; +} + +macro_rules! make_type { + ( $ty:expr ) => { + UnresolvedType { typ: $ty, span: None } }; } @@ -183,7 +192,7 @@ fn transform_function(ty: &str, func: &mut NoirFunction) { pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { let context_ident = ident!("inputs"); let context_pattern = Pattern::Identifier(context_ident); - let context_type = UnresolvedType::Named(ident_path!(ty), vec![]); + let context_type = make_type!(UnresolvedTypeData::Named(ident_path!(ty), vec![])); let visibility = Visibility::Private; (context_pattern, context_type, visibility) @@ -234,16 +243,17 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) match pattern { Pattern::Identifier(ident) => { // Match the type to determine the padding to do - let expression = match ty { + let unresolved_type = &ty.typ; + let expression = match unresolved_type { // `hasher.add_multiple({ident}.serialize())` - UnresolvedType::Named(..) => add_struct_to_hasher(ident), + UnresolvedTypeData::Named(..) => add_struct_to_hasher(ident), // TODO: if this is an array of structs, we should call serialise on each of them (no methods currently do this yet) - UnresolvedType::Array(..) => add_array_to_hasher(ident), + UnresolvedTypeData::Array(..) => add_array_to_hasher(ident), // `hasher.add({ident})` - UnresolvedType::FieldElement => add_field_to_hasher(ident), + UnresolvedTypeData::FieldElement => add_field_to_hasher(ident), // Add the integer to the hasher, casted to a field // `hasher.add({ident} as Field)` - UnresolvedType::Integer(..) => add_int_to_hasher(ident), + UnresolvedTypeData::Integer(..) => add_int_to_hasher(ident), _ => unreachable!("[Aztec Noir] Provided parameter type is not supported"), }; injected_expressions.push(expression); @@ -300,7 +310,7 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { let return_path = chained_path!("abi", ty); - let ty = UnresolvedType::Named(return_path, vec![]); + let ty = make_type!(UnresolvedTypeData::Named(return_path, vec![])); FunctionReturnType::Ty(ty, Span::default()) } @@ -365,7 +375,7 @@ fn add_array_to_hasher(ident: &Ident) -> Statement { // `hasher.add({ident}[i] as Field)` let cast_expression = cast!( index_array!(ident.clone(), "i"), // lhs - `ident[i]` - UnresolvedType::FieldElement // cast to - `as Field` + UnresolvedTypeData::FieldElement // cast to - `as Field` ); // What will be looped over // - `hasher.add({ident}[i] as Field)` @@ -402,7 +412,7 @@ fn add_int_to_hasher(ident: &Ident) -> Statement { // `{ident} as Field` let cast_operation = cast!( variable_path!(ident_path!(ident.clone())), // lhs - UnresolvedType::FieldElement // rhs + UnresolvedTypeData::FieldElement // rhs ); // `hasher.add({ident} as Field)` diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 66a65c09157..379a74a440e 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -18,7 +18,7 @@ pub use module_data::*; mod namespace; pub use namespace::*; -#[cfg(feature = "aztec")] +// #[cfg(feature = "aztec")] mod aztec_library; /// The name that is used for a non-contract program's entry-point function. @@ -88,7 +88,7 @@ impl CrateDefMap { let root_file_id = context.crate_graph[crate_id].root_file_id; let ast = parse_file(&mut context.file_manager, root_file_id, errors); - #[cfg(feature = "aztec")] + // #[cfg(feature = "aztec")] let ast = aztec_library::transform(ast); // Allocate a default Module for the root, giving it a ModuleId diff --git a/crates/noirc_frontend/src/lexer/lexer.rs b/crates/noirc_frontend/src/lexer/lexer.rs index 09528d4fc27..194c5788268 100644 --- a/crates/noirc_frontend/src/lexer/lexer.rs +++ b/crates/noirc_frontend/src/lexer/lexer.rs @@ -464,54 +464,58 @@ mod tests { let input = "#"; let mut lexer = Lexer::new(input); - let token = lexer.next().unwrap(); - assert!(token.is_err()); -} + let token = lexer.next().unwrap(); + assert!(token.is_err()); + } -#[test] -fn deprecated_attribute() { - let input = r#"#[deprecated]"#; - let mut lexer = Lexer::new(input); + #[test] + fn deprecated_attribute() { + let input = r#"#[deprecated]"#; + let mut lexer = Lexer::new(input); - let token = lexer.next().unwrap().unwrap(); - assert_eq!(token.token(), &Token::Attribute(Attribute::Deprecated(None))); -} + let token = lexer.next().unwrap().unwrap(); + assert_eq!(token.token(), &Token::Attribute(Attribute::Deprecated(None))); + } -#[test] -fn deprecated_attribute_with_note() { - let input = r#"#[deprecated("hello")]"#; - let mut lexer = Lexer::new(input); + #[test] + fn deprecated_attribute_with_note() { + let input = r#"#[deprecated("hello")]"#; + let mut lexer = Lexer::new(input); - let token = lexer.next().unwrap().unwrap(); - assert_eq!(token.token(), &Token::Attribute(Attribute::Deprecated("hello".to_string().into()))); -} + let token = lexer.next().unwrap().unwrap(); + assert_eq!( + token.token(), + &Token::Attribute(Attribute::Deprecated("hello".to_string().into())) + ); + } -#[test] -fn custom_attribute() { - let input = r#"#[custom(hello)]"#; - let mut lexer = Lexer::new(input); + #[test] + fn custom_attribute() { + let input = r#"#[custom(hello)]"#; + let mut lexer = Lexer::new(input); - let token = lexer.next().unwrap().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Custom("custom(hello)".to_string().into())) - ); -} + let token = lexer.next().unwrap().unwrap(); + assert_eq!( + token.token(), + &Token::Attribute(Attribute::Custom("custom(hello)".to_string().into())) + ); + } -#[test] -fn test_custom_gate_syntax() { - let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; + #[test] + fn test_custom_gate_syntax() { + let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; - let expected = vec![ - Token::Attribute(Attribute::Foreign("sha256".to_string())), - Token::Attribute(Attribute::Foreign("blake2s".to_string())), - Token::Attribute(Attribute::Builtin("sum".to_string())), - ]; + let expected = vec![ + Token::Attribute(Attribute::Foreign("sha256".to_string())), + Token::Attribute(Attribute::Foreign("blake2s".to_string())), + Token::Attribute(Attribute::Builtin("sum".to_string())), + ]; - let mut lexer = Lexer::new(input); - for token in expected.into_iter() { - let got = lexer.next_token().unwrap(); - assert_eq!(got, token); + let mut lexer = Lexer::new(input); + for token in expected.into_iter() { + let got = lexer.next_token().unwrap(); + assert_eq!(got, token); + } } #[test] From 6601135a68f63876bdc7199c8b9383f25c7b11a1 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:04:47 +0000 Subject: [PATCH 18/21] fix: appease clippy gods --- crates/noirc_frontend/src/hir/def_map/aztec_library.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 942e5a60584..72e0cfee7ef 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -131,7 +131,7 @@ pub(crate) fn transform(mut ast: ParsedModule) -> ParsedModule { /// Determines if the function is annotated with `aztec(private)` or `aztec(public)` /// If it is, it calls the `transform` function which will perform the required transformations. -fn transform_module(functions: &mut Vec) { +fn transform_module(functions: &mut [NoirFunction]) { for func in functions.iter_mut() { if let Some(Attribute::Custom(custom_attribute)) = func.def.attribute.as_ref() { match custom_attribute.as_str() { @@ -154,7 +154,7 @@ fn transform_function(ty: &str, func: &mut NoirFunction) { // Insert the context creation as the first action let create_context = create_context(&context_name, &func.def.parameters); - func.def.body.0.splice(0..0, (&create_context).iter().cloned()); + func.def.body.0.splice(0..0, (create_context).iter().cloned()); // Add the inputs to the params let input = create_inputs(&inputs_name); @@ -223,7 +223,7 @@ pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { /// let mut context = PrivateContext::new(inputs, hasher.hash()); /// } /// ``` -fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) -> Vec { +fn create_context(ty: &str, params: &[(Pattern, UnresolvedType, Visibility)]) -> Vec { let mut injected_expressions: Vec = vec![]; // `let mut hasher = Hasher::new();` @@ -282,7 +282,7 @@ fn create_context(ty: &str, params: &Vec<(Pattern, UnresolvedType, Visibility)>) injected_expressions.push(let_context); // Return all expressions that will be injected by the hasher - return injected_expressions; + injected_expressions } /// Create Return Type From 1c60707837f2711ba0e6d44e970d092f6be123d3 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:25:11 +0000 Subject: [PATCH 19/21] fix: dirty merge --- .../src/hir/def_map/aztec_library.rs | 18 +++---- crates/noirc_frontend/src/lexer/lexer.rs | 50 ------------------- 2 files changed, 9 insertions(+), 59 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 72e0cfee7ef..4b27f5fe98e 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -8,9 +8,9 @@ use crate::{ UnresolvedType, UnresolvedTypeData, Visibility, }; -///////////////////////////////////////////////////////////////////////// -/// Helper macros for creating noir ast nodes /// -///////////////////////////////////////////////////////////////////////// +// +// Helper macros for creating noir ast nodes +// macro_rules! ident { ($name:expr) => { Ident::new($name.to_string(), Span::default()) @@ -112,9 +112,9 @@ macro_rules! index_array { }; } -///////////////////////////////////////////////////////////////////////// -/// Create AST Nodes for Aztec /// -///////////////////////////////////////////////////////////////////////// +// +// Create AST Nodes for Aztec +// /// Traverses every function in the ast, calling `transform_function` which /// determines if further processing is required @@ -341,9 +341,9 @@ pub(crate) fn create_context_finish() -> Statement { Statement::Expression(method_call) } -///////////////////////////////////////////////////////////////////////// -/// Methods to create hasher inputs /// -///////////////////////////////////////////////////////////////////////// +// +// Methods to create hasher inputs +// fn add_struct_to_hasher(ident: &Ident) -> Statement { // If this is a struct, we call serialize and add the array to the hasher diff --git a/crates/noirc_frontend/src/lexer/lexer.rs b/crates/noirc_frontend/src/lexer/lexer.rs index 194c5788268..3d436694fc8 100644 --- a/crates/noirc_frontend/src/lexer/lexer.rs +++ b/crates/noirc_frontend/src/lexer/lexer.rs @@ -489,18 +489,6 @@ mod tests { ); } - #[test] - fn custom_attribute() { - let input = r#"#[custom(hello)]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next().unwrap().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Custom("custom(hello)".to_string().into())) - ); - } - #[test] fn test_custom_gate_syntax() { let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; @@ -518,27 +506,6 @@ mod tests { } } - #[test] - fn deprecated_attribute() { - let input = r#"#[deprecated]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next().unwrap().unwrap(); - assert_eq!(token.token(), &Token::Attribute(Attribute::Deprecated(None))); - } - - #[test] - fn deprecated_attribute_with_note() { - let input = r#"#[deprecated("hello")]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next().unwrap().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Deprecated("hello".to_string().into())) - ); - } - #[test] fn custom_attribute() { let input = r#"#[custom(hello)]"#; @@ -588,23 +555,6 @@ mod tests { assert_eq!(sub_string, "test(invalid_scope)"); } - #[test] - fn test_custom_gate_syntax() { - let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; - - let expected = vec![ - Token::Attribute(Attribute::Foreign("sha256".to_string())), - Token::Attribute(Attribute::Foreign("blake2s".to_string())), - Token::Attribute(Attribute::Builtin("sum".to_string())), - ]; - - let mut lexer = Lexer::new(input); - for token in expected.into_iter() { - let got = lexer.next_token().unwrap(); - assert_eq!(got, token); - } - } - #[test] fn test_int_type() { let input = "u16 i16 i108 u104.5"; From 84e0a2c502a2de75efadbc099c37308923e0a848 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:37:52 +0000 Subject: [PATCH 20/21] fix: reenable flags after fixes --- crates/noirc_frontend/src/hir/def_map/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/noirc_frontend/src/hir/def_map/mod.rs b/crates/noirc_frontend/src/hir/def_map/mod.rs index 379a74a440e..66a65c09157 100644 --- a/crates/noirc_frontend/src/hir/def_map/mod.rs +++ b/crates/noirc_frontend/src/hir/def_map/mod.rs @@ -18,7 +18,7 @@ pub use module_data::*; mod namespace; pub use namespace::*; -// #[cfg(feature = "aztec")] +#[cfg(feature = "aztec")] mod aztec_library; /// The name that is used for a non-contract program's entry-point function. @@ -88,7 +88,7 @@ impl CrateDefMap { let root_file_id = context.crate_graph[crate_id].root_file_id; let ast = parse_file(&mut context.file_manager, root_file_id, errors); - // #[cfg(feature = "aztec")] + #[cfg(feature = "aztec")] let ast = aztec_library::transform(ast); // Allocate a default Module for the root, giving it a ModuleId From 32278cc13a90ac111a2c33b8dbd44a513b70dd00 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 29 Aug 2023 08:58:39 -0500 Subject: [PATCH 21/21] Update crates/noirc_frontend/src/hir/def_map/aztec_library.rs --- crates/noirc_frontend/src/hir/def_map/aztec_library.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs index 4b27f5fe98e..420a1036f4b 100644 --- a/crates/noirc_frontend/src/hir/def_map/aztec_library.rs +++ b/crates/noirc_frontend/src/hir/def_map/aztec_library.rs @@ -169,7 +169,7 @@ fn transform_function(ty: &str, func: &mut NoirFunction) { func.def.return_visibility = Visibility::Public; // Distinct return types are only required for private functions - if ty.eq("Private") { + if ty == "Private" { func.def.return_distinctness = Distinctness::Distinct; } }