diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 9823b25d8c95..974efb37ab3b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -3,7 +3,7 @@ use dep::protocol_types::{ traits::{FromField, ToField} }; -use crate::context::{PrivateContext, PublicContext}; +use crate::context::{PrivateContext, PublicContext, UnconstrainedContext}; use crate::state_vars::{ storage::Storage, shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange} @@ -225,6 +225,34 @@ impl SharedMutable { } } +impl SharedMutable where T: ToField + FromField + Eq { + pub fn get_current_value_in_unconstrained(self) -> T { + let block_number = self.context.block_number() as u32; + self.read_value_change().get_current_at(block_number) + } + + pub fn get_current_delay_in_unconstrained(self) -> u32 { + let block_number = self.context.block_number() as u32; + self.read_delay_change().get_current(block_number) + } + + pub fn get_scheduled_value_in_unconstrained(self) -> (T, u32) { + self.read_value_change().get_scheduled() + } + + pub fn get_scheduled_delay_in_unconstrained(self) -> (u32, u32) { + self.read_delay_change().get_scheduled() + } + + fn read_value_change(self) -> ScheduledValueChange { + self.context.storage_read(self.get_value_change_storage_slot()) + } + + fn read_delay_change(self) -> ScheduledDelayChange { + self.context.storage_read(self.get_delay_change_storage_slot()) + } +} + unconstrained fn get_public_storage_hints( address: AztecAddress, storage_slot: Field, 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 6af65f9286cd..60b20626a121 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 @@ -16,7 +16,7 @@ contract DocsExample { use dep::aztec::prelude::{ AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, - PrivateSet, SharedImmutable, Deserialize + PrivateSet, SharedImmutable, SharedMutable, Deserialize }; use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys}; use dep::aztec::note::note_getter_options::Comparator; @@ -49,6 +49,7 @@ contract DocsExample { // docs:start:storage-public-immutable-declaration public_immutable: PublicImmutable, // docs:end:storage-public-immutable-declaration + shared_mutable: SharedMutable, } // Note: The following is no longer necessary to implement manually as our macros do this for us. It is left here @@ -87,7 +88,9 @@ contract DocsExample { ), // docs:end:storage-minters-init // docs:start:storage-public-immutable - public_immutable: PublicImmutable::new(context, 9)// docs:end:storage-public-immutable + public_immutable: PublicImmutable::new(context, 9), + // docs:end:storage-public-immutable + shared_mutable: SharedMutable::new(context, 10) } } } @@ -302,6 +305,21 @@ contract DocsExample { storage.private_immutable.is_initialized() } + #[aztec(public)] + fn set_shared_mutable(value: Field) { + storage.shared_mutable.schedule_value_change(value); + } + + #[aztec(public)] + #[aztec(view)] + fn get_shared_mutable() -> pub Field { + storage.shared_mutable.get_current_value_in_public() + } + + unconstrained fn get_shared_mutable_unconstrained() -> pub Field { + storage.shared_mutable.get_current_value_in_unconstrained() + } + /// Macro equivalence section use dep::aztec::hash::hash_args; diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 400a25e9f361..55a7345d0f2b 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -236,6 +236,34 @@ describe('e2e_state_vars', () => { }); }); + describe('SharedMutable', () => { + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await contract.methods.get_shared_mutable().send().wait(); + } + }; + + it('checks authorized in AuthContract from TestContract with our SharedMutablePrivateGetter before and after a value change', async () => { + // We set the value here, knowing there will be some delay before the value change takes place + await contract.methods.set_shared_mutable(new Fr(6969696969)).send().wait(); + + const value = await contract.methods.get_shared_mutable_unconstrained().simulate(); + + // We expect the value to not have been applied yet + expect(value).toEqual(0n); + + // We wait for the SharedMutable delay + await delay(5); + + // We check after the delay, expecting to find the value we set. + const newValueUnconstrained = await contract.methods.get_shared_mutable_unconstrained().simulate(); + const newValue = await contract.methods.get_shared_mutable().simulate(); + + expect(newValueUnconstrained).toEqual(6969696969n); + expect(newValueUnconstrained).toEqual(newValue); + }); + }); + describe('SharedMutablePrivateGetter', () => { let authContract: AuthContract; let testContract: TestContract;