From 9e6605cf7cc6e778b681e4e0c39788ab58249f55 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Tue, 30 Jan 2024 15:57:06 +0100 Subject: [PATCH] chore!: Serialize, Deserialize and NoteInterface as Traits (#4135) Closes: https://github.com/AztecProtocol/aztec-packages/issues/3756, https://github.com/AztecProtocol/aztec-packages/issues/2838 Taking advantage of @jfecher's fantastic work in https://github.com/noir-lang/noir/pull/4000, implemented `Serialize` and `Deserialize`. Together with `NoteInterface`, they make possible getting rid of all the serialization interfaces, which greatly simplify how the storage is handled and opens the door to further improvements. ~~Still some clutter to go, the lengths are still needed in some places.~~ ![Brace yourself](https://i.imgflip.com/8crkve.jpg) I'm so sorry. --------- Co-authored-by: sirasistant --- boxes/token/src/contracts/src/main.nr | 30 +- boxes/token/src/contracts/src/types.nr | 1 - .../src/contracts/src/types/balance_set.nr | 12 +- .../src/contracts/src/types/balances_map.nr | 5 +- .../src/types/safe_u120_serialization.nr | 18 -- .../src/contracts/src/types/token_note.nr | 89 ++---- .../contracts/src/types/transparent_note.nr | 119 +++---- .../contracts/syntax/storage/private_state.md | 12 +- .../contracts/syntax/storage/public_state.md | 15 +- docs/docs/developers/testing/cheat_codes.md | 8 +- .../tutorials/writing_token_contract.md | 4 +- docs/docs/misc/migration_notes.md | 298 ++++++++++++++++++ .../aztec-nr/address-note/src/address_note.nr | 100 ++---- yarn-project/aztec-nr/authwit/src/account.nr | 5 +- .../aztec-nr/authwit/src/entrypoint.nr | 25 +- yarn-project/aztec-nr/aztec/src/abi.nr | 15 +- yarn-project/aztec-nr/aztec/src/context.nr | 8 +- .../aztec/src/history/note_inclusion.nr | 5 +- .../aztec/src/history/note_validity.nr | 7 +- .../src/history/nullifier_non_inclusion.nr | 5 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 44 +-- .../aztec-nr/aztec/src/note/note_getter.nr | 67 ++-- .../aztec/src/note/note_getter_options.nr | 10 +- .../aztec-nr/aztec/src/note/note_interface.nr | 23 +- .../aztec/src/note/note_viewer_options.nr | 8 +- yarn-project/aztec-nr/aztec/src/note/utils.nr | 64 ++-- .../src/oracle/get_public_data_witness.nr | 16 +- .../aztec-nr/aztec/src/oracle/notes.nr | 18 +- .../aztec-nr/aztec/src/oracle/storage.nr | 8 +- .../src/state_vars/immutable_singleton.nr | 23 +- .../aztec/src/state_vars/public_state.nr | 21 +- .../aztec-nr/aztec/src/state_vars/set.nr | 32 +- .../aztec/src/state_vars/singleton.nr | 38 ++- yarn-project/aztec-nr/aztec/src/types.nr | 1 - .../aztec/src/types/type_serialization.nr | 15 - .../address_serialization.nr | 22 -- .../type_serialization/bool_serialization.nr | 16 - .../type_serialization/field_serialization.nr | 18 -- .../type_serialization/u32_serialization.nr | 16 - .../type_serialization/u8_serialization.nr | 16 - .../src/compressed_string.nr | 38 +-- .../aztec-nr/compressed-string/src/lib.nr | 2 +- .../src/easy_private_state.nr | 7 +- .../aztec-nr/field-note/src/field_note.nr | 81 ++--- yarn-project/aztec-nr/safe-math/Nargo.toml | 3 +- yarn-project/aztec-nr/safe-math/src/lib.nr | 2 +- .../aztec-nr/safe-math/src/safe_u120.nr | 16 + .../slow-updates-tree/src/slow_map.nr | 28 +- .../aztec-nr/value-note/src/balance_utils.nr | 4 +- yarn-project/aztec-nr/value-note/src/utils.nr | 16 +- .../aztec-nr/value-note/src/value_note.nr | 98 ++---- .../benchmarking_contract/src/main.nr | 16 +- .../contracts/card_game_contract/src/cards.nr | 5 +- .../contracts/card_game_contract/src/game.nr | 105 +++--- .../contracts/card_game_contract/src/main.nr | 10 +- .../contracts/child_contract/src/main.nr | 4 +- .../contracts/counter_contract/src/main.nr | 4 +- .../docs_example_contract/src/main.nr | 27 +- .../src/types/card_note.nr | 77 ++--- .../docs_example_contract/src/types/leader.nr | 22 +- .../easy_private_token_contract/src/main.nr | 6 +- .../easy_private_voting_contract/src/main.nr | 22 +- .../src/ecdsa_public_key_note.nr | 125 +++----- .../ecdsa_account_contract/src/main.nr | 8 +- .../contracts/escrow_contract/src/main.nr | 7 +- .../inclusion_proofs_contract/src/main.nr | 30 +- .../contracts/lending_contract/src/asset.nr | 49 ++- .../contracts/lending_contract/src/main.nr | 34 +- .../pending_commitments_contract/src/main.nr | 8 +- .../price_feed_contract/src/asset.nr | 23 +- .../contracts/price_feed_contract/src/main.nr | 5 +- .../contracts/reader_contract/src/main.nr | 2 +- .../schnorr_account_contract/src/main.nr | 8 +- .../src/public_key_note.nr | 105 +++--- .../contracts/slow_tree_contract/src/main.nr | 6 +- .../stateful_test_contract/src/main.nr | 14 +- .../contracts/test_contract/src/main.nr | 38 ++- .../token_blacklist_contract/src/main.nr | 42 +-- .../token_blacklist_contract/src/types.nr | 1 - .../src/types/balance_set.nr | 5 +- .../src/types/safe_u120_serialization.nr | 18 -- .../src/types/token_note.nr | 90 ++---- .../src/types/transparent_note.nr | 120 +++---- .../token_bridge_contract/src/main.nr | 6 +- .../contracts/token_contract/src/main.nr | 60 ++-- .../contracts/token_contract/src/types.nr | 1 - .../token_contract/src/types/balance_set.nr | 5 +- .../src/types/safe_u120_serialization.nr | 18 -- .../token_contract/src/types/token_note.nr | 92 ++---- .../src/types/transparent_note.nr | 129 ++++---- .../contracts/uniswap_contract/src/main.nr | 14 +- .../types/src/abis/function_selector.nr | 25 +- .../abis/nullifier_key_validation_request.nr | 21 +- .../src/abis/private_circuit_public_inputs.nr | 4 +- .../src/crates/types/src/abis/side_effect.nr | 22 +- .../src/crates/types/src/address.nr | 49 +-- .../types/src/contrakt/deployment_data.nr | 7 +- .../src/contrakt/storage_update_request.nr | 8 +- .../src/crates/types/src/grumpkin_point.nr | 11 +- .../src/crates/types/src/lib.nr | 1 + .../src/crates/types/src/traits.nr | 12 + .../crates/types/src/type_serialization.nr | 56 ++++ 102 files changed, 1452 insertions(+), 1677 deletions(-) delete mode 100644 boxes/token/src/contracts/src/types/safe_u120_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/address_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/bool_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/field_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/u32_serialization.nr delete mode 100644 yarn-project/aztec-nr/aztec/src/types/type_serialization/u8_serialization.nr delete mode 100644 yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/safe_u120_serialization.nr delete mode 100644 yarn-project/noir-contracts/contracts/token_contract/src/types/safe_u120_serialization.nr create mode 100644 yarn-project/noir-protocol-circuits/src/crates/types/src/type_serialization.nr diff --git a/boxes/token/src/contracts/src/main.nr b/boxes/token/src/contracts/src/main.nr index 673ee997663..5b85b2e4d74 100644 --- a/boxes/token/src/contracts/src/main.nr +++ b/boxes/token/src/contracts/src/main.nr @@ -24,11 +24,6 @@ contract Token { context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::{ - field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN}, - address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, - }, protocol_types::{ abis::function_selector::FunctionSelector, address::AztecAddress, @@ -45,29 +40,28 @@ contract Token { // docs:end:import_authwit use crate::types::{ - transparent_note::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}, - token_note::{TokenNote, TokenNoteMethods, TOKEN_NOTE_LEN}, + transparent_note::TransparentNote, + token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::{BalancesMap}, - safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN} }; // 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: BalancesMap, // docs:end:storage_balances - total_supply: PublicState, + total_supply: PublicState, // docs:start:storage_pending_shields - pending_shields: Set, + pending_shields: Set, // docs:end:storage_pending_shields - public_balances: Map>, + public_balances: Map>, } // docs:end:storage_struct @@ -79,7 +73,6 @@ contract Token { admin: PublicState::new( context, 1, - AddressSerializationMethods, ), // docs:end:storage_admin_init // docs:start:storage_minters_init @@ -90,7 +83,6 @@ contract Token { PublicState::new( context, slot, - BoolSerializationMethods, ) }, ), @@ -101,10 +93,9 @@ contract Token { total_supply: PublicState::new( context, 4, - SafeU120SerializationMethods, ), // docs:start:storage_pending_shields_init - pending_shields: Set::new(context, 5, TransparentNoteMethods), + pending_shields: Set::new(context, 5), // docs:end:storage_pending_shields_init public_balances: Map::new( context, @@ -113,7 +104,6 @@ contract Token { PublicState::new( context, slot, - SafeU120SerializationMethods, ) }, ), @@ -385,9 +375,9 @@ contract Token { ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); if (storage_slot == 5) { - note_utils::compute_note_hash_and_nullifier(TransparentNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize, note_header, serialized_note) } else { - note_utils::compute_note_hash_and_nullifier(TokenNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize, note_header, serialized_note) } } // docs:end:compute_note_hash_and_nullifier diff --git a/boxes/token/src/contracts/src/types.nr b/boxes/token/src/contracts/src/types.nr index e29a8151e9f..d3b3b1c9e77 100644 --- a/boxes/token/src/contracts/src/types.nr +++ b/boxes/token/src/contracts/src/types.nr @@ -2,4 +2,3 @@ mod transparent_note; mod balance_set; mod balances_map; mod token_note; -mod safe_u120_serialization; diff --git a/boxes/token/src/contracts/src/types/balance_set.nr b/boxes/token/src/contracts/src/types/balance_set.nr index 231320de558..184fd5fe925 100644 --- a/boxes/token/src/contracts/src/types/balance_set.nr +++ b/boxes/token/src/contracts/src/types/balance_set.nr @@ -13,23 +13,19 @@ use dep::aztec::note::{ 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 crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; + +use crate::types::token_note::TokenNote; // 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 { owner: AztecAddress, - set: Set + set: Set } impl BalanceSet { - pub fn new(set: Set, owner: AztecAddress) -> Self { + pub fn new(set: Set, owner: AztecAddress) -> Self { Self { owner, set, diff --git a/boxes/token/src/contracts/src/types/balances_map.nr b/boxes/token/src/contracts/src/types/balances_map.nr index 9d6f92c0ac0..e8cb09f62a3 100644 --- a/boxes/token/src/contracts/src/types/balances_map.nr +++ b/boxes/token/src/contracts/src/types/balances_map.nr @@ -4,11 +4,11 @@ use crate::types::balance_set::BalanceSet; use dep::aztec::hash::pedersen_hash; use dep::aztec::protocol_types::address::AztecAddress; -use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; +use crate::types::token_note::TokenNote; use dep::aztec::state_vars::{map::Map, set::Set}; struct BalancesMap { - store: Map>, + store: Map>, } impl BalancesMap { @@ -20,7 +20,6 @@ impl BalancesMap { Set { context, storage_slot, - note_interface: TokenNoteMethods, } }); Self { diff --git a/boxes/token/src/contracts/src/types/safe_u120_serialization.nr b/boxes/token/src/contracts/src/types/safe_u120_serialization.nr deleted file mode 100644 index 876007184fe..00000000000 --- a/boxes/token/src/contracts/src/types/safe_u120_serialization.nr +++ /dev/null @@ -1,18 +0,0 @@ -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, -}; diff --git a/boxes/token/src/contracts/src/types/token_note.nr b/boxes/token/src/contracts/src/types/token_note.nr index f8adf31959d..2f27cf4cb6d 100644 --- a/boxes/token/src/contracts/src/types/token_note.nr +++ b/boxes/token/src/contracts/src/types/token_note.nr @@ -14,6 +14,7 @@ use dep::aztec::{ state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash, + protocol_types::traits::{Serialize, Deserialize}, }; use dep::aztec::oracle::{ rand::rand, @@ -39,21 +40,14 @@ struct TokenNote { header: NoteHeader, } -impl TokenNote { - pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { - Self { - amount, - owner, - randomness: rand(), - header: NoteHeader::empty(), - } - } - - pub fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { +impl Serialize for TokenNote { + fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { [self.amount.value as Field, self.owner.to_field(), self.randomness] } +} - pub fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> Self { +impl Deserialize for TokenNote { + fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> Self { Self { amount: SafeU120::new(serialized_note[0]), owner: AztecAddress::from_field(serialized_note[1]), @@ -61,8 +55,10 @@ impl TokenNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for TokenNote { + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount.value as Field, @@ -72,8 +68,8 @@ impl TokenNote { } // docs:start:nullifier - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -84,8 +80,8 @@ impl TokenNote { } // docs:end:nullifier - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -95,12 +91,16 @@ impl TokenNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(self) -> NoteHeader { + self.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !self.amount.is_zero() { let encryption_pub_key = get_public_key(self.owner); @@ -115,46 +115,13 @@ impl TokenNote { } } -fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> TokenNote { - TokenNote::deserialize(serialized_note) -} - -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, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: TokenNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: TokenNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut TokenNote, header: NoteHeader) { - note.set_header(header) -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: TokenNote) { - note.broadcast(context, slot); +impl TokenNote { + pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { + Self { + amount, + owner, + randomness: rand(), + header: NoteHeader::empty(), + } + } } - -global TokenNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/boxes/token/src/contracts/src/types/transparent_note.nr b/boxes/token/src/contracts/src/types/transparent_note.nr index 361413bc82b..4408e20dee4 100644 --- a/boxes/token/src/contracts/src/types/transparent_note.nr +++ b/boxes/token/src/contracts/src/types/transparent_note.nr @@ -7,6 +7,7 @@ use dep::aztec::{ }, hash::{compute_secret_hash, pedersen_hash}, context::PrivateContext, + protocol_types::traits::{Serialize, Deserialize} }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -22,38 +23,14 @@ struct TransparentNote { header: NoteHeader, } -impl TransparentNote { - - // CONSTRUCTORS - - pub 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 - pub fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { - amount: amount, - secret_hash: compute_secret_hash(secret), - secret: secret, - header: NoteHeader::empty(), - } - } - - - // STANDARD NOTE_INTERFACE FUNCTIONS - - pub fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { +impl Serialize for TransparentNote { + fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { [self.amount, self.secret_hash] } +} - pub fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { +impl Deserialize for TransparentNote { + fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { TransparentNote { amount: serialized_note[0], secret_hash: serialized_note[1], @@ -61,8 +38,11 @@ impl TransparentNote { header: NoteHeader::empty(), } } +} + +impl NoteInterface for TransparentNote { - pub fn compute_note_hash(self) -> Field { + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount, @@ -70,69 +50,58 @@ impl TransparentNote { ],0) } - pub fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { + fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { self.compute_nullifier_without_context() } - pub fn compute_nullifier_without_context(self) -> Field { - let siloed_note_hash = compute_note_hash_for_read_or_nullify(TransparentNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let siloed_note_hash = compute_note_hash_for_read_or_nullify(self); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([self.secret, siloed_note_hash],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } - - // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - pub fn knows_secret(self, secret: Field) { - let hash = compute_secret_hash(secret); - assert(self.secret_hash == hash); + fn get_header(self) -> NoteHeader { + self.header } -} -fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> TransparentNote { - TransparentNote::deserialize(serialized_note) -} - -fn serialize(note: TransparentNote) -> [Field; TRANSPARENT_NOTE_LEN] { - note.serialize() + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + assert(false, "TransparentNote does not support broadcast"); + } } -fn compute_note_hash(note: TransparentNote) -> Field { - note.compute_note_hash() -} +impl TransparentNote { -fn compute_nullifier(note: TransparentNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} + // CONSTRUCTORS -fn compute_nullifier_without_context(note: TransparentNote) -> Field { - note.compute_nullifier_without_context() -} + pub fn new(amount: Field, secret_hash: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: secret_hash, + secret: 0, + header: NoteHeader::empty(), + } + } -fn get_header(note: TransparentNote) -> NoteHeader { - note.header -} + // new oracle call primitive + // get me the secret corresponding to this hash + pub fn new_from_secret(amount: Field, secret: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: compute_secret_hash(secret), + secret: secret, + header: NoteHeader::empty(), + } + } -fn set_header(note: &mut TransparentNote, header: NoteHeader) { - note.set_header(header) -} + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE -fn broadcast(context: &mut PrivateContext, slot: Field, note: TransparentNote) { - assert(false, "TransparentNote does not support broadcast"); + pub fn knows_secret(self, secret: Field) { + let hash = compute_secret_hash(secret); + assert(self.secret_hash == hash); + } } - -global TransparentNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; // docs:end:token_types_all \ No newline at end of file diff --git a/docs/docs/developers/contracts/syntax/storage/private_state.md b/docs/docs/developers/contracts/syntax/storage/private_state.md index cfaf57d4c03..f4e3836d030 100644 --- a/docs/docs/developers/contracts/syntax/storage/private_state.md +++ b/docs/docs/developers/contracts/syntax/storage/private_state.md @@ -32,9 +32,13 @@ Unlike public state variables, which can be arbitrary types, private state varia Notes are the fundamental elements in the private world. -A note should conform to the following interface: +A note should implement the following traits: -#include_code NoteInterface /yarn-project/aztec-nr/aztec/src/note/note_interface.nr rust +#include_code note_interface /yarn-project/aztec-nr/aztec/src/note/note_interface.nr rust + +#include_code serialize /yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr rust + +#include_code deserialize /yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr rust The interplay between a private state variable and its notes can be confusing. Here's a summary to aid intuition: @@ -66,7 +70,7 @@ Interestingly, if a developer requires a private state to be modifiable by users Singleton is a private state variable that is unique in a way. When a Singleton is initialized, a note is created to represent its value. And the way to update the value is to destroy the current note, and create a new one with the updated value. -Like for public state, we define the struct to have context, a storage slot and `note_interface` specifying how the note should be constructed and manipulated. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr). +Like for public state, we define the struct to have context and a storage slot. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr). An example of singleton usage in the account contracts is keeping track of public keys. The `Singleton` is added to the `Storage` struct as follows: @@ -74,7 +78,7 @@ An example of singleton usage in the account contracts is keeping track of publi ### `new` -As part of the initialization of the `Storage` struct, the `Singleton` is created as follows, here at the specified storage slot and with the `NoteInterface` for `CardNote`. +As part of the initialization of the `Storage` struct, the `Singleton` is created as follows at the specified storage slot. #include_code start_vars_singleton /yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/syntax/storage/public_state.md b/docs/docs/developers/contracts/syntax/storage/public_state.md index fa66f66ec6f..3218d9a7bab 100644 --- a/docs/docs/developers/contracts/syntax/storage/public_state.md +++ b/docs/docs/developers/contracts/syntax/storage/public_state.md @@ -8,17 +8,14 @@ For a higher level overview of the state model in Aztec, see the [state model](. ## Overview -The `PublicState` struct is generic over the variable type `T` and its serialized size `T_SERIALIZED_LEN`. +The `PublicState` struct is generic over the variable type `T`. The type *must* implement Serialize and Deserialize traits, as specified here: -:::info -Currently, the length of the types must be specified when declaring the storage struct but the intention is that this will be inferred in the future. -::: +#include_code serialize /yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr rust +#include_code deserialize /yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr rust The struct contains a `storage_slot` which, similar to Ethereum, is used to figure out _where_ in storage the variable is located. Notice that while we don't have the exact same [state model](../../../../learn/concepts/hybrid_state/main.md) as EVM chains it will look similar from the contract developers point of view. -Beyond the struct, the `PublicState` also contains `serialization_methods`, which is a struct with methods that instruct the `PublicState` how to serialize and deserialize the variable. You can find the details of `PublicState` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr). - -The Aztec.nr library provides serialization methods for various common types. +You can find the details of `PublicState` in the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr). :::info An example using a larger struct can be found in the [lending example](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/contracts/lending_contract)'s use of an [`Asset`](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/noir-contracts/contracts/lending_contract/src/asset.nr). @@ -26,7 +23,7 @@ An example using a larger struct can be found in the [lending example](https://g ### `new` -When declaring the storage for `T` as a persistent public storage variable, we use the `PublicState::new()` constructor. As seen below, this takes the `storage_slot` and the `serialization_methods` as arguments along with the [`Context`](../context.mdx), which in this case is used to share interface with other structures. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr). +When declaring the storage for `T` as a persistent public storage variable, we use the `PublicState::new()` constructor. As seen below, this takes the `storage_slot` and the [`Context`](../context.mdx), which in this case is used to share interface with other structures. You can view the implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr). #### Single value example @@ -68,7 +65,7 @@ mapping(address => bool) internal minters; ### `read` -On the `PublicState` structs we have a `read` method to read the value at the location in storage and using the specified deserialization method to deserialize it. +On the `PublicState` structs we have a `read` method to read the value at the location in storage. #### Reading from our `admin` example diff --git a/docs/docs/developers/testing/cheat_codes.md b/docs/docs/developers/testing/cheat_codes.md index d789872625e..982020d4ae1 100644 --- a/docs/docs/developers/testing/cheat_codes.md +++ b/docs/docs/developers/testing/cheat_codes.md @@ -468,7 +468,7 @@ struct Storage { impl Storage { fn init() -> Self { Storage { - balances: Map::new(1, |slot| PublicState::new(slot, FieldSerializationMethods)), + balances: Map::new(1, |slot| PublicState::new(slot)), } } } @@ -500,13 +500,13 @@ Note: One Field element occupies a storage slot. Hence, structs with multiple fi ```rust struct Storage { - balances: Map>, + balances: Map>, } impl Storage { - fn init() -> Self { + fn init(context: Context) -> Self { Storage { - balances: Map::new(1, |slot| PublicState::new(slot, FieldSerializationMethods)), + balances: Map::new(context, 1, |context, slot| PublicState::new(context, slot)), } } } diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index 27ce57c8fbe..3a867ab7a70 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -235,7 +235,7 @@ Below the dependencies, paste the following Storage struct: Reading through the storage variables: -- `admin` a single Field value stored in public state. `FIELD_SERIALIZED_LEN` indicates the length of the variable, which is 1 in this case because it's a single Field element. A `Field` is basically an unsigned integer with a maximum value determined by the underlying cryptographic curve. +- `admin` a single Field value stored in public state. A `Field` is basically an unsigned integer with a maximum value determined by the underlying cryptographic curve. - `minters` is a mapping of Fields in public state. This will store whether an account is an approved minter on the contract. - `balances` is a mapping of private balances. Private balances are stored in a `Set` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. - `total_supply` is a Field value stored in public state and represents the total number of tokens minted. @@ -248,8 +248,6 @@ You can read more about it [here](../contracts/syntax/storage/main.md). Once we have Storage defined, we need to specify how to initialize it. The `init` method creates and initializes an instance of `Storage`. We define an initialization method for each of the storage variables defined above. Storage initialization is generic and can largely be reused for similar types, across different contracts, but it is important to note that each storage variable specifies it's storage slot, starting at 1. -Also, the public storage variables define the type that they store by passing the methods by which they are serialized. Because all `PublicState` in this contract is storing Field elements, each storage variable takes `FieldSerializationMethods`. - #include_code storage_init /yarn-project/noir-contracts/contracts/token_contract/src/main.nr rust ## Functions diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 54a95d598f9..bea84d5c980 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -6,6 +6,304 @@ keywords: [sandbox, cli, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## 0.22.0 + +### [Aztec.nr] `Serialize`, `Deserialize`, `NoteInterface` as Traits, removal of SerializationMethods and SERIALIZED_LEN + +Storage definition and initialization has been simplified. Previously: + +```rust +struct Storage { + leader: PublicState, + legendary_card: Singleton, + profiles: Map>, + test: Set, + imm_singleton: ImmutableSingleton, +} + +impl Storage { + fn init(context: Context) -> Self { + Storage { + leader: PublicState::new( + context, + 1, + LeaderSerializationMethods, + ), + legendary_card: Singleton::new(context, 2, CardNoteMethods), + profiles: Map::new( + context, + 3, + |context, slot| { + Singleton::new(context, slot, CardNoteMethods) + }, + ), + test: Set::new(context, 4, CardNoteMethods), + imm_singleton: ImmutableSingleton::new(context, 4, CardNoteMethods), + } + } + } +``` + +Now: + +```rust +struct Storage { + leader: PublicState, + legendary_card: Singleton, + profiles: Map>, + test: Set, + imm_singleton: ImmutableSingleton, +} + +impl Storage { + fn init(context: Context) -> Self { + Storage { + leader: PublicState::new( + context, + 1 + ), + legendary_card: Singleton::new(context, 2), + profiles: Map::new( + context, + 3, + |context, slot| { + Singleton::new(context, slot) + }, + ), + test: Set::new(context, 4), + imm_singleton: ImmutableSingleton::new(context, 4), + } + } +} +``` + +For this to work, Notes must implement Serialize, Deserialize and NoteInterface Traits. Previously: + +```rust +use dep::aztec::protocol_types::address::AztecAddress; +use dep::aztec::{ + note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, + }, + oracle::{ + nullifier_key::get_nullifier_secret_key, + get_public_key::get_public_key, + }, + log::emit_encrypted_log, + hash::pedersen_hash, + context::PrivateContext, +}; + +// Shows how to create a custom note + +global CARD_NOTE_LEN: Field = 1; + +impl CardNote { + pub fn new(owner: AztecAddress) -> Self { + CardNote { + owner, + } + } + + pub fn serialize(self) -> [Field; CARD_NOTE_LEN] { + [self.owner.to_field()] + } + + pub fn deserialize(serialized_note: [Field; CARD_NOTE_LEN]) -> Self { + CardNote { + owner: AztecAddress::from_field(serialized_note[1]), + } + } + + pub fn compute_note_hash(self) -> Field { + pedersen_hash([ + self.owner.to_field(), + ],0) + } + + pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(CardNoteMethods, self); + let secret = context.request_nullifier_secret_key(self.owner); + pedersen_hash([ + note_hash_for_nullify, + secret.high, + secret.low, + ],0) + } + + pub fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(CardNoteMethods, self); + let secret = get_nullifier_secret_key(self.owner); + pedersen_hash([ + note_hash_for_nullify, + secret.high, + secret.low, + ],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(serialized_note: [Field; CARD_NOTE_LEN]) -> CardNote { + CardNote::deserialize(serialized_note) +} + +fn serialize(note: CardNote) -> [Field; CARD_NOTE_LEN] { + note.serialize() +} + +fn compute_note_hash(note: CardNote) -> Field { + note.compute_note_hash() +} + +fn compute_nullifier(note: CardNote, context: &mut PrivateContext) -> Field { + note.compute_nullifier(context) +} + +fn compute_nullifier_without_context(note: CardNote) -> Field { + note.compute_nullifier_without_context() +} + +fn get_header(note: CardNote) -> NoteHeader { + note.header +} + +fn set_header(note: &mut CardNote, header: NoteHeader) { + note.set_header(header) +} + +// Broadcasts the note as an encrypted log on L1. +fn broadcast(context: &mut PrivateContext, slot: Field, note: CardNote) { + note.broadcast(context, slot); +} + +global CardNoteMethods = NoteInterface { + deserialize, + serialize, + compute_note_hash, + compute_nullifier, + compute_nullifier_without_context, + get_header, + set_header, + broadcast, +}; +``` + +Now: + +```rust +use dep::aztec::{ + note::{ + note_header::NoteHeader, + note_interface::NoteInterface, + utils::compute_note_hash_for_read_or_nullify, + }, + oracle::{ + nullifier_key::get_nullifier_secret_key, + get_public_key::get_public_key, + }, + log::emit_encrypted_log, + hash::pedersen_hash, + context::PrivateContext, + protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize, Empty} + } +}; + +// Shows how to create a custom note + +global CARD_NOTE_LEN: Field = 1; + +impl CardNote { + pub fn new(owner: AztecAddress) -> Self { + CardNote { + owner, + } + } +} + +impl Serialize for CardNote { + fn serialize(self) -> [Field; CARD_NOTE_LEN] { + [self.owner.to_field()] + } +} + +impl Deserialize for CardNote { + fn deserialize(serialized_note: [Field; CARD_NOTE_LEN]) -> Self { + CardNote { + owner: AztecAddress::from_field(serialized_note[2]), + } + } +} + +impl NoteInterface for CardNote { + fn compute_note_hash(self) -> Field { + pedersen_hash([ + self.owner.to_field(), + ],0) + } + + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); + let secret = context.request_nullifier_secret_key(self.owner); + pedersen_hash([ + note_hash_for_nullify, + secret.high, + secret.low, + ],0) + } + + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); + let secret = get_nullifier_secret_key(self.owner); + pedersen_hash([ + note_hash_for_nullify, + secret.high, + secret.low, + ],0) + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + fn get_header(note: CardNote) -> NoteHeader { + note.header + } + + // Broadcasts the note as an encrypted log on L1. + 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(), + ); + } +} +``` + +Public state must implement Serialize and Deserialize traits. + ## 0.20.0 ### [Aztec.nr] Changes to `NoteInterface` diff --git a/yarn-project/aztec-nr/address-note/src/address_note.nr b/yarn-project/aztec-nr/address-note/src/address_note.nr index 199cbd7b078..3dc945793f2 100644 --- a/yarn-project/aztec-nr/address-note/src/address_note.nr +++ b/yarn-project/aztec-nr/address-note/src/address_note.nr @@ -2,7 +2,10 @@ use dep::aztec::log::emit_encrypted_log; // docs:end:encrypted_import use dep::aztec::{ - protocol_types::address::AztecAddress, + protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize, Empty} + }, note::{ note_header::NoteHeader, note_interface::NoteInterface, @@ -14,7 +17,7 @@ use dep::aztec::{ get_public_key::get_public_key, }, hash::pedersen_hash, - context::PrivateContext, + context::PrivateContext }; global ADDRESS_NOTE_LEN: Field = 3; @@ -28,24 +31,14 @@ struct AddressNote { header: NoteHeader, } -impl AddressNote { - pub fn new(address: AztecAddress, owner: AztecAddress) -> Self { - let randomness = rand(); - AddressNote { - address, - owner, - randomness, - header: NoteHeader::empty(), - } - } -// docs:end:address_note_def - - - pub fn serialize(self) -> [Field; ADDRESS_NOTE_LEN]{ +impl Serialize for AddressNote { + fn serialize(self) -> [Field; ADDRESS_NOTE_LEN]{ [self.address.to_field(), self.owner.to_field(), self.randomness] } +} - pub fn deserialize(serialized_note: [Field; ADDRESS_NOTE_LEN]) -> Self { +impl Deserialize for AddressNote { + fn deserialize(serialized_note: [Field; ADDRESS_NOTE_LEN]) -> Self { AddressNote { address: AztecAddress::from_field(serialized_note[0]), owner: AztecAddress::from_field(serialized_note[1]), @@ -53,14 +46,16 @@ impl AddressNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for AddressNote { + 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, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(AddressNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -70,8 +65,8 @@ impl AddressNote { ],0) } - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(AddressNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -81,12 +76,16 @@ impl AddressNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(note: Self) -> NoteHeader { + note.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { let encryption_pub_key = get_public_key(self.owner); // docs:start:encrypted emit_encrypted_log( @@ -100,46 +99,15 @@ impl AddressNote { } } -fn deserialize(serialized_note: [Field; ADDRESS_NOTE_LEN]) -> AddressNote { - AddressNote::deserialize(serialized_note) -} - -fn serialize(note: AddressNote) -> [Field; ADDRESS_NOTE_LEN] { - note.serialize() -} - -fn compute_note_hash(note: AddressNote) -> Field { - note.compute_note_hash() -} - -fn compute_nullifier(note: AddressNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: AddressNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: AddressNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut AddressNote, header: NoteHeader) { - note.set_header(header); -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: AddressNote) { - note.broadcast(context, slot); +impl AddressNote { + pub fn new(address: AztecAddress, owner: AztecAddress) -> Self { + let randomness = rand(); + AddressNote { + address, + owner, + randomness, + header: NoteHeader::empty(), + } + } +// docs:end:address_note_def } - -global AddressNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/aztec-nr/authwit/src/account.nr b/yarn-project/aztec-nr/authwit/src/account.nr index 21c13e3c8ef..790aee2b662 100644 --- a/yarn-project/aztec-nr/authwit/src/account.nr +++ b/yarn-project/aztec-nr/authwit/src/account.nr @@ -1,6 +1,5 @@ use dep::aztec::context::{PrivateContext, PublicContext, Context}; use dep::aztec::state_vars::{map::Map, public_state::PublicState}; -use dep::aztec::types::type_serialization::bool_serialization::{BoolSerializationMethods,BOOL_SERIALIZED_LEN}; use crate::entrypoint::EntrypointPayload; use crate::auth::IS_VALID_SELECTOR; @@ -8,7 +7,7 @@ use crate::auth::IS_VALID_SELECTOR; struct AccountActions { context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool, - approved_action: Map>, + approved_action: Map>, } impl AccountActions { @@ -20,7 +19,7 @@ impl AccountActions { context, approved_action_storage_slot, |context, slot| { - PublicState::new(context, slot, BoolSerializationMethods) + PublicState::new(context, slot) }, ), } diff --git a/yarn-project/aztec-nr/authwit/src/entrypoint.nr b/yarn-project/aztec-nr/authwit/src/entrypoint.nr index 82c3f5f6e2f..05ca66240f0 100644 --- a/yarn-project/aztec-nr/authwit/src/entrypoint.nr +++ b/yarn-project/aztec-nr/authwit/src/entrypoint.nr @@ -12,6 +12,7 @@ use dep::aztec::protocol_types::{ address::AztecAddress, constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, + traits::{Hash, Serialize} }; global ACCOUNT_MAX_CALLS: Field = 4; @@ -27,11 +28,13 @@ struct FunctionCall { is_public: bool, } -impl FunctionCall { +impl Serialize for FunctionCall { fn serialize(self) -> [Field; FUNCTION_CALL_SIZE] { [self.args_hash, self.function_selector.to_field(), self.target_address.to_field(), self.is_public as Field] } +} +impl FunctionCall { fn to_be_bytes(self) -> [u8; FUNCTION_CALL_SIZE_IN_BYTES] { let mut bytes: [u8; FUNCTION_CALL_SIZE_IN_BYTES] = [0; FUNCTION_CALL_SIZE_IN_BYTES]; let args_hash_bytes = self.args_hash.to_be_bytes(32); @@ -58,14 +61,7 @@ struct EntrypointPayload { } // docs:end:entrypoint-struct -impl EntrypointPayload { - fn hash(self) -> Field { - pedersen_hash( - self.serialize(), - GENERATOR_INDEX__SIGNATURE_PAYLOAD - ) - } - +impl Serialize for EntrypointPayload { // Serializes the entrypoint struct fn serialize(self) -> [Field; ENTRYPOINT_PAYLOAD_SIZE] { let mut fields: BoundedVec = BoundedVec::new(0); @@ -75,7 +71,18 @@ impl EntrypointPayload { fields.push(self.nonce); fields.storage } +} + +impl Hash for EntrypointPayload { + fn hash(self) -> Field { + pedersen_hash( + self.serialize(), + GENERATOR_INDEX__SIGNATURE_PAYLOAD + ) + } +} +impl EntrypointPayload { // Serializes the payload as an array of bytes. Useful for hashing with sha256. fn to_be_bytes(self) -> [u8; ENTRYPOINT_PAYLOAD_SIZE_IN_BYTES] { let mut bytes: [u8; ENTRYPOINT_PAYLOAD_SIZE_IN_BYTES] = [0; ENTRYPOINT_PAYLOAD_SIZE_IN_BYTES]; diff --git a/yarn-project/aztec-nr/aztec/src/abi.nr b/yarn-project/aztec-nr/aztec/src/abi.nr index 74ba77db97e..6e194584313 100644 --- a/yarn-project/aztec-nr/aztec/src/abi.nr +++ b/yarn-project/aztec-nr/aztec/src/abi.nr @@ -6,6 +6,7 @@ use dep::protocol_types::{ }, contrakt::deployment_data::ContractDeploymentData, hash::hash_args, + traits::{Hash, Serialize}, header::Header, }; @@ -16,7 +17,7 @@ struct PrivateGlobalVariables { } // docs:end:private-global-variables -impl PrivateGlobalVariables { +impl Serialize<2> for PrivateGlobalVariables { fn serialize(self) -> [Field; 2] { [self.chain_id, self.version] } @@ -31,7 +32,7 @@ struct PublicGlobalVariables { } // docs:end:public-global-variables -impl PublicGlobalVariables { +impl Serialize<4> for PublicGlobalVariables { fn serialize(self) -> [Field; 4] { [self.chain_id, self.version, self.block_number, self.timestamp] } @@ -61,6 +62,12 @@ struct Hasher { fields: [Field], } +impl Hash for Hasher { + fn hash(self) -> Field { + hash_args(self.fields) + } +} + impl Hasher { pub fn new()-> Self { Self { fields: [] } @@ -75,8 +82,4 @@ impl Hasher { self.fields = self.fields.push_back(fields[i]); } } - - pub fn hash(self) -> Field { - hash_args(self.fields) - } } diff --git a/yarn-project/aztec-nr/aztec/src/context.nr b/yarn-project/aztec-nr/aztec/src/context.nr index 777c6ec1b54..9a838bc8b41 100644 --- a/yarn-project/aztec-nr/aztec/src/context.nr +++ b/yarn-project/aztec-nr/aztec/src/context.nr @@ -330,10 +330,10 @@ impl PrivateContext { }, args_hash: reader.read(), return_values: reader.read_array([0; RETURN_VALUES_LENGTH]), // +1 - read_requests: reader.read_struct_array(SideEffect::deserialise, [SideEffect::empty(); MAX_READ_REQUESTS_PER_CALL]), - nullifier_key_validation_requests: reader.read_struct_array(NullifierKeyValidationRequest::deserialise, [NullifierKeyValidationRequest::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL]), - new_commitments: reader.read_struct_array(SideEffect::deserialise, [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL]), - new_nullifiers: reader.read_struct_array(SideEffectLinkedToNoteHash::deserialise, [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL]), + read_requests: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_READ_REQUESTS_PER_CALL]), + nullifier_key_validation_requests: reader.read_struct_array(NullifierKeyValidationRequest::deserialize, [NullifierKeyValidationRequest::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL]), + new_commitments: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_NEW_COMMITMENTS_PER_CALL]), + new_nullifiers: reader.read_struct_array(SideEffectLinkedToNoteHash::deserialize, [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL]), private_call_stack_hashes: reader.read_array([0; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]), public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), diff --git a/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr index 19493952f7f..15a2acc44ed 100644 --- a/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr +++ b/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr @@ -30,12 +30,11 @@ pub fn prove_note_commitment_inclusion( } pub fn prove_note_inclusion( - note_interface: NoteInterface, note_with_header: Note, block_number: u32, // The block at which we'll prove that the note exists context: PrivateContext -) { - let note_commitment = compute_note_hash_for_read_or_nullify(note_interface, note_with_header); +) where Note: NoteInterface { + let note_commitment = compute_note_hash_for_read_or_nullify(note_with_header); prove_note_commitment_inclusion(note_commitment, block_number, context); } diff --git a/yarn-project/aztec-nr/aztec/src/history/note_validity.nr b/yarn-project/aztec-nr/aztec/src/history/note_validity.nr index 30abac51c74..6742771d705 100644 --- a/yarn-project/aztec-nr/aztec/src/history/note_validity.nr +++ b/yarn-project/aztec-nr/aztec/src/history/note_validity.nr @@ -9,11 +9,10 @@ use crate::{ // A helper function that proves that a note is valid at the given block number pub fn prove_note_validity( - note_interface: NoteInterface, note_with_header: Note, block_number: u32, // The block at which we'll prove that the note exists context: &mut PrivateContext -) { - prove_note_inclusion(note_interface, note_with_header, block_number, *context); - prove_note_not_nullified(note_interface, note_with_header, block_number, context); +) where Note: NoteInterface { + prove_note_inclusion(note_with_header, block_number, *context); + prove_note_not_nullified(note_with_header, block_number, context); } diff --git a/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr index 812165a5c74..0c40d4d648b 100644 --- a/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr +++ b/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr @@ -50,12 +50,11 @@ pub fn prove_nullifier_non_inclusion( } pub fn prove_note_not_nullified( - note_interface: NoteInterface, note_with_header: Note, block_number: u32, // The block at which we'll prove that the note was not nullified context: &mut PrivateContext -) { - let nullifier = compute_siloed_nullifier(note_interface, note_with_header, context); +) where Note: NoteInterface { + let nullifier = compute_siloed_nullifier(note_with_header, context); prove_nullifier_non_inclusion(nullifier, block_number, *context); } diff --git a/yarn-project/aztec-nr/aztec/src/note/lifecycle.nr b/yarn-project/aztec-nr/aztec/src/note/lifecycle.nr index d91154e72d8..75d7bfcf363 100644 --- a/yarn-project/aztec-nr/aztec/src/note/lifecycle.nr +++ b/yarn-project/aztec-nr/aztec/src/note/lifecycle.nr @@ -9,63 +9,51 @@ use crate::note::{ utils::compute_note_hash_for_read_or_nullify, }; use crate::oracle::notes::{notify_created_note, notify_nullified_note}; +use dep::protocol_types::traits::{Serialize, Deserialize}; pub fn create_note( context: &mut PrivateContext, storage_slot: Field, note: &mut Note, - note_interface: NoteInterface, broadcast: bool -) { +) where Note: NoteInterface + Serialize + Deserialize { let contract_address = (*context).this_address(); let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true }; - let set_header = note_interface.set_header; - set_header(note, header); + // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed + Note::set_header(note, header); // As `is_transient` is true, this will compute the inner note hsah - let inner_note_hash = compute_note_hash_for_read_or_nullify(note_interface, *note); + let inner_note_hash = compute_note_hash_for_read_or_nullify(*note); - let serialize = note_interface.serialize; - let serialized_note = serialize(*note); + // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088 + let serialized_note: [Field; N] = Note::serialize(*note); assert(notify_created_note(storage_slot, serialized_note, inner_note_hash) == 0); context.push_new_note_hash(inner_note_hash); if broadcast { - let broadcast = note_interface.broadcast; - broadcast(context, storage_slot, *note); + Note::broadcast(*note, context, storage_slot); } } -pub fn create_note_hash_from_public( - context: &mut PublicContext, - storage_slot: Field, - note: &mut Note, - note_interface: NoteInterface -) { +pub fn create_note_hash_from_public(context: &mut PublicContext, storage_slot: Field, note: &mut Note) where Note: NoteInterface { let contract_address = (*context).this_address(); let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true }; - let set_header = note_interface.set_header; - set_header(note, header); - let inner_note_hash = compute_note_hash_for_read_or_nullify(note_interface, *note); + // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed + Note::set_header(note, header); + let inner_note_hash = compute_note_hash_for_read_or_nullify(*note); context.push_new_note_hash(inner_note_hash); } -pub fn destroy_note( - context: &mut PrivateContext, - note: Note, - note_interface: NoteInterface -) { +pub fn destroy_note(context: &mut PrivateContext, note: Note) where Note: NoteInterface { let mut nullifier = 0; let mut nullified_commitment: Field = 0; - let compute_nullifier = note_interface.compute_nullifier; - nullifier = compute_nullifier(note, context); + nullifier = note.compute_nullifier(context); // We also need the note commitment corresponding to the "nullifier" - let get_header = note_interface.get_header; - let header = get_header(note); + let header = note.get_header(); // `nullified_commitment` is used to inform the kernel which pending commitment // the nullifier corresponds to so they can be matched and both squashed/deleted. // nonzero nonce implies "persistable" nullifier (nullifies a persistent/in-tree @@ -73,7 +61,7 @@ pub fn destroy_note( // just siloes and forwards the nullifier to its output. if (header.is_transient) { // TODO(1718): Can we reuse the note commitment computed in `compute_nullifier`? - nullified_commitment = compute_note_hash_for_read_or_nullify(note_interface, note); + nullified_commitment = compute_note_hash_for_read_or_nullify(note); } assert(notify_nullified_note(nullifier, nullified_commitment) == 0); diff --git a/yarn-project/aztec-nr/aztec/src/note/note_getter.nr b/yarn-project/aztec-nr/aztec/src/note/note_getter.nr index 441f77f0d1f..a442aad9f83 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_getter.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_getter.nr @@ -1,10 +1,13 @@ use dep::std::option::Option; -use dep::protocol_types::constants::{ - MAX_READ_REQUESTS_PER_CALL, - GET_NOTE_ORACLE_RETURN_LENGTH, - GET_NOTES_ORACLE_RETURN_LENGTH, - MAX_NOTES_PER_PAGE, - VIEW_NOTE_ORACLE_RETURN_LENGTH, +use dep::protocol_types::{ + constants::{ + MAX_READ_REQUESTS_PER_CALL, + GET_NOTE_ORACLE_RETURN_LENGTH, + GET_NOTES_ORACLE_RETURN_LENGTH, + MAX_NOTES_PER_PAGE, + VIEW_NOTE_ORACLE_RETURN_LENGTH, + }, + traits::{Deserialize, Serialize} }; use crate::context::PrivateContext; use crate::note::{ @@ -19,11 +22,9 @@ use crate::types::vec::BoundedVec; fn check_note_header( context: PrivateContext, storage_slot: Field, - note_interface: NoteInterface, note: Note -) { - let get_header = note_interface.get_header; - let header = get_header(note); +) where Note: NoteInterface { + let header = note.get_header(); let contract_address = context.this_address(); assert(header.contract_address.eq(contract_address)); assert(header.storage_slot == storage_slot); @@ -72,14 +73,13 @@ fn check_notes_order( pub fn get_note( context: &mut PrivateContext, - storage_slot: Field, - note_interface: NoteInterface -) -> Note { - let note = get_note_internal(storage_slot, note_interface); + storage_slot: Field +) -> Note where Note: NoteInterface + Deserialize { + let note = get_note_internal(storage_slot); - check_note_header(*context, storage_slot, note_interface, note); + check_note_header(*context, storage_slot, note); - let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note_interface, note); + let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note); context.push_read_request(note_hash_for_read_request); note @@ -88,26 +88,24 @@ pub fn get_note( pub fn get_notes( context: &mut PrivateContext, storage_slot: Field, - note_interface: NoteInterface, options: NoteGetterOptions -) -> [Option; MAX_READ_REQUESTS_PER_CALL] { - let opt_notes = get_notes_internal(storage_slot, note_interface, options); +) -> [Option; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface + Deserialize + Serialize { + let opt_notes = get_notes_internal(storage_slot, options); let mut num_notes = 0; let mut prev_fields = [0; N]; for i in 0..opt_notes.len() { let opt_note = opt_notes[i]; if opt_note.is_some() { let note = opt_note.unwrap_unchecked(); - let serialize = note_interface.serialize; - let fields = serialize(note); - check_note_header(*context, storage_slot, note_interface, note); + let fields = note.serialize(); + check_note_header(*context, storage_slot, note); check_note_fields(fields, options.selects); if i != 0 { check_notes_order(prev_fields, fields, options.sorts); } prev_fields = fields; - let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note_interface, note); + let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure // failure if malicious oracle injects 0 nonce here for a "pre-existing" note. context.push_read_request(note_hash_for_read_request); @@ -121,12 +119,12 @@ pub fn get_notes( opt_notes } -unconstrained fn get_note_internal(storage_slot: Field, note_interface: NoteInterface) -> Note { +unconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface + Deserialize { let placeholder_note = [Option::none()]; let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH]; + let placeholder_note_length = [0; N]; oracle::notes::get_notes( storage_slot, - note_interface, 0, [], [], @@ -137,21 +135,21 @@ unconstrained fn get_note_internal(storage_slot: Field, note_interface: 0, // offset NoteStatus.ACTIVE, placeholder_note, - placeholder_fields + placeholder_fields, + placeholder_note_length )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular). } unconstrained fn get_notes_internal( storage_slot: Field, - note_interface: NoteInterface, options: NoteGetterOptions -) -> [Option; MAX_READ_REQUESTS_PER_CALL] { +) -> [Option; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface + Deserialize { let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts); let placeholder_opt_notes = [Option::none(); MAX_READ_REQUESTS_PER_CALL]; let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH]; + let placeholder_note_length = [0; N]; let opt_notes = oracle::notes::get_notes( storage_slot, - note_interface, num_selects, select_by, select_values, @@ -162,7 +160,8 @@ unconstrained fn get_notes_internal( options.offset, options.status, placeholder_opt_notes, - placeholder_fields + placeholder_fields, + placeholder_note_length ); let filter = options.filter; @@ -172,15 +171,14 @@ unconstrained fn get_notes_internal( unconstrained pub fn view_notes( storage_slot: Field, - note_interface: NoteInterface, options: NoteViewerOptions -) -> [Option; MAX_NOTES_PER_PAGE] { +) -> [Option; MAX_NOTES_PER_PAGE] where Note: NoteInterface + Deserialize { let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts); let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE]; let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH]; + let placeholder_note_length = [0; N]; oracle::notes::get_notes( storage_slot, - note_interface, num_selects, select_by, select_values, @@ -191,7 +189,8 @@ unconstrained pub fn view_notes( options.offset, options.status, placeholder_opt_notes, - placeholder_fields + placeholder_fields, + placeholder_note_length ) } diff --git a/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr b/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr index 3010135ebb3..611ac239a34 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_getter_options.nr @@ -1,6 +1,10 @@ use dep::std::option::Option; use crate::types::vec::BoundedVec; -use dep::protocol_types::constants::MAX_READ_REQUESTS_PER_CALL; +use dep::protocol_types::{ + constants::MAX_READ_REQUESTS_PER_CALL, + traits::Deserialize, +}; +use crate::note::note_interface::NoteInterface; struct ComparatorEnum { EQ: u3, @@ -89,7 +93,7 @@ struct NoteGetterOptions { // And finally, a custom filter to refine the outcome further. impl NoteGetterOptions { // This function initializes a NoteGetterOptions that simply returns the maximum number of notes allowed in a call. - pub fn new() -> NoteGetterOptions { + pub fn new() -> NoteGetterOptions where Note: NoteInterface + Deserialize { NoteGetterOptions { selects: BoundedVec::new(Option::none()), sorts: BoundedVec::new(Option::none()), @@ -106,7 +110,7 @@ impl NoteGetterOptions { pub fn with_filter( filter: fn ([Option; MAX_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_READ_REQUESTS_PER_CALL], filter_args: FILTER_ARGS, - ) -> Self { + ) -> Self where Note: NoteInterface + Deserialize { NoteGetterOptions { selects: BoundedVec::new(Option::none()), sorts: BoundedVec::new(Option::none()), diff --git a/yarn-project/aztec-nr/aztec/src/note/note_interface.nr b/yarn-project/aztec-nr/aztec/src/note/note_interface.nr index 614c20d2777..48bd234e035 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_interface.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_interface.nr @@ -1,22 +1,19 @@ use crate::context::PrivateContext; use crate::note::note_header::NoteHeader; -// docs:start:NoteInterface -struct NoteInterface { - deserialize: fn ([Field; N]) -> Note, +// docs:start:note_interface +trait NoteInterface { + fn compute_note_hash(self) -> Field; - serialize: fn (Note) -> [Field; N], + fn get_header(self) -> NoteHeader; - compute_note_hash: fn (Note) -> Field, + fn set_header(&mut self, header: NoteHeader) -> (); - compute_nullifier: fn (Note, &mut PrivateContext) -> Field, + fn compute_nullifier(self, context: &mut PrivateContext) -> Field; - compute_nullifier_without_context: fn (Note) -> Field, + fn compute_nullifier_without_context(self) -> Field; - get_header: fn (Note) -> NoteHeader, - - set_header: fn (&mut Note, NoteHeader) -> (), - - broadcast: fn (&mut PrivateContext, Field, Note) -> (), + fn broadcast(self, context: &mut PrivateContext, slot: Field) -> (); } -// docs:end:NoteInterface \ No newline at end of file +// docs:end:note_interface + diff --git a/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr b/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr index 4b1c8949f3c..5677b33f429 100644 --- a/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr +++ b/yarn-project/aztec-nr/aztec/src/note/note_viewer_options.nr @@ -1,7 +1,11 @@ use dep::std::option::Option; -use dep::protocol_types::constants::MAX_NOTES_PER_PAGE; use crate::note::note_getter_options::{Select, Sort, Comparator, NoteStatus}; use crate::types::vec::BoundedVec; +use dep::protocol_types::{ + constants::MAX_NOTES_PER_PAGE, + traits::Deserialize, +}; +use crate::note::note_interface::NoteInterface; // docs:start:NoteViewerOptions struct NoteViewerOptions { @@ -14,7 +18,7 @@ struct NoteViewerOptions { // docs:end:NoteViewerOptions impl NoteViewerOptions { - pub fn new() -> NoteViewerOptions { + pub fn new() -> NoteViewerOptions where Note: NoteInterface + Deserialize { NoteViewerOptions { selects: BoundedVec::new(Option::none()), sorts: BoundedVec::new(Option::none()), diff --git a/yarn-project/aztec-nr/aztec/src/note/utils.nr b/yarn-project/aztec-nr/aztec/src/note/utils.nr index e38a141e6cd..148657752bb 100644 --- a/yarn-project/aztec-nr/aztec/src/note/utils.nr +++ b/yarn-project/aztec-nr/aztec/src/note/utils.nr @@ -15,6 +15,7 @@ use dep::protocol_types::{ GENERATOR_INDEX__SILOED_COMMITMENT, }, hash::pedersen_hash, + traits::{Deserialize, Serialize}, }; fn compute_inner_hash(storage_slot: Field, note_hash: Field) -> Field { @@ -32,89 +33,76 @@ fn compute_unique_hash(nonce: Field, siloed_note_hash: Field) -> Field { pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_COMMITMENT) } -fn compute_inner_note_hash(note_interface: NoteInterface, note: Note) -> Field { - let get_header = note_interface.get_header; - let header = get_header(note); - - let compute_note_hash = note_interface.compute_note_hash; - let note_hash = compute_note_hash(note); +fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface { + let header = note.get_header(); + let note_hash = note.compute_note_hash(); compute_inner_hash(header.storage_slot, note_hash) } -fn compute_siloed_note_hash(note_interface: NoteInterface, note_with_header: Note) -> Field { - let get_header = note_interface.get_header; - let header = get_header(note_with_header); +fn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { + let header = note_with_header.get_header(); - let inner_note_hash = compute_inner_note_hash(note_interface, note_with_header); + let inner_note_hash = compute_inner_note_hash(note_with_header); compute_siloed_hash(header.contract_address, inner_note_hash) } -fn compute_unique_siloed_note_hash(note_interface: NoteInterface, note_with_header: Note) -> Field { - let get_header = note_interface.get_header; - let header = get_header(note_with_header); +fn compute_unique_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { + let header = note_with_header.get_header(); - let siloed_note_hash = compute_siloed_note_hash(note_interface, note_with_header); + let siloed_note_hash = compute_siloed_note_hash(note_with_header); compute_unique_hash(header.nonce, siloed_note_hash) } -pub fn compute_siloed_nullifier( - note_interface: NoteInterface, +pub fn compute_siloed_nullifier( note_with_header: Note, context: &mut PrivateContext -) -> Field { - let get_header = note_interface.get_header; - let header = get_header(note_with_header); - - let compute_nullifier = note_interface.compute_nullifier; - let inner_nullifier = compute_nullifier(note_with_header, context); +) -> Field where Note: NoteInterface { + let header = note_with_header.get_header(); + let inner_nullifier = note_with_header.compute_nullifier(context); let input = [header.contract_address.to_field(), inner_nullifier]; pedersen_hash(input, GENERATOR_INDEX__OUTER_NULLIFIER) } -pub fn compute_note_hash_for_read_or_nullify(note_interface: NoteInterface, note_with_header: Note) -> Field { - let get_header = note_interface.get_header; - let header = get_header(note_with_header); +pub fn compute_note_hash_for_read_or_nullify(note: Note) -> Field where Note: NoteInterface { + let header = note.get_header(); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) if (header.is_transient) { // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address). - compute_inner_note_hash(note_interface, note_with_header) + compute_inner_note_hash(note) } else if (header.nonce == 0) { // If not transient and nonce is zero, that means we are reading a public note. - compute_siloed_note_hash(note_interface, note_with_header) + compute_siloed_note_hash(note) } else { // When nonce is nonzero, that means we are reading a settled note (from tree) created in a // previous TX. So we need the unique_siloed_note_hash which has already been hashed with // contract address and then nonce. This hash will match the existing leaf in the private // data tree, so the kernel can just perform a membership check directly on this hash/leaf. - compute_unique_siloed_note_hash(note_interface, note_with_header) + compute_unique_siloed_note_hash(note) } } -pub fn compute_note_hash_and_nullifier( - note_interface: NoteInterface, +pub fn compute_note_hash_and_nullifier( + deserialize: fn([Field; N]) -> T, note_header: NoteHeader, serialized_note: [Field; S] -) -> [Field; 4] { - let deserialize = note_interface.deserialize; - let set_header = note_interface.set_header; +) -> [Field; 4] where T: NoteInterface { let mut note = deserialize(arr_copy_slice(serialized_note, [0; N], 0)); - set_header(&mut note, note_header); + // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed + T::set_header((&mut note), note_header); - let compute_note_hash = note_interface.compute_note_hash; - let note_hash = compute_note_hash(note); + let note_hash = note.compute_note_hash(); let inner_note_hash = compute_inner_hash(note_header.storage_slot, note_hash); let siloed_note_hash = compute_siloed_hash(note_header.contract_address, inner_note_hash); let unique_siloed_note_hash = compute_unique_hash(note_header.nonce, siloed_note_hash); - let compute_nullifier_without_context = note_interface.compute_nullifier_without_context; - let inner_nullifier = compute_nullifier_without_context(note); + let inner_nullifier = note.compute_nullifier_without_context(); [inner_note_hash, siloed_note_hash, unique_siloed_note_hash, inner_nullifier] } diff --git a/yarn-project/aztec-nr/aztec/src/oracle/get_public_data_witness.nr b/yarn-project/aztec-nr/aztec/src/oracle/get_public_data_witness.nr index 555a8078580..f0c4ce2f8e9 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/get_public_data_witness.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/get_public_data_witness.nr @@ -1,5 +1,8 @@ -use dep::protocol_types::constants::PUBLIC_DATA_TREE_HEIGHT; -use dep::protocol_types::hash::pedersen_hash; +use dep::protocol_types::{ + constants::PUBLIC_DATA_TREE_HEIGHT, + hash::pedersen_hash, + traits::{Hash, Serialize} +}; use crate::utils::arr_copy_slice; global LEAF_PREIMAGE_LENGTH: Field = 4; @@ -14,11 +17,13 @@ struct PublicDataTreeLeafPreimage { next_slot :Field, } -impl PublicDataTreeLeafPreimage { +impl Serialize for PublicDataTreeLeafPreimage { fn serialize(self) -> [Field; LEAF_PREIMAGE_LENGTH] { [self.slot, self.value, self.next_index as Field, self.next_slot] } +} +impl Hash for PublicDataTreeLeafPreimage { fn hash(self) -> Field { // Performs the same hashing as StandardIndexedTree::encodeLeaf(...) pedersen_hash(self.serialize(), 0) @@ -34,10 +39,7 @@ struct PublicDataWitness { #[oracle(getPublicDataTreeWitness)] fn get_public_data_witness_oracle(_block_number: u32, _leaf_slot: Field) -> [Field; PUBLIC_DATA_WITNESS] {} -unconstrained pub fn get_public_data_witness( - block_number: u32, - leaf_slot: Field -) -> PublicDataWitness { +unconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness { let fields = get_public_data_witness_oracle(block_number, leaf_slot); PublicDataWitness { index: fields[0], diff --git a/yarn-project/aztec-nr/aztec/src/oracle/notes.nr b/yarn-project/aztec-nr/aztec/src/oracle/notes.nr index c4f2940f3a2..3c7c7ebb5d3 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/notes.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/notes.nr @@ -5,7 +5,10 @@ use crate::note::{ }; use crate::utils::arr_copy_slice; -use dep::protocol_types::address::AztecAddress; +use dep::protocol_types::{ + address::AztecAddress, + traits::Deserialize +}; #[oracle(notifyCreatedNote)] fn notify_created_note_oracle(_storage_slot: Field, _serialized_note: [Field; N], _inner_note_hash: Field) -> Field {} @@ -69,7 +72,6 @@ unconstrained fn get_notes_oracle_wrapper( unconstrained pub fn get_notes( storage_slot: Field, - note_interface: NoteInterface, num_selects: u8, select_by: [u8; M], select_values: [Field; M], @@ -80,8 +82,9 @@ unconstrained pub fn get_notes( offset: u32, status: u2, mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array. - placeholder_fields: [Field; NS] // TODO: Remove it and use `limit` to initialize the note array. -) -> [Option; S] { + placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array. + _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter +) -> [Option; S] where Note: NoteInterface + Deserialize { let fields = get_notes_oracle_wrapper( storage_slot, num_selects, @@ -97,8 +100,6 @@ unconstrained pub fn get_notes( ); let num_notes = fields[0] as u32; let contract_address = AztecAddress::from_field(fields[1]); - let deserialize = note_interface.deserialize; - let set_header = note_interface.set_header; for i in 0..placeholder_opt_notes.len() { if i as u32 < num_notes { // lengths named as per typescript. @@ -109,8 +110,9 @@ unconstrained pub fn get_notes( let is_transient = fields[read_offset + 1] as bool; let header = NoteHeader { contract_address, nonce, storage_slot, is_transient }; let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2); - let mut note = deserialize(serialized_note); - set_header(&mut note, header); + let mut note = Note::deserialize(serialized_note); + // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed + Note::set_header(&mut note, header); placeholder_opt_notes[i] = Option::some(note); }; } diff --git a/yarn-project/aztec-nr/aztec/src/oracle/storage.nr b/yarn-project/aztec-nr/aztec/src/oracle/storage.nr index abb7766ba91..72bec83be3a 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/storage.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/storage.nr @@ -1,3 +1,5 @@ +use dep::protocol_types::traits::{Deserialize, Serialize}; + #[oracle(storageRead)] fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {} @@ -5,15 +7,13 @@ unconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; storage_read_oracle(_storage_slot, N) } -pub fn storage_read(storage_slot: Field, deserialize: fn([Field; N]) -> T) -> T { - let fields = storage_read_oracle_wrapper(storage_slot); - deserialize(fields) +pub fn storage_read(storage_slot: Field) -> [Field; N] { + storage_read_oracle_wrapper(storage_slot) } #[oracle(storageWrite)] fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {} -// TODO: Remove return value. unconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) { let _hash = storage_write_oracle(storage_slot, fields); } diff --git a/yarn-project/aztec-nr/aztec/src/state_vars/immutable_singleton.nr b/yarn-project/aztec-nr/aztec/src/state_vars/immutable_singleton.nr index 5bdc4d072d3..187feca45fc 100644 --- a/yarn-project/aztec-nr/aztec/src/state_vars/immutable_singleton.nr +++ b/yarn-project/aztec-nr/aztec/src/state_vars/immutable_singleton.nr @@ -1,7 +1,8 @@ use dep::std::option::Option; use dep::protocol_types::{ address::AztecAddress, - constants::{ + traits::{Serialize, Deserialize}, + constants::{ GENERATOR_INDEX__INITIALIZATION_NULLIFIER, }, hash::pedersen_hash, @@ -17,25 +18,22 @@ use crate::note::{ use crate::oracle::notes::check_nullifier_exists; // docs:start:struct -struct ImmutableSingleton { +struct ImmutableSingleton { context: Option<&mut PrivateContext>, storage_slot: Field, - note_interface: NoteInterface, } // docs:end:struct -impl ImmutableSingleton { +impl ImmutableSingleton { // docs:start:new pub fn new( context: Context, storage_slot: Field, - note_interface: NoteInterface, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); Self { context: context.private, storage_slot, - note_interface, } } // docs:end:new @@ -58,11 +56,11 @@ impl ImmutableSingleton { // docs:end:is_initialized // docs:start:initialize - pub fn initialize( + pub fn initialize( self, note: &mut Note, broadcast: bool, - ) { + ) where Note: NoteInterface + Serialize + Deserialize { let context = self.context.unwrap(); // Nullify the storage slot. @@ -73,24 +71,23 @@ impl ImmutableSingleton { context, self.storage_slot, note, - self.note_interface, broadcast, ); } // docs:end:initialize // docs:start:get_note - pub fn get_note(self) -> Note { + pub fn get_note(self) -> Note where Note: NoteInterface + Deserialize { let context = self.context.unwrap(); let storage_slot = self.storage_slot; - get_note(context, storage_slot, self.note_interface) + get_note(context, storage_slot) } // docs:end:get_note // docs:start:view_note - unconstrained pub fn view_note(self) -> Note { + unconstrained pub fn view_note(self) -> Note where Note: NoteInterface + Deserialize { let options = NoteViewerOptions::new().set_limit(1); - view_notes(self.storage_slot, self.note_interface, options)[0].unwrap() + view_notes(self.storage_slot, options)[0].unwrap() } // docs:end:view_note } diff --git a/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr b/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr index 10970a92c0d..9309f3d9d49 100644 --- a/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr +++ b/yarn-project/aztec-nr/aztec/src/state_vars/public_state.nr @@ -1,46 +1,43 @@ use crate::context::{Context}; use crate::oracle::storage::storage_read; use crate::oracle::storage::storage_write; -use crate::types::type_serialization::TypeSerializationInterface; use dep::std::option::Option; +use dep::protocol_types::traits::{Deserialize, Serialize}; // docs:start:public_state_struct -struct PublicState { +struct PublicState { context: Context, storage_slot: Field, - serialization_methods: TypeSerializationInterface, } // docs:end:public_state_struct -impl PublicState { +impl PublicState { // docs:start:public_state_struct_new pub fn new( // Note: Passing the contexts to new(...) just to have an interface compatible with a Map. context: Context, storage_slot: Field, - serialization_methods: TypeSerializationInterface, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); PublicState { context, storage_slot, - serialization_methods, } } // docs:end:public_state_struct_new // docs:start:public_state_struct_read - pub fn read(self) -> T { - assert(self.context.private.is_none(), "Public state reads only supported in public functions"); - storage_read(self.storage_slot, self.serialization_methods.deserialize) + pub fn read(self) -> T where T: Deserialize { + assert(self.context.private.is_none(), "Public state writes only supported in public functions"); + let fields = storage_read(self.storage_slot); + T::deserialize(fields) } // docs:end:public_state_struct_read // docs:start:public_state_struct_write - pub fn write(self, value: T) { + pub fn write(self, value: T) where T: Serialize { assert(self.context.private.is_none(), "Public state writes only supported in public functions"); - let serialize = self.serialization_methods.serialize; - let fields = serialize(value); + let fields = T::serialize(value); storage_write(self.storage_slot, fields); } // docs:end:public_state_struct_write diff --git a/yarn-project/aztec-nr/aztec/src/state_vars/set.nr b/yarn-project/aztec-nr/aztec/src/state_vars/set.nr index 1d873e1b149..489ccfad838 100644 --- a/yarn-project/aztec-nr/aztec/src/state_vars/set.nr +++ b/yarn-project/aztec-nr/aztec/src/state_vars/set.nr @@ -3,6 +3,7 @@ use crate::abi::PublicContextInputs; use dep::protocol_types::{ constants::{MAX_NOTES_PER_PAGE, MAX_READ_REQUESTS_PER_CALL}, abis::side_effect::{SideEffect, SideEffectLinkedToNoteHash}, + traits::{Deserialize, Serialize}, }; use crate::context::{PrivateContext, PublicContext, Context}; use crate::note::{ @@ -16,51 +17,46 @@ use crate::note::{ }; // docs:start:struct -struct Set { +struct Set { context: Context, storage_slot: Field, - note_interface: NoteInterface, } // docs:end:struct -impl Set { +impl Set { // docs:start:new pub fn new( context: Context, storage_slot: Field, - note_interface: NoteInterface, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); Set { context, storage_slot, - note_interface, } } // docs:end:new // docs:start:insert - pub fn insert(self, + pub fn insert(self, note: &mut Note, broadcast: bool, - ) { + ) where Note: NoteInterface + Deserialize + Serialize { create_note( self.context.private.unwrap(), self.storage_slot, note, - self.note_interface, broadcast, ); } // docs:end:insert // docs:start:insert_from_public - pub fn insert_from_public(self, note: &mut Note) { + pub fn insert_from_public(self, note: &mut Note) where Note: NoteInterface { create_note_hash_from_public( self.context.public.unwrap(), self.storage_slot, note, - self.note_interface, ); } // docs:end:insert_from_public @@ -76,30 +72,28 @@ impl Set { } // docs:start:remove - pub fn remove(self, note: Note) { + pub fn remove(self, note: Note) where Note: NoteInterface { let context = self.context.private.unwrap(); - let note_hash = compute_note_hash_for_read_or_nullify(self.note_interface, note); + let note_hash = compute_note_hash_for_read_or_nullify(note); let has_been_read = context.read_requests.any(|r: SideEffect| r.value == note_hash); assert(has_been_read, "Can only remove a note that has been read from the set."); destroy_note( context, note, - self.note_interface, ); } // docs:end:remove // docs:start:get_notes - pub fn get_notes( + pub fn get_notes( self, options: NoteGetterOptions, - ) -> [Option; MAX_READ_REQUESTS_PER_CALL] { + ) -> [Option; MAX_READ_REQUESTS_PER_CALL] where Note: NoteInterface + Serialize + Deserialize { let storage_slot = self.storage_slot; let opt_notes = get_notes( self.context.private.unwrap(), storage_slot, - self.note_interface, options, ); opt_notes @@ -107,11 +101,11 @@ impl Set { // docs:end:get_notes // docs:start:view_notes - unconstrained pub fn view_notes( + unconstrained pub fn view_notes( self, options: NoteViewerOptions, - ) -> [Option; MAX_NOTES_PER_PAGE] { - view_notes(self.storage_slot, self.note_interface, options) + ) -> [Option; MAX_NOTES_PER_PAGE] where Note: NoteInterface + Deserialize { + view_notes(self.storage_slot, options) } // docs:end:view_notes } diff --git a/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr b/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr index b5a2d3fe280..19b4e91bb5c 100644 --- a/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr +++ b/yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr @@ -6,6 +6,7 @@ use dep::protocol_types::{ GENERATOR_INDEX__INITIALIZATION_NULLIFIER, }, hash::pedersen_hash, + traits::{Serialize, Deserialize}, }; use crate::context::{PrivateContext, PublicContext, Context}; @@ -21,25 +22,22 @@ use crate::oracle::{ }; // docs:start:struct -struct Singleton { +struct Singleton { context: Option<&mut PrivateContext>, - storage_slot: Field, - note_interface: NoteInterface, + storage_slot: Field } // docs:end:struct -impl Singleton { +impl Singleton { // docs:start:new pub fn new( context: Context, storage_slot: Field, - note_interface: NoteInterface, ) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); Self { context: context.private, storage_slot, - note_interface, } } // docs:end:new @@ -64,58 +62,58 @@ impl Singleton { // docs:end:is_initialized // docs:start:initialize - pub fn initialize( + pub fn initialize( self, note: &mut Note, broadcast: bool, - ) { + ) where Note: NoteInterface + Serialize + Deserialize { let context = self.context.unwrap(); // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); context.push_new_nullifier(nullifier, 0); - create_note(context, self.storage_slot, note, self.note_interface, broadcast); + create_note(context, self.storage_slot, note, broadcast); } // docs:end:initialize // docs:start:replace - pub fn replace( + pub fn replace( self, new_note: &mut Note, broadcast: bool, - ) { + ) where Note: NoteInterface + Serialize + Deserialize { let context = self.context.unwrap(); - let prev_note = get_note(context, self.storage_slot, self.note_interface); + let prev_note = get_note(context, self.storage_slot); // Nullify previous note. - destroy_note(context, prev_note, self.note_interface); + destroy_note(context, prev_note); // Add replacement note. - create_note(context, self.storage_slot, new_note, self.note_interface, broadcast); + create_note(context, self.storage_slot, new_note, broadcast); } // docs:end:replace // docs:start:get_note - pub fn get_note(self, broadcast: bool) -> Note { + pub fn get_note(self, broadcast: bool) -> Note where Note: NoteInterface + Serialize + Deserialize { let context = self.context.unwrap(); - let mut note = get_note(context, self.storage_slot, self.note_interface); + let mut note = get_note(context, self.storage_slot); // Nullify current note to make sure it's reading the latest note. - destroy_note(context, note, self.note_interface); + destroy_note(context, note); // Add the same note again. // Because a nonce is added to every note in the kernel, its nullifier will be different. - create_note(context, self.storage_slot, &mut note, self.note_interface, broadcast); + create_note(context, self.storage_slot, &mut note, broadcast); note } // docs:end:get_note // docs:start:view_note - unconstrained pub fn view_note(self) -> Note { + unconstrained pub fn view_note(self) -> Note where Note: NoteInterface + Deserialize { let options = NoteViewerOptions::new().set_limit(1); - view_notes(self.storage_slot, self.note_interface, options)[0].unwrap() + view_notes(self.storage_slot, options)[0].unwrap() } // docs:end:view_note } diff --git a/yarn-project/aztec-nr/aztec/src/types.nr b/yarn-project/aztec-nr/aztec/src/types.nr index 18f6888ae32..ae46c9e0c88 100644 --- a/yarn-project/aztec-nr/aztec/src/types.nr +++ b/yarn-project/aztec-nr/aztec/src/types.nr @@ -1,2 +1 @@ mod vec; // This can/should be moved out into an official noir library -mod type_serialization; diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr deleted file mode 100644 index 016548a544f..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization.nr +++ /dev/null @@ -1,15 +0,0 @@ -mod bool_serialization; -mod field_serialization; -mod u8_serialization; -mod u32_serialization; -mod address_serialization; - -/** - * Before Noir supports traits, a way of specifying the serialization and deserialization methods for a type. - */ -// docs:start:TypeSerializationInterface -struct TypeSerializationInterface { - deserialize: fn ([Field; N]) -> T, - serialize: fn (T) -> [Field; N], -} -// docs:end:TypeSerializationInterface \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/address_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/address_serialization.nr deleted file mode 100644 index 4994bdc0437..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization/address_serialization.nr +++ /dev/null @@ -1,22 +0,0 @@ -use crate::types::type_serialization::TypeSerializationInterface; -use dep::protocol_types::{ - address::{ - AztecAddress, - EthAddress - }, -}; - -global AZTEC_ADDRESS_SERIALIZED_LEN: Field = 1; - -fn deserialize(fields: [Field; AZTEC_ADDRESS_SERIALIZED_LEN]) -> AztecAddress { - AztecAddress::from_field(fields[0]) -} - -fn serialize(value: AztecAddress) -> [Field; AZTEC_ADDRESS_SERIALIZED_LEN] { - [value.to_field()] -} - -global AddressSerializationMethods = TypeSerializationInterface { - deserialize, - serialize, -}; diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/bool_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/bool_serialization.nr deleted file mode 100644 index 255f519234c..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization/bool_serialization.nr +++ /dev/null @@ -1,16 +0,0 @@ -use crate::types::type_serialization::TypeSerializationInterface; - -global BOOL_SERIALIZED_LEN: Field = 1; - -fn deserializeBool(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool { - fields[0] as bool -} - -fn serializeBool(value: bool) -> [Field; BOOL_SERIALIZED_LEN] { - [value as Field] -} - -global BoolSerializationMethods = TypeSerializationInterface { - deserialize: deserializeBool, - serialize: serializeBool, -}; diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/field_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/field_serialization.nr deleted file mode 100644 index 3c13de1112e..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization/field_serialization.nr +++ /dev/null @@ -1,18 +0,0 @@ -use crate::types::type_serialization::TypeSerializationInterface; - -// docs:start:field_serialization -global FIELD_SERIALIZED_LEN: Field = 1; - -fn deserializeField(fields: [Field; FIELD_SERIALIZED_LEN]) -> Field { - fields[0] -} - -fn serializeField(value: Field) -> [Field; FIELD_SERIALIZED_LEN] { - [value] -} - -global FieldSerializationMethods = TypeSerializationInterface { - deserialize: deserializeField, - serialize: serializeField, -}; -// docs:end:field_serialization \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/u32_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/u32_serialization.nr deleted file mode 100644 index 2517532b420..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization/u32_serialization.nr +++ /dev/null @@ -1,16 +0,0 @@ -use crate::types::type_serialization::TypeSerializationInterface; - -global U32_SERIALIZED_LEN: Field = 1; - -fn deserializeU32(fields: [Field; U32_SERIALIZED_LEN]) -> u32 { - fields[0] as u32 -} - -fn serializeU32(value: u32) -> [Field; U32_SERIALIZED_LEN] { - [value as Field] -} - -global U32SerializationMethods = TypeSerializationInterface { - deserialize: deserializeU32, - serialize: serializeU32, -}; diff --git a/yarn-project/aztec-nr/aztec/src/types/type_serialization/u8_serialization.nr b/yarn-project/aztec-nr/aztec/src/types/type_serialization/u8_serialization.nr deleted file mode 100644 index 8011d02675c..00000000000 --- a/yarn-project/aztec-nr/aztec/src/types/type_serialization/u8_serialization.nr +++ /dev/null @@ -1,16 +0,0 @@ -use crate::types::type_serialization::TypeSerializationInterface; - -global U8_SERIALIZED_LEN: Field = 1; - -fn deserializeU8(fields: [Field; U8_SERIALIZED_LEN]) -> u8 { - fields[0] as u8 -} - -fn serializeU8(value: u8) -> [Field; U8_SERIALIZED_LEN] { - [value as Field] -} - -global U8SerializationMethods = TypeSerializationInterface { - deserialize: deserializeU8, - serialize: serializeU8, -}; diff --git a/yarn-project/aztec-nr/compressed-string/src/compressed_string.nr b/yarn-project/aztec-nr/compressed-string/src/compressed_string.nr index 0cf51b8edb2..7f7945d1cfc 100644 --- a/yarn-project/aztec-nr/compressed-string/src/compressed_string.nr +++ b/yarn-project/aztec-nr/compressed-string/src/compressed_string.nr @@ -1,5 +1,7 @@ -use dep::aztec::types::type_serialization::TypeSerializationInterface; -use dep::aztec::protocol_types::utils::field::field_from_bytes; +use dep::aztec::protocol_types::{ + utils::field::field_from_bytes, + traits::{Serialize, Deserialize} +}; use dep::std; // A Fixedsize Compressed String. @@ -8,6 +10,18 @@ struct FieldCompressedString{ value: Field } +impl Serialize<1> for FieldCompressedString { + fn serialize(self) -> [Field; 1] { + [self.value] + } +} + +impl Deserialize<1> for FieldCompressedString { + fn deserialize(input: [Field; 1]) -> Self { + Self { value: input[0] } + } +} + impl FieldCompressedString{ pub fn is_eq(self, other: FieldCompressedString) -> bool { self.value == other.value @@ -29,28 +43,8 @@ impl FieldCompressedString{ } result } - - pub fn serialize(self) -> [Field; 1] { - [self.value] - } - - pub fn deserialize(input: [Field; 1]) -> Self { - Self { value: input[0] } - } } -fn deserialize(fields: [Field; 1]) -> FieldCompressedString { - FieldCompressedString { value: fields[0] } -} - -fn serialize(value: FieldCompressedString) -> [Field; 1] { - value.serialize() -} -global FieldCompressedStringSerializationMethods = TypeSerializationInterface { - deserialize, - serialize, -}; - // The general Compressed String. // Compresses M bytes into N fields. // Can be used for longer strings that don't fit in a single field. diff --git a/yarn-project/aztec-nr/compressed-string/src/lib.nr b/yarn-project/aztec-nr/compressed-string/src/lib.nr index aef2a573fdf..b441f622b40 100644 --- a/yarn-project/aztec-nr/compressed-string/src/lib.nr +++ b/yarn-project/aztec-nr/compressed-string/src/lib.nr @@ -1,4 +1,4 @@ mod compressed_string; use crate::compressed_string::{CompressedString}; -use crate::compressed_string::{FieldCompressedString, FieldCompressedStringSerializationMethods}; +use crate::compressed_string::FieldCompressedString; diff --git a/yarn-project/aztec-nr/easy-private-state/src/easy_private_state.nr b/yarn-project/aztec-nr/easy-private-state/src/easy_private_state.nr index 29feeeb26b0..d6b6fbf650f 100644 --- a/yarn-project/aztec-nr/easy-private-state/src/easy_private_state.nr +++ b/yarn-project/aztec-nr/easy-private-state/src/easy_private_state.nr @@ -6,12 +6,12 @@ use dep::aztec::{ }; use dep::value_note::{ filter::filter_notes_min_sum, - value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN}, + value_note::ValueNote, }; struct EasyPrivateUint { context: Context, - set: Set, + set: Set, storage_slot: Field, } @@ -23,8 +23,7 @@ impl EasyPrivateUint { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); let set = Set { context, - storage_slot, - note_interface: ValueNoteMethods, + storage_slot }; EasyPrivateUint { context, 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 8aa8fbe5520..45b2ba61208 100644 --- a/yarn-project/aztec-nr/field-note/src/field_note.nr +++ b/yarn-project/aztec-nr/field-note/src/field_note.nr @@ -5,6 +5,7 @@ use dep::aztec::{ }, hash::pedersen_hash, context::PrivateContext, + protocol_types::traits::{Serialize, Deserialize}, }; global FIELD_NOTE_LEN: Field = 1; @@ -17,86 +18,58 @@ struct FieldNote { header: NoteHeader, } -impl FieldNote { - pub fn new(value: Field) -> Self { - FieldNote { - value, - header: NoteHeader::empty(), - } - } - - pub fn serialize(self) -> [Field; FIELD_NOTE_LEN]{ +impl Serialize for FieldNote { + fn serialize(self) -> [Field; FIELD_NOTE_LEN]{ [self.value] } +} - pub fn deserialize(serialized_note: [Field; FIELD_NOTE_LEN]) -> Self { +impl Deserialize for FieldNote { + fn deserialize(serialized_note: [Field; FIELD_NOTE_LEN]) -> Self { FieldNote { value: serialized_note[0], header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for FieldNote { + 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: Self, _context: &mut PrivateContext) -> Field { + fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { // This note is expected to be shared between users and for this reason can't be nullified using a secret. 0 } - pub fn compute_nullifier_without_context(_self: Self) -> Field { + fn compute_nullifier_without_context(self) -> Field { // This note is expected to be shared between users and for this reason can't be nullified using a secret. 0 } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } -} - -fn deserialize(serialized_note: [Field; FIELD_NOTE_LEN]) -> FieldNote { - FieldNote::deserialize(serialized_note) -} - -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, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: FieldNote) -> Field { - note.compute_nullifier_without_context() -} -fn get_header(note: FieldNote) -> NoteHeader { - note.header -} + fn get_header(self) -> NoteHeader { + self.header + } -fn set_header(note: &mut FieldNote, header: NoteHeader) { - note.set_header(header); + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + assert( + false, "FieldNote does not support broadcast. Add it to PXE directly using the `.addNote` function." + ); + } } -fn broadcast(context: &mut PrivateContext, slot: Field, note: FieldNote) { - assert( - false, "FieldNote does not support broadcast. Add it to PXE directly using the `.addNote` function." - ); +impl FieldNote { + pub fn new(value: Field) -> Self { + FieldNote { + value, + header: NoteHeader::empty(), + } + } } -global FieldNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/aztec-nr/safe-math/Nargo.toml b/yarn-project/aztec-nr/safe-math/Nargo.toml index 6625680128f..aaa75e68977 100644 --- a/yarn-project/aztec-nr/safe-math/Nargo.toml +++ b/yarn-project/aztec-nr/safe-math/Nargo.toml @@ -4,4 +4,5 @@ authors = [""] compiler_version = ">=0.18.0" type = "lib" -[dependencies] \ No newline at end of file +[dependencies] +aztec = { path = "../aztec" } \ No newline at end of file diff --git a/yarn-project/aztec-nr/safe-math/src/lib.nr b/yarn-project/aztec-nr/safe-math/src/lib.nr index 7e29a39a85e..79dd63eb4b8 100644 --- a/yarn-project/aztec-nr/safe-math/src/lib.nr +++ b/yarn-project/aztec-nr/safe-math/src/lib.nr @@ -1,3 +1,3 @@ mod safe_u120; -use crate::safe_u120::SafeU120; +use crate::safe_u120::{SafeU120, SAFE_U120_SERIALIZED_LEN}; 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 d1ce40a01a6..4ef341bf839 100644 --- a/yarn-project/aztec-nr/safe-math/src/safe_u120.nr +++ b/yarn-project/aztec-nr/safe-math/src/safe_u120.nr @@ -1,4 +1,5 @@ use dep::std::cmp::Eq; +use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; struct SafeU120 { value: u120, @@ -13,6 +14,21 @@ impl Eq for SafeU120 { } } +global SAFE_U120_SERIALIZED_LEN: Field = 1; + +impl Serialize for SafeU120 { + fn serialize(value: SafeU120) -> [Field; SAFE_U120_SERIALIZED_LEN] { + [value.value as Field] + } +} + +impl Deserialize for SafeU120 { + // This is safe when reading from storage IF only correct safeu120 was written to storage + fn deserialize(fields: [Field; SAFE_U120_SERIALIZED_LEN]) -> SafeU120 { + SafeU120 { value: fields[0] as u120 } + } +} + impl SafeU120 { pub fn min() -> Self { Self { diff --git a/yarn-project/aztec-nr/slow-updates-tree/src/slow_map.nr b/yarn-project/aztec-nr/slow-updates-tree/src/slow_map.nr index d2dc5c67830..065ab009197 100644 --- a/yarn-project/aztec-nr/slow-updates-tree/src/slow_map.nr +++ b/yarn-project/aztec-nr/slow-updates-tree/src/slow_map.nr @@ -1,7 +1,6 @@ use dep::aztec::context::{PrivateContext, PublicContext, Context}; -use dep::aztec::types::type_serialization::TypeSerializationInterface; use dep::aztec::oracle::storage::{storage_read, storage_write}; - +use dep::aztec::protocol_types::traits::{Serialize, Deserialize}; use dep::std::hash::pedersen_hash; use dep::std::merkle::compute_merkle_root; use dep::std::option::Option; @@ -20,20 +19,15 @@ struct Leaf { after: Field, } -fn serialize_leaf(leaf: Leaf) -> [Field; 3] { - [leaf.next_change, leaf.before, leaf.after] -} - -fn deserialize_leaf(serialized: [Field; 3]) -> Leaf { - Leaf { next_change: serialized[0], before: serialized[1], after: serialized[2] } +impl Serialize<3> for Leaf { + fn serialize(leaf: Leaf) -> [Field; 3] { + [leaf.next_change, leaf.before, leaf.after] + } } -impl Leaf { - fn serialize(self: Self) -> [Field; 3] { - serialize_leaf(self) - } - fn deserialize(serialized: [Field; 3]) -> Self { - deserialize_leaf(serialized) +impl Deserialize<3> for Leaf { + fn deserialize(serialized: [Field; 3]) -> Leaf { + Leaf { next_change: serialized[0], before: serialized[1], after: serialized[2] } } } @@ -117,7 +111,8 @@ impl SlowMap { } pub fn read_root(self: Self) -> Leaf { - storage_read(self.storage_slot, deserialize_leaf) + let fields = storage_read(self.storage_slot); + Leaf::deserialize(fields) } // Beware that the initial root could include much state that is not shown by the public storage! @@ -147,7 +142,8 @@ impl SlowMap { // docs:start:read_leaf_at pub fn read_leaf_at(self: Self, key: Field) -> Leaf { let derived_storage_slot = pedersen_hash([self.storage_slot, key]); - storage_read(derived_storage_slot, deserialize_leaf) + let fields = storage_read(derived_storage_slot); + Leaf::deserialize(fields) } // docs:end:read_leaf_at diff --git a/yarn-project/aztec-nr/value-note/src/balance_utils.nr b/yarn-project/aztec-nr/value-note/src/balance_utils.nr index cd577b97af7..74c6c79272e 100644 --- a/yarn-project/aztec-nr/value-note/src/balance_utils.nr +++ b/yarn-project/aztec-nr/value-note/src/balance_utils.nr @@ -5,11 +5,11 @@ use dep::aztec::note::{ use dep::aztec::state_vars::set::Set; use crate::value_note::{VALUE_NOTE_LEN, ValueNote}; -unconstrained pub fn get_balance(set: Set) -> Field { +unconstrained pub fn get_balance(set: Set) -> Field { get_balance_with_offset(set, 0) } -unconstrained pub fn get_balance_with_offset(set: Set, offset: u32) -> Field { +unconstrained pub fn get_balance_with_offset(set: Set, offset: u32) -> Field { let mut balance = 0; // docs:start:view_notes let options = NoteViewerOptions::new().set_offset(offset); diff --git a/yarn-project/aztec-nr/value-note/src/utils.nr b/yarn-project/aztec-nr/value-note/src/utils.nr index 277e0b114c3..d7ef7c948dc 100644 --- a/yarn-project/aztec-nr/value-note/src/utils.nr +++ b/yarn-project/aztec-nr/value-note/src/utils.nr @@ -17,7 +17,7 @@ pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteG // Creates a new note for the recipient. // Inserts it to the recipient's set of notes. -pub fn increment(balance: Set, amount: Field, recipient: AztecAddress) { +pub fn increment(balance: Set, amount: Field, recipient: AztecAddress) { let mut note = ValueNote::new(amount, recipient); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. balance.insert(&mut note, amount != 0); @@ -27,7 +27,7 @@ pub fn increment(balance: Set, amount: Field, recipie // Remove those notes. // If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed. // Fail if the sum of the selected notes is less than the amount. -pub fn decrement(balance: Set, amount: Field, owner: AztecAddress) { +pub fn decrement(balance: Set, amount: Field, owner: AztecAddress) { let sum = decrement_by_at_most(balance, amount, owner); assert(sum == amount, "Balance too low"); } @@ -40,11 +40,7 @@ pub fn decrement(balance: Set, amount: Field, owner: // equal `amount`. // // It returns the decremented amount, which should be less than or equal to max_amount. -pub fn decrement_by_at_most( - balance: Set, - max_amount: Field, - owner: AztecAddress -) -> Field { +pub fn decrement_by_at_most(balance: Set, max_amount: Field, owner: AztecAddress) -> Field { let options = create_note_getter_options_for_decreasing_balance(max_amount); let opt_notes = balance.get_notes(options); @@ -68,11 +64,7 @@ pub fn decrement_by_at_most( // Removes the note from the owner's set of notes. // Returns the value of the destroyed note. -pub fn destroy_note( - balance: Set, - owner: AztecAddress, - note: ValueNote -) -> Field { +pub fn destroy_note(balance: Set, owner: AztecAddress, note: ValueNote) -> Field { // Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while // spending someone else's notes). assert(note.owner.eq(owner)); diff --git a/yarn-project/aztec-nr/value-note/src/value_note.nr b/yarn-project/aztec-nr/value-note/src/value_note.nr index 4cffea0d4fa..db0516f8306 100644 --- a/yarn-project/aztec-nr/value-note/src/value_note.nr +++ b/yarn-project/aztec-nr/value-note/src/value_note.nr @@ -1,5 +1,8 @@ use dep::aztec::{ - protocol_types::address::AztecAddress, + protocol_types::{ + address::AztecAddress, + traits::{Deserialize, Serialize} + }, note::{ note_header::NoteHeader, note_interface::NoteInterface, @@ -26,23 +29,14 @@ struct ValueNote { } // docs:end:value-note-def -impl ValueNote { - pub fn new(value: Field, owner: AztecAddress) -> Self { - let randomness = rand(); - let header = NoteHeader::empty(); - ValueNote { - value, - owner, - randomness, - header, - } - } - - pub fn serialize(self) -> [Field; VALUE_NOTE_LEN] { +impl Serialize for ValueNote { + fn serialize(self) -> [Field; VALUE_NOTE_LEN] { [self.value, self.owner.to_field(), self.randomness] } +} - pub fn deserialize(serialized_note: [Field; VALUE_NOTE_LEN]) -> Self { +impl Deserialize for ValueNote { + fn deserialize(serialized_note: [Field; VALUE_NOTE_LEN]) -> Self { ValueNote { value: serialized_note[0], owner: AztecAddress::from_field(serialized_note[1]), @@ -50,16 +44,19 @@ impl ValueNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for ValueNote { + + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash(self.serialize(),0) } // docs:start:nullifier - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(ValueNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -71,8 +68,8 @@ impl ValueNote { // docs:end:nullifier - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(ValueNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -82,12 +79,16 @@ impl ValueNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(self) -> NoteHeader { + self.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { let encryption_pub_key = get_public_key(self.owner); emit_encrypted_log( context, @@ -99,46 +100,15 @@ impl ValueNote { } } -fn deserialize(serialized_note: [Field; VALUE_NOTE_LEN]) -> ValueNote { - ValueNote::deserialize(serialized_note) -} - -fn serialize(note: ValueNote) -> [Field; VALUE_NOTE_LEN] { - note.serialize() -} - -fn compute_note_hash(note: ValueNote) -> Field { - note.compute_note_hash() -} - -fn compute_nullifier(note: ValueNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: ValueNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: ValueNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut ValueNote, header: NoteHeader) { - note.set_header(header) -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: ValueNote) { - note.broadcast(context, slot); +impl ValueNote { + pub fn new(value: Field, owner: AztecAddress) -> Self { + let randomness = rand(); + let header = NoteHeader::empty(); + ValueNote { + value, + owner, + randomness, + header, + } + } } - -global ValueNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/benchmarking_contract/src/main.nr b/yarn-project/noir-contracts/contracts/benchmarking_contract/src/main.nr index 2daab6e3ed6..8b9bd1df476 100644 --- a/yarn-project/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -7,31 +7,31 @@ contract Benchmarking { use dep::value_note::{ utils::{increment, decrement}, - value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + value_note::{VALUE_NOTE_LEN, ValueNote}, }; use dep::aztec::{ protocol_types::{ abis::function_selector::FunctionSelector, address::AztecAddress, + type_serialization::FIELD_SERIALIZED_LEN }, context::{Context}, note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, }; struct Storage { - notes: Map>, - balances: Map>, + notes: Map>, + balances: Map>, } impl Storage { - fn init(context: Context) -> pub Self { + fn init(context: Context) -> Self { Storage { - notes: Map::new(context, 1, |context, slot| { Set::new(context, slot, ValueNoteMethods) }), - balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) }), + notes: Map::new(context, 1, |context, slot| { Set::new(context, slot) }), + balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot) }), } } } @@ -85,6 +85,6 @@ contract Benchmarking { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/card_game_contract/src/cards.nr b/yarn-project/noir-contracts/contracts/card_game_contract/src/cards.nr index b0b17ef7ac1..9569a41b774 100644 --- a/yarn-project/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/yarn-project/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -19,7 +19,7 @@ use dep::std::{ option::Option, }; use dep::value_note::{ - value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN}, + value_note::{ValueNote, VALUE_NOTE_LEN}, }; struct Card { @@ -88,7 +88,7 @@ impl CardNote { } struct Deck { - set: Set, + set: Set, } pub fn filter_cards( @@ -125,7 +125,6 @@ impl Deck { let set = Set { context, storage_slot, - note_interface: ValueNoteMethods, }; Deck { set diff --git a/yarn-project/noir-contracts/contracts/card_game_contract/src/game.nr b/yarn-project/noir-contracts/contracts/card_game_contract/src/game.nr index 63b50bcf783..4e9c75a77f7 100644 --- a/yarn-project/noir-contracts/contracts/card_game_contract/src/game.nr +++ b/yarn-project/noir-contracts/contracts/card_game_contract/src/game.nr @@ -1,5 +1,7 @@ -use dep::aztec::protocol_types::address::AztecAddress; -use dep::aztec::types::type_serialization::TypeSerializationInterface; +use dep::aztec::protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize}, +}; use crate::cards::Card; global NUMBER_OF_PLAYERS = 2; @@ -31,59 +33,59 @@ struct Game { global GAME_SERIALIZED_LEN: Field = 15; -fn deserializeGame(fields: [Field; GAME_SERIALIZED_LEN]) -> Game { - let players = [ - PlayerEntry { - address: AztecAddress::from_field(fields[0]), - deck_strength: fields[1] as u32, - points: fields[2] as u120 - }, - PlayerEntry { - address: AztecAddress::from_field(fields[3]), - deck_strength: fields[4] as u32, - points: fields[5] as u120 - } - ]; - let rounds_cards = [ - Card::from_field(fields[6]), Card::from_field(fields[7]), - Card::from_field(fields[8]), Card::from_field(fields[9]) - ]; - Game { - players, - rounds_cards, - started: fields[10] as bool, - finished: fields[11] as bool, - claimed: fields[12] as bool, - current_player: fields[13] as u32, - current_round: fields[14] as u32 +impl Serialize for Game { + fn serialize(game: Game) -> [Field; GAME_SERIALIZED_LEN] { + [ + game.players[0].address.to_field(), + game.players[0].deck_strength as Field, + game.players[0].points as Field, + game.players[1].address.to_field(), + game.players[1].deck_strength as Field, + game.players[1].points as Field, + game.rounds_cards[0].to_field(), + game.rounds_cards[1].to_field(), + game.rounds_cards[2].to_field(), + game.rounds_cards[3].to_field(), + game.started as Field, + game.finished as Field, + game.claimed as Field, + game.current_player as Field, + game.current_round as Field + ] } } -fn serializeGame(game: Game) -> [Field; GAME_SERIALIZED_LEN] { - [ - game.players[0].address.to_field(), - game.players[0].deck_strength as Field, - game.players[0].points as Field, - game.players[1].address.to_field(), - game.players[1].deck_strength as Field, - game.players[1].points as Field, - game.rounds_cards[0].to_field(), - game.rounds_cards[1].to_field(), - game.rounds_cards[2].to_field(), - game.rounds_cards[3].to_field(), - game.started as Field, - game.finished as Field, - game.claimed as Field, - game.current_player as Field, - game.current_round as Field - ] +impl Deserialize for Game { + fn deserialize(fields: [Field; GAME_SERIALIZED_LEN]) -> Game { + let players = [ + PlayerEntry { + address: AztecAddress::from_field(fields[0]), + deck_strength: fields[1] as u32, + points: fields[2] as u120 + }, + PlayerEntry { + address: AztecAddress::from_field(fields[3]), + deck_strength: fields[4] as u32, + points: fields[5] as u120 + } + ]; + let rounds_cards = [ + Card::from_field(fields[6]), Card::from_field(fields[7]), + Card::from_field(fields[8]), Card::from_field(fields[9]) + ]; + Game { + players, + rounds_cards, + started: fields[10] as bool, + finished: fields[11] as bool, + claimed: fields[12] as bool, + current_player: fields[13] as u32, + current_round: fields[14] as u32 + } + } } impl Game { - pub fn serialize(self: Self) -> [Field; GAME_SERIALIZED_LEN] { - serializeGame(self) - } - pub fn add_player(&mut self, player_entry: PlayerEntry) -> bool { let mut added = false; @@ -166,8 +168,3 @@ impl Game { } } } - -global GameSerializationMethods = TypeSerializationInterface { - deserialize: deserializeGame, - serialize: serializeGame, -}; diff --git a/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr b/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr index 4aacb388d9a..df143229104 100644 --- a/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/card_game_contract/src/main.nr @@ -20,7 +20,7 @@ contract CardGame { use dep::value_note::{ balance_utils, value_note::{ - ValueNoteMethods, + ValueNote, VALUE_NOTE_LEN, }, }; @@ -49,14 +49,13 @@ contract CardGame { PLAYABLE_CARDS, PlayerEntry, Game, - GameSerializationMethods, GAME_SERIALIZED_LEN }; struct Storage { collections: Map, game_decks: Map>, - games: Map>, + games: Map>, } impl Storage { @@ -96,8 +95,7 @@ contract CardGame { |context, slot| { PublicState::new( context, - slot, - GameSerializationMethods, + slot ) }, ) @@ -245,6 +243,6 @@ contract CardGame { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/child_contract/src/main.nr b/yarn-project/noir-contracts/contracts/child_contract/src/main.nr index 49caabe92cf..ee7213c4687 100644 --- a/yarn-project/noir-contracts/contracts/child_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/child_contract/src/main.nr @@ -7,7 +7,6 @@ contract Child { context::{PrivateContext, PublicContext, Context}, log::emit_unencrypted_log, state_vars::public_state::PublicState, - types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, }; use dep::aztec::protocol_types::{ abis::function_selector::FunctionSelector, @@ -15,7 +14,7 @@ contract Child { }; struct Storage { - current_value: PublicState, + current_value: PublicState, } impl Storage { @@ -24,7 +23,6 @@ contract Child { current_value: PublicState::new( context, 1, - FieldSerializationMethods, ), } } diff --git a/yarn-project/noir-contracts/contracts/counter_contract/src/main.nr b/yarn-project/noir-contracts/contracts/counter_contract/src/main.nr index 07558511816..e424fbda693 100644 --- a/yarn-project/noir-contracts/contracts/counter_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/counter_contract/src/main.nr @@ -12,7 +12,7 @@ contract Counter { use dep::value_note::{ balance_utils, value_note::{ - ValueNoteMethods, + ValueNote, VALUE_NOTE_LEN, }, }; @@ -74,7 +74,7 @@ contract Counter { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } // docs:end:nullifier } diff --git a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr index bee8a425161..9300ef77ecd 100644 --- a/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -33,22 +33,22 @@ contract DocsExample { // how to import methods from other files/folders within your workspace use crate::options::create_account_card_getter_options; use crate::types::{ - card_note::{CardNote, CardNoteMethods, CARD_NOTE_LEN}, - leader::{Leader, LeaderSerializationMethods, LEADER_SERIALIZED_LEN}, + card_note::{CardNote, CARD_NOTE_LEN}, + leader::Leader, }; struct Storage { // Shows how to create a custom struct in Public - leader: PublicState, + leader: PublicState, // docs:start:storage-singleton-declaration - legendary_card: Singleton, + legendary_card: Singleton, // docs:end:storage-singleton-declaration // just used for docs example to show how to create a singleton map. // docs:start:storage-map-singleton-declaration - profiles: Map>, + profiles: Map>, // docs:end:storage-map-singleton-declaration - test: Set, - imm_singleton: ImmutableSingleton, + test: Set, + imm_singleton: ImmutableSingleton, } impl Storage { @@ -56,11 +56,10 @@ contract DocsExample { Storage { leader: PublicState::new( context, - 1, - LeaderSerializationMethods, + 1 ), // docs:start:start_vars_singleton - legendary_card: Singleton::new(context, 2, CardNoteMethods), + legendary_card: Singleton::new(context, 2), // docs:end:start_vars_singleton // just used for docs example (not for game play): // docs:start:state_vars-MapSingleton @@ -68,12 +67,12 @@ contract DocsExample { context, 3, |context, slot| { - Singleton::new(context, slot, CardNoteMethods) + Singleton::new(context, slot) }, ), // docs:end:state_vars-MapSingleton - test: Set::new(context, 4, CardNoteMethods), - imm_singleton: ImmutableSingleton::new(context, 4, CardNoteMethods), + test: Set::new(context, 4), + imm_singleton: ImmutableSingleton::new(context, 4), } } } @@ -189,7 +188,7 @@ contract DocsExample { serialized_note: [Field; CARD_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(CardNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(CardNote::deserialize, note_header, serialized_note) } /// Macro equivalence section diff --git a/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index f185518c412..0f38b9bc34a 100644 --- a/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -1,4 +1,3 @@ -use dep::aztec::protocol_types::address::AztecAddress; use dep::aztec::{ note::{ note_header::NoteHeader, @@ -12,6 +11,10 @@ use dep::aztec::{ log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext, + protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize, Empty} + } }; // Shows how to create a custom note @@ -36,12 +39,16 @@ impl CardNote { header: NoteHeader::empty(), } } +} - pub fn serialize(self) -> [Field; CARD_NOTE_LEN] { +impl Serialize for CardNote { + fn serialize(self) -> [Field; CARD_NOTE_LEN] { [self.points as Field, self.randomness, self.owner.to_field()] } +} - pub fn deserialize(serialized_note: [Field; CARD_NOTE_LEN]) -> Self { +impl Deserialize for CardNote { + fn deserialize(serialized_note: [Field; CARD_NOTE_LEN]) -> Self { CardNote { points: serialized_note[0] as u8, randomness: serialized_note[1], @@ -49,8 +56,10 @@ impl CardNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for CardNote { + fn compute_note_hash(self) -> Field { pedersen_hash([ self.points as Field, self.randomness, @@ -58,8 +67,8 @@ impl CardNote { ],0) } - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(CardNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); pedersen_hash([ note_hash_for_nullify, @@ -68,8 +77,8 @@ impl CardNote { ],0) } - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(CardNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); pedersen_hash([ note_hash_for_nullify, @@ -78,12 +87,16 @@ impl CardNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(note: CardNote) -> NoteHeader { + note.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { let encryption_pub_key = get_public_key(self.owner); emit_encrypted_log( context, @@ -94,47 +107,3 @@ impl CardNote { ); } } - -fn deserialize(serialized_note: [Field; CARD_NOTE_LEN]) -> CardNote { - CardNote::deserialize(serialized_note) -} - -fn serialize(note: CardNote) -> [Field; CARD_NOTE_LEN] { - note.serialize() -} - -fn compute_note_hash(note: CardNote) -> Field { - note.compute_note_hash() -} - -fn compute_nullifier(note: CardNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: CardNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: CardNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut CardNote, header: NoteHeader) { - note.set_header(header) -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: CardNote) { - note.broadcast(context, slot); -} - -global CardNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/leader.nr b/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/leader.nr index ca034261ec0..7be0ef86dbf 100644 --- a/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/leader.nr +++ b/yarn-project/noir-contracts/contracts/docs_example_contract/src/types/leader.nr @@ -1,5 +1,7 @@ -use dep::aztec::protocol_types::address::AztecAddress; -use dep::aztec::types::type_serialization::TypeSerializationInterface; +use dep::aztec::protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize} +}; // Shows how to create a custom struct in Public struct Leader { @@ -9,15 +11,15 @@ struct Leader { global LEADER_SERIALIZED_LEN: Field = 2; -fn deserialize(fields: [Field; LEADER_SERIALIZED_LEN]) -> Leader { - Leader { account: AztecAddress::from_field(fields[0]), points: fields[1] as u8 } +impl Deserialize for Leader { + fn deserialize(fields: [Field; LEADER_SERIALIZED_LEN]) -> Self { + Leader { account: AztecAddress::from_field(fields[0]), points: fields[1] as u8 } + } } -fn serialize(leader: Leader) -> [Field; LEADER_SERIALIZED_LEN] { - [leader.account.to_field(), leader.points as Field] +impl Serialize for Leader { + fn serialize(self) -> [Field; LEADER_SERIALIZED_LEN] { + [self.account.to_field(), self.points as Field] + } } -global LeaderSerializationMethods = TypeSerializationInterface { - deserialize, - serialize, -}; diff --git a/yarn-project/noir-contracts/contracts/easy_private_token_contract/src/main.nr b/yarn-project/noir-contracts/contracts/easy_private_token_contract/src/main.nr index 2a342aa3e88..c43aae116ea 100644 --- a/yarn-project/noir-contracts/contracts/easy_private_token_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/easy_private_token_contract/src/main.nr @@ -13,7 +13,7 @@ contract EasyPrivateToken { use dep::value_note::{ balance_utils, value_note::{ - ValueNoteMethods, + ValueNote, VALUE_NOTE_LEN, }, }; @@ -24,7 +24,7 @@ contract EasyPrivateToken { } impl Storage { - fn init(context: Context) -> pub Self { + fn init(context: Context) -> Self { Storage { balances: Map::new( context, @@ -82,7 +82,7 @@ contract EasyPrivateToken { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } // docs:end:easy_private_token_contract diff --git a/yarn-project/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/yarn-project/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index ceddb93c70c..5cc3606d39e 100644 --- a/yarn-project/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -3,22 +3,17 @@ contract EasyPrivateVoting { use dep::aztec::{ protocol_types::{ abis::function_selector::FunctionSelector, - address::AztecAddress, + address::AztecAddress }, context::{PrivateContext, Context}, - state_vars::{ map::Map, public_state::PublicState,}, - types::type_serialization::{ // serialization methods for using booleans and aztec addresses - bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN}, - address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, - field_serialization::{ FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - }, + state_vars::{ map::Map, public_state::PublicState}, }; // docs:end:imports // docs:start:storage_struct struct Storage { - admin: PublicState, // admin can end vote - tally: Map>, // we will store candidate as key and number of votes as value - voteEnded: PublicState, // voteEnded is boolean + admin: PublicState, // admin can end vote + tally: Map>, // we will store candidate as key and number of votes as value + voteEnded: PublicState, // voteEnded is boolean } // docs:end:storage_struct // docs:start:storage_impl @@ -28,7 +23,6 @@ contract EasyPrivateVoting { admin: PublicState::new( context, 1, // storage slot. this can be anything except 0. it is hashed, and hash on 0 = 0 - AddressSerializationMethods, ), tally: Map::new( context, @@ -36,15 +30,13 @@ contract EasyPrivateVoting { |context, slot| { PublicState::new( context, - slot, - FieldSerializationMethods, + slot, ) }, ), voteEnded: PublicState::new( context, - 3, - BoolSerializationMethods, + 3 ) } } } diff --git a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index d02320b5ea8..28d7c84fe79 100644 --- a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -12,6 +12,7 @@ use dep::aztec::{ log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext, + protocol_types::traits::{Serialize, Deserialize}, }; global ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5; @@ -25,23 +26,14 @@ struct EcdsaPublicKeyNote { header: NoteHeader, } -impl EcdsaPublicKeyNote { - pub fn new(x: [u8; 32], y: [u8; 32], owner: AztecAddress) -> Self { - EcdsaPublicKeyNote { - x, - y, - owner, - header: NoteHeader::empty(), - } - } - - // serialize the note as 5 fields where: +impl Serialize for EcdsaPublicKeyNote { + // serialize the note as 5 fields where: // [0] = x[0..31] (upper bound excluded) // [1] = x[31] // [2] = y[0..31] // [3] = y[31] // [4] = owner - pub fn serialize(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] { + fn serialize(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] { let mut x: Field = 0; let mut y: Field = 0; let mut mul: Field = 1; @@ -59,9 +51,37 @@ impl EcdsaPublicKeyNote { [x, last_x, y, last_y, self.owner.to_field()] } +} + +impl Deserialize for EcdsaPublicKeyNote { + fn deserialize(serialized_note: [Field; ECDSA_PUBLIC_KEY_NOTE_LEN]) -> EcdsaPublicKeyNote { + let mut x: [u8; 32] = [0; 32]; + let mut y: [u8; 32] = [0; 32]; + + let part_x = serialized_note[0].to_be_bytes(32); + for i in 0..31 { + x[i] = part_x[i + 1]; + } + x[31] = serialized_note[1].to_be_bytes(32)[31]; + + let part_y = serialized_note[2].to_be_bytes(32); + for i in 0..31 { + y[i] = part_y[i + 1]; + } + y[31] = serialized_note[3].to_be_bytes(32)[31]; + + EcdsaPublicKeyNote { x, y, owner: AztecAddress::from_field(serialized_note[4]), header: NoteHeader::empty() } + } +} - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(EcdsaPublicKeyNoteInterface, self); +impl NoteInterface for EcdsaPublicKeyNote { + fn compute_note_hash(note: EcdsaPublicKeyNote) -> Field { + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash(note.serialize(), 0) + } + + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -71,8 +91,8 @@ impl EcdsaPublicKeyNote { ],0) } - pub fn compute_nullifier_without_context(self) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(EcdsaPublicKeyNoteInterface, self); + fn compute_nullifier_without_context(self) -> Field { + let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -82,12 +102,16 @@ impl EcdsaPublicKeyNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(self) -> NoteHeader { + self.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { let encryption_pub_key = get_public_key(self.owner); emit_encrypted_log( context, @@ -99,62 +123,15 @@ impl EcdsaPublicKeyNote { } } -fn deserialize(serialized_note: [Field; ECDSA_PUBLIC_KEY_NOTE_LEN]) -> EcdsaPublicKeyNote { - let mut x: [u8; 32] = [0; 32]; - let mut y: [u8; 32] = [0; 32]; - - let part_x = serialized_note[0].to_be_bytes(32); - for i in 0..31 { - x[i] = part_x[i + 1]; - } - x[31] = serialized_note[1].to_be_bytes(32)[31]; - - let part_y = serialized_note[2].to_be_bytes(32); - for i in 0..31 { - y[i] = part_y[i + 1]; +impl EcdsaPublicKeyNote { + pub fn new(x: [u8; 32], y: [u8; 32], owner: AztecAddress) -> Self { + EcdsaPublicKeyNote { + x, + y, + owner, + header: NoteHeader::empty(), + } } - y[31] = serialized_note[3].to_be_bytes(32)[31]; - - EcdsaPublicKeyNote { x, y, owner: AztecAddress::from_field(serialized_note[4]), header: NoteHeader::empty() } -} - -fn serialize(note: EcdsaPublicKeyNote) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] { - note.serialize() -} -fn compute_note_hash(note: EcdsaPublicKeyNote) -> Field { - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash(note.serialize(), 0) + } - -fn compute_nullifier(note: EcdsaPublicKeyNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: EcdsaPublicKeyNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: EcdsaPublicKeyNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut EcdsaPublicKeyNote, header: NoteHeader) { - note.set_header(header); -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: EcdsaPublicKeyNote) { - note.broadcast(context, slot); -} - -global EcdsaPublicKeyNoteInterface = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index da730b23c32..53c26c8b3c3 100644 --- a/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -23,17 +23,17 @@ contract EcdsaAccount { }; use crate::ecdsa_public_key_note::{ - EcdsaPublicKeyNote, EcdsaPublicKeyNoteInterface, ECDSA_PUBLIC_KEY_NOTE_LEN, + EcdsaPublicKeyNote, ECDSA_PUBLIC_KEY_NOTE_LEN, }; struct Storage { - public_key: ImmutableSingleton, + public_key: ImmutableSingleton, } impl Storage { fn init(context: Context) -> Self { Storage { - public_key: ImmutableSingleton::new(context, 1, EcdsaPublicKeyNoteInterface), + public_key: ImmutableSingleton::new(context, 1), } } } @@ -106,6 +106,6 @@ contract EcdsaAccount { ) -> pub [Field; 4] { assert(storage_slot == 1); let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(EcdsaPublicKeyNoteInterface, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(EcdsaPublicKeyNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr b/yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr index 09b92c5131f..0aaf5426fda 100644 --- a/yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/escrow_contract/src/main.nr @@ -20,18 +20,17 @@ contract Escrow { use dep::address_note::address_note::{ AddressNote, - AddressNoteMethods, ADDRESS_NOTE_LEN, }; struct Storage { - owners: Set, + owners: Set, } impl Storage { fn init(context: Context) -> Self { Storage { - owners: Set::new(context, 1, AddressNoteMethods), + owners: Set::new(context, 1), } } } @@ -77,6 +76,6 @@ contract Escrow { ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); assert(storage_slot == 1); - note_utils::compute_note_hash_and_nullifier(AddressNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(AddressNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 957603e65b6..3867148bcd6 100644 --- a/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -14,9 +14,6 @@ contract InclusionProofs { set::Set, public_state::PublicState, }, - types::{ - type_serialization::field_serialization::FieldSerializationMethods, - }, context::Context, note::{ note_getter_options::NoteGetterOptions, @@ -49,11 +46,11 @@ contract InclusionProofs { // docs:end:imports }; // docs:start:value_note_imports - use dep::value_note::value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN}; + use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; // docs:end:value_note_imports struct Storage { - private_values: Map>, - public_value: PublicState, + private_values: Map>, + public_value: PublicState, } impl Storage { @@ -63,13 +60,12 @@ contract InclusionProofs { context, 1, // Storage slot |context, slot| { - Set::new(context, slot, ValueNoteMethods) + Set::new(context, slot) }, ), public_value: PublicState::new( context, 2, // Storage slot - FieldSerializationMethods, ), } } @@ -117,12 +113,7 @@ contract InclusionProofs { // 2) Prove the note inclusion if maybe_note.is_some() { // docs:start:prove_note_inclusion - prove_note_inclusion( - ValueNoteMethods, - maybe_note.unwrap_unchecked(), - block_number, - context - ); + prove_note_inclusion(maybe_note.unwrap_unchecked(), block_number, context); // docs:end:prove_note_inclusion } else { // Note was not found so we will prove inclusion of the spare commitment @@ -149,12 +140,7 @@ contract InclusionProofs { // 3) Compute the nullifier from the note if maybe_note.is_some() { // docs:start:prove_note_not_nullified - prove_note_not_nullified( - ValueNoteMethods, - maybe_note.unwrap_unchecked(), - block_number, - &mut context - ); + prove_note_not_nullified(maybe_note.unwrap_unchecked(), block_number, &mut context); // docs:end:prove_note_not_nullified } else { // Note was not found so we will use the spare nullifier @@ -177,7 +163,7 @@ contract InclusionProofs { // 2) Prove the note validity // docs:start:prove_note_validity - prove_note_validity(ValueNoteMethods, note, block_number, &mut context); + prove_note_validity(note, block_number, &mut context); // docs:end:prove_note_validity } @@ -261,6 +247,6 @@ contract InclusionProofs { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/lending_contract/src/asset.nr b/yarn-project/noir-contracts/contracts/lending_contract/src/asset.nr index b71696a3a5f..5fbbb83a855 100644 --- a/yarn-project/noir-contracts/contracts/lending_contract/src/asset.nr +++ b/yarn-project/noir-contracts/contracts/lending_contract/src/asset.nr @@ -1,5 +1,7 @@ -use dep::aztec::protocol_types::address::AztecAddress; -use dep::aztec::types::type_serialization::TypeSerializationInterface; +use dep::aztec::protocol_types::{ + address::AztecAddress, + traits::{Deserialize, Serialize} +}; // Struct to be used to represent "totals". Generally, there should be one per asset. // It stores the global values that are shared among all users, such as an accumulator @@ -15,33 +17,26 @@ struct Asset { global ASSET_SERIALIZED_LEN: Field = 4; -// Right now we are wasting so many writes. If changing last_updated_ts -// we will end up rewriting all of them, wasting writes. -fn deserializeAsset(fields: [Field; ASSET_SERIALIZED_LEN]) -> Asset { - Asset { - interest_accumulator: fields[0] as u120, - last_updated_ts: fields[1] as u120, - loan_to_value: fields[2] as u120, - oracle: AztecAddress::from_field(fields[3]) +impl Serialize for Asset { + fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { + [ + asset.interest_accumulator as Field, + asset.last_updated_ts as Field, + asset.loan_to_value as Field, + asset.oracle.to_field() + ] } } -fn serializeAsset(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { - [ - asset.interest_accumulator as Field, - asset.last_updated_ts as Field, - asset.loan_to_value as Field, - asset.oracle.to_field() - ] -} - -impl Asset { - pub fn serialize(self: Self) -> [Field; ASSET_SERIALIZED_LEN] { - serializeAsset(self) +impl Deserialize for Asset { + // Right now we are wasting so many writes. If changing last_updated_ts + // we will end up rewriting all of them, wasting writes. + fn deserialize(fields: [Field; ASSET_SERIALIZED_LEN]) -> Asset { + Asset { + interest_accumulator: fields[0] as u120, + last_updated_ts: fields[1] as u120, + loan_to_value: fields[2] as u120, + oracle: AztecAddress::from_field(fields[3]) + } } } - -global AssetSerializationMethods = TypeSerializationInterface { - deserialize: deserializeAsset, - serialize: serializeAsset, -}; diff --git a/yarn-project/noir-contracts/contracts/lending_contract/src/main.nr b/yarn-project/noir-contracts/contracts/lending_contract/src/main.nr index 1c80bf6e4a2..9811f0919d1 100644 --- a/yarn-project/noir-contracts/contracts/lending_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/lending_contract/src/main.nr @@ -22,25 +22,20 @@ contract Lending { state_vars::{ map::Map, public_state::PublicState, - }, - types::type_serialization::{ - field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - TypeSerializationInterface, - address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, - }, + } }; - use crate::asset::{ASSET_SERIALIZED_LEN, Asset, AssetSerializationMethods}; + use crate::asset::Asset; use crate::interest_math::compute_multiplier; use crate::helpers::{covered_by_collateral, DebtReturn, debt_updates, debt_value, compute_identifier}; use crate::interfaces::{Token, Lending, PriceFeed}; // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - collateral_asset: PublicState, - stable_coin: PublicState, - assets: Map>, - collateral: Map>, - static_debt: Map>, // abusing keys very heavily + collateral_asset: PublicState, + stable_coin: PublicState, + assets: Map>, + collateral: Map>, + static_debt: Map>, // abusing keys very heavily } impl Storage { @@ -48,13 +43,11 @@ contract Lending { Storage { collateral_asset: PublicState::new( context, - 1, - AddressSerializationMethods, + 1 ), stable_coin: PublicState::new( context, - 2, - AddressSerializationMethods, + 2 ), assets: Map::new( context, @@ -62,8 +55,7 @@ contract Lending { |context, slot| { PublicState::new( context, - slot, - AssetSerializationMethods, + slot ) }, ), @@ -73,8 +65,7 @@ contract Lending { |context, slot| { PublicState::new( context, - slot, - FieldSerializationMethods, + slot ) }, ), @@ -84,8 +75,7 @@ contract Lending { |context, slot| { PublicState::new( context, - slot, - FieldSerializationMethods, + slot ) }, ), diff --git a/yarn-project/noir-contracts/contracts/pending_commitments_contract/src/main.nr b/yarn-project/noir-contracts/contracts/pending_commitments_contract/src/main.nr index 6792fcef1cf..3878ae5134c 100644 --- a/yarn-project/noir-contracts/contracts/pending_commitments_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/pending_commitments_contract/src/main.nr @@ -8,7 +8,7 @@ contract PendingCommitments { use dep::value_note::{ balance_utils, filter::filter_notes_min_sum, - value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + value_note::{VALUE_NOTE_LEN, ValueNote}, }; use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, @@ -26,7 +26,7 @@ contract PendingCommitments { }; struct Storage { - balances: Map>, + balances: Map>, } impl Storage { @@ -36,7 +36,7 @@ contract PendingCommitments { context, 1, // Storage slot |context, slot| { - Set::new(context, slot, ValueNoteMethods) + Set::new(context, slot) }, ), } @@ -296,6 +296,6 @@ contract PendingCommitments { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/price_feed_contract/src/asset.nr b/yarn-project/noir-contracts/contracts/price_feed_contract/src/asset.nr index 9d464eefddc..047705a1ace 100644 --- a/yarn-project/noir-contracts/contracts/price_feed_contract/src/asset.nr +++ b/yarn-project/noir-contracts/contracts/price_feed_contract/src/asset.nr @@ -1,4 +1,4 @@ -use dep::aztec::types::type_serialization::TypeSerializationInterface; +use dep::aztec::protocol_types::traits::{Serialize, Deserialize}; struct Asset { price: u120, @@ -6,21 +6,14 @@ struct Asset { global ASSET_SERIALIZED_LEN: Field = 1; -fn deserializeAsset(fields: [Field; ASSET_SERIALIZED_LEN]) -> Asset { - Asset { price: fields[0] as u120 } -} - -fn serializeAsset(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { - [asset.price as Field] +impl Serialize for Asset { + fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { + [asset.price as Field] + } } -impl Asset { - fn serialize(self: Self) -> [Field; ASSET_SERIALIZED_LEN] { - serializeAsset(self) +impl Deserialize for Asset { + fn deserialize(fields: [Field; ASSET_SERIALIZED_LEN]) -> Asset { + Asset { price: fields[0] as u120 } } } - -global AssetSerializationMethods = TypeSerializationInterface { - deserialize: deserializeAsset, - serialize: serializeAsset, -}; diff --git a/yarn-project/noir-contracts/contracts/price_feed_contract/src/main.nr b/yarn-project/noir-contracts/contracts/price_feed_contract/src/main.nr index 4e301359438..a72caab5e83 100644 --- a/yarn-project/noir-contracts/contracts/price_feed_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/price_feed_contract/src/main.nr @@ -10,11 +10,11 @@ contract PriceFeed { }, }; use dep::aztec::protocol_types::address::AztecAddress; - use crate::asset::{ASSET_SERIALIZED_LEN, Asset, AssetSerializationMethods}; + use crate::asset::Asset; // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - assets: Map>, + assets: Map>, } impl Storage { @@ -27,7 +27,6 @@ contract PriceFeed { PublicState::new( context, slot, - AssetSerializationMethods, ) }, ), diff --git a/yarn-project/noir-contracts/contracts/reader_contract/src/main.nr b/yarn-project/noir-contracts/contracts/reader_contract/src/main.nr index 931a5e25501..b8c65f95c67 100644 --- a/yarn-project/noir-contracts/contracts/reader_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/reader_contract/src/main.nr @@ -4,7 +4,7 @@ contract Reader { abis::function_selector::FunctionSelector, }; - use dep::compressed_string::{FieldCompressedString, FieldCompressedStringSerializationMethods}; + use dep::compressed_string::FieldCompressedString; #[aztec(private)] diff --git a/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 001437e9c9d..ef0402fcc01 100644 --- a/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -20,11 +20,11 @@ contract SchnorrAccount { auth_witness::get_auth_witness, }; - use crate::public_key_note::{PublicKeyNote, PublicKeyNoteMethods, PUBLIC_KEY_NOTE_LEN}; + use crate::public_key_note::{PublicKeyNote, PUBLIC_KEY_NOTE_LEN}; struct Storage { // docs:start:storage - signing_public_key: ImmutableSingleton, + signing_public_key: ImmutableSingleton, // docs:end:storage } @@ -32,7 +32,7 @@ contract SchnorrAccount { fn init(context: Context) -> Self { Storage { // docs:start:storage_init - signing_public_key: ImmutableSingleton::new(context, 1, PublicKeyNoteMethods), + signing_public_key: ImmutableSingleton::new(context, 1), // docs:end:storage_init } } @@ -113,6 +113,6 @@ contract SchnorrAccount { ) -> pub [Field; 4] { assert(storage_slot == 1); let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(PublicKeyNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(PublicKeyNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index 82330325d1a..ff9f1b78be0 100644 --- a/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/yarn-project/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -11,8 +11,11 @@ use dep::aztec::{ }, log::emit_encrypted_log, context::PrivateContext, + protocol_types::{ + address::AztecAddress, + traits::{Serialize, Deserialize}, + } }; -use dep::aztec::protocol_types::address::AztecAddress; global PUBLIC_KEY_NOTE_LEN: Field = 3; @@ -25,23 +28,27 @@ struct PublicKeyNote { header: NoteHeader, } -impl PublicKeyNote { - pub fn new(x: Field, y: Field, owner: AztecAddress) -> Self { +impl Serialize for PublicKeyNote { + fn serialize(self) -> [Field; PUBLIC_KEY_NOTE_LEN] { + [self.x, self.y, self.owner.to_field()] + } +} + +impl Deserialize for PublicKeyNote { + fn deserialize(serialized_note: [Field; PUBLIC_KEY_NOTE_LEN]) -> PublicKeyNote { PublicKeyNote { - x, - y, - owner, - header: NoteHeader::empty(), + x: serialized_note[0], + y: serialized_note[1], + owner: AztecAddress::from_field(serialized_note[2]), + header: NoteHeader::empty() } } +} - // serialize the note as 3 fields - pub fn serialize(self) -> [Field; PUBLIC_KEY_NOTE_LEN] { - [self.x, self.y, self.owner.to_field()] - } +impl NoteInterface for PublicKeyNote { - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(PublicKeyNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -51,8 +58,8 @@ impl PublicKeyNote { ],0) } - pub fn compute_nullifier_without_context(self) -> Field { - let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(PublicKeyNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let unique_siloed_note_hash = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -62,12 +69,21 @@ impl PublicKeyNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn compute_note_hash(note: PublicKeyNote) -> Field { + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash(note.serialize(), 0) + } + + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(self) -> NoteHeader { + self.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { let encryption_pub_key = get_public_key(self.owner); emit_encrypted_log( context, @@ -79,52 +95,13 @@ impl PublicKeyNote { } } -fn deserialize(serialized_note: [Field; PUBLIC_KEY_NOTE_LEN]) -> PublicKeyNote { - PublicKeyNote { - x: serialized_note[0], - y: serialized_note[1], - owner: AztecAddress::from_field(serialized_note[2]), - header: NoteHeader::empty() +impl PublicKeyNote { + pub fn new(x: Field, y: Field, owner: AztecAddress) -> Self { + PublicKeyNote { + x, + y, + owner, + header: NoteHeader::empty(), + } } } - -fn serialize(note: PublicKeyNote) -> [Field; PUBLIC_KEY_NOTE_LEN] { - note.serialize() -} - -fn compute_note_hash(note: PublicKeyNote) -> Field { - // TODO(#1205) Should use a non-zero generator index. - pedersen_hash(note.serialize(), 0) -} - -fn compute_nullifier(note: PublicKeyNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: PublicKeyNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: PublicKeyNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut PublicKeyNote, header: NoteHeader) { - note.set_header(header); -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: PublicKeyNote) { - note.broadcast(context, slot); -} - -global PublicKeyNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/slow_tree_contract/src/main.nr b/yarn-project/noir-contracts/contracts/slow_tree_contract/src/main.nr index d0cdb1092b2..e0986fbd238 100644 --- a/yarn-project/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/slow_tree_contract/src/main.nr @@ -14,7 +14,7 @@ contract SlowTree { use dep::value_note::{ balance_utils, utils::{increment, decrement}, - value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + value_note::{VALUE_NOTE_LEN, ValueNote}, }; use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, @@ -23,9 +23,7 @@ contract SlowTree { utils as note_utils, }, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::field_serialization::{ - FieldSerializationMethods, FIELD_SERIALIZED_LEN, - }, + protocol_types::type_serialization::FIELD_SERIALIZED_LEN, }; use dep::slow_updates_tree::slow_map::{ SlowMap, Leaf, SlowUpdateProof, compute_merkle_root, deserialize_slow_update_proof diff --git a/yarn-project/noir-contracts/contracts/stateful_test_contract/src/main.nr b/yarn-project/noir-contracts/contracts/stateful_test_contract/src/main.nr index 9f02dc97bb5..cfca700e66e 100644 --- a/yarn-project/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -5,7 +5,7 @@ contract StatefulTest { use dep::value_note::{ balance_utils, utils::{increment, decrement}, - value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + value_note::{VALUE_NOTE_LEN, ValueNote}, }; use dep::aztec::{ context::{PrivateContext, PublicContext, Context}, @@ -14,14 +14,11 @@ contract StatefulTest { utils as note_utils, }, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::field_serialization::{ - FieldSerializationMethods, FIELD_SERIALIZED_LEN, - }, }; struct Storage { - notes: Map>, - public_values: Map>, + notes: Map>, + public_values: Map>, } impl Storage { @@ -31,7 +28,7 @@ contract StatefulTest { context, 1, // Storage slot |context, slot| { - Set::new(context, slot, ValueNoteMethods) + Set::new(context, slot) }, ), public_values: Map::new( @@ -41,7 +38,6 @@ contract StatefulTest { PublicState::new( context, slot, - FieldSerializationMethods, ) }, ), @@ -88,6 +84,6 @@ contract StatefulTest { serialized_note: [Field; VALUE_NOTE_LEN] ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } diff --git a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr index 11d0f4705f6..14d7a7f6ee6 100644 --- a/yarn-project/noir-contracts/contracts/test_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/test_contract/src/main.nr @@ -1,9 +1,15 @@ // 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; - use dep::aztec::protocol_types::address::{ - AztecAddress, - EthAddress, + use dep::aztec::protocol_types::{ + address::{ + AztecAddress, + EthAddress, + }, + constants::{ + MAX_READ_REQUESTS_PER_CALL, + MAX_NOTES_PER_PAGE + } }; // The following import is here in order to make the event macro work because the macro doesn't add the import. // It doesn't add the import because in the future we will re-export all the types via aztec-nr and aztec-nr is @@ -38,8 +44,8 @@ contract Test { types::vec::BoundedVec, }; 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}; - use dep::value_note::value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN}; + use dep::field_note::field_note::FieldNote; + use dep::value_note::value_note::{ValueNote,VALUE_NOTE_LEN}; #[event] struct ExampleEvent { @@ -47,13 +53,13 @@ contract Test { } struct Storage { - example_constant: ImmutableSingleton, + example_constant: ImmutableSingleton, } impl Storage { fn init(context: Context) -> Self { Storage { - example_constant: ImmutableSingleton::new(context, 1, FieldNoteMethods), + example_constant: ImmutableSingleton::new(context, 1), } } } @@ -93,7 +99,7 @@ contract Test { assert(storage_slot != 1, "storage slot 1 is reserved for example_constant"); let mut note = ValueNote::new(value, owner); - create_note(&mut context, storage_slot, &mut note, ValueNoteMethods, true); + create_note(&mut context, storage_slot, &mut note, true); } #[aztec(private)] @@ -105,7 +111,7 @@ contract Test { options = options.set_status(NoteStatus.ACTIVE_OR_NULLIFIED); } - let opt_notes = get_notes(&mut context, storage_slot, ValueNoteMethods, options); + let opt_notes: [Option; MAX_READ_REQUESTS_PER_CALL] = get_notes(&mut context, storage_slot, options); // We can't get the return value of a private function from the outside world in an end to end test, so we // expose it via an unecrypted log instead. @@ -122,7 +128,7 @@ contract Test { options = options.set_status(NoteStatus.ACTIVE_OR_NULLIFIED); } - let opt_notes = get_notes(&mut context, storage_slot, ValueNoteMethods, options); + let opt_notes: [Option; MAX_READ_REQUESTS_PER_CALL] = get_notes(&mut context, storage_slot, options); // We can't get the return value of a private function from the outside world in an end to end test, so we // expose it via an unecrypted log instead. @@ -138,7 +144,7 @@ contract Test { options = options.set_status(NoteStatus.ACTIVE_OR_NULLIFIED); } - let opt_notes = view_notes(storage_slot, ValueNoteMethods, options); + let opt_notes: [Option; MAX_NOTES_PER_PAGE] = view_notes(storage_slot, options); opt_notes[0].unwrap().value } @@ -154,7 +160,7 @@ contract Test { options = options.set_status(NoteStatus.ACTIVE_OR_NULLIFIED); } - let opt_notes = view_notes(storage_slot, ValueNoteMethods, options); + let opt_notes: [Option; MAX_NOTES_PER_PAGE] = view_notes(storage_slot, options); [opt_notes[0].unwrap().value, opt_notes[1].unwrap().value] } @@ -164,11 +170,11 @@ contract Test { assert(storage_slot != 1, "storage slot 1 is reserved for example_constant"); let options = NoteGetterOptions::new(); - let opt_notes = get_notes(&mut context, storage_slot, ValueNoteMethods, options); + let opt_notes: [Option; MAX_READ_REQUESTS_PER_CALL] = get_notes(&mut context, storage_slot, options); let note = opt_notes[0].unwrap(); - destroy_note(&mut context, note, ValueNoteMethods); + destroy_note(&mut context, note); } // Test codegen for Aztec.nr interfaces @@ -330,11 +336,11 @@ contract Test { ) -> pub [Field; 4] { if (storage_slot == 1) { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(FieldNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize, note_header, serialized_note) } else { // For ValueNotes created via write_value_to_storage let note_header = NoteHeader::new(contract_address, nonce, storage_slot); - note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(ValueNote::deserialize, note_header, serialized_note) } } } diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/main.nr index d0fd433342a..b8b02f80817 100644 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -30,14 +30,9 @@ contract TokenBlacklist { context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, state_vars::{map::Map, public_state::PublicState, set::Set, immutable_singleton::ImmutableSingleton}, - types::type_serialization::{ - field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN}, - address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, - }, }; - use dep::field_note::field_note::{FieldNote, FieldNoteMethods, FIELD_NOTE_LEN}; + use dep::field_note::field_note::{FieldNote, FIELD_NOTE_LEN}; use dep::authwit::{ auth::{ @@ -47,10 +42,9 @@ contract TokenBlacklist { }; use crate::types::{ - transparent_note::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}, - token_note::{TokenNote, TokenNoteMethods, TOKEN_NOTE_LEN}, + transparent_note::TransparentNote, + token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::{BalancesMap}, - safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN}, roles::UserFlags, }; // docs:start:interface @@ -58,13 +52,13 @@ contract TokenBlacklist { // docs:end:interface struct Storage { - admin: PublicState, + admin: PublicState, balances: BalancesMap, - total_supply: PublicState, - pending_shields: Set, - public_balances: Map>, - slow_update: ImmutableSingleton, - public_slow_update: PublicState, + total_supply: PublicState, + pending_shields: Set, + public_balances: Map>, + slow_update: ImmutableSingleton, + public_slow_update: PublicState, } impl Storage { @@ -73,33 +67,29 @@ contract TokenBlacklist { admin: PublicState::new( context, 1, - AddressSerializationMethods, ), balances: BalancesMap::new(context, 3), total_supply: PublicState::new( context, 4, - SafeU120SerializationMethods, ), - pending_shields: Set::new(context, 5, TransparentNoteMethods), + pending_shields: Set::new(context, 5), public_balances: Map::new( context, 6, |context, slot| { PublicState::new( context, - slot, - SafeU120SerializationMethods, + slot ) }, ), // Below is an abomination to have same value in private and public (immutable in solidity). // docs:start:slow_updates_storage - slow_update: ImmutableSingleton::new(context, 7, FieldNoteMethods), + slow_update: ImmutableSingleton::new(context, 7), public_slow_update: PublicState::new( context, - 8, - AddressSerializationMethods, + 8 ), // docs:end:slow_updates_storage @@ -393,11 +383,11 @@ contract TokenBlacklist { ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); if (storage_slot == 5) { - note_utils::compute_note_hash_and_nullifier(TransparentNoteMethods, note_header, preimage) + note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize, note_header, preimage) } else if (storage_slot == 7) { - note_utils::compute_note_hash_and_nullifier(FieldNoteMethods, note_header, preimage) + note_utils::compute_note_hash_and_nullifier(FieldNote::deserialize, note_header, preimage) } else { - note_utils::compute_note_hash_and_nullifier(TokenNoteMethods, note_header, preimage) + note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize, note_header, preimage) } } } diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types.nr index f5a3aeaa6fd..3ba03658390 100644 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types.nr +++ b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types.nr @@ -2,5 +2,4 @@ mod transparent_note; mod balance_set; mod balances_map; mod token_note; -mod safe_u120_serialization; mod roles; diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/balance_set.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/balance_set.nr index e63efeab306..ae6536ff4a2 100644 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/balance_set.nr +++ b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/balance_set.nr @@ -16,7 +16,7 @@ use dep::aztec::note::{ note_interface::NoteInterface, utils::compute_note_hash_for_read_or_nullify, }; -use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; +use crate::types::token_note::TokenNote; // A set implementing standard manipulation of balances. // Does not require spending key, but only knowledge. @@ -24,7 +24,7 @@ use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; struct BalanceSet { context: Context, owner: AztecAddress, - set: Set + set: Set } impl BalanceSet { @@ -33,7 +33,6 @@ impl BalanceSet { let set = Set { context, storage_slot, - note_interface: TokenNoteMethods, }; Self { context, diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/safe_u120_serialization.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/safe_u120_serialization.nr deleted file mode 100644 index 876007184fe..00000000000 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/safe_u120_serialization.nr +++ /dev/null @@ -1,18 +0,0 @@ -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, -}; diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index 41e921d16d0..235c121637a 100644 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -10,6 +10,7 @@ use dep::aztec::{ state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash, + protocol_types::traits::{Serialize, Deserialize} }; use dep::aztec::oracle::{ rand::rand, @@ -35,21 +36,14 @@ struct TokenNote { header: NoteHeader, } -impl TokenNote { - pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { - Self { - amount, - owner, - randomness: rand(), - header: NoteHeader::empty(), - } - } - - pub fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { +impl Serialize for TokenNote { + fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { [self.amount.value as Field, self.owner.to_field(), self.randomness] } +} - pub fn deserialize(preimage: [Field; TOKEN_NOTE_LEN]) -> Self { +impl Deserialize for TokenNote { + fn deserialize(preimage: [Field; TOKEN_NOTE_LEN]) -> Self { Self { amount: SafeU120::new(preimage[0]), owner: AztecAddress::from_field(preimage[1]), @@ -57,8 +51,10 @@ impl TokenNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for TokenNote { + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount.value as Field, @@ -68,8 +64,8 @@ impl TokenNote { } // docs:start:nullifier - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -80,8 +76,8 @@ impl TokenNote { } // docs:end:nullifier - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -91,12 +87,17 @@ impl TokenNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + + fn get_header(note: TokenNote) -> NoteHeader { + note.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !self.amount.is_zero() { let encryption_pub_key = get_public_key(self.owner); @@ -111,46 +112,13 @@ impl TokenNote { } } -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, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: TokenNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: TokenNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut TokenNote, header: NoteHeader) { - note.set_header(header) -} - -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: TokenNote) { - note.broadcast(context, slot); +impl TokenNote { + pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { + Self { + amount, + owner, + randomness: rand(), + header: NoteHeader::empty(), + } + } } - -global TokenNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index 36658d459cc..0d5922db695 100644 --- a/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/yarn-project/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -7,6 +7,7 @@ use dep::aztec::{ }, hash::{compute_secret_hash, pedersen_hash}, context::PrivateContext, + protocol_types::traits::{Serialize, Deserialize} }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -22,38 +23,14 @@ struct TransparentNote { header: NoteHeader, } -impl TransparentNote { - - // CONSTRUCTORS - - pub 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 - pub fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { - amount: amount, - secret_hash: compute_secret_hash(secret), - secret: secret, - header: NoteHeader::empty(), - } - } - - - // STANDARD NOTE_INTERFACE FUNCTIONS - - pub fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { +impl Serialize for TransparentNote { + fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { [self.amount, self.secret_hash] } +} - pub fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> Self { +impl Deserialize for TransparentNote { + fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> Self { TransparentNote { amount: preimage[0], secret_hash: preimage[1], @@ -61,8 +38,11 @@ impl TransparentNote { header: NoteHeader::empty(), } } +} + +impl NoteInterface for TransparentNote { - pub fn compute_note_hash(self) -> Field { + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount, @@ -70,69 +50,59 @@ impl TransparentNote { ],0) } - pub fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { + fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { self.compute_nullifier_without_context() } - pub fn compute_nullifier_without_context(self) -> Field { - let siloed_note_hash = compute_note_hash_for_read_or_nullify(TransparentNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + // TODO(#1386): should use `compute_note_hash_for_read_or_nullify` once public functions inject nonce! + let siloed_note_hash = compute_note_hash_for_read_or_nullify(self); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([self.secret, siloed_note_hash],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } - - // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - pub fn knows_secret(self, secret: Field) { - let hash = compute_secret_hash(secret); - assert(self.secret_hash == hash); + fn get_header(self) -> NoteHeader { + self.header } -} -fn deserialize(preimage: [Field; TRANSPARENT_NOTE_LEN]) -> TransparentNote { - TransparentNote::deserialize(preimage) -} - -fn serialize(note: TransparentNote) -> [Field; TRANSPARENT_NOTE_LEN] { - note.serialize() + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + assert(false, "TransparentNote does not support broadcast"); + } } -fn compute_note_hash(note: TransparentNote) -> Field { - note.compute_note_hash() -} +impl TransparentNote { -fn compute_nullifier(note: TransparentNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} + // CONSTRUCTORS -fn compute_nullifier_without_context(note: TransparentNote) -> Field { - note.compute_nullifier_without_context() -} + pub fn new(amount: Field, secret_hash: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: secret_hash, + secret: 0, + header: NoteHeader::empty(), + } + } -fn get_header(note: TransparentNote) -> NoteHeader { - note.header -} + // new oracle call primitive + // get me the secret corresponding to this hash + pub fn new_from_secret(amount: Field, secret: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: compute_secret_hash(secret), + secret: secret, + header: NoteHeader::empty(), + } + } -fn set_header(note: &mut TransparentNote, header: NoteHeader) { - note.set_header(header) -} + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE -fn broadcast(context: &mut PrivateContext, slot: Field, note: TransparentNote) { - assert(false, "TransparentNote does not support broadcast"); + pub fn knows_secret(self, secret: Field) { + let hash = compute_secret_hash(secret); + assert(self.secret_hash == hash); + } } - -global TransparentNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; // docs:end:token_types_all \ No newline at end of file diff --git a/yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr b/yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr index ebf6c279a95..e7893ef8ceb 100644 --- a/yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -19,7 +19,6 @@ contract TokenBridge { context::{Context}, hash::{compute_secret_hash}, state_vars::{public_state::PublicState}, - types::type_serialization::address_serialization::AddressSerializationMethods, }; use dep::token_portal_content_hash_lib::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash}; @@ -30,7 +29,7 @@ contract TokenBridge { // docs:start:token_bridge_storage_and_constructor // Storage structure, containing all storage, and specifying what slots they use. struct Storage { - token: PublicState, + token: PublicState, } impl Storage { @@ -38,8 +37,7 @@ contract TokenBridge { Storage { token: PublicState::new( context, - 1, - AddressSerializationMethods, + 1 ), } } diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/contracts/token_contract/src/main.nr index 080f252969b..06c09e335e0 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/main.nr @@ -13,8 +13,8 @@ contract Token { // Libs use dep::std::option::Option; - use dep::safe_math::SafeU120; - use dep::compressed_string::{FieldCompressedString, FieldCompressedStringSerializationMethods}; + use dep::safe_math::{SafeU120, SAFE_U120_SERIALIZED_LEN}; + use dep::compressed_string::{FieldCompressedString}; use dep::aztec::{ note::{ @@ -25,16 +25,16 @@ contract Token { context::{PrivateContext, PublicContext, Context}, hash::{compute_secret_hash}, state_vars::{map::Map, public_state::PublicState, set::Set}, - types::type_serialization::{ - field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, - bool_serialization::{BoolSerializationMethods, BOOL_SERIALIZED_LEN}, - address_serialization::{AddressSerializationMethods, AZTEC_ADDRESS_SERIALIZED_LEN}, - u8_serialization::{U8SerializationMethods, U8_SERIALIZED_LEN}, - }, - }; - use dep::aztec::protocol_types::{ - abis::function_selector::FunctionSelector, - address::AztecAddress, + protocol_types::{ + type_serialization::{ + FIELD_SERIALIZED_LEN, + BOOL_SERIALIZED_LEN, + U8_SERIALIZED_LEN, + AZTEC_ADDRESS_SERIALIZED_LEN + }, + abis::function_selector::FunctionSelector, + address::AztecAddress + } }; // docs:start:import_authwit @@ -47,32 +47,31 @@ contract Token { // docs:end:import_authwit use crate::types::{ - transparent_note::{TransparentNote, TransparentNoteMethods, TRANSPARENT_NOTE_LEN}, - token_note::{TokenNote, TokenNoteMethods, TOKEN_NOTE_LEN}, - balances_map::{BalancesMap}, - safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN} + transparent_note::TransparentNote, + token_note::{TokenNote, TOKEN_NOTE_LEN}, + balances_map::{BalancesMap} }; // 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: BalancesMap, // docs:end:storage_balances - total_supply: PublicState, + total_supply: PublicState, // docs:start:storage_pending_shields - pending_shields: Set, + pending_shields: Set, // docs:end:storage_pending_shields - public_balances: Map>, - symbol: PublicState, - name: PublicState, - decimals: PublicState, + public_balances: Map>, + symbol: PublicState, + name: PublicState, + decimals: PublicState, } // docs:end:storage_struct @@ -84,7 +83,6 @@ contract Token { admin: PublicState::new( context, 1, - AddressSerializationMethods, ), // docs:end:storage_admin_init // docs:start:storage_minters_init @@ -95,7 +93,6 @@ contract Token { PublicState::new( context, slot, - BoolSerializationMethods, ) }, ), @@ -106,10 +103,9 @@ contract Token { total_supply: PublicState::new( context, 4, - SafeU120SerializationMethods, ), // docs:start:storage_pending_shields_init - pending_shields: Set::new(context, 5, TransparentNoteMethods), + pending_shields: Set::new(context, 5), // docs:end:storage_pending_shields_init public_balances: Map::new( context, @@ -118,24 +114,20 @@ contract Token { PublicState::new( context, slot, - SafeU120SerializationMethods, ) }, ), symbol: PublicState::new( context, 7, - FieldCompressedStringSerializationMethods, ), name: PublicState::new( context, 8, - FieldCompressedStringSerializationMethods, ), decimals: PublicState::new( context, 9, - U8SerializationMethods, ), } } @@ -446,9 +438,9 @@ contract Token { ) -> pub [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); if (storage_slot == 5) { - note_utils::compute_note_hash_and_nullifier(TransparentNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(TransparentNote::deserialize, note_header, serialized_note) } else { - note_utils::compute_note_hash_and_nullifier(TokenNoteMethods, note_header, serialized_note) + note_utils::compute_note_hash_and_nullifier(TokenNote::deserialize, note_header, serialized_note) } } // docs:end:compute_note_hash_and_nullifier diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types.nr index e29a8151e9f..d3b3b1c9e77 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/types.nr @@ -2,4 +2,3 @@ mod transparent_note; mod balance_set; mod balances_map; mod token_note; -mod safe_u120_serialization; diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types/balance_set.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types/balance_set.nr index fc2303da23b..707c73461af 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types/balance_set.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/types/balance_set.nr @@ -18,7 +18,7 @@ use dep::aztec::note::{ note_interface::NoteInterface, utils::compute_note_hash_for_read_or_nullify, }; -use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; +use crate::types::token_note::TokenNote; // A set implementing standard manipulation of balances. // Does not require spending key, but only knowledge. @@ -26,7 +26,7 @@ use crate::types::token_note::{TokenNote, TOKEN_NOTE_LEN, TokenNoteMethods}; struct BalanceSet { context: Context, owner: AztecAddress, - set: Set + set: Set } impl BalanceSet { @@ -35,7 +35,6 @@ impl BalanceSet { let set = Set { context, storage_slot, - note_interface: TokenNoteMethods, }; Self { context, diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types/safe_u120_serialization.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types/safe_u120_serialization.nr deleted file mode 100644 index 876007184fe..00000000000 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types/safe_u120_serialization.nr +++ /dev/null @@ -1,18 +0,0 @@ -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, -}; diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types/token_note.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types/token_note.nr index f87ccd3cef2..ad0567bf28e 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -14,6 +14,10 @@ use dep::aztec::{ state_vars::set::Set, log::emit_encrypted_log, hash::pedersen_hash, + protocol_types::traits::{ + Serialize, + Deserialize + }, }; use dep::aztec::oracle::{ rand::rand, @@ -39,21 +43,14 @@ struct TokenNote { header: NoteHeader, } -impl TokenNote { - pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { - Self { - amount, - owner, - randomness: rand(), - header: NoteHeader::empty(), - } - } - - pub fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { +impl Serialize for TokenNote { + fn serialize(self) -> [Field; TOKEN_NOTE_LEN] { [self.amount.value as Field, self.owner.to_field(), self.randomness] } +} - pub fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> Self { +impl Deserialize for TokenNote { + fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> Self { Self { amount: SafeU120::new(serialized_note[0]), owner: AztecAddress::from_field(serialized_note[1]), @@ -61,8 +58,10 @@ impl TokenNote { header: NoteHeader::empty(), } } +} - pub fn compute_note_hash(self) -> Field { +impl NoteInterface for TokenNote { + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount.value as Field, @@ -72,8 +71,8 @@ impl TokenNote { } // docs:start:nullifier - pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = context.request_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -84,8 +83,8 @@ impl TokenNote { } // docs:end:nullifier - pub fn compute_nullifier_without_context(self) -> Field { - let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(TokenNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(self); let secret = get_nullifier_secret_key(self.owner); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ @@ -95,12 +94,16 @@ impl TokenNote { ],0) } - pub fn set_header(&mut self, header: NoteHeader) { + fn set_header(&mut self, header: NoteHeader) { self.header = header; } + fn get_header(note: TokenNote) -> NoteHeader { + note.header + } + // Broadcasts the note as an encrypted log on L1. - pub fn broadcast(self, context: &mut PrivateContext, slot: Field) { + fn broadcast(self, context: &mut PrivateContext, slot: Field) { // We only bother inserting the note if non-empty to save funds on gas. if !self.amount.is_zero() { let encryption_pub_key = get_public_key(self.owner); @@ -115,46 +118,15 @@ impl TokenNote { } } -fn deserialize(serialized_note: [Field; TOKEN_NOTE_LEN]) -> TokenNote { - TokenNote::deserialize(serialized_note) -} - -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, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} - -fn compute_nullifier_without_context(note: TokenNote) -> Field { - note.compute_nullifier_without_context() -} - -fn get_header(note: TokenNote) -> NoteHeader { - note.header -} - -fn set_header(note: &mut TokenNote, header: NoteHeader) { - note.set_header(header) -} +impl TokenNote { + pub fn new(amount: SafeU120, owner: AztecAddress) -> Self { + Self { + amount, + owner, + randomness: rand(), + header: NoteHeader::empty(), + } + } -// Broadcasts the note as an encrypted log on L1. -fn broadcast(context: &mut PrivateContext, slot: Field, note: TokenNote) { - note.broadcast(context, slot); + } - -global TokenNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; diff --git a/yarn-project/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/yarn-project/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index 361413bc82b..0c5ea2a724e 100644 --- a/yarn-project/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/yarn-project/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -7,6 +7,7 @@ use dep::aztec::{ }, hash::{compute_secret_hash, pedersen_hash}, context::PrivateContext, + protocol_types::traits::{Serialize, Deserialize, Empty} }; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -22,38 +23,14 @@ struct TransparentNote { header: NoteHeader, } -impl TransparentNote { - - // CONSTRUCTORS - - pub 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 - pub fn new_from_secret(amount: Field, secret: Field) -> Self { - TransparentNote { - amount: amount, - secret_hash: compute_secret_hash(secret), - secret: secret, - header: NoteHeader::empty(), - } - } - - - // STANDARD NOTE_INTERFACE FUNCTIONS - - pub fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { +impl Serialize for TransparentNote { + fn serialize(self) -> [Field; TRANSPARENT_NOTE_LEN] { [self.amount, self.secret_hash] } +} - pub fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { +impl Deserialize for TransparentNote { + fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { TransparentNote { amount: serialized_note[0], secret_hash: serialized_note[1], @@ -61,8 +38,18 @@ impl TransparentNote { header: NoteHeader::empty(), } } +} + +impl Empty for TransparentNote { + fn empty() -> Self { + TransparentNote::new(0, 0) + } - pub fn compute_note_hash(self) -> Field { +} + +impl NoteInterface for TransparentNote { + + fn compute_note_hash(self) -> Field { // TODO(#1205) Should use a non-zero generator index. pedersen_hash([ self.amount, @@ -70,69 +57,59 @@ impl TransparentNote { ],0) } - pub fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { + fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { self.compute_nullifier_without_context() } - pub fn compute_nullifier_without_context(self) -> Field { - let siloed_note_hash = compute_note_hash_for_read_or_nullify(TransparentNoteMethods, self); + fn compute_nullifier_without_context(self) -> Field { + // TODO(#1386): should use `compute_note_hash_for_read_or_nullify` once public functions inject nonce! + let siloed_note_hash = compute_note_hash_for_read_or_nullify(self); // TODO(#1205) Should use a non-zero generator index. pedersen_hash([self.secret, siloed_note_hash],0) } - pub fn set_header(&mut self, header: NoteHeader) { + + fn set_header(&mut self, header: NoteHeader) { self.header = header; } - - // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - - pub fn knows_secret(self, secret: Field) { - let hash = compute_secret_hash(secret); - assert(self.secret_hash == hash); + fn get_header(note: TransparentNote) -> NoteHeader { + note.header } -} - -fn deserialize(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> TransparentNote { - TransparentNote::deserialize(serialized_note) -} - -fn serialize(note: TransparentNote) -> [Field; TRANSPARENT_NOTE_LEN] { - note.serialize() -} -fn compute_note_hash(note: TransparentNote) -> Field { - note.compute_note_hash() + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + assert(false, "TransparentNote does not support broadcast"); + } } -fn compute_nullifier(note: TransparentNote, context: &mut PrivateContext) -> Field { - note.compute_nullifier(context) -} +impl TransparentNote { -fn compute_nullifier_without_context(note: TransparentNote) -> Field { - note.compute_nullifier_without_context() -} + // CONSTRUCTORS -fn get_header(note: TransparentNote) -> NoteHeader { - note.header -} + pub 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 + pub fn new_from_secret(amount: Field, secret: Field) -> Self { + TransparentNote { + amount: amount, + secret_hash: compute_secret_hash(secret), + secret: secret, + header: NoteHeader::empty(), + } + } -fn set_header(note: &mut TransparentNote, header: NoteHeader) { - note.set_header(header) -} + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE -fn broadcast(context: &mut PrivateContext, slot: Field, note: TransparentNote) { - assert(false, "TransparentNote does not support broadcast"); + pub fn knows_secret(self, secret: Field) { + let hash = compute_secret_hash(secret); + assert(self.secret_hash == hash); + } } - -global TransparentNoteMethods = NoteInterface { - deserialize, - serialize, - compute_note_hash, - compute_nullifier, - compute_nullifier_without_context, - get_header, - set_header, - broadcast, -}; // docs:end:token_types_all \ No newline at end of file diff --git a/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr b/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr index 35a4d520af1..c06630b6f92 100644 --- a/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/yarn-project/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -17,12 +17,6 @@ contract Uniswap { context::{PrivateContext, PublicContext, Context}, oracle::{context::get_portal_address}, state_vars::{map::Map, public_state::PublicState}, - types::type_serialization::bool_serialization::{ - BoolSerializationMethods, BOOL_SERIALIZED_LEN, - }, - types::type_serialization::field_serialization::{ - FieldSerializationMethods, FIELD_SERIALIZED_LEN, - }, }; use dep::authwit::auth::{IS_VALID_SELECTOR, assert_current_call_valid_authwit_public, compute_authwit_message_hash}; @@ -32,10 +26,10 @@ contract Uniswap { struct Storage { // like with account contracts, stores the approval message on a slot and tracks if they are active - approved_action: Map>, + approved_action: Map>, // tracks the nonce used to create the approval message for burning funds // gets incremented each time after use to prevent replay attacks - nonce_for_burn_approval: PublicState, + nonce_for_burn_approval: PublicState, } impl Storage { @@ -45,10 +39,10 @@ contract Uniswap { context, 1, |context, slot| { - PublicState::new(context, slot, BoolSerializationMethods) + PublicState::new(context, slot) }, ), - nonce_for_burn_approval: PublicState::new(context, 2, FieldSerializationMethods), + nonce_for_burn_approval: PublicState::new(context, 2), } } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/function_selector.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/function_selector.nr index c9ddf6da8be..93538f5248e 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/function_selector.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/function_selector.nr @@ -1,5 +1,6 @@ use crate::utils::field::field_from_bytes; use dep::std::cmp::Eq; +use crate::traits::{Serialize, Deserialize}; global SELECTOR_SIZE = 4; @@ -14,6 +15,20 @@ impl Eq for FunctionSelector { } } +impl Serialize<1> for FunctionSelector { + fn serialize(self: Self) -> [Field; 1] { + [self.inner as Field] + } +} + +impl Deserialize<1> for FunctionSelector { + fn deserialize(fields: [Field; 1]) -> Self { + Self { + inner: fields[0] as u32 + } + } +} + impl FunctionSelector { fn to_field(self) -> Field { self.inner as Field @@ -46,14 +61,4 @@ impl FunctionSelector { pub fn zero() -> Self { Self { inner: 0 } } - - pub fn serialize(self: Self) -> [Field; 1] { - [self.inner as Field] - } - - pub fn deserialize(fields: [Field; 1]) -> Self { - Self { - inner: fields[0] as u32 - } - } } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/nullifier_key_validation_request.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/nullifier_key_validation_request.nr index 190b477f8c7..b43754493d1 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/nullifier_key_validation_request.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/nullifier_key_validation_request.nr @@ -1,7 +1,7 @@ use dep::std::cmp::Eq; use crate::{ address::AztecAddress, - traits::Empty, + traits::{Empty, Serialize, Deserialize}, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, }; @@ -30,8 +30,8 @@ impl Empty for NullifierKeyValidationRequest { } } -impl NullifierKeyValidationRequest { - pub fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_SERIALIZED_LEN] { +impl Serialize for NullifierKeyValidationRequest { + fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_SERIALIZED_LEN] { [ self.public_key.x, self.public_key.y, @@ -39,14 +39,18 @@ impl NullifierKeyValidationRequest { self.secret_key.low, ] } +} - pub fn deserialise(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_SERIALIZED_LEN]) -> Self { +impl Deserialize for NullifierKeyValidationRequest { + fn deserialize(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_SERIALIZED_LEN]) -> Self { Self { public_key: GrumpkinPoint::new(fields[0], fields[1]), secret_key: GrumpkinPrivateKey::new(fields[2], fields[3]), } } +} +impl NullifierKeyValidationRequest { pub fn to_context(self, contract_address: AztecAddress) -> NullifierKeyValidationRequestContext { NullifierKeyValidationRequestContext { public_key: self.public_key, @@ -80,8 +84,8 @@ impl Empty for NullifierKeyValidationRequestContext { } } -impl NullifierKeyValidationRequestContext { - pub fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_SERIALIZED_LEN] { +impl Serialize for NullifierKeyValidationRequestContext { + fn serialize(self) -> [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_SERIALIZED_LEN] { [ self.public_key.x, self.public_key.y, @@ -90,8 +94,10 @@ impl NullifierKeyValidationRequestContext { self.contract_address.to_field(), ] } +} - pub fn deserialise(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_SERIALIZED_LEN]) -> Self { +impl Deserialize for NullifierKeyValidationRequestContext { + fn deserialize(fields: [Field; NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_SERIALIZED_LEN]) -> Self { Self { public_key: GrumpkinPoint::new(fields[0], fields[1]), secret_key: GrumpkinPrivateKey::new(fields[2], fields[3]), @@ -99,3 +105,4 @@ impl NullifierKeyValidationRequestContext { } } } + diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr index a3b07213146..466420cd416 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/private_circuit_public_inputs.nr @@ -25,7 +25,7 @@ use crate::constants::{ PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, }; -use crate::traits::Hash; +use crate::traits::{Hash, Serialize, Deserialize}; struct PrivateCircuitPublicInputs { call_context: CallContext, @@ -99,7 +99,7 @@ impl Hash for PrivateCircuitPublicInputs { } } -impl PrivateCircuitPublicInputs { +impl Serialize for PrivateCircuitPublicInputs { fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(0); fields.push_array(self.call_context.serialize()); diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/side_effect.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/side_effect.nr index 3303ef4539f..f49b429a417 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/side_effect.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/abis/side_effect.nr @@ -1,6 +1,6 @@ use crate::constants::{GENERATOR_INDEX__SIDE_EFFECT}; use dep::std::cmp::Eq; -use crate::traits::{Empty, Hash}; +use crate::traits::{Empty, Hash, Serialize, Deserialize}; trait Ordered { fn counter(self) -> u32; @@ -40,18 +40,22 @@ impl Hash for SideEffect { } } -impl SideEffect { - pub fn serialize(self) -> [Field; 2] { +impl Serialize<2> for SideEffect { + fn serialize(self) -> [Field; 2] { [self.value, self.counter as Field] } +} - pub fn deserialise(values: [Field; 2]) -> Self { +impl Deserialize<2> for SideEffect { + fn deserialize(values: [Field; 2]) -> Self { Self { value: values[0], counter: values[1] as u32, } } +} +impl SideEffect { pub fn is_empty(self) -> bool { (self.value == 0) & (self.counter == 0) @@ -96,19 +100,23 @@ impl Hash for SideEffectLinkedToNoteHash { } } -impl SideEffectLinkedToNoteHash{ - pub fn serialize(self) -> [Field; 3] { +impl Serialize<3> for SideEffectLinkedToNoteHash { + fn serialize(self) -> [Field; 3] { [self.value, self.note_hash, self.counter as Field] } +} - pub fn deserialise(values: [Field; 3]) -> Self { +impl Deserialize<3> for SideEffectLinkedToNoteHash { + fn deserialize(values: [Field; 3]) -> Self { Self { value: values[0], note_hash: values[1], counter: values[2] as u32, } } +} +impl SideEffectLinkedToNoteHash{ pub fn is_empty(self) -> bool { (self.value == 0) & (self.note_hash == 0) diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/address.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/address.nr index 14706b5bd14..0f581c0507b 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/address.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/address.nr @@ -8,7 +8,8 @@ use crate::{ grumpkin_point::GrumpkinPoint, }; use dep::std::cmp::Eq; -use crate::traits::{Empty, ToField}; +use crate::traits::{Empty, ToField, Serialize, Deserialize}; +use crate::type_serialization::{ETH_ADDRESS_SERIALIZED_LEN, AZTEC_ADDRESS_SERIALIZED_LEN}; // Aztec address struct AztecAddress { @@ -35,6 +36,18 @@ impl ToField for AztecAddress { } } +impl Serialize for AztecAddress { + fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_SERIALIZED_LEN] { + [self.to_field()] + } +} + +impl Deserialize for AztecAddress { + fn deserialize(fields: [Field; AZTEC_ADDRESS_SERIALIZED_LEN]) -> Self { + AztecAddress::from_field(fields[0]) + } +} + impl AztecAddress { pub fn zero() -> Self { Self { @@ -71,16 +84,6 @@ impl AztecAddress { inner : result } } - - pub fn serialize(self: Self) -> [Field; 1] { - [self.inner] - } - - pub fn deserialize(fields: [Field; 1]) -> Self { - Self { - inner: fields[0] - } - } } struct EthAddress{ @@ -107,6 +110,20 @@ impl ToField for EthAddress { } } +impl Serialize for EthAddress { + fn serialize(self: Self) -> [Field; ETH_ADDRESS_SERIALIZED_LEN] { + [self.inner] + } +} + +impl Deserialize for EthAddress { + fn deserialize(fields: [Field; ETH_ADDRESS_SERIALIZED_LEN]) -> Self { + Self { + inner: fields[0] + } + } +} + impl EthAddress{ pub fn zero() -> Self { Self { @@ -134,16 +151,6 @@ impl EthAddress{ inner : result } } - - pub fn serialize(self: Self) -> [Field; 1] { - [self.inner] - } - - pub fn deserialize(fields: [Field; 1]) -> Self { - Self { - inner: fields[0] - } - } } // Partial address diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/deployment_data.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/deployment_data.nr index a0ef079d69a..040aec6e2d3 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/deployment_data.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/deployment_data.nr @@ -5,7 +5,7 @@ use crate::constants::{ }; use crate::hash::pedersen_hash; use crate::grumpkin_point::GrumpkinPoint; -use crate::traits::Hash; +use crate::traits::{Hash, Serialize}; // docs:start:contract-deployment-data struct ContractDeploymentData { @@ -23,7 +23,7 @@ impl Hash for ContractDeploymentData { } } -impl ContractDeploymentData { +impl Serialize for ContractDeploymentData { fn serialize(self) -> [Field; CONTRACT_DEPLOYMENT_DATA_LENGTH] { [ self.deployer_public_key.x, @@ -34,7 +34,10 @@ impl ContractDeploymentData { self.portal_contract_address.to_field(), ] } +} +impl ContractDeploymentData { + fn assert_is_zero(self) { self.deployer_public_key.assert_is_zero(); assert(self.constructor_vk_hash == 0); diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/storage_update_request.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/storage_update_request.nr index 0cfbc1cabb1..ecd535c96ff 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/storage_update_request.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/contrakt/storage_update_request.nr @@ -6,7 +6,7 @@ use crate::{ hash::pedersen_hash, }; use dep::std::cmp::Eq; -use crate::traits::{Hash, Empty}; +use crate::traits::{Hash, Empty, Serialize}; struct StorageUpdateRequest{ storage_slot : Field, @@ -39,11 +39,13 @@ impl Hash for StorageUpdateRequest { } } -impl StorageUpdateRequest { - pub fn serialize(self) -> [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH] { +impl Serialize for StorageUpdateRequest { + fn serialize(self) -> [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH] { [self.storage_slot, self.old_value, self.new_value] } +} +impl StorageUpdateRequest { pub fn is_empty(self) -> bool { self.storage_slot == 0 } diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/grumpkin_point.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/grumpkin_point.nr index 6afee7c4df0..71322d0afa5 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/grumpkin_point.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/grumpkin_point.nr @@ -1,3 +1,4 @@ +use crate::traits::{Serialize, Deserialize}; use dep::std::cmp::Eq; global GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2; @@ -7,6 +8,12 @@ struct GrumpkinPoint { y: Field, } +impl Serialize for GrumpkinPoint { + fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] { + [self.x, self.y] + } +} + impl Eq for GrumpkinPoint { fn eq(self, point: GrumpkinPoint) -> bool { (point.x == self.x) & (point.y == self.y) @@ -29,10 +36,6 @@ impl GrumpkinPoint { (self.x == 0) & (self.y == 0) } - fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] { - [self.x, self.y] - } - // TODO(David): Would be quite careful here as (0,0) is not a point // on the curve. A boolean flag may be the better approach here, // would also cost less constraints. It seems like we don't need to diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/lib.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/lib.nr index 0bbcd8eecda..936ed75a951 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/lib.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/lib.nr @@ -13,6 +13,7 @@ mod constants; mod mocked; mod hash; mod traits; +mod type_serialization; mod header; diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr index 68ad8e56ff6..e4cd56320cc 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/traits.nr @@ -44,3 +44,15 @@ impl ToField for Field { self } } + +// docs:start:serialize +trait Serialize { + fn serialize(self) -> [Field; N]; +} +// docs:end:serialize + +// docs:start:deserialize +trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; +} +// docs:end:deserialize \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/type_serialization.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/type_serialization.nr new file mode 100644 index 00000000000..7bc12f02d27 --- /dev/null +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/type_serialization.nr @@ -0,0 +1,56 @@ +use crate::traits::{Serialize, Deserialize}; + +global BOOL_SERIALIZED_LEN: Field = 1; +global U32_SERIALIZED_LEN: Field = 1; +global U8_SERIALIZED_LEN: Field = 1; +global FIELD_SERIALIZED_LEN: Field = 1; +global AZTEC_ADDRESS_SERIALIZED_LEN = 1; +global ETH_ADDRESS_SERIALIZED_LEN = 1; + +impl Serialize for u32 { + fn serialize(self) -> [Field; U32_SERIALIZED_LEN] { + [self as Field] + } +} + +impl Deserialize for u32 { + fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self { + fields[0] as u32 + } +} + +impl Serialize for u8 { + fn serialize(self) -> [Field; U32_SERIALIZED_LEN] { + [self as Field] + } +} + +impl Deserialize for u8 { + fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self { + fields[0] as u8 + } +} + +impl Serialize for Field { + fn serialize(self) -> [Field; U32_SERIALIZED_LEN] { + [self] + } +} + +impl Deserialize for Field { + fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self { + fields[0] + } +} + +impl Serialize for bool { + fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] { + [self as Field] + } +} + +impl Deserialize for bool { + fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool { + fields[0] as bool + } +}