@aztec/pxe 0.0.1-commit.fff30aa → 0.0.1-dev
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 +1 -1
- package/dest/block_synchronizer/block_synchronizer.d.ts +5 -3
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +10 -2
- package/dest/config/package_info.js +1 -1
- 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 +18 -10
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +5 -2
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.d.ts +4 -1
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +53 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -14
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +16 -14
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +19 -2
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +108 -5
- package/dest/contract_sync/contract_sync_service.d.ts +2 -1
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +41 -7
- 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 +12 -19
- package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
- package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/utils.js +2 -1
- package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +2 -1
- package/dest/entrypoints/pxe_creation_options.d.ts +4 -1
- package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
- package/dest/entrypoints/server/index.d.ts +2 -1
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +1 -0
- package/dest/entrypoints/server/utils.d.ts +1 -1
- package/dest/entrypoints/server/utils.d.ts.map +1 -1
- package/dest/entrypoints/server/utils.js +2 -1
- package/dest/events/event_service.d.ts +13 -5
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +28 -7
- package/dest/hooks/authorize_utility_call.d.ts +37 -0
- package/dest/hooks/authorize_utility_call.d.ts.map +1 -0
- package/dest/hooks/authorize_utility_call.js +4 -0
- package/dest/hooks/execution_hooks.d.ts +42 -0
- package/dest/hooks/execution_hooks.d.ts.map +1 -0
- package/dest/hooks/execution_hooks.js +9 -0
- package/dest/hooks/index.d.ts +4 -0
- package/dest/hooks/index.d.ts.map +1 -0
- package/dest/hooks/index.js +1 -0
- package/dest/logs/log_service.d.ts +1 -1
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +20 -35
- package/dest/messages/message_context_service.d.ts +1 -1
- package/dest/messages/message_context_service.d.ts.map +1 -1
- package/dest/messages/message_context_service.js +12 -10
- package/dest/notes/note_service.d.ts +25 -3
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +80 -65
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +2 -2
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +2 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +18 -4
- package/dest/private_kernel/private_kernel_oracle.d.ts +1 -1
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +7 -2
- package/dest/pxe.d.ts +20 -5
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +61 -59
- package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.d.ts +42 -0
- package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.d.ts.map +1 -0
- package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.js +93 -0
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts +15 -0
- package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts.map +1 -0
- package/dest/storage/backwards_compatibility_tests/schema_tests.js +588 -0
- package/dest/storage/backwards_compatibility_tests/store_spy.d.ts +19 -0
- package/dest/storage/backwards_compatibility_tests/store_spy.d.ts.map +1 -0
- package/dest/storage/backwards_compatibility_tests/store_spy.js +63 -0
- package/dest/storage/open_pxe_stores.d.ts +31 -0
- package/dest/storage/open_pxe_stores.d.ts.map +1 -0
- package/dest/storage/open_pxe_stores.js +26 -0
- package/dest/tagging/get_all_logs_by_tags.d.ts +1 -1
- package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
- package/dest/tagging/get_all_logs_by_tags.js +3 -0
- package/dest/tagging/index.d.ts +4 -3
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +3 -2
- package/dest/tagging/persist_sender_tagging_index_ranges.d.ts +29 -0
- package/dest/tagging/persist_sender_tagging_index_ranges.d.ts.map +1 -0
- package/dest/tagging/persist_sender_tagging_index_ranges.js +42 -0
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +56 -0
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -0
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +158 -0
- package/dest/tagging/reconcile_tagging_index_ranges.d.ts +36 -0
- package/dest/tagging/reconcile_tagging_index_ranges.d.ts.map +1 -0
- package/dest/tagging/reconcile_tagging_index_ranges.js +74 -0
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +19 -8
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +11 -6
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +21 -0
- package/package.json +17 -16
- package/src/bin/check_oracle_version.ts +1 -1
- package/src/block_synchronizer/block_synchronizer.ts +11 -3
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/contract_function_simulator.ts +32 -9
- package/src/contract_function_simulator/oracle/interfaces.ts +12 -1
- package/src/contract_function_simulator/oracle/oracle.ts +73 -1
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +25 -21
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +165 -29
- package/src/contract_sync/contract_sync_service.ts +55 -23
- package/src/contract_sync/helpers.ts +11 -23
- package/src/entrypoints/client/bundle/utils.ts +1 -0
- package/src/entrypoints/client/lazy/utils.ts +1 -0
- package/src/entrypoints/pxe_creation_options.ts +4 -0
- package/src/entrypoints/server/index.ts +1 -0
- package/src/entrypoints/server/utils.ts +1 -0
- package/src/events/event_service.ts +52 -17
- package/src/hooks/authorize_utility_call.ts +40 -0
- package/src/hooks/execution_hooks.ts +48 -0
- package/src/hooks/index.ts +7 -0
- package/src/logs/log_service.ts +46 -71
- package/src/messages/message_context_service.ts +25 -24
- package/src/notes/note_service.ts +115 -91
- package/src/oracle_version.ts +2 -2
- package/src/private_kernel/private_kernel_execution_prover.ts +29 -3
- package/src/private_kernel/private_kernel_oracle.ts +15 -5
- package/src/pxe.ts +116 -53
- package/src/storage/backwards_compatibility_tests/__snapshots__/AddressStore.json +22 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/AnchorBlockStore.json +3 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/CapsuleStore.json +16 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/ContractStore.json +28 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/KeyStore.json +52 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/L2TipsKVStore.json +42 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/NoteStore.json +36 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/PrivateEventStore.json +44 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/RecipientTaggingStore.json +18 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/SenderAddressBookStore.json +16 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/SenderTaggingStore.json +22 -0
- package/src/storage/backwards_compatibility_tests/__snapshots__/opened_stores.json +97 -0
- package/src/storage/backwards_compatibility_tests/kv_store_snapshot.ts +122 -0
- package/src/storage/backwards_compatibility_tests/schema_tests.ts +707 -0
- package/src/storage/backwards_compatibility_tests/store_spy.ts +73 -0
- package/src/storage/open_pxe_stores.ts +47 -0
- package/src/tagging/get_all_logs_by_tags.ts +4 -0
- package/src/tagging/index.ts +3 -2
- package/src/tagging/persist_sender_tagging_index_ranges.ts +57 -0
- package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +236 -0
- package/src/tagging/reconcile_tagging_index_ranges.ts +102 -0
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +33 -10
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +23 -8
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +0 -14
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +0 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +0 -85
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +0 -14
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +0 -1
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +0 -33
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +0 -130
- package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +0 -44
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
|
|
2
2
|
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { uniqueBy } from '@aztec/foundation/collection';
|
|
3
4
|
import { Aes128 } from '@aztec/foundation/crypto/aes128';
|
|
4
5
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
6
|
import { Point } from '@aztec/foundation/curves/grumpkin';
|
|
@@ -7,6 +8,15 @@ import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
7
8
|
import type { MembershipWitness } from '@aztec/foundation/trees';
|
|
8
9
|
import type { KeyStore } from '@aztec/key-store';
|
|
9
10
|
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
11
|
+
import {
|
|
12
|
+
type CircuitSimulator,
|
|
13
|
+
ExecutionError,
|
|
14
|
+
extractCallStack,
|
|
15
|
+
resolveAssertionMessageFromError,
|
|
16
|
+
toACVMWitness,
|
|
17
|
+
witnessMapToFields,
|
|
18
|
+
} from '@aztec/simulator/client';
|
|
19
|
+
import { type FunctionCall, FunctionSelector } from '@aztec/stdlib/abi';
|
|
10
20
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
11
21
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
22
|
import { BlockHash, type L2TipsProvider } from '@aztec/stdlib/block';
|
|
@@ -19,11 +29,12 @@ import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs'
|
|
|
19
29
|
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
20
30
|
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
21
31
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
22
|
-
import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
|
|
32
|
+
import type { BlockHeader, Capsule, IndexedTxEffect, OffchainEffect, TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
23
33
|
|
|
24
34
|
import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
|
|
25
35
|
import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
|
|
26
36
|
import { EventService } from '../../events/event_service.js';
|
|
37
|
+
import type { ExecutionHooks } from '../../hooks/index.js';
|
|
27
38
|
import { LogService } from '../../logs/log_service.js';
|
|
28
39
|
import { MessageContextService } from '../../messages/message_context_service.js';
|
|
29
40
|
import { NoteService } from '../../notes/note_service.js';
|
|
@@ -44,6 +55,7 @@ import { UtilityContext } from '../noir-structs/utility_context.js';
|
|
|
44
55
|
import { pickNotes } from '../pick_notes.js';
|
|
45
56
|
import type { IMiscOracle, IUtilityExecutionOracle, NoteData } from './interfaces.js';
|
|
46
57
|
import { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
|
|
58
|
+
import { Oracle } from './oracle.js';
|
|
47
59
|
|
|
48
60
|
/** Args for UtilityExecutionOracle constructor. */
|
|
49
61
|
export type UtilityExecutionOracleArgs = {
|
|
@@ -67,6 +79,10 @@ export type UtilityExecutionOracleArgs = {
|
|
|
67
79
|
jobId: string;
|
|
68
80
|
log?: ReturnType<typeof createLogger>;
|
|
69
81
|
scopes: AztecAddress[];
|
|
82
|
+
simulator: CircuitSimulator;
|
|
83
|
+
hooks?: ExecutionHooks;
|
|
84
|
+
/** Needed to trigger contract synchronization before nested cross-contract calls. */
|
|
85
|
+
utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
|
|
70
86
|
};
|
|
71
87
|
|
|
72
88
|
/**
|
|
@@ -103,6 +119,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
103
119
|
protected readonly jobId: string;
|
|
104
120
|
protected logger: ReturnType<typeof createLogger>;
|
|
105
121
|
protected readonly scopes: AztecAddress[];
|
|
122
|
+
protected readonly simulator: CircuitSimulator;
|
|
123
|
+
protected readonly hooks: ExecutionHooks | undefined;
|
|
124
|
+
protected readonly utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
|
|
106
125
|
|
|
107
126
|
constructor(args: UtilityExecutionOracleArgs) {
|
|
108
127
|
this.contractAddress = args.contractAddress;
|
|
@@ -124,6 +143,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
124
143
|
this.jobId = args.jobId;
|
|
125
144
|
this.logger = args.log ?? createLogger('simulator:client_view_context');
|
|
126
145
|
this.scopes = args.scopes;
|
|
146
|
+
this.simulator = args.simulator;
|
|
147
|
+
this.hooks = args.hooks;
|
|
148
|
+
this.utilityExecutor = args.utilityExecutor;
|
|
127
149
|
}
|
|
128
150
|
|
|
129
151
|
public assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
@@ -289,6 +311,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
289
311
|
throw new Error(`Block number ${blockNumber} is higher than current block ${anchorBlockNumber}`);
|
|
290
312
|
}
|
|
291
313
|
|
|
314
|
+
// Most contracts query state at the "current" block, which is the anchor. Skip the RPC when we can.
|
|
315
|
+
if (blockNumber === anchorBlockNumber) {
|
|
316
|
+
return this.anchorBlockHeader;
|
|
317
|
+
}
|
|
318
|
+
|
|
292
319
|
const block = await this.aztecNode.getBlock(blockNumber);
|
|
293
320
|
return block?.header;
|
|
294
321
|
}
|
|
@@ -626,36 +653,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
626
653
|
eventValidationRequests: EventValidationRequest[],
|
|
627
654
|
scope: AztecAddress,
|
|
628
655
|
) {
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
request.owner,
|
|
634
|
-
request.storageSlot,
|
|
635
|
-
request.randomness,
|
|
636
|
-
request.noteNonce,
|
|
637
|
-
request.content,
|
|
638
|
-
request.noteHash,
|
|
639
|
-
request.nullifier,
|
|
640
|
-
request.txHash,
|
|
641
|
-
scope,
|
|
642
|
-
),
|
|
643
|
-
);
|
|
656
|
+
const txEffects = await this.#fetchTxEffects([
|
|
657
|
+
...noteValidationRequests.map(r => r.txHash),
|
|
658
|
+
...eventValidationRequests.map(r => r.txHash),
|
|
659
|
+
]);
|
|
644
660
|
|
|
661
|
+
const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
|
|
645
662
|
const eventService = new EventService(this.anchorBlockHeader, this.aztecNode, this.privateEventStore, this.jobId);
|
|
646
|
-
const eventStorePromises = eventValidationRequests.map(request =>
|
|
647
|
-
eventService.validateAndStoreEvent(
|
|
648
|
-
request.contractAddress,
|
|
649
|
-
request.eventTypeId,
|
|
650
|
-
request.randomness,
|
|
651
|
-
request.serializedEvent,
|
|
652
|
-
request.eventCommitment,
|
|
653
|
-
request.txHash,
|
|
654
|
-
scope,
|
|
655
|
-
),
|
|
656
|
-
);
|
|
657
663
|
|
|
658
|
-
await Promise.all([
|
|
664
|
+
await Promise.all([
|
|
665
|
+
noteService.validateAndStoreNotes(noteValidationRequests, scope, txEffects),
|
|
666
|
+
eventService.validateAndStoreEvents(eventValidationRequests, scope, txEffects),
|
|
667
|
+
]);
|
|
659
668
|
}
|
|
660
669
|
|
|
661
670
|
public async getLogsByTag(
|
|
@@ -785,6 +794,23 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
785
794
|
return this.ephemeralArrayService.newArray(maybeMessageContexts.map(MessageContext.toSerializedOption));
|
|
786
795
|
}
|
|
787
796
|
|
|
797
|
+
/**
|
|
798
|
+
* Fetches the effects of a transaction by its hash. Returns null if the tx is not found or is beyond the anchor
|
|
799
|
+
* block.
|
|
800
|
+
*/
|
|
801
|
+
public async getTxEffect(txHash: TxHash): Promise<TxEffect | null> {
|
|
802
|
+
if (txHash.hash.isZero()) {
|
|
803
|
+
throw new Error('Invalid tx hash passed into aztec_utl_getTxEffect oracle handler');
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
const txEffect = await this.aztecNode.getTxEffect(txHash);
|
|
807
|
+
if (!txEffect || txEffect.l2BlockNumber > this.anchorBlockHeader.getBlockNumber()) {
|
|
808
|
+
return null;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
return txEffect.data;
|
|
812
|
+
}
|
|
813
|
+
|
|
788
814
|
public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
|
|
789
815
|
if (!contractAddress.equals(this.contractAddress)) {
|
|
790
816
|
// TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
|
|
@@ -894,13 +920,123 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
894
920
|
return Promise.resolve();
|
|
895
921
|
}
|
|
896
922
|
|
|
923
|
+
/** Executes another utility function from within this one and returns its serialized return values. */
|
|
924
|
+
public async callUtilityFunction(
|
|
925
|
+
targetContractAddress: AztecAddress,
|
|
926
|
+
functionSelector: FunctionSelector,
|
|
927
|
+
args: Fr[],
|
|
928
|
+
): Promise<Fr[]> {
|
|
929
|
+
const targetArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(
|
|
930
|
+
targetContractAddress,
|
|
931
|
+
functionSelector,
|
|
932
|
+
);
|
|
933
|
+
|
|
934
|
+
if (!targetContractAddress.equals(this.contractAddress)) {
|
|
935
|
+
const request = {
|
|
936
|
+
caller: this.contractAddress,
|
|
937
|
+
target: targetContractAddress,
|
|
938
|
+
functionSelector,
|
|
939
|
+
functionName: targetArtifact.name,
|
|
940
|
+
args,
|
|
941
|
+
callerContext: ('isPrivate' in this ? 'private' : 'utility') as 'private' | 'utility',
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
const response = this.hooks
|
|
945
|
+
? await this.hooks.authorizeUtilityCall(request)
|
|
946
|
+
: { authorized: false, reason: 'No execution hooks configured' };
|
|
947
|
+
|
|
948
|
+
if (!response.authorized) {
|
|
949
|
+
const reason = response.reason ? `: ${response.reason}` : '';
|
|
950
|
+
throw new Error(
|
|
951
|
+
`Cross-contract utility call denied${reason}. ${this.contractAddress} attempted to call ` +
|
|
952
|
+
`${targetContractAddress}:${functionSelector} (${targetArtifact.name}). ` +
|
|
953
|
+
`See https://docs.aztec.network/errors/11`,
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
await this.contractSyncService.ensureContractSynced(
|
|
958
|
+
targetContractAddress,
|
|
959
|
+
functionSelector,
|
|
960
|
+
this.utilityExecutor,
|
|
961
|
+
this.anchorBlockHeader,
|
|
962
|
+
this.jobId,
|
|
963
|
+
this.scopes,
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
this.logger.debug(
|
|
968
|
+
`Calling nested utility function ${targetContractAddress}:${functionSelector} from ${this.contractAddress}`,
|
|
969
|
+
);
|
|
970
|
+
|
|
971
|
+
const nestedOracle = new UtilityExecutionOracle({
|
|
972
|
+
contractAddress: targetContractAddress,
|
|
973
|
+
authWitnesses: this.authWitnesses,
|
|
974
|
+
capsules: this.capsules,
|
|
975
|
+
anchorBlockHeader: this.anchorBlockHeader,
|
|
976
|
+
contractStore: this.contractStore,
|
|
977
|
+
noteStore: this.noteStore,
|
|
978
|
+
keyStore: this.keyStore,
|
|
979
|
+
addressStore: this.addressStore,
|
|
980
|
+
aztecNode: this.aztecNode,
|
|
981
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
982
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
983
|
+
capsuleService: this.capsuleService,
|
|
984
|
+
privateEventStore: this.privateEventStore,
|
|
985
|
+
messageContextService: this.messageContextService,
|
|
986
|
+
contractSyncService: this.contractSyncService,
|
|
987
|
+
l2TipsStore: this.l2TipsStore,
|
|
988
|
+
jobId: this.jobId,
|
|
989
|
+
scopes: this.scopes,
|
|
990
|
+
simulator: this.simulator,
|
|
991
|
+
hooks: this.hooks,
|
|
992
|
+
utilityExecutor: this.utilityExecutor,
|
|
993
|
+
log: this.logger,
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
const initialWitness = toACVMWitness(0, args);
|
|
997
|
+
const acvmCallback = new Oracle(nestedOracle);
|
|
998
|
+
const acirExecutionResult = await this.simulator
|
|
999
|
+
.executeUserCircuit(initialWitness, targetArtifact, acvmCallback.toACIRCallback())
|
|
1000
|
+
.catch((err: Error) => {
|
|
1001
|
+
err.message = resolveAssertionMessageFromError(err, targetArtifact);
|
|
1002
|
+
throw new ExecutionError(
|
|
1003
|
+
err.message,
|
|
1004
|
+
{ contractAddress: targetContractAddress, functionSelector },
|
|
1005
|
+
extractCallStack(err, targetArtifact.debug),
|
|
1006
|
+
{ cause: err },
|
|
1007
|
+
);
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
897
1013
|
/** Returns offchain effects collected during execution. */
|
|
898
1014
|
public getOffchainEffects(): OffchainEffect[] {
|
|
899
1015
|
return this.offchainEffects;
|
|
900
1016
|
}
|
|
901
1017
|
|
|
1018
|
+
/**
|
|
1019
|
+
* Fetches tx effects for the given hashes in parallel, deduplicating repeated hashes so each tx is only requested
|
|
1020
|
+
* once. Returns a map keyed by `TxHash.toString()`; hashes for which the node has no tx effect are omitted.
|
|
1021
|
+
*/
|
|
1022
|
+
async #fetchTxEffects(txHashes: TxHash[]): Promise<Map<string, IndexedTxEffect>> {
|
|
1023
|
+
const uniqueTxHashes = uniqueBy(txHashes, h => h.toString());
|
|
1024
|
+
const fetched = await Promise.all(uniqueTxHashes.map(h => this.aztecNode.getTxEffect(h)));
|
|
1025
|
+
return new Map(
|
|
1026
|
+
uniqueTxHashes
|
|
1027
|
+
.map((h, i): [string, IndexedTxEffect | undefined] => [h.toString(), fetched[i]])
|
|
1028
|
+
.filter((entry): entry is [string, IndexedTxEffect] => entry[1] !== undefined),
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
902
1032
|
/** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
|
|
903
1033
|
async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
|
|
1034
|
+
// Most contracts query state at the "current" block, which is the anchor. Skip the validation when we can.
|
|
1035
|
+
const anchorHash = await this.anchorBlockHeader.hash();
|
|
1036
|
+
if (blockHash.equals(anchorHash)) {
|
|
1037
|
+
return query();
|
|
1038
|
+
}
|
|
1039
|
+
|
|
904
1040
|
const [response] = await Promise.all([
|
|
905
1041
|
query(),
|
|
906
1042
|
(async () => {
|
|
@@ -911,7 +1047,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
911
1047
|
|
|
912
1048
|
if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
|
|
913
1049
|
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 ${
|
|
1050
|
+
`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 ${anchorHash}).`,
|
|
915
1051
|
);
|
|
916
1052
|
}
|
|
917
1053
|
})(),
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { Logger } from '@aztec/foundation/log';
|
|
2
2
|
import { Semaphore } from '@aztec/foundation/queue';
|
|
3
|
+
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
3
4
|
import type { FunctionCall, FunctionSelector } from '@aztec/stdlib/abi';
|
|
4
5
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
6
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
6
7
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
7
8
|
|
|
8
9
|
import type { StagedStore } from '../job_coordinator/job_coordinator.js';
|
|
10
|
+
import { NoteService } from '../notes/note_service.js';
|
|
9
11
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
10
12
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
11
|
-
import {
|
|
13
|
+
import { syncScope, verifyCurrentClassId } from './helpers.js';
|
|
12
14
|
|
|
13
15
|
/** Maximum number of scope syncs running concurrently across the PXE. */
|
|
14
16
|
const MAX_CONCURRENT_SCOPE_SYNCS = 5;
|
|
@@ -27,6 +29,10 @@ export class ContractSyncService implements StagedStore {
|
|
|
27
29
|
// The value is a promise that resolves when the contract is synced.
|
|
28
30
|
private syncedContracts: Map<string, Promise<void>> = new Map();
|
|
29
31
|
|
|
32
|
+
// Tracks class ID verification per contract. Keyed by contract address only (no scope), since
|
|
33
|
+
// class ID verification is scope-independent. Cleared on wipe/discard.
|
|
34
|
+
private classIdVerificationCache: Map<string, Promise<void>> = new Map();
|
|
35
|
+
|
|
30
36
|
// Per-job excluded contract addresses - these contracts should not be synced.
|
|
31
37
|
private excludedFromSync: Map<string, Set<string>> = new Map();
|
|
32
38
|
|
|
@@ -68,22 +74,8 @@ export class ContractSyncService implements StagedStore {
|
|
|
68
74
|
return;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
|
-
this.#startSyncIfNeeded(
|
|
72
|
-
contractAddress,
|
|
73
|
-
scopes,
|
|
74
|
-
() => verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader),
|
|
75
|
-
scope =>
|
|
76
|
-
syncState(
|
|
77
|
-
contractAddress,
|
|
78
|
-
this.contractStore,
|
|
79
|
-
functionToInvokeAfterSync,
|
|
80
|
-
utilityExecutor,
|
|
81
|
-
this.noteStore,
|
|
82
|
-
this.aztecNode,
|
|
83
|
-
anchorBlockHeader,
|
|
84
|
-
jobId,
|
|
85
|
-
scope,
|
|
86
|
-
),
|
|
77
|
+
this.#startSyncIfNeeded(contractAddress, scopes, anchorBlockHeader, jobId, scope =>
|
|
78
|
+
syncScope(contractAddress, this.contractStore, functionToInvokeAfterSync, utilityExecutor, scope),
|
|
87
79
|
);
|
|
88
80
|
|
|
89
81
|
await this.#awaitSync(contractAddress, scopes);
|
|
@@ -101,6 +93,7 @@ export class ContractSyncService implements StagedStore {
|
|
|
101
93
|
wipe(): void {
|
|
102
94
|
this.log.debug(`Wiping contract sync cache (${this.syncedContracts.size} entries)`);
|
|
103
95
|
this.syncedContracts.clear();
|
|
96
|
+
this.classIdVerificationCache.clear();
|
|
104
97
|
}
|
|
105
98
|
|
|
106
99
|
commit(jobId: string): Promise<void> {
|
|
@@ -113,6 +106,7 @@ export class ContractSyncService implements StagedStore {
|
|
|
113
106
|
// We clear the synced contracts cache here because, when the job is discarded, any associated database writes from
|
|
114
107
|
// the sync are also undone.
|
|
115
108
|
this.syncedContracts.clear();
|
|
109
|
+
this.classIdVerificationCache.clear();
|
|
116
110
|
this.excludedFromSync.delete(jobId);
|
|
117
111
|
return Promise.resolve();
|
|
118
112
|
}
|
|
@@ -122,14 +116,16 @@ export class ContractSyncService implements StagedStore {
|
|
|
122
116
|
}
|
|
123
117
|
|
|
124
118
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
119
|
+
* For each unsynced scope, creates a promise that waits on:
|
|
120
|
+
* 1. Class ID verification (cached per contract, scope-independent).
|
|
121
|
+
* 2. Note nullifier sync (shared, batched across all unsynced scopes).
|
|
122
|
+
* 3. Per-scope sync (individual, semaphore-bounded).
|
|
128
123
|
*/
|
|
129
124
|
#startSyncIfNeeded(
|
|
130
125
|
contractAddress: AztecAddress,
|
|
131
126
|
scopes: AztecAddress[],
|
|
132
|
-
|
|
127
|
+
anchorBlockHeader: BlockHeader,
|
|
128
|
+
jobId: string,
|
|
133
129
|
syncScopeFn: (scope: AztecAddress) => Promise<void>,
|
|
134
130
|
): void {
|
|
135
131
|
const scopesToSync = scopes.filter(scope => !this.syncedContracts.has(toKey(contractAddress, scope)));
|
|
@@ -138,11 +134,13 @@ export class ContractSyncService implements StagedStore {
|
|
|
138
134
|
}
|
|
139
135
|
|
|
140
136
|
this.log.debug(`Syncing contract ${contractAddress} for ${scopesToSync.length} scope(s)`);
|
|
141
|
-
|
|
137
|
+
|
|
138
|
+
const verifyPromise = this.#verifyClassId(contractAddress, anchorBlockHeader);
|
|
139
|
+
const syncNullifiersPromise = this.#syncNoteNullifiers(contractAddress, anchorBlockHeader, jobId, scopesToSync);
|
|
142
140
|
|
|
143
141
|
for (const scope of scopesToSync) {
|
|
144
142
|
const key = toKey(contractAddress, scope);
|
|
145
|
-
const promise = Promise.all([verifyPromise, this.#runBounded(() => syncScopeFn(scope))])
|
|
143
|
+
const promise = Promise.all([verifyPromise, syncNullifiersPromise, this.#runBounded(() => syncScopeFn(scope))])
|
|
146
144
|
.then(() => {})
|
|
147
145
|
.catch(err => {
|
|
148
146
|
this.syncedContracts.delete(key);
|
|
@@ -152,6 +150,40 @@ export class ContractSyncService implements StagedStore {
|
|
|
152
150
|
}
|
|
153
151
|
}
|
|
154
152
|
|
|
153
|
+
/** Verifies the local class ID matches the on-chain value (cached, evicts on failure so retries re-verify). */
|
|
154
|
+
#verifyClassId(contractAddress: AztecAddress, anchorBlockHeader: BlockHeader): Promise<void> {
|
|
155
|
+
const contractKey = contractAddress.toString();
|
|
156
|
+
const cached = this.classIdVerificationCache.get(contractKey);
|
|
157
|
+
if (cached) {
|
|
158
|
+
return cached;
|
|
159
|
+
}
|
|
160
|
+
const promise = verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader).catch(
|
|
161
|
+
err => {
|
|
162
|
+
this.classIdVerificationCache.delete(contractKey);
|
|
163
|
+
throw err;
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
this.classIdVerificationCache.set(contractKey, promise);
|
|
167
|
+
return promise;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Syncs note nullifiers across all unsynced scopes in a single batched call. */
|
|
171
|
+
async #syncNoteNullifiers(
|
|
172
|
+
contractAddress: AztecAddress,
|
|
173
|
+
anchorBlockHeader: BlockHeader,
|
|
174
|
+
jobId: string,
|
|
175
|
+
scopes: AztecAddress[],
|
|
176
|
+
): Promise<void> {
|
|
177
|
+
// Protocol contracts don't have private state to sync
|
|
178
|
+
if (isProtocolContract(contractAddress)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// This runs in parallel with per-scope sync (which also writes to the note store). That's safe because
|
|
182
|
+
// the note store handles concurrent operations.
|
|
183
|
+
const noteService = new NoteService(this.noteStore, this.aztecNode, anchorBlockHeader, jobId);
|
|
184
|
+
await noteService.syncNoteNullifiers(contractAddress, scopes);
|
|
185
|
+
}
|
|
186
|
+
|
|
155
187
|
/** Runs fn while holding a slot in #syncSlot, bounding total concurrent scope syncs. */
|
|
156
188
|
async #runBounded<T>(fn: () => Promise<T>): Promise<T> {
|
|
157
189
|
await this.#syncSlot.acquire();
|
|
@@ -6,9 +6,7 @@ import { DelayedPublicMutableValues, DelayedPublicMutableValuesWithHash } from '
|
|
|
6
6
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
7
7
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
9
|
-
import { NoteService } from '../notes/note_service.js';
|
|
10
9
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
11
|
-
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* Read the current class id of a contract from the execution data provider or AztecNode. If not found, class id
|
|
@@ -38,36 +36,26 @@ export async function readCurrentClassId(
|
|
|
38
36
|
return currentClassId;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
export async function
|
|
39
|
+
export async function syncScope(
|
|
42
40
|
contractAddress: AztecAddress,
|
|
43
41
|
contractStore: ContractStore,
|
|
44
42
|
functionToInvokeAfterSync: FunctionSelector | null,
|
|
45
43
|
utilityExecutor: (privateSyncCall: FunctionCall, scopes: AztecAddress[]) => Promise<any>,
|
|
46
|
-
noteStore: NoteStore,
|
|
47
|
-
aztecNode: AztecNode,
|
|
48
|
-
anchorBlockHeader: BlockHeader,
|
|
49
|
-
jobId: string,
|
|
50
44
|
scope: AztecAddress,
|
|
51
45
|
) {
|
|
52
46
|
// Protocol contracts don't have private state to sync
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
throw new Error(
|
|
57
|
-
'Forbidden `sync_state` invocation. `sync_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const noteService = new NoteService(noteStore, aztecNode, anchorBlockHeader, jobId);
|
|
62
|
-
const scopes: AztecAddress[] = [scope];
|
|
47
|
+
if (isProtocolContract(contractAddress)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
63
50
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
]);
|
|
51
|
+
const syncStateFunctionCall = await contractStore.getFunctionCall('sync_state', [scope], contractAddress);
|
|
52
|
+
if (functionToInvokeAfterSync && functionToInvokeAfterSync.equals(syncStateFunctionCall.selector)) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'Forbidden `sync_state` invocation. `sync_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
|
|
55
|
+
);
|
|
70
56
|
}
|
|
57
|
+
|
|
58
|
+
await utilityExecutor(syncStateFunctionCall, [scope]);
|
|
71
59
|
}
|
|
72
60
|
|
|
73
61
|
/**
|
|
@@ -4,6 +4,8 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
|
4
4
|
import type { CircuitSimulator } from '@aztec/simulator/client';
|
|
5
5
|
import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
|
|
6
6
|
|
|
7
|
+
import type { ExecutionHooks } from '../hooks/index.js';
|
|
8
|
+
|
|
7
9
|
export type PXECreationOptions = {
|
|
8
10
|
loggers?: { store?: Logger; pxe?: Logger; prover?: Logger };
|
|
9
11
|
/** Actor label to include in log output (e.g., 'pxe-0', 'pxe-test'). */
|
|
@@ -11,6 +13,8 @@ export type PXECreationOptions = {
|
|
|
11
13
|
proverOrOptions?: PrivateKernelProver | BBPrivateKernelProverOptions;
|
|
12
14
|
store?: AztecAsyncKVStore;
|
|
13
15
|
simulator?: CircuitSimulator;
|
|
16
|
+
/** Optional hooks to observe and influence contract execution. */
|
|
17
|
+
hooks?: ExecutionHooks;
|
|
14
18
|
};
|
|
15
19
|
|
|
16
20
|
/** Checks if the given value implements the PrivateKernelProver interface via duck-typing. */
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import type { EventSelector } from '@aztec/stdlib/abi';
|
|
4
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
-
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
3
|
+
import { computePrivateEventCommitment, siloNullifier } from '@aztec/stdlib/hash';
|
|
6
4
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
7
|
-
import type { BlockHeader,
|
|
5
|
+
import type { BlockHeader, IndexedTxEffect } from '@aztec/stdlib/tx';
|
|
8
6
|
|
|
7
|
+
import type { EventValidationRequest } from '../contract_function_simulator/noir-structs/event_validation_request.js';
|
|
9
8
|
import { PrivateEventStore } from '../storage/private_event_store/private_event_store.js';
|
|
10
9
|
|
|
11
10
|
export class EventService {
|
|
@@ -17,26 +16,62 @@ export class EventService {
|
|
|
17
16
|
private readonly log = createLogger('pxe:event_service'),
|
|
18
17
|
) {}
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Validates and stores a batch of private events against pre-fetched tx effects.
|
|
21
|
+
*
|
|
22
|
+
* @param requests - The events to validate and store.
|
|
23
|
+
* @param scope - The scope under which the events are being stored.
|
|
24
|
+
* @param txEffects - Pre-fetched tx effects keyed by `TxHash.toString()`. Must contain entries for every request's
|
|
25
|
+
* txHash; missing entries are treated as a node bug and cause an error.
|
|
26
|
+
*/
|
|
27
|
+
public async validateAndStoreEvents(
|
|
28
|
+
requests: EventValidationRequest[],
|
|
27
29
|
scope: AztecAddress,
|
|
30
|
+
txEffects: Map<string, IndexedTxEffect>,
|
|
28
31
|
): Promise<void> {
|
|
32
|
+
if (requests.length === 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
|
|
37
|
+
|
|
38
|
+
await Promise.all(requests.map(req => this.#validateAndStoreEvent(req, scope, txEffects, anchorBlockNumber)));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async #validateAndStoreEvent(
|
|
42
|
+
request: EventValidationRequest,
|
|
43
|
+
scope: AztecAddress,
|
|
44
|
+
txEffects: Map<string, IndexedTxEffect>,
|
|
45
|
+
anchorBlockNumber: number,
|
|
46
|
+
): Promise<void> {
|
|
47
|
+
const {
|
|
48
|
+
contractAddress,
|
|
49
|
+
eventTypeId: selector,
|
|
50
|
+
randomness,
|
|
51
|
+
serializedEvent: content,
|
|
52
|
+
eventCommitment,
|
|
53
|
+
txHash,
|
|
54
|
+
} = request;
|
|
55
|
+
|
|
56
|
+
// Defense-in-depth: the built-in private-event path derives this commitment from content before enqueueing, but
|
|
57
|
+
// unconstrained PXE-side code (e.g. a custom message handler) can reach this oracle with arbitrary
|
|
58
|
+
// (content, commitment) pairs. Without this check it could bind arbitrary content to a legitimate tx nullifier,
|
|
59
|
+
// causing PXE to surface fabricated event data.
|
|
60
|
+
const recomputedCommitment = await computePrivateEventCommitment(randomness, selector.toField(), content);
|
|
61
|
+
if (!recomputedCommitment.equals(eventCommitment)) {
|
|
62
|
+
this.log.warn(
|
|
63
|
+
`Skipping event whose content does not hash to the provided commitment. contract=${contractAddress}, selector=${selector}, eventCommitment=${eventCommitment}, txHash=${txHash}, recomputedCommitment=${recomputedCommitment}`,
|
|
64
|
+
);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
29
68
|
// While using 'latest' block number would be fine for private events since they cannot be accessed from Aztec.nr
|
|
30
69
|
// (and thus we're less concerned about being ahead of the synced block), we use the synced block number to
|
|
31
70
|
// maintain consistent behavior in the PXE. Additionally, events should never be ahead of the synced block here
|
|
32
71
|
// since `fetchTaggedLogs` only processes logs up to the synced block.
|
|
33
|
-
const
|
|
34
|
-
siloNullifier(contractAddress, eventCommitment),
|
|
35
|
-
this.aztecNode.getTxEffect(txHash),
|
|
36
|
-
]);
|
|
37
|
-
|
|
38
|
-
const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
|
|
72
|
+
const siloedEventCommitment = await siloNullifier(contractAddress, eventCommitment);
|
|
39
73
|
|
|
74
|
+
const txEffect = txEffects.get(txHash.toString());
|
|
40
75
|
if (!txEffect) {
|
|
41
76
|
// We error out instead of just logging a warning and skipping the event because this would indicate a bug. This
|
|
42
77
|
// is because the node has already served info about this tx either when obtaining the log (TxScopedL2Log contain
|