|
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'; |
@@ -28,7 +29,7 @@ import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs' |
28 | 29 | import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging'; |
29 | 30 | import type { NoteStatus } from '@aztec/stdlib/note'; |
30 | 31 | import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees'; |
31 | | -import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx'; |
| 32 | +import type { BlockHeader, Capsule, IndexedTxEffect, OffchainEffect, TxHash } from '@aztec/stdlib/tx'; |
32 | 33 |
|
33 | 34 | import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js'; |
34 | 35 | import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js'; |
@@ -639,36 +640,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra |
639 | 640 | eventValidationRequests: EventValidationRequest[], |
640 | 641 | scope: AztecAddress, |
641 | 642 | ) { |
642 | | - const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId); |
643 | | - const noteStorePromises = noteValidationRequests.map(request => |
644 | | - noteService.validateAndStoreNote( |
645 | | - request.contractAddress, |
646 | | - request.owner, |
647 | | - request.storageSlot, |
648 | | - request.randomness, |
649 | | - request.noteNonce, |
650 | | - request.content, |
651 | | - request.noteHash, |
652 | | - request.nullifier, |
653 | | - request.txHash, |
654 | | - scope, |
655 | | - ), |
656 | | - ); |
| 643 | + const txEffects = await this.#fetchTxEffects([ |
| 644 | + ...noteValidationRequests.map(r => r.txHash), |
| 645 | + ...eventValidationRequests.map(r => r.txHash), |
| 646 | + ]); |
657 | 647 |
|
| 648 | + const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId); |
658 | 649 | const eventService = new EventService(this.anchorBlockHeader, this.aztecNode, this.privateEventStore, this.jobId); |
659 | | - const eventStorePromises = eventValidationRequests.map(request => |
660 | | - eventService.validateAndStoreEvent( |
661 | | - request.contractAddress, |
662 | | - request.eventTypeId, |
663 | | - request.randomness, |
664 | | - request.serializedEvent, |
665 | | - request.eventCommitment, |
666 | | - request.txHash, |
667 | | - scope, |
668 | | - ), |
669 | | - ); |
670 | 650 |
|
671 | | - await Promise.all([...noteStorePromises, ...eventStorePromises]); |
| 651 | + await Promise.all([ |
| 652 | + noteService.validateAndStoreNotes(noteValidationRequests, scope, txEffects), |
| 653 | + eventService.validateAndStoreEvents(eventValidationRequests, scope, txEffects), |
| 654 | + ]); |
672 | 655 | } |
673 | 656 |
|
674 | 657 | public async getLogsByTag( |
@@ -976,6 +959,20 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra |
976 | 959 | return this.offchainEffects; |
977 | 960 | } |
978 | 961 |
|
| 962 | + /** |
| 963 | + * Fetches tx effects for the given hashes in parallel, deduplicating repeated hashes so each tx is only requested |
| 964 | + * once. Returns a map keyed by `TxHash.toString()`; hashes for which the node has no tx effect are omitted. |
| 965 | + */ |
| 966 | + async #fetchTxEffects(txHashes: TxHash[]): Promise<Map<string, IndexedTxEffect>> { |
| 967 | + const uniqueTxHashes = uniqueBy(txHashes, h => h.toString()); |
| 968 | + const fetched = await Promise.all(uniqueTxHashes.map(h => this.aztecNode.getTxEffect(h))); |
| 969 | + return new Map( |
| 970 | + uniqueTxHashes |
| 971 | + .map((h, i): [string, IndexedTxEffect | undefined] => [h.toString(), fetched[i]]) |
| 972 | + .filter((entry): entry is [string, IndexedTxEffect] => entry[1] !== undefined), |
| 973 | + ); |
| 974 | + } |
| 975 | + |
979 | 976 | /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */ |
980 | 977 | async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> { |
981 | 978 | const [response] = await Promise.all([ |
|
0 commit comments