From e22a5cbc92bf219e1c169f029e6e7bdaec7af4a0 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 07:51:37 +0000 Subject: [PATCH 1/9] WIP --- yarn-project/aztec-nr/field-note/Nargo.toml | 8 ++ .../aztec-nr/field-note/src/field_note.nr | 121 ++++++++++++++++++ yarn-project/aztec-nr/field-note/src/lib.nr | 1 + 3 files changed, 130 insertions(+) create mode 100644 yarn-project/aztec-nr/field-note/Nargo.toml create mode 100644 yarn-project/aztec-nr/field-note/src/field_note.nr create mode 100644 yarn-project/aztec-nr/field-note/src/lib.nr diff --git a/yarn-project/aztec-nr/field-note/Nargo.toml b/yarn-project/aztec-nr/field-note/Nargo.toml new file mode 100644 index 00000000000..1d50983678b --- /dev/null +++ b/yarn-project/aztec-nr/field-note/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "address_note" +authors = ["aztec-labs"] +compiler_version = "0.7.1" +type = "lib" + +[dependencies] +aztec = { path = "../aztec" } \ No newline at end of file diff --git a/yarn-project/aztec-nr/field-note/src/field_note.nr b/yarn-project/aztec-nr/field-note/src/field_note.nr new file mode 100644 index 00000000000..7712d1080e2 --- /dev/null +++ b/yarn-project/aztec-nr/field-note/src/field_note.nr @@ -0,0 +1,121 @@ +use dep::aztec::{ + note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, + }, + oracle::{ + rand::rand, + get_secret_key::get_secret_key, + get_public_key::get_public_key, + }, + log::emit_encrypted_log, + hash::pedersen_hash, + context::PrivateContext, +}; + +global FIELD_NOTE_LEN: Field = 3; + +// Stores a field +struct FieldNote { + value: Field, + owner: Field, + randomness: Field, + header: NoteHeader, +} + +impl FieldNote { + pub fn new(value: Field, owner: Field) -> Self { + let randomness = rand(); + FieldNote { + value, + owner, + randomness, + header: NoteHeader::empty(), + } + } + + pub fn serialize(self) -> [Field; FIELD_NOTE_LEN]{ + [self.address, self.owner, self.randomness] + } + + pub fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> Self { + FieldNote { + address: preimage[0], + owner: preimage[1], + randomness: preimage[2], + header: NoteHeader::empty(), + } + } + + pub fn compute_note_hash(self) -> Field { + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash(self.serialize(), 0) + } + + pub fn compute_nullifier(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(FieldNoteMethods, self); + let secret = get_secret_key(self.owner); + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash([ + note_hash_for_nullify, + secret.low, + secret.high, + ], 0) + } + + pub fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + // Broadcasts the note as an encrypted log on L1. + pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + let encryption_pub_key = get_public_key(self.owner); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + encryption_pub_key, + self.serialize(), + ); + } +} + +fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> FieldNote { + FieldNote::deserialize(preimage) +} + +fn serialize(note: FieldNote) -> [Field; FIELD_NOTE_LEN]{ + note.serialize() +} + +fn compute_note_hash(note: FieldNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: FieldNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: FieldNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut FieldNote, header: NoteHeader) { + note.set_header(header); +} + +// Broadcasts the note as an encrypted log on L1. +fn broadcast(context: &mut PrivateContext, slot: Field, note: FieldNote) { + note.broadcast(context, slot); +} + +global FieldNoteMethods = NoteInterface { + deserialize, + serialize, + compute_note_hash, + compute_nullifier, + get_header, + set_header, + broadcast, +}; diff --git a/yarn-project/aztec-nr/field-note/src/lib.nr b/yarn-project/aztec-nr/field-note/src/lib.nr new file mode 100644 index 00000000000..f016584e48c --- /dev/null +++ b/yarn-project/aztec-nr/field-note/src/lib.nr @@ -0,0 +1 @@ +mod address_note; \ No newline at end of file From f4d5f102c3c687c57d862b763e0c592bd30c8a22 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 14:04:01 +0000 Subject: [PATCH 2/9] WIP --- .../aztec-nr/field-note/src/field_note.nr | 44 +++---------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/yarn-project/aztec-nr/field-note/src/field_note.nr b/yarn-project/aztec-nr/field-note/src/field_note.nr index 7712d1080e2..b8f54f26488 100644 --- a/yarn-project/aztec-nr/field-note/src/field_note.nr +++ b/yarn-project/aztec-nr/field-note/src/field_note.nr @@ -2,48 +2,34 @@ use dep::aztec::{ note::{ note_header::NoteHeader, note_interface::NoteInterface, - utils::compute_note_hash_for_read_or_nullify, }, - oracle::{ - rand::rand, - get_secret_key::get_secret_key, - get_public_key::get_public_key, - }, - log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext, }; -global FIELD_NOTE_LEN: Field = 3; +global FIELD_NOTE_LEN: Field = 1; // Stores a field struct FieldNote { value: Field, - owner: Field, - randomness: Field, header: NoteHeader, } impl FieldNote { pub fn new(value: Field, owner: Field) -> Self { - let randomness = rand(); FieldNote { value, - owner, - randomness, header: NoteHeader::empty(), } } pub fn serialize(self) -> [Field; FIELD_NOTE_LEN]{ - [self.address, self.owner, self.randomness] + [self.value] } pub fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> Self { FieldNote { - address: preimage[0], - owner: preimage[1], - randomness: preimage[2], + value: preimage[0], header: NoteHeader::empty(), } } @@ -54,31 +40,12 @@ impl FieldNote { } pub fn compute_nullifier(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(FieldNoteMethods, self); - let secret = get_secret_key(self.owner); - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash([ - note_hash_for_nullify, - secret.low, - secret.high, - ], 0) + 0 } pub fn set_header(&mut self, header: NoteHeader) { self.header = header; } - - // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { - let encryption_pub_key = get_public_key(self.owner); - emit_encrypted_log( - context, - (*context).this_address(), - slot, - encryption_pub_key, - self.serialize(), - ); - } } fn deserialize(preimage: [Field; FIELD_NOTE_LEN]) -> FieldNote { @@ -105,9 +72,8 @@ fn set_header(note: &mut FieldNote, header: NoteHeader) { note.set_header(header); } -// Broadcasts the note as an encrypted log on L1. fn broadcast(context: &mut PrivateContext, slot: Field, note: FieldNote) { - note.broadcast(context, slot); + assert(false, "FieldNote does not support broadcast"); } global FieldNoteMethods = NoteInterface { From 39c3035861138616c9001316c448f0ff3517087a Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 14:39:55 +0000 Subject: [PATCH 3/9] WIP --- yarn-project/aztec-nr/field-note/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-nr/field-note/Nargo.toml b/yarn-project/aztec-nr/field-note/Nargo.toml index 1d50983678b..a00c3f2c582 100644 --- a/yarn-project/aztec-nr/field-note/Nargo.toml +++ b/yarn-project/aztec-nr/field-note/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "address_note" +name = "field_note" authors = ["aztec-labs"] compiler_version = "0.7.1" type = "lib" From 7583564a1395d08475b63132888d5256fd8bb7e5 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 15:00:16 +0000 Subject: [PATCH 4/9] final touches --- yarn-project/aztec-nr/field-note/src/field_note.nr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-nr/field-note/src/field_note.nr b/yarn-project/aztec-nr/field-note/src/field_note.nr index b8f54f26488..89553046ccd 100644 --- a/yarn-project/aztec-nr/field-note/src/field_note.nr +++ b/yarn-project/aztec-nr/field-note/src/field_note.nr @@ -9,7 +9,9 @@ use dep::aztec::{ global FIELD_NOTE_LEN: Field = 1; -// Stores a field +// A note which stores a field and is expected to be passed around using the `addNote` function. +// WARNING: This Note is not private as it does not contain randomness and hence it can be easy to perform preimage +// attack on it. struct FieldNote { value: Field, header: NoteHeader, @@ -40,6 +42,7 @@ impl FieldNote { } pub fn compute_nullifier(self) -> Field { + // This note is expected to be shared between users and for this reason can't be nullified using a secret. 0 } @@ -73,7 +76,7 @@ fn set_header(note: &mut FieldNote, header: NoteHeader) { } fn broadcast(context: &mut PrivateContext, slot: Field, note: FieldNote) { - assert(false, "FieldNote does not support broadcast"); + assert(false, "FieldNote does not support broadcast. Add it to PXE directly using the `.addNote` function."); } global FieldNoteMethods = NoteInterface { From 29eae853990d87750d23b30e8d4cb11328772eb9 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 15:02:24 +0000 Subject: [PATCH 5/9] removed unused dependency --- .../noir-contracts/src/contracts/token_contract/Nargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/token_contract/Nargo.toml index 1da51baf184..860f56f4b40 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/Nargo.toml +++ b/yarn-project/noir-contracts/src/contracts/token_contract/Nargo.toml @@ -6,6 +6,5 @@ type = "contract" [dependencies] aztec = { path = "../../../../aztec-nr/aztec" } -value_note = { path = "../../../../aztec-nr/value-note"} safe_math = { path = "../../../../aztec-nr/safe-math" } authwit = { path = "../../../../aztec-nr/authwit" } \ No newline at end of file From 208bbc34332dd24fadbcebb86ed9a4bbc02f15d5 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 25 Oct 2023 15:21:12 +0000 Subject: [PATCH 6/9] fixes --- yarn-project/aztec-nr/field-note/src/field_note.nr | 2 +- yarn-project/aztec-nr/field-note/src/lib.nr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-nr/field-note/src/field_note.nr b/yarn-project/aztec-nr/field-note/src/field_note.nr index 89553046ccd..845dd0cea59 100644 --- a/yarn-project/aztec-nr/field-note/src/field_note.nr +++ b/yarn-project/aztec-nr/field-note/src/field_note.nr @@ -18,7 +18,7 @@ struct FieldNote { } impl FieldNote { - pub fn new(value: Field, owner: Field) -> Self { + pub fn new(value: Field) -> Self { FieldNote { value, header: NoteHeader::empty(), diff --git a/yarn-project/aztec-nr/field-note/src/lib.nr b/yarn-project/aztec-nr/field-note/src/lib.nr index f016584e48c..2625d3a2277 100644 --- a/yarn-project/aztec-nr/field-note/src/lib.nr +++ b/yarn-project/aztec-nr/field-note/src/lib.nr @@ -1 +1 @@ -mod address_note; \ No newline at end of file +mod field_note; \ No newline at end of file From 948310a03fd5639239f1df0ec06f95ebbe6dd03e Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 30 Oct 2023 11:03:17 +0000 Subject: [PATCH 7/9] no camel case in test contract --- .../import_test_contract/src/main.nr | 16 ++-- .../contracts/test_contract/src/interface.nr | 76 +++++++++---------- .../src/contracts/test_contract/src/main.nr | 60 +++++++-------- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr index 11247b403b6..599a28218fb 100644 --- a/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/import_test_contract/src/main.nr @@ -32,15 +32,15 @@ contract ImportTest { true, 1 as u32, [1, 2], - AStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + AStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, ADeepStructTestCodeGenStruct { - aField: 1, - aBool: true, - aNote: ANoteADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, - manyNotes: [ - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secretHash: 2 }, + a_field: 1, + a_bool: true, + a_note: ANoteADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, + many_notes: [ + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, + ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, ] } ); diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr index 66b6bd143d4..589fc69f397 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr @@ -6,24 +6,24 @@ use dep::aztec::constants_gen::RETURN_VALUES_LENGTH; struct AStructTestCodeGenStruct { amount: Field, - secretHash: Field, + secret_hash: Field, } struct ADeepStructTestCodeGenStruct { - aField: Field, - aBool: bool, - aNote: ANoteADeepStructTestCodeGenStruct, - manyNotes: [ManyNotesADeepStructTestCodeGenStruct;3], + a_field: Field, + a_bool: bool, + a_note: ANoteADeepStructTestCodeGenStruct, + many_notes: [ManyNotesADeepStructTestCodeGenStruct;3], } struct ANoteADeepStructTestCodeGenStruct { amount: Field, - secretHash: Field, + secret_hash: Field, } struct ManyNotesADeepStructTestCodeGenStruct { amount: Field, - secretHash: Field, + secret_hash: Field, } @@ -83,11 +83,11 @@ impl TestPrivateContextInterface { self, context: &mut PrivateContext, amount: Field, - secretHash: Field + secret_hash: Field ) { let mut serialized_args = [0; 2]; serialized_args[0] = amount; - serialized_args[1] = secretHash; + serialized_args[1] = secret_hash; context.call_public_function(self.address, 0x9749ca06, serialized_args) } @@ -97,11 +97,11 @@ impl TestPrivateContextInterface { self, context: &mut PrivateContext, amount: Field, - secretHash: Field + secret_hash: Field ) { let mut serialized_args = [0; 2]; serialized_args[0] = amount; - serialized_args[1] = secretHash; + serialized_args[1] = secret_hash; context.call_public_function(self.address, 0xdf02db8d, serialized_args) } @@ -200,31 +200,31 @@ impl TestPrivateContextInterface { pub fn test_code_gen( self, context: &mut PrivateContext, - aField: Field, - aBool: bool, - aNumber: u32, - anArray: [Field;2], - aStruct: AStructTestCodeGenStruct, - aDeepStruct: ADeepStructTestCodeGenStruct + a_field: Field, + a_bool: bool, + a_number: u32, + an_array: [Field;2], + a_struct: AStructTestCodeGenStruct, + a_deep_struct: ADeepStructTestCodeGenStruct ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialized_args = [0; 17]; - serialized_args[0] = aField; - serialized_args[1] = aBool as Field; - serialized_args[2] = aNumber as Field; - serialized_args[3] = anArray[0]; - serialized_args[4] = anArray[1]; - serialized_args[5] = aStruct.amount; - serialized_args[6] = aStruct.secretHash; - serialized_args[7] = aDeepStruct.aField; - serialized_args[8] = aDeepStruct.aBool as Field; - serialized_args[9] = aDeepStruct.aNote.amount; - serialized_args[10] = aDeepStruct.aNote.secretHash; - serialized_args[11] = aDeepStruct.manyNotes[0].amount; - serialized_args[12] = aDeepStruct.manyNotes[0].secretHash; - serialized_args[13] = aDeepStruct.manyNotes[1].amount; - serialized_args[14] = aDeepStruct.manyNotes[1].secretHash; - serialized_args[15] = aDeepStruct.manyNotes[2].amount; - serialized_args[16] = aDeepStruct.manyNotes[2].secretHash; + serialized_args[0] = a_field; + serialized_args[1] = a_bool as Field; + serialized_args[2] = a_number as Field; + serialized_args[3] = an_array[0]; + serialized_args[4] = an_array[1]; + serialized_args[5] = a_struct.amount; + serialized_args[6] = a_struct.secret_hash; + serialized_args[7] = a_deep_struct.a_field; + serialized_args[8] = a_deep_struct.a_bool as Field; + serialized_args[9] = a_deep_struct.a_note.amount; + serialized_args[10] = a_deep_struct.a_note.secret_hash; + serialized_args[11] = a_deep_struct.many_notes[0].amount; + serialized_args[12] = a_deep_struct.many_notes[0].secret_hash; + serialized_args[13] = a_deep_struct.many_notes[1].amount; + serialized_args[14] = a_deep_struct.many_notes[1].secret_hash; + serialized_args[15] = a_deep_struct.many_notes[2].amount; + serialized_args[16] = a_deep_struct.many_notes[2].secret_hash; context.call_private_function(self.address, 0x0f054f9b, serialized_args) } @@ -270,11 +270,11 @@ impl TestPublicContextInterface { self, context: PublicContext, amount: Field, - secretHash: Field + secret_hash: Field ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialized_args = [0; 2]; serialized_args[0] = amount; - serialized_args[1] = secretHash; + serialized_args[1] = secret_hash; context.call_public_function(self.address, 0x9749ca06, serialized_args) } @@ -284,11 +284,11 @@ impl TestPublicContextInterface { self, context: PublicContext, amount: Field, - secretHash: Field + secret_hash: Field ) -> [Field; RETURN_VALUES_LENGTH] { let mut serialized_args = [0; 2]; serialized_args[0] = amount; - serialized_args[1] = secretHash; + serialized_args[1] = secret_hash; context.call_public_function(self.address, 0xdf02db8d, serialized_args) } diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr index 329b67abf99..3b50aa2154a 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr @@ -64,27 +64,27 @@ contract Test { // Note; this function is deliberately NOT annotated with #[aztec(private)] due to its use in tests fn test_code_gen( inputs: PrivateContextInputs, - aField: Field, - aBool: bool, - aNumber: u32, - anArray: [Field; 2], - aStruct: DummyNote, - aDeepStruct: DeepStruct, + a_field: Field, + a_bool: bool, + a_number: u32, + an_array: [Field; 2], + a_struct: DummyNote, + a_deep_struct: DeepStruct, ) -> distinct pub abi::PrivateCircuitPublicInputs { let mut args: BoundedVec = BoundedVec::new(0); - args.push(aField); - args.push(aBool as Field); - args.push(aNumber as Field); - args.push_array(anArray); - args.push(aStruct.amount); - args.push(aStruct.secretHash); - args.push(aDeepStruct.aField); - args.push(aDeepStruct.aBool as Field); - args.push(aDeepStruct.aNote.amount); - args.push(aDeepStruct.aNote.secretHash); - for note in aDeepStruct.manyNotes { + args.push(a_field); + args.push(a_bool as Field); + args.push(a_number as Field); + args.push_array(an_array); + args.push(a_struct.amount); + args.push(a_struct.secret_hash); + args.push(a_deep_struct.a_field); + args.push(a_deep_struct.a_bool as Field); + args.push(a_deep_struct.a_note.amount); + args.push(a_deep_struct.a_note.secret_hash); + for note in a_deep_struct.many_notes { args.push(note.amount); - args.push(note.secretHash); + args.push(note.secret_hash); } let args_hash = abi::hash_args(args.storage); let mut context = PrivateContext::new(inputs, args_hash); @@ -96,10 +96,10 @@ contract Test { #[aztec(public)] fn create_l2_to_l1_message_public( amount: Field, - secretHash: Field, + secret_hash: Field, ) { // Create a commitment to the amount - let note = DummyNote::new(amount, secretHash); + let note = DummyNote::new(amount, secret_hash); // Public oracle call to emit new commitment. context.message_portal(note.get_commitment()); @@ -110,10 +110,10 @@ contract Test { #[aztec(public)] fn create_nullifier_public( amount: Field, - secretHash: Field, + secret_hash: Field, ) { // Create a commitment to the amount - let note = DummyNote::new(amount, secretHash); + let note = DummyNote::new(amount, secret_hash); // Public oracle call to emit new commitment. context.push_new_nullifier(note.get_commitment(), EMPTY_NULLIFIED_COMMITMENT); @@ -186,26 +186,26 @@ contract Test { struct DummyNote { amount: Field, - secretHash: Field + secret_hash: Field } impl DummyNote { - fn new(amount: Field, secretHash: Field) -> pub Self { + fn new(amount: Field, secret_hash: Field) -> pub Self { Self { amount: amount, - secretHash: secretHash + secret_hash: secret_hash } } fn get_commitment(self) -> pub Field { - pedersen_hash([self.amount, self.secretHash],0) + pedersen_hash([self.amount, self.secret_hash],0) } } struct DeepStruct { - aField: Field, - aBool: bool, - aNote: DummyNote, - manyNotes: [DummyNote; 3], + a_field: Field, + a_bool: bool, + a_note: DummyNote, + many_notes: [DummyNote; 3], } } From 37eb228ef521f8987ddd4e5e230fddbdea188e18 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 30 Oct 2023 13:51:04 +0000 Subject: [PATCH 8/9] using and testing FieldNote --- .../src/e2e_non_contract_account.test.ts | 24 ++++++++++- .../src/contracts/test_contract/Nargo.toml | 1 + .../contracts/test_contract/src/interface.nr | 12 ++++++ .../src/contracts/test_contract/src/main.nr | 43 +++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts index a5b5fe1d0c0..895646a9e95 100644 --- a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts +++ b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts @@ -4,7 +4,7 @@ import { siloNullifier } from '@aztec/circuits.js/abis'; import { DebugLogger } from '@aztec/foundation/log'; import { toBigInt } from '@aztec/foundation/serialize'; import { TestContract } from '@aztec/noir-contracts/types'; -import { AztecNode, PXE, TxStatus } from '@aztec/types'; +import { AztecNode, NotePreimage, PXE, TxStatus } from '@aztec/types'; import { setup } from './fixtures/utils.js'; @@ -17,9 +17,9 @@ describe('e2e_non_contract_account', () => { let logger: DebugLogger; let contract: TestContract; + let wallet: Wallet; beforeEach(async () => { - let wallet: Wallet; ({ teardown, aztecNode, pxe, wallet, logger } = await setup(1)); nonContractAccountWallet = new SignerlessWallet(pxe); @@ -59,4 +59,24 @@ describe('e2e_non_contract_account', () => { const msgSender = toBigInt(logs[0].log.data); expect(msgSender).toBe(0n); }, 120_000); + + // Note: This test doesn't really belong here as it doesn't have anything to do with non-contract accounts. I needed + // to test the FieldNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this + // seems wasteful. Move this test if a better place is found. + it('can set and get a constant', async () => { + const value = 123n; + + const receipt = await contract.methods.set_constant(value).send().wait({ interval: 0.1 }); + + // check that 1 commitment was created + const tx = await pxe.getTx(receipt.txHash); + const nonZeroCommitments = tx?.newCommitments.filter(c => c.value > 0); + expect(nonZeroCommitments?.length).toBe(1); + + // Add the note + const preimage = new NotePreimage([new Fr(value)]); + await wallet.addNote(wallet.getCompleteAddress().address, contract.address, new Fr(1), preimage, receipt.txHash); + + expect(await contract.methods.get_constant().view()).toEqual(value); + }); }); diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/test_contract/Nargo.toml index afa5e911ac9..be62c146701 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/Nargo.toml +++ b/yarn-project/noir-contracts/src/contracts/test_contract/Nargo.toml @@ -6,4 +6,5 @@ type = "contract" [dependencies] aztec = { path = "../../../../aztec-nr/aztec" } +field_note = { path = "../../../../aztec-nr/field-note" } token_portal_content_hash_lib = { path = "../token_portal_content_hash_lib" } diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr index 589fc69f397..1bb62e9f3f6 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/interface.nr @@ -197,6 +197,18 @@ impl TestPrivateContextInterface { } + pub fn set_constant( + self, + context: &mut PrivateContext, + value: Field + ) -> [Field; RETURN_VALUES_LENGTH] { + let mut serialized_args = [0; 1]; + serialized_args[0] = value; + + context.call_private_function(self.address, 0x1b3b9e18, serialized_args) + } + + pub fn test_code_gen( self, context: &mut PrivateContext, diff --git a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr index 3b50aa2154a..b22de0d2894 100644 --- a/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/test_contract/src/main.nr @@ -1,30 +1,51 @@ // A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests. contract Test { + use dep::std::option::Option; + // docs:start:unencrypted_import use dep::aztec::log::emit_unencrypted_log; // docs:end:unencrypted_import use dep::aztec::{ + context::Context, abi, abi::PrivateContextInputs, hash::pedersen_hash, context::PrivateContext, + note::{ + note_header::NoteHeader, + utils as note_utils, + }, oracle::{ get_public_key::get_public_key as get_public_key_oracle, context::get_portal_address, rand::rand }, + state_vars::immutable_singleton::ImmutableSingleton, log::emit_unencrypted_log_from_private, types::vec::BoundedVec, constants_gen::EMPTY_NULLIFIED_COMMITMENT, }; use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash}; + use dep::field_note::field_note::{FieldNote, FieldNoteMethods, FIELD_NOTE_LEN}; #[event] struct ExampleEvent { value: Field, } + struct Storage { + example_constant: ImmutableSingleton, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + example_constant: ImmutableSingleton::new(context, 1, FieldNoteMethods), + } + } + } + #[aztec(private)] // docs:start:empty-constructor fn constructor() {} @@ -177,6 +198,19 @@ contract Test { context.consume_l1_to_l2_message(msg_key, content_hash, secret_for_L1_to_L2_message_consumption); } + #[aztec(private)] + fn set_constant( + value: Field, + ) { + let mut note = FieldNote::new(value); + storage.example_constant.initialize(&mut note, Option::none(), false); + } + + unconstrained fn get_constant() -> Field { + let constant = storage.example_constant.view_note(); + constant.value + } + // Purely exists for testing unconstrained fn get_random( kindaSeed: Field @@ -208,4 +242,13 @@ contract Test { a_note: DummyNote, many_notes: [DummyNote; 3], } + + // Computes note hash and nullifier. + // Note 1: Needs to be defined by every contract producing logs. + // Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. + unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; FIELD_NOTE_LEN]) -> [Field; 4] { + assert(storage_slot == 1); + let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + note_utils::compute_note_hash_and_nullifier(FieldNoteMethods, note_header, preimage) + } } From 176c2a1918c8ad0dae6f9267d345de81dcc4ab27 Mon Sep 17 00:00:00 2001 From: benesjan Date: Mon, 30 Oct 2023 14:32:44 +0000 Subject: [PATCH 9/9] fix --- .../acir-simulator/src/client/private_execution.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts index 4b089fa49b9..aee54d0da7c 100644 --- a/yarn-project/acir-simulator/src/client/private_execution.test.ts +++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts @@ -387,8 +387,10 @@ describe('Private Execution test suite', () => { beforeAll(async () => { // These args should match the ones hardcoded in importer contract - const dummyNote = { amount: 1, secretHash: 2 }; - const deepStruct = { aField: 1, aBool: true, aNote: dummyNote, manyNotes: [dummyNote, dummyNote, dummyNote] }; + // eslint-disable-next-line camelcase + const dummyNote = { amount: 1, secret_hash: 2 }; + // eslint-disable-next-line camelcase + const deepStruct = { a_field: 1, a_bool: true, a_note: dummyNote, many_notes: [dummyNote, dummyNote, dummyNote] }; args = [1, true, 1, [1, 2], dummyNote, deepStruct]; testCodeGenArtifact = getFunctionArtifact(TestContractArtifact, 'test_code_gen'); const serializedArgs = encodeArguments(testCodeGenArtifact, args);