diff --git a/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md b/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md index 8775d976f55..1c68a23fda7 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md +++ b/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md @@ -466,7 +466,7 @@ contract FPC { #[private] fn fee_entrypoint_private(amount: Field, asset: AztecAddress, secret_hash: Field, nonce: Field) { - assert(asset == storage.other_asset.read_private()); + assert(asset == storage.other_asset.read()); Token::at(asset).transfer_to_public(context.msg_sender(), context.this_address(), amount, nonce).call(&mut context); FPC::at(context.this_address()).pay_fee_with_shielded_rebate(amount, asset, secret_hash).enqueue(&mut context); } diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 4b258efb087..64407b34c36 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -8,6 +8,20 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## TBD +### [aztec.nr] SharedImmutable renamings + +`SharedImmutable::read_private` and `SharedImmutable::read_public` were renamed to simply `read`, since only one of these versions is ever available depending on the current context. + +```diff +// In private +- let value = storage.my_var.read_private(); ++ let value = storage.my_var.read(); + +// In public +- let value = storage.my_var.read_public(); ++ let value = storage.my_var.read(); +``` + ### [aztec.nr] SharedMutable renamings `SharedMutable` getters (`get_current_value_in_public`, etc.) were renamed by dropping the `_in` suffix, since only one of these versions is ever available depending on the current context. @@ -27,10 +41,11 @@ Aztec is in full-speed development. Literally every version breaks compatibility The `AztecAddress.random()` function now returns valid addresses, i.e. addresses that can receive encrypted messages and therefore have notes be sent to them. `AztecAddress.isValid()` was also added to check for validity of an address. ## 0.63.0 + ### [PXE] Note tagging and discovery PXE's trial decryption of notes has been replaced in favor of a tagging and discovery approach. It is much more efficient and should scale a lot better as the network size increases, since -notes can now be discovered on-demand. For the time being, this means that accounts residing *on different PXE instances* should add senders to their contact list, so notes can be discovered +notes can now be discovered on-demand. For the time being, this means that accounts residing _on different PXE instances_ should add senders to their contact list, so notes can be discovered (accounts created on the same PXE instance will be added as senders for each other by default) ```diff @@ -51,12 +66,14 @@ const receipt = await inclusionsProofsContract.methods.create_note(owner, 5n).se ``` ### [Token contract] Partial notes related refactor + We've decided to replace the old "shield" flow with one leveraging partial notes. This led to a removal of `shield` and `redeem_shield` functions and an introduction of `transfer_to_private`. An advantage of the new approach is that only 1 tx is required and the API of partial notes is generally nicer. For more information on partial notes refer to docs. ### [Token contract] Function naming changes + There have been a few naming changes done for improved consistency. These are the renamings: `transfer_public` --> `transfer_in_public` @@ -65,7 +82,9 @@ These are the renamings: `burn` --> `burn_private` ## 0.62.0 + ### [TXE] Single execution environment + Thanks to recent advancements in Brillig TXE performs every single call as if it was a nested call, spawning a new ACVM or AVM simulator without performance loss. This ensures every single test runs in a consistent environment and allows for clearer test syntax: @@ -74,6 +93,7 @@ This ensures every single test runs in a consistent environment and allows for c -env.call_private(my_contract_interface) +MyContract::at(address).my_function(args).call(&mut env.private()); ``` + This implies every contract has to be deployed before it can be tested (via `env.deploy` or `env.deploy_self`) and of course it has to be recompiled if its code was changed before TXE can use the modified bytecode. ### Uniqueness of L1 to L2 messages @@ -115,18 +135,22 @@ The address now serves as someone's public key to encrypt incoming notes. An add Because of removing key rotation, we can now store addresses as the owner of a note. Because of this and the above change, we can and have removed the process of registering a recipient, because now we do not need any keys of the recipient. example_note.nr + ```diff -npk_m_hash: Field +owner: AztecAddress ``` PXE Interface + ```diff -registerRecipient(completeAddress: CompleteAddress) ``` ## 0.58.0 + ### [l1-contracts] Inbox's MessageSent event emits global tree index + Earlier `MessageSent` event in Inbox emitted a subtree index (index of the message in the subtree of the l2Block). But the nodes and Aztec.nr expects the index in the global L1_TO_L2_MESSAGES_TREE. So to make it easier to parse this, Inbox now emits this global index. ## 0.57.0 @@ -135,8 +159,8 @@ Earlier `MessageSent` event in Inbox emitted a subtree index (index of the messa PXE APIs have been refactored to better reflect the lifecycle of a Tx (`execute private -> simulate kernels -> simulate public (estimate gas) -> prove -> send`) -* `.simulateTx`: Now returns a `TxSimulationResult`, containing the output of private execution, kernel simulation and public simulation (optional). -* `.proveTx`: Now accepts the result of executing the private part of a transaction, so simulation doesn't have to happen again. +- `.simulateTx`: Now returns a `TxSimulationResult`, containing the output of private execution, kernel simulation and public simulation (optional). +- `.proveTx`: Now accepts the result of executing the private part of a transaction, so simulation doesn't have to happen again. Thanks to this refactor, `ContractFunctionInteraction` has been updated to remove its internal cache and avoid bugs due to its mutable nature. As a result our type-safe interfaces now have to be used as follows: @@ -153,7 +177,6 @@ It's still possible to use `.send()` as before, which will perform proving under More changes are coming to these APIs to better support gas estimation mechanisms and advanced features. - ### Changes to public calling convention Contracts that include public functions (that is, marked with `#[public]`), are required to have a function `public_dispatch(selector: Field)` which acts as an entry point. This will be soon the only public function registered/deployed in contracts. The calling convention is updated so that external calls are made to this function. diff --git a/docs/docs/reference/developer_references/smart_contract_reference/storage/shared_state.md b/docs/docs/reference/developer_references/smart_contract_reference/storage/shared_state.md index f7c08262556..6978398613e 100644 --- a/docs/docs/reference/developer_references/smart_contract_reference/storage/shared_state.md +++ b/docs/docs/reference/developer_references/smart_contract_reference/storage/shared_state.md @@ -118,14 +118,10 @@ This function sets the immutable value. It must only be called once during contr A `SharedImmutable`'s storage **must** only be set once via `initialize`. Attempting to override this by manually accessing the underlying storage slots breaks all properties of the data structure, rendering it useless. ::: -### `read_public` +### `read` -Returns the stored immutable value in a public execution context. +Returns the stored immutable value. This function is available in public, private and unconstrained contexts. -#include_code read_decimals_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code read_shared_immutable_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -### `read_private` - -Returns the stored immutable value in a private execution context. - -#include_code read_decimals_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code read_shared_immutable_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr index 52eab0990c4..ea5ac0b46d0 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr @@ -45,7 +45,7 @@ where self.context.storage_write(self.storage_slot, value); } - pub fn read_public(self) -> T { + pub fn read(self) -> T { self.context.storage_read(self.storage_slot) } } @@ -54,7 +54,7 @@ impl SharedImmutable where T: Serialize + Deserialize, { - pub unconstrained fn read_public(self) -> T { + pub unconstrained fn read(self) -> T { self.context.storage_read(self.storage_slot) } } @@ -63,7 +63,7 @@ impl SharedImmutable where T: Serialize + Deserialize, { - pub fn read_private(self) -> T { + pub fn read(self) -> T { let header = self.context.get_header(); let mut fields = [0; T_SERIALIZED_LEN]; diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index d188ebe78db..2f8cd94a604 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -59,7 +59,7 @@ contract AppSubscription { context.set_as_fee_payer(); // TODO(palla/gas) Assert fee_juice_limit_per_tx is less than this tx gas_limit - let _gas_limit = storage.fee_juice_limit_per_tx.read_private(); + let _gas_limit = storage.fee_juice_limit_per_tx.read(); context.end_setup(); @@ -67,7 +67,7 @@ contract AppSubscription { // is performing the check. privately_check_block_number(Comparator.LT, note.expiry_block_number, &mut context); - payload.execute_calls(&mut context, storage.target_address.read_private()); + payload.execute_calls(&mut context, storage.target_address.read()); } #[public] @@ -95,11 +95,11 @@ contract AppSubscription { ) { assert(tx_count as u64 <= SUBSCRIPTION_TXS as u64); - Token::at(storage.subscription_token_address.read_private()) + Token::at(storage.subscription_token_address.read()) .transfer_in_private( context.msg_sender(), - storage.subscription_recipient_address.read_private(), - storage.subscription_price.read_private(), + storage.subscription_recipient_address.read(), + storage.subscription_price.read(), nonce, ) .call(&mut context); diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr index edaf81c7cc4..bbaf23913b3 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -29,7 +29,7 @@ contract Claim { #[private] fn claim(proof_note: ValueNote, recipient: AztecAddress) { // 1) Check that the note corresponds to the target contract and belongs to the sender - let target_address = storage.target_contract.read_private(); + let target_address = storage.target_contract.read(); assert( target_address == proof_note.header.contract_address, "Note does not correspond to the target contract", @@ -51,8 +51,8 @@ contract Claim { context.push_nullifier(nullifier); // 4) Finally we mint the reward token to the sender of the transaction - Token::at(storage.reward_token.read_private()) - .mint_to_public(recipient, proof_note.value) - .enqueue(&mut context); + Token::at(storage.reward_token.read()).mint_to_public(recipient, proof_note.value).enqueue( + &mut context, + ); } } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 991b10c40a4..056cc5d80b0 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -70,13 +70,13 @@ contract Crowdfunding { // 1) Check that the deadline has not passed --> we do that via the router contract to conceal which contract // is performing the check. // docs:start:call-check-deadline - let deadline = storage.deadline.read_private(); + let deadline = storage.deadline.read(); privately_check_timestamp(Comparator.LT, deadline, &mut context); // docs:end:call-check-deadline // docs:start:do-transfer // 2) Transfer the donation tokens from donor to this contract let donor = context.msg_sender(); - Token::at(storage.donation_token.read_private()) + Token::at(storage.donation_token.read()) .transfer_in_private(donor, context.this_address(), amount as Field, 0) .call(&mut context); // docs:end:do-transfer @@ -101,13 +101,13 @@ contract Crowdfunding { #[private] fn withdraw(amount: u64) { // 1) Check that msg_sender() is the operator - let operator_address = storage.operator.read_private(); + let operator_address = storage.operator.read(); assert(context.msg_sender() == operator_address, "Not an operator"); // 2) Transfer the donation tokens from this contract to the operator - Token::at(storage.donation_token.read_private()) - .transfer(operator_address, amount as Field) - .call(&mut context); + Token::at(storage.donation_token.read()).transfer(operator_address, amount as Field).call( + &mut context, + ); // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn Crowdfunding::at(context.this_address()) ._publish_donation_receipts(amount, operator_address) diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index dada8fd336b..6ca4ad621f6 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -103,7 +103,7 @@ contract DocsExample { #[private] fn match_shared_immutable(account: AztecAddress, points: u8) { let expected = Leader { account, points }; - let read = storage.shared_immutable.read_private(); + let read = storage.shared_immutable.read(); assert(read.account == expected.account, "Invalid account"); assert(read.points == expected.points, "Invalid points"); @@ -138,23 +138,23 @@ contract DocsExample { #[public] #[view] fn get_shared_immutable_constrained_public() -> Leader { - storage.shared_immutable.read_public() + storage.shared_immutable.read() } #[public] fn get_shared_immutable_constrained_public_multiple() -> [Leader; 5] { - let a = storage.shared_immutable.read_public(); + let a = storage.shared_immutable.read(); [a, a, a, a, a] } #[private] #[view] fn get_shared_immutable_constrained_private() -> Leader { - storage.shared_immutable.read_private() + storage.shared_immutable.read() } unconstrained fn get_shared_immutable() -> Leader { - storage.shared_immutable.read_public() + storage.shared_immutable.read() } #[public] @@ -165,8 +165,8 @@ contract DocsExample { // docs:end:initialize_public_immutable } + // docs:start:read_public_immutable unconstrained fn get_public_immutable() -> Leader { - // docs:start:read_public_immutable storage.public_immutable.read() // docs:end:read_public_immutable } diff --git a/noir-projects/noir-contracts/contracts/fee_juice_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fee_juice_contract/src/main.nr index 065427f87d1..01757a26de8 100644 --- a/noir-projects/noir-contracts/contracts/fee_juice_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fee_juice_contract/src/main.nr @@ -43,14 +43,14 @@ contract FeeJuice { // is a hardcoded constant in the rollup circuits. #[public] fn set_portal(portal_address: EthAddress) { - assert(storage.portal_address.read_public().is_zero()); + assert(storage.portal_address.read().is_zero()); storage.portal_address.initialize(portal_address); } #[private] fn claim(to: AztecAddress, amount: Field, secret: Field, message_leaf_index: Field) { let content_hash = get_bridge_gas_msg_hash(to, amount); - let portal_address = storage.portal_address.read_private(); + let portal_address = storage.portal_address.read(); assert(!portal_address.is_zero()); // Consume message and emit nullifier diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index ab1ffdc4753..a35be34fca8 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -29,7 +29,7 @@ contract FPC { #[private] fn fee_entrypoint_private(amount: Field, asset: AztecAddress, nonce: Field) { // TODO(PR #8022): Once SharedImmutable performs only 1 merkle proof here, we'll save ~4k gates - let settings = storage.settings.read_private(); + let settings = storage.settings.read(); assert(asset == settings.other_asset); diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr index ccefcbef97f..1df5506002c 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr @@ -96,25 +96,25 @@ contract NFT { #[public] #[view] fn public_get_name() -> pub FieldCompressedString { - storage.name.read_public() + storage.name.read() } #[private] #[view] fn private_get_name() -> pub FieldCompressedString { - storage.name.read_private() + storage.name.read() } #[public] #[view] fn public_get_symbol() -> pub FieldCompressedString { - storage.symbol.read_public() + storage.symbol.read() } #[private] #[view] fn private_get_symbol() -> pub FieldCompressedString { - storage.symbol.read_private() + storage.symbol.read() } #[public] diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 0c20ba05832..c104e23a505 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -43,12 +43,12 @@ contract TokenBridge { #[private] fn get_portal_address() -> EthAddress { - storage.portal_address.read_private() + storage.portal_address.read() } #[public] fn get_portal_address_public() -> EthAddress { - storage.portal_address.read_public() + storage.portal_address.read() } // docs:start:claim_public @@ -61,12 +61,12 @@ contract TokenBridge { context.consume_l1_to_l2_message( content_hash, secret, - storage.portal_address.read_public(), + storage.portal_address.read(), message_leaf_index, ); // Mint tokens - Token::at(storage.token.read_public()).mint_to_public(to, amount).call(&mut context); + Token::at(storage.token.read()).mint_to_public(to, amount).call(&mut context); } // docs:end:claim_public @@ -82,12 +82,12 @@ contract TokenBridge { ) { // Send an L2 to L1 message let content = get_withdraw_content_hash(recipient, amount, caller_on_l1); - context.message_portal(storage.portal_address.read_public(), content); + context.message_portal(storage.portal_address.read(), content); // Burn tokens - Token::at(storage.token.read_public()) - .burn_public(context.msg_sender(), amount, nonce) - .call(&mut context); + Token::at(storage.token.read()).burn_public(context.msg_sender(), amount, nonce).call( + &mut context, + ); } // docs:end:exit_to_l1_public @@ -108,12 +108,12 @@ contract TokenBridge { context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, - storage.portal_address.read_private(), + storage.portal_address.read(), message_leaf_index, ); // Read the token address from storage - let token_address = storage.token.read_private(); + let token_address = storage.token.read(); // At last we mint the tokens // docs:start:call_mint_on_token @@ -137,7 +137,7 @@ contract TokenBridge { ) { // Send an L2 to L1 message let content = get_withdraw_content_hash(recipient, amount, caller_on_l1); - context.message_portal(storage.portal_address.read_private(), content); + context.message_portal(storage.portal_address.read(), content); // docs:start:call_assert_token_is_same // Assert that user provided token address is same as seen in storage. @@ -151,7 +151,7 @@ contract TokenBridge { #[public] #[view] fn get_token() -> AztecAddress { - storage.token.read_public() + storage.token.read() } // docs:end:get_token @@ -159,10 +159,7 @@ contract TokenBridge { #[public] #[internal] fn _assert_token_is_same(token: AztecAddress) { - assert( - storage.token.read_public().eq(token), - "Token address is not the same as seen in storage", - ); + assert(storage.token.read().eq(token), "Token address is not the same as seen in storage"); } // docs:end:assert_token_is_same } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index e33553ba6b3..677a585dc72 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -117,41 +117,42 @@ contract Token { #[public] #[view] fn public_get_name() -> FieldCompressedString { - storage.name.read_public() + storage.name.read() } #[private] #[view] fn private_get_name() -> FieldCompressedString { - storage.name.read_private() + storage.name.read() } #[public] #[view] fn public_get_symbol() -> pub FieldCompressedString { - storage.symbol.read_public() + storage.symbol.read() } #[private] #[view] fn private_get_symbol() -> pub FieldCompressedString { - storage.symbol.read_private() + storage.symbol.read() } + // docs:start:read_shared_immutable_public #[public] #[view] fn public_get_decimals() -> pub u8 { - // docs:start:read_decimals_public - storage.decimals.read_public() - // docs:end:read_decimals_public + storage.decimals.read() } + // docs:end:read_shared_immutable_public + + // docs:start:read_shared_immutable_private #[private] #[view] fn private_get_decimals() -> pub u8 { - // docs:start:read_decimals_private - storage.decimals.read_private() - // docs:end:read_decimals_private + storage.decimals.read() } + // docs:end:read_shared_immutable_private // docs:start:admin #[public] diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index e1fd634121f..66b78d4430d 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -104,7 +104,7 @@ contract Uniswap { secret_hash_for_L1_to_l2_message, caller_on_L1, ); - context.message_portal(storage.portal_address.read_public(), content_hash); + context.message_portal(storage.portal_address.read(), content_hash); } // docs:end:swap_public @@ -174,7 +174,7 @@ contract Uniswap { secret_hash_for_L1_to_l2_message, caller_on_L1, ); - context.message_portal(storage.portal_address.read_private(), content_hash); + context.message_portal(storage.portal_address.read(), content_hash); } // docs:end:swap_private @@ -208,7 +208,7 @@ contract Uniswap { // We need to make a call to update it. set_authorized(&mut context, message_hash, true); - let this_portal_address = storage.portal_address.read_public(); + let this_portal_address = storage.portal_address.read(); // Exit to L1 Uniswap Portal ! TokenBridge::at(token_bridge) .exit_to_l1_public(this_portal_address, amount, this_portal_address, nonce)