Skip to content

Commit

Permalink
feat!: rename sharedimmutable methods (#10164)
Browse files Browse the repository at this point in the history
We used to have to do this because we only knew the context at runtime,
but since #6442 we
no longer need this. I'm also doing this for some other state vars, but
chose do to so in separate PRs as some of those changes are a bit
messier.
  • Loading branch information
nventuro authored Nov 25, 2024
1 parent 12b1daa commit ef7cd86
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
31 changes: 27 additions & 4 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<public|private|unconstrained>` suffix, since only one of these versions is ever available depending on the current context.
Expand All @@ -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
Expand All @@ -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`
Expand All @@ -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:

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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:

Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand All @@ -54,7 +54,7 @@ impl<T, let T_SERIALIZED_LEN: u32> SharedImmutable<T, UnconstrainedContext>
where
T: Serialize<T_SERIALIZED_LEN> + Deserialize<T_SERIALIZED_LEN>,
{
pub unconstrained fn read_public(self) -> T {
pub unconstrained fn read(self) -> T {
self.context.storage_read(self.storage_slot)
}
}
Expand All @@ -63,7 +63,7 @@ impl<T, let T_SERIALIZED_LEN: u32> SharedImmutable<T, &mut PrivateContext>
where
T: Serialize<T_SERIALIZED_LEN> + Deserialize<T_SERIALIZED_LEN>,
{
pub fn read_private(self) -> T {
pub fn read(self) -> T {
let header = self.context.get_header();
let mut fields = [0; T_SERIALIZED_LEN];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ 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();

// We check that the note is not expired. We do that via the router contract to conceal which contract
// 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]
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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]
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading

0 comments on commit ef7cd86

Please sign in to comment.