From 2e5e43a399b3a952e6284877b9931949b808b0b2 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 15:19:52 +0000 Subject: [PATCH 1/9] chore: initial storage cleanup --- barretenberg/build-system | 1 + .../aztec-nr/aztec/src/types/address.nr | 4 + .../aztec/src/types/type_serialization.nr | 1 + .../aztec_address_serialization.nr | 17 +++ .../aztec-nr/safe-math/src/safe_u120.nr | 54 +++++++ .../src/contracts/token_contract/src/main.nr | 132 ++++++++-------- .../src/contracts/token_contract/src/types.nr | 134 +---------------- .../token_contract/src/types/balance_set.nr | 128 ++++++++++++++++ .../src/types/safe_u120_serialization.nr | 18 +++ .../token_contract/src/types/token_note.nr | 142 ++++++++++++++++++ .../src/types/transparent_note.nr | 129 ++++++++++++++++ 11 files changed, 564 insertions(+), 196 deletions(-) create mode 160000 barretenberg/build-system create mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/aztec_address_serialization.nr create mode 100644 yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr create mode 100644 yarn-project/noir-contracts/src/contracts/token_contract/src/types/safe_u120_serialization.nr create mode 100644 yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr create mode 100644 yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr diff --git a/barretenberg/build-system b/barretenberg/build-system new file mode 160000 index 00000000000..a109f3aef28 --- /dev/null +++ b/barretenberg/build-system @@ -0,0 +1 @@ +Subproject commit a109f3aef28cea4a50481cdf2d74fc3909212c0b diff --git a/yarn-project/aztec-nr/aztec/src/types/address.nr b/yarn-project/aztec-nr/aztec/src/types/address.nr index 6849767b8d0..79a8f1bd343 100644 --- a/yarn-project/aztec-nr/aztec/src/types/address.nr +++ b/yarn-project/aztec-nr/aztec/src/types/address.nr @@ -9,6 +9,10 @@ impl AztecAddress { } } + fn eq(self: Self, other: Self) -> bool { + self.address == other.address + } + fn serialize(self: Self) -> [Field; 1] { [self.address] } diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr index b45dcd7c855..b1bb9651ba6 100644 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr +++ b/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr @@ -1,6 +1,7 @@ mod bool_serialization; mod field_serialization; mod u32_serialization; +mod aztec_address_serialization; /** * Before Noir supports traits, a way of specifying the serialization and deserialization methods for a type. diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/aztec_address_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/aztec_address_serialization.nr new file mode 100644 index 00000000000..8ce68ec513f --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/types/type_serialization/aztec_address_serialization.nr @@ -0,0 +1,17 @@ +use crate::types::type_serialization::TypeSerializationInterface; +use crate::types::address::AztecAddress; + +global AZTEC_ADDRESS_SERIALIZED_LEN: Field = 1; + +fn deserialize(fields: [Field; AZTEC_ADDRESS_SERIALIZED_LEN]) -> AztecAddress { + AztecAddress::new(fields[0]) +} + +fn serialize(value: AztecAddress) -> [Field; AZTEC_ADDRESS_SERIALIZED_LEN] { + [value.address] +} + +global AztecAddressSerializationMethods = TypeSerializationInterface { + deserialize, + serialize, +}; \ No newline at end of file diff --git a/yarn-project/aztec-nr/safe-math/src/safe_u120.nr b/yarn-project/aztec-nr/safe-math/src/safe_u120.nr index 5feeb3cca23..a36c05ac3cd 100644 --- a/yarn-project/aztec-nr/safe-math/src/safe_u120.nr +++ b/yarn-project/aztec-nr/safe-math/src/safe_u120.nr @@ -41,6 +41,22 @@ impl SafeU120 { self.value == other.value } + fn lt(self: Self, other: Self) -> bool { + self.value < other.value + } + + fn le(self: Self, other: Self) -> bool { + self.value <= other.value + } + + fn gt(self: Self, other: Self) -> bool { + self.value > other.value + } + + fn ge(self: Self, other: Self) -> bool { + self.value >= other.value + } + fn sub( self: Self, b: Self, @@ -139,6 +155,44 @@ fn test_eq() { assert(a.eq(b)); } +#[test] +fn test_lt() { + let a = SafeU120::new(1); + let b = SafeU120::new(2); + assert(a.lt(b)); + assert(b.lt(a) == false); +} + + +#[test] +fn test_le() { + let a = SafeU120::new(2); + let b = SafeU120::new(2); + let c = SafeU120::new(5); + assert(a.le(b)); + assert(a.le(c)); + assert(c.le(a) == false); +} + +#[test] +fn test_gt() { + let a = SafeU120::new(1); + let b = SafeU120::new(2); + assert(b.gt(a)); + assert(a.gt(b) == false); +} + + +#[test] +fn test_ge() { + let a = SafeU120::new(2); + let b = SafeU120::new(2); + let c = SafeU120::new(5); + assert(a.ge(b)); + assert(a.ge(c) == false); + assert(c.ge(a)); +} + #[test(should_fail)] fn test_init_too_large() { let b = SafeU120::max().value as Field + 1; // max + 1 diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr index f9871004b29..4f5dae986a0 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr @@ -16,12 +16,6 @@ contract Token { use dep::safe_math::SafeU120; - use dep::value_note::{ - balance_utils, - utils::{increment, decrement}, - value_note::{VALUE_NOTE_LEN, ValueNoteMethods, ValueNote}, - }; - use dep::aztec::{ note::{ note_header::NoteHeader, @@ -29,47 +23,53 @@ contract Token { }, context::{PrivateContext, PublicContext, Context}, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::field_serialization::{ - FieldSerializationMethods, FIELD_SERIALIZED_LEN, + types::type_serialization::{ + field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, + bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN}, + aztec_address_serialization::{AztecAddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, }, types::address::{AztecAddress}, oracle::compute_selector::compute_selector, auth::{assert_valid_message_for, assert_valid_public_message_for} }; - use crate::types::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}; + use crate::types::{ + transparent_note::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}, + token_note::{TokenNote, TokenNoteMethods, TOKEN_NOTE_LEN}, + balance_set::{BalanceSet}, + safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN} + }; use crate::util::{compute_message_hash}; // docs:end::imports // docs:start:storage_struct struct Storage { - // docs:start:storage_admin - admin: PublicState, + admin: PublicState, // docs:end:storage_admin // docs:start:storage_minters - minters: Map>, + minters: Map>, // docs:end:storage_minters // docs:start:storage_balances - balances: Map>, + balances: Map, // docs:end:storage_balances - total_supply: PublicState, + total_supply: PublicState, // docs:start:storage_pending_shields pending_shields: Set, // docs:end:storage_pending_shields - public_balances: Map>, + public_balances: Map>, } // docs:end:storage_struct // docs:start:storage_init impl Storage { - fn init(context: Context) -> pub Self { + fn init(context: Context) -> Self { Storage { // docs:start:storage_admin_init admin: PublicState::new( context, 1, - FieldSerializationMethods, + AztecAddressSerializationMethods, ), // docs:end:storage_admin_init // docs:start:storage_minters_init @@ -80,7 +80,7 @@ contract Token { PublicState::new( context, slot, - FieldSerializationMethods, + BoolSerializationMethods, ) }, ), @@ -89,13 +89,13 @@ contract Token { context, 3, |context, slot| { - Set::new(context, slot, ValueNoteMethods) + BalanceSet::new(context, slot) }, ), total_supply: PublicState::new( context, 4, - FieldSerializationMethods, + SafeU120SerializationMethods, ), // docs:start:storage_pending_shields_init pending_shields: Set::new(context, 5, TransparentNoteMethods), @@ -107,7 +107,7 @@ contract Token { PublicState::new( context, slot, - FieldSerializationMethods, + SafeU120SerializationMethods, ) }, ), @@ -130,9 +130,9 @@ contract Token { fn set_admin( new_admin: AztecAddress, ) { - assert(storage.admin.read() == context.msg_sender(), "caller is not admin"); + assert(storage.admin.read().eq(AztecAddress::new(context.msg_sender())), "caller is not admin"); // docs:start:write_admin - storage.admin.write(new_admin.address); + storage.admin.write(new_admin); // docs:end:write_admin } // docs:end:set_admin @@ -144,10 +144,10 @@ contract Token { approve: bool, ) { // docs:start:read_admin - assert(storage.admin.read() == context.msg_sender(), "caller is not admin"); + assert(storage.admin.read().eq(AztecAddress::new(context.msg_sender())), "caller is not admin"); // docs:end:read_admin // docs:start:write_minter - storage.minters.at(minter.address).write(approve as Field); + storage.minters.at(minter.address).write(approve); // docs:end:write_minter } // docs:end:set_minter @@ -159,14 +159,14 @@ contract Token { amount: Field, ) -> Field { // docs:start:read_minter - assert(storage.minters.at(context.msg_sender()).read() == 1, "caller is not minter"); + assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); // docs:end:read_minter let amount = SafeU120::new(amount); - let new_balance = SafeU120::new(storage.public_balances.at(to.address).read()).add(amount); - let supply = SafeU120::new(storage.total_supply.read()).add(amount); + let new_balance = storage.public_balances.at(to.address).read().add(amount); + let supply = storage.total_supply.read().add(amount); - storage.public_balances.at(to.address).write(new_balance.value as Field); - storage.total_supply.write(supply.value as Field); + storage.public_balances.at(to.address).write(new_balance); + storage.total_supply.write(supply); 1 } // docs:end:mint_public @@ -177,12 +177,12 @@ contract Token { amount: Field, secret_hash: Field, ) -> Field { - assert(storage.minters.at(context.msg_sender()).read() == 1, "caller is not minter"); + assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); let pending_shields = storage.pending_shields; let mut note = TransparentNote::new(amount, secret_hash); - let supply = SafeU120::new(storage.total_supply.read()).add(SafeU120::new(amount)); + let supply = storage.total_supply.read().add(SafeU120::new(amount)); - storage.total_supply.write(supply.value as Field); + storage.total_supply.write(supply); // docs:start:insert_from_public pending_shields.insert_from_public(&mut note); // docs:end:insert_from_public @@ -208,12 +208,12 @@ contract Token { } let amount = SafeU120::new(amount); - let from_balance = SafeU120::new(storage.public_balances.at(from.address).read()).sub(amount); + let from_balance = storage.public_balances.at(from.address).read().sub(amount); let pending_shields = storage.pending_shields; let mut note = TransparentNote::new(amount.value as Field, secret_hash); - storage.public_balances.at(from.address).write(from_balance.value as Field); + storage.public_balances.at(from.address).write(from_balance); pending_shields.insert_from_public(&mut note); 1 } @@ -236,11 +236,11 @@ contract Token { } let amount = SafeU120::new(amount); - let from_balance = SafeU120::new(storage.public_balances.at(from.address).read()).sub(amount); - storage.public_balances.at(from.address).write(from_balance.value as Field); + let from_balance = storage.public_balances.at(from.address).read().sub(amount); + storage.public_balances.at(from.address).write(from_balance); - let to_balance = SafeU120::new(storage.public_balances.at(to.address).read()).add(amount); - storage.public_balances.at(to.address).write(to_balance.value as Field); + let to_balance = storage.public_balances.at(to.address).read().add(amount); + storage.public_balances.at(to.address).write(to_balance); 1 } @@ -262,11 +262,11 @@ contract Token { } let amount = SafeU120::new(amount); - let from_balance = SafeU120::new(storage.public_balances.at(from.address).read()).sub(amount); - storage.public_balances.at(from.address).write(from_balance.value as Field); + let from_balance = storage.public_balances.at(from.address).read().sub(amount); + storage.public_balances.at(from.address).write(from_balance); - let new_supply = SafeU120::new(storage.total_supply.read()).sub(amount); - storage.total_supply.write(new_supply.value as Field); + let new_supply = storage.total_supply.read().sub(amount); + storage.total_supply.write(new_supply); 1 } @@ -286,7 +286,8 @@ contract Token { // docs:start:assert_contains_and_remove_publicly_created pending_shields.assert_contains_and_remove_publicly_created(&mut public_note); // docs:end:assert_contains_and_remove_publicly_created - increment(balance, amount, to.address); + + balance.add(SafeU120::new(amount), to.address); 1 } @@ -309,7 +310,7 @@ contract Token { } let from_balance = storage.balances.at(from.address); - decrement(from_balance, amount, from.address); + from_balance.sub(SafeU120::new(amount), from.address); let selector = compute_selector("_increase_public_balance((Field),Field)"); let _void = context.call_public_function(context.this_address(), selector, [to.address, amount]); @@ -337,8 +338,9 @@ contract Token { let from_balance = storage.balances.at(from.address); let to_balance = storage.balances.at(to.address); - decrement(from_balance, amount, from.address); - increment(to_balance, amount, to.address); + let amount = SafeU120::new(amount); + from_balance.sub(amount, from.address); + to_balance.add(amount, to.address); 1 } @@ -360,8 +362,7 @@ contract Token { } let from_balance = storage.balances.at(from.address); - - decrement(from_balance, amount, from.address); + from_balance.sub(SafeU120::new(amount), from.address); let selector = compute_selector("_reduce_total_supply(Field)"); let _void = context.call_public_function(context.this_address(), selector, [amount]); @@ -380,8 +381,8 @@ contract Token { fn _initialize( new_admin: AztecAddress, ) { - storage.admin.write(new_admin.address); - storage.minters.at(new_admin.address).write(1); + storage.admin.write(new_admin); + storage.minters.at(new_admin.address).write(true); } // docs:end:initialize @@ -393,8 +394,8 @@ contract Token { to: AztecAddress, amount: Field, ) { - let new_balance = SafeU120::new(storage.public_balances.at(to.address).read()).add(SafeU120::new(amount)); - storage.public_balances.at(to.address).write(new_balance.value as Field); + let new_balance = storage.public_balances.at(to.address).read().add(SafeU120::new(amount)); + storage.public_balances.at(to.address).write(new_balance); } // docs:end:increase_public_balance @@ -404,8 +405,8 @@ contract Token { amount: Field, ) { // Only to be called from burn. - let new_supply = SafeU120::new(storage.total_supply.read()).sub(SafeU120::new(amount)); - storage.total_supply.write(new_supply.value as Field); + let new_supply = storage.total_supply.read().sub(SafeU120::new(amount)); + storage.total_supply.write(new_supply); } // docs:end:reduce_total_supply @@ -413,7 +414,7 @@ contract Token { // docs:start:admin unconstrained fn admin() -> Field { - storage.admin.read() + storage.admin.read().address } // docs:end:admin @@ -421,31 +422,30 @@ contract Token { unconstrained fn is_minter( minter: AztecAddress, ) -> bool { - storage.minters.at(minter.address).read() as bool + storage.minters.at(minter.address).read() } // docs:end:is_minter // docs:start:total_supply - unconstrained fn total_supply() -> Field { - storage.total_supply.read() + unconstrained fn total_supply() -> u120 { + storage.total_supply.read().value } // docs:end:total_supply // docs:start:balance_of_private unconstrained fn balance_of_private( owner: AztecAddress, - ) -> Field { + ) -> u120 { let owner_balance = storage.balances.at(owner.address); - - balance_utils::get_balance(owner_balance) + owner_balance.balance_of().value } // docs:end:balance_of_private // docs:start:balance_of_public unconstrained fn balance_of_public( owner: AztecAddress, - ) -> Field { - storage.public_balances.at(owner.address).read() + ) -> u120 { + storage.public_balances.at(owner.address).read().value } // docs:end:balance_of_public @@ -456,12 +456,12 @@ contract Token { // 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; VALUE_NOTE_LEN]) -> [Field; 4] { + unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; TOKEN_NOTE_LEN]) -> [Field; 4] { let note_header = NoteHeader { contract_address, nonce, storage_slot }; if (storage_slot == 5) { note_utils::compute_note_hash_and_nullifier(TransparentNoteMethods, note_header, preimage) } else { - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) + note_utils::compute_note_hash_and_nullifier(TokenNoteMethods, note_header, preimage) } } // docs:end:compute_note_hash_and_nullifier diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr index 8b7e250cec9..da389a51e69 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr @@ -1,130 +1,4 @@ -// docs:start:token_types_all -use dep::std::hash::pedersen; -use dep::std::hash::pedersen_with_separator; -use dep::aztec::note::{ - note_header::NoteHeader, - note_interface::NoteInterface, - utils::compute_siloed_note_hash, -}; -use dep::aztec::constants_gen::GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET; - -global TRANSPARENT_NOTE_LEN: Field = 2; - - -// Transparent note represents a note that is created in the clear (public execution), -// but can only be spent by those that know the preimage of the "secret_hash" -struct TransparentNote { - amount: Field, - secret_hash: Field, - // the fields below are not serialized/deserialized - secret: Field, - header: NoteHeader, -} - -impl TransparentNote { - - // CONSTRUCTORS - - fn new(amount: Field, secret_hash: Field) -> Self { - TransparentNote { - amount: amount, - secret_hash: secret_hash, - secret: 0, - header: NoteHeader::empty(), - } - } - - // new oracle call primitive - // get me the secret corresponding to this hash - fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { - amount: amount, - secret_hash: TransparentNote::compute_secret_hash(secret), - secret: secret, - header: NoteHeader::empty(), - } - } - - - // STANDARD NOTE_INTERFACE FUNCTIONS - - fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { - [self.amount, self.secret_hash] - } - - fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> Self { - TransparentNote { - amount: preimage[0], - secret_hash: preimage[1], - secret: 0, - header: NoteHeader::empty(), - } - } - - fn compute_note_hash(self) -> Field { - // TODO(#1205) Should use a non-zero generator index. - dep::std::hash::pedersen([ - self.amount, - self.secret_hash, - ])[0] - } - - fn compute_nullifier(self) -> Field { - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): should use - // `compute_note_hash_for_read_or_nullify` once public functions inject nonce! - let siloed_note_hash = compute_siloed_note_hash(TransparentNoteMethods, self); - // TODO(#1205) Should use a non-zero generator index. - pedersen([self.secret, siloed_note_hash])[0] - } - - fn set_header(&mut self, header: NoteHeader) { - self.header = header; - } - - - // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - fn compute_secret_hash(secret: Field) -> Field { - // TODO(#1205) This is probably not the right index to use - pedersen_with_separator([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET)[0] - } - - fn knows_secret(self, secret: Field) { - let hash = TransparentNote::compute_secret_hash(secret); - assert(self.secret_hash == hash); - } -} - -fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> TransparentNote { - TransparentNote::deserialize(preimage) -} - -fn serialize(note: TransparentNote) -> [Field; TRANSPARENT_NOTE_LEN] { - note.serialize() -} - -fn compute_note_hash(note: TransparentNote) -> Field { - note.compute_note_hash() -} - -fn compute_nullifier(note: TransparentNote) -> Field { - note.compute_nullifier() -} - -fn get_header(note: TransparentNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut TransparentNote, header: NoteHeader) { - note.set_header(header) -} - -global TransparentNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - get_header, - set_header, -}; -// docs:end:token_types_all \ No newline at end of file +mod transparent_note; +mod balance_set; +mod token_note; +mod safe_u120_serialization; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr new file mode 100644 index 00000000000..52e98f22d8e --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr @@ -0,0 +1,128 @@ +use dep::std::option::Option; +use dep::safe_math::SafeU120; +use dep::aztec::{ + context::Context, + constants_gen::MAX_READ_REQUESTS_PER_CALL, + state_vars::set::Set, + log::emit_encrypted_log, +}; +use dep::aztec::note::{ + note_getter::view_notes, + note_getter_options::{NoteGetterOptions, SortOrder}, + note_viewer_options::NoteViewerOptions +}; +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, +}; +use dep::aztec::oracle::{ + rand::rand, + get_secret_key::get_secret_key, + get_public_key::get_public_key, +}; + +use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; + +struct BalanceSet { + context: Context, + set: Set +} + +impl BalanceSet { + fn new(context: Context, storage_slot: Field) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + let set = Set { + context, + storage_slot, + note_interface: TokenNoteMethods, + }; + Self { + context, + set, + } + } + + unconstrained fn balance_of(self: Self) -> SafeU120 { + self.balance_of_with_offset(0) + } + + unconstrained fn balance_of_with_offset(self: Self, offset: u32) -> SafeU120 { + // Same as SafeU120::new(0), but fewer constraints because no check. + let mut balance = SafeU120::min(); + // docs:start:view_notes + let options = NoteViewerOptions::new().set_offset(offset); + let opt_notes = self.set.view_notes(options); + // docs:end:view_notes + let len = opt_notes.len(); + for i in 0..len { + if opt_notes[i].is_some() { + balance = balance.add(opt_notes[i].unwrap_unchecked().amount); + } + } + if (opt_notes[len - 1].is_some()) { + balance = balance.add(self.balance_of_with_offset(offset + opt_notes.len() as u32)); + } + + balance + } + + fn add(self: Self, addend: SafeU120, owner: Field) { + let mut addend_note = TokenNote::new(addend, owner); + + // docs:start:insert + self.set.insert(&mut addend_note); + // docs:end:insert + + addend_note.emit_encrypted( + self.context.private.unwrap(), + self.set.storage_slot + ); + } + + fn sub(self: Self, subtrahend: SafeU120, owner: Field) { + // docs:start:get_notes + let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); + let maybe_notes = self.set.get_notes(options); + // docs:end:get_notes + + let mut minuend: SafeU120 = SafeU120::min(); + for i in 0..maybe_notes.len() { + if maybe_notes[i].is_some() { + let note = maybe_notes[i].unwrap_unchecked(); + + // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while + // spending someone else's notes). + // TODO: Get back to this, should already be constrained somewhere else? + assert(note.owner == owner); + + // Removes the note from the owner's set of notes. + // docs:start:remove + self.set.remove(note); + // docs:end:remove + + minuend = minuend.add(note.amount); + } + } + + // This is to provide a nicer error msg, + // without it minuend-subtrahend would still catch it, but more generic error then. + assert(minuend.ge(subtrahend) == true, "Balance too low"); + + self.add(minuend.sub(subtrahend), owner); + } +} + +fn filter_notes_min_sum(notes: [Option; MAX_READ_REQUESTS_PER_CALL], min_sum: SafeU120) -> [Option; MAX_READ_REQUESTS_PER_CALL] { + let mut selected = [Option::none(); MAX_READ_REQUESTS_PER_CALL]; + //let min_sum = SafeU120::new(min_sum); + let mut sum = SafeU120::min(); + for i in 0..notes.len() { + if notes[i].is_some() & sum.lt(min_sum) { + let note = notes[i].unwrap_unchecked(); + selected[i] = Option::some(note); + sum = sum.add(note.amount); + } + } + selected +} \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/safe_u120_serialization.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/safe_u120_serialization.nr new file mode 100644 index 00000000000..f4f3ef84d23 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/safe_u120_serialization.nr @@ -0,0 +1,18 @@ +use dep::aztec::types::type_serialization::TypeSerializationInterface; +use dep::safe_math::SafeU120; + +global SAFE_U120_SERIALIZED_LEN: Field = 1; + +// This is safe when reading from storage IF only correct safeu120 was written to storage +fn deserializeU120(fields: [Field; SAFE_U120_SERIALIZED_LEN]) -> SafeU120 { + SafeU120{value: fields[0] as u120} +} + +fn serializeU120(value: SafeU120) -> [Field; SAFE_U120_SERIALIZED_LEN] { + [value.value as Field] +} + +global SafeU120SerializationMethods = TypeSerializationInterface { + deserialize: deserializeU120, + serialize: serializeU120, +}; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr new file mode 100644 index 00000000000..94110bbfa06 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr @@ -0,0 +1,142 @@ +use dep::aztec::{ + note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, + }, + context::PrivateContext, + constants_gen::MAX_READ_REQUESTS_PER_CALL, + state_vars::set::Set, + log::emit_encrypted_log +}; +use dep::aztec::oracle::{ + rand::rand, + get_secret_key::get_secret_key, + get_public_key::get_public_key, +}; + +use dep::safe_math::SafeU120; +use dep::std::option::Option; + +global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. + +struct TokenNote { + // the amount of tokens in the note + amount: SafeU120, + // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note + // can be privately spent. When nullifier secret and encryption private key is same + // we can simply use the owner for this one. + owner: Field, + // randomness of the note to hide contents. + randomness: Field, + // the note header (contract_address, nonce, storage_slot) + header: NoteHeader, +} + +impl TokenNote { + fn new(amount: SafeU120, owner: Field) -> Self { + Self { + amount, + owner, + randomness: rand(), + header: NoteHeader::empty(), + } + } + + fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { + [self.amount.value as Field, self.owner, self.randomness] + } + + fn deserialize(preimage: [Field; TOKEN_NOTE_LEN]) -> Self { + Self { + amount: SafeU120::new(preimage[0]), + owner: preimage[1], + randomness: preimage[2], + header: NoteHeader::empty(), + } + } + + fn compute_note_hash(self) -> Field { + // TODO(#1205) Should use a non-zero generator index. + dep::std::hash::pedersen([ + self.amount.value as Field, + self.owner, + self.randomness, + ])[0] + } + + // docs:start:nullifier + fn compute_nullifier(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + // The secret must be constrained, otherwise easy to double-spend + let secret = get_secret_key(self.owner); + // TODO(#1205) Should use a non-zero generator index. + dep::std::hash::pedersen([ + note_hash_for_nullify, + secret.low, + secret.high, + ])[0] + } + // docs:end:nullifier + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + + fn emit_encrypted( + self: &mut Self, + context: &mut PrivateContext, + storage_slot: Field, + ) { + // We only bother inserting the note if non-empty to save funds on gas. + if !self.amount.is_zero() { + // docs:start:encrypted + let application_contract_address = (*context).this_address(); + let encryption_pub_key = get_public_key(self.owner); + let encrypted_data = (*self).serialize(); + + emit_encrypted_log( + context, + application_contract_address, + storage_slot, + encryption_pub_key, + encrypted_data, + ); + // docs:end:encrypted + } + } +} + +fn deserialize(preimage: [Field; TOKEN_NOTE_LEN]) -> TokenNote { + TokenNote::deserialize(preimage) +} + +fn serialize(note: TokenNote) -> [Field; TOKEN_NOTE_LEN] { + note.serialize() +} + +fn compute_note_hash(note: TokenNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: TokenNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: TokenNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut TokenNote, header: NoteHeader) { + note.set_header(header) +} + +global TokenNoteMethods = NoteInterface { + deserialize, + serialize, + compute_note_hash, + compute_nullifier, + get_header, + set_header, +}; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr new file mode 100644 index 00000000000..4d79bb636aa --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr @@ -0,0 +1,129 @@ +// docs:start:token_types_all +use dep::std::hash::pedersen; +use dep::std::hash::pedersen_with_separator; +use dep::aztec::note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_siloed_note_hash, +}; +use dep::aztec::constants_gen::GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET; + +global TRANSPARENT_NOTE_LEN: Field = 2; + +// Transparent note represents a note that is created in the clear (public execution), +// but can only be spent by those that know the preimage of the "secret_hash" +struct TransparentNote { + amount: Field, + secret_hash: Field, + // the fields below are not serialized/deserialized + secret: Field, + header: NoteHeader, +} + +impl TransparentNote { + + // CONSTRUCTORS + + fn new(amount: Field, secret_hash: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: secret_hash, + secret: 0, + header: NoteHeader::empty(), + } + } + + // new oracle call primitive + // get me the secret corresponding to this hash + fn new_from_secret(amount: Field, secret: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: TransparentNote::compute_secret_hash(secret), + secret: secret, + header: NoteHeader::empty(), + } + } + + + // STANDARD NOTE_INTERFACE FUNCTIONS + + fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { + [self.amount, self.secret_hash] + } + + fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> Self { + TransparentNote { + amount: preimage[0], + secret_hash: preimage[1], + secret: 0, + header: NoteHeader::empty(), + } + } + + fn compute_note_hash(self) -> Field { + // TODO(#1205) Should use a non-zero generator index. + dep::std::hash::pedersen([ + self.amount, + self.secret_hash, + ])[0] + } + + fn compute_nullifier(self) -> Field { + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): should use + // `compute_note_hash_for_read_or_nullify` once public functions inject nonce! + let siloed_note_hash = compute_siloed_note_hash(TransparentNoteMethods, self); + // TODO(#1205) Should use a non-zero generator index. + pedersen([self.secret, siloed_note_hash])[0] + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE + + fn compute_secret_hash(secret: Field) -> Field { + // TODO(#1205) This is probably not the right index to use + pedersen_with_separator([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET)[0] + } + + fn knows_secret(self, secret: Field) { + let hash = TransparentNote::compute_secret_hash(secret); + assert(self.secret_hash == hash); + } +} + +fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> TransparentNote { + TransparentNote::deserialize(preimage) +} + +fn serialize(note: TransparentNote) -> [Field; TRANSPARENT_NOTE_LEN] { + note.serialize() +} + +fn compute_note_hash(note: TransparentNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: TransparentNote) -> Field { + note.compute_nullifier() +} + +fn get_header(note: TransparentNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut TransparentNote, header: NoteHeader) { + note.set_header(header) +} + +global TransparentNoteMethods = NoteInterface { + deserialize, + serialize, + compute_note_hash, + compute_nullifier, + get_header, + set_header, +}; +// docs:end:token_types_all \ No newline at end of file From 0d5e97ab2bbbbb075621aa323f8d392bb305cc7d Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 15:44:30 +0000 Subject: [PATCH 2/9] chore: build-system submodule --- barretenberg/build-system | 1 - 1 file changed, 1 deletion(-) delete mode 160000 barretenberg/build-system diff --git a/barretenberg/build-system b/barretenberg/build-system deleted file mode 160000 index a109f3aef28..00000000000 --- a/barretenberg/build-system +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a109f3aef28cea4a50481cdf2d74fc3909212c0b From 018cd6402a936120d080466ad4e7d0b6022ad1ee Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 16:17:48 +0000 Subject: [PATCH 3/9] feat: balances_map --- .../src/contracts/token_contract/src/main.nr | 33 ++++++------------- .../src/contracts/token_contract/src/types.nr | 1 + .../token_contract/src/types/balance_set.nr | 25 ++++++++------ .../token_contract/src/types/balances_map.nr | 27 +++++++++++++++ .../token_contract/src/types/token_note.nr | 16 ++++----- 5 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 yarn-project/noir-contracts/src/contracts/token_contract/src/types/balances_map.nr diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr index 4f5dae986a0..2cf48a52994 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr @@ -36,7 +36,7 @@ contract Token { use crate::types::{ transparent_note::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}, token_note::{TokenNote, TokenNoteMethods, TOKEN_NOTE_LEN}, - balance_set::{BalanceSet}, + balances_map::{BalancesMap}, safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN} }; use crate::util::{compute_message_hash}; @@ -51,7 +51,7 @@ contract Token { minters: Map>, // docs:end:storage_minters // docs:start:storage_balances - balances: Map, + balances: BalancesMap, // docs:end:storage_balances total_supply: PublicState, // docs:start:storage_pending_shields @@ -63,7 +63,7 @@ contract Token { // docs:start:storage_init impl Storage { - fn init(context: Context) -> Self { + fn init(context: Context) -> pub Self { Storage { // docs:start:storage_admin_init admin: PublicState::new( @@ -85,13 +85,7 @@ contract Token { }, ), // docs:end:storage_minters_init - balances: Map::new( - context, - 3, - |context, slot| { - BalanceSet::new(context, slot) - }, - ), + balances: BalancesMap::new(context, 3), total_supply: PublicState::new( context, 4, @@ -280,14 +274,13 @@ contract Token { secret: Field, ) -> Field { let pending_shields = storage.pending_shields; - let balance = storage.balances.at(to.address); let mut public_note = TransparentNote::new_from_secret(amount, secret); // docs:start:assert_contains_and_remove_publicly_created pending_shields.assert_contains_and_remove_publicly_created(&mut public_note); // docs:end:assert_contains_and_remove_publicly_created - balance.add(SafeU120::new(amount), to.address); + storage.balances.at(to).add(SafeU120::new(amount)); 1 } @@ -309,8 +302,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - let from_balance = storage.balances.at(from.address); - from_balance.sub(SafeU120::new(amount), from.address); + storage.balances.at(from).sub(SafeU120::new(amount)); let selector = compute_selector("_increase_public_balance((Field),Field)"); let _void = context.call_public_function(context.this_address(), selector, [to.address, amount]); @@ -335,12 +327,9 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - let from_balance = storage.balances.at(from.address); - let to_balance = storage.balances.at(to.address); - let amount = SafeU120::new(amount); - from_balance.sub(amount, from.address); - to_balance.add(amount, to.address); + storage.balances.at(from).sub(amount); + storage.balances.at(to).add(amount); 1 } @@ -361,8 +350,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - let from_balance = storage.balances.at(from.address); - from_balance.sub(SafeU120::new(amount), from.address); + storage.balances.at(from).sub(SafeU120::new(amount)); let selector = compute_selector("_reduce_total_supply(Field)"); let _void = context.call_public_function(context.this_address(), selector, [amount]); @@ -436,8 +424,7 @@ contract Token { unconstrained fn balance_of_private( owner: AztecAddress, ) -> u120 { - let owner_balance = storage.balances.at(owner.address); - owner_balance.balance_of().value + storage.balances.at(owner).balance_of().value } // docs:end:balance_of_private diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr index da389a51e69..1f4883a54c6 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr @@ -1,4 +1,5 @@ mod transparent_note; mod balance_set; +mod balances_map; mod token_note; mod safe_u120_serialization; \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr index 52e98f22d8e..f5f260c16f1 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr @@ -5,6 +5,7 @@ use dep::aztec::{ constants_gen::MAX_READ_REQUESTS_PER_CALL, state_vars::set::Set, log::emit_encrypted_log, + types::address::AztecAddress, }; use dep::aztec::note::{ note_getter::view_notes, @@ -24,13 +25,17 @@ use dep::aztec::oracle::{ use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; +// A set implementing standard manipulation of balances. +// Does not require spending key, but only knowledge. +// Spending key requirement should be enforced by the contract using this. struct BalanceSet { context: Context, + owner: AztecAddress, set: Set } impl BalanceSet { - fn new(context: Context, storage_slot: Field) -> Self { + fn new(context: Context, owner: AztecAddress, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); let set = Set { context, @@ -39,6 +44,7 @@ impl BalanceSet { }; Self { context, + owner, set, } } @@ -67,8 +73,8 @@ impl BalanceSet { balance } - fn add(self: Self, addend: SafeU120, owner: Field) { - let mut addend_note = TokenNote::new(addend, owner); + fn add(self: Self, addend: SafeU120) { + let mut addend_note = TokenNote::new(addend, self.owner); // docs:start:insert self.set.insert(&mut addend_note); @@ -80,7 +86,7 @@ impl BalanceSet { ); } - fn sub(self: Self, subtrahend: SafeU120, owner: Field) { + fn sub(self: Self, subtrahend: SafeU120) { // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let maybe_notes = self.set.get_notes(options); @@ -91,12 +97,10 @@ impl BalanceSet { if maybe_notes[i].is_some() { let note = maybe_notes[i].unwrap_unchecked(); - // Ensure the notes are actually owned by the owner (to prevent user from generating a valid proof while - // spending someone else's notes). - // TODO: Get back to this, should already be constrained somewhere else? - assert(note.owner == owner); - // Removes the note from the owner's set of notes. + // This will call the the `compute_nullifer` function of the `token_note` + // which require knowledge of the secret key (currently the users encryption key). + // The contract logic must ensure that the spending key is used as well. // docs:start:remove self.set.remove(note); // docs:end:remove @@ -107,9 +111,10 @@ impl BalanceSet { // This is to provide a nicer error msg, // without it minuend-subtrahend would still catch it, but more generic error then. + // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. assert(minuend.ge(subtrahend) == true, "Balance too low"); - self.add(minuend.sub(subtrahend), owner); + self.add(minuend.sub(subtrahend)); } } diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balances_map.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balances_map.nr new file mode 100644 index 00000000000..fef342cbea7 --- /dev/null +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balances_map.nr @@ -0,0 +1,27 @@ +use dep::aztec::context::{PrivateContext, PublicContext, Context}; +use dep::aztec::types::address::AztecAddress; +use dep::std::option::Option; +use crate::types::balance_set::BalanceSet; + +struct BalancesMap { + context: Context, + storage_slot: Field, +} + +impl BalancesMap { + fn new( + context: Context, + storage_slot: Field, + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + Self { + context, + storage_slot, + } + } + + fn at(self, owner: AztecAddress) -> BalanceSet { + let derived_storage_slot = dep::std::hash::pedersen([self.storage_slot, owner.address])[0]; + BalanceSet::new(self.context, owner, derived_storage_slot) + } +} diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr index 94110bbfa06..a18d7982fb8 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr @@ -9,6 +9,7 @@ use dep::aztec::{ state_vars::set::Set, log::emit_encrypted_log }; +use dep::aztec::types::address::AztecAddress; use dep::aztec::oracle::{ rand::rand, get_secret_key::get_secret_key, @@ -26,7 +27,7 @@ struct TokenNote { // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note // can be privately spent. When nullifier secret and encryption private key is same // we can simply use the owner for this one. - owner: Field, + owner: AztecAddress, // randomness of the note to hide contents. randomness: Field, // the note header (contract_address, nonce, storage_slot) @@ -34,7 +35,7 @@ struct TokenNote { } impl TokenNote { - fn new(amount: SafeU120, owner: Field) -> Self { + fn new(amount: SafeU120, owner: AztecAddress) -> Self { Self { amount, owner, @@ -44,13 +45,13 @@ impl TokenNote { } fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { - [self.amount.value as Field, self.owner, self.randomness] + [self.amount.value as Field, self.owner.address, self.randomness] } fn deserialize(preimage: [Field; TOKEN_NOTE_LEN]) -> Self { Self { amount: SafeU120::new(preimage[0]), - owner: preimage[1], + owner: AztecAddress::new(preimage[1]), randomness: preimage[2], header: NoteHeader::empty(), } @@ -60,7 +61,7 @@ impl TokenNote { // TODO(#1205) Should use a non-zero generator index. dep::std::hash::pedersen([ self.amount.value as Field, - self.owner, + self.owner.address as Field, self.randomness, ])[0] } @@ -68,8 +69,7 @@ impl TokenNote { // docs:start:nullifier fn compute_nullifier(self) -> Field { let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); - // The secret must be constrained, otherwise easy to double-spend - let secret = get_secret_key(self.owner); + let secret = get_secret_key(self.owner.address); // TODO(#1205) Should use a non-zero generator index. dep::std::hash::pedersen([ note_hash_for_nullify, @@ -93,7 +93,7 @@ impl TokenNote { if !self.amount.is_zero() { // docs:start:encrypted let application_contract_address = (*context).this_address(); - let encryption_pub_key = get_public_key(self.owner); + let encryption_pub_key = get_public_key(self.owner.address); let encrypted_data = (*self).serialize(); emit_encrypted_log( From 69dfd941cf4f72608023fe802c5a50ba945c28cc Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 16:32:22 +0000 Subject: [PATCH 4/9] chore: extend rebuildPattern for docs --- build_manifest.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build_manifest.yml b/build_manifest.yml index f955b467221..bdb1f1361e9 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -166,5 +166,6 @@ docs: - ^.*.ts$ - ^.release-please-manifest.json$ - ^.*/noir-version.json$ + - ^.*.nr$ dependencies: - - yarn-project + - yarn-project \ No newline at end of file From 9d88c7a74e4eb988096f6facc023443e1586bb9f Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 16:39:20 +0000 Subject: [PATCH 5/9] chore: fix the docs link --- .../docs/dev_docs/tutorials/writing_dapp/contract_deployment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md b/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md index 83ddeebce38..9155fd48be1 100644 --- a/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md +++ b/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md @@ -32,7 +32,7 @@ The `Token` contract also requires two helper files. Copy-them too: Create `contracts/token/types.nr` and copy-paste the following: -#include_code token_types_all yarn-project/noir-contracts/src/contracts/token_contract/src/types.nr rust +#include_code token_types_all yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr rust Finally, create `contracts/token/util.nr` and copy-paste the following: From a33149ef13c7275eb32028e87cfb5a94c7e70522 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Tue, 26 Sep 2023 16:44:35 +0000 Subject: [PATCH 6/9] chore: fix strage.md typo and solidity example --- docs/docs/dev_docs/contracts/syntax/storage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/dev_docs/contracts/syntax/storage.md b/docs/docs/dev_docs/contracts/syntax/storage.md index 63dca65f2ba..4bac605a736 100644 --- a/docs/docs/dev_docs/contracts/syntax/storage.md +++ b/docs/docs/dev_docs/contracts/syntax/storage.md @@ -71,7 +71,7 @@ This function behaves similarly for both private and public maps. An example cou Above, we are specifying that we want to get the storage in the Map `at` the `msg_sender()`, read the value stored and check that `msg_sender()` is indeed a minter. Doing a similar operation in Solidity code would look like: ```solidity -require(minters[msg.sender] == 1, "caller is not minter"); +require(minters[msg.sender], "caller is not minter"); ``` ## Public State Variables @@ -141,7 +141,7 @@ In this case, specifying that we are dealing with a map of Fields, and that it s This would be similar to the following in solidity: ```solidity -mapping(address => uint256) internal minters; +mapping(address => bool) internal minters; ``` ### `read` @@ -159,7 +159,7 @@ For our `admin` example from earlier, this could be used as follows to check tha #include_code read_admin /yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust -#### Reading from out `minters` example +#### Reading from our `minters` example As we saw in the Map earlier, a very similar operation can be done to perform a lookup in a map. From c576dcdde02eab61ffbcbbb2ce7773e02c78a670 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 27 Sep 2023 11:46:20 +0000 Subject: [PATCH 7/9] chore: time issue --- yarn-project/end-to-end/src/e2e_token_contract.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/e2e_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_token_contract.test.ts index 578c0a3e291..a910d8bd6e4 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract.test.ts @@ -18,7 +18,7 @@ const hashPayload = async (payload: Fr[]) => { ); }; -const TIMEOUT = 60_000; +const TIMEOUT = 90_000; describe('e2e_token_contract', () => { jest.setTimeout(TIMEOUT); From ff748f07ee653fb47197a94e7dae5cff2d0c2147 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Fri, 29 Sep 2023 08:54:21 +0000 Subject: [PATCH 8/9] chore: address some nits --- .../src/contracts/token_contract/src/types/token_note.nr | 1 + .../contracts/token_contract/src/types/transparent_note.nr | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr index a18d7982fb8..1322f248332 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr @@ -31,6 +31,7 @@ struct TokenNote { // randomness of the note to hide contents. randomness: Field, // the note header (contract_address, nonce, storage_slot) + // included in the note such that it becomes part of encrypted logs for later use. header: NoteHeader, } diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr index 4d79bb636aa..ae32796f2bd 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr @@ -15,8 +15,9 @@ global TRANSPARENT_NOTE_LEN: Field = 2; struct TransparentNote { amount: Field, secret_hash: Field, - // the fields below are not serialized/deserialized + // the secret is just here for ease of use and won't be (de)serialized secret: Field, + // header is just here to satisfy the NoteInterface header: NoteHeader, } @@ -69,8 +70,7 @@ impl TransparentNote { } fn compute_nullifier(self) -> Field { - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): should use - // `compute_note_hash_for_read_or_nullify` once public functions inject nonce! + // TODO(#1386): should use `compute_note_hash_for_read_or_nullify` once public functions inject nonce! let siloed_note_hash = compute_siloed_note_hash(TransparentNoteMethods, self); // TODO(#1205) Should use a non-zero generator index. pedersen([self.secret, siloed_note_hash])[0] From 3826da580b5643aa0ecc50e088ec2ac4fe35c073 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Fri, 29 Sep 2023 10:29:38 +0000 Subject: [PATCH 9/9] chore: remove stale comment --- .../src/contracts/token_contract/src/types/balance_set.nr | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr index f5f260c16f1..3789e62c96a 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/balance_set.nr @@ -120,7 +120,6 @@ impl BalanceSet { fn filter_notes_min_sum(notes: [Option; MAX_READ_REQUESTS_PER_CALL], min_sum: SafeU120) -> [Option; MAX_READ_REQUESTS_PER_CALL] { let mut selected = [Option::none(); MAX_READ_REQUESTS_PER_CALL]; - //let min_sum = SafeU120::new(min_sum); let mut sum = SafeU120::min(); for i in 0..notes.len() { if notes[i].is_some() & sum.lt(min_sum) {