@aztec/pxe 0.77.1 → 0.78.0

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.
Files changed (180) hide show
  1. package/dest/bin/index.js +1 -1
  2. package/dest/config/index.d.ts +1 -0
  3. package/dest/config/index.d.ts.map +1 -1
  4. package/dest/config/index.js +1 -0
  5. package/dest/entrypoints/client/bundle/index.d.ts +6 -0
  6. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -0
  7. package/dest/entrypoints/client/bundle/index.js +5 -0
  8. package/dest/entrypoints/client/bundle/utils.d.ts +16 -0
  9. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -0
  10. package/dest/entrypoints/client/bundle/utils.js +30 -0
  11. package/dest/entrypoints/client/lazy/index.d.ts +6 -0
  12. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -0
  13. package/dest/entrypoints/client/lazy/index.js +5 -0
  14. package/dest/entrypoints/client/lazy/utils.d.ts +15 -0
  15. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -0
  16. package/dest/entrypoints/client/lazy/utils.js +29 -0
  17. package/dest/entrypoints/client/pxe_creation_options.d.ts +11 -0
  18. package/dest/entrypoints/client/pxe_creation_options.d.ts.map +1 -0
  19. package/dest/entrypoints/server/index.d.ts +7 -0
  20. package/dest/entrypoints/server/index.d.ts.map +1 -0
  21. package/dest/entrypoints/server/index.js +6 -0
  22. package/dest/{utils/create_pxe_service.d.ts → entrypoints/server/utils.d.ts} +4 -4
  23. package/dest/entrypoints/server/utils.d.ts.map +1 -0
  24. package/dest/{utils/create_pxe_service.js → entrypoints/server/utils.js} +5 -11
  25. package/dest/kernel_oracle/index.d.ts +2 -1
  26. package/dest/kernel_oracle/index.d.ts.map +1 -1
  27. package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
  28. package/dest/kernel_prover/kernel_prover.js +0 -24
  29. package/dest/note_decryption_utils/add_public_values_to_payload.d.ts +2 -2
  30. package/dest/note_decryption_utils/add_public_values_to_payload.d.ts.map +1 -1
  31. package/dest/note_decryption_utils/add_public_values_to_payload.js +3 -3
  32. package/dest/{pxe_data_provider → pxe_oracle_interface}/index.d.ts +17 -9
  33. package/dest/pxe_oracle_interface/index.d.ts.map +1 -0
  34. package/dest/{pxe_data_provider → pxe_oracle_interface}/index.js +104 -61
  35. package/dest/pxe_oracle_interface/tagging_utils.d.ts.map +1 -0
  36. package/dest/pxe_service/error_enriching.d.ts +3 -4
  37. package/dest/pxe_service/error_enriching.d.ts.map +1 -1
  38. package/dest/pxe_service/error_enriching.js +4 -4
  39. package/dest/pxe_service/pxe_service.d.ts +18 -14
  40. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  41. package/dest/pxe_service/pxe_service.js +118 -65
  42. package/dest/storage/address_data_provider/address_data_provider.d.ts +13 -0
  43. package/dest/storage/address_data_provider/address_data_provider.d.ts.map +1 -0
  44. package/dest/storage/address_data_provider/address_data_provider.js +50 -0
  45. package/dest/storage/address_data_provider/index.d.ts +2 -0
  46. package/dest/storage/address_data_provider/index.d.ts.map +1 -0
  47. package/dest/storage/address_data_provider/index.js +1 -0
  48. package/dest/storage/auth_witness_data_provider/auth_witness_data_provider.d.ts +11 -0
  49. package/dest/storage/auth_witness_data_provider/auth_witness_data_provider.d.ts.map +1 -0
  50. package/dest/storage/auth_witness_data_provider/auth_witness_data_provider.js +20 -0
  51. package/dest/storage/auth_witness_data_provider/index.d.ts +2 -0
  52. package/dest/storage/auth_witness_data_provider/index.d.ts.map +1 -0
  53. package/dest/storage/auth_witness_data_provider/index.js +1 -0
  54. package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts +16 -0
  55. package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts.map +1 -0
  56. package/dest/storage/capsule_data_provider/capsule_data_provider.js +57 -0
  57. package/dest/storage/capsule_data_provider/index.d.ts +2 -0
  58. package/dest/storage/capsule_data_provider/index.d.ts.map +1 -0
  59. package/dest/storage/capsule_data_provider/index.js +1 -0
  60. package/dest/{contract_data_provider → storage/contract_data_provider}/contract_data_provider.d.ts +38 -33
  61. package/dest/storage/contract_data_provider/contract_data_provider.d.ts.map +1 -0
  62. package/dest/{contract_data_provider → storage/contract_data_provider}/contract_data_provider.js +87 -42
  63. package/dest/storage/contract_data_provider/index.d.ts.map +1 -0
  64. package/dest/storage/contract_data_provider/private_functions_tree.d.ts.map +1 -0
  65. package/dest/storage/data_provider.d.ts +4 -0
  66. package/dest/storage/data_provider.d.ts.map +1 -0
  67. package/dest/storage/data_provider.js +1 -0
  68. package/dest/storage/index.d.ts +10 -0
  69. package/dest/storage/index.d.ts.map +1 -0
  70. package/dest/storage/index.js +9 -0
  71. package/dest/storage/note_data_provider/index.d.ts +3 -0
  72. package/dest/storage/note_data_provider/index.d.ts.map +1 -0
  73. package/dest/storage/note_data_provider/index.js +2 -0
  74. package/dest/storage/note_data_provider/note_dao.d.ts.map +1 -0
  75. package/dest/storage/note_data_provider/note_data_provider.d.ts +20 -0
  76. package/dest/storage/note_data_provider/note_data_provider.d.ts.map +1 -0
  77. package/dest/storage/note_data_provider/note_data_provider.js +249 -0
  78. package/dest/storage/sync_data_provider/index.d.ts +2 -0
  79. package/dest/storage/sync_data_provider/index.d.ts.map +1 -0
  80. package/dest/storage/sync_data_provider/index.js +1 -0
  81. package/dest/storage/sync_data_provider/sync_data_provider.d.ts +12 -0
  82. package/dest/storage/sync_data_provider/sync_data_provider.d.ts.map +1 -0
  83. package/dest/storage/sync_data_provider/sync_data_provider.js +29 -0
  84. package/dest/storage/tagging_data_provider/index.d.ts +2 -0
  85. package/dest/storage/tagging_data_provider/index.d.ts.map +1 -0
  86. package/dest/storage/tagging_data_provider/index.js +1 -0
  87. package/dest/storage/tagging_data_provider/tagging_data_provider.d.ts +18 -0
  88. package/dest/storage/tagging_data_provider/tagging_data_provider.d.ts.map +1 -0
  89. package/dest/storage/tagging_data_provider/tagging_data_provider.js +65 -0
  90. package/dest/synchronizer/synchronizer.d.ts +7 -3
  91. package/dest/synchronizer/synchronizer.d.ts.map +1 -1
  92. package/dest/synchronizer/synchronizer.js +16 -11
  93. package/dest/test/pxe_test_suite.d.ts.map +1 -0
  94. package/dest/{pxe_service/test → test}/pxe_test_suite.js +2 -6
  95. package/package.json +19 -26
  96. package/src/bin/index.ts +1 -1
  97. package/src/config/index.ts +2 -0
  98. package/src/entrypoints/client/bundle/index.ts +5 -0
  99. package/src/entrypoints/client/bundle/utils.ts +58 -0
  100. package/src/entrypoints/client/lazy/index.ts +5 -0
  101. package/src/entrypoints/client/lazy/utils.ts +53 -0
  102. package/src/entrypoints/client/pxe_creation_options.ts +7 -0
  103. package/src/entrypoints/server/index.ts +6 -0
  104. package/src/{utils/create_pxe_service.ts → entrypoints/server/utils.ts} +7 -18
  105. package/src/kernel_oracle/index.ts +1 -1
  106. package/src/kernel_prover/kernel_prover.ts +0 -46
  107. package/src/note_decryption_utils/add_public_values_to_payload.ts +4 -4
  108. package/src/{pxe_data_provider → pxe_oracle_interface}/index.ts +128 -96
  109. package/src/pxe_service/error_enriching.ts +8 -6
  110. package/src/pxe_service/pxe_service.ts +155 -89
  111. package/src/storage/address_data_provider/address_data_provider.ts +71 -0
  112. package/src/storage/address_data_provider/index.ts +1 -0
  113. package/src/storage/auth_witness_data_provider/auth_witness_data_provider.ts +34 -0
  114. package/src/storage/auth_witness_data_provider/index.ts +1 -0
  115. package/src/storage/capsule_data_provider/capsule_data_provider.ts +80 -0
  116. package/src/storage/capsule_data_provider/index.ts +1 -0
  117. package/src/{contract_data_provider → storage/contract_data_provider}/contract_data_provider.ts +128 -48
  118. package/src/storage/data_provider.ts +3 -0
  119. package/src/storage/index.ts +10 -0
  120. package/src/storage/note_data_provider/index.ts +2 -0
  121. package/src/storage/note_data_provider/note_data_provider.ts +345 -0
  122. package/src/storage/sync_data_provider/index.ts +1 -0
  123. package/src/storage/sync_data_provider/sync_data_provider.ts +40 -0
  124. package/src/storage/tagging_data_provider/index.ts +1 -0
  125. package/src/storage/tagging_data_provider/tagging_data_provider.ts +92 -0
  126. package/src/synchronizer/synchronizer.ts +15 -10
  127. package/src/{pxe_service/test → test}/pxe_test_suite.ts +2 -9
  128. package/dest/contract_data_provider/contract_data_provider.d.ts.map +0 -1
  129. package/dest/contract_data_provider/index.d.ts.map +0 -1
  130. package/dest/contract_data_provider/private_functions_tree.d.ts.map +0 -1
  131. package/dest/database/index.d.ts +0 -3
  132. package/dest/database/index.d.ts.map +0 -1
  133. package/dest/database/index.js +0 -2
  134. package/dest/database/interfaces/contract_artifact_db.d.ts +0 -20
  135. package/dest/database/interfaces/contract_artifact_db.d.ts.map +0 -1
  136. package/dest/database/interfaces/contract_artifact_db.js +0 -3
  137. package/dest/database/interfaces/contract_instance_db.d.ts +0 -20
  138. package/dest/database/interfaces/contract_instance_db.d.ts.map +0 -1
  139. package/dest/database/interfaces/contract_instance_db.js +0 -3
  140. package/dest/database/interfaces/index.d.ts +0 -4
  141. package/dest/database/interfaces/index.d.ts.map +0 -1
  142. package/dest/database/interfaces/pxe_database.d.ts +0 -211
  143. package/dest/database/interfaces/pxe_database.d.ts.map +0 -1
  144. package/dest/database/interfaces/pxe_database.js +0 -4
  145. package/dest/database/interfaces/pxe_database_test_suite.d.ts +0 -7
  146. package/dest/database/interfaces/pxe_database_test_suite.d.ts.map +0 -1
  147. package/dest/database/interfaces/pxe_database_test_suite.js +0 -557
  148. package/dest/database/kv_pxe_database.d.ts +0 -58
  149. package/dest/database/kv_pxe_database.d.ts.map +0 -1
  150. package/dest/database/kv_pxe_database.js +0 -480
  151. package/dest/database/note_dao.d.ts.map +0 -1
  152. package/dest/index.d.ts +0 -9
  153. package/dest/index.d.ts.map +0 -1
  154. package/dest/index.js +0 -8
  155. package/dest/pxe_data_provider/index.d.ts.map +0 -1
  156. package/dest/pxe_data_provider/tagging_utils.d.ts.map +0 -1
  157. package/dest/pxe_service/test/pxe_test_suite.d.ts.map +0 -1
  158. package/dest/utils/create_pxe_service.d.ts.map +0 -1
  159. package/src/database/index.ts +0 -2
  160. package/src/database/interfaces/contract_artifact_db.ts +0 -20
  161. package/src/database/interfaces/contract_instance_db.ts +0 -21
  162. package/src/database/interfaces/index.ts +0 -3
  163. package/src/database/interfaces/pxe_database.ts +0 -240
  164. package/src/database/interfaces/pxe_database_test_suite.ts +0 -558
  165. package/src/database/kv_pxe_database.ts +0 -670
  166. package/src/index.ts +0 -9
  167. /package/dest/{database/interfaces/index.js → entrypoints/client/pxe_creation_options.js} +0 -0
  168. /package/dest/{pxe_data_provider → pxe_oracle_interface}/tagging_utils.d.ts +0 -0
  169. /package/dest/{pxe_data_provider → pxe_oracle_interface}/tagging_utils.js +0 -0
  170. /package/dest/{contract_data_provider → storage/contract_data_provider}/index.d.ts +0 -0
  171. /package/dest/{contract_data_provider → storage/contract_data_provider}/index.js +0 -0
  172. /package/dest/{contract_data_provider → storage/contract_data_provider}/private_functions_tree.d.ts +0 -0
  173. /package/dest/{contract_data_provider → storage/contract_data_provider}/private_functions_tree.js +0 -0
  174. /package/dest/{database → storage/note_data_provider}/note_dao.d.ts +0 -0
  175. /package/dest/{database → storage/note_data_provider}/note_dao.js +0 -0
  176. /package/dest/{pxe_service/test → test}/pxe_test_suite.d.ts +0 -0
  177. /package/src/{pxe_data_provider → pxe_oracle_interface}/tagging_utils.ts +0 -0
  178. /package/src/{contract_data_provider → storage/contract_data_provider}/index.ts +0 -0
  179. /package/src/{contract_data_provider → storage/contract_data_provider}/private_functions_tree.ts +0 -0
  180. /package/src/{database → storage/note_data_provider}/note_dao.ts +0 -0
@@ -1,18 +1,26 @@
1
1
  import type { Fr } from '@aztec/foundation/fields';
2
+ import { toArray } from '@aztec/foundation/iterable';
2
3
  import type { MembershipWitness } from '@aztec/foundation/trees';
4
+ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
3
5
  import { ContractClassNotFoundError, ContractNotFoundError } from '@aztec/simulator/client';
4
6
  import {
5
7
  type ContractArtifact,
6
8
  type FunctionArtifact,
7
9
  type FunctionDebugMetadata,
8
- type FunctionSelector,
10
+ FunctionSelector,
11
+ FunctionType,
12
+ contractArtifactFromBuffer,
13
+ contractArtifactToBuffer,
9
14
  getFunctionDebugMetadata,
10
15
  } from '@aztec/stdlib/abi';
11
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
12
- import type { ContractClass, ContractInstance } from '@aztec/stdlib/contract';
16
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
17
+ import {
18
+ type ContractClass,
19
+ type ContractInstanceWithAddress,
20
+ SerializableContractInstance,
21
+ } from '@aztec/stdlib/contract';
13
22
 
14
- import type { ContractArtifactDatabase } from '../database/interfaces/contract_artifact_db.js';
15
- import type { ContractInstanceDatabase } from '../database/interfaces/contract_instance_db.js';
23
+ import type { DataProvider } from '../data_provider.js';
16
24
  import { PrivateFunctionsTree } from './private_functions_tree.js';
17
25
 
18
26
  /**
@@ -22,30 +30,133 @@ import { PrivateFunctionsTree } from './private_functions_tree.js';
22
30
  * to efficiently serve the requested data. It interacts with the ContractDatabase and AztecNode to fetch
23
31
  * the required information and facilitate cryptographic proof generation.
24
32
  */
25
- export class ContractDataProvider {
33
+ export class ContractDataProvider implements DataProvider {
26
34
  /** Map from contract class id to private function tree. */
27
- private contractClasses: Map<string, PrivateFunctionsTree> = new Map();
35
+ private contractClassesCache: Map<string, PrivateFunctionsTree> = new Map();
36
+
37
+ #contractArtifacts: AztecAsyncMap<string, Buffer>;
38
+ #contractInstances: AztecAsyncMap<string, Buffer>;
39
+
40
+ constructor(store: AztecAsyncKVStore) {
41
+ this.#contractArtifacts = store.openMap('contract_artifacts');
42
+ this.#contractInstances = store.openMap('contracts_instances');
43
+ }
44
+
45
+ // Setters
46
+
47
+ public async addContractArtifact(id: Fr, contract: ContractArtifact): Promise<void> {
48
+ const privateFunctions = contract.functions.filter(
49
+ functionArtifact => functionArtifact.functionType === FunctionType.PRIVATE,
50
+ );
51
+
52
+ const privateSelectors = await Promise.all(
53
+ privateFunctions.map(async privateFunctionArtifact =>
54
+ (
55
+ await FunctionSelector.fromNameAndParameters(privateFunctionArtifact.name, privateFunctionArtifact.parameters)
56
+ ).toString(),
57
+ ),
58
+ );
59
+
60
+ if (privateSelectors.length !== new Set(privateSelectors).size) {
61
+ throw new Error('Repeated function selectors of private functions');
62
+ }
63
+
64
+ await this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract));
65
+ }
66
+
67
+ async addContractInstance(contract: ContractInstanceWithAddress): Promise<void> {
68
+ await this.#contractInstances.set(
69
+ contract.address.toString(),
70
+ new SerializableContractInstance(contract).toBuffer(),
71
+ );
72
+ }
73
+
74
+ // Private getters
75
+
76
+ async #getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
77
+ const contract = await this.#contractInstances.getAsync(address.toString());
78
+ return contract && SerializableContractInstance.fromBuffer(contract).withAddress(address);
79
+ }
28
80
 
29
- constructor(private db: ContractArtifactDatabase & ContractInstanceDatabase) {}
81
+ async #getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
82
+ const contract = await this.#contractArtifacts.getAsync(id.toString());
83
+ // TODO(@spalladino): AztecAsyncMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from.
84
+ return contract && contractArtifactFromBuffer(Buffer.from(contract));
85
+ }
86
+
87
+ /**
88
+ * Retrieve or create a ContractTree instance based on the provided class id.
89
+ * If an existing tree with the same class id is found in the cache, it will be returned.
90
+ * Otherwise, a new ContractTree instance will be created using the contract data from the database
91
+ * and added to the cache before returning.
92
+ *
93
+ * @param classId - The class id of the contract for which the ContractTree is required.
94
+ * @returns A ContractTree instance associated with the specified contract address.
95
+ * @throws An Error if the contract is not found in the ContractDatabase.
96
+ */
97
+ private async getTreeForClassId(classId: Fr): Promise<PrivateFunctionsTree> {
98
+ if (!this.contractClassesCache.has(classId.toString())) {
99
+ const artifact = await this.#getContractArtifact(classId);
100
+ if (!artifact) {
101
+ throw new ContractClassNotFoundError(classId.toString());
102
+ }
103
+ const tree = await PrivateFunctionsTree.create(artifact);
104
+ this.contractClassesCache.set(classId.toString(), tree);
105
+ }
106
+ return this.contractClassesCache.get(classId.toString())!;
107
+ }
108
+
109
+ /**
110
+ * Retrieve or create a ContractTree instance based on the provided AztecAddress.
111
+ * If an existing tree with the same contract address is found in the cache, it will be returned.
112
+ * Otherwise, a new ContractTree instance will be created using the contract data from the database
113
+ * and added to the cache before returning.
114
+ *
115
+ * @param contractAddress - The AztecAddress of the contract for which the ContractTree is required.
116
+ * @returns A ContractTree instance associated with the specified contract address.
117
+ * @throws An Error if the contract is not found in the ContractDatabase.
118
+ */
119
+ private async getTreeForAddress(contractAddress: AztecAddress): Promise<PrivateFunctionsTree> {
120
+ const instance = await this.getContractInstance(contractAddress);
121
+ return this.getTreeForClassId(instance.currentContractClassId);
122
+ }
123
+
124
+ // Public getters
125
+
126
+ async getContractsAddresses(): Promise<AztecAddress[]> {
127
+ const keys = await toArray(this.#contractInstances.keysAsync());
128
+ return keys.map(AztecAddress.fromString);
129
+ }
30
130
 
31
131
  /** Returns a contract instance for a given address. Throws if not found. */
32
- public async getContractInstance(contractAddress: AztecAddress): Promise<ContractInstance> {
33
- const instance = await this.db.getContractInstance(contractAddress);
132
+ public async getContractInstance(contractAddress: AztecAddress): Promise<ContractInstanceWithAddress> {
133
+ const instance = await this.#getContractInstance(contractAddress);
34
134
  if (!instance) {
35
135
  throw new ContractNotFoundError(contractAddress.toString());
36
136
  }
37
137
  return instance;
38
138
  }
39
139
 
140
+ public async getContractArtifact(contractClassId: Fr): Promise<ContractArtifact> {
141
+ const tree = await this.getTreeForClassId(contractClassId);
142
+ return tree.getArtifact();
143
+ }
144
+
40
145
  /** Returns a contract class for a given class id. Throws if not found. */
41
146
  public async getContractClass(contractClassId: Fr): Promise<ContractClass> {
42
147
  const tree = await this.getTreeForClassId(contractClassId);
43
148
  return tree.getContractClass();
44
149
  }
45
150
 
46
- public async getContractArtifact(contractClassId: Fr): Promise<ContractArtifact> {
47
- const tree = await this.getTreeForClassId(contractClassId);
48
- return tree.getArtifact();
151
+ public async getContract(
152
+ address: AztecAddress,
153
+ ): Promise<(ContractInstanceWithAddress & ContractArtifact) | undefined> {
154
+ const instance = await this.getContractInstance(address);
155
+ const artifact = instance && (await this.getContractArtifact(instance?.currentContractClassId));
156
+ if (!instance || !artifact) {
157
+ return undefined;
158
+ }
159
+ return { ...instance, ...artifact };
49
160
  }
50
161
 
51
162
  /**
@@ -142,40 +253,9 @@ export class ContractDataProvider {
142
253
  return `${contractName}:${functionName}`;
143
254
  }
144
255
 
145
- /**
146
- * Retrieve or create a ContractTree instance based on the provided class id.
147
- * If an existing tree with the same class id is found in the cache, it will be returned.
148
- * Otherwise, a new ContractTree instance will be created using the contract data from the database
149
- * and added to the cache before returning.
150
- *
151
- * @param classId - The class id of the contract for which the ContractTree is required.
152
- * @returns A ContractTree instance associated with the specified contract address.
153
- * @throws An Error if the contract is not found in the ContractDatabase.
154
- */
155
- private async getTreeForClassId(classId: Fr): Promise<PrivateFunctionsTree> {
156
- if (!this.contractClasses.has(classId.toString())) {
157
- const artifact = await this.db.getContractArtifact(classId);
158
- if (!artifact) {
159
- throw new ContractClassNotFoundError(classId.toString());
160
- }
161
- const tree = await PrivateFunctionsTree.create(artifact);
162
- this.contractClasses.set(classId.toString(), tree);
163
- }
164
- return this.contractClasses.get(classId.toString())!;
165
- }
166
-
167
- /**
168
- * Retrieve or create a ContractTree instance based on the provided AztecAddress.
169
- * If an existing tree with the same contract address is found in the cache, it will be returned.
170
- * Otherwise, a new ContractTree instance will be created using the contract data from the database
171
- * and added to the cache before returning.
172
- *
173
- * @param contractAddress - The AztecAddress of the contract for which the ContractTree is required.
174
- * @returns A ContractTree instance associated with the specified contract address.
175
- * @throws An Error if the contract is not found in the ContractDatabase.
176
- */
177
- private async getTreeForAddress(contractAddress: AztecAddress): Promise<PrivateFunctionsTree> {
178
- const instance = await this.getContractInstance(contractAddress);
179
- return this.getTreeForClassId(instance.currentContractClassId);
256
+ public async getSize() {
257
+ return (await toArray(this.#contractInstances.valuesAsync()))
258
+ .concat(await toArray(this.#contractArtifacts.valuesAsync()))
259
+ .reduce((sum, value) => sum + value.length, 0);
180
260
  }
181
261
  }
@@ -0,0 +1,3 @@
1
+ export interface DataProvider {
2
+ getSize(): Promise<number>;
3
+ }
@@ -0,0 +1,10 @@
1
+ export * from './address_data_provider/index.js';
2
+ export * from './auth_witness_data_provider/index.js';
3
+ export * from './capsule_data_provider/index.js';
4
+ export * from './contract_data_provider/index.js';
5
+ export * from './note_data_provider/index.js';
6
+ export * from './sync_data_provider/index.js';
7
+ export * from './tagging_data_provider/index.js';
8
+ export * from './data_provider.js';
9
+
10
+ export const PXE_DATA_SCHEMA_VERSION = 2;
@@ -0,0 +1,2 @@
1
+ export { NoteDao } from './note_dao.js';
2
+ export { NoteDataProvider } from './note_data_provider.js';
@@ -0,0 +1,345 @@
1
+ import { toBufferBE } from '@aztec/foundation/bigint-buffer';
2
+ import type { Fr, Point } from '@aztec/foundation/fields';
3
+ import { toArray } from '@aztec/foundation/iterable';
4
+ import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
5
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
6
+ import type { InBlock } from '@aztec/stdlib/block';
7
+ import type { PublicKey } from '@aztec/stdlib/keys';
8
+ import { NoteStatus, type NotesFilter } from '@aztec/stdlib/note';
9
+
10
+ import type { DataProvider } from '../data_provider.js';
11
+ import { NoteDao } from './note_dao.js';
12
+
13
+ export class NoteDataProvider implements DataProvider {
14
+ #store: AztecAsyncKVStore;
15
+
16
+ #notes: AztecAsyncMap<string, Buffer>;
17
+ #nullifiedNotes: AztecAsyncMap<string, Buffer>;
18
+ #nullifierToNoteId: AztecAsyncMap<string, string>;
19
+ #nullifiersByBlockNumber: AztecAsyncMultiMap<number, string>;
20
+
21
+ #nullifiedNotesToScope: AztecAsyncMultiMap<string, string>;
22
+ #nullifiedNotesByContract: AztecAsyncMultiMap<string, string>;
23
+ #nullifiedNotesByStorageSlot: AztecAsyncMultiMap<string, string>;
24
+ #nullifiedNotesByTxHash: AztecAsyncMultiMap<string, string>;
25
+ #nullifiedNotesByAddressPoint: AztecAsyncMultiMap<string, string>;
26
+ #nullifiedNotesByNullifier: AztecAsyncMap<string, string>;
27
+
28
+ #scopes: AztecAsyncMap<string, true>;
29
+ #notesToScope: AztecAsyncMultiMap<string, string>;
30
+ #notesByContractAndScope: Map<string, AztecAsyncMultiMap<string, string>>;
31
+ #notesByStorageSlotAndScope: Map<string, AztecAsyncMultiMap<string, string>>;
32
+ #notesByTxHashAndScope: Map<string, AztecAsyncMultiMap<string, string>>;
33
+ #notesByAddressPointAndScope: Map<string, AztecAsyncMultiMap<string, string>>;
34
+
35
+ private constructor(store: AztecAsyncKVStore) {
36
+ this.#store = store;
37
+ this.#notes = store.openMap('notes');
38
+ this.#nullifiedNotes = store.openMap('nullified_notes');
39
+ this.#nullifierToNoteId = store.openMap('nullifier_to_note');
40
+ this.#nullifiersByBlockNumber = store.openMultiMap('nullifier_to_block_number');
41
+
42
+ this.#nullifiedNotesToScope = store.openMultiMap('nullified_notes_to_scope');
43
+ this.#nullifiedNotesByContract = store.openMultiMap('nullified_notes_by_contract');
44
+ this.#nullifiedNotesByStorageSlot = store.openMultiMap('nullified_notes_by_storage_slot');
45
+ this.#nullifiedNotesByTxHash = store.openMultiMap('nullified_notes_by_tx_hash');
46
+ this.#nullifiedNotesByAddressPoint = store.openMultiMap('nullified_notes_by_address_point');
47
+ this.#nullifiedNotesByNullifier = store.openMap('nullified_notes_by_nullifier');
48
+
49
+ this.#scopes = store.openMap('scopes');
50
+ this.#notesToScope = store.openMultiMap('notes_to_scope');
51
+ this.#notesByContractAndScope = new Map<string, AztecAsyncMultiMap<string, string>>();
52
+ this.#notesByStorageSlotAndScope = new Map<string, AztecAsyncMultiMap<string, string>>();
53
+ this.#notesByTxHashAndScope = new Map<string, AztecAsyncMultiMap<string, string>>();
54
+ this.#notesByAddressPointAndScope = new Map<string, AztecAsyncMultiMap<string, string>>();
55
+ }
56
+
57
+ public static async create(store: AztecAsyncKVStore): Promise<NoteDataProvider> {
58
+ const pxeDB = new NoteDataProvider(store);
59
+ for await (const scope of pxeDB.#scopes.keysAsync()) {
60
+ pxeDB.#notesByContractAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_contract`));
61
+ pxeDB.#notesByStorageSlotAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_storage_slot`));
62
+ pxeDB.#notesByTxHashAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_tx_hash`));
63
+ pxeDB.#notesByAddressPointAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_address_point`));
64
+ }
65
+ return pxeDB;
66
+ }
67
+
68
+ public async addScope(scope: AztecAddress): Promise<boolean> {
69
+ const scopeString = scope.toString();
70
+
71
+ if (await this.#scopes.hasAsync(scopeString)) {
72
+ return false;
73
+ }
74
+
75
+ await this.#scopes.set(scopeString, true);
76
+ this.#notesByContractAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_contract`));
77
+ this.#notesByStorageSlotAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_storage_slot`));
78
+ this.#notesByTxHashAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_tx_hash`));
79
+ this.#notesByAddressPointAndScope.set(
80
+ scopeString,
81
+ this.#store.openMultiMap(`${scopeString}:notes_by_address_point`),
82
+ );
83
+
84
+ return true;
85
+ }
86
+
87
+ async addNotes(notes: NoteDao[], scope: AztecAddress = AztecAddress.ZERO): Promise<void> {
88
+ if (!(await this.#scopes.hasAsync(scope.toString()))) {
89
+ await this.addScope(scope);
90
+ }
91
+
92
+ return this.#store.transactionAsync(async () => {
93
+ for (const dao of notes) {
94
+ // store notes by their index in the notes hash tree
95
+ // this provides the uniqueness we need to store individual notes
96
+ // and should also return notes in the order that they were created.
97
+ // Had we stored them by their nullifier, they would be returned in random order
98
+ const noteIndex = toBufferBE(dao.index, 32).toString('hex');
99
+ await this.#notes.set(noteIndex, dao.toBuffer());
100
+ await this.#notesToScope.set(noteIndex, scope.toString());
101
+ await this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
102
+
103
+ await this.#notesByContractAndScope.get(scope.toString())!.set(dao.contractAddress.toString(), noteIndex);
104
+ await this.#notesByStorageSlotAndScope.get(scope.toString())!.set(dao.storageSlot.toString(), noteIndex);
105
+ await this.#notesByTxHashAndScope.get(scope.toString())!.set(dao.txHash.toString(), noteIndex);
106
+ await this.#notesByAddressPointAndScope.get(scope.toString())!.set(dao.addressPoint.toString(), noteIndex);
107
+ }
108
+ });
109
+ }
110
+
111
+ public removeNotesAfter(blockNumber: number): Promise<void> {
112
+ return this.#store.transactionAsync(async () => {
113
+ const notes = await toArray(this.#notes.valuesAsync());
114
+ for (const note of notes) {
115
+ const noteDao = NoteDao.fromBuffer(note);
116
+ if (noteDao.l2BlockNumber > blockNumber) {
117
+ const noteIndex = toBufferBE(noteDao.index, 32).toString('hex');
118
+ await this.#notes.delete(noteIndex);
119
+ await this.#notesToScope.delete(noteIndex);
120
+ await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
121
+ const scopes = await toArray(this.#scopes.keysAsync());
122
+ for (const scope of scopes) {
123
+ await this.#notesByAddressPointAndScope.get(scope)!.deleteValue(noteDao.addressPoint.toString(), noteIndex);
124
+ await this.#notesByTxHashAndScope.get(scope)!.deleteValue(noteDao.txHash.toString(), noteIndex);
125
+ await this.#notesByContractAndScope.get(scope)!.deleteValue(noteDao.contractAddress.toString(), noteIndex);
126
+ await this.#notesByStorageSlotAndScope.get(scope)!.deleteValue(noteDao.storageSlot.toString(), noteIndex);
127
+ }
128
+ }
129
+ }
130
+ });
131
+ }
132
+
133
+ public async unnullifyNotesAfter(blockNumber: number, synchedBlockNumber?: number): Promise<void> {
134
+ const nullifiersToUndo: string[] = [];
135
+ const currentBlockNumber = blockNumber + 1;
136
+ const maxBlockNumber = synchedBlockNumber ?? currentBlockNumber;
137
+ for (let i = currentBlockNumber; i <= maxBlockNumber; i++) {
138
+ nullifiersToUndo.push(...(await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i))));
139
+ }
140
+ const notesIndexesToReinsert = await Promise.all(
141
+ nullifiersToUndo.map(nullifier => this.#nullifiedNotesByNullifier.getAsync(nullifier)),
142
+ );
143
+ const notNullNoteIndexes = notesIndexesToReinsert.filter(noteIndex => noteIndex != undefined);
144
+ const nullifiedNoteBuffers = await Promise.all(
145
+ notNullNoteIndexes.map(noteIndex => this.#nullifiedNotes.getAsync(noteIndex!)),
146
+ );
147
+ const noteDaos = nullifiedNoteBuffers
148
+ .filter(buffer => buffer != undefined)
149
+ .map(buffer => NoteDao.fromBuffer(buffer!));
150
+
151
+ await this.#store.transactionAsync(async () => {
152
+ for (const dao of noteDaos) {
153
+ const noteIndex = toBufferBE(dao.index, 32).toString('hex');
154
+ await this.#notes.set(noteIndex, dao.toBuffer());
155
+ await this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
156
+
157
+ let scopes = (await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex))) ?? [];
158
+
159
+ if (scopes.length === 0) {
160
+ scopes = [new AztecAddress(dao.addressPoint.x).toString()];
161
+ }
162
+
163
+ for (const scope of scopes) {
164
+ await this.#notesByContractAndScope.get(scope.toString())!.set(dao.contractAddress.toString(), noteIndex);
165
+ await this.#notesByStorageSlotAndScope.get(scope.toString())!.set(dao.storageSlot.toString(), noteIndex);
166
+ await this.#notesByTxHashAndScope.get(scope.toString())!.set(dao.txHash.toString(), noteIndex);
167
+ await this.#notesByAddressPointAndScope.get(scope.toString())!.set(dao.addressPoint.toString(), noteIndex);
168
+ await this.#notesToScope.set(noteIndex, scope);
169
+ }
170
+
171
+ await this.#nullifiedNotes.delete(noteIndex);
172
+ await this.#nullifiedNotesToScope.delete(noteIndex);
173
+ await this.#nullifiersByBlockNumber.deleteValue(dao.l2BlockNumber, dao.siloedNullifier.toString());
174
+ await this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex);
175
+ await this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex);
176
+ await this.#nullifiedNotesByTxHash.deleteValue(dao.txHash.toString(), noteIndex);
177
+ await this.#nullifiedNotesByAddressPoint.deleteValue(dao.addressPoint.toString(), noteIndex);
178
+ await this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString());
179
+ }
180
+ });
181
+ }
182
+
183
+ async getNotes(filter: NotesFilter): Promise<NoteDao[]> {
184
+ const publicKey: PublicKey | undefined = filter.owner ? await filter.owner.toAddressPoint() : undefined;
185
+
186
+ filter.status = filter.status ?? NoteStatus.ACTIVE;
187
+
188
+ const candidateNoteSources = [];
189
+
190
+ filter.scopes ??= (await toArray(this.#scopes.keysAsync())).map(addressString =>
191
+ AztecAddress.fromString(addressString),
192
+ );
193
+
194
+ const activeNoteIdsPerScope: string[][] = [];
195
+
196
+ for (const scope of new Set(filter.scopes)) {
197
+ const formattedScopeString = scope.toString();
198
+ if (!(await this.#scopes.hasAsync(formattedScopeString))) {
199
+ throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
200
+ }
201
+
202
+ activeNoteIdsPerScope.push(
203
+ publicKey
204
+ ? await toArray(
205
+ this.#notesByAddressPointAndScope.get(formattedScopeString)!.getValuesAsync(publicKey.toString()),
206
+ )
207
+ : filter.txHash
208
+ ? await toArray(
209
+ this.#notesByTxHashAndScope.get(formattedScopeString)!.getValuesAsync(filter.txHash.toString()),
210
+ )
211
+ : filter.contractAddress
212
+ ? await toArray(
213
+ this.#notesByContractAndScope
214
+ .get(formattedScopeString)!
215
+ .getValuesAsync(filter.contractAddress.toString()),
216
+ )
217
+ : filter.storageSlot
218
+ ? await toArray(
219
+ this.#notesByStorageSlotAndScope.get(formattedScopeString)!.getValuesAsync(filter.storageSlot.toString()),
220
+ )
221
+ : await toArray(this.#notesByAddressPointAndScope.get(formattedScopeString)!.valuesAsync()),
222
+ );
223
+ }
224
+
225
+ candidateNoteSources.push({
226
+ ids: new Set(activeNoteIdsPerScope.flat()),
227
+ notes: this.#notes,
228
+ });
229
+
230
+ if (filter.status == NoteStatus.ACTIVE_OR_NULLIFIED) {
231
+ candidateNoteSources.push({
232
+ ids: publicKey
233
+ ? await toArray(this.#nullifiedNotesByAddressPoint.getValuesAsync(publicKey.toString()))
234
+ : filter.txHash
235
+ ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString()))
236
+ : filter.contractAddress
237
+ ? await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString()))
238
+ : filter.storageSlot
239
+ ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString()))
240
+ : await toArray(this.#nullifiedNotes.keysAsync()),
241
+ notes: this.#nullifiedNotes,
242
+ });
243
+ }
244
+
245
+ const result: NoteDao[] = [];
246
+ for (const { ids, notes } of candidateNoteSources) {
247
+ for (const id of ids) {
248
+ const serializedNote = await notes.getAsync(id);
249
+ if (!serializedNote) {
250
+ continue;
251
+ }
252
+
253
+ const note = NoteDao.fromBuffer(serializedNote);
254
+ if (filter.contractAddress && !note.contractAddress.equals(filter.contractAddress)) {
255
+ continue;
256
+ }
257
+
258
+ if (filter.txHash && !note.txHash.equals(filter.txHash)) {
259
+ continue;
260
+ }
261
+
262
+ if (filter.storageSlot && !note.storageSlot.equals(filter.storageSlot!)) {
263
+ continue;
264
+ }
265
+
266
+ if (publicKey && !note.addressPoint.equals(publicKey)) {
267
+ continue;
268
+ }
269
+
270
+ if (filter.siloedNullifier && !note.siloedNullifier.equals(filter.siloedNullifier)) {
271
+ continue;
272
+ }
273
+
274
+ result.push(note);
275
+ }
276
+ }
277
+
278
+ return result;
279
+ }
280
+
281
+ removeNullifiedNotes(nullifiers: InBlock<Fr>[], accountAddressPoint: Point): Promise<NoteDao[]> {
282
+ if (nullifiers.length === 0) {
283
+ return Promise.resolve([]);
284
+ }
285
+
286
+ return this.#store.transactionAsync(async () => {
287
+ const nullifiedNotes: NoteDao[] = [];
288
+
289
+ for (const blockScopedNullifier of nullifiers) {
290
+ const { data: nullifier, l2BlockNumber: blockNumber } = blockScopedNullifier;
291
+ const noteIndex = await this.#nullifierToNoteId.getAsync(nullifier.toString());
292
+ if (!noteIndex) {
293
+ continue;
294
+ }
295
+
296
+ const noteBuffer = noteIndex ? await this.#notes.getAsync(noteIndex) : undefined;
297
+
298
+ if (!noteBuffer) {
299
+ // note doesn't exist. Maybe it got nullified already
300
+ continue;
301
+ }
302
+ const noteScopes = (await toArray(this.#notesToScope.getValuesAsync(noteIndex))) ?? [];
303
+ const note = NoteDao.fromBuffer(noteBuffer);
304
+ if (!note.addressPoint.equals(accountAddressPoint)) {
305
+ // tried to nullify someone else's note
306
+ continue;
307
+ }
308
+
309
+ nullifiedNotes.push(note);
310
+
311
+ await this.#notes.delete(noteIndex);
312
+ await this.#notesToScope.delete(noteIndex);
313
+
314
+ const scopes = await toArray(this.#scopes.keysAsync());
315
+
316
+ for (const scope of scopes) {
317
+ await this.#notesByAddressPointAndScope.get(scope)!.deleteValue(accountAddressPoint.toString(), noteIndex);
318
+ await this.#notesByTxHashAndScope.get(scope)!.deleteValue(note.txHash.toString(), noteIndex);
319
+ await this.#notesByContractAndScope.get(scope)!.deleteValue(note.contractAddress.toString(), noteIndex);
320
+ await this.#notesByStorageSlotAndScope.get(scope)!.deleteValue(note.storageSlot.toString(), noteIndex);
321
+ }
322
+
323
+ if (noteScopes !== undefined) {
324
+ for (const scope of noteScopes) {
325
+ await this.#nullifiedNotesToScope.set(noteIndex, scope);
326
+ }
327
+ }
328
+ await this.#nullifiedNotes.set(noteIndex, note.toBuffer());
329
+ await this.#nullifiersByBlockNumber.set(blockNumber, nullifier.toString());
330
+ await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
331
+ await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
332
+ await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
333
+ await this.#nullifiedNotesByAddressPoint.set(note.addressPoint.toString(), noteIndex);
334
+ await this.#nullifiedNotesByNullifier.set(nullifier.toString(), noteIndex);
335
+
336
+ await this.#nullifierToNoteId.delete(nullifier.toString());
337
+ }
338
+ return nullifiedNotes;
339
+ });
340
+ }
341
+
342
+ async getSize() {
343
+ return (await this.getNotes({})).reduce((sum, note) => sum + note.getSize(), 0);
344
+ }
345
+ }
@@ -0,0 +1 @@
1
+ export { SyncDataProvider } from './sync_data_provider.js';
@@ -0,0 +1,40 @@
1
+ import type { AztecAsyncKVStore, AztecAsyncSingleton } from '@aztec/kv-store';
2
+ import { BlockHeader } from '@aztec/stdlib/tx';
3
+
4
+ import type { DataProvider } from '../data_provider.js';
5
+
6
+ export class SyncDataProvider implements DataProvider {
7
+ #store: AztecAsyncKVStore;
8
+ #synchronizedHeader: AztecAsyncSingleton<Buffer>;
9
+
10
+ constructor(store: AztecAsyncKVStore) {
11
+ this.#store = store;
12
+ this.#synchronizedHeader = this.#store.openSingleton('header');
13
+ }
14
+
15
+ async setHeader(header: BlockHeader): Promise<void> {
16
+ await this.#synchronizedHeader.set(header.toBuffer());
17
+ }
18
+
19
+ async getBlockNumber(): Promise<number | undefined> {
20
+ const headerBuffer = await this.#synchronizedHeader.getAsync();
21
+ if (!headerBuffer) {
22
+ return undefined;
23
+ }
24
+
25
+ return Number(BlockHeader.fromBuffer(headerBuffer).globalVariables.blockNumber.toBigInt());
26
+ }
27
+
28
+ async getBlockHeader(): Promise<BlockHeader> {
29
+ const headerBuffer = await this.#synchronizedHeader.getAsync();
30
+ if (!headerBuffer) {
31
+ throw new Error(`Header not set`);
32
+ }
33
+
34
+ return BlockHeader.fromBuffer(headerBuffer);
35
+ }
36
+
37
+ async getSize(): Promise<number> {
38
+ return (await this.#synchronizedHeader.getAsync())?.length ?? 0;
39
+ }
40
+ }
@@ -0,0 +1 @@
1
+ export { TaggingDataProvider } from './tagging_data_provider.js';