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