Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
dc63a8a
merge with merge-train
mverzilli Feb 18, 2026
3d45e98
simplify SimulationReturn
mverzilli Feb 17, 2026
7796706
add migration notes
mverzilli Feb 17, 2026
6313c8b
add offchainEffects usage after send() e2e
mverzilli Feb 17, 2026
8d1c752
fix playground
mverzilli Feb 17, 2026
6accc0c
fix boxes
mverzilli Feb 17, 2026
03192e5
fix aztec.js for boxes
mverzilli Feb 17, 2026
3efe757
sort out types
mverzilli Feb 17, 2026
57af637
fix authwit types
mverzilli Feb 17, 2026
3a2718f
fix e2e
mverzilli Feb 17, 2026
2cb9c2c
fix more e2e
mverzilli Feb 17, 2026
660ee5e
fix e2e tests
mverzilli Feb 17, 2026
70aaf1a
update docs examples
mverzilli Feb 17, 2026
0f78a1e
fix more e2e tests
mverzilli Feb 18, 2026
71c5d25
merge
mverzilli Feb 18, 2026
6b58772
another e2e fix
mverzilli Feb 18, 2026
fe599bc
fix e2es after rebase
mverzilli Feb 18, 2026
9f368e0
merge
mverzilli Feb 24, 2026
37bca03
bring migration notes up to date
mverzilli Feb 24, 2026
db86e05
Merge branch 'merge-train/fairies' into mv/expose-offchain-messages
mverzilli Feb 24, 2026
0a7c6cb
fix lint issue
mverzilli Feb 24, 2026
6802923
fix new e2es
mverzilli Feb 24, 2026
1303d5f
trivial versions of offchain enqueue and inbox
mverzilli Feb 25, 2026
0598298
resolve message context via oracles
mverzilli Feb 25, 2026
1196587
customizable offchain discovery
mverzilli Feb 26, 2026
90a32a2
refactor to use capsule arrays
mverzilli Feb 26, 2026
179f59d
handle reorgs
mverzilli Feb 26, 2026
007a57a
clean up reorg test
mverzilli Feb 26, 2026
df8d9b0
make offchain reception a builtin feature
mverzilli Feb 26, 2026
ae40fd1
move DiscoverOffchainMessages to a more reasonable location
mverzilli Feb 27, 2026
d6e55cf
document discover_offchain_messages
mverzilli Feb 27, 2026
c996539
rename to offchain_message_handler
mverzilli Feb 27, 2026
cec2345
hook -> handler
mverzilli Feb 27, 2026
dfef1bd
enqueue -> receive
mverzilli Feb 27, 2026
fd71740
nicer doc for offchain_receive
mverzilli Feb 27, 2026
d0e7098
document OffchainMessageHandler
mverzilli Feb 27, 2026
0f0b27c
offchain_inbox -> offchain
mverzilli Feb 27, 2026
e41e847
offchain_sync_inbox -> default_handler
mverzilli Feb 27, 2026
642a023
receive_offchain_message -> receive
mverzilli Feb 27, 2026
485854d
better docs
mverzilli Feb 27, 2026
49bf4cf
more docs, and visibility restriction
mverzilli Feb 27, 2026
f40df63
more cleanup of offchain inbox handler
mverzilli Mar 2, 2026
e116475
cleanup
mverzilli Mar 2, 2026
db98953
doc comments on MessageTxContext
mverzilli Mar 2, 2026
eca5012
move MessageTxContext
mverzilli Mar 2, 2026
ab48b79
rename MessageContextResponse on TS side
mverzilli Mar 2, 2026
e92d6f7
add tx context serialization tests on ts side
mverzilli Mar 2, 2026
36facfa
consider anchor block
mverzilli Mar 2, 2026
8882923
extract MessageContextService
mverzilli Mar 2, 2026
463709e
tests for oracle
mverzilli Mar 2, 2026
e9e9457
add MessageContextService unit tests
mverzilli Mar 2, 2026
2e18798
rename
mverzilli Mar 2, 2026
f71c4ab
fix private oracle tests
mverzilli Mar 2, 2026
b38b65d
merge with merge-train
mverzilli Feb 18, 2026
06e28d0
simplify SimulationReturn
mverzilli Feb 17, 2026
67809c9
add migration notes
mverzilli Feb 17, 2026
71e3d6a
add offchainEffects usage after send() e2e
mverzilli Feb 17, 2026
9e48615
fix playground
mverzilli Feb 17, 2026
28a9838
fix boxes
mverzilli Feb 17, 2026
bb3fc26
fix aztec.js for boxes
mverzilli Feb 17, 2026
e08d59d
sort out types
mverzilli Feb 17, 2026
c742fd8
fix authwit types
mverzilli Feb 17, 2026
6fc1f3a
fix e2e
mverzilli Feb 17, 2026
2cf5d3a
fix more e2e
mverzilli Feb 17, 2026
1c42899
fix e2e tests
mverzilli Feb 17, 2026
7aadeeb
update docs examples
mverzilli Feb 17, 2026
9d9dd3e
fix more e2e tests
mverzilli Feb 18, 2026
64321b2
merge
mverzilli Feb 18, 2026
70754f0
another e2e fix
mverzilli Feb 18, 2026
cc8685e
fix e2es after rebase
mverzilli Feb 18, 2026
1e855a5
bring migration notes up to date
mverzilli Feb 24, 2026
59f75e4
fix lint issue
mverzilli Feb 24, 2026
3711ec8
fix new e2es
mverzilli Feb 24, 2026
bb6d848
separate offchainMessages from offchainEffects
mverzilli Mar 3, 2026
e24c4db
migration_notes
mverzilli Mar 3, 2026
71f0bac
fix bootstrap
mverzilli Mar 3, 2026
2aa9f7b
update migration notes
mverzilli Mar 3, 2026
9614920
fix e2e
mverzilli Mar 3, 2026
2532396
SimulationReturn -> SimulationResult
mverzilli Mar 3, 2026
548851c
update wallet schema
mverzilli Mar 3, 2026
63bea95
fix batch_call test
mverzilli Mar 3, 2026
566b695
fix units
mverzilli Mar 3, 2026
d3bdfde
add todo
mverzilli Mar 3, 2026
0ede901
Merge branch 'mv/expose-offchain-messages' into martin/poc-offchain-r…
mverzilli Mar 3, 2026
b3d02cc
fix imports
mverzilli Mar 3, 2026
efe87d0
use new apis in e2e
mverzilli Mar 3, 2026
2fbd2dc
fix reorg test
mverzilli Mar 3, 2026
3d806c0
more explanatary comments on inbox loop
mverzilli Mar 3, 2026
f98a26a
wip: receive many msgs at once
mverzilli Mar 9, 2026
f6bc97d
merge from fairies
mverzilli Mar 9, 2026
c0ff5a0
receive many offchain messages on a single call
mverzilli Mar 9, 2026
85491ae
add message ttl data
mverzilli Mar 9, 2026
6c22f22
accept expiration
mverzilli Mar 9, 2026
84e3f6b
remove extension point
mverzilli Mar 9, 2026
accae75
reject contracts with an offchain_receive fn
mverzilli Mar 9, 2026
3cb806f
move offchain stuff from delivery to processing
mverzilli Mar 9, 2026
62de4b3
reduce visibility of mods
mverzilli Mar 9, 2026
3458acf
move more stuff to offchain mod
mverzilli Mar 9, 2026
84d5b66
remove accidental comment
mverzilli Mar 9, 2026
e639cb9
OffchainMessageHandler -> OffchainInboxSync
mverzilli Mar 9, 2026
93f1dda
offchain::default_handler -> offchain::sync_inbox
mverzilli Mar 9, 2026
2bca4e1
reduce visibility of OffchainInboxSync
mverzilli Mar 9, 2026
6e401de
better comments
mverzilli Mar 9, 2026
0844a69
wat auto-formatter
mverzilli Mar 9, 2026
ea21ed1
nit
mverzilli Mar 9, 2026
ac69d74
bound by tx ttl
mverzilli Mar 9, 2026
0685eb3
fix bug in loop and better comments
mverzilli Mar 9, 2026
c743282
bump tolerance to 2 hours
mverzilli Mar 9, 2026
4f6eaa9
mark MessageTxContext as Serialize
mverzilli Mar 9, 2026
04120d7
better comments for MessageTxContext
mverzilli Mar 9, 2026
2ab7299
nit
mverzilli Mar 9, 2026
2ba8b7e
extract test aux for reorg
mverzilli Mar 10, 2026
046bbfe
make it a bit more robust
mverzilli Mar 10, 2026
e4336c5
throw on malformed tx effects
mverzilli Mar 10, 2026
ac0a5c4
remove unnecessary oracle version bump
mverzilli Mar 10, 2026
11303bd
lint disable camel case warnings
mverzilli Mar 10, 2026
15fe102
add tests for offchain sync
mverzilli Mar 10, 2026
36a5701
merge from fairies
mverzilli Mar 10, 2026
3c60911
bump oracle version
mverzilli Mar 10, 2026
54225cb
cleanup test cases
mverzilli Mar 10, 2026
81de2db
fix message context tests
mverzilli Mar 10, 2026
e51d360
add test case for resolved message
mverzilli Mar 10, 2026
f368122
code review comments
mverzilli Mar 11, 2026
4de1d5f
Merge branch 'merge-train/fairies' into martin/poc-offchain-reception
mverzilli Mar 11, 2026
52de33f
update oracle version hash
mverzilli Mar 11, 2026
5518b6f
wip
mverzilli Mar 13, 2026
3ec52e6
merge from fairies
mverzilli Mar 13, 2026
5772be0
use new oracle legacy handling schema
mverzilli Mar 13, 2026
9e68da0
clean up noir side of capsules
mverzilli Mar 16, 2026
f28b45e
make zero address mean global scope
mverzilli Mar 16, 2026
bc7c013
bump pxe db schema version
mverzilli Mar 16, 2026
9e2a2e0
make transient capsules optionally scoped
mverzilli Mar 16, 2026
8b806fa
Merge branch 'merge-train/fairies' into martin/scoped-capsules
mverzilli Mar 16, 2026
381941d
fix oracles
mverzilli Mar 16, 2026
2d1bbf1
add some comments for clarity
mverzilli Mar 16, 2026
e0e8572
Merge branch 'merge-train/fairies' into martin/scoped-capsules
mverzilli Mar 16, 2026
12993f9
fix lint issues
mverzilli Mar 16, 2026
d789f03
Merge branch 'merge-train/fairies' into martin/scoped-capsules
mverzilli Mar 16, 2026
5f62f05
Merge branch 'merge-train/fairies' into martin/scoped-capsules
mverzilli Mar 16, 2026
9f4867a
nit
mverzilli Mar 16, 2026
10fcea7
nit
mverzilli Mar 16, 2026
ebe8c5e
remove some oracles from legacy mapping
mverzilli Mar 16, 2026
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
41 changes: 34 additions & 7 deletions noir-projects/aztec-nr/aztec/src/oracle/capsules.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ where
T: Serialize,
{
let serialized = value.serialize();
store_oracle(contract_address, slot, serialized);
// TODO(@mverzilli): bubble scope param up, for now none=global scope
store_oracle(contract_address, slot, serialized, Option::none());
}

/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none()
Expand All @@ -16,25 +17,44 @@ pub unconstrained fn load<T>(contract_address: AztecAddress, slot: Field) -> Opt
where
T: Deserialize,
{
let serialized_option = load_oracle(contract_address, slot, <T as Deserialize>::N);
// TODO(@mverzilli): bubble scope param up, for now none=global scope
let serialized_option = load_oracle(
contract_address,
slot,
<T as Deserialize>::N,
Option::none(),
);
serialized_option.map(|arr| Deserialize::deserialize(arr))
}

/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.
pub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {
delete_oracle(contract_address, slot);
// TODO(@mverzilli): bubble scope param up, for now none=global scope
delete_oracle(contract_address, slot, Option::none());
}

/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data
/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`. Supports overlapping source and
/// destination regions (which will result in the overlapped source values being overwritten). All copied slots must
/// exist in the database (i.e. have been stored and not deleted)
pub unconstrained fn copy(contract_address: AztecAddress, src_slot: Field, dst_slot: Field, num_entries: u32) {
copy_oracle(contract_address, src_slot, dst_slot, num_entries);
// TODO(@mverzilli): bubble scope param up, for now none=global scope
copy_oracle(
contract_address,
src_slot,
dst_slot,
num_entries,
Option::none(),
);
}

#[oracle(aztec_utl_storeCapsule)]
unconstrained fn store_oracle<let N: u32>(contract_address: AztecAddress, slot: Field, values: [Field; N]) {}
unconstrained fn store_oracle<let N: u32>(
contract_address: AztecAddress,
slot: Field,
values: [Field; N],
scope: Option<AztecAddress>,
) {}

/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must
/// have.
Expand All @@ -48,13 +68,20 @@ unconstrained fn load_oracle<let N: u32>(
contract_address: AztecAddress,
slot: Field,
array_len: u32,
scope: Option<AztecAddress>,
) -> Option<[Field; N]> {}

#[oracle(aztec_utl_deleteCapsule)]
unconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}
unconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field, scope: Option<AztecAddress>) {}

#[oracle(aztec_utl_copyCapsule)]
unconstrained fn copy_oracle(contract_address: AztecAddress, src_slot: Field, dst_slot: Field, num_entries: u32) {}
unconstrained fn copy_oracle(
contract_address: AztecAddress,
src_slot: Field,
dst_slot: Field,
num_entries: u32,
scope: Option<AztecAddress>,
) {}

mod test {
// These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/oracle/version.nr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
///
/// @dev Whenever a contract function or Noir test is run, the `aztec_utl_assertCompatibleOracleVersion` oracle is
/// called and if the oracle version is incompatible an error is thrown.
pub global ORACLE_VERSION: Field = 16;
pub global ORACLE_VERSION: Field = 17;

/// Asserts that the version of the oracle is compatible with the version expected by the contract.
pub fn assert_compatible_oracle_version() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ where
T: Serialize,
{
let serialized = value.serialize();
store_oracle(contract_address, slot, serialized);
store_oracle(contract_address, slot, serialized, Option::none());
}

/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none()
Expand All @@ -16,13 +16,13 @@ pub unconstrained fn load<T>(contract_address: AztecAddress, slot: Field) -> Opt
where
T: Deserialize,
{
let serialized_option = load_oracle(contract_address, slot, <T as Deserialize>::N);
let serialized_option = load_oracle(contract_address, slot, <T as Deserialize>::N, Option::none());
serialized_option.map(|arr| Deserialize::deserialize(arr))
}

/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.
pub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {
delete_oracle(contract_address, slot);
delete_oracle(contract_address, slot, Option::none());
}

/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data
Expand All @@ -35,14 +35,15 @@ pub unconstrained fn copy(
dst_slot: Field,
num_entries: u32,
) {
copy_oracle(contract_address, src_slot, dst_slot, num_entries);
copy_oracle(contract_address, src_slot, dst_slot, num_entries, Option::none());
}

#[oracle(aztec_utl_storeCapsule)]
unconstrained fn store_oracle<let N: u32>(
contract_address: AztecAddress,
slot: Field,
values: [Field; N],
scope: Option<AztecAddress>,
) {}

/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must
Expand All @@ -57,15 +58,17 @@ unconstrained fn load_oracle<let N: u32>(
contract_address: AztecAddress,
slot: Field,
array_len: u32,
scope: Option<AztecAddress>,
) -> Option<[Field; N]> {}

#[oracle(aztec_utl_deleteCapsule)]
unconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}
unconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field, scope: Option<AztecAddress>) {}

#[oracle(aztec_utl_copyCapsule)]
unconstrained fn copy_oracle(
contract_address: AztecAddress,
src_slot: Field,
dst_slot: Field,
num_entries: u32,
scope: Option<AztecAddress>,
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,16 @@ export interface IUtilityExecutionOracle {
messageContextRequestsArrayBaseSlot: Fr,
messageContextResponsesArrayBaseSlot: Fr,
): Promise<void>;
storeCapsule(contractAddress: AztecAddress, key: Fr, capsule: Fr[]): Promise<void>;
loadCapsule(contractAddress: AztecAddress, key: Fr): Promise<Fr[] | null>;
deleteCapsule(contractAddress: AztecAddress, key: Fr): Promise<void>;
copyCapsule(contractAddress: AztecAddress, srcKey: Fr, dstKey: Fr, numEntries: number): Promise<void>;
storeCapsule(contractAddress: AztecAddress, key: Fr, capsule: Fr[], scope?: AztecAddress): void;
loadCapsule(contractAddress: AztecAddress, key: Fr, scope?: AztecAddress): Promise<Fr[] | null>;
deleteCapsule(contractAddress: AztecAddress, key: Fr, scope?: AztecAddress): void;
copyCapsule(
contractAddress: AztecAddress,
srcKey: Fr,
dstKey: Fr,
numEntries: number,
scope?: AztecAddress,
): Promise<void>;
aes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer>;
getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point>;
emitOffchainEffect(data: Fr[]): Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ export function buildLegacyOracleCallbacks(oracle: Oracle): ACIRCallback {
contractAddress: ACVMField[],
slot: ACVMField[],
tSize: ACVMField[],
): Promise<(ACVMField | ACVMField[])[]> => oracle.aztec_utl_loadCapsule(contractAddress, slot, tSize),
): Promise<(ACVMField | ACVMField[])[]> =>
// Last two params represent an Option<AztecAddress> == None, which means the capsule is contract-global,
// matching legacy behavior.
oracle.aztec_utl_loadCapsule(contractAddress, slot, tSize, [new Fr(0).toString()], [new Fr(0).toString()]),
privateStoreInExecutionCache: (values: ACVMField[], hash: ACVMField[]): Promise<ACVMField[]> =>
oracle.aztec_prv_storeInExecutionCache(values, hash),
privateLoadFromExecutionCache: (returnsHash: ACVMField[]): Promise<ACVMField[][]> =>
Expand Down Expand Up @@ -65,15 +68,30 @@ export function buildLegacyOracleCallbacks(oracle: Oracle): ACIRCallback {
contractAddress: ACVMField[],
slot: ACVMField[],
capsule: ACVMField[],
): Promise<ACVMField[]> => oracle.aztec_utl_storeCapsule(contractAddress, slot, capsule),
): Promise<ACVMField[]> =>
// Last two params represent an Option<AztecAddress> == None, which means the capsule is contract-global,
// matching legacy behavior.
oracle.aztec_utl_storeCapsule(contractAddress, slot, capsule, [new Fr(0).toString()], [new Fr(0).toString()]),
utilityCopyCapsule: (
contractAddress: ACVMField[],
srcSlot: ACVMField[],
dstSlot: ACVMField[],
numEntries: ACVMField[],
): Promise<ACVMField[]> => oracle.aztec_utl_copyCapsule(contractAddress, srcSlot, dstSlot, numEntries),
): Promise<ACVMField[]> =>
// Last two params represent an Option<AztecAddress> == None, which means the capsule is contract-global,
// matching legacy behavior.
oracle.aztec_utl_copyCapsule(
contractAddress,
srcSlot,
dstSlot,
numEntries,
[new Fr(0).toString()],
[new Fr(0).toString()],
),
utilityDeleteCapsule: (contractAddress: ACVMField[], slot: ACVMField[]): Promise<ACVMField[]> =>
oracle.aztec_utl_deleteCapsule(contractAddress, slot),
// Last two params represent an Option<AztecAddress> == None, which means the capsule is contract-global,
// matching legacy behavior.
oracle.aztec_utl_deleteCapsule(contractAddress, slot, [new Fr(0).toString()], [new Fr(0).toString()]),
utilityAes128Decrypt: (
ciphertextBVecStorage: ACVMField[],
ciphertextLength: ACVMField[],
Expand Down
35 changes: 29 additions & 6 deletions yarn-project/pxe/src/contract_function_simulator/oracle/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export class UnavailableOracleError extends Error {
}
}

function optionalAddressFromAcvmFields(scopeSome: ACVMField, scopeValue: ACVMField) {
return Fr.fromString(scopeSome).toNumber() === 1 ? AztecAddress.fromField(Fr.fromString(scopeValue)) : undefined;
}

/**
* A data source that has all the apis required by Aztec.nr.
*/
Expand Down Expand Up @@ -544,28 +548,36 @@ export class Oracle {
}

// eslint-disable-next-line camelcase
async aztec_utl_storeCapsule(
aztec_utl_storeCapsule(
[contractAddress]: ACVMField[],
[slot]: ACVMField[],
capsule: ACVMField[],
[scopeSome]: ACVMField[],
[scopeValue]: ACVMField[],
): Promise<ACVMField[]> {
await this.handlerAsUtility().storeCapsule(
const scope = optionalAddressFromAcvmFields(scopeSome, scopeValue);
this.handlerAsUtility().storeCapsule(
AztecAddress.fromField(Fr.fromString(contractAddress)),
Fr.fromString(slot),
capsule.map(Fr.fromString),
scope,
);
return [];
return Promise.resolve([]);
}

// eslint-disable-next-line camelcase
async aztec_utl_loadCapsule(
[contractAddress]: ACVMField[],
[slot]: ACVMField[],
[tSize]: ACVMField[],
[scopeSome]: ACVMField[],
[scopeValue]: ACVMField[],
): Promise<(ACVMField | ACVMField[])[]> {
const scope = optionalAddressFromAcvmFields(scopeSome, scopeValue);
const values = await this.handlerAsUtility().loadCapsule(
AztecAddress.fromField(Fr.fromString(contractAddress)),
Fr.fromString(slot),
scope,
);

// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
Expand All @@ -580,12 +592,19 @@ export class Oracle {
}

// eslint-disable-next-line camelcase
async aztec_utl_deleteCapsule([contractAddress]: ACVMField[], [slot]: ACVMField[]): Promise<ACVMField[]> {
await this.handlerAsUtility().deleteCapsule(
aztec_utl_deleteCapsule(
[contractAddress]: ACVMField[],
[slot]: ACVMField[],
[scopeSome]: ACVMField[],
[scopeValue]: ACVMField[],
): Promise<ACVMField[]> {
const scope = optionalAddressFromAcvmFields(scopeSome, scopeValue);
this.handlerAsUtility().deleteCapsule(
AztecAddress.fromField(Fr.fromString(contractAddress)),
Fr.fromString(slot),
scope,
);
return [];
return Promise.resolve([]);
}

// eslint-disable-next-line camelcase
Expand All @@ -594,12 +613,16 @@ export class Oracle {
[srcSlot]: ACVMField[],
[dstSlot]: ACVMField[],
[numEntries]: ACVMField[],
[scopeSome]: ACVMField[],
[scopeValue]: ACVMField[],
): Promise<ACVMField[]> {
const scope = optionalAddressFromAcvmFields(scopeSome, scopeValue);
await this.handlerAsUtility().copyCapsule(
AztecAddress.fromField(Fr.fromString(contractAddress)),
Fr.fromString(srcSlot),
Fr.fromString(dstSlot),
Fr.fromString(numEntries).toNumber(),
scope,
);
return [];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/server';
import { deriveKeys } from '@aztec/stdlib/keys';
import { Note, NoteDao } from '@aztec/stdlib/note';
import { makeL2Tips } from '@aztec/stdlib/testing';
import { BlockHeader, GlobalVariables, TxHash } from '@aztec/stdlib/tx';
import { BlockHeader, Capsule, GlobalVariables, TxHash } from '@aztec/stdlib/tx';

import { mock } from 'jest-mock-extended';
import type { _MockProxy } from 'jest-mock-extended/lib/Mock.js';
Expand Down Expand Up @@ -245,6 +245,73 @@ describe('Utility Execution test suite', () => {
});
});

describe('capsules', () => {
it('forwards scope to the capsule store', async () => {
const scope = await AztecAddress.random();
const slot = Fr.random();
const srcSlot = Fr.random();
const dstSlot = Fr.random();
const capsule = [Fr.random()];

capsuleStore.loadCapsule.mockResolvedValueOnce(capsule);

utilityExecutionOracle.storeCapsule(contractAddress, slot, capsule, scope);
await utilityExecutionOracle.loadCapsule(contractAddress, slot, scope);
utilityExecutionOracle.deleteCapsule(contractAddress, slot, scope);
await utilityExecutionOracle.copyCapsule(contractAddress, srcSlot, dstSlot, 1, scope);

expect(capsuleStore.storeCapsule).toHaveBeenCalledWith(contractAddress, slot, capsule, 'test-job-id', scope);
expect(capsuleStore.loadCapsule).toHaveBeenCalledWith(contractAddress, slot, 'test-job-id', scope);
expect(capsuleStore.deleteCapsule).toHaveBeenCalledWith(contractAddress, slot, 'test-job-id', scope);
expect(capsuleStore.copyCapsule).toHaveBeenCalledWith(
contractAddress,
srcSlot,
dstSlot,
1,
'test-job-id',
scope,
);
});

it('loads transient capsules by scope', async () => {
const scope = await AztecAddress.random();
const slot = Fr.random();
const transientGlobal = [Fr.random()];
const transientScoped = [Fr.random()];
const persisted = [Fr.random()];

utilityExecutionOracle = new UtilityExecutionOracle({
contractAddress,
authWitnesses: [],
capsules: [
new Capsule(contractAddress, slot, transientGlobal),
new Capsule(contractAddress, slot, transientScoped, scope),
],
anchorBlockHeader,
contractStore,
noteStore,
keyStore,
addressStore,
aztecNode,
recipientTaggingStore,
senderAddressBookStore,
capsuleStore,
privateEventStore,
messageContextService,
jobId: 'test-job-id',
scopes: 'ALL_SCOPES',
});

capsuleStore.loadCapsule.mockResolvedValueOnce(persisted);

expect(await utilityExecutionOracle.loadCapsule(contractAddress, slot)).toEqual(transientGlobal);
expect(await utilityExecutionOracle.loadCapsule(contractAddress, slot, AztecAddress.ZERO)).toEqual(
transientGlobal,
);
expect(await utilityExecutionOracle.loadCapsule(contractAddress, slot, scope)).toEqual(transientScoped);
});
});

describe('utilityResolveMessageContexts', () => {
const requestSlot = Fr.random();
const responseSlot = Fr.random();
Expand Down
Loading
Loading