@aztec/pxe 0.0.1-commit.e588bc7e5 → 0.0.1-commit.e5a3663dd
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_stream_source.d.ts +10 -0
- package/dest/block_synchronizer/block_stream_source.d.ts.map +1 -0
- package/dest/block_synchronizer/block_stream_source.js +37 -0
- package/dest/block_synchronizer/block_synchronizer.d.ts +6 -2
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +24 -10
- package/dest/config/index.d.ts +1 -1
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +7 -14
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +8 -5
- 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 +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
- 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 +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +15 -2
- 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 +10 -1
- package/dest/contract_function_simulator/oracle/oracle.d.ts +14 -2
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +105 -3
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -11
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +21 -17
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +34 -13
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +149 -28
- 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 +20 -3
- 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_sync/contract_sync_service.d.ts +1 -1
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +35 -23
- 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/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 -2
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +1 -1
- 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 +1 -1
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +10 -1
- package/dest/events/private_event_filter_validator.d.ts +3 -2
- package/dest/events/private_event_filter_validator.d.ts.map +1 -1
- package/dest/events/private_event_filter_validator.js +15 -0
- package/dest/logs/log_service.d.ts +6 -6
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +8 -20
- 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/private_kernel/private_kernel_execution_prover.d.ts +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +4 -7
- package/dest/private_kernel/private_kernel_oracle.d.ts +5 -5
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +12 -15
- package/dest/pxe.d.ts +16 -4
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +49 -20
- package/dest/storage/anchor_block_store/anchor_block_store.js +1 -1
- package/dest/storage/capsule_store/capsule_store.d.ts +1 -1
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +8 -5
- package/dest/storage/contract_store/contract_store.d.ts +1 -1
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +4 -2
- package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +3 -0
- package/dest/storage/private_event_store/stored_private_event.js +1 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +2 -2
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +2 -16
- package/package.json +16 -16
- package/src/bin/check_oracle_version.ts +4 -4
- package/src/block_synchronizer/block_stream_source.ts +52 -0
- package/src/block_synchronizer/block_synchronizer.ts +27 -11
- package/src/config/index.ts +2 -8
- package/src/contract_function_simulator/contract_function_simulator.ts +8 -4
- package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
- 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 -1
- package/src/contract_function_simulator/oracle/interfaces.ts +30 -1
- package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +7 -1
- package/src/contract_function_simulator/oracle/oracle.ts +157 -3
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +34 -20
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +241 -55
- package/src/contract_function_simulator/pick_notes.ts +22 -3
- package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
- package/src/contract_sync/contract_sync_service.ts +57 -51
- package/src/entrypoints/client/bundle/utils.ts +2 -3
- 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 -1
- package/src/entrypoints/server/utils.ts +2 -3
- package/src/events/event_service.ts +13 -1
- package/src/events/private_event_filter_validator.ts +21 -1
- package/src/logs/log_service.ts +14 -50
- package/src/oracle_version.ts +20 -10
- package/src/private_kernel/private_kernel_execution_prover.ts +4 -9
- package/src/private_kernel/private_kernel_oracle.ts +14 -14
- package/src/pxe.ts +86 -24
- package/src/storage/anchor_block_store/anchor_block_store.ts +1 -1
- package/src/storage/capsule_store/capsule_store.ts +15 -5
- package/src/storage/contract_store/contract_store.ts +8 -6
- package/src/storage/private_event_store/private_event_store.ts +4 -0
- package/src/storage/private_event_store/stored_private_event.ts +1 -1
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +5 -15
|
@@ -7,9 +7,18 @@ import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
7
7
|
import type { MembershipWitness } from '@aztec/foundation/trees';
|
|
8
8
|
import type { KeyStore } from '@aztec/key-store';
|
|
9
9
|
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
10
|
+
import {
|
|
11
|
+
type CircuitSimulator,
|
|
12
|
+
ExecutionError,
|
|
13
|
+
extractCallStack,
|
|
14
|
+
resolveAssertionMessageFromError,
|
|
15
|
+
toACVMWitness,
|
|
16
|
+
witnessMapToFields,
|
|
17
|
+
} from '@aztec/simulator/client';
|
|
18
|
+
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
10
19
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
11
20
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
|
-
import { BlockHash } from '@aztec/stdlib/block';
|
|
21
|
+
import { BlockHash, type L2TipsProvider } from '@aztec/stdlib/block';
|
|
13
22
|
import type { CompleteAddress, ContractInstance, PartialAddress } from '@aztec/stdlib/contract';
|
|
14
23
|
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
15
24
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
@@ -27,7 +36,7 @@ import { EventService } from '../../events/event_service.js';
|
|
|
27
36
|
import { LogService } from '../../logs/log_service.js';
|
|
28
37
|
import { MessageContextService } from '../../messages/message_context_service.js';
|
|
29
38
|
import { NoteService } from '../../notes/note_service.js';
|
|
30
|
-
import {
|
|
39
|
+
import { ORACLE_VERSION_MAJOR } from '../../oracle_version.js';
|
|
31
40
|
import type { AddressStore } from '../../storage/address_store/address_store.js';
|
|
32
41
|
import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
|
|
33
42
|
import type { ContractStore } from '../../storage/contract_store/contract_store.js';
|
|
@@ -35,6 +44,7 @@ import type { NoteStore } from '../../storage/note_store/note_store.js';
|
|
|
35
44
|
import type { PrivateEventStore } from '../../storage/private_event_store/private_event_store.js';
|
|
36
45
|
import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
|
|
37
46
|
import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_address_book_store.js';
|
|
47
|
+
import { EphemeralArrayService } from '../ephemeral_array_service.js';
|
|
38
48
|
import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
|
|
39
49
|
import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
|
|
40
50
|
import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
|
|
@@ -43,6 +53,7 @@ import { UtilityContext } from '../noir-structs/utility_context.js';
|
|
|
43
53
|
import { pickNotes } from '../pick_notes.js';
|
|
44
54
|
import type { IMiscOracle, IUtilityExecutionOracle, NoteData } from './interfaces.js';
|
|
45
55
|
import { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
|
|
56
|
+
import { Oracle } from './oracle.js';
|
|
46
57
|
|
|
47
58
|
/** Args for UtilityExecutionOracle constructor. */
|
|
48
59
|
export type UtilityExecutionOracleArgs = {
|
|
@@ -62,9 +73,11 @@ export type UtilityExecutionOracleArgs = {
|
|
|
62
73
|
privateEventStore: PrivateEventStore;
|
|
63
74
|
messageContextService: MessageContextService;
|
|
64
75
|
contractSyncService: ContractSyncService;
|
|
76
|
+
l2TipsStore: L2TipsProvider;
|
|
65
77
|
jobId: string;
|
|
66
78
|
log?: ReturnType<typeof createLogger>;
|
|
67
79
|
scopes: AztecAddress[];
|
|
80
|
+
simulator: CircuitSimulator;
|
|
68
81
|
};
|
|
69
82
|
|
|
70
83
|
/**
|
|
@@ -77,6 +90,10 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
77
90
|
private contractLogger: Logger | undefined;
|
|
78
91
|
private aztecnrLogger: Logger | undefined;
|
|
79
92
|
private offchainEffects: OffchainEffect[] = [];
|
|
93
|
+
private readonly ephemeralArrayService = new EphemeralArrayService();
|
|
94
|
+
|
|
95
|
+
// We store oracle version to be able to show a nice error message when an oracle handler is missing.
|
|
96
|
+
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
80
97
|
|
|
81
98
|
protected readonly contractAddress: AztecAddress;
|
|
82
99
|
protected readonly authWitnesses: AuthWitness[];
|
|
@@ -93,9 +110,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
93
110
|
protected readonly privateEventStore: PrivateEventStore;
|
|
94
111
|
protected readonly messageContextService: MessageContextService;
|
|
95
112
|
protected readonly contractSyncService: ContractSyncService;
|
|
113
|
+
protected readonly l2TipsStore: L2TipsProvider;
|
|
96
114
|
protected readonly jobId: string;
|
|
97
115
|
protected logger: ReturnType<typeof createLogger>;
|
|
98
116
|
protected readonly scopes: AztecAddress[];
|
|
117
|
+
protected readonly simulator: CircuitSimulator;
|
|
99
118
|
|
|
100
119
|
constructor(args: UtilityExecutionOracleArgs) {
|
|
101
120
|
this.contractAddress = args.contractAddress;
|
|
@@ -113,12 +132,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
113
132
|
this.privateEventStore = args.privateEventStore;
|
|
114
133
|
this.messageContextService = args.messageContextService;
|
|
115
134
|
this.contractSyncService = args.contractSyncService;
|
|
135
|
+
this.l2TipsStore = args.l2TipsStore;
|
|
116
136
|
this.jobId = args.jobId;
|
|
117
137
|
this.logger = args.log ?? createLogger('simulator:client_view_context');
|
|
118
138
|
this.scopes = args.scopes;
|
|
139
|
+
this.simulator = args.simulator;
|
|
119
140
|
}
|
|
120
141
|
|
|
121
|
-
public assertCompatibleOracleVersion(
|
|
142
|
+
public assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
122
143
|
// TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed.
|
|
123
144
|
// Protocol contracts/canonical contracts shipped with committed bytecode that cannot be changed. Assert they use
|
|
124
145
|
// the expected pinned version or the current one. We want to allow for both the pinned and the current versions
|
|
@@ -126,27 +147,36 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
126
147
|
// pinned contracts (like e.g. next)
|
|
127
148
|
const LEGACY_ORACLE_VERSION = 12;
|
|
128
149
|
if (isProtocolContract(this.contractAddress)) {
|
|
129
|
-
if (
|
|
150
|
+
if (major !== LEGACY_ORACLE_VERSION && major !== ORACLE_VERSION_MAJOR) {
|
|
130
151
|
const hint =
|
|
131
|
-
|
|
152
|
+
major > ORACLE_VERSION_MAJOR
|
|
132
153
|
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
133
154
|
: '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.';
|
|
134
155
|
throw new Error(
|
|
135
|
-
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${LEGACY_ORACLE_VERSION} or ${
|
|
156
|
+
`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})`,
|
|
136
157
|
);
|
|
137
158
|
}
|
|
159
|
+
this.contractOracleVersion = { major, minor };
|
|
138
160
|
return;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
if (
|
|
163
|
+
if (major !== ORACLE_VERSION_MAJOR) {
|
|
142
164
|
const hint =
|
|
143
|
-
|
|
165
|
+
major > ORACLE_VERSION_MAJOR
|
|
144
166
|
? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
|
|
145
167
|
: '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.';
|
|
146
168
|
throw new Error(
|
|
147
|
-
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${
|
|
169
|
+
`Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
|
|
148
170
|
);
|
|
149
171
|
}
|
|
172
|
+
|
|
173
|
+
// Major matches - store both major and minor for later diagnostics (e.g. when an oracle is not found)
|
|
174
|
+
this.contractOracleVersion = { major, minor };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
|
|
178
|
+
public nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
|
|
179
|
+
return this.contractOracleVersion;
|
|
150
180
|
}
|
|
151
181
|
|
|
152
182
|
public getRandomField(): Fr {
|
|
@@ -316,10 +346,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
316
346
|
}
|
|
317
347
|
|
|
318
348
|
/**
|
|
319
|
-
* Returns an auth witness for the given message hash
|
|
320
|
-
* for this transaction first, and falls back to the local database if not found.
|
|
349
|
+
* Returns an auth witness for the given message hash from the list of transient witnesses for this transaction.
|
|
321
350
|
* @param messageHash - Hash of the message to authenticate.
|
|
322
|
-
* @returns Authentication witness for the requested message hash.
|
|
351
|
+
* @returns Authentication witness for the requested message hash, or undefined if not found.
|
|
323
352
|
*/
|
|
324
353
|
public getAuthWitness(messageHash: Fr): Promise<Fr[] | undefined> {
|
|
325
354
|
return Promise.resolve(this.authWitnesses.find(w => w.requestHash.equals(messageHash))?.witness);
|
|
@@ -493,31 +522,44 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
493
522
|
logContractMessage(logger, LogLevels[level], strippedMessage, fields);
|
|
494
523
|
}
|
|
495
524
|
|
|
525
|
+
// Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
496
526
|
public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
|
|
497
|
-
const logService =
|
|
527
|
+
const logService = this.#createLogService();
|
|
528
|
+
const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
|
|
529
|
+
await this.capsuleService.appendToCapsuleArray(
|
|
530
|
+
this.contractAddress,
|
|
531
|
+
pendingTaggedLogArrayBaseSlot,
|
|
532
|
+
logs.map(log => log.toFields()),
|
|
533
|
+
this.jobId,
|
|
534
|
+
scope,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/** Fetches pending tagged logs into a freshly allocated ephemeral array and returns its base slot. */
|
|
539
|
+
public async getPendingTaggedLogsV2(scope: AztecAddress): Promise<Fr> {
|
|
540
|
+
const logService = this.#createLogService();
|
|
541
|
+
const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
|
|
542
|
+
return this.ephemeralArrayService.newArray(logs.map(log => log.toFields()));
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
#createLogService(): LogService {
|
|
546
|
+
return new LogService(
|
|
498
547
|
this.aztecNode,
|
|
499
548
|
this.anchorBlockHeader,
|
|
549
|
+
this.l2TipsStore,
|
|
500
550
|
this.keyStore,
|
|
501
|
-
this.capsuleService,
|
|
502
551
|
this.recipientTaggingStore,
|
|
503
552
|
this.senderAddressBookStore,
|
|
504
553
|
this.addressStore,
|
|
505
554
|
this.jobId,
|
|
506
555
|
this.logger.getBindings(),
|
|
507
556
|
);
|
|
508
|
-
|
|
509
|
-
await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, scope);
|
|
510
557
|
}
|
|
511
558
|
|
|
512
559
|
/**
|
|
513
|
-
*
|
|
514
|
-
* `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them
|
|
515
|
-
* queryable via `get_notes` and `getPrivateEvents`.
|
|
560
|
+
* Legacy: validates note/event requests stored in capsule arrays.
|
|
516
561
|
*
|
|
517
|
-
*
|
|
518
|
-
* @param contractAddress - The address of the contract that the logs are tagged for.
|
|
519
|
-
* @param noteValidationRequestsArrayBaseSlot - The base slot of capsule array containing note validation requests.
|
|
520
|
-
* @param eventValidationRequestsArrayBaseSlot - The base slot of capsule array containing event validation requests.
|
|
562
|
+
* Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
521
563
|
*/
|
|
522
564
|
public async validateAndStoreEnqueuedNotesAndEvents(
|
|
523
565
|
contractAddress: AztecAddress,
|
|
@@ -532,8 +574,6 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
532
574
|
throw new Error(`Got a note validation request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
533
575
|
}
|
|
534
576
|
|
|
535
|
-
// We read all note and event validation requests and process them all concurrently. This makes the process much
|
|
536
|
-
// faster as we don't need to wait for the network round-trip.
|
|
537
577
|
const noteValidationRequests = (
|
|
538
578
|
await this.capsuleService.readCapsuleArray(
|
|
539
579
|
contractAddress,
|
|
@@ -552,6 +592,53 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
552
592
|
)
|
|
553
593
|
).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
554
594
|
|
|
595
|
+
await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
|
|
596
|
+
|
|
597
|
+
await this.capsuleService.setCapsuleArray(
|
|
598
|
+
contractAddress,
|
|
599
|
+
noteValidationRequestsArrayBaseSlot,
|
|
600
|
+
[],
|
|
601
|
+
this.jobId,
|
|
602
|
+
scope,
|
|
603
|
+
);
|
|
604
|
+
await this.capsuleService.setCapsuleArray(
|
|
605
|
+
contractAddress,
|
|
606
|
+
eventValidationRequestsArrayBaseSlot,
|
|
607
|
+
[],
|
|
608
|
+
this.jobId,
|
|
609
|
+
scope,
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
public async validateAndStoreEnqueuedNotesAndEventsV2(
|
|
614
|
+
noteValidationRequestsArrayBaseSlot: Fr,
|
|
615
|
+
eventValidationRequestsArrayBaseSlot: Fr,
|
|
616
|
+
maxNotePackedLen: number,
|
|
617
|
+
maxEventSerializedLen: number,
|
|
618
|
+
scope: AztecAddress,
|
|
619
|
+
) {
|
|
620
|
+
const noteValidationRequests = this.ephemeralArrayService
|
|
621
|
+
.readArrayAt(noteValidationRequestsArrayBaseSlot)
|
|
622
|
+
.map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
|
|
623
|
+
|
|
624
|
+
const eventValidationRequests = this.ephemeralArrayService
|
|
625
|
+
.readArrayAt(eventValidationRequestsArrayBaseSlot)
|
|
626
|
+
.map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
|
|
627
|
+
|
|
628
|
+
await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Dispatches note and event validation requests to the service layer.
|
|
633
|
+
*
|
|
634
|
+
* This function is an auxiliary to support legacy (capsule backed) and new (ephemeral array backed) versions of the
|
|
635
|
+
* `validateAndStoreEnqueuedNotesAndEvents` oracle.
|
|
636
|
+
*/
|
|
637
|
+
async #processValidationRequests(
|
|
638
|
+
noteValidationRequests: NoteValidationRequest[],
|
|
639
|
+
eventValidationRequests: EventValidationRequest[],
|
|
640
|
+
scope: AztecAddress,
|
|
641
|
+
) {
|
|
555
642
|
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
|
|
556
643
|
const noteStorePromises = noteValidationRequests.map(request =>
|
|
557
644
|
noteService.validateAndStoreNote(
|
|
@@ -582,22 +669,6 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
582
669
|
);
|
|
583
670
|
|
|
584
671
|
await Promise.all([...noteStorePromises, ...eventStorePromises]);
|
|
585
|
-
|
|
586
|
-
// Requests are cleared once we're done.
|
|
587
|
-
await this.capsuleService.setCapsuleArray(
|
|
588
|
-
contractAddress,
|
|
589
|
-
noteValidationRequestsArrayBaseSlot,
|
|
590
|
-
[],
|
|
591
|
-
this.jobId,
|
|
592
|
-
scope,
|
|
593
|
-
);
|
|
594
|
-
await this.capsuleService.setCapsuleArray(
|
|
595
|
-
contractAddress,
|
|
596
|
-
eventValidationRequestsArrayBaseSlot,
|
|
597
|
-
[],
|
|
598
|
-
this.jobId,
|
|
599
|
-
scope,
|
|
600
|
-
);
|
|
601
672
|
}
|
|
602
673
|
|
|
603
674
|
public async getLogsByTag(
|
|
@@ -617,18 +688,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
617
688
|
await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
|
|
618
689
|
).map(LogRetrievalRequest.fromFields);
|
|
619
690
|
|
|
620
|
-
const logService =
|
|
621
|
-
this.aztecNode,
|
|
622
|
-
this.anchorBlockHeader,
|
|
623
|
-
this.keyStore,
|
|
624
|
-
this.capsuleService,
|
|
625
|
-
this.recipientTaggingStore,
|
|
626
|
-
this.senderAddressBookStore,
|
|
627
|
-
this.addressStore,
|
|
628
|
-
this.jobId,
|
|
629
|
-
this.logger.getBindings(),
|
|
630
|
-
);
|
|
631
|
-
|
|
691
|
+
const logService = this.#createLogService();
|
|
632
692
|
const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
|
|
633
693
|
|
|
634
694
|
// Requests are cleared once we're done.
|
|
@@ -650,6 +710,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
650
710
|
);
|
|
651
711
|
}
|
|
652
712
|
|
|
713
|
+
public async getLogsByTagV2(requestArrayBaseSlot: Fr): Promise<Fr> {
|
|
714
|
+
const logRetrievalRequests = this.ephemeralArrayService
|
|
715
|
+
.readArrayAt(requestArrayBaseSlot)
|
|
716
|
+
.map(LogRetrievalRequest.fromFields);
|
|
717
|
+
const logService = this.#createLogService();
|
|
718
|
+
|
|
719
|
+
const maybeLogRetrievalResponses = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
|
|
720
|
+
|
|
721
|
+
return this.ephemeralArrayService.newArray(maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption));
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
|
|
653
725
|
public async getMessageContextsByTxHash(
|
|
654
726
|
contractAddress: AztecAddress,
|
|
655
727
|
messageContextRequestsArrayBaseSlot: Fr,
|
|
@@ -661,7 +733,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
661
733
|
throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
|
|
662
734
|
}
|
|
663
735
|
|
|
664
|
-
// TODO(@mverzilli): this is a prime example of where using
|
|
736
|
+
// TODO(@mverzilli): this is a prime example of where using an ephemeral array would make much more sense, we don't
|
|
665
737
|
// need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
|
|
666
738
|
// At the same time, we don't want to allow any global scope access other than where backwards compatibility
|
|
667
739
|
// forces us to. Hence we need the scope here to be artificial.
|
|
@@ -705,6 +777,27 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
705
777
|
}
|
|
706
778
|
}
|
|
707
779
|
|
|
780
|
+
/** Reads tx hash requests from an ephemeral array, resolves their contexts, and returns the response slot. */
|
|
781
|
+
public async getMessageContextsByTxHashV2(requestArrayBaseSlot: Fr): Promise<Fr> {
|
|
782
|
+
const requestFields = this.ephemeralArrayService.readArrayAt(requestArrayBaseSlot);
|
|
783
|
+
|
|
784
|
+
const txHashes = requestFields.map((fields, i) => {
|
|
785
|
+
if (fields.length !== 1) {
|
|
786
|
+
throw new Error(
|
|
787
|
+
`Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
return fields[0];
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
|
|
794
|
+
txHashes,
|
|
795
|
+
this.anchorBlockHeader.getBlockNumber(),
|
|
796
|
+
);
|
|
797
|
+
|
|
798
|
+
return this.ephemeralArrayService.newArray(maybeMessageContexts.map(MessageContext.toSerializedOption));
|
|
799
|
+
}
|
|
800
|
+
|
|
708
801
|
public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
|
|
709
802
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
710
803
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
@@ -781,11 +874,103 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
781
874
|
return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
|
|
782
875
|
}
|
|
783
876
|
|
|
877
|
+
public pushEphemeral(slot: Fr, elements: Fr[]): number {
|
|
878
|
+
return this.ephemeralArrayService.push(slot, elements);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
public popEphemeral(slot: Fr): Fr[] {
|
|
882
|
+
return this.ephemeralArrayService.pop(slot);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
public getEphemeral(slot: Fr, index: number): Fr[] {
|
|
886
|
+
return this.ephemeralArrayService.get(slot, index);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
public setEphemeral(slot: Fr, index: number, elements: Fr[]): void {
|
|
890
|
+
this.ephemeralArrayService.set(slot, index, elements);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
public getEphemeralLen(slot: Fr): number {
|
|
894
|
+
return this.ephemeralArrayService.len(slot);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
public removeEphemeral(slot: Fr, index: number): void {
|
|
898
|
+
this.ephemeralArrayService.remove(slot, index);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
public clearEphemeral(slot: Fr): void {
|
|
902
|
+
this.ephemeralArrayService.clear(slot);
|
|
903
|
+
}
|
|
904
|
+
|
|
784
905
|
public emitOffchainEffect(data: Fr[]): Promise<void> {
|
|
785
906
|
this.offchainEffects.push({ data, contractAddress: this.contractAddress });
|
|
786
907
|
return Promise.resolve();
|
|
787
908
|
}
|
|
788
909
|
|
|
910
|
+
/** Executes another utility function from within this one and returns its serialized return values. */
|
|
911
|
+
public async callUtilityFunction(
|
|
912
|
+
targetContractAddress: AztecAddress,
|
|
913
|
+
functionSelector: FunctionSelector,
|
|
914
|
+
args: Fr[],
|
|
915
|
+
): Promise<Fr[]> {
|
|
916
|
+
// TODO(F-29): We want to support cross-contract utility calls, but doing so safely requires wallets to have
|
|
917
|
+
// a way to authorize which contracts can be called transitively, since those calls may expose private state.
|
|
918
|
+
// Until that is in place, restrict nested utility calls to the same contract only.
|
|
919
|
+
if (!targetContractAddress.equals(this.contractAddress)) {
|
|
920
|
+
throw new Error(
|
|
921
|
+
`Cross-contract utility calls are not yet supported: cannot call ${targetContractAddress} from utility function on ${this.contractAddress}.`,
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
this.logger.debug(
|
|
926
|
+
`Calling nested utility function ${targetContractAddress}:${functionSelector} from ${this.contractAddress}`,
|
|
927
|
+
);
|
|
928
|
+
|
|
929
|
+
const targetArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(
|
|
930
|
+
targetContractAddress,
|
|
931
|
+
functionSelector,
|
|
932
|
+
);
|
|
933
|
+
|
|
934
|
+
const nestedOracle = new UtilityExecutionOracle({
|
|
935
|
+
contractAddress: targetContractAddress,
|
|
936
|
+
authWitnesses: this.authWitnesses,
|
|
937
|
+
capsules: this.capsules,
|
|
938
|
+
anchorBlockHeader: this.anchorBlockHeader,
|
|
939
|
+
contractStore: this.contractStore,
|
|
940
|
+
noteStore: this.noteStore,
|
|
941
|
+
keyStore: this.keyStore,
|
|
942
|
+
addressStore: this.addressStore,
|
|
943
|
+
aztecNode: this.aztecNode,
|
|
944
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
945
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
946
|
+
capsuleService: this.capsuleService,
|
|
947
|
+
privateEventStore: this.privateEventStore,
|
|
948
|
+
messageContextService: this.messageContextService,
|
|
949
|
+
contractSyncService: this.contractSyncService,
|
|
950
|
+
l2TipsStore: this.l2TipsStore,
|
|
951
|
+
jobId: this.jobId,
|
|
952
|
+
scopes: this.scopes,
|
|
953
|
+
simulator: this.simulator,
|
|
954
|
+
log: this.logger,
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
const initialWitness = toACVMWitness(0, args);
|
|
958
|
+
const acvmCallback = new Oracle(nestedOracle);
|
|
959
|
+
const acirExecutionResult = await this.simulator
|
|
960
|
+
.executeUserCircuit(initialWitness, targetArtifact, acvmCallback.toACIRCallback())
|
|
961
|
+
.catch((err: Error) => {
|
|
962
|
+
err.message = resolveAssertionMessageFromError(err, targetArtifact);
|
|
963
|
+
throw new ExecutionError(
|
|
964
|
+
err.message,
|
|
965
|
+
{ contractAddress: targetContractAddress, functionSelector },
|
|
966
|
+
extractCallStack(err, targetArtifact.debug),
|
|
967
|
+
{ cause: err },
|
|
968
|
+
);
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
972
|
+
}
|
|
973
|
+
|
|
789
974
|
/** Returns offchain effects collected during execution. */
|
|
790
975
|
public getOffchainEffects(): OffchainEffect[] {
|
|
791
976
|
return this.offchainEffects;
|
|
@@ -796,7 +981,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
796
981
|
const [response] = await Promise.all([
|
|
797
982
|
query(),
|
|
798
983
|
(async () => {
|
|
799
|
-
const
|
|
984
|
+
const block = await this.aztecNode.getBlock(blockHash);
|
|
985
|
+
const header = block?.header;
|
|
800
986
|
if (!header) {
|
|
801
987
|
throw new Error(`Could not find block header for block hash ${blockHash}`);
|
|
802
988
|
}
|
|
@@ -85,9 +85,24 @@ interface ContainsNote {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const selectPropertyFromPackedNoteContent = (noteData: Fr[], selector: PropertySelector): Fr => {
|
|
88
|
+
if (selector.index >= noteData.length) {
|
|
89
|
+
throw new Error(`Property selector index ${selector.index} out of bounds for note with ${noteData.length} fields`);
|
|
90
|
+
}
|
|
91
|
+
if (selector.offset + selector.length > Fr.SIZE_IN_BYTES) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Property selector range (offset=${selector.offset}, length=${selector.length}) exceeds Fr buffer size of ${Fr.SIZE_IN_BYTES} bytes`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
88
96
|
const noteValueBuffer = noteData[selector.index].toBuffer();
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
// Noir's PropertySelector counts offset from the LSB (last byte of the big-endian buffer),
|
|
98
|
+
// so offset=0,length=Fr.SIZE_IN_BYTES reads the entire field, and offset=0,length=1 reads the last byte.
|
|
99
|
+
const start = Fr.SIZE_IN_BYTES - selector.offset - selector.length;
|
|
100
|
+
const end = Fr.SIZE_IN_BYTES - selector.offset;
|
|
101
|
+
const noteValue = noteValueBuffer.subarray(start, end);
|
|
102
|
+
// Left-pad to Fr.SIZE_IN_BYTES so Fr.fromBuffer interprets the value correctly.
|
|
103
|
+
const padded = Buffer.alloc(Fr.SIZE_IN_BYTES);
|
|
104
|
+
noteValue.copy(padded, Fr.SIZE_IN_BYTES - noteValue.length);
|
|
105
|
+
return Fr.fromBuffer(padded);
|
|
91
106
|
};
|
|
92
107
|
|
|
93
108
|
const selectNotes = <T extends ContainsNote>(noteDatas: T[], selects: Select[]): T[] =>
|
|
@@ -103,7 +118,11 @@ const selectNotes = <T extends ContainsNote>(noteDatas: T[], selects: Select[]):
|
|
|
103
118
|
[Comparator.GTE]: () => !noteValueFr.lt(value),
|
|
104
119
|
};
|
|
105
120
|
|
|
106
|
-
|
|
121
|
+
const fn = comparatorSelector[comparator];
|
|
122
|
+
if (!fn) {
|
|
123
|
+
throw new Error(`Invalid comparator value: ${comparator}`);
|
|
124
|
+
}
|
|
125
|
+
return fn();
|
|
107
126
|
}),
|
|
108
127
|
);
|
|
109
128
|
|
|
@@ -29,6 +29,7 @@ export class ProxiedContractStoreFactory {
|
|
|
29
29
|
}
|
|
30
30
|
instance.currentContractClassId = realInstance.currentContractClassId;
|
|
31
31
|
instance.originalContractClassId = realInstance.originalContractClassId;
|
|
32
|
+
instance.initializationHash = realInstance.initializationHash;
|
|
32
33
|
return instance;
|
|
33
34
|
} else {
|
|
34
35
|
return target.getContractInstance(address);
|
|
@@ -47,6 +48,9 @@ export class ProxiedContractStoreFactory {
|
|
|
47
48
|
return fn;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}. The stub does not implement this function.`,
|
|
53
|
+
);
|
|
50
54
|
} else {
|
|
51
55
|
return target.getFunctionArtifact(contractAddress, selector);
|
|
52
56
|
}
|
|
@@ -64,6 +68,9 @@ export class ProxiedContractStoreFactory {
|
|
|
64
68
|
return fn;
|
|
65
69
|
}
|
|
66
70
|
}
|
|
71
|
+
throw new Error(
|
|
72
|
+
`Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}. The stub does not implement this function.`,
|
|
73
|
+
);
|
|
67
74
|
} else {
|
|
68
75
|
return target.getFunctionArtifactWithDebugMetadata(contractAddress, selector);
|
|
69
76
|
}
|
|
@@ -78,6 +85,6 @@ export class ProxiedContractStoreFactory {
|
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
},
|
|
81
|
-
});
|
|
88
|
+
}) satisfies ContractStore;
|
|
82
89
|
}
|
|
83
90
|
}
|