@aztec/kv-store 0.0.0-test.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 (166) hide show
  1. package/README.md +10 -0
  2. package/dest/config.d.ts +17 -0
  3. package/dest/config.d.ts.map +1 -0
  4. package/dest/config.js +24 -0
  5. package/dest/indexeddb/array.d.ts +21 -0
  6. package/dest/indexeddb/array.d.ts.map +1 -0
  7. package/dest/indexeddb/array.js +104 -0
  8. package/dest/indexeddb/index.d.ts +7 -0
  9. package/dest/indexeddb/index.d.ts.map +1 -0
  10. package/dest/indexeddb/index.js +19 -0
  11. package/dest/indexeddb/map.d.ts +26 -0
  12. package/dest/indexeddb/map.d.ts.map +1 -0
  13. package/dest/indexeddb/map.js +133 -0
  14. package/dest/indexeddb/set.d.ts +17 -0
  15. package/dest/indexeddb/set.d.ts.map +1 -0
  16. package/dest/indexeddb/set.js +24 -0
  17. package/dest/indexeddb/singleton.d.ts +16 -0
  18. package/dest/indexeddb/singleton.d.ts.map +1 -0
  19. package/dest/indexeddb/singleton.js +37 -0
  20. package/dest/indexeddb/store.d.ts +97 -0
  21. package/dest/indexeddb/store.d.ts.map +1 -0
  22. package/dest/indexeddb/store.js +164 -0
  23. package/dest/interfaces/array.d.ts +80 -0
  24. package/dest/interfaces/array.d.ts.map +1 -0
  25. package/dest/interfaces/array.js +3 -0
  26. package/dest/interfaces/array_test_suite.d.ts +3 -0
  27. package/dest/interfaces/array_test_suite.d.ts.map +1 -0
  28. package/dest/interfaces/array_test_suite.js +104 -0
  29. package/dest/interfaces/common.d.ts +23 -0
  30. package/dest/interfaces/common.d.ts.map +1 -0
  31. package/dest/interfaces/common.js +3 -0
  32. package/dest/interfaces/counter.d.ts +59 -0
  33. package/dest/interfaces/counter.d.ts.map +1 -0
  34. package/dest/interfaces/counter.js +1 -0
  35. package/dest/interfaces/index.d.ts +8 -0
  36. package/dest/interfaces/index.d.ts.map +1 -0
  37. package/dest/interfaces/index.js +6 -0
  38. package/dest/interfaces/map.d.ts +134 -0
  39. package/dest/interfaces/map.d.ts.map +1 -0
  40. package/dest/interfaces/map.js +3 -0
  41. package/dest/interfaces/map_test_suite.d.ts +3 -0
  42. package/dest/interfaces/map_test_suite.d.ts.map +1 -0
  43. package/dest/interfaces/map_test_suite.js +151 -0
  44. package/dest/interfaces/set.d.ts +44 -0
  45. package/dest/interfaces/set.d.ts.map +1 -0
  46. package/dest/interfaces/set.js +1 -0
  47. package/dest/interfaces/set_test_suite.d.ts +3 -0
  48. package/dest/interfaces/set_test_suite.d.ts.map +1 -0
  49. package/dest/interfaces/set_test_suite.js +96 -0
  50. package/dest/interfaces/singleton.d.ts +29 -0
  51. package/dest/interfaces/singleton.d.ts.map +1 -0
  52. package/dest/interfaces/singleton.js +4 -0
  53. package/dest/interfaces/singleton_test_suite.d.ts +3 -0
  54. package/dest/interfaces/singleton_test_suite.d.ts.map +1 -0
  55. package/dest/interfaces/singleton_test_suite.js +30 -0
  56. package/dest/interfaces/store.d.ts +145 -0
  57. package/dest/interfaces/store.d.ts.map +1 -0
  58. package/dest/interfaces/store.js +1 -0
  59. package/dest/interfaces/store_test_suite.d.ts +3 -0
  60. package/dest/interfaces/store_test_suite.d.ts.map +1 -0
  61. package/dest/interfaces/store_test_suite.js +37 -0
  62. package/dest/interfaces/utils.d.ts +16 -0
  63. package/dest/interfaces/utils.d.ts.map +1 -0
  64. package/dest/interfaces/utils.js +16 -0
  65. package/dest/lmdb/array.d.ts +23 -0
  66. package/dest/lmdb/array.d.ts.map +1 -0
  67. package/dest/lmdb/array.js +117 -0
  68. package/dest/lmdb/counter.d.ts +19 -0
  69. package/dest/lmdb/counter.d.ts.map +1 -0
  70. package/dest/lmdb/counter.js +50 -0
  71. package/dest/lmdb/index.d.ts +12 -0
  72. package/dest/lmdb/index.d.ts.map +1 -0
  73. package/dest/lmdb/index.js +25 -0
  74. package/dest/lmdb/map.d.ts +52 -0
  75. package/dest/lmdb/map.d.ts.map +1 -0
  76. package/dest/lmdb/map.js +222 -0
  77. package/dest/lmdb/set.d.ts +18 -0
  78. package/dest/lmdb/set.d.ts.map +1 -0
  79. package/dest/lmdb/set.js +32 -0
  80. package/dest/lmdb/singleton.d.ts +14 -0
  81. package/dest/lmdb/singleton.d.ts.map +1 -0
  82. package/dest/lmdb/singleton.js +26 -0
  83. package/dest/lmdb/store.d.ts +110 -0
  84. package/dest/lmdb/store.d.ts.map +1 -0
  85. package/dest/lmdb/store.js +216 -0
  86. package/dest/lmdb-v2/array.d.ts +18 -0
  87. package/dest/lmdb-v2/array.d.ts.map +1 -0
  88. package/dest/lmdb-v2/array.js +101 -0
  89. package/dest/lmdb-v2/factory.d.ts +12 -0
  90. package/dest/lmdb-v2/factory.d.ts.map +1 -0
  91. package/dest/lmdb-v2/factory.js +60 -0
  92. package/dest/lmdb-v2/index.d.ts +3 -0
  93. package/dest/lmdb-v2/index.d.ts.map +1 -0
  94. package/dest/lmdb-v2/index.js +2 -0
  95. package/dest/lmdb-v2/map.d.ts +86 -0
  96. package/dest/lmdb-v2/map.d.ts.map +1 -0
  97. package/dest/lmdb-v2/map.js +193 -0
  98. package/dest/lmdb-v2/message.d.ts +112 -0
  99. package/dest/lmdb-v2/message.d.ts.map +1 -0
  100. package/dest/lmdb-v2/message.js +18 -0
  101. package/dest/lmdb-v2/read_transaction.d.ts +14 -0
  102. package/dest/lmdb-v2/read_transaction.d.ts.map +1 -0
  103. package/dest/lmdb-v2/read_transaction.js +101 -0
  104. package/dest/lmdb-v2/singleton.d.ts +12 -0
  105. package/dest/lmdb-v2/singleton.d.ts.map +1 -0
  106. package/dest/lmdb-v2/singleton.js +31 -0
  107. package/dest/lmdb-v2/store.d.ts +43 -0
  108. package/dest/lmdb-v2/store.d.ts.map +1 -0
  109. package/dest/lmdb-v2/store.js +181 -0
  110. package/dest/lmdb-v2/utils.d.ts +19 -0
  111. package/dest/lmdb-v2/utils.d.ts.map +1 -0
  112. package/dest/lmdb-v2/utils.js +126 -0
  113. package/dest/lmdb-v2/write_transaction.d.ts +19 -0
  114. package/dest/lmdb-v2/write_transaction.d.ts.map +1 -0
  115. package/dest/lmdb-v2/write_transaction.js +254 -0
  116. package/dest/stores/index.d.ts +2 -0
  117. package/dest/stores/index.d.ts.map +1 -0
  118. package/dest/stores/index.js +1 -0
  119. package/dest/stores/l2_tips_store.d.ts +13 -0
  120. package/dest/stores/l2_tips_store.d.ts.map +1 -0
  121. package/dest/stores/l2_tips_store.js +65 -0
  122. package/dest/utils.d.ts +12 -0
  123. package/dest/utils.d.ts.map +1 -0
  124. package/dest/utils.js +24 -0
  125. package/package.json +99 -0
  126. package/src/config.ts +34 -0
  127. package/src/indexeddb/array.ts +118 -0
  128. package/src/indexeddb/index.ts +29 -0
  129. package/src/indexeddb/map.ts +142 -0
  130. package/src/indexeddb/set.ts +37 -0
  131. package/src/indexeddb/singleton.ts +49 -0
  132. package/src/indexeddb/store.ts +197 -0
  133. package/src/interfaces/array.ts +90 -0
  134. package/src/interfaces/array_test_suite.ts +130 -0
  135. package/src/interfaces/common.ts +20 -0
  136. package/src/interfaces/counter.ts +65 -0
  137. package/src/interfaces/index.ts +7 -0
  138. package/src/interfaces/map.ts +151 -0
  139. package/src/interfaces/map_test_suite.ts +143 -0
  140. package/src/interfaces/set.ts +48 -0
  141. package/src/interfaces/set_test_suite.ts +81 -0
  142. package/src/interfaces/singleton.ts +29 -0
  143. package/src/interfaces/singleton_test_suite.ts +46 -0
  144. package/src/interfaces/store.ts +177 -0
  145. package/src/interfaces/store_test_suite.ts +56 -0
  146. package/src/interfaces/utils.ts +21 -0
  147. package/src/lmdb/array.ts +139 -0
  148. package/src/lmdb/counter.ts +67 -0
  149. package/src/lmdb/index.ts +37 -0
  150. package/src/lmdb/map.ts +248 -0
  151. package/src/lmdb/set.ts +45 -0
  152. package/src/lmdb/singleton.ts +35 -0
  153. package/src/lmdb/store.ts +263 -0
  154. package/src/lmdb-v2/array.ts +115 -0
  155. package/src/lmdb-v2/factory.ts +98 -0
  156. package/src/lmdb-v2/index.ts +2 -0
  157. package/src/lmdb-v2/map.ts +233 -0
  158. package/src/lmdb-v2/message.ts +146 -0
  159. package/src/lmdb-v2/read_transaction.ts +116 -0
  160. package/src/lmdb-v2/singleton.ts +34 -0
  161. package/src/lmdb-v2/store.ts +237 -0
  162. package/src/lmdb-v2/utils.ts +150 -0
  163. package/src/lmdb-v2/write_transaction.ts +314 -0
  164. package/src/stores/index.ts +1 -0
  165. package/src/stores/l2_tips_store.ts +70 -0
  166. package/src/utils.ts +40 -0
@@ -0,0 +1,110 @@
1
+ import { type RootDatabase } from 'lmdb';
2
+ import type { AztecArray, AztecAsyncArray } from '../interfaces/array.js';
3
+ import type { Key, StoreSize } from '../interfaces/common.js';
4
+ import type { AztecAsyncCounter, AztecCounter } from '../interfaces/counter.js';
5
+ import type { AztecAsyncMap, AztecAsyncMultiMap, AztecMap, AztecMapWithSize, AztecMultiMap, AztecMultiMapWithSize } from '../interfaces/map.js';
6
+ import type { AztecAsyncSet, AztecSet } from '../interfaces/set.js';
7
+ import type { AztecAsyncSingleton, AztecSingleton } from '../interfaces/singleton.js';
8
+ import type { AztecAsyncKVStore, AztecKVStore } from '../interfaces/store.js';
9
+ /**
10
+ * A key-value store backed by LMDB.
11
+ */
12
+ export declare class AztecLmdbStore implements AztecKVStore, AztecAsyncKVStore {
13
+ #private;
14
+ readonly isEphemeral: boolean;
15
+ private path;
16
+ syncGetters: true;
17
+ constructor(rootDb: RootDatabase, isEphemeral: boolean, path: string);
18
+ /**
19
+ * Creates a new AztecKVStore backed by LMDB. The path to the database is optional. If not provided,
20
+ * the database will be stored in a temporary location and be deleted when the process exists.
21
+ *
22
+ * The `rollupAddress` passed is checked against what is stored in the database. If they do not match,
23
+ * the database is cleared before returning the store. This way data is not accidentally shared between
24
+ * different rollup instances.
25
+ *
26
+ * @param path - A path on the disk to store the database. Optional
27
+ * @param ephemeral - true if the store should only exist in memory and not automatically be flushed to disk. Optional
28
+ * @param log - A logger to use. Optional
29
+ * @returns The store
30
+ */
31
+ static open(path?: string, mapSizeKb?: number, // defaults to 1 GB map size
32
+ ephemeral?: boolean, log?: import("@aztec/foundation/log").Logger): AztecLmdbStore;
33
+ /**
34
+ * Forks the current DB into a new DB by backing it up to a temporary location and opening a new lmdb db.
35
+ * @returns A new AztecLmdbStore.
36
+ */
37
+ fork(): Promise<AztecLmdbStore>;
38
+ /**
39
+ * Creates a new AztecMap in the store.
40
+ * @param name - Name of the map
41
+ * @returns A new AztecMap
42
+ */
43
+ openMap<K extends Key, V>(name: string): AztecMap<K, V> & AztecAsyncMap<K, V>;
44
+ /**
45
+ * Creates a new AztecSet in the store.
46
+ * @param name - Name of the set
47
+ * @returns A new AztecSet
48
+ */
49
+ openSet<K extends Key>(name: string): AztecSet<K> & AztecAsyncSet<K>;
50
+ /**
51
+ * Creates a new AztecMultiMap in the store. A multi-map stores multiple values for a single key automatically.
52
+ * @param name - Name of the map
53
+ * @returns A new AztecMultiMap
54
+ */
55
+ openMultiMap<K extends Key, V>(name: string): AztecMultiMap<K, V> & AztecAsyncMultiMap<K, V>;
56
+ openCounter<K extends Key>(name: string): AztecCounter<K> & AztecAsyncCounter<K>;
57
+ /**
58
+ * Creates a new AztecMultiMapWithSize in the store. A multi-map with size stores multiple values for a single key automatically.
59
+ * @param name - Name of the map
60
+ * @returns A new AztecMultiMapWithSize
61
+ */
62
+ openMultiMapWithSize<K extends Key, V>(name: string): AztecMultiMapWithSize<K, V>;
63
+ /**
64
+ * Creates a new AztecMapWithSize in the store.
65
+ * @param name - Name of the map
66
+ * @returns A new AztecMapWithSize
67
+ */
68
+ openMapWithSize<K extends Key, V>(name: string): AztecMapWithSize<K, V>;
69
+ /**
70
+ * Creates a new AztecArray in the store.
71
+ * @param name - Name of the array
72
+ * @returns A new AztecArray
73
+ */
74
+ openArray<T>(name: string): AztecArray<T> & AztecAsyncArray<T>;
75
+ /**
76
+ * Creates a new AztecSingleton in the store.
77
+ * @param name - Name of the singleton
78
+ * @returns A new AztecSingleton
79
+ */
80
+ openSingleton<T>(name: string): AztecSingleton<T> & AztecAsyncSingleton<T>;
81
+ /**
82
+ * Runs a callback in a transaction.
83
+ * @param callback - Function to execute in a transaction
84
+ * @returns A promise that resolves to the return value of the callback
85
+ */
86
+ transaction<T>(callback: () => T): Promise<T>;
87
+ /**
88
+ * Runs a callback in a transaction.
89
+ * @param callback - Function to execute in a transaction
90
+ * @returns A promise that resolves to the return value of the callback
91
+ */
92
+ transactionAsync<T>(callback: () => Promise<T>): Promise<T>;
93
+ /**
94
+ * Clears all entries in the store & sub DBs.
95
+ */
96
+ clear(): Promise<void>;
97
+ /**
98
+ * Drops the database & sub DBs.
99
+ */
100
+ drop(): Promise<void>;
101
+ /**
102
+ * Close the database. Note, once this is closed we can no longer interact with the DB.
103
+ */
104
+ close(): Promise<void>;
105
+ /** Deletes this store and removes the database files from disk */
106
+ delete(): Promise<void>;
107
+ estimateSize(): Promise<StoreSize>;
108
+ private estimateSubDBSize;
109
+ }
110
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/lmdb/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ import { randomBytes } from '@aztec/foundation/crypto';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { promises as fs, mkdirSync } from 'fs';
4
+ import { open } from 'lmdb';
5
+ import { tmpdir } from 'os';
6
+ import { join } from 'path';
7
+ import { LmdbAztecArray } from './array.js';
8
+ import { LmdbAztecCounter } from './counter.js';
9
+ import { LmdbAztecMap, LmdbAztecMapWithSize } from './map.js';
10
+ import { LmdbAztecSet } from './set.js';
11
+ import { LmdbAztecSingleton } from './singleton.js';
12
+ /**
13
+ * A key-value store backed by LMDB.
14
+ */ export class AztecLmdbStore {
15
+ isEphemeral;
16
+ path;
17
+ syncGetters;
18
+ #rootDb;
19
+ #data;
20
+ #multiMapData;
21
+ #log;
22
+ constructor(rootDb, isEphemeral, path){
23
+ this.isEphemeral = isEphemeral;
24
+ this.path = path;
25
+ this.syncGetters = true;
26
+ this.#log = createLogger('kv-store:lmdb');
27
+ this.#rootDb = rootDb;
28
+ // big bucket to store all the data
29
+ this.#data = rootDb.openDB('data', {
30
+ encoding: 'msgpack',
31
+ keyEncoding: 'ordered-binary'
32
+ });
33
+ this.#multiMapData = rootDb.openDB('data_dup_sort', {
34
+ encoding: 'ordered-binary',
35
+ keyEncoding: 'ordered-binary',
36
+ dupSort: true
37
+ });
38
+ }
39
+ /**
40
+ * Creates a new AztecKVStore backed by LMDB. The path to the database is optional. If not provided,
41
+ * the database will be stored in a temporary location and be deleted when the process exists.
42
+ *
43
+ * The `rollupAddress` passed is checked against what is stored in the database. If they do not match,
44
+ * the database is cleared before returning the store. This way data is not accidentally shared between
45
+ * different rollup instances.
46
+ *
47
+ * @param path - A path on the disk to store the database. Optional
48
+ * @param ephemeral - true if the store should only exist in memory and not automatically be flushed to disk. Optional
49
+ * @param log - A logger to use. Optional
50
+ * @returns The store
51
+ */ static open(path, mapSizeKb = 1 * 1024 * 1024, ephemeral = false, log = createLogger('kv-store:lmdb')) {
52
+ const dbPath = path ?? join(tmpdir(), randomBytes(8).toString('hex'));
53
+ mkdirSync(dbPath, {
54
+ recursive: true
55
+ });
56
+ const mapSize = 1024 * mapSizeKb;
57
+ log.debug(`Opening LMDB database at ${path || 'temporary location'} with map size ${mapSize}`);
58
+ const rootDb = open({
59
+ path: dbPath,
60
+ noSync: ephemeral,
61
+ mapSize
62
+ });
63
+ return new AztecLmdbStore(rootDb, ephemeral, dbPath);
64
+ }
65
+ /**
66
+ * Forks the current DB into a new DB by backing it up to a temporary location and opening a new lmdb db.
67
+ * @returns A new AztecLmdbStore.
68
+ */ async fork() {
69
+ const baseDir = this.path;
70
+ this.#log.debug(`Forking store with basedir ${baseDir}`);
71
+ const forkPath = await fs.mkdtemp(join(baseDir, 'aztec-store-fork-'));
72
+ this.#log.verbose(`Forking store to ${forkPath}`);
73
+ await this.#rootDb.backup(forkPath, false);
74
+ const forkDb = open(forkPath, {
75
+ noSync: this.isEphemeral
76
+ });
77
+ this.#log.debug(`Forked store at ${forkPath} opened successfully`);
78
+ return new AztecLmdbStore(forkDb, this.isEphemeral, forkPath);
79
+ }
80
+ /**
81
+ * Creates a new AztecMap in the store.
82
+ * @param name - Name of the map
83
+ * @returns A new AztecMap
84
+ */ openMap(name) {
85
+ return new LmdbAztecMap(this.#data, name);
86
+ }
87
+ /**
88
+ * Creates a new AztecSet in the store.
89
+ * @param name - Name of the set
90
+ * @returns A new AztecSet
91
+ */ openSet(name) {
92
+ return new LmdbAztecSet(this.#data, name);
93
+ }
94
+ /**
95
+ * Creates a new AztecMultiMap in the store. A multi-map stores multiple values for a single key automatically.
96
+ * @param name - Name of the map
97
+ * @returns A new AztecMultiMap
98
+ */ openMultiMap(name) {
99
+ return new LmdbAztecMap(this.#multiMapData, name);
100
+ }
101
+ openCounter(name) {
102
+ return new LmdbAztecCounter(this.#data, name);
103
+ }
104
+ /**
105
+ * Creates a new AztecMultiMapWithSize in the store. A multi-map with size stores multiple values for a single key automatically.
106
+ * @param name - Name of the map
107
+ * @returns A new AztecMultiMapWithSize
108
+ */ openMultiMapWithSize(name) {
109
+ return new LmdbAztecMapWithSize(this.#multiMapData, name);
110
+ }
111
+ /**
112
+ * Creates a new AztecMapWithSize in the store.
113
+ * @param name - Name of the map
114
+ * @returns A new AztecMapWithSize
115
+ */ openMapWithSize(name) {
116
+ return new LmdbAztecMapWithSize(this.#data, name);
117
+ }
118
+ /**
119
+ * Creates a new AztecArray in the store.
120
+ * @param name - Name of the array
121
+ * @returns A new AztecArray
122
+ */ openArray(name) {
123
+ return new LmdbAztecArray(this.#data, name);
124
+ }
125
+ /**
126
+ * Creates a new AztecSingleton in the store.
127
+ * @param name - Name of the singleton
128
+ * @returns A new AztecSingleton
129
+ */ openSingleton(name) {
130
+ return new LmdbAztecSingleton(this.#data, name);
131
+ }
132
+ /**
133
+ * Runs a callback in a transaction.
134
+ * @param callback - Function to execute in a transaction
135
+ * @returns A promise that resolves to the return value of the callback
136
+ */ transaction(callback) {
137
+ return this.#rootDb.transaction(callback);
138
+ }
139
+ /**
140
+ * Runs a callback in a transaction.
141
+ * @param callback - Function to execute in a transaction
142
+ * @returns A promise that resolves to the return value of the callback
143
+ */ async transactionAsync(callback) {
144
+ return await this.#rootDb.transaction(callback);
145
+ }
146
+ /**
147
+ * Clears all entries in the store & sub DBs.
148
+ */ async clear() {
149
+ await this.#data.clearAsync();
150
+ await this.#multiMapData.clearAsync();
151
+ await this.#rootDb.clearAsync();
152
+ }
153
+ /**
154
+ * Drops the database & sub DBs.
155
+ */ async drop() {
156
+ await this.#data.drop();
157
+ await this.#multiMapData.drop();
158
+ await this.#rootDb.drop();
159
+ }
160
+ /**
161
+ * Close the database. Note, once this is closed we can no longer interact with the DB.
162
+ */ async close() {
163
+ await this.#data.close();
164
+ await this.#multiMapData.close();
165
+ await this.#rootDb.close();
166
+ }
167
+ /** Deletes this store and removes the database files from disk */ async delete() {
168
+ await this.drop();
169
+ await this.close();
170
+ if (this.path) {
171
+ await fs.rm(this.path, {
172
+ recursive: true,
173
+ force: true,
174
+ maxRetries: 3
175
+ });
176
+ this.#log.verbose(`Deleted database files at ${this.path}`);
177
+ }
178
+ }
179
+ estimateSize() {
180
+ const stats = this.#rootDb.getStats();
181
+ // The 'mapSize' is the total amount of virtual address space allocated to the DB (effectively the maximum possible size)
182
+ // http://www.lmdb.tech/doc/group__mdb.html#a4bde3c8b676457342cba2fe27aed5fbd
183
+ let mapSize = 0;
184
+ if ('mapSize' in stats && typeof stats.mapSize === 'number') {
185
+ mapSize = stats.mapSize;
186
+ }
187
+ const dataResult = this.estimateSubDBSize(this.#data);
188
+ const multiResult = this.estimateSubDBSize(this.#multiMapData);
189
+ return Promise.resolve({
190
+ mappingSize: mapSize,
191
+ actualSize: dataResult.actualSize + multiResult.actualSize,
192
+ numItems: dataResult.numItems + multiResult.numItems
193
+ });
194
+ }
195
+ estimateSubDBSize(db) {
196
+ const stats = db.getStats();
197
+ let actualSize = 0;
198
+ let numItems = 0;
199
+ // This is the total number of key/value pairs present in the DB
200
+ if ('entryCount' in stats && typeof stats.entryCount === 'number') {
201
+ numItems = stats.entryCount;
202
+ }
203
+ // The closest value we can get to the actual size of the database is the number of consumed pages * the page size
204
+ if ('treeBranchPageCount' in stats && typeof stats.treeBranchPageCount === 'number' && 'treeLeafPageCount' in stats && typeof stats.treeLeafPageCount === 'number' && 'overflowPages' in stats && typeof stats.overflowPages === 'number' && 'pageSize' in stats && typeof stats.pageSize === 'number') {
205
+ const branchPages = stats.treeBranchPageCount;
206
+ const leafPages = stats.treeLeafPageCount;
207
+ const overflowPages = stats.overflowPages;
208
+ const pageSize = stats.pageSize;
209
+ actualSize = (branchPages + leafPages + overflowPages) * pageSize;
210
+ }
211
+ return {
212
+ actualSize,
213
+ numItems
214
+ };
215
+ }
216
+ }
@@ -0,0 +1,18 @@
1
+ import type { AztecAsyncArray } from '../interfaces/array.js';
2
+ import { AztecLMDBStoreV2 } from './store.js';
3
+ export declare class LMDBArray<T> implements AztecAsyncArray<T> {
4
+ private store;
5
+ private length;
6
+ private encoder;
7
+ private prefix;
8
+ constructor(store: AztecLMDBStoreV2, name: string);
9
+ pop(): Promise<T | undefined>;
10
+ push(...vals: T[]): Promise<number>;
11
+ setAt(index: number, val: T): Promise<boolean>;
12
+ atAsync(index: number): Promise<T | undefined>;
13
+ lengthAsync(): Promise<number>;
14
+ entriesAsync(): AsyncIterableIterator<[number, T]>;
15
+ valuesAsync(): AsyncIterableIterator<T>;
16
+ [Symbol.asyncIterator](): AsyncIterableIterator<T>;
17
+ }
18
+ //# sourceMappingURL=array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,EAAE,gBAAgB,EAA+B,MAAM,YAAY,CAAC;AAG3E,qBAAa,SAAS,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAKzC,OAAO,CAAC,KAAK;IAJzB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAS;gBAEH,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM;IAKzD,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAgB7B,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAWnC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAc9C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAexC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,YAAY,IAAI,qBAAqB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IA2BlD,WAAW,IAAI,qBAAqB,CAAC,CAAC,CAAC;IAM9C,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC;CAGnD"}
@@ -0,0 +1,101 @@
1
+ import { Encoder } from 'msgpackr/pack';
2
+ import { execInReadTx, execInWriteTx } from './store.js';
3
+ import { deserializeKey, serializeKey } from './utils.js';
4
+ export class LMDBArray {
5
+ store;
6
+ length;
7
+ encoder;
8
+ prefix;
9
+ constructor(store, name){
10
+ this.store = store;
11
+ this.encoder = new Encoder();
12
+ this.length = store.openSingleton(name + ':length');
13
+ this.prefix = `array:${name}`;
14
+ }
15
+ pop() {
16
+ return execInWriteTx(this.store, async (tx)=>{
17
+ const length = await this.lengthAsync();
18
+ if (length === 0) {
19
+ return;
20
+ }
21
+ const val = await tx.get(serializeKey(this.prefix, length - 1));
22
+ await tx.remove(serializeKey(this.prefix, length - 1));
23
+ await this.length.set(length - 1);
24
+ return val ? this.encoder.unpack(val) : undefined;
25
+ });
26
+ }
27
+ push(...vals) {
28
+ return execInWriteTx(this.store, async (tx)=>{
29
+ let length = await this.lengthAsync();
30
+ for (const val of vals){
31
+ await tx.set(serializeKey(this.prefix, length++), this.encoder.pack(val));
32
+ }
33
+ await this.length.set(length);
34
+ return length;
35
+ });
36
+ }
37
+ setAt(index, val) {
38
+ return execInWriteTx(this.store, async (tx)=>{
39
+ const length = await this.lengthAsync();
40
+ if (index < 0) {
41
+ index += length;
42
+ }
43
+ if (index < 0 || index >= length) {
44
+ return false;
45
+ }
46
+ await tx.set(serializeKey(this.prefix, index), this.encoder.pack(val));
47
+ return true;
48
+ });
49
+ }
50
+ atAsync(index) {
51
+ return execInReadTx(this.store, async (tx)=>{
52
+ const length = await this.lengthAsync();
53
+ if (index < 0) {
54
+ index += length;
55
+ }
56
+ if (index < 0 || index >= length) {
57
+ return undefined;
58
+ }
59
+ const val = await tx.get(serializeKey(this.prefix, index));
60
+ return val ? this.encoder.unpack(val) : undefined;
61
+ });
62
+ }
63
+ async lengthAsync() {
64
+ return await this.length.getAsync() ?? 0;
65
+ }
66
+ async *entriesAsync() {
67
+ // pin array length so that pushes don't affect iteration
68
+ const length = await this.lengthAsync();
69
+ if (length === 0) {
70
+ return;
71
+ }
72
+ let tx = this.store.getCurrentWriteTx();
73
+ const shouldClose = !tx;
74
+ tx ??= this.store.getReadTx();
75
+ try {
76
+ for await (const [key, val] of tx.iterate(serializeKey(this.prefix, 0), undefined, false, length)){
77
+ const deserializedKey = deserializeKey(this.prefix, key);
78
+ // if pops happened while iterating we may have read too much. Terminate early
79
+ if (deserializedKey === false) {
80
+ break;
81
+ }
82
+ yield [
83
+ deserializedKey,
84
+ this.encoder.unpack(val)
85
+ ];
86
+ }
87
+ } finally{
88
+ if (shouldClose) {
89
+ tx.close();
90
+ }
91
+ }
92
+ }
93
+ async *valuesAsync() {
94
+ for await (const [_, value] of this.entriesAsync()){
95
+ yield value;
96
+ }
97
+ }
98
+ [Symbol.asyncIterator]() {
99
+ return this.valuesAsync();
100
+ }
101
+ }
@@ -0,0 +1,12 @@
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { type Logger } from '@aztec/foundation/log';
3
+ import type { DataStoreConfig } from '../config.js';
4
+ import { AztecLMDBStoreV2 } from './store.js';
5
+ export declare function createStore(name: string, schemaVersion: number, config: DataStoreConfig, log?: Logger): Promise<AztecLMDBStoreV2>;
6
+ export declare function openTmpStore(name: string, ephemeral?: boolean, dbMapSizeKb?: number, // 10GB
7
+ maxReaders?: number, log?: Logger): Promise<AztecLMDBStoreV2>;
8
+ export declare function openStoreAt(dataDir: string, dbMapSizeKb?: number, // 10GB
9
+ maxReaders?: number, log?: Logger): Promise<AztecLMDBStoreV2>;
10
+ export declare function openVersionedStoreAt(dataDir: string, schemaVersion: number, rollupAddress: EthAddress, dbMapSizeKb?: number, // 10GB
11
+ maxReaders?: number, log?: Logger): Promise<AztecLMDBStoreV2>;
12
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAOlE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI9C,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,eAAe,EACvB,GAAG,GAAE,MAAiD,GACrD,OAAO,CAAC,gBAAgB,CAAC,CAyB3B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,OAAc,EACzB,WAAW,SAAqB,EAAE,OAAO;AACzC,UAAU,SAAc,EACxB,GAAG,GAAE,MAAiD,GACrD,OAAO,CAAC,gBAAgB,CAAC,CAqB3B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,WAAW,SAAqB,EAAE,OAAO;AACzC,UAAU,SAAc,EACxB,GAAG,GAAE,MAAyC,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,UAAU,EACzB,WAAW,SAAqB,EAAE,OAAO;AACzC,UAAU,SAAc,EACxB,GAAG,GAAE,MAAyC,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAM3B"}
@@ -0,0 +1,60 @@
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { createLogger } from '@aztec/foundation/log';
3
+ import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
4
+ import { mkdir, mkdtemp, rm } from 'fs/promises';
5
+ import { tmpdir } from 'os';
6
+ import { join } from 'path';
7
+ import { AztecLMDBStoreV2 } from './store.js';
8
+ const MAX_READERS = 16;
9
+ export async function createStore(name, schemaVersion, config, log = createLogger('kv-store:lmdb-v2:' + name)) {
10
+ const { dataDirectory, l1Contracts } = config;
11
+ let store;
12
+ if (typeof dataDirectory !== 'undefined') {
13
+ // Get rollup address from contracts config, or use zero address
14
+ const subDir = join(dataDirectory, name);
15
+ await mkdir(subDir, {
16
+ recursive: true
17
+ });
18
+ const rollupAddress = l1Contracts ? l1Contracts.rollupAddress : EthAddress.ZERO;
19
+ // Create a version manager
20
+ const versionManager = new DatabaseVersionManager(schemaVersion, rollupAddress, subDir, (dbDirectory)=>AztecLMDBStoreV2.new(dbDirectory, config.dataStoreMapSizeKB, MAX_READERS, ()=>Promise.resolve(), log));
21
+ log.info(`Creating ${name} data store at directory ${subDir} with map size ${config.dataStoreMapSizeKB} KB (LMDB v2)`);
22
+ [store] = await versionManager.open();
23
+ } else {
24
+ store = await openTmpStore(name, true, config.dataStoreMapSizeKB, MAX_READERS, log);
25
+ }
26
+ return store;
27
+ }
28
+ export async function openTmpStore(name, ephemeral = true, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, log = createLogger('kv-store:lmdb-v2:' + name)) {
29
+ const dataDir = await mkdtemp(join(tmpdir(), name + '-'));
30
+ log.debug(`Created temporary data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
31
+ // pass a cleanup callback because process.on('beforeExit', cleanup) does not work under Jest
32
+ const cleanup = async ()=>{
33
+ if (ephemeral) {
34
+ try {
35
+ await rm(dataDir, {
36
+ recursive: true,
37
+ force: true,
38
+ maxRetries: 3
39
+ });
40
+ log.debug(`Deleted temporary data store: ${dataDir}`);
41
+ } catch (err) {
42
+ log.warn(`Failed to delete temporary data directory (LMDB v2) ${dataDir}: ${err}`);
43
+ }
44
+ } else {
45
+ log.debug(`Leaving temporary data store: ${dataDir}`);
46
+ }
47
+ };
48
+ // For temporary stores, we don't need to worry about versioning
49
+ // as they are ephemeral and get cleaned up after use
50
+ return AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, cleanup, log);
51
+ }
52
+ export async function openStoreAt(dataDir, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, log = createLogger('kv-store:lmdb-v2')) {
53
+ log.debug(`Opening data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
54
+ return await AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, undefined, log);
55
+ }
56
+ export async function openVersionedStoreAt(dataDir, schemaVersion, rollupAddress, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, log = createLogger('kv-store:lmdb-v2')) {
57
+ log.debug(`Opening data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
58
+ const [store] = await new DatabaseVersionManager(schemaVersion, rollupAddress, dataDir, (dataDir)=>AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, undefined, log)).open();
59
+ return store;
60
+ }
@@ -0,0 +1,3 @@
1
+ export * from './store.js';
2
+ export * from './factory.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './store.js';
2
+ export * from './factory.js';
@@ -0,0 +1,86 @@
1
+ import type { Key, Range } from '../interfaces/common.js';
2
+ import type { AztecAsyncMap, AztecAsyncMultiMap } from '../interfaces/map.js';
3
+ import { type AztecLMDBStoreV2 } from './store.js';
4
+ export declare class LMDBMap<K extends Key, V> implements AztecAsyncMap<K, V> {
5
+ private store;
6
+ private prefix;
7
+ private encoder;
8
+ constructor(store: AztecLMDBStoreV2, name: string);
9
+ /**
10
+ * Sets the value at the given key.
11
+ * @param key - The key to set the value at
12
+ * @param val - The value to set
13
+ */
14
+ set(key: K, val: V): Promise<void>;
15
+ /**
16
+ * Sets the value at the given key if it does not already exist.
17
+ * @param key - The key to set the value at
18
+ * @param val - The value to set
19
+ */
20
+ setIfNotExists(key: K, val: V): Promise<boolean>;
21
+ /**
22
+ * Deletes the value at the given key.
23
+ * @param key - The key to delete the value at
24
+ */
25
+ delete(key: K): Promise<void>;
26
+ getAsync(key: K): Promise<V | undefined>;
27
+ hasAsync(key: K): Promise<boolean>;
28
+ /**
29
+ * Iterates over the map's key-value entries in the key's natural order
30
+ * @param range - The range of keys to iterate over
31
+ */
32
+ entriesAsync(range?: Range<K>): AsyncIterableIterator<[K, V]>;
33
+ /**
34
+ * Iterates over the map's values in the key's natural order
35
+ * @param range - The range of keys to iterate over
36
+ */
37
+ valuesAsync(range?: Range<K>): AsyncIterableIterator<V>;
38
+ /**
39
+ * Iterates over the map's keys in the key's natural order
40
+ * @param range - The range of keys to iterate over
41
+ */
42
+ keysAsync(range?: Range<K>): AsyncIterableIterator<K>;
43
+ }
44
+ export declare class LMDBMultiMap<K extends Key, V> implements AztecAsyncMultiMap<K, V> {
45
+ private store;
46
+ private prefix;
47
+ private encoder;
48
+ constructor(store: AztecLMDBStoreV2, name: string);
49
+ /**
50
+ * Sets the value at the given key.
51
+ * @param key - The key to set the value at
52
+ * @param val - The value to set
53
+ */
54
+ set(key: K, val: V): Promise<void>;
55
+ /**
56
+ * Sets the value at the given key if it does not already exist.
57
+ * @param key - The key to set the value at
58
+ * @param val - The value to set
59
+ */
60
+ setIfNotExists(key: K, val: V): Promise<boolean>;
61
+ /**
62
+ * Deletes the value at the given key.
63
+ * @param key - The key to delete the value at
64
+ */
65
+ delete(key: K): Promise<void>;
66
+ getAsync(key: K): Promise<V | undefined>;
67
+ hasAsync(key: K): Promise<boolean>;
68
+ /**
69
+ * Iterates over the map's key-value entries in the key's natural order
70
+ * @param range - The range of keys to iterate over
71
+ */
72
+ entriesAsync(range?: Range<K>): AsyncIterableIterator<[K, V]>;
73
+ /**
74
+ * Iterates over the map's values in the key's natural order
75
+ * @param range - The range of keys to iterate over
76
+ */
77
+ valuesAsync(range?: Range<K>): AsyncIterableIterator<V>;
78
+ /**
79
+ * Iterates over the map's keys in the key's natural order
80
+ * @param range - The range of keys to iterate over
81
+ */
82
+ keysAsync(range?: Range<K>): AsyncIterableIterator<K>;
83
+ deleteValue(key: K, val: V | undefined): Promise<void>;
84
+ getValuesAsync(key: K): AsyncIterableIterator<V>;
85
+ }
86
+ //# sourceMappingURL=map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/map.ts"],"names":[],"mappings":"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"}