@aztec/pxe 0.71.0 → 0.72.1
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/database/kv_pxe_database.d.ts +3 -3
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +3 -3
- package/dest/database/note_dao.d.ts +1 -1
- package/dest/database/note_dao.d.ts.map +1 -1
- package/dest/database/note_dao.js +3 -3
- package/dest/database/outgoing_note_dao.d.ts +1 -1
- package/dest/database/outgoing_note_dao.d.ts.map +1 -1
- package/dest/database/outgoing_note_dao.js +3 -3
- package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.js +70 -48
- package/dest/pxe_service/pxe_service.d.ts +6 -6
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +31 -28
- package/dest/pxe_service/test/pxe_test_suite.js +9 -9
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +30 -16
- package/package.json +15 -15
- package/src/database/kv_pxe_database.ts +6 -4
- package/src/database/note_dao.ts +5 -5
- package/src/database/outgoing_note_dao.ts +5 -5
- package/src/database/pxe_database_test_suite.ts +71 -56
- package/src/pxe_service/pxe_service.ts +47 -46
- package/src/pxe_service/test/pxe_test_suite.ts +8 -8
- package/src/simulator_oracle/index.ts +45 -17
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
MAX_NOTE_HASHES_PER_TX,
|
|
28
28
|
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
29
29
|
PrivateLog,
|
|
30
|
+
PublicLog,
|
|
30
31
|
computeAddressSecret,
|
|
31
32
|
computeTaggingSecretPoint,
|
|
32
33
|
} from '@aztec/circuits.js';
|
|
@@ -329,7 +330,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
329
330
|
async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
|
|
330
331
|
const senderCompleteAddress = await this.getCompleteAddress(sender);
|
|
331
332
|
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
|
|
332
|
-
const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient);
|
|
333
|
+
const secretPoint = await computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient);
|
|
333
334
|
// Silo the secret so it can't be used to track other app's notes
|
|
334
335
|
const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]);
|
|
335
336
|
return appSecret;
|
|
@@ -356,10 +357,12 @@ export class SimulatorOracle implements DBOracle {
|
|
|
356
357
|
const senders = [...(await this.db.getSenderAddresses()), ...(await this.keyStore.getAccounts())].filter(
|
|
357
358
|
(address, index, self) => index === self.findIndex(otherAddress => otherAddress.equals(address)),
|
|
358
359
|
);
|
|
359
|
-
const appTaggingSecrets =
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
360
|
+
const appTaggingSecrets = await Promise.all(
|
|
361
|
+
senders.map(async contact => {
|
|
362
|
+
const sharedSecret = await computeTaggingSecretPoint(recipientCompleteAddress, recipientIvsk, contact);
|
|
363
|
+
return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
|
|
364
|
+
}),
|
|
365
|
+
);
|
|
363
366
|
const indexes = await this.db.getTaggingSecretsIndexesAsRecipient(appTaggingSecrets);
|
|
364
367
|
return appTaggingSecrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i]));
|
|
365
368
|
}
|
|
@@ -499,15 +502,31 @@ export class SimulatorOracle implements DBOracle {
|
|
|
499
502
|
|
|
500
503
|
logsByTags.forEach((logsByTag, logIndex) => {
|
|
501
504
|
if (logsByTag.length > 0) {
|
|
505
|
+
// Check that public logs have the correct contract address
|
|
506
|
+
const checkedLogsbyTag = logsByTag.filter(
|
|
507
|
+
l => !l.isFromPublic || PublicLog.fromBuffer(l.logData).contractAddress.equals(contractAddress),
|
|
508
|
+
);
|
|
509
|
+
if (checkedLogsbyTag.length < logsByTag.length) {
|
|
510
|
+
const discarded = logsByTag.filter(
|
|
511
|
+
log => checkedLogsbyTag.find(filteredLog => filteredLog.equals(log)) === undefined,
|
|
512
|
+
);
|
|
513
|
+
this.log.warn(
|
|
514
|
+
`Discarded ${
|
|
515
|
+
logsByTag.length - checkedLogsbyTag.length
|
|
516
|
+
} public logs with mismatched contract address ${contractAddress}:`,
|
|
517
|
+
discarded.map(l => PublicLog.fromBuffer(l.logData)),
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
502
521
|
// The logs for the given tag exist so we store them for later processing
|
|
503
|
-
logsForRecipient.push(...
|
|
522
|
+
logsForRecipient.push(...checkedLogsbyTag);
|
|
504
523
|
|
|
505
524
|
// We retrieve the indexed tagging secret corresponding to the log as I need that to evaluate whether
|
|
506
525
|
// a new largest index have been found.
|
|
507
526
|
const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex];
|
|
508
527
|
const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()];
|
|
509
528
|
|
|
510
|
-
this.log.debug(`Found ${
|
|
529
|
+
this.log.debug(`Found ${checkedLogsbyTag.length} logs as recipient ${recipient}`, {
|
|
511
530
|
recipient,
|
|
512
531
|
secret: secretCorrespondingToLog.appTaggingSecret,
|
|
513
532
|
contractName,
|
|
@@ -588,7 +607,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
588
607
|
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
589
608
|
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
590
609
|
);
|
|
591
|
-
const addressSecret = computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM);
|
|
610
|
+
const addressSecret = await computeAddressSecret(recipientCompleteAddress.getPreaddress(), ivskM);
|
|
592
611
|
|
|
593
612
|
// Since we could have notes with the same index for different txs, we need
|
|
594
613
|
// to keep track of them scoping by txHash
|
|
@@ -597,8 +616,8 @@ export class SimulatorOracle implements DBOracle {
|
|
|
597
616
|
|
|
598
617
|
for (const scopedLog of scopedLogs) {
|
|
599
618
|
const payload = scopedLog.isFromPublic
|
|
600
|
-
? L1NotePayload.decryptAsIncomingFromPublic(scopedLog.logData, addressSecret)
|
|
601
|
-
: L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
|
|
619
|
+
? await L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret)
|
|
620
|
+
: await L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
|
|
602
621
|
|
|
603
622
|
if (!payload) {
|
|
604
623
|
this.log.verbose('Unable to decrypt log');
|
|
@@ -703,7 +722,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
703
722
|
})
|
|
704
723
|
.filter(nullifier => nullifier !== undefined) as InBlock<Fr>[];
|
|
705
724
|
|
|
706
|
-
const nullifiedNotes = await this.db.removeNullifiedNotes(foundNullifiers, recipient.toAddressPoint());
|
|
725
|
+
const nullifiedNotes = await this.db.removeNullifiedNotes(foundNullifiers, await recipient.toAddressPoint());
|
|
707
726
|
nullifiedNotes.forEach(noteDao => {
|
|
708
727
|
this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
|
|
709
728
|
contract: noteDao.contractAddress,
|
|
@@ -724,21 +743,30 @@ export class SimulatorOracle implements DBOracle {
|
|
|
724
743
|
txHash: Fr,
|
|
725
744
|
recipient: AztecAddress,
|
|
726
745
|
): Promise<NoteDao> {
|
|
746
|
+
// We need to validate that the note does indeed exist in the world state to avoid adding notes that are then
|
|
747
|
+
// impossible to prove.
|
|
748
|
+
|
|
727
749
|
const receipt = await this.aztecNode.getTxReceipt(new TxHash(txHash));
|
|
728
750
|
if (receipt === undefined) {
|
|
729
751
|
throw new Error(`Failed to fetch tx receipt for tx hash ${txHash} when searching for note hashes`);
|
|
730
752
|
}
|
|
731
|
-
const { blockNumber, blockHash } = receipt;
|
|
732
753
|
|
|
754
|
+
// Siloed and unique hashes are computed by us instead of relying on values sent by the contract to make sure
|
|
755
|
+
// we're not e.g. storing notes that belong to some other contract, which would constitute a security breach.
|
|
733
756
|
const uniqueNoteHash = computeUniqueNoteHash(nonce, siloNoteHash(contractAddress, noteHash));
|
|
734
757
|
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
735
758
|
|
|
759
|
+
// We store notes by their index in the global note hash tree, which has the convenient side effect of validating
|
|
760
|
+
// note existence in said tree. Note that while this is technically a historical query, we perform it at the latest
|
|
761
|
+
// locally synced block number which *should* be recent enough to be available. We avoid querying at 'latest' since
|
|
762
|
+
// we want to avoid accidentally processing notes that only exist ahead in time of the locally synced state.
|
|
763
|
+
const syncedBlockNumber = await this.db.getBlockNumber();
|
|
736
764
|
const uniqueNoteHashTreeIndex = (
|
|
737
|
-
await this.aztecNode.findLeavesIndexes(
|
|
765
|
+
await this.aztecNode.findLeavesIndexes(syncedBlockNumber!, MerkleTreeId.NOTE_HASH_TREE, [uniqueNoteHash])
|
|
738
766
|
)[0];
|
|
739
767
|
if (uniqueNoteHashTreeIndex === undefined) {
|
|
740
768
|
throw new Error(
|
|
741
|
-
`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present on the tree at block ${
|
|
769
|
+
`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present on the tree at block ${syncedBlockNumber} (from tx ${txHash})`,
|
|
742
770
|
);
|
|
743
771
|
}
|
|
744
772
|
|
|
@@ -750,10 +778,10 @@ export class SimulatorOracle implements DBOracle {
|
|
|
750
778
|
noteHash,
|
|
751
779
|
siloedNullifier,
|
|
752
780
|
new TxHash(txHash),
|
|
753
|
-
blockNumber!,
|
|
754
|
-
blockHash!.toString(),
|
|
781
|
+
receipt.blockNumber!,
|
|
782
|
+
receipt.blockHash!.toString(),
|
|
755
783
|
uniqueNoteHashTreeIndex,
|
|
756
|
-
recipient.toAddressPoint(),
|
|
784
|
+
await recipient.toAddressPoint(),
|
|
757
785
|
NoteSelector.empty(), // todo: remove
|
|
758
786
|
);
|
|
759
787
|
}
|