@aztec/pxe 0.0.1-commit.c7c42ec → 0.0.1-commit.f295ac2
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/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 +21 -13
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/benchmarked_node.d.ts +9 -0
- package/dest/contract_function_simulator/benchmarked_node.d.ts.map +1 -0
- package/dest/contract_function_simulator/benchmarked_node.js +77 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +8 -9
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +33 -16
- package/dest/contract_function_simulator/execution_note_cache.d.ts +18 -9
- package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
- package/dest/contract_function_simulator/execution_note_cache.js +45 -28
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -2
- 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 +5 -2
- package/dest/contract_function_simulator/noir-structs/utility_context.d.ts +4 -10
- package/dest/contract_function_simulator/noir-structs/utility_context.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/utility_context.js +7 -18
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +9 -8
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts +3 -1
- package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +4 -4
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.js +5 -5
- package/dest/contract_function_simulator/oracle/oracle.d.ts +6 -6
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +20 -19
- package/dest/contract_function_simulator/oracle/private_execution.d.ts +5 -9
- package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.js +11 -10
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +8 -18
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +10 -35
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +14 -12
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +54 -52
- 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 +10 -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 +10 -1
- package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
- 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 +11 -7
- package/dest/events/event_service.d.ts +4 -3
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +17 -19
- package/dest/events/private_event_filter_validator.d.ts +5 -5
- package/dest/events/private_event_filter_validator.d.ts.map +1 -1
- package/dest/events/private_event_filter_validator.js +5 -6
- package/dest/job_coordinator/job_coordinator.d.ts +74 -0
- package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
- package/dest/job_coordinator/job_coordinator.js +93 -0
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +5 -3
- package/dest/notes/note_service.d.ts +3 -3
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +23 -28
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +2 -2
- package/dest/private_kernel/hints/index.d.ts +2 -2
- package/dest/private_kernel/hints/index.d.ts.map +1 -1
- package/dest/private_kernel/hints/index.js +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +28 -0
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -0
- package/dest/private_kernel/hints/{build_private_kernel_reset_private_inputs.js → private_kernel_reset_private_inputs_builder.js} +13 -7
- 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 -5
- package/dest/private_kernel/private_kernel_oracle.d.ts +24 -28
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +90 -2
- package/dest/pxe.d.ts +8 -36
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +65 -87
- package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +132 -23
- package/dest/storage/contract_store/contract_store.d.ts +2 -1
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +12 -0
- package/dest/storage/note_store/note_store.d.ts +6 -5
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +89 -94
- package/dest/storage/private_event_store/private_event_store.d.ts +33 -6
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +139 -32
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts +15 -8
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/recipient_tagging_store.js +69 -12
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -9
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +110 -28
- package/dest/tagging/constants.d.ts +2 -0
- package/dest/tagging/constants.d.ts.map +1 -0
- package/dest/tagging/constants.js +10 -0
- package/dest/tagging/index.d.ts +2 -2
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +1 -10
- 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 +7 -7
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +2 -2
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +8 -8
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
- 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 +2 -2
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +4 -2
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +4 -2
- package/dest/tree_membership/tree_membership_service.d.ts +9 -11
- package/dest/tree_membership/tree_membership_service.d.ts.map +1 -1
- package/dest/tree_membership/tree_membership_service.js +25 -34
- package/package.json +18 -18
- package/src/block_synchronizer/block_synchronizer.ts +30 -12
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/benchmarked_node.ts +103 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +42 -16
- package/src/contract_function_simulator/execution_note_cache.ts +44 -25
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +4 -0
- package/src/contract_function_simulator/noir-structs/utility_context.ts +6 -25
- package/src/contract_function_simulator/oracle/interfaces.ts +8 -7
- package/src/contract_function_simulator/oracle/note_packing_utils.ts +6 -6
- package/src/contract_function_simulator/oracle/oracle.ts +24 -22
- package/src/contract_function_simulator/oracle/private_execution.ts +10 -19
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +13 -38
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +56 -50
- package/src/entrypoints/client/bundle/utils.ts +7 -1
- package/src/entrypoints/client/lazy/utils.ts +7 -2
- package/src/entrypoints/pxe_creation_options.ts +2 -1
- package/src/entrypoints/server/index.ts +1 -0
- package/src/entrypoints/server/utils.ts +11 -15
- package/src/events/event_service.ts +17 -21
- package/src/events/private_event_filter_validator.ts +3 -5
- package/src/job_coordinator/job_coordinator.ts +149 -0
- package/src/logs/log_service.ts +3 -1
- package/src/notes/note_service.ts +23 -29
- package/src/oracle_version.ts +2 -2
- package/src/private_kernel/hints/index.ts +1 -1
- package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +33 -22
- package/src/private_kernel/private_kernel_execution_prover.ts +3 -5
- package/src/private_kernel/private_kernel_oracle.ts +116 -36
- package/src/pxe.ts +98 -116
- package/src/storage/capsule_store/capsule_store.ts +159 -23
- package/src/storage/contract_store/contract_store.ts +20 -0
- package/src/storage/note_store/note_store.ts +98 -95
- package/src/storage/private_event_store/private_event_store.ts +199 -37
- package/src/storage/tagging_store/recipient_tagging_store.ts +89 -13
- package/src/storage/tagging_store/sender_tagging_store.ts +129 -28
- package/src/tagging/constants.ts +10 -0
- package/src/tagging/index.ts +1 -11
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +10 -6
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +8 -7
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +6 -2
- package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +4 -1
- package/src/tree_membership/tree_membership_service.ts +27 -42
- package/dest/contract_function_simulator/proxied_node.d.ts +0 -9
- package/dest/contract_function_simulator/proxied_node.d.ts.map +0 -1
- package/dest/contract_function_simulator/proxied_node.js +0 -27
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts +0 -46
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +0 -1
- package/dest/private_kernel/private_kernel_oracle_impl.js +0 -86
- package/dest/public_storage/public_storage_service.d.ts +0 -24
- package/dest/public_storage/public_storage_service.d.ts.map +0 -1
- package/dest/public_storage/public_storage_service.js +0 -26
- package/src/contract_function_simulator/proxied_node.ts +0 -33
- package/src/private_kernel/private_kernel_oracle_impl.ts +0 -133
- package/src/public_storage/public_storage_service.ts +0 -33
|
@@ -2,12 +2,13 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
|
-
import type {
|
|
5
|
+
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
|
|
6
6
|
import type { EventSelector } from '@aztec/stdlib/abi';
|
|
7
7
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
8
|
import { L2BlockHash } from '@aztec/stdlib/block';
|
|
9
9
|
import { type InTx, TxHash } from '@aztec/stdlib/tx';
|
|
10
10
|
|
|
11
|
+
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
11
12
|
import type { PackedPrivateEvent } from '../../pxe.js';
|
|
12
13
|
|
|
13
14
|
export type PrivateEventStoreFilter = {
|
|
@@ -19,48 +20,141 @@ export type PrivateEventStoreFilter = {
|
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
type PrivateEventEntry = {
|
|
23
|
+
randomness: Fr; // Note that this value is currently not being returned on queries and is therefore temporarily unused
|
|
22
24
|
msgContent: Buffer;
|
|
23
|
-
eventCommitmentIndex: number;
|
|
24
25
|
l2BlockNumber: number;
|
|
25
26
|
l2BlockHash: Buffer;
|
|
26
27
|
txHash: Buffer;
|
|
28
|
+
/** The index of the tx within the block, used for ordering events */
|
|
29
|
+
txIndexInBlock: number;
|
|
30
|
+
/** The index of the event within the tx (based on nullifier position), used for ordering events */
|
|
31
|
+
eventIndexInTx: number;
|
|
32
|
+
/** The lookup key for #eventsByContractScopeSelector, used for cleanup during rollback */
|
|
33
|
+
lookupKey: string;
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
type PrivateEventMetadata = InTx & {
|
|
30
37
|
contractAddress: AztecAddress;
|
|
31
38
|
scope: AztecAddress;
|
|
39
|
+
/** The index of the tx within the block */
|
|
40
|
+
txIndexInBlock: number;
|
|
41
|
+
/** The index of the event within the tx (based on nullifier position) */
|
|
42
|
+
eventIndexInTx: number;
|
|
32
43
|
};
|
|
33
44
|
|
|
34
45
|
/**
|
|
35
46
|
* Stores decrypted private event logs.
|
|
36
47
|
*/
|
|
37
|
-
export class PrivateEventStore {
|
|
48
|
+
export class PrivateEventStore implements StagedStore {
|
|
49
|
+
readonly storeName: string = 'private_event';
|
|
50
|
+
|
|
38
51
|
#store: AztecAsyncKVStore;
|
|
39
|
-
/**
|
|
40
|
-
#eventLogs:
|
|
41
|
-
/**
|
|
42
|
-
#
|
|
43
|
-
/**
|
|
44
|
-
#
|
|
52
|
+
/** Map storing the actual private event log entries, keyed by siloedEventCommitment */
|
|
53
|
+
#eventLogs: AztecAsyncMap<string, PrivateEventEntry>;
|
|
54
|
+
/** Multi-map from contractAddress_scope_eventSelector to siloedEventCommitment for efficient lookup */
|
|
55
|
+
#eventsByContractScopeSelector: AztecAsyncMultiMap<string, string>;
|
|
56
|
+
/** Multi-map from block number to siloedEventCommitment for rollback support */
|
|
57
|
+
#eventsByBlockNumber: AztecAsyncMultiMap<number, string>;
|
|
58
|
+
/** Map from siloedEventCommitment to boolean indicating if log has been seen. */
|
|
59
|
+
#seenLogs: AztecAsyncMap<string, boolean>;
|
|
60
|
+
|
|
61
|
+
/** jobId => eventId (event siloed nullifier) => PrivateEventEntry */
|
|
62
|
+
#eventLogsInJobStage: Map<string, Map<string, PrivateEventEntry>>;
|
|
45
63
|
|
|
46
64
|
logger = createLogger('private_event_store');
|
|
47
65
|
|
|
48
66
|
constructor(store: AztecAsyncKVStore) {
|
|
49
67
|
this.#store = store;
|
|
50
|
-
this.#eventLogs = this.#store.
|
|
51
|
-
this.#
|
|
68
|
+
this.#eventLogs = this.#store.openMap('private_event_logs');
|
|
69
|
+
this.#eventsByContractScopeSelector = this.#store.openMultiMap('events_by_contract_scope_selector');
|
|
52
70
|
this.#seenLogs = this.#store.openMap('seen_logs');
|
|
71
|
+
this.#eventsByBlockNumber = this.#store.openMultiMap('events_by_block_number');
|
|
72
|
+
|
|
73
|
+
this.#eventLogsInJobStage = new Map();
|
|
53
74
|
}
|
|
54
75
|
|
|
55
76
|
#keyFor(contractAddress: AztecAddress, scope: AztecAddress, eventSelector: EventSelector): string {
|
|
56
77
|
return `${contractAddress.toString()}_${scope.toString()}_${eventSelector.toString()}`;
|
|
57
78
|
}
|
|
58
79
|
|
|
80
|
+
async commit(jobId: string): Promise<void> {
|
|
81
|
+
await Promise.all(
|
|
82
|
+
[...this.#getEventLogsInJobStage(jobId).entries()].map(async ([eventId, eventEntry]) => {
|
|
83
|
+
this.logger.verbose('storing private event log (KV store)', eventEntry);
|
|
84
|
+
|
|
85
|
+
await Promise.all([
|
|
86
|
+
this.#eventLogs.set(eventId, eventEntry),
|
|
87
|
+
this.#eventsByContractScopeSelector.set(eventEntry.lookupKey, eventId),
|
|
88
|
+
this.#eventsByBlockNumber.set(eventEntry.l2BlockNumber, eventId),
|
|
89
|
+
this.#seenLogs.set(eventId, true),
|
|
90
|
+
]);
|
|
91
|
+
}),
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return this.discardStaged(jobId);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
discardStaged(jobId: string): Promise<void> {
|
|
98
|
+
this.#eventLogsInJobStage.delete(jobId);
|
|
99
|
+
return Promise.resolve();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#getEventLogsInJobStage(jobId: string): Map<string, PrivateEventEntry> {
|
|
103
|
+
let jobStage = this.#eventLogsInJobStage.get(jobId);
|
|
104
|
+
if (jobStage === undefined) {
|
|
105
|
+
jobStage = new Map();
|
|
106
|
+
this.#eventLogsInJobStage.set(jobId, jobStage);
|
|
107
|
+
}
|
|
108
|
+
return jobStage;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async #isSeenLog(jobId: string, eventId: string): Promise<boolean> {
|
|
112
|
+
const eventLogsInJobStage = this.#getEventLogsInJobStage(jobId).get(eventId);
|
|
113
|
+
return !!eventLogsInJobStage || !!(await this.#seenLogs.getAsync(eventId));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#addEventLogToStage(jobId: string, eventId: string, eventEntry: PrivateEventEntry) {
|
|
117
|
+
this.#getEventLogsInJobStage(jobId).set(eventId, eventEntry);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async #getEventSiloedNullifiers(
|
|
121
|
+
contractAddress: AztecAddress,
|
|
122
|
+
scope: AztecAddress,
|
|
123
|
+
eventSelector: EventSelector,
|
|
124
|
+
jobId?: string,
|
|
125
|
+
): Promise<string[]> {
|
|
126
|
+
const key = this.#keyFor(contractAddress, scope, eventSelector);
|
|
127
|
+
const eventSiloedNullifiersInStorage: string[] = [];
|
|
128
|
+
for await (const eventId of this.#eventsByContractScopeSelector.getValuesAsync(key)) {
|
|
129
|
+
eventSiloedNullifiersInStorage.push(eventId);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!jobId) {
|
|
133
|
+
return eventSiloedNullifiersInStorage;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const eventSiloedNullifiersInJobStage = new Set(
|
|
137
|
+
[...this.#getEventLogsInJobStage(jobId).entries()]
|
|
138
|
+
.filter(([_, entry]) => entry.lookupKey === key)
|
|
139
|
+
.map(([idx, _]) => idx),
|
|
140
|
+
);
|
|
141
|
+
return [...new Set(eventSiloedNullifiersInStorage).union(eventSiloedNullifiersInJobStage)];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async #getEventLogBySiloedNullifier(eventId: string, jobId?: string): Promise<PrivateEventEntry | undefined> {
|
|
145
|
+
if (jobId) {
|
|
146
|
+
return this.#getEventLogsInJobStage(jobId).get(eventId) ?? (await this.#eventLogs.getAsync(eventId));
|
|
147
|
+
} else {
|
|
148
|
+
return await this.#eventLogs.getAsync(eventId);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
59
152
|
/**
|
|
60
153
|
* Store a private event log.
|
|
61
154
|
* @param eventSelector - The event selector of the event.
|
|
155
|
+
* @param randomness - The randomness used for the event commitment.
|
|
62
156
|
* @param msgContent - The content of the event.
|
|
63
|
-
* @param
|
|
157
|
+
* @param siloedEventCommitment - The siloed event commitment (used as unique identifier).
|
|
64
158
|
* @param metadata
|
|
65
159
|
* contractAddress - The address of the contract that emitted the event.
|
|
66
160
|
* scope - The address to which the event is scoped.
|
|
@@ -69,38 +163,44 @@ export class PrivateEventStore {
|
|
|
69
163
|
*/
|
|
70
164
|
storePrivateEventLog(
|
|
71
165
|
eventSelector: EventSelector,
|
|
166
|
+
randomness: Fr,
|
|
72
167
|
msgContent: Fr[],
|
|
73
|
-
|
|
168
|
+
siloedEventCommitment: Fr,
|
|
74
169
|
metadata: PrivateEventMetadata,
|
|
170
|
+
jobId: string,
|
|
75
171
|
): Promise<void> {
|
|
76
|
-
const { contractAddress, scope, txHash, l2BlockNumber, l2BlockHash } = metadata;
|
|
172
|
+
const { contractAddress, scope, txHash, l2BlockNumber, l2BlockHash, txIndexInBlock, eventIndexInTx } = metadata;
|
|
77
173
|
|
|
78
174
|
return this.#store.transactionAsync(async () => {
|
|
79
175
|
const key = this.#keyFor(contractAddress, scope, eventSelector);
|
|
80
176
|
|
|
81
|
-
//
|
|
82
|
-
|
|
177
|
+
// The siloed event commitment is guaranteed to be unique as it's inserted into the nullifier tree. For this
|
|
178
|
+
// reason we use it as id.
|
|
179
|
+
const eventId = siloedEventCommitment.toString();
|
|
180
|
+
|
|
181
|
+
const hasBeenSeen = await this.#isSeenLog(jobId, eventId);
|
|
83
182
|
if (hasBeenSeen) {
|
|
84
|
-
this.logger.verbose('Ignoring duplicate event log', { txHash: txHash.toString(),
|
|
183
|
+
this.logger.verbose('Ignoring duplicate event log', { txHash: txHash.toString(), siloedEventCommitment });
|
|
85
184
|
return;
|
|
86
185
|
}
|
|
87
186
|
|
|
88
|
-
this.logger.verbose('storing private event log', {
|
|
187
|
+
this.logger.verbose('storing private event log (job stage)', {
|
|
188
|
+
contractAddress,
|
|
189
|
+
scope,
|
|
190
|
+
msgContent,
|
|
191
|
+
l2BlockNumber,
|
|
192
|
+
});
|
|
89
193
|
|
|
90
|
-
|
|
91
|
-
|
|
194
|
+
this.#addEventLogToStage(jobId, eventId, {
|
|
195
|
+
randomness,
|
|
92
196
|
msgContent: serializeToBuffer(msgContent),
|
|
93
197
|
l2BlockNumber,
|
|
94
198
|
l2BlockHash: l2BlockHash.toBuffer(),
|
|
95
|
-
eventCommitmentIndex,
|
|
96
199
|
txHash: txHash.toBuffer(),
|
|
200
|
+
txIndexInBlock,
|
|
201
|
+
eventIndexInTx,
|
|
202
|
+
lookupKey: key,
|
|
97
203
|
});
|
|
98
|
-
|
|
99
|
-
const existingIndices = (await this.#eventLogIndex.getAsync(key)) || [];
|
|
100
|
-
await this.#eventLogIndex.set(key, [...existingIndices, index]);
|
|
101
|
-
|
|
102
|
-
// Mark this log as seen using eventCommitmentIndex
|
|
103
|
-
await this.#seenLogs.set(eventCommitmentIndex, true);
|
|
104
204
|
});
|
|
105
205
|
}
|
|
106
206
|
|
|
@@ -112,21 +212,26 @@ export class PrivateEventStore {
|
|
|
112
212
|
* fromBlock: The block number to search from (inclusive).
|
|
113
213
|
* toBlock: The block number to search upto (exclusive).
|
|
114
214
|
* scope: - The addresses that decrypted the logs.
|
|
115
|
-
* @returns - The event log contents, augmented with metadata about
|
|
116
|
-
*
|
|
215
|
+
* @returns - The event log contents, augmented with metadata about the transaction and block in which the event was
|
|
216
|
+
* included.
|
|
117
217
|
*/
|
|
118
218
|
public async getPrivateEvents(
|
|
119
219
|
eventSelector: EventSelector,
|
|
120
220
|
filter: PrivateEventStoreFilter,
|
|
121
221
|
): Promise<PackedPrivateEvent[]> {
|
|
122
|
-
const events: Array<{
|
|
222
|
+
const events: Array<{
|
|
223
|
+
l2BlockNumber: number;
|
|
224
|
+
txIndexInBlock: number;
|
|
225
|
+
eventIndexInTx: number;
|
|
226
|
+
event: PackedPrivateEvent;
|
|
227
|
+
}> = [];
|
|
123
228
|
|
|
124
229
|
for (const scope of filter.scopes) {
|
|
125
|
-
const
|
|
126
|
-
|
|
230
|
+
const eventIds = await this.#getEventSiloedNullifiers(filter.contractAddress, scope, eventSelector);
|
|
231
|
+
|
|
232
|
+
for (const eventId of eventIds) {
|
|
233
|
+
const entry = await this.#getEventLogBySiloedNullifier(eventId);
|
|
127
234
|
|
|
128
|
-
for (const index of indices) {
|
|
129
|
-
const entry = await this.#eventLogs.atAsync(index);
|
|
130
235
|
if (!entry || entry.l2BlockNumber < filter.fromBlock || entry.l2BlockNumber >= filter.toBlock) {
|
|
131
236
|
continue;
|
|
132
237
|
}
|
|
@@ -143,7 +248,9 @@ export class PrivateEventStore {
|
|
|
143
248
|
}
|
|
144
249
|
|
|
145
250
|
events.push({
|
|
146
|
-
|
|
251
|
+
l2BlockNumber: entry.l2BlockNumber,
|
|
252
|
+
txIndexInBlock: entry.txIndexInBlock,
|
|
253
|
+
eventIndexInTx: entry.eventIndexInTx,
|
|
147
254
|
event: {
|
|
148
255
|
packedEvent: msgContent,
|
|
149
256
|
l2BlockNumber: BlockNumber(entry.l2BlockNumber),
|
|
@@ -155,8 +262,63 @@ export class PrivateEventStore {
|
|
|
155
262
|
}
|
|
156
263
|
}
|
|
157
264
|
|
|
158
|
-
// Sort by
|
|
159
|
-
events.sort((a, b) =>
|
|
265
|
+
// Sort by block number, then by tx index within block, then by event index within tx
|
|
266
|
+
events.sort((a, b) => {
|
|
267
|
+
if (a.l2BlockNumber !== b.l2BlockNumber) {
|
|
268
|
+
return a.l2BlockNumber - b.l2BlockNumber;
|
|
269
|
+
}
|
|
270
|
+
if (a.txIndexInBlock !== b.txIndexInBlock) {
|
|
271
|
+
return a.txIndexInBlock - b.txIndexInBlock;
|
|
272
|
+
}
|
|
273
|
+
return a.eventIndexInTx - b.eventIndexInTx;
|
|
274
|
+
});
|
|
160
275
|
return events.map(ev => ev.event);
|
|
161
276
|
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Rolls back private events that were stored after a given `blockNumber` and up to `synchedBlockNumber` (the block
|
|
280
|
+
* number up to which PXE managed to sync before the reorg happened).
|
|
281
|
+
*
|
|
282
|
+
* We don't need staged writes for a rollback since it's handled in the context of a blockchain rewind.
|
|
283
|
+
*
|
|
284
|
+
* Rollbacks are handled by the BlockSynchronizer, which runs a DB transaction across stores when it detects a
|
|
285
|
+
* re-org, including setting the new anchor block after rolling back.
|
|
286
|
+
*
|
|
287
|
+
* So if anything fails in the process of rolling back any store, all DB changes occurring during rollbacks will be
|
|
288
|
+
* lost and the anchor block will not be updated; which means this code will eventually need to run again
|
|
289
|
+
* (i.e.: PXE will detect it's basing it work on an invalid block hash, then which re-triggers rewind).
|
|
290
|
+
*
|
|
291
|
+
* For further details, refer to `BlockSynchronizer#handleBlockStreamEvent`.
|
|
292
|
+
*
|
|
293
|
+
* IMPORTANT: This method must be called within a transaction to ensure atomicity.
|
|
294
|
+
*/
|
|
295
|
+
public async rollback(blockNumber: number, synchedBlockNumber: number): Promise<void> {
|
|
296
|
+
let removedCount = 0;
|
|
297
|
+
|
|
298
|
+
for (let block = blockNumber + 1; block <= synchedBlockNumber; block++) {
|
|
299
|
+
const eventIds: string[] = [];
|
|
300
|
+
for await (const eventId of this.#eventsByBlockNumber.getValuesAsync(block)) {
|
|
301
|
+
eventIds.push(eventId);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (eventIds.length > 0) {
|
|
305
|
+
await this.#eventsByBlockNumber.delete(block);
|
|
306
|
+
|
|
307
|
+
for (const eventId of eventIds) {
|
|
308
|
+
const entry = await this.#eventLogs.getAsync(eventId);
|
|
309
|
+
if (!entry) {
|
|
310
|
+
throw new Error(`Event log not found for eventId ${eventId}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
await this.#eventLogs.delete(eventId);
|
|
314
|
+
await this.#seenLogs.delete(eventId);
|
|
315
|
+
await this.#eventsByContractScopeSelector.deleteValue(entry.lookupKey, eventId);
|
|
316
|
+
|
|
317
|
+
removedCount++;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
this.logger.verbose(`Rolled back ${removedCount} private events after block ${blockNumber}`);
|
|
323
|
+
}
|
|
162
324
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
2
2
|
import type { DirectionalAppTaggingSecret } from '@aztec/stdlib/logs';
|
|
3
3
|
|
|
4
|
+
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Data provider of tagging data used when syncing the logs as a recipient. The sender counterpart of this class
|
|
6
8
|
* is called SenderTaggingStore. We have the providers separate for the sender and recipient because
|
|
@@ -8,46 +10,120 @@ import type { DirectionalAppTaggingSecret } from '@aztec/stdlib/logs';
|
|
|
8
10
|
*
|
|
9
11
|
* @dev Chain reorgs do not need to be handled here because both the finalized and aged indexes refer to finalized
|
|
10
12
|
* blocks, which by definition cannot be affected by reorgs.
|
|
11
|
-
*
|
|
12
|
-
* TODO(benesjan): Relocate to yarn-project/pxe/src/storage/tagging_store
|
|
13
13
|
*/
|
|
14
|
-
export class RecipientTaggingStore {
|
|
14
|
+
export class RecipientTaggingStore implements StagedStore {
|
|
15
|
+
storeName: string = 'recipient_tagging';
|
|
16
|
+
|
|
15
17
|
#store: AztecAsyncKVStore;
|
|
16
18
|
|
|
17
19
|
#highestAgedIndex: AztecAsyncMap<string, number>;
|
|
18
20
|
#highestFinalizedIndex: AztecAsyncMap<string, number>;
|
|
19
21
|
|
|
22
|
+
// jobId => secret => number
|
|
23
|
+
#highestAgedIndexForJob: Map<string, Map<string, number>>;
|
|
24
|
+
|
|
25
|
+
// jobId => secret => number
|
|
26
|
+
#highestFinalizedIndexForJob: Map<string, Map<string, number>>;
|
|
27
|
+
|
|
20
28
|
constructor(store: AztecAsyncKVStore) {
|
|
21
29
|
this.#store = store;
|
|
22
30
|
|
|
23
31
|
this.#highestAgedIndex = this.#store.openMap('highest_aged_index');
|
|
24
32
|
this.#highestFinalizedIndex = this.#store.openMap('highest_finalized_index');
|
|
33
|
+
|
|
34
|
+
this.#highestAgedIndexForJob = new Map();
|
|
35
|
+
this.#highestFinalizedIndexForJob = new Map();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#getHighestAgedIndexForJob(jobId: string): Map<string, number> {
|
|
39
|
+
let highestAgedIndexForJob = this.#highestAgedIndexForJob.get(jobId);
|
|
40
|
+
if (!highestAgedIndexForJob) {
|
|
41
|
+
highestAgedIndexForJob = new Map();
|
|
42
|
+
this.#highestAgedIndexForJob.set(jobId, highestAgedIndexForJob);
|
|
43
|
+
}
|
|
44
|
+
return highestAgedIndexForJob;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async #readHighestAgedIndex(jobId: string, secret: string): Promise<number | undefined> {
|
|
48
|
+
return this.#getHighestAgedIndexForJob(jobId).get(secret) ?? (await this.#highestAgedIndex.getAsync(secret));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#writeHighestAgedIndex(jobId: string, secret: string, index: number) {
|
|
52
|
+
this.#getHighestAgedIndexForJob(jobId).set(secret, index);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#getHighestFinalizedIndexForJob(jobId: string): Map<string, number> {
|
|
56
|
+
let jobStagedHighestFinalizedIndex = this.#highestFinalizedIndexForJob.get(jobId);
|
|
57
|
+
if (!jobStagedHighestFinalizedIndex) {
|
|
58
|
+
jobStagedHighestFinalizedIndex = new Map();
|
|
59
|
+
this.#highestFinalizedIndexForJob.set(jobId, jobStagedHighestFinalizedIndex);
|
|
60
|
+
}
|
|
61
|
+
return jobStagedHighestFinalizedIndex;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async #readHighestFinalizedIndex(jobId: string, secret: string): Promise<number | undefined> {
|
|
65
|
+
return (
|
|
66
|
+
this.#getHighestFinalizedIndexForJob(jobId).get(secret) ?? (await this.#highestFinalizedIndex.getAsync(secret))
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#writeHighestFinalizedIndex(jobId: string, secret: string, index: number) {
|
|
71
|
+
this.#getHighestFinalizedIndexForJob(jobId).set(secret, index);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Writes all job-specific in-memory data to persistent storage.
|
|
76
|
+
*
|
|
77
|
+
* @remark This method must run in a DB transaction context. It's designed to be called from JobCoordinator#commitJob.
|
|
78
|
+
*/
|
|
79
|
+
async commit(jobId: string): Promise<void> {
|
|
80
|
+
const highestAgedIndexForJob = this.#highestAgedIndexForJob.get(jobId);
|
|
81
|
+
if (highestAgedIndexForJob) {
|
|
82
|
+
for (const [secret, index] of highestAgedIndexForJob.entries()) {
|
|
83
|
+
await this.#highestAgedIndex.set(secret, index);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const highestFinalizedIndexForJob = this.#highestFinalizedIndexForJob.get(jobId);
|
|
88
|
+
if (highestFinalizedIndexForJob) {
|
|
89
|
+
for (const [secret, index] of highestFinalizedIndexForJob.entries()) {
|
|
90
|
+
await this.#highestFinalizedIndex.set(secret, index);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return this.discardStaged(jobId);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
discardStaged(jobId: string): Promise<void> {
|
|
98
|
+
this.#highestAgedIndexForJob.delete(jobId);
|
|
99
|
+
this.#highestFinalizedIndexForJob.delete(jobId);
|
|
100
|
+
return Promise.resolve();
|
|
25
101
|
}
|
|
26
102
|
|
|
27
|
-
getHighestAgedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
|
|
28
|
-
return this.#
|
|
103
|
+
getHighestAgedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
|
|
104
|
+
return this.#readHighestAgedIndex(jobId, secret.toString());
|
|
29
105
|
}
|
|
30
106
|
|
|
31
|
-
async updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number): Promise<void> {
|
|
32
|
-
const currentIndex = await this.#
|
|
107
|
+
async updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
|
|
108
|
+
const currentIndex = await this.#readHighestAgedIndex(jobId, secret.toString());
|
|
33
109
|
if (currentIndex !== undefined && index <= currentIndex) {
|
|
34
110
|
// Log sync should never set a lower highest aged index.
|
|
35
111
|
throw new Error(`New highest aged index (${index}) must be higher than the current one (${currentIndex})`);
|
|
36
112
|
}
|
|
37
|
-
|
|
113
|
+
this.#writeHighestAgedIndex(jobId, secret.toString(), index);
|
|
38
114
|
}
|
|
39
115
|
|
|
40
|
-
getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
|
|
41
|
-
return this.#
|
|
116
|
+
getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
|
|
117
|
+
return this.#readHighestFinalizedIndex(jobId, secret.toString());
|
|
42
118
|
}
|
|
43
119
|
|
|
44
|
-
async updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number): Promise<void> {
|
|
45
|
-
const currentIndex = await this.#
|
|
120
|
+
async updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
|
|
121
|
+
const currentIndex = await this.#readHighestFinalizedIndex(jobId, secret.toString());
|
|
46
122
|
if (currentIndex !== undefined && index < currentIndex) {
|
|
47
123
|
// Log sync should never set a lower highest finalized index but it can happen that it would try to set the same
|
|
48
124
|
// one because we are loading logs from highest aged index + 1 and not from the highest finalized index.
|
|
49
125
|
throw new Error(`New highest finalized index (${index}) must be higher than the current one (${currentIndex})`);
|
|
50
126
|
}
|
|
51
|
-
|
|
127
|
+
this.#writeHighestFinalizedIndex(jobId, secret.toString(), index);
|
|
52
128
|
}
|
|
53
129
|
}
|