Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/docs/developers/docs/resources/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,31 @@ Update attributes of your functions:
fn my_utility_func() {
```

### Dropping remote mutable references to public context

`PrivateContext` generally needs to be passed as a mutable reference to functions because it does actually hold state
we're mutating. This is not the case for `PublicContext`, or `UtilityContext` - these are just marker objects that
indicate the current execution mode and make available the correct subset of the API. For this reason we have dropped
the mutable reference from the API.

If you've passed the context as an argument to custom functions you will need to do the following migration (example
from our token contract):

```diff
#[contract_library_method]
fn _finalize_transfer_to_private(
from_and_completer: AztecAddress,
amount: u128,
partial_note: PartialUintNote,
- context: &mut PublicContext,
- storage: Storage<&mut PublicContext>,
+ context: PublicContext,
+ storage: Storage<PublicContext>,
) {
...
}
```

### Authwit Test Helper now takes `env`

The `add_private_authwit_from_call_interface` test helper available in `test::helpers::authwit` now takes a `TestEnvironment` parameter, mirroring `add_public_authwit_from_call_interface`. This adds some unfortunate verbosity, but there are bigger plans to improve authwit usage in Noir tests in the near future.
Expand Down
18 changes: 7 additions & 11 deletions noir-projects/aztec-nr/aztec/src/authwit/auth.nr
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,13 @@ pub fn assert_inner_hash_valid_authwit(
* @param on_behalf_of The address that has allegedly authorized the current call
*/
pub unconstrained fn assert_current_call_valid_authwit_public(
context: &mut PublicContext,
context: PublicContext,
on_behalf_of: AztecAddress,
) {
let inner_hash = compute_inner_authwit_hash([
(*context).msg_sender().unwrap().to_field(),
(*context).selector().to_field(),
(*context).get_args_hash(),
context.msg_sender().unwrap().to_field(),
context.selector().to_field(),
context.get_args_hash(),
]);
assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);
}
Expand All @@ -337,7 +337,7 @@ pub unconstrained fn assert_current_call_valid_authwit_public(
* @param on_behalf_of The address that has allegedly authorized the `inner_hash`
*/
pub unconstrained fn assert_inner_hash_valid_authwit_public(
context: &mut PublicContext,
context: PublicContext,
on_behalf_of: AztecAddress,
inner_hash: Field,
) {
Expand Down Expand Up @@ -434,11 +434,7 @@ pub fn compute_authwit_message_hash(
* @param message_hash The hash of the message to authorize
* @param authorize True if the message should be authorized, false if it should be revoked
*/
pub unconstrained fn set_authorized(
context: &mut PublicContext,
message_hash: Field,
authorize: bool,
) {
pub unconstrained fn set_authorized(context: PublicContext, message_hash: Field, authorize: bool) {
let res = context.call_public_function(
CANONICAL_AUTH_REGISTRY_ADDRESS,
comptime { FunctionSelector::from_signature("set_authorized(Field,bool)") },
Expand All @@ -455,7 +451,7 @@ pub unconstrained fn set_authorized(
*
* @param reject True if all authwits should be rejected, false otherwise
*/
pub unconstrained fn set_reject_all(context: &mut PublicContext, reject: bool) {
pub unconstrained fn set_reject_all(context: PublicContext, reject: bool) {
let res = context.call_public_function(
CANONICAL_AUTH_REGISTRY_ADDRESS,
comptime { FunctionSelector::from_signature("set_reject_all(bool)") },
Expand Down
6 changes: 3 additions & 3 deletions noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ where
/// # Returns
/// * `T` - Whatever data the called function has returned.
///
pub unconstrained fn call(self, context: &mut PublicContext) -> T {
pub unconstrained fn call(self, context: PublicContext) -> T {
let returns = context.call_public_function(
self.target_contract,
self.selector,
Expand Down Expand Up @@ -337,7 +337,7 @@ where
/// # Returns
/// * `T` - Whatever data the called function has returned.
///
pub unconstrained fn view(self, context: &mut PublicContext) -> T {
pub unconstrained fn view(self, context: PublicContext) -> T {
let returns = context.static_call_public_function(
self.target_contract,
self.selector,
Expand Down Expand Up @@ -610,7 +610,7 @@ where
/// # Returns
/// * `T` - Whatever data the called function has returned.
///
pub unconstrained fn view(self, context: &mut PublicContext) -> T {
pub unconstrained fn view(self, context: PublicContext) -> T {
let returns = context.static_call_public_function(
self.target_contract,
self.selector,
Expand Down
14 changes: 7 additions & 7 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl PublicContext {
/// # Arguments
/// * `log` - The data to log, must implement Serialize trait
///
pub fn emit_public_log<T>(_self: &mut Self, log: T)
pub fn emit_public_log<T>(_self: Self, log: T)
where
T: Serialize,
{
Expand Down Expand Up @@ -214,7 +214,7 @@ impl PublicContext {
/// * Will revert if message doesn't exist or was already consumed
///
pub fn consume_l1_to_l2_message(
&mut self,
self: Self,
content: Field,
secret: Field,
sender: EthAddress,
Expand Down Expand Up @@ -269,7 +269,7 @@ impl PublicContext {
/// * `recipient` - Ethereum address that will receive the message
/// * `content` - Message content (32 bytes as a Field element)
///
pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {
pub fn message_portal(_self: Self, recipient: EthAddress, content: Field) {
// Safety: AVM opcodes are constrained by the AVM itself
unsafe { send_l2_to_l1_msg(recipient, content) };
}
Expand All @@ -288,7 +288,7 @@ impl PublicContext {
/// * `[Field]` - Return data from the called function
///
pub unconstrained fn call_public_function(
_self: &mut Self,
_self: Self,
contract_address: AztecAddress,
function_selector: FunctionSelector,
args: [Field],
Expand Down Expand Up @@ -333,7 +333,7 @@ impl PublicContext {
/// * `[Field]` - Return data from the called function
///
pub unconstrained fn static_call_public_function(
_self: &mut Self,
_self: Self,
contract_address: AztecAddress,
function_selector: FunctionSelector,
args: [Field],
Expand Down Expand Up @@ -381,7 +381,7 @@ impl PublicContext {
/// # Advanced
/// * The note hash will be siloed with the contract address by the protocol
///
pub fn push_note_hash(_self: &mut Self, note_hash: Field) {
pub fn push_note_hash(_self: Self, note_hash: Field) {
// Safety: AVM opcodes are constrained by the AVM itself
unsafe { emit_note_hash(note_hash) };
}
Expand All @@ -406,7 +406,7 @@ impl PublicContext {
/// * Automatically siloed with the contract address by the protocol
/// * Used for preventing double-spending and ensuring one-time actions
///
pub fn push_nullifier(_self: &mut Self, nullifier: Field) {
pub fn push_nullifier(_self: Self, nullifier: Field) {
// Safety: AVM opcodes are constrained by the AVM itself
unsafe { emit_nullifier(nullifier) };
}
Expand Down
6 changes: 3 additions & 3 deletions noir-projects/aztec-nr/aztec/src/contract_self.nr
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use protocol_types::{
///
/// # Type Parameters
///
/// - `Context`: The execution context type - either `&mut PrivateContext`, `&mut PublicContext`, or `UtilityContext`
/// - `Context`: The execution context type - either `&mut PrivateContext`, `PublicContext`, or `UtilityContext`
/// - `Storage`: The contract's storage struct (defined with `#[storage]`), or `()` if the contract has no storage
pub struct ContractSelf<Context, Storage> {
/// The address of this contract
Expand Down Expand Up @@ -133,15 +133,15 @@ impl<Storage> ContractSelf<&mut PrivateContext, Storage> {
/// This implementation is used when a contract function is marked with `#[external("public")]`.
/// Public functions are executed by the sequencer in the Aztec Virtual Machine (AVM) and can work only with public
/// state.
impl<Storage> ContractSelf<&mut PublicContext, Storage> {
impl<Storage> ContractSelf<PublicContext, Storage> {
/// Creates a new `ContractSelf` instance for a public function.
///
/// This constructor is called automatically by the macro system and should not be called directly.
///
/// # Parameters
/// - `context`: A mutable reference to the public execution context
/// - `storage`: The contract's storage instance
pub fn new_public(context: &mut PublicContext, storage: Storage) -> Self {
pub fn new_public(context: PublicContext, storage: Storage) -> Self {
Self { context, storage, address: context.this_address() }
}

Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/event/event_emission.nr
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ where
}
}

pub fn emit_event_in_public<Event>(event: Event, context: &mut PublicContext)
pub fn emit_event_in_public<Event>(event: Event, context: PublicContext)
where
Event: EventInterface + Serialize,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::{
};

// Used by `create_mark_as_initialized` (you won't find it through searching)
pub fn mark_as_initialized_public(context: &mut PublicContext) {
pub fn mark_as_initialized_public(context: PublicContext) {
let init_nullifier =
compute_unsiloed_contract_initialization_nullifier((*context).this_address());
compute_unsiloed_contract_initialization_nullifier((context).this_address());
context.push_nullifier(init_nullifier);
}

Expand All @@ -26,7 +26,7 @@ pub fn mark_as_initialized_private(context: &mut PrivateContext) {
}

// Used by `create_init_check` (you won't find it through searching)
pub fn assert_is_initialized_public(context: &mut PublicContext) {
pub fn assert_is_initialized_public(context: PublicContext) {
let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());
assert(context.nullifier_exists(init_nullifier, context.this_address()), "Not initialized");
}
Expand Down
8 changes: 4 additions & 4 deletions noir-projects/aztec-nr/aztec/src/macros/functions/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ pub(crate) comptime fn transform_public(f: FunctionDefinition) {

let storage_init = if module_has_storage {
quote {
let storage = Storage::init(&mut context);
let storage = Storage::init(context);
}
} else {
// Contract does not have Storage defined, so we set storage to the unit type `()`. ContractSelf requires a
Expand All @@ -223,13 +223,13 @@ pub(crate) comptime fn transform_public(f: FunctionDefinition) {
let contract_self_creation = quote {
#[allow(unused_variables)]
let mut self = {
let mut context = dep::aztec::context::public_context::PublicContext::new(|| {
let context = dep::aztec::context::public_context::PublicContext::new(|| {
// We start from 1 because we skip the selector for the dispatch function.
let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote);
dep::aztec::hash::hash_args_array(serialized_args)
});
$storage_init
aztec::contract_self::ContractSelf::new_public(&mut context, storage)
aztec::contract_self::ContractSelf::new_public(context, storage)
};
};

Expand All @@ -253,7 +253,7 @@ pub(crate) comptime fn transform_public(f: FunctionDefinition) {

let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {
(
quote { aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_public(*self.context); },
quote { aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_public(self.context); },
quote { aztec::macros::functions::initialization_utils::mark_as_initialized_public(self.context); },
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl<T, let InitialDelay: u64, Context> DelayedPublicMutable<T, InitialDelay, Co
}
}

impl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, &mut PublicContext>
impl<T, let InitialDelay: u64> DelayedPublicMutable<T, InitialDelay, PublicContext>
where
T: Eq,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ global storage_slot: Field = 47;
global TEST_INITIAL_DELAY: u64 = 60 * 60 * 24;

unconstrained fn in_public(
context: &mut PublicContext,
) -> DelayedPublicMutable<MockStruct, TEST_INITIAL_DELAY, &mut PublicContext> {
context: PublicContext,
) -> DelayedPublicMutable<MockStruct, TEST_INITIAL_DELAY, PublicContext> {
DelayedPublicMutable::new(context, storage_slot)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl<T, Context> PublicImmutable<T, Context> {
}
}

impl<T> PublicImmutable<T, &mut PublicContext> {
impl<T> PublicImmutable<T, PublicContext> {
/// Initializes a PublicImmutable state variable instance with a permanent value.
///
/// This function sets the immutable value for this state variable. It can only
Expand Down Expand Up @@ -171,7 +171,7 @@ impl<T> PublicImmutable<T, &mut PublicContext> {
T: Packable + Eq,
{
assert(self.is_initialized(), "Trying to read from uninitialized PublicImmutable");
WithHash::public_storage_read(*self.context, self.storage_slot)
WithHash::public_storage_read(self.context, self.storage_slot)
}

/// Reads the value stored in this PublicImmutable without checking if the value
Expand All @@ -193,7 +193,7 @@ impl<T> PublicImmutable<T, &mut PublicContext> {
where
T: Packable + Eq,
{
WithHash::public_storage_read(*self.context, self.storage_slot)
WithHash::public_storage_read(self.context, self.storage_slot)
}

fn is_initialized(self) -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::mem::zeroed;

global storage_slot: Field = 7;

fn in_public(context: &mut PublicContext) -> PublicImmutable<MockStruct, &mut PublicContext> {
fn in_public(context: PublicContext) -> PublicImmutable<MockStruct, PublicContext> {
PublicImmutable::new(context, storage_slot)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<T, Context> PublicMutable<T, Context> {
}
}

impl<T> PublicMutable<T, &mut PublicContext> {
impl<T> PublicMutable<T, PublicContext> {
/// Reads the current value stored in this PublicMutable state variable.
///
/// # Returns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::mem::zeroed;

global storage_slot: Field = 7;

fn in_public(context: &mut PublicContext) -> PublicMutable<MockStruct, &mut PublicContext> {
fn in_public(context: PublicContext) -> PublicMutable<MockStruct, PublicContext> {
PublicMutable::new(context, storage_slot)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,7 @@ impl TestEnvironment {
/// state_var.read()
/// });
/// ```
pub unconstrained fn public_context<Env, T>(
self: Self,
f: fn[Env](&mut PublicContext) -> T,
) -> T {
pub unconstrained fn public_context<Env, T>(self: Self, f: fn[Env](PublicContext) -> T) -> T {
self.public_context_opts(PublicContextOptions { contract_address: Option::none() }, f)
}

Expand All @@ -183,20 +180,20 @@ impl TestEnvironment {
pub unconstrained fn public_context_at<Env, T>(
self: Self,
addr: AztecAddress,
f: fn[Env](&mut PublicContext) -> T,
f: fn[Env](PublicContext) -> T,
) -> T {
self.public_context_opts(PublicContextOptions { contract_address: Option::some(addr) }, f)
}

unconstrained fn public_context_opts<Env, T>(
_self: Self,
opts: PublicContextOptions,
f: fn[Env](&mut PublicContext) -> T,
f: fn[Env](PublicContext) -> T,
) -> T {
txe_oracles::set_public_txe_context(opts.contract_address);

let mut context = PublicContext::new(|| 0);
let ret_value = f(&mut context);
let ret_value = f(context);

txe_oracles::set_top_level_txe_context();

Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/uint-note/src/uint_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ global NOTE_COMPLETION_LOG_LENGTH: u32 = 2;

impl PartialUintNote {
/// Completes the partial note, creating a new note that can be used like any other UintNote.
pub fn complete(self, context: &mut PublicContext, completer: AztecAddress, value: u128) {
pub fn complete(self, context: PublicContext, completer: AztecAddress, value: u128) {
// A note with a value of zero is valid, but we cannot currently complete a partial note with such a value
// because this will result in the completion log having its last field set to 0. Public logs currently do not
// track their length, and so trailing zeros are simply trimmed. This results in the completion log missing its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ pub contract NFT {
from_and_completer: AztecAddress,
token_id: Field,
partial_note: PartialNFTNote,
context: &mut PublicContext,
storage: Storage<&mut PublicContext>,
context: PublicContext,
storage: Storage<PublicContext>,
) {
let public_owners_storage = storage.public_owners.at(token_id);
assert(public_owners_storage.read().eq(from_and_completer), "invalid NFT owner");
Expand Down
Loading
Loading