@aztec/pxe 0.73.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2
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/index.js +3 -5
- package/dest/config/index.js +18 -21
- package/dest/config/package_info.js +4 -2
- package/dest/contract_data_oracle/index.js +69 -79
- package/dest/contract_data_oracle/private_functions_tree.js +44 -50
- package/dest/database/contracts/contract_artifact_db.js +3 -2
- package/dest/database/contracts/contract_instance_db.js +3 -2
- package/dest/database/index.js +0 -1
- package/dest/database/kv_pxe_database.js +243 -259
- package/dest/database/note_dao.js +28 -43
- package/dest/database/outgoing_note_dao.js +20 -34
- package/dest/database/pxe_database.js +4 -2
- package/dest/database/pxe_database_test_suite.js +296 -151
- package/dest/index.js +0 -1
- package/dest/kernel_oracle/index.js +9 -6
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +68 -66
- package/dest/kernel_prover/hints/index.js +0 -1
- package/dest/kernel_prover/index.js +0 -1
- package/dest/kernel_prover/kernel_prover.js +60 -65
- package/dest/kernel_prover/proving_data_oracle.js +4 -2
- package/dest/note_decryption_utils/add_public_values_to_payload.js +8 -9
- package/dest/pxe_http/index.js +0 -1
- package/dest/pxe_http/pxe_http_server.js +8 -6
- package/dest/pxe_service/error_enriching.js +10 -13
- package/dest/pxe_service/index.js +0 -1
- package/dest/pxe_service/pxe_service.js +283 -288
- package/dest/pxe_service/test/pxe_test_suite.js +40 -27
- package/dest/simulator/index.js +1 -3
- package/dest/simulator_oracle/index.js +266 -231
- package/dest/simulator_oracle/tagging_utils.js +4 -6
- package/dest/synchronizer/index.js +0 -1
- package/dest/synchronizer/synchronizer.js +42 -39
- package/dest/utils/create_pxe_service.js +9 -9
- package/package.json +15 -15
- package/src/pxe_service/pxe_service.ts +12 -14
- package/src/synchronizer/synchronizer.ts +5 -2
- package/dest/bin/index.d.ts +0 -3
- package/dest/bin/index.d.ts.map +0 -1
- package/dest/config/index.d.ts +0 -46
- package/dest/config/index.d.ts.map +0 -1
- package/dest/config/package_info.d.ts +0 -5
- package/dest/config/package_info.d.ts.map +0 -1
- package/dest/contract_data_oracle/index.d.ts +0 -104
- package/dest/contract_data_oracle/index.d.ts.map +0 -1
- package/dest/contract_data_oracle/private_functions_tree.d.ts +0 -65
- package/dest/contract_data_oracle/private_functions_tree.d.ts.map +0 -1
- package/dest/database/contracts/contract_artifact_db.d.ts +0 -20
- package/dest/database/contracts/contract_artifact_db.d.ts.map +0 -1
- package/dest/database/contracts/contract_instance_db.d.ts +0 -19
- package/dest/database/contracts/contract_instance_db.d.ts.map +0 -1
- package/dest/database/index.d.ts +0 -3
- package/dest/database/index.d.ts.map +0 -1
- package/dest/database/kv_pxe_database.d.ts +0 -55
- package/dest/database/kv_pxe_database.d.ts.map +0 -1
- package/dest/database/note_dao.d.ts +0 -103
- package/dest/database/note_dao.d.ts.map +0 -1
- package/dest/database/outgoing_note_dao.d.ts +0 -73
- package/dest/database/outgoing_note_dao.d.ts.map +0 -1
- package/dest/database/pxe_database.d.ts +0 -216
- package/dest/database/pxe_database.d.ts.map +0 -1
- package/dest/database/pxe_database_test_suite.d.ts +0 -7
- package/dest/database/pxe_database_test_suite.d.ts.map +0 -1
- package/dest/index.d.ts +0 -15
- package/dest/index.d.ts.map +0 -1
- package/dest/kernel_oracle/index.d.ts +0 -34
- package/dest/kernel_oracle/index.d.ts.map +0 -1
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
- package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
- package/dest/kernel_prover/hints/index.d.ts +0 -2
- package/dest/kernel_prover/hints/index.d.ts.map +0 -1
- package/dest/kernel_prover/index.d.ts +0 -3
- package/dest/kernel_prover/index.d.ts.map +0 -1
- package/dest/kernel_prover/kernel_prover.d.ts +0 -38
- package/dest/kernel_prover/kernel_prover.d.ts.map +0 -1
- package/dest/kernel_prover/proving_data_oracle.d.ts +0 -65
- package/dest/kernel_prover/proving_data_oracle.d.ts.map +0 -1
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts +0 -10
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts.map +0 -1
- package/dest/pxe_http/index.d.ts +0 -2
- package/dest/pxe_http/index.d.ts.map +0 -1
- package/dest/pxe_http/pxe_http_server.d.ts +0 -16
- package/dest/pxe_http/pxe_http_server.d.ts.map +0 -1
- package/dest/pxe_service/error_enriching.d.ts +0 -11
- package/dest/pxe_service/error_enriching.d.ts.map +0 -1
- package/dest/pxe_service/index.d.ts +0 -4
- package/dest/pxe_service/index.d.ts.map +0 -1
- package/dest/pxe_service/pxe_service.d.ts +0 -97
- package/dest/pxe_service/pxe_service.d.ts.map +0 -1
- package/dest/pxe_service/test/pxe_test_suite.d.ts +0 -3
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +0 -1
- package/dest/simulator/index.d.ts +0 -10
- package/dest/simulator/index.d.ts.map +0 -1
- package/dest/simulator_oracle/index.d.ts +0 -129
- package/dest/simulator_oracle/index.d.ts.map +0 -1
- package/dest/simulator_oracle/tagging_utils.d.ts +0 -16
- package/dest/simulator_oracle/tagging_utils.d.ts.map +0 -1
- package/dest/synchronizer/index.d.ts +0 -2
- package/dest/synchronizer/index.d.ts.map +0 -1
- package/dest/synchronizer/synchronizer.d.ts +0 -29
- package/dest/synchronizer/synchronizer.d.ts.map +0 -1
- package/dest/utils/create_pxe_service.d.ts +0 -16
- package/dest/utils/create_pxe_service.d.ts.map +0 -1
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
var _KVPxeDatabase_instances, _KVPxeDatabase_synchronizedBlock, _KVPxeDatabase_completeAddresses, _KVPxeDatabase_completeAddressIndex, _KVPxeDatabase_addressBook, _KVPxeDatabase_authWitnesses, _KVPxeDatabase_capsules, _KVPxeDatabase_notes, _KVPxeDatabase_nullifiedNotes, _KVPxeDatabase_nullifierToNoteId, _KVPxeDatabase_nullifiersByBlockNumber, _KVPxeDatabase_nullifiedNotesToScope, _KVPxeDatabase_nullifiedNotesByContract, _KVPxeDatabase_nullifiedNotesByStorageSlot, _KVPxeDatabase_nullifiedNotesByTxHash, _KVPxeDatabase_nullifiedNotesByAddressPoint, _KVPxeDatabase_nullifiedNotesByNullifier, _KVPxeDatabase_contractArtifacts, _KVPxeDatabase_contractInstances, _KVPxeDatabase_db, _KVPxeDatabase_scopes, _KVPxeDatabase_notesToScope, _KVPxeDatabase_notesByContractAndScope, _KVPxeDatabase_notesByStorageSlotAndScope, _KVPxeDatabase_notesByTxHashAndScope, _KVPxeDatabase_notesByAddressPointAndScope, _KVPxeDatabase_taggingSecretIndexesForSenders, _KVPxeDatabase_taggingSecretIndexesForRecipients, _KVPxeDatabase_contractStore, _KVPxeDatabase_addScope, _KVPxeDatabase_getCompleteAddress, _KVPxeDatabase_setTaggingSecretsIndexes, _KVPxeDatabase_getTaggingSecretsIndexes;
|
|
2
|
-
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
1
|
import { MerkleTreeId, NoteStatus } from '@aztec/circuit-types';
|
|
4
|
-
import { AztecAddress, BlockHeader, CompleteAddress, SerializableContractInstance
|
|
2
|
+
import { AztecAddress, BlockHeader, CompleteAddress, SerializableContractInstance } from '@aztec/circuits.js';
|
|
5
3
|
import { FunctionSelector, FunctionType } from '@aztec/foundation/abi';
|
|
6
4
|
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
|
|
7
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -11,169 +9,174 @@ import { contractArtifactFromBuffer, contractArtifactToBuffer } from '@aztec/typ
|
|
|
11
9
|
import { NoteDao } from './note_dao.js';
|
|
12
10
|
/**
|
|
13
11
|
* A PXE database backed by LMDB.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
*/ export class KVPxeDatabase {
|
|
13
|
+
db;
|
|
14
|
+
#synchronizedBlock;
|
|
15
|
+
#completeAddresses;
|
|
16
|
+
#completeAddressIndex;
|
|
17
|
+
#addressBook;
|
|
18
|
+
#authWitnesses;
|
|
19
|
+
#capsules;
|
|
20
|
+
#notes;
|
|
21
|
+
#nullifiedNotes;
|
|
22
|
+
#nullifierToNoteId;
|
|
23
|
+
#nullifiersByBlockNumber;
|
|
24
|
+
#nullifiedNotesToScope;
|
|
25
|
+
#nullifiedNotesByContract;
|
|
26
|
+
#nullifiedNotesByStorageSlot;
|
|
27
|
+
#nullifiedNotesByTxHash;
|
|
28
|
+
#nullifiedNotesByAddressPoint;
|
|
29
|
+
#nullifiedNotesByNullifier;
|
|
30
|
+
#contractArtifacts;
|
|
31
|
+
#contractInstances;
|
|
32
|
+
#db;
|
|
33
|
+
#scopes;
|
|
34
|
+
#notesToScope;
|
|
35
|
+
#notesByContractAndScope;
|
|
36
|
+
#notesByStorageSlotAndScope;
|
|
37
|
+
#notesByTxHashAndScope;
|
|
38
|
+
#notesByAddressPointAndScope;
|
|
39
|
+
// Stores the last index used for each tagging secret, taking direction into account
|
|
40
|
+
// This is necessary to avoid reusing the same index for the same secret, which happens if
|
|
41
|
+
// sender and recipient are the same
|
|
42
|
+
#taggingSecretIndexesForSenders;
|
|
43
|
+
#taggingSecretIndexesForRecipients;
|
|
44
|
+
// Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${key}`
|
|
45
|
+
#contractStore;
|
|
46
|
+
debug;
|
|
47
|
+
constructor(db){
|
|
18
48
|
this.db = db;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
_KVPxeDatabase_taggingSecretIndexesForSenders.set(this, void 0);
|
|
48
|
-
_KVPxeDatabase_taggingSecretIndexesForRecipients.set(this, void 0);
|
|
49
|
-
// Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${key}`
|
|
50
|
-
_KVPxeDatabase_contractStore.set(this, void 0);
|
|
51
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_db, db, "f");
|
|
52
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_completeAddresses, db.openArray('complete_addresses'), "f");
|
|
53
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_completeAddressIndex, db.openMap('complete_address_index'), "f");
|
|
54
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_addressBook, db.openSet('address_book'), "f");
|
|
55
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_authWitnesses, db.openMap('auth_witnesses'), "f");
|
|
56
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_capsules, db.openArray('capsules'), "f");
|
|
57
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_contractArtifacts, db.openMap('contract_artifacts'), "f");
|
|
58
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_contractInstances, db.openMap('contracts_instances'), "f");
|
|
59
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_synchronizedBlock, db.openSingleton('header'), "f");
|
|
60
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notes, db.openMap('notes'), "f");
|
|
61
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotes, db.openMap('nullified_notes'), "f");
|
|
62
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifierToNoteId, db.openMap('nullifier_to_note'), "f");
|
|
63
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiersByBlockNumber, db.openMultiMap('nullifier_to_block_number'), "f");
|
|
64
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesToScope, db.openMultiMap('nullified_notes_to_scope'), "f");
|
|
65
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesByContract, db.openMultiMap('nullified_notes_by_contract'), "f");
|
|
66
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesByStorageSlot, db.openMultiMap('nullified_notes_by_storage_slot'), "f");
|
|
67
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesByTxHash, db.openMultiMap('nullified_notes_by_tx_hash'), "f");
|
|
68
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesByAddressPoint, db.openMultiMap('nullified_notes_by_address_point'), "f");
|
|
69
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_nullifiedNotesByNullifier, db.openMap('nullified_notes_by_nullifier'), "f");
|
|
70
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_scopes, db.openSet('scopes'), "f");
|
|
71
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notesToScope, db.openMultiMap('notes_to_scope'), "f");
|
|
72
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notesByContractAndScope, new Map(), "f");
|
|
73
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notesByStorageSlotAndScope, new Map(), "f");
|
|
74
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notesByTxHashAndScope, new Map(), "f");
|
|
75
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_notesByAddressPointAndScope, new Map(), "f");
|
|
76
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_taggingSecretIndexesForSenders, db.openMap('tagging_secret_indexes_for_senders'), "f");
|
|
77
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_taggingSecretIndexesForRecipients, db.openMap('tagging_secret_indexes_for_recipients'), "f");
|
|
78
|
-
__classPrivateFieldSet(this, _KVPxeDatabase_contractStore, db.openMap('contract_store'), "f");
|
|
49
|
+
this.#db = db;
|
|
50
|
+
this.#completeAddresses = db.openArray('complete_addresses');
|
|
51
|
+
this.#completeAddressIndex = db.openMap('complete_address_index');
|
|
52
|
+
this.#addressBook = db.openSet('address_book');
|
|
53
|
+
this.#authWitnesses = db.openMap('auth_witnesses');
|
|
54
|
+
this.#capsules = db.openArray('capsules');
|
|
55
|
+
this.#contractArtifacts = db.openMap('contract_artifacts');
|
|
56
|
+
this.#contractInstances = db.openMap('contracts_instances');
|
|
57
|
+
this.#synchronizedBlock = db.openSingleton('header');
|
|
58
|
+
this.#notes = db.openMap('notes');
|
|
59
|
+
this.#nullifiedNotes = db.openMap('nullified_notes');
|
|
60
|
+
this.#nullifierToNoteId = db.openMap('nullifier_to_note');
|
|
61
|
+
this.#nullifiersByBlockNumber = db.openMultiMap('nullifier_to_block_number');
|
|
62
|
+
this.#nullifiedNotesToScope = db.openMultiMap('nullified_notes_to_scope');
|
|
63
|
+
this.#nullifiedNotesByContract = db.openMultiMap('nullified_notes_by_contract');
|
|
64
|
+
this.#nullifiedNotesByStorageSlot = db.openMultiMap('nullified_notes_by_storage_slot');
|
|
65
|
+
this.#nullifiedNotesByTxHash = db.openMultiMap('nullified_notes_by_tx_hash');
|
|
66
|
+
this.#nullifiedNotesByAddressPoint = db.openMultiMap('nullified_notes_by_address_point');
|
|
67
|
+
this.#nullifiedNotesByNullifier = db.openMap('nullified_notes_by_nullifier');
|
|
68
|
+
this.#scopes = db.openSet('scopes');
|
|
69
|
+
this.#notesToScope = db.openMultiMap('notes_to_scope');
|
|
70
|
+
this.#notesByContractAndScope = new Map();
|
|
71
|
+
this.#notesByStorageSlotAndScope = new Map();
|
|
72
|
+
this.#notesByTxHashAndScope = new Map();
|
|
73
|
+
this.#notesByAddressPointAndScope = new Map();
|
|
74
|
+
this.#taggingSecretIndexesForSenders = db.openMap('tagging_secret_indexes_for_senders');
|
|
75
|
+
this.#taggingSecretIndexesForRecipients = db.openMap('tagging_secret_indexes_for_recipients');
|
|
76
|
+
this.#contractStore = db.openMap('contract_store');
|
|
79
77
|
this.debug = createDebugOnlyLogger('aztec:kv-pxe-database');
|
|
80
78
|
}
|
|
81
79
|
static async create(db) {
|
|
82
80
|
const pxeDB = new KVPxeDatabase(db);
|
|
83
|
-
for await (const scope of
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
for await (const scope of pxeDB.#scopes.entriesAsync()){
|
|
82
|
+
pxeDB.#notesByContractAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_contract`));
|
|
83
|
+
pxeDB.#notesByStorageSlotAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_storage_slot`));
|
|
84
|
+
pxeDB.#notesByTxHashAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_tx_hash`));
|
|
85
|
+
pxeDB.#notesByAddressPointAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_address_point`));
|
|
88
86
|
}
|
|
89
87
|
return pxeDB;
|
|
90
88
|
}
|
|
91
89
|
async getContract(address) {
|
|
92
90
|
const instance = await this.getContractInstance(address);
|
|
93
|
-
const artifact = instance &&
|
|
91
|
+
const artifact = instance && await this.getContractArtifact(instance?.contractClassId);
|
|
94
92
|
if (!instance || !artifact) {
|
|
95
93
|
return undefined;
|
|
96
94
|
}
|
|
97
|
-
return {
|
|
95
|
+
return {
|
|
96
|
+
...instance,
|
|
97
|
+
...artifact
|
|
98
|
+
};
|
|
98
99
|
}
|
|
99
100
|
async addContractArtifact(id, contract) {
|
|
100
|
-
const privateFunctions = contract.functions.filter(functionArtifact
|
|
101
|
-
const privateSelectors = await Promise.all(privateFunctions.map(async (privateFunctionArtifact)
|
|
101
|
+
const privateFunctions = contract.functions.filter((functionArtifact)=>functionArtifact.functionType === FunctionType.PRIVATE);
|
|
102
|
+
const privateSelectors = await Promise.all(privateFunctions.map(async (privateFunctionArtifact)=>(await FunctionSelector.fromNameAndParameters(privateFunctionArtifact.name, privateFunctionArtifact.parameters)).toString()));
|
|
102
103
|
if (privateSelectors.length !== new Set(privateSelectors).size) {
|
|
103
104
|
throw new Error('Repeated function selectors of private functions');
|
|
104
105
|
}
|
|
105
|
-
await
|
|
106
|
+
await this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract));
|
|
106
107
|
}
|
|
107
108
|
async getContractArtifact(id) {
|
|
108
|
-
const contract = await
|
|
109
|
+
const contract = await this.#contractArtifacts.getAsync(id.toString());
|
|
109
110
|
// TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
|
|
110
111
|
return contract && contractArtifactFromBuffer(Buffer.from(contract));
|
|
111
112
|
}
|
|
112
113
|
async addContractInstance(contract) {
|
|
113
|
-
await
|
|
114
|
+
await this.#contractInstances.set(contract.address.toString(), new SerializableContractInstance(contract).toBuffer());
|
|
114
115
|
}
|
|
115
116
|
async getContractInstance(address) {
|
|
116
|
-
const contract = await
|
|
117
|
+
const contract = await this.#contractInstances.getAsync(address.toString());
|
|
117
118
|
return contract && SerializableContractInstance.fromBuffer(contract).withAddress(address);
|
|
118
119
|
}
|
|
119
120
|
async getContractsAddresses() {
|
|
120
|
-
const keys = await toArray(
|
|
121
|
+
const keys = await toArray(this.#contractInstances.keysAsync());
|
|
121
122
|
return keys.map(AztecAddress.fromString);
|
|
122
123
|
}
|
|
123
124
|
async addAuthWitness(messageHash, witness) {
|
|
124
|
-
await
|
|
125
|
+
await this.#authWitnesses.set(messageHash.toString(), witness.map((w)=>w.toBuffer()));
|
|
125
126
|
}
|
|
126
127
|
async getAuthWitness(messageHash) {
|
|
127
|
-
const witness = await
|
|
128
|
-
return Promise.resolve(witness?.map(w
|
|
128
|
+
const witness = await this.#authWitnesses.getAsync(messageHash.toString());
|
|
129
|
+
return Promise.resolve(witness?.map((w)=>Fr.fromBuffer(w)));
|
|
129
130
|
}
|
|
130
131
|
async addCapsule(capsule) {
|
|
131
|
-
await
|
|
132
|
+
await this.#capsules.push(capsule.map((c)=>c.toBuffer()));
|
|
132
133
|
}
|
|
133
134
|
async popCapsule() {
|
|
134
|
-
const val = await
|
|
135
|
-
return val?.map(b
|
|
135
|
+
const val = await this.#capsules.pop();
|
|
136
|
+
return val?.map((b)=>Fr.fromBuffer(b));
|
|
136
137
|
}
|
|
137
138
|
async addNote(note, scope) {
|
|
138
|
-
await this.addNotes([
|
|
139
|
+
await this.addNotes([
|
|
140
|
+
note
|
|
141
|
+
], scope);
|
|
139
142
|
}
|
|
140
143
|
async addNotes(notes, scope = AztecAddress.ZERO) {
|
|
141
|
-
if (!
|
|
142
|
-
await
|
|
144
|
+
if (!await this.#scopes.hasAsync(scope.toString())) {
|
|
145
|
+
await this.#addScope(scope);
|
|
143
146
|
}
|
|
144
|
-
return this.db.transactionAsync(async ()
|
|
145
|
-
for (const dao of notes)
|
|
147
|
+
return this.db.transactionAsync(async ()=>{
|
|
148
|
+
for (const dao of notes){
|
|
146
149
|
// store notes by their index in the notes hash tree
|
|
147
150
|
// this provides the uniqueness we need to store individual notes
|
|
148
151
|
// and should also return notes in the order that they were created.
|
|
149
152
|
// Had we stored them by their nullifier, they would be returned in random order
|
|
150
153
|
const noteIndex = toBufferBE(dao.index, 32).toString('hex');
|
|
151
|
-
await
|
|
152
|
-
await
|
|
153
|
-
await
|
|
154
|
-
await
|
|
155
|
-
await
|
|
156
|
-
await
|
|
157
|
-
await
|
|
154
|
+
await this.#notes.set(noteIndex, dao.toBuffer());
|
|
155
|
+
await this.#notesToScope.set(noteIndex, scope.toString());
|
|
156
|
+
await this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
|
|
157
|
+
await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
|
|
158
|
+
await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
|
|
159
|
+
await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
|
|
160
|
+
await this.#notesByAddressPointAndScope.get(scope.toString()).set(dao.addressPoint.toString(), noteIndex);
|
|
158
161
|
}
|
|
159
162
|
});
|
|
160
163
|
}
|
|
161
164
|
removeNotesAfter(blockNumber) {
|
|
162
|
-
return this.db.transactionAsync(async ()
|
|
163
|
-
const notes = await toArray(
|
|
164
|
-
for (const note of notes)
|
|
165
|
+
return this.db.transactionAsync(async ()=>{
|
|
166
|
+
const notes = await toArray(this.#notes.valuesAsync());
|
|
167
|
+
for (const note of notes){
|
|
165
168
|
const noteDao = NoteDao.fromBuffer(note);
|
|
166
169
|
if (noteDao.l2BlockNumber > blockNumber) {
|
|
167
170
|
const noteIndex = toBufferBE(noteDao.index, 32).toString('hex');
|
|
168
|
-
await
|
|
169
|
-
await
|
|
170
|
-
await
|
|
171
|
-
const scopes = await toArray(
|
|
172
|
-
for (const scope of scopes)
|
|
173
|
-
await
|
|
174
|
-
await
|
|
175
|
-
await
|
|
176
|
-
await
|
|
171
|
+
await this.#notes.delete(noteIndex);
|
|
172
|
+
await this.#notesToScope.delete(noteIndex);
|
|
173
|
+
await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
|
|
174
|
+
const scopes = await toArray(this.#scopes.entriesAsync());
|
|
175
|
+
for (const scope of scopes){
|
|
176
|
+
await this.#notesByAddressPointAndScope.get(scope).deleteValue(noteDao.addressPoint.toString(), noteIndex);
|
|
177
|
+
await this.#notesByTxHashAndScope.get(scope).deleteValue(noteDao.txHash.toString(), noteIndex);
|
|
178
|
+
await this.#notesByContractAndScope.get(scope).deleteValue(noteDao.contractAddress.toString(), noteIndex);
|
|
179
|
+
await this.#notesByStorageSlotAndScope.get(scope).deleteValue(noteDao.storageSlot.toString(), noteIndex);
|
|
177
180
|
}
|
|
178
181
|
}
|
|
179
182
|
}
|
|
@@ -182,40 +185,40 @@ export class KVPxeDatabase {
|
|
|
182
185
|
async unnullifyNotesAfter(blockNumber) {
|
|
183
186
|
const nullifiersToUndo = [];
|
|
184
187
|
const currentBlockNumber = blockNumber + 1;
|
|
185
|
-
const maxBlockNumber =
|
|
186
|
-
for
|
|
187
|
-
nullifiersToUndo.push(...
|
|
188
|
+
const maxBlockNumber = await this.getBlockNumber() ?? currentBlockNumber;
|
|
189
|
+
for(let i = currentBlockNumber; i <= maxBlockNumber; i++){
|
|
190
|
+
nullifiersToUndo.push(...await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i)));
|
|
188
191
|
}
|
|
189
|
-
const notesIndexesToReinsert = await Promise.all(nullifiersToUndo.map(nullifier
|
|
190
|
-
const notNullNoteIndexes = notesIndexesToReinsert.filter(noteIndex
|
|
191
|
-
const nullifiedNoteBuffers = await Promise.all(notNullNoteIndexes.map(noteIndex
|
|
192
|
-
const noteDaos = nullifiedNoteBuffers
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
await this.db.transactionAsync(async () => {
|
|
196
|
-
for (const dao of noteDaos) {
|
|
192
|
+
const notesIndexesToReinsert = await Promise.all(nullifiersToUndo.map((nullifier)=>this.#nullifiedNotesByNullifier.getAsync(nullifier)));
|
|
193
|
+
const notNullNoteIndexes = notesIndexesToReinsert.filter((noteIndex)=>noteIndex != undefined);
|
|
194
|
+
const nullifiedNoteBuffers = await Promise.all(notNullNoteIndexes.map((noteIndex)=>this.#nullifiedNotes.getAsync(noteIndex)));
|
|
195
|
+
const noteDaos = nullifiedNoteBuffers.filter((buffer)=>buffer != undefined).map((buffer)=>NoteDao.fromBuffer(buffer));
|
|
196
|
+
await this.db.transactionAsync(async ()=>{
|
|
197
|
+
for (const dao of noteDaos){
|
|
197
198
|
const noteIndex = toBufferBE(dao.index, 32).toString('hex');
|
|
198
|
-
await
|
|
199
|
-
await
|
|
200
|
-
let scopes =
|
|
199
|
+
await this.#notes.set(noteIndex, dao.toBuffer());
|
|
200
|
+
await this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
|
|
201
|
+
let scopes = await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex)) ?? [];
|
|
201
202
|
if (scopes.length === 0) {
|
|
202
|
-
scopes = [
|
|
203
|
+
scopes = [
|
|
204
|
+
new AztecAddress(dao.addressPoint.x).toString()
|
|
205
|
+
];
|
|
203
206
|
}
|
|
204
|
-
for (const scope of scopes)
|
|
205
|
-
await
|
|
206
|
-
await
|
|
207
|
-
await
|
|
208
|
-
await
|
|
209
|
-
await
|
|
207
|
+
for (const scope of scopes){
|
|
208
|
+
await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
|
|
209
|
+
await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
|
|
210
|
+
await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
|
|
211
|
+
await this.#notesByAddressPointAndScope.get(scope.toString()).set(dao.addressPoint.toString(), noteIndex);
|
|
212
|
+
await this.#notesToScope.set(noteIndex, scope);
|
|
210
213
|
}
|
|
211
|
-
await
|
|
212
|
-
await
|
|
213
|
-
await
|
|
214
|
-
await
|
|
215
|
-
await
|
|
216
|
-
await
|
|
217
|
-
await
|
|
218
|
-
await
|
|
214
|
+
await this.#nullifiedNotes.delete(noteIndex);
|
|
215
|
+
await this.#nullifiedNotesToScope.delete(noteIndex);
|
|
216
|
+
await this.#nullifiersByBlockNumber.deleteValue(dao.l2BlockNumber, dao.siloedNullifier.toString());
|
|
217
|
+
await this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex);
|
|
218
|
+
await this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex);
|
|
219
|
+
await this.#nullifiedNotesByTxHash.deleteValue(dao.txHash.toString(), noteIndex);
|
|
220
|
+
await this.#nullifiedNotesByAddressPoint.deleteValue(dao.addressPoint.toString(), noteIndex);
|
|
221
|
+
await this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString());
|
|
219
222
|
}
|
|
220
223
|
});
|
|
221
224
|
}
|
|
@@ -223,46 +226,28 @@ export class KVPxeDatabase {
|
|
|
223
226
|
const publicKey = filter.owner ? await filter.owner.toAddressPoint() : undefined;
|
|
224
227
|
filter.status = filter.status ?? NoteStatus.ACTIVE;
|
|
225
228
|
const candidateNoteSources = [];
|
|
226
|
-
filter.scopes
|
|
229
|
+
filter.scopes ??= (await toArray(this.#scopes.entriesAsync())).map((addressString)=>AztecAddress.fromString(addressString));
|
|
227
230
|
const activeNoteIdsPerScope = [];
|
|
228
|
-
for (const scope of new Set(filter.scopes))
|
|
231
|
+
for (const scope of new Set(filter.scopes)){
|
|
229
232
|
const formattedScopeString = scope.toString();
|
|
230
|
-
if (!
|
|
233
|
+
if (!await this.#scopes.hasAsync(formattedScopeString)) {
|
|
231
234
|
throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
|
|
232
235
|
}
|
|
233
|
-
activeNoteIdsPerScope.push(publicKey
|
|
234
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_notesByAddressPointAndScope, "f").get(formattedScopeString).getValuesAsync(publicKey.toString()))
|
|
235
|
-
: filter.txHash
|
|
236
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_notesByTxHashAndScope, "f").get(formattedScopeString).getValuesAsync(filter.txHash.toString()))
|
|
237
|
-
: filter.contractAddress
|
|
238
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_notesByContractAndScope, "f")
|
|
239
|
-
.get(formattedScopeString)
|
|
240
|
-
.getValuesAsync(filter.contractAddress.toString()))
|
|
241
|
-
: filter.storageSlot
|
|
242
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_notesByStorageSlotAndScope, "f").get(formattedScopeString).getValuesAsync(filter.storageSlot.toString()))
|
|
243
|
-
: await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_notesByAddressPointAndScope, "f").get(formattedScopeString).valuesAsync()));
|
|
236
|
+
activeNoteIdsPerScope.push(publicKey ? await toArray(this.#notesByAddressPointAndScope.get(formattedScopeString).getValuesAsync(publicKey.toString())) : filter.txHash ? await toArray(this.#notesByTxHashAndScope.get(formattedScopeString).getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#notesByContractAndScope.get(formattedScopeString).getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#notesByStorageSlotAndScope.get(formattedScopeString).getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#notesByAddressPointAndScope.get(formattedScopeString).valuesAsync()));
|
|
244
237
|
}
|
|
245
238
|
candidateNoteSources.push({
|
|
246
239
|
ids: new Set(activeNoteIdsPerScope.flat()),
|
|
247
|
-
notes:
|
|
240
|
+
notes: this.#notes
|
|
248
241
|
});
|
|
249
242
|
if (filter.status == NoteStatus.ACTIVE_OR_NULLIFIED) {
|
|
250
243
|
candidateNoteSources.push({
|
|
251
|
-
ids: publicKey
|
|
252
|
-
|
|
253
|
-
: filter.txHash
|
|
254
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_nullifiedNotesByTxHash, "f").getValuesAsync(filter.txHash.toString()))
|
|
255
|
-
: filter.contractAddress
|
|
256
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_nullifiedNotesByContract, "f").getValuesAsync(filter.contractAddress.toString()))
|
|
257
|
-
: filter.storageSlot
|
|
258
|
-
? await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_nullifiedNotesByStorageSlot, "f").getValuesAsync(filter.storageSlot.toString()))
|
|
259
|
-
: await toArray(__classPrivateFieldGet(this, _KVPxeDatabase_nullifiedNotes, "f").keysAsync()),
|
|
260
|
-
notes: __classPrivateFieldGet(this, _KVPxeDatabase_nullifiedNotes, "f"),
|
|
244
|
+
ids: publicKey ? await toArray(this.#nullifiedNotesByAddressPoint.getValuesAsync(publicKey.toString())) : filter.txHash ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#nullifiedNotes.keysAsync()),
|
|
245
|
+
notes: this.#nullifiedNotes
|
|
261
246
|
});
|
|
262
247
|
}
|
|
263
248
|
const result = [];
|
|
264
|
-
for (const { ids, notes } of candidateNoteSources)
|
|
265
|
-
for (const id of ids)
|
|
249
|
+
for (const { ids, notes } of candidateNoteSources){
|
|
250
|
+
for (const id of ids){
|
|
266
251
|
const serializedNote = await notes.getAsync(id);
|
|
267
252
|
if (!serializedNote) {
|
|
268
253
|
continue;
|
|
@@ -292,91 +277,100 @@ export class KVPxeDatabase {
|
|
|
292
277
|
if (nullifiers.length === 0) {
|
|
293
278
|
return Promise.resolve([]);
|
|
294
279
|
}
|
|
295
|
-
return this.db.transactionAsync(async ()
|
|
280
|
+
return this.db.transactionAsync(async ()=>{
|
|
296
281
|
const nullifiedNotes = [];
|
|
297
|
-
for (const blockScopedNullifier of nullifiers)
|
|
282
|
+
for (const blockScopedNullifier of nullifiers){
|
|
298
283
|
const { data: nullifier, l2BlockNumber: blockNumber } = blockScopedNullifier;
|
|
299
|
-
const noteIndex = await
|
|
284
|
+
const noteIndex = await this.#nullifierToNoteId.getAsync(nullifier.toString());
|
|
300
285
|
if (!noteIndex) {
|
|
301
286
|
continue;
|
|
302
287
|
}
|
|
303
|
-
const noteBuffer = noteIndex ? await
|
|
288
|
+
const noteBuffer = noteIndex ? await this.#notes.getAsync(noteIndex) : undefined;
|
|
304
289
|
if (!noteBuffer) {
|
|
305
|
-
// note doesn't exist. Maybe it got nullified already
|
|
306
290
|
continue;
|
|
307
291
|
}
|
|
308
|
-
const noteScopes =
|
|
292
|
+
const noteScopes = await toArray(this.#notesToScope.getValuesAsync(noteIndex)) ?? [];
|
|
309
293
|
const note = NoteDao.fromBuffer(noteBuffer);
|
|
310
294
|
if (!note.addressPoint.equals(accountAddressPoint)) {
|
|
311
|
-
// tried to nullify someone else's note
|
|
312
295
|
continue;
|
|
313
296
|
}
|
|
314
297
|
nullifiedNotes.push(note);
|
|
315
|
-
await
|
|
316
|
-
await
|
|
317
|
-
const scopes = await toArray(
|
|
318
|
-
for (const scope of scopes)
|
|
319
|
-
await
|
|
320
|
-
await
|
|
321
|
-
await
|
|
322
|
-
await
|
|
298
|
+
await this.#notes.delete(noteIndex);
|
|
299
|
+
await this.#notesToScope.delete(noteIndex);
|
|
300
|
+
const scopes = await toArray(this.#scopes.entriesAsync());
|
|
301
|
+
for (const scope of scopes){
|
|
302
|
+
await this.#notesByAddressPointAndScope.get(scope).deleteValue(accountAddressPoint.toString(), noteIndex);
|
|
303
|
+
await this.#notesByTxHashAndScope.get(scope).deleteValue(note.txHash.toString(), noteIndex);
|
|
304
|
+
await this.#notesByContractAndScope.get(scope).deleteValue(note.contractAddress.toString(), noteIndex);
|
|
305
|
+
await this.#notesByStorageSlotAndScope.get(scope).deleteValue(note.storageSlot.toString(), noteIndex);
|
|
323
306
|
}
|
|
324
307
|
if (noteScopes !== undefined) {
|
|
325
|
-
for (const scope of noteScopes)
|
|
326
|
-
await
|
|
308
|
+
for (const scope of noteScopes){
|
|
309
|
+
await this.#nullifiedNotesToScope.set(noteIndex, scope);
|
|
327
310
|
}
|
|
328
311
|
}
|
|
329
|
-
await
|
|
330
|
-
await
|
|
331
|
-
await
|
|
332
|
-
await
|
|
333
|
-
await
|
|
334
|
-
await
|
|
335
|
-
await
|
|
336
|
-
await
|
|
312
|
+
await this.#nullifiedNotes.set(noteIndex, note.toBuffer());
|
|
313
|
+
await this.#nullifiersByBlockNumber.set(blockNumber, nullifier.toString());
|
|
314
|
+
await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
|
|
315
|
+
await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
|
|
316
|
+
await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
|
|
317
|
+
await this.#nullifiedNotesByAddressPoint.set(note.addressPoint.toString(), noteIndex);
|
|
318
|
+
await this.#nullifiedNotesByNullifier.set(nullifier.toString(), noteIndex);
|
|
319
|
+
await this.#nullifierToNoteId.delete(nullifier.toString());
|
|
337
320
|
}
|
|
338
321
|
return nullifiedNotes;
|
|
339
322
|
});
|
|
340
323
|
}
|
|
341
324
|
async addNullifiedNote(note) {
|
|
342
325
|
const noteIndex = toBufferBE(note.index, 32).toString('hex');
|
|
343
|
-
await
|
|
344
|
-
await
|
|
345
|
-
await
|
|
346
|
-
await
|
|
347
|
-
await
|
|
326
|
+
await this.#nullifiedNotes.set(noteIndex, note.toBuffer());
|
|
327
|
+
await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
|
|
328
|
+
await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
|
|
329
|
+
await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
|
|
330
|
+
await this.#nullifiedNotesByAddressPoint.set(note.addressPoint.toString(), noteIndex);
|
|
348
331
|
}
|
|
349
332
|
async setHeader(header) {
|
|
350
|
-
await
|
|
333
|
+
await this.#synchronizedBlock.set(header.toBuffer());
|
|
351
334
|
}
|
|
352
335
|
async getBlockNumber() {
|
|
353
|
-
const headerBuffer = await
|
|
336
|
+
const headerBuffer = await this.#synchronizedBlock.getAsync();
|
|
354
337
|
if (!headerBuffer) {
|
|
355
338
|
return undefined;
|
|
356
339
|
}
|
|
357
340
|
return Number(BlockHeader.fromBuffer(headerBuffer).globalVariables.blockNumber.toBigInt());
|
|
358
341
|
}
|
|
359
342
|
async getBlockHeader() {
|
|
360
|
-
const headerBuffer = await
|
|
343
|
+
const headerBuffer = await this.#synchronizedBlock.getAsync();
|
|
361
344
|
if (!headerBuffer) {
|
|
362
345
|
throw new Error(`Header not set`);
|
|
363
346
|
}
|
|
364
347
|
return BlockHeader.fromBuffer(headerBuffer);
|
|
365
348
|
}
|
|
349
|
+
async #addScope(scope) {
|
|
350
|
+
const scopeString = scope.toString();
|
|
351
|
+
if (await this.#scopes.hasAsync(scopeString)) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
await this.#scopes.add(scopeString);
|
|
355
|
+
this.#notesByContractAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_contract`));
|
|
356
|
+
this.#notesByStorageSlotAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_storage_slot`));
|
|
357
|
+
this.#notesByTxHashAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_tx_hash`));
|
|
358
|
+
this.#notesByAddressPointAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_address_point`));
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
366
361
|
addCompleteAddress(completeAddress) {
|
|
367
|
-
return this.db.transactionAsync(async ()
|
|
368
|
-
await
|
|
362
|
+
return this.db.transactionAsync(async ()=>{
|
|
363
|
+
await this.#addScope(completeAddress.address);
|
|
369
364
|
const addressString = completeAddress.address.toString();
|
|
370
365
|
const buffer = completeAddress.toBuffer();
|
|
371
|
-
const existing = await
|
|
366
|
+
const existing = await this.#completeAddressIndex.getAsync(addressString);
|
|
372
367
|
if (existing === undefined) {
|
|
373
|
-
const index = await
|
|
374
|
-
await
|
|
375
|
-
await
|
|
368
|
+
const index = await this.#completeAddresses.lengthAsync();
|
|
369
|
+
await this.#completeAddresses.push(buffer);
|
|
370
|
+
await this.#completeAddressIndex.set(addressString, index);
|
|
376
371
|
return true;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const existingBuffer = await __classPrivateFieldGet(this, _KVPxeDatabase_completeAddresses, "f").atAsync(existing);
|
|
372
|
+
} else {
|
|
373
|
+
const existingBuffer = await this.#completeAddresses.atAsync(existing);
|
|
380
374
|
if (existingBuffer && Buffer.from(existingBuffer).equals(buffer)) {
|
|
381
375
|
return false;
|
|
382
376
|
}
|
|
@@ -384,73 +378,87 @@ export class KVPxeDatabase {
|
|
|
384
378
|
}
|
|
385
379
|
});
|
|
386
380
|
}
|
|
381
|
+
async #getCompleteAddress(address) {
|
|
382
|
+
const index = await this.#completeAddressIndex.getAsync(address.toString());
|
|
383
|
+
if (index === undefined) {
|
|
384
|
+
return undefined;
|
|
385
|
+
}
|
|
386
|
+
const value = await this.#completeAddresses.atAsync(index);
|
|
387
|
+
return value ? await CompleteAddress.fromBuffer(value) : undefined;
|
|
388
|
+
}
|
|
387
389
|
getCompleteAddress(account) {
|
|
388
|
-
return
|
|
390
|
+
return this.#getCompleteAddress(account);
|
|
389
391
|
}
|
|
390
392
|
async getCompleteAddresses() {
|
|
391
|
-
return await Promise.all((await toArray(
|
|
393
|
+
return await Promise.all((await toArray(this.#completeAddresses.valuesAsync())).map((v)=>CompleteAddress.fromBuffer(v)));
|
|
392
394
|
}
|
|
393
395
|
async addSenderAddress(address) {
|
|
394
|
-
if (await
|
|
396
|
+
if (await this.#addressBook.hasAsync(address.toString())) {
|
|
395
397
|
return false;
|
|
396
398
|
}
|
|
397
|
-
await
|
|
399
|
+
await this.#addressBook.add(address.toString());
|
|
398
400
|
return true;
|
|
399
401
|
}
|
|
400
402
|
async getSenderAddresses() {
|
|
401
|
-
return (await toArray(
|
|
403
|
+
return (await toArray(this.#addressBook.entriesAsync())).map(AztecAddress.fromString);
|
|
402
404
|
}
|
|
403
405
|
async removeSenderAddress(address) {
|
|
404
|
-
if (!
|
|
406
|
+
if (!await this.#addressBook.hasAsync(address.toString())) {
|
|
405
407
|
return false;
|
|
406
408
|
}
|
|
407
|
-
await
|
|
409
|
+
await this.#addressBook.delete(address.toString());
|
|
408
410
|
return true;
|
|
409
411
|
}
|
|
410
412
|
async estimateSize() {
|
|
411
|
-
const noteSize = (await this.getNotes({})).reduce((sum, note)
|
|
412
|
-
const authWitsSize = (await toArray(
|
|
413
|
-
const addressesSize =
|
|
413
|
+
const noteSize = (await this.getNotes({})).reduce((sum, note)=>sum + note.getSize(), 0);
|
|
414
|
+
const authWitsSize = (await toArray(this.#authWitnesses.valuesAsync())).reduce((sum, value)=>sum + value.length * Fr.SIZE_IN_BYTES, 0);
|
|
415
|
+
const addressesSize = await this.#completeAddresses.lengthAsync() * CompleteAddress.SIZE_IN_BYTES;
|
|
414
416
|
const treeRootsSize = Object.keys(MerkleTreeId).length * Fr.SIZE_IN_BYTES;
|
|
415
417
|
return noteSize + treeRootsSize + authWitsSize + addressesSize;
|
|
416
418
|
}
|
|
417
419
|
async setTaggingSecretsIndexesAsSender(indexedSecrets) {
|
|
418
|
-
await
|
|
420
|
+
await this.#setTaggingSecretsIndexes(indexedSecrets, this.#taggingSecretIndexesForSenders);
|
|
419
421
|
}
|
|
420
422
|
async setTaggingSecretsIndexesAsRecipient(indexedSecrets) {
|
|
421
|
-
await
|
|
423
|
+
await this.#setTaggingSecretsIndexes(indexedSecrets, this.#taggingSecretIndexesForRecipients);
|
|
424
|
+
}
|
|
425
|
+
async #setTaggingSecretsIndexes(indexedSecrets, storageMap) {
|
|
426
|
+
await Promise.all(indexedSecrets.map((indexedSecret)=>storageMap.set(indexedSecret.appTaggingSecret.toString(), indexedSecret.index)));
|
|
422
427
|
}
|
|
423
428
|
async getTaggingSecretsIndexesAsRecipient(appTaggingSecrets) {
|
|
424
|
-
return await
|
|
429
|
+
return await this.#getTaggingSecretsIndexes(appTaggingSecrets, this.#taggingSecretIndexesForRecipients);
|
|
425
430
|
}
|
|
426
431
|
async getTaggingSecretsIndexesAsSender(appTaggingSecrets) {
|
|
427
|
-
return await
|
|
432
|
+
return await this.#getTaggingSecretsIndexes(appTaggingSecrets, this.#taggingSecretIndexesForSenders);
|
|
433
|
+
}
|
|
434
|
+
#getTaggingSecretsIndexes(appTaggingSecrets, storageMap) {
|
|
435
|
+
return Promise.all(appTaggingSecrets.map(async (secret)=>await storageMap.getAsync(`${secret.toString()}`) ?? 0));
|
|
428
436
|
}
|
|
429
437
|
resetNoteSyncData() {
|
|
430
|
-
return this.db.transactionAsync(async ()
|
|
431
|
-
const recipients = await toArray(
|
|
432
|
-
await Promise.all(recipients.map(recipient
|
|
433
|
-
const senders = await toArray(
|
|
434
|
-
await Promise.all(senders.map(sender
|
|
438
|
+
return this.db.transactionAsync(async ()=>{
|
|
439
|
+
const recipients = await toArray(this.#taggingSecretIndexesForRecipients.keysAsync());
|
|
440
|
+
await Promise.all(recipients.map((recipient)=>this.#taggingSecretIndexesForRecipients.delete(recipient)));
|
|
441
|
+
const senders = await toArray(this.#taggingSecretIndexesForSenders.keysAsync());
|
|
442
|
+
await Promise.all(senders.map((sender)=>this.#taggingSecretIndexesForSenders.delete(sender)));
|
|
435
443
|
});
|
|
436
444
|
}
|
|
437
445
|
async dbStore(contractAddress, slot, values) {
|
|
438
|
-
await
|
|
446
|
+
await this.#contractStore.set(dbSlotToKey(contractAddress, slot), Buffer.concat(values.map((value)=>value.toBuffer())));
|
|
439
447
|
}
|
|
440
448
|
async dbLoad(contractAddress, slot) {
|
|
441
|
-
const dataBuffer = await
|
|
449
|
+
const dataBuffer = await this.#contractStore.getAsync(dbSlotToKey(contractAddress, slot));
|
|
442
450
|
if (!dataBuffer) {
|
|
443
451
|
this.debug(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
|
|
444
452
|
return null;
|
|
445
453
|
}
|
|
446
454
|
const values = [];
|
|
447
|
-
for
|
|
455
|
+
for(let i = 0; i < dataBuffer.length; i += Fr.SIZE_IN_BYTES){
|
|
448
456
|
values.push(Fr.fromBuffer(dataBuffer.subarray(i, i + Fr.SIZE_IN_BYTES)));
|
|
449
457
|
}
|
|
450
458
|
return values;
|
|
451
459
|
}
|
|
452
460
|
async dbDelete(contractAddress, slot) {
|
|
453
|
-
await
|
|
461
|
+
await this.#contractStore.delete(dbSlotToKey(contractAddress, slot));
|
|
454
462
|
}
|
|
455
463
|
async dbCopy(contractAddress, srcSlot, dstSlot, numEntries) {
|
|
456
464
|
// In order to support overlaping source and destination regions we need to check the relative positions of source
|
|
@@ -461,41 +469,17 @@ export class KVPxeDatabase {
|
|
|
461
469
|
if (srcSlot.lt(dstSlot)) {
|
|
462
470
|
indexes.reverse();
|
|
463
471
|
}
|
|
464
|
-
for (const i of indexes)
|
|
472
|
+
for (const i of indexes){
|
|
465
473
|
const currentSrcSlot = dbSlotToKey(contractAddress, srcSlot.add(new Fr(i)));
|
|
466
474
|
const currentDstSlot = dbSlotToKey(contractAddress, dstSlot.add(new Fr(i)));
|
|
467
|
-
const toCopy = await
|
|
475
|
+
const toCopy = await this.#contractStore.getAsync(currentSrcSlot);
|
|
468
476
|
if (!toCopy) {
|
|
469
477
|
throw new Error(`Attempted to copy empty slot ${currentSrcSlot} for contract ${contractAddress.toString()}`);
|
|
470
478
|
}
|
|
471
|
-
await
|
|
479
|
+
await this.#contractStore.set(currentDstSlot, toCopy);
|
|
472
480
|
}
|
|
473
481
|
}
|
|
474
482
|
}
|
|
475
|
-
_KVPxeDatabase_synchronizedBlock = new WeakMap(), _KVPxeDatabase_completeAddresses = new WeakMap(), _KVPxeDatabase_completeAddressIndex = new WeakMap(), _KVPxeDatabase_addressBook = new WeakMap(), _KVPxeDatabase_authWitnesses = new WeakMap(), _KVPxeDatabase_capsules = new WeakMap(), _KVPxeDatabase_notes = new WeakMap(), _KVPxeDatabase_nullifiedNotes = new WeakMap(), _KVPxeDatabase_nullifierToNoteId = new WeakMap(), _KVPxeDatabase_nullifiersByBlockNumber = new WeakMap(), _KVPxeDatabase_nullifiedNotesToScope = new WeakMap(), _KVPxeDatabase_nullifiedNotesByContract = new WeakMap(), _KVPxeDatabase_nullifiedNotesByStorageSlot = new WeakMap(), _KVPxeDatabase_nullifiedNotesByTxHash = new WeakMap(), _KVPxeDatabase_nullifiedNotesByAddressPoint = new WeakMap(), _KVPxeDatabase_nullifiedNotesByNullifier = new WeakMap(), _KVPxeDatabase_contractArtifacts = new WeakMap(), _KVPxeDatabase_contractInstances = new WeakMap(), _KVPxeDatabase_db = new WeakMap(), _KVPxeDatabase_scopes = new WeakMap(), _KVPxeDatabase_notesToScope = new WeakMap(), _KVPxeDatabase_notesByContractAndScope = new WeakMap(), _KVPxeDatabase_notesByStorageSlotAndScope = new WeakMap(), _KVPxeDatabase_notesByTxHashAndScope = new WeakMap(), _KVPxeDatabase_notesByAddressPointAndScope = new WeakMap(), _KVPxeDatabase_taggingSecretIndexesForSenders = new WeakMap(), _KVPxeDatabase_taggingSecretIndexesForRecipients = new WeakMap(), _KVPxeDatabase_contractStore = new WeakMap(), _KVPxeDatabase_instances = new WeakSet(), _KVPxeDatabase_addScope = async function _KVPxeDatabase_addScope(scope) {
|
|
476
|
-
const scopeString = scope.toString();
|
|
477
|
-
if (await __classPrivateFieldGet(this, _KVPxeDatabase_scopes, "f").hasAsync(scopeString)) {
|
|
478
|
-
return false;
|
|
479
|
-
}
|
|
480
|
-
await __classPrivateFieldGet(this, _KVPxeDatabase_scopes, "f").add(scopeString);
|
|
481
|
-
__classPrivateFieldGet(this, _KVPxeDatabase_notesByContractAndScope, "f").set(scopeString, __classPrivateFieldGet(this, _KVPxeDatabase_db, "f").openMultiMap(`${scopeString}:notes_by_contract`));
|
|
482
|
-
__classPrivateFieldGet(this, _KVPxeDatabase_notesByStorageSlotAndScope, "f").set(scopeString, __classPrivateFieldGet(this, _KVPxeDatabase_db, "f").openMultiMap(`${scopeString}:notes_by_storage_slot`));
|
|
483
|
-
__classPrivateFieldGet(this, _KVPxeDatabase_notesByTxHashAndScope, "f").set(scopeString, __classPrivateFieldGet(this, _KVPxeDatabase_db, "f").openMultiMap(`${scopeString}:notes_by_tx_hash`));
|
|
484
|
-
__classPrivateFieldGet(this, _KVPxeDatabase_notesByAddressPointAndScope, "f").set(scopeString, __classPrivateFieldGet(this, _KVPxeDatabase_db, "f").openMultiMap(`${scopeString}:notes_by_address_point`));
|
|
485
|
-
return true;
|
|
486
|
-
}, _KVPxeDatabase_getCompleteAddress = async function _KVPxeDatabase_getCompleteAddress(address) {
|
|
487
|
-
const index = await __classPrivateFieldGet(this, _KVPxeDatabase_completeAddressIndex, "f").getAsync(address.toString());
|
|
488
|
-
if (index === undefined) {
|
|
489
|
-
return undefined;
|
|
490
|
-
}
|
|
491
|
-
const value = await __classPrivateFieldGet(this, _KVPxeDatabase_completeAddresses, "f").atAsync(index);
|
|
492
|
-
return value ? await CompleteAddress.fromBuffer(value) : undefined;
|
|
493
|
-
}, _KVPxeDatabase_setTaggingSecretsIndexes = async function _KVPxeDatabase_setTaggingSecretsIndexes(indexedSecrets, storageMap) {
|
|
494
|
-
await Promise.all(indexedSecrets.map(indexedSecret => storageMap.set(indexedSecret.appTaggingSecret.toString(), indexedSecret.index)));
|
|
495
|
-
}, _KVPxeDatabase_getTaggingSecretsIndexes = function _KVPxeDatabase_getTaggingSecretsIndexes(appTaggingSecrets, storageMap) {
|
|
496
|
-
return Promise.all(appTaggingSecrets.map(async (secret) => (await storageMap.getAsync(`${secret.toString()}`)) ?? 0));
|
|
497
|
-
};
|
|
498
483
|
function dbSlotToKey(contractAddress, slot) {
|
|
499
484
|
return `${contractAddress.toString()}:${slot.toString()}`;
|
|
500
485
|
}
|
|
501
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia3ZfcHhlX2RhdGFiYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFiYXNlL2t2X3B4ZV9kYXRhYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBZ0IsWUFBWSxFQUFFLFVBQVUsRUFBb0IsTUFBTSxzQkFBc0IsQ0FBQztBQUNoRyxPQUFPLEVBQ0wsWUFBWSxFQUNaLFdBQVcsRUFDWCxlQUFlLEVBSWYsNEJBQTRCLEdBQzdCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUF5QixnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM5RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDN0QsT0FBTyxFQUFFLEVBQUUsRUFBYyxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNyRCxPQUFPLEVBQWMscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQVMxRSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUV4RixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR3hDOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUF3Q3hCLFlBQThCLEVBQXFCOztRQUFyQixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQXZDbkQsbURBQWdEO1FBQ2hELG1EQUE0QztRQUM1QyxzREFBcUQ7UUFDckQsNkNBQW9DO1FBQ3BDLCtDQUFnRDtRQUNoRCwwQ0FBcUM7UUFDckMsdUNBQXNDO1FBQ3RDLGdEQUErQztRQUMvQyxtREFBa0Q7UUFDbEQseURBQTZEO1FBRTdELHVEQUEyRDtRQUMzRCwwREFBOEQ7UUFDOUQsNkRBQWlFO1FBQ2pFLHdEQUE0RDtRQUM1RCw4REFBa0U7UUFDbEUsMkRBQTBEO1FBQzFELG1EQUFrRDtRQUNsRCxt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
|