@aztec/pxe 0.0.1-commit.3f296a7d2 → 0.0.1-commit.3f5453c7b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bin/check_oracle_version.js +4 -4
- package/dest/block_synchronizer/block_synchronizer.d.ts +1 -1
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +6 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +3 -4
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +4 -3
- package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
- package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
- package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -4
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +3 -6
- package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
- package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +3 -4
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +3 -6
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +31 -20
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +28 -23
- package/dest/contract_function_simulator/oracle/oracle.d.ts +50 -20
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +157 -41
- package/dest/contract_function_simulator/oracle/private_execution.js +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +7 -8
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +16 -7
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +53 -38
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +200 -93
- package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
- package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
- package/dest/contract_function_simulator/pick_notes.js +9 -2
- package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
- package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
- package/dest/contract_function_simulator/proxied_contract_data_source.js +3 -0
- package/dest/contract_logging.d.ts +9 -4
- package/dest/contract_logging.d.ts.map +1 -1
- package/dest/contract_logging.js +21 -6
- package/dest/contract_sync/contract_sync_service.d.ts +3 -4
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +12 -22
- package/dest/contract_sync/helpers.d.ts +2 -3
- package/dest/contract_sync/helpers.d.ts.map +1 -1
- package/dest/contract_sync/helpers.js +7 -2
- package/dest/debug/pxe_debug_utils.d.ts +3 -3
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/index.d.ts +1 -2
- package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/index.js +0 -1
- package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
- package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/utils.js +2 -2
- package/dest/entrypoints/client/lazy/index.d.ts +1 -2
- package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/index.js +0 -1
- package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +2 -2
- package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
- package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
- package/dest/entrypoints/pxe_creation_options.js +3 -1
- package/dest/entrypoints/server/index.d.ts +2 -3
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +1 -2
- package/dest/entrypoints/server/utils.d.ts +2 -2
- package/dest/entrypoints/server/utils.d.ts.map +1 -1
- package/dest/entrypoints/server/utils.js +2 -2
- package/dest/events/event_service.d.ts +3 -2
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +16 -4
- package/dest/logs/log_service.d.ts +5 -8
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +24 -37
- package/dest/messages/message_context_service.d.ts +3 -3
- package/dest/messages/message_context_service.d.ts.map +1 -1
- package/dest/messages/message_context_service.js +3 -3
- package/dest/notes/note_service.d.ts +4 -5
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +14 -5
- package/dest/notes_filter.d.ts +2 -3
- package/dest/notes_filter.d.ts.map +1 -1
- package/dest/oracle_version.d.ts +4 -3
- package/dest/oracle_version.d.ts.map +1 -1
- package/dest/oracle_version.js +20 -10
- package/dest/pxe.d.ts +4 -5
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +6 -4
- package/dest/storage/capsule_store/capsule_service.d.ts +21 -0
- package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
- package/dest/storage/capsule_store/capsule_service.js +50 -0
- package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +33 -28
- package/dest/storage/capsule_store/index.d.ts +2 -1
- package/dest/storage/capsule_store/index.d.ts.map +1 -1
- package/dest/storage/capsule_store/index.js +1 -0
- package/dest/storage/metadata.d.ts +1 -1
- package/dest/storage/metadata.js +1 -1
- package/dest/storage/note_store/note_store.d.ts +1 -1
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +2 -2
- package/package.json +16 -16
- package/src/bin/check_oracle_version.ts +4 -4
- package/src/block_synchronizer/block_synchronizer.ts +6 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +6 -6
- package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -4
- package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
- package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -1
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -4
- package/src/contract_function_simulator/oracle/interfaces.ts +46 -18
- package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +20 -51
- package/src/contract_function_simulator/oracle/oracle.ts +222 -36
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -1
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +19 -10
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +337 -119
- package/src/contract_function_simulator/pick_notes.ts +9 -2
- package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
- package/src/contract_logging.ts +18 -5
- package/src/contract_sync/contract_sync_service.ts +32 -43
- package/src/contract_sync/helpers.ts +4 -4
- package/src/debug/pxe_debug_utils.ts +3 -3
- package/src/entrypoints/client/bundle/index.ts +0 -1
- package/src/entrypoints/client/bundle/utils.ts +2 -3
- package/src/entrypoints/client/lazy/index.ts +0 -1
- package/src/entrypoints/client/lazy/utils.ts +2 -3
- package/src/entrypoints/pxe_creation_options.ts +7 -0
- package/src/entrypoints/server/index.ts +1 -2
- package/src/entrypoints/server/utils.ts +2 -3
- package/src/events/event_service.ts +17 -4
- package/src/logs/log_service.ts +52 -78
- package/src/messages/message_context_service.ts +3 -4
- package/src/notes/note_service.ts +18 -8
- package/src/notes_filter.ts +1 -3
- package/src/oracle_version.ts +20 -10
- package/src/pxe.ts +11 -10
- package/src/storage/capsule_store/capsule_service.ts +90 -0
- package/src/storage/capsule_store/capsule_store.ts +34 -26
- package/src/storage/capsule_store/index.ts +1 -0
- package/src/storage/metadata.ts +1 -1
- package/src/storage/note_store/note_store.ts +2 -5
- package/dest/access_scopes.d.ts +0 -9
- package/dest/access_scopes.d.ts.map +0 -1
- package/dest/access_scopes.js +0 -6
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +0 -16
- package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +0 -1
- package/dest/contract_function_simulator/noir-structs/message_tx_context.js +0 -57
- package/src/access_scopes.ts +0 -9
- package/src/contract_function_simulator/noir-structs/message_tx_context.ts +0 -55
|
@@ -15,31 +15,30 @@ import { siloNullifier } from '@aztec/stdlib/hash';
|
|
|
15
15
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
16
16
|
import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
|
|
17
17
|
import { type PublicKeys, computeAddressSecret } from '@aztec/stdlib/keys';
|
|
18
|
-
import {
|
|
18
|
+
import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs';
|
|
19
19
|
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
20
20
|
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
21
21
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
22
22
|
import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
|
|
23
23
|
|
|
24
|
-
import
|
|
25
|
-
import { createContractLogger, logContractMessage } from '../../contract_logging.js';
|
|
24
|
+
import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
|
|
26
25
|
import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
|
|
27
26
|
import { EventService } from '../../events/event_service.js';
|
|
28
27
|
import { LogService } from '../../logs/log_service.js';
|
|
29
28
|
import { MessageContextService } from '../../messages/message_context_service.js';
|
|
30
29
|
import { NoteService } from '../../notes/note_service.js';
|
|
31
|
-
import {
|
|
30
|
+
import { ORACLE_VERSION_MAJOR } from '../../oracle_version.js';
|
|
32
31
|
import type { AddressStore } from '../../storage/address_store/address_store.js';
|
|
33
|
-
import type {
|
|
32
|
+
import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
|
|
34
33
|
import type { ContractStore } from '../../storage/contract_store/contract_store.js';
|
|
35
34
|
import type { NoteStore } from '../../storage/note_store/note_store.js';
|
|
36
35
|
import type { PrivateEventStore } from '../../storage/private_event_store/private_event_store.js';
|
|
37
36
|
import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
|
|
38
37
|
import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_address_book_store.js';
|
|
38
|
+
import { EphemeralArrayService } from '../ephemeral_array_service.js';
|
|
39
39
|
import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
|
|
40
40
|
import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
|
|
41
41
|
import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
|
|
42
|
-
import { MessageTxContext } from '../noir-structs/message_tx_context.js';
|
|
43
42
|
import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
|
|
44
43
|
import { UtilityContext } from '../noir-structs/utility_context.js';
|
|
45
44
|
import { pickNotes } from '../pick_notes.js';
|
|
@@ -60,13 +59,13 @@ export type UtilityExecutionOracleArgs = {
|
|
|
60
59
|
aztecNode: AztecNode;
|
|
61
60
|
recipientTaggingStore: RecipientTaggingStore;
|
|
62
61
|
senderAddressBookStore: SenderAddressBookStore;
|
|
63
|
-
|
|
62
|
+
capsuleService: CapsuleService;
|
|
64
63
|
privateEventStore: PrivateEventStore;
|
|
65
64
|
messageContextService: MessageContextService;
|
|
66
65
|
contractSyncService: ContractSyncService;
|
|
67
66
|
jobId: string;
|
|
68
67
|
log?: ReturnType<typeof createLogger>;
|
|
69
|
-
scopes:
|
|
68
|
+
scopes: AztecAddress[];
|
|
70
69
|
};
|
|
71
70
|
|
|
72
71
|
/**
|
|
@@ -77,7 +76,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
77
76
|
isUtility = true as const;
|
|
78
77
|
|
|
79
78
|
private contractLogger: Logger | undefined;
|
|
79
|
+
private aztecnrLogger: Logger | undefined;
|
|
80
80
|
private offchainEffects: OffchainEffect[] = [];
|
|
81
|
+
private readonly ephemeralArrayService = new EphemeralArrayService();
|
|
82
|
+
|
|
83
|
+
// We store oracle version to be able to show a nice error message when an oracle handler is missing.
|
|
84
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
81
85
|
|
|
82
86
|
protected readonly contractAddress: AztecAddress;
|
|
83
87
|
protected readonly authWitnesses: AuthWitness[];
|
|
@@ -90,13 +94,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
90
94
|
protected readonly aztecNode: AztecNode;
|
|
91
95
|
protected readonly recipientTaggingStore: RecipientTaggingStore;
|
|
92
96
|
protected readonly senderAddressBookStore: SenderAddressBookStore;
|
|
93
|
-
protected readonly
|
|
97
|
+
protected readonly capsuleService: CapsuleService;
|
|
94
98
|
protected readonly privateEventStore: PrivateEventStore;
|
|
95
99
|
protected readonly messageContextService: MessageContextService;
|
|
96
100
|
protected readonly contractSyncService: ContractSyncService;
|
|
97
101
|
protected readonly jobId: string;
|
|
98
102
|
protected logger: ReturnType<typeof createLogger>;
|
|
99
|
-
protected readonly scopes:
|
|
103
|
+
protected readonly scopes: AztecAddress[];
|
|
100
104
|
|
|
101
105
|
constructor(args: UtilityExecutionOracleArgs) {
|
|
102
106
|
this.contractAddress = args.contractAddress;
|
|
@@ -110,7 +114,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
110
114
|
this.aztecNode = args.aztecNode;
|
|
111
115
|
this.recipientTaggingStore = args.recipientTaggingStore;
|
|
112
116
|
this.senderAddressBookStore = args.senderAddressBookStore;
|
|
113
|
-
this.
|
|
117
|
+
this.capsuleService = args.capsuleService;
|
|
114
118
|
this.privateEventStore = args.privateEventStore;
|
|
115
119
|
this.messageContextService = args.messageContextService;
|
|
116
120
|
this.contractSyncService = args.contractSyncService;
|
|
@@ -119,7 +123,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
119
123
|
this.scopes = args.scopes;
|
|
120
124
|
}
|
|
121
125
|
|
|
122
|
-
public assertCompatibleOracleVersion(
|
|
126
|
+
public assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
123
127
|
// TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed.
|
|
124
128
|
// Protocol contracts/canonical contracts shipped with committed bytecode that cannot be changed. Assert they use
|
|
125
129
|
// the expected pinned version or the current one. We want to allow for both the pinned and the current versions
|
|
@@ -127,17 +131,36 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
127
131
|
// pinned contracts (like e.g. next)
|
|
128
132
|
const LEGACY_ORACLE_VERSION = 12;
|
|
129
133
|
if (isProtocolContract(this.contractAddress)) {
|
|
130
|
-
if (
|
|
134
|
+
if (major !== LEGACY_ORACLE_VERSION && major !== ORACLE_VERSION_MAJOR) {
|
|
135
|
+
const hint =
|
|
136
|
+
major > ORACLE_VERSION_MAJOR
|
|
137
|
+
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
138
|
+
: 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
131
139
|
throw new Error(
|
|
132
|
-
`
|
|
140
|
+
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${LEGACY_ORACLE_VERSION} or ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
133
141
|
);
|
|
134
142
|
}
|
|
143
|
+
this.contractOracleVersion = { major, minor };
|
|
135
144
|
return;
|
|
136
145
|
}
|
|
137
146
|
|
|
138
|
-
if (
|
|
139
|
-
|
|
147
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
148
|
+
const hint =
|
|
149
|
+
major > ORACLE_VERSION_MAJOR
|
|
150
|
+
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
151
|
+
: 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
154
|
+
);
|
|
140
155
|
}
|
|
156
|
+
|
|
157
|
+
// Major matches - store both major and minor for later diagnostics (e.g. when an oracle is not found)
|
|
158
|
+
this.contractOracleVersion = { major, minor };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
162
|
+
public nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
163
|
+
return this.contractOracleVersion;
|
|
141
164
|
}
|
|
142
165
|
|
|
143
166
|
public getRandomField(): Fr {
|
|
@@ -156,33 +179,32 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
156
179
|
* @throws If scopes are defined and the account is not in the scopes.
|
|
157
180
|
*/
|
|
158
181
|
public async getKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
|
|
164
|
-
hasAccess = true;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (!hasAccess) {
|
|
168
|
-
throw new Error(`Key validation request denied: no scoped account has a key with hash ${pkMHash.toString()}.`);
|
|
182
|
+
let hasAccess = false;
|
|
183
|
+
for (let i = 0; i < this.scopes.length && !hasAccess; i++) {
|
|
184
|
+
if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
|
|
185
|
+
hasAccess = true;
|
|
169
186
|
}
|
|
170
187
|
}
|
|
188
|
+
if (!hasAccess) {
|
|
189
|
+
throw new Error(`Key validation request denied: no scoped account has a key with hash ${pkMHash.toString()}.`);
|
|
190
|
+
}
|
|
171
191
|
return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
|
|
172
192
|
}
|
|
173
193
|
|
|
174
194
|
/**
|
|
175
195
|
* Fetches the index and sibling path of a leaf at a given block from the note hash tree.
|
|
176
|
-
* @param
|
|
177
|
-
* witness.
|
|
196
|
+
* @param blockHash - The hash of a block that contains the note hash tree root in which to find the
|
|
197
|
+
* membership witness.
|
|
178
198
|
* @param noteHash - The note hash to find in the note hash tree.
|
|
179
199
|
* @returns The membership witness containing the leaf index and sibling path
|
|
180
200
|
*/
|
|
181
201
|
public getNoteHashMembershipWitness(
|
|
182
|
-
|
|
202
|
+
blockHash: BlockHash,
|
|
183
203
|
noteHash: Fr,
|
|
184
204
|
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
185
|
-
return this
|
|
205
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
206
|
+
this.aztecNode.getNoteHashMembershipWitness(blockHash, noteHash),
|
|
207
|
+
);
|
|
186
208
|
}
|
|
187
209
|
|
|
188
210
|
/**
|
|
@@ -191,16 +213,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
191
213
|
* Block hashes are the leaves of the archive tree. Each time a new block is added to the chain,
|
|
192
214
|
* its block hash is appended as a new leaf to the archive tree.
|
|
193
215
|
*
|
|
194
|
-
* @param
|
|
216
|
+
* @param referenceBlockHash - The hash of a block that contains the archive tree root in which to find the membership
|
|
195
217
|
* witness.
|
|
196
218
|
* @param blockHash - The block hash to find in the archive tree.
|
|
197
219
|
* @returns The membership witness containing the leaf index and sibling path
|
|
198
220
|
*/
|
|
199
221
|
public getBlockHashMembershipWitness(
|
|
200
|
-
|
|
222
|
+
referenceBlockHash: BlockHash,
|
|
201
223
|
blockHash: BlockHash,
|
|
202
224
|
): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
|
|
203
|
-
|
|
225
|
+
// Note that we validate that the reference block hash is at or before the anchor block - we don't test the block
|
|
226
|
+
// hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
|
|
227
|
+
// membership witness as there is none.
|
|
228
|
+
return this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
|
|
229
|
+
this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
|
|
230
|
+
);
|
|
204
231
|
}
|
|
205
232
|
|
|
206
233
|
/**
|
|
@@ -213,7 +240,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
213
240
|
blockHash: BlockHash,
|
|
214
241
|
nullifier: Fr,
|
|
215
242
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
216
|
-
return this
|
|
243
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
244
|
+
this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier),
|
|
245
|
+
);
|
|
217
246
|
}
|
|
218
247
|
|
|
219
248
|
/**
|
|
@@ -229,7 +258,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
229
258
|
blockHash: BlockHash,
|
|
230
259
|
nullifier: Fr,
|
|
231
260
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
232
|
-
return this
|
|
261
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
262
|
+
this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier),
|
|
263
|
+
);
|
|
233
264
|
}
|
|
234
265
|
|
|
235
266
|
/**
|
|
@@ -239,7 +270,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
239
270
|
* @returns - The witness
|
|
240
271
|
*/
|
|
241
272
|
public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
242
|
-
return this
|
|
273
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
274
|
+
this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
|
|
275
|
+
);
|
|
243
276
|
}
|
|
244
277
|
|
|
245
278
|
/**
|
|
@@ -262,7 +295,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
262
295
|
* @param account - The account address.
|
|
263
296
|
* @returns The public keys and partial address, or `undefined` if the account is not registered.
|
|
264
297
|
*/
|
|
265
|
-
public async
|
|
298
|
+
public async getPublicKeysAndPartialAddress(
|
|
266
299
|
account: AztecAddress,
|
|
267
300
|
): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
|
|
268
301
|
const completeAddress = await this.addressStore.getCompleteAddress(account);
|
|
@@ -368,7 +401,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
368
401
|
* @param innerNullifier - The inner nullifier.
|
|
369
402
|
* @returns A boolean indicating whether the nullifier exists in the tree or not.
|
|
370
403
|
*/
|
|
371
|
-
public async
|
|
404
|
+
public async doesNullifierExist(innerNullifier: Fr) {
|
|
372
405
|
const [nullifier, anchorBlockHash] = await Promise.all([
|
|
373
406
|
siloNullifier(this.contractAddress, innerNullifier!),
|
|
374
407
|
this.anchorBlockHeader.hash(),
|
|
@@ -380,7 +413,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
380
413
|
}
|
|
381
414
|
|
|
382
415
|
/**
|
|
383
|
-
*
|
|
416
|
+
* Returns the membership witness of an un-nullified L1 to L2 message.
|
|
384
417
|
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
385
418
|
* @param messageHash - Hash of the message.
|
|
386
419
|
* @param secret - Secret used to compute a nullifier.
|
|
@@ -393,6 +426,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
393
426
|
contractAddress,
|
|
394
427
|
messageHash,
|
|
395
428
|
secret,
|
|
429
|
+
await this.anchorBlockHeader.hash(),
|
|
396
430
|
);
|
|
397
431
|
|
|
398
432
|
return new MessageLoadOracleInputs(messageIndex, siblingPath);
|
|
@@ -405,29 +439,31 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
405
439
|
* @param startStorageSlot - The starting storage slot.
|
|
406
440
|
* @param numberOfElements - Number of elements to read from the starting storage slot.
|
|
407
441
|
*/
|
|
408
|
-
public
|
|
442
|
+
public getFromPublicStorage(
|
|
409
443
|
blockHash: BlockHash,
|
|
410
444
|
contractAddress: AztecAddress,
|
|
411
445
|
startStorageSlot: Fr,
|
|
412
446
|
numberOfElements: number,
|
|
413
447
|
) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
448
|
+
return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
|
|
449
|
+
const slots = Array(numberOfElements)
|
|
450
|
+
.fill(0)
|
|
451
|
+
.map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
|
|
417
452
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
453
|
+
const values = await Promise.all(
|
|
454
|
+
slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
|
|
455
|
+
);
|
|
421
456
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
457
|
+
this.logger.debug(
|
|
458
|
+
`Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
|
|
459
|
+
);
|
|
425
460
|
|
|
426
|
-
|
|
461
|
+
return values;
|
|
462
|
+
});
|
|
427
463
|
}
|
|
428
464
|
|
|
429
465
|
/**
|
|
430
|
-
* Returns a per-contract logger whose output is prefixed with `
|
|
466
|
+
* Returns a per-contract logger whose output is prefixed with `contract:<name>(<addrAbbrev>)`.
|
|
431
467
|
*/
|
|
432
468
|
async #getContractLogger(): Promise<Logger> {
|
|
433
469
|
if (!this.contractLogger) {
|
|
@@ -436,45 +472,78 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
436
472
|
this.contractLogger = await createContractLogger(
|
|
437
473
|
this.contractAddress,
|
|
438
474
|
addr => this.contractStore.getDebugContractName(addr),
|
|
475
|
+
'user',
|
|
439
476
|
{ instanceId: this.jobId },
|
|
440
477
|
);
|
|
441
478
|
}
|
|
442
479
|
return this.contractLogger;
|
|
443
480
|
}
|
|
444
481
|
|
|
482
|
+
/**
|
|
483
|
+
* Returns a per-contract logger whose output is prefixed with `aztecnr:<name>(<addrAbbrev>)`.
|
|
484
|
+
*/
|
|
485
|
+
async #getAztecnrLogger(): Promise<Logger> {
|
|
486
|
+
if (!this.aztecnrLogger) {
|
|
487
|
+
// Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
|
|
488
|
+
// to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
|
|
489
|
+
this.aztecnrLogger = await createContractLogger(
|
|
490
|
+
this.contractAddress,
|
|
491
|
+
addr => this.contractStore.getDebugContractName(addr),
|
|
492
|
+
'aztecnr',
|
|
493
|
+
{ instanceId: this.jobId },
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
return this.aztecnrLogger;
|
|
497
|
+
}
|
|
498
|
+
|
|
445
499
|
public async log(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
446
500
|
if (!LogLevels[level]) {
|
|
447
501
|
throw new Error(`Invalid log level: ${level}`);
|
|
448
502
|
}
|
|
449
|
-
|
|
450
|
-
|
|
503
|
+
|
|
504
|
+
const { kind, message: strippedMessage } = stripAztecnrLogPrefix(message);
|
|
505
|
+
|
|
506
|
+
const logger = kind == 'aztecnr' ? await this.#getAztecnrLogger() : await this.#getContractLogger();
|
|
507
|
+
logContractMessage(logger, LogLevels[level], strippedMessage, fields);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
511
|
+
public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
|
|
512
|
+
const logService = this.#createLogService();
|
|
513
|
+
const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
|
|
514
|
+
await this.capsuleService.appendToCapsuleArray(
|
|
515
|
+
this.contractAddress,
|
|
516
|
+
pendingTaggedLogArrayBaseSlot,
|
|
517
|
+
logs.map(log => log.toFields()),
|
|
518
|
+
this.jobId,
|
|
519
|
+
scope,
|
|
520
|
+
);
|
|
451
521
|
}
|
|
452
522
|
|
|
453
|
-
|
|
454
|
-
|
|
523
|
+
/** Fetches pending tagged logs into a freshly allocated ephemeral array and returns its base slot. */
|
|
524
|
+
public async getPendingTaggedLogsV2(scope: AztecAddress): Promise<Fr> {
|
|
525
|
+
const logService = this.#createLogService();
|
|
526
|
+
const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
|
|
527
|
+
return this.ephemeralArrayService.newArray(logs.map(log => log.toFields()));
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
#createLogService(): LogService {
|
|
531
|
+
return new LogService(
|
|
455
532
|
this.aztecNode,
|
|
456
533
|
this.anchorBlockHeader,
|
|
457
534
|
this.keyStore,
|
|
458
|
-
this.capsuleStore,
|
|
459
535
|
this.recipientTaggingStore,
|
|
460
536
|
this.senderAddressBookStore,
|
|
461
537
|
this.addressStore,
|
|
462
538
|
this.jobId,
|
|
463
539
|
this.logger.getBindings(),
|
|
464
540
|
);
|
|
465
|
-
|
|
466
|
-
await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
|
|
467
541
|
}
|
|
468
542
|
|
|
469
543
|
/**
|
|
470
|
-
*
|
|
471
|
-
* `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them
|
|
472
|
-
* queryable via `get_notes` and `getPrivateEvents`.
|
|
544
|
+
* Legacy: validates note/event requests stored in capsule arrays.
|
|
473
545
|
*
|
|
474
|
-
*
|
|
475
|
-
* @param contractAddress - The address of the contract that the logs are tagged for.
|
|
476
|
-
* @param noteValidationRequestsArrayBaseSlot - The base slot of capsule array containing note validation requests.
|
|
477
|
-
* @param eventValidationRequestsArrayBaseSlot - The base slot of capsule array containing event validation requests.
|
|
546
|
+
* Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
478
547
|
*/
|
|
479
548
|
public async validateAndStoreEnqueuedNotesAndEvents(
|
|
480
549
|
contractAddress: AztecAddress,
|
|
@@ -482,22 +551,78 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
482
551
|
eventValidationRequestsArrayBaseSlot: Fr,
|
|
483
552
|
maxNotePackedLen: number,
|
|
484
553
|
maxEventSerializedLen: number,
|
|
554
|
+
scope: AztecAddress,
|
|
485
555
|
) {
|
|
486
556
|
// TODO(#10727): allow other contracts to store notes
|
|
487
557
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
488
558
|
throw new Error(`Got a note validation request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
489
559
|
}
|
|
490
560
|
|
|
491
|
-
// We read all note and event validation requests and process them all concurrently. This makes the process much
|
|
492
|
-
// faster as we don't need to wait for the network round-trip.
|
|
493
561
|
const noteValidationRequests = (
|
|
494
|
-
await this.
|
|
562
|
+
await this.capsuleService.readCapsuleArray(
|
|
563
|
+
contractAddress,
|
|
564
|
+
noteValidationRequestsArrayBaseSlot,
|
|
565
|
+
this.jobId,
|
|
566
|
+
scope,
|
|
567
|
+
)
|
|
495
568
|
).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
|
|
496
569
|
|
|
497
570
|
const eventValidationRequests = (
|
|
498
|
-
await this.
|
|
571
|
+
await this.capsuleService.readCapsuleArray(
|
|
572
|
+
contractAddress,
|
|
573
|
+
eventValidationRequestsArrayBaseSlot,
|
|
574
|
+
this.jobId,
|
|
575
|
+
scope,
|
|
576
|
+
)
|
|
499
577
|
).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
500
578
|
|
|
579
|
+
await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
|
|
580
|
+
|
|
581
|
+
await this.capsuleService.setCapsuleArray(
|
|
582
|
+
contractAddress,
|
|
583
|
+
noteValidationRequestsArrayBaseSlot,
|
|
584
|
+
[],
|
|
585
|
+
this.jobId,
|
|
586
|
+
scope,
|
|
587
|
+
);
|
|
588
|
+
await this.capsuleService.setCapsuleArray(
|
|
589
|
+
contractAddress,
|
|
590
|
+
eventValidationRequestsArrayBaseSlot,
|
|
591
|
+
[],
|
|
592
|
+
this.jobId,
|
|
593
|
+
scope,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
public async validateAndStoreEnqueuedNotesAndEventsV2(
|
|
598
|
+
noteValidationRequestsArrayBaseSlot: Fr,
|
|
599
|
+
eventValidationRequestsArrayBaseSlot: Fr,
|
|
600
|
+
maxNotePackedLen: number,
|
|
601
|
+
maxEventSerializedLen: number,
|
|
602
|
+
scope: AztecAddress,
|
|
603
|
+
) {
|
|
604
|
+
const noteValidationRequests = this.ephemeralArrayService
|
|
605
|
+
.readArrayAt(noteValidationRequestsArrayBaseSlot)
|
|
606
|
+
.map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
|
|
607
|
+
|
|
608
|
+
const eventValidationRequests = this.ephemeralArrayService
|
|
609
|
+
.readArrayAt(eventValidationRequestsArrayBaseSlot)
|
|
610
|
+
.map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
611
|
+
|
|
612
|
+
await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Dispatches note and event validation requests to the service layer.
|
|
617
|
+
*
|
|
618
|
+
* This function is an auxiliary to support legacy (capsule backed) and new (ephemeral array backed) versions of the
|
|
619
|
+
* `validateAndStoreEnqueuedNotesAndEvents` oracle.
|
|
620
|
+
*/
|
|
621
|
+
async #processValidationRequests(
|
|
622
|
+
noteValidationRequests: NoteValidationRequest[],
|
|
623
|
+
eventValidationRequests: EventValidationRequest[],
|
|
624
|
+
scope: AztecAddress,
|
|
625
|
+
) {
|
|
501
626
|
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
|
|
502
627
|
const noteStorePromises = noteValidationRequests.map(request =>
|
|
503
628
|
noteService.validateAndStoreNote(
|
|
@@ -510,7 +635,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
510
635
|
request.noteHash,
|
|
511
636
|
request.nullifier,
|
|
512
637
|
request.txHash,
|
|
513
|
-
|
|
638
|
+
scope,
|
|
514
639
|
),
|
|
515
640
|
);
|
|
516
641
|
|
|
@@ -523,21 +648,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
523
648
|
request.serializedEvent,
|
|
524
649
|
request.eventCommitment,
|
|
525
650
|
request.txHash,
|
|
526
|
-
|
|
651
|
+
scope,
|
|
527
652
|
),
|
|
528
653
|
);
|
|
529
654
|
|
|
530
655
|
await Promise.all([...noteStorePromises, ...eventStorePromises]);
|
|
531
|
-
|
|
532
|
-
// Requests are cleared once we're done.
|
|
533
|
-
await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
|
|
534
|
-
await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
|
|
535
656
|
}
|
|
536
657
|
|
|
537
|
-
public async
|
|
658
|
+
public async getLogsByTag(
|
|
538
659
|
contractAddress: AztecAddress,
|
|
539
660
|
logRetrievalRequestsArrayBaseSlot: Fr,
|
|
540
661
|
logRetrievalResponsesArrayBaseSlot: Fr,
|
|
662
|
+
scope: AztecAddress,
|
|
541
663
|
) {
|
|
542
664
|
// TODO(#10727): allow other contracts to process partial notes
|
|
543
665
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
@@ -547,48 +669,63 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
547
669
|
// We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
|
|
548
670
|
// don't need to wait for the network round-trip.
|
|
549
671
|
const logRetrievalRequests = (
|
|
550
|
-
await this.
|
|
672
|
+
await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
|
|
551
673
|
).map(LogRetrievalRequest.fromFields);
|
|
552
674
|
|
|
553
|
-
const logService =
|
|
554
|
-
|
|
555
|
-
this.anchorBlockHeader,
|
|
556
|
-
this.keyStore,
|
|
557
|
-
this.capsuleStore,
|
|
558
|
-
this.recipientTaggingStore,
|
|
559
|
-
this.senderAddressBookStore,
|
|
560
|
-
this.addressStore,
|
|
561
|
-
this.jobId,
|
|
562
|
-
this.logger.getBindings(),
|
|
563
|
-
);
|
|
564
|
-
|
|
565
|
-
const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
|
|
675
|
+
const logService = this.#createLogService();
|
|
676
|
+
const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
|
|
566
677
|
|
|
567
678
|
// Requests are cleared once we're done.
|
|
568
|
-
await this.
|
|
679
|
+
await this.capsuleService.setCapsuleArray(
|
|
680
|
+
contractAddress,
|
|
681
|
+
logRetrievalRequestsArrayBaseSlot,
|
|
682
|
+
[],
|
|
683
|
+
this.jobId,
|
|
684
|
+
scope,
|
|
685
|
+
);
|
|
569
686
|
|
|
570
687
|
// The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
|
|
571
|
-
await this.
|
|
688
|
+
await this.capsuleService.setCapsuleArray(
|
|
572
689
|
contractAddress,
|
|
573
690
|
logRetrievalResponsesArrayBaseSlot,
|
|
574
691
|
maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
|
|
575
692
|
this.jobId,
|
|
693
|
+
scope,
|
|
576
694
|
);
|
|
577
695
|
}
|
|
578
696
|
|
|
579
|
-
public async
|
|
697
|
+
public async getLogsByTagV2(requestArrayBaseSlot: Fr): Promise<Fr> {
|
|
698
|
+
const logRetrievalRequests = this.ephemeralArrayService
|
|
699
|
+
.readArrayAt(requestArrayBaseSlot)
|
|
700
|
+
.map(LogRetrievalRequest.fromFields);
|
|
701
|
+
const logService = this.#createLogService();
|
|
702
|
+
|
|
703
|
+
const maybeLogRetrievalResponses = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
|
|
704
|
+
|
|
705
|
+
return this.ephemeralArrayService.newArray(maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption));
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
709
|
+
public async getMessageContextsByTxHash(
|
|
580
710
|
contractAddress: AztecAddress,
|
|
581
711
|
messageContextRequestsArrayBaseSlot: Fr,
|
|
582
712
|
messageContextResponsesArrayBaseSlot: Fr,
|
|
713
|
+
scope: AztecAddress,
|
|
583
714
|
) {
|
|
584
715
|
try {
|
|
585
716
|
if (!this.contractAddress.equals(contractAddress)) {
|
|
586
717
|
throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
587
718
|
}
|
|
588
|
-
|
|
719
|
+
|
|
720
|
+
// TODO(@mverzilli): this is a prime example of where using an ephemeral array would make much more sense, we don't
|
|
721
|
+
// need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
|
|
722
|
+
// At the same time, we don't want to allow any global scope access other than where backwards compatibility
|
|
723
|
+
// forces us to. Hence we need the scope here to be artificial.
|
|
724
|
+
const requestCapsules = await this.capsuleService.readCapsuleArray(
|
|
589
725
|
contractAddress,
|
|
590
726
|
messageContextRequestsArrayBaseSlot,
|
|
591
727
|
this.jobId,
|
|
728
|
+
scope,
|
|
592
729
|
);
|
|
593
730
|
|
|
594
731
|
const txHashes = requestCapsules.map((fields, i) => {
|
|
@@ -600,66 +737,94 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
600
737
|
return fields[0];
|
|
601
738
|
});
|
|
602
739
|
|
|
603
|
-
const maybeMessageContexts = await this.messageContextService.
|
|
740
|
+
const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
|
|
604
741
|
txHashes,
|
|
605
742
|
this.anchorBlockHeader.getBlockNumber(),
|
|
606
743
|
);
|
|
607
744
|
|
|
608
745
|
// Leave response in response capsule array.
|
|
609
|
-
await this.
|
|
746
|
+
await this.capsuleService.setCapsuleArray(
|
|
610
747
|
contractAddress,
|
|
611
748
|
messageContextResponsesArrayBaseSlot,
|
|
612
|
-
maybeMessageContexts.map(
|
|
749
|
+
maybeMessageContexts.map(MessageContext.toSerializedOption),
|
|
613
750
|
this.jobId,
|
|
751
|
+
scope,
|
|
614
752
|
);
|
|
615
753
|
} finally {
|
|
616
|
-
await this.
|
|
754
|
+
await this.capsuleService.setCapsuleArray(
|
|
755
|
+
contractAddress,
|
|
756
|
+
messageContextRequestsArrayBaseSlot,
|
|
757
|
+
[],
|
|
758
|
+
this.jobId,
|
|
759
|
+
scope,
|
|
760
|
+
);
|
|
617
761
|
}
|
|
618
762
|
}
|
|
619
763
|
|
|
620
|
-
|
|
764
|
+
/** Reads tx hash requests from an ephemeral array, resolves their contexts, and returns the response slot. */
|
|
765
|
+
public async getMessageContextsByTxHashV2(requestArrayBaseSlot: Fr): Promise<Fr> {
|
|
766
|
+
const requestFields = this.ephemeralArrayService.readArrayAt(requestArrayBaseSlot);
|
|
767
|
+
|
|
768
|
+
const txHashes = requestFields.map((fields, i) => {
|
|
769
|
+
if (fields.length !== 1) {
|
|
770
|
+
throw new Error(
|
|
771
|
+
`Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
return fields[0];
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
|
|
778
|
+
txHashes,
|
|
779
|
+
this.anchorBlockHeader.getBlockNumber(),
|
|
780
|
+
);
|
|
781
|
+
|
|
782
|
+
return this.ephemeralArrayService.newArray(maybeMessageContexts.map(MessageContext.toSerializedOption));
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
|
|
621
786
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
622
787
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
623
788
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
624
789
|
}
|
|
625
|
-
this.
|
|
626
|
-
return Promise.resolve();
|
|
790
|
+
this.capsuleService.setCapsule(contractAddress, slot, capsule, this.jobId, scope);
|
|
627
791
|
}
|
|
628
792
|
|
|
629
|
-
public
|
|
793
|
+
public getCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): Promise<Fr[] | null> {
|
|
630
794
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
631
795
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
632
796
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
633
797
|
}
|
|
634
|
-
return (
|
|
635
|
-
// TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
|
|
636
|
-
this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
|
|
637
|
-
(await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
|
|
638
|
-
);
|
|
798
|
+
return this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
|
|
639
799
|
}
|
|
640
800
|
|
|
641
|
-
public deleteCapsule(contractAddress: AztecAddress, slot: Fr):
|
|
801
|
+
public deleteCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): void {
|
|
642
802
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
643
803
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
644
804
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
645
805
|
}
|
|
646
|
-
this.
|
|
647
|
-
return Promise.resolve();
|
|
806
|
+
this.capsuleService.deleteCapsule(contractAddress, slot, this.jobId, scope);
|
|
648
807
|
}
|
|
649
808
|
|
|
650
|
-
public copyCapsule(
|
|
809
|
+
public copyCapsule(
|
|
810
|
+
contractAddress: AztecAddress,
|
|
811
|
+
srcSlot: Fr,
|
|
812
|
+
dstSlot: Fr,
|
|
813
|
+
numEntries: number,
|
|
814
|
+
scope: AztecAddress,
|
|
815
|
+
): Promise<void> {
|
|
651
816
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
652
817
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
653
818
|
throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
|
|
654
819
|
}
|
|
655
|
-
return this.
|
|
820
|
+
return this.capsuleService.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, this.jobId, scope);
|
|
656
821
|
}
|
|
657
822
|
|
|
658
823
|
/**
|
|
659
824
|
* Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
|
|
660
825
|
* stored notes or events are discovered.
|
|
661
826
|
*/
|
|
662
|
-
public
|
|
827
|
+
public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
|
|
663
828
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
664
829
|
throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
|
|
665
830
|
}
|
|
@@ -667,25 +832,58 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
667
832
|
}
|
|
668
833
|
|
|
669
834
|
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
|
|
670
|
-
public
|
|
835
|
+
public decryptAes128(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
|
|
671
836
|
const aes128 = new Aes128();
|
|
672
837
|
return aes128.decryptBufferCBC(ciphertext, iv, symKey);
|
|
673
838
|
}
|
|
674
839
|
|
|
675
840
|
/**
|
|
676
|
-
* Retrieves the shared secret for a given address and ephemeral public key.
|
|
841
|
+
* Retrieves the app-siloed shared secret for a given address and ephemeral public key.
|
|
677
842
|
* @param address - The address to get the secret for.
|
|
678
843
|
* @param ephPk - The ephemeral public key to get the secret for.
|
|
679
|
-
* @
|
|
844
|
+
* @param contractAddress - The contract address for app-siloing (validated against execution context).
|
|
845
|
+
* @returns The app-siloed shared secret as a Field.
|
|
680
846
|
*/
|
|
681
|
-
public async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<
|
|
682
|
-
|
|
847
|
+
public async getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr> {
|
|
848
|
+
if (!contractAddress.equals(this.contractAddress)) {
|
|
849
|
+
throw new Error(
|
|
850
|
+
`getSharedSecret called with contract address ${contractAddress}, expected ${this.contractAddress}`,
|
|
851
|
+
);
|
|
852
|
+
}
|
|
683
853
|
const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
|
|
684
854
|
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
685
855
|
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
686
856
|
);
|
|
687
857
|
const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
|
|
688
|
-
return
|
|
858
|
+
return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
public pushEphemeral(slot: Fr, elements: Fr[]): number {
|
|
862
|
+
return this.ephemeralArrayService.push(slot, elements);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
public popEphemeral(slot: Fr): Fr[] {
|
|
866
|
+
return this.ephemeralArrayService.pop(slot);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
public getEphemeral(slot: Fr, index: number): Fr[] {
|
|
870
|
+
return this.ephemeralArrayService.get(slot, index);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
public setEphemeral(slot: Fr, index: number, elements: Fr[]): void {
|
|
874
|
+
this.ephemeralArrayService.set(slot, index, elements);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
public getEphemeralLen(slot: Fr): number {
|
|
878
|
+
return this.ephemeralArrayService.len(slot);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
public removeEphemeral(slot: Fr, index: number): void {
|
|
882
|
+
this.ephemeralArrayService.remove(slot, index);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
public clearEphemeral(slot: Fr): void {
|
|
886
|
+
this.ephemeralArrayService.clear(slot);
|
|
689
887
|
}
|
|
690
888
|
|
|
691
889
|
public emitOffchainEffect(data: Fr[]): Promise<void> {
|
|
@@ -697,4 +895,24 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
697
895
|
public getOffchainEffects(): OffchainEffect[] {
|
|
698
896
|
return this.offchainEffects;
|
|
699
897
|
}
|
|
898
|
+
|
|
899
|
+
/** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
|
|
900
|
+
async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
|
|
901
|
+
const [response] = await Promise.all([
|
|
902
|
+
query(),
|
|
903
|
+
(async () => {
|
|
904
|
+
const header = await this.aztecNode.getBlockHeader(blockHash);
|
|
905
|
+
if (!header) {
|
|
906
|
+
throw new Error(`Could not find block header for block hash ${blockHash}`);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
|
|
910
|
+
throw new Error(
|
|
911
|
+
`Made a node query with a reference block hash ${blockHash} with block number ${header.getBlockNumber()}, which is ahead of the anchor block number ${this.anchorBlockHeader.getBlockNumber()} (from anchor block hash ${await this.anchorBlockHeader.hash()}).`,
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
})(),
|
|
915
|
+
]);
|
|
916
|
+
return response;
|
|
917
|
+
}
|
|
700
918
|
}
|