@aztec/pxe 0.0.1-commit.8c0b8ff → 0.0.1-commit.8cb2d04d8
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 +13 -1
- package/dest/config/index.d.ts +2 -2
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +8 -15
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +3 -5
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +3 -2
- 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 -5
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +3 -4
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +2 -3
- 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 +6 -0
- package/dest/events/event_service.d.ts +1 -1
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +10 -1
- package/dest/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 +3 -2
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +12 -9
- 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 +1 -1
- 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 +1 -1
- package/package.json +16 -16
- package/src/block_synchronizer/block_synchronizer.ts +16 -2
- package/src/config/index.ts +3 -9
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/contract_function_simulator.ts +3 -5
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +17 -5
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +2 -3
- package/src/contract_function_simulator/pick_notes.ts +8 -0
- package/src/events/event_service.ts +13 -1
- package/src/private_kernel/private_kernel_oracle.ts +14 -14
- package/src/pxe.ts +10 -7
- 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 +3 -1
|
@@ -2,7 +2,7 @@ import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import type { EventSelector } from '@aztec/stdlib/abi';
|
|
4
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
-
import { siloNullifier } from '@aztec/stdlib/hash';
|
|
5
|
+
import { computePrivateEventCommitment, siloNullifier } from '@aztec/stdlib/hash';
|
|
6
6
|
import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
7
7
|
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
@@ -26,6 +26,18 @@ export class EventService {
|
|
|
26
26
|
txHash: TxHash,
|
|
27
27
|
scope: AztecAddress,
|
|
28
28
|
): Promise<void> {
|
|
29
|
+
// Defense-in-depth: the built-in private-event path derives this commitment from content before enqueueing, but
|
|
30
|
+
// unconstrained PXE-side code (e.g. a custom message handler) can reach this oracle with arbitrary
|
|
31
|
+
// (content, commitment) pairs. Without this check it could bind arbitrary content to a legitimate tx nullifier,
|
|
32
|
+
// causing PXE to surface fabricated event data.
|
|
33
|
+
const recomputedCommitment = await computePrivateEventCommitment(randomness, selector.toField(), content);
|
|
34
|
+
if (!recomputedCommitment.equals(eventCommitment)) {
|
|
35
|
+
this.log.warn(
|
|
36
|
+
`Skipping event whose content does not hash to the provided commitment. contract=${contractAddress}, selector=${selector}, eventCommitment=${eventCommitment}, txHash=${txHash}, recomputedCommitment=${recomputedCommitment}`,
|
|
37
|
+
);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
29
41
|
// While using 'latest' block number would be fine for private events since they cannot be accessed from Aztec.nr
|
|
30
42
|
// (and thus we're less concerned about being ahead of the synced block), we use the synced block number to
|
|
31
43
|
// maintain consistent behavior in the PXE. Additionally, events should never be ahead of the synced block here
|
|
@@ -7,13 +7,13 @@ import { getVKIndex, getVKSiblingPath } from '@aztec/noir-protocol-circuits-type
|
|
|
7
7
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
8
8
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
9
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
|
-
import { BlockHash } from '@aztec/stdlib/block';
|
|
11
10
|
import { type ContractInstanceWithAddress, computeSaltedInitializationHash } from '@aztec/stdlib/contract';
|
|
12
11
|
import { DelayedPublicMutableValues, DelayedPublicMutableValuesWithHash } from '@aztec/stdlib/delayed-public-mutable';
|
|
13
12
|
import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
|
|
14
13
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
15
14
|
import { UpdatedClassIdHints } from '@aztec/stdlib/kernel';
|
|
16
15
|
import type { NullifierMembershipWitness } from '@aztec/stdlib/trees';
|
|
16
|
+
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
17
17
|
import type { VerificationKeyAsFields } from '@aztec/stdlib/vks';
|
|
18
18
|
|
|
19
19
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
@@ -26,7 +26,7 @@ export class PrivateKernelOracle {
|
|
|
26
26
|
private contractStore: ContractStore,
|
|
27
27
|
private keyStore: KeyStore,
|
|
28
28
|
private node: AztecNode,
|
|
29
|
-
private
|
|
29
|
+
private blockHeader: BlockHeader,
|
|
30
30
|
) {}
|
|
31
31
|
|
|
32
32
|
/** Retrieves the preimage of a contract address from the registered contract instances db. */
|
|
@@ -80,22 +80,20 @@ export class PrivateKernelOracle {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/** Returns a membership witness with the sibling path and leaf index in our note hash tree. */
|
|
83
|
-
getNoteHashMembershipWitness(
|
|
84
|
-
|
|
83
|
+
async getNoteHashMembershipWitness(
|
|
84
|
+
noteHash: Fr,
|
|
85
|
+
): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
|
|
86
|
+
return this.node.getNoteHashMembershipWitness(await this.blockHeader.hash(), noteHash);
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/** Returns a membership witness with the sibling path and leaf index in our nullifier indexed merkle tree. */
|
|
88
|
-
getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
|
|
89
|
-
return this.node.getNullifierMembershipWitness(this.
|
|
90
|
+
async getNullifierMembershipWitness(nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
|
|
91
|
+
return this.node.getNullifierMembershipWitness(await this.blockHeader.hash(), nullifier);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
/** Returns the root of our note hash merkle tree. */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!header) {
|
|
96
|
-
throw new Error(`No block header found for block hash ${this.blockHash}`);
|
|
97
|
-
}
|
|
98
|
-
return header.state.partial.noteHashTree.root;
|
|
95
|
+
getNoteHashTreeRoot(): Fr {
|
|
96
|
+
return this.blockHeader.state.partial.noteHashTree.root;
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
/**
|
|
@@ -126,14 +124,16 @@ export class PrivateKernelOracle {
|
|
|
126
124
|
ProtocolContractAddress.ContractInstanceRegistry,
|
|
127
125
|
delayedPublicMutableHashSlot,
|
|
128
126
|
);
|
|
129
|
-
const
|
|
127
|
+
const blockHash = await this.blockHeader.hash();
|
|
128
|
+
|
|
129
|
+
const updatedClassIdWitness = await this.node.getPublicDataWitness(blockHash, hashLeafSlot);
|
|
130
130
|
|
|
131
131
|
if (!updatedClassIdWitness) {
|
|
132
132
|
throw new Error(`No public data tree witness found for ${hashLeafSlot}`);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
const readStorage = (storageSlot: Fr) =>
|
|
136
|
-
this.node.getPublicStorageAt(
|
|
136
|
+
this.node.getPublicStorageAt(blockHash, ProtocolContractAddress.ContractInstanceRegistry, storageSlot);
|
|
137
137
|
const delayedPublicMutableValues = await DelayedPublicMutableValues.readFromTree(
|
|
138
138
|
delayedPublicMutableSlot,
|
|
139
139
|
readStorage,
|
package/src/pxe.ts
CHANGED
|
@@ -148,6 +148,7 @@ export type PXECreateArgs = {
|
|
|
148
148
|
export class PXE {
|
|
149
149
|
private constructor(
|
|
150
150
|
private node: AztecNode,
|
|
151
|
+
private db: AztecAsyncKVStore,
|
|
151
152
|
private blockStateSynchronizer: BlockSynchronizer,
|
|
152
153
|
private keyStore: KeyStore,
|
|
153
154
|
private contractStore: ContractStore,
|
|
@@ -247,6 +248,7 @@ export class PXE {
|
|
|
247
248
|
|
|
248
249
|
const pxe = new PXE(
|
|
249
250
|
node,
|
|
251
|
+
store,
|
|
250
252
|
synchronizer,
|
|
251
253
|
keyStore,
|
|
252
254
|
contractStore,
|
|
@@ -484,8 +486,7 @@ export class PXE {
|
|
|
484
486
|
config: PrivateKernelExecutionProverConfig,
|
|
485
487
|
): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
486
488
|
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
487
|
-
const
|
|
488
|
-
const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
|
|
489
|
+
const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHeader);
|
|
489
490
|
const kernelTraceProver = new PrivateKernelExecutionProver(
|
|
490
491
|
kernelOracle,
|
|
491
492
|
proofCreator,
|
|
@@ -579,8 +580,8 @@ export class PXE {
|
|
|
579
580
|
if (wasAdded) {
|
|
580
581
|
this.log.info(`Added sender:\n ${sender.toString()}`);
|
|
581
582
|
// Wipe the entire sync cache: the new sender's tagged logs could contain notes/events for any contract, so
|
|
582
|
-
// all contracts must re-sync to discover them.
|
|
583
|
-
this.contractSyncService.wipe();
|
|
583
|
+
// all contracts must re-sync to discover them. Queued to avoid wiping while a job is in flight.
|
|
584
|
+
await this.#putInJobQueue(() => Promise.resolve(this.contractSyncService.wipe()));
|
|
584
585
|
} else {
|
|
585
586
|
this.log.info(`Sender:\n "${sender.toString()}"\n already registered.`);
|
|
586
587
|
}
|
|
@@ -1174,9 +1175,11 @@ export class PXE {
|
|
|
1174
1175
|
}
|
|
1175
1176
|
|
|
1176
1177
|
/**
|
|
1177
|
-
* Stops the PXE's job queue.
|
|
1178
|
+
* Stops the PXE's job queue and closes the backing store.
|
|
1178
1179
|
*/
|
|
1179
|
-
public stop(): Promise<void> {
|
|
1180
|
-
|
|
1180
|
+
public async stop(): Promise<void> {
|
|
1181
|
+
await this.jobQueue.end();
|
|
1182
|
+
await this.blockStateSynchronizer.stop();
|
|
1183
|
+
await this.db.close();
|
|
1181
1184
|
}
|
|
1182
1185
|
}
|
|
@@ -234,6 +234,10 @@ export class PrivateEventStore implements StagedStore {
|
|
|
234
234
|
* IMPORTANT: This method must be called within a transaction to ensure atomicity.
|
|
235
235
|
*/
|
|
236
236
|
public async rollback(blockNumber: number, synchedBlockNumber: number): Promise<void> {
|
|
237
|
+
if (this.#eventsForJob.size > 0) {
|
|
238
|
+
throw new Error('PXE private event store rollback is not allowed while jobs are running');
|
|
239
|
+
}
|
|
240
|
+
|
|
237
241
|
// First pass: collect all event IDs for all blocks, starting reads during iteration to keep tx alive.
|
|
238
242
|
const eventsByBlock: Map<number, { eventId: string; eventReadPromise: Promise<Buffer | undefined> }[]> = new Map();
|
|
239
243
|
|
|
@@ -49,7 +49,7 @@ export class StoredPrivateEvent {
|
|
|
49
49
|
const msgContentLength = reader.readNumber();
|
|
50
50
|
const msgContent = reader.readArray(msgContentLength, Fr);
|
|
51
51
|
const l2BlockNumber = reader.readNumber();
|
|
52
|
-
const l2BlockHash =
|
|
52
|
+
const l2BlockHash = BlockHash.fromBuffer(reader);
|
|
53
53
|
const txHash = TxHash.fromBuffer(reader);
|
|
54
54
|
const txIndexInBlock = reader.readNumber();
|
|
55
55
|
const eventIndexInTx = reader.readNumber();
|
|
@@ -113,7 +113,9 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
113
113
|
|
|
114
114
|
if (highestAgedIndex !== undefined && highestAgedIndex > highestFinalizedIndex) {
|
|
115
115
|
// This is just a sanity check as this should never happen.
|
|
116
|
-
throw new Error(
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Highest aged index (${highestAgedIndex}) must not exceed highest finalized index (${highestFinalizedIndex})`,
|
|
118
|
+
);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
await taggingStore.updateHighestFinalizedIndex(secret, highestFinalizedIndex, jobId);
|