@feelyourprotocol/mpt 8141.0.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 (204) hide show
  1. package/README.md +448 -0
  2. package/dist/cjs/constructors.d.ts +12 -0
  3. package/dist/cjs/constructors.d.ts.map +1 -0
  4. package/dist/cjs/constructors.js +57 -0
  5. package/dist/cjs/constructors.js.map +1 -0
  6. package/dist/cjs/db/checkpointDB.d.ts +87 -0
  7. package/dist/cjs/db/checkpointDB.d.ts.map +1 -0
  8. package/dist/cjs/db/checkpointDB.js +258 -0
  9. package/dist/cjs/db/checkpointDB.js.map +1 -0
  10. package/dist/cjs/db/index.d.ts +2 -0
  11. package/dist/cjs/db/index.d.ts.map +1 -0
  12. package/dist/cjs/db/index.js +18 -0
  13. package/dist/cjs/db/index.js.map +1 -0
  14. package/dist/cjs/index.d.ts +8 -0
  15. package/dist/cjs/index.d.ts.map +1 -0
  16. package/dist/cjs/index.js +24 -0
  17. package/dist/cjs/index.js.map +1 -0
  18. package/dist/cjs/mpt.d.ts +261 -0
  19. package/dist/cjs/mpt.d.ts.map +1 -0
  20. package/dist/cjs/mpt.js +900 -0
  21. package/dist/cjs/mpt.js.map +1 -0
  22. package/dist/cjs/node/branch.d.ts +14 -0
  23. package/dist/cjs/node/branch.d.ts.map +1 -0
  24. package/dist/cjs/node/branch.js +52 -0
  25. package/dist/cjs/node/branch.js.map +1 -0
  26. package/dist/cjs/node/extension.d.ts +7 -0
  27. package/dist/cjs/node/extension.d.ts.map +1 -0
  28. package/dist/cjs/node/extension.js +14 -0
  29. package/dist/cjs/node/extension.js.map +1 -0
  30. package/dist/cjs/node/extensionOrLeafNodeBase.d.ts +15 -0
  31. package/dist/cjs/node/extensionOrLeafNodeBase.d.ts.map +1 -0
  32. package/dist/cjs/node/extensionOrLeafNodeBase.js +42 -0
  33. package/dist/cjs/node/extensionOrLeafNodeBase.js.map +1 -0
  34. package/dist/cjs/node/index.d.ts +5 -0
  35. package/dist/cjs/node/index.d.ts.map +1 -0
  36. package/dist/cjs/node/index.js +21 -0
  37. package/dist/cjs/node/index.js.map +1 -0
  38. package/dist/cjs/node/leaf.d.ts +7 -0
  39. package/dist/cjs/node/leaf.d.ts.map +1 -0
  40. package/dist/cjs/node/leaf.js +14 -0
  41. package/dist/cjs/node/leaf.js.map +1 -0
  42. package/dist/cjs/node/util.d.ts +8 -0
  43. package/dist/cjs/node/util.d.ts.map +1 -0
  44. package/dist/cjs/node/util.js +38 -0
  45. package/dist/cjs/node/util.js.map +1 -0
  46. package/dist/cjs/package.json +3 -0
  47. package/dist/cjs/proof/index.d.ts +3 -0
  48. package/dist/cjs/proof/index.d.ts.map +1 -0
  49. package/dist/cjs/proof/index.js +19 -0
  50. package/dist/cjs/proof/index.js.map +1 -0
  51. package/dist/cjs/proof/proof.d.ts +41 -0
  52. package/dist/cjs/proof/proof.d.ts.map +1 -0
  53. package/dist/cjs/proof/proof.js +119 -0
  54. package/dist/cjs/proof/proof.js.map +1 -0
  55. package/dist/cjs/proof/range.d.ts +35 -0
  56. package/dist/cjs/proof/range.d.ts.map +1 -0
  57. package/dist/cjs/proof/range.js +456 -0
  58. package/dist/cjs/proof/range.js.map +1 -0
  59. package/dist/cjs/types.d.ts +110 -0
  60. package/dist/cjs/types.d.ts.map +1 -0
  61. package/dist/cjs/types.js +6 -0
  62. package/dist/cjs/types.js.map +1 -0
  63. package/dist/cjs/util/asyncWalk.d.ts +20 -0
  64. package/dist/cjs/util/asyncWalk.d.ts.map +1 -0
  65. package/dist/cjs/util/asyncWalk.js +50 -0
  66. package/dist/cjs/util/asyncWalk.js.map +1 -0
  67. package/dist/cjs/util/encoding.d.ts +31 -0
  68. package/dist/cjs/util/encoding.d.ts.map +1 -0
  69. package/dist/cjs/util/encoding.js +200 -0
  70. package/dist/cjs/util/encoding.js.map +1 -0
  71. package/dist/cjs/util/genesisState.d.ts +6 -0
  72. package/dist/cjs/util/genesisState.d.ts.map +1 -0
  73. package/dist/cjs/util/genesisState.js +45 -0
  74. package/dist/cjs/util/genesisState.js.map +1 -0
  75. package/dist/cjs/util/hex.d.ts +20 -0
  76. package/dist/cjs/util/hex.d.ts.map +1 -0
  77. package/dist/cjs/util/hex.js +48 -0
  78. package/dist/cjs/util/hex.js.map +1 -0
  79. package/dist/cjs/util/index.d.ts +4 -0
  80. package/dist/cjs/util/index.d.ts.map +1 -0
  81. package/dist/cjs/util/index.js +20 -0
  82. package/dist/cjs/util/index.js.map +1 -0
  83. package/dist/cjs/util/nibbles.d.ts +30 -0
  84. package/dist/cjs/util/nibbles.d.ts.map +1 -0
  85. package/dist/cjs/util/nibbles.js +79 -0
  86. package/dist/cjs/util/nibbles.js.map +1 -0
  87. package/dist/cjs/util/walkController.d.ts +72 -0
  88. package/dist/cjs/util/walkController.d.ts.map +1 -0
  89. package/dist/cjs/util/walkController.js +138 -0
  90. package/dist/cjs/util/walkController.js.map +1 -0
  91. package/dist/esm/constructors.d.ts +12 -0
  92. package/dist/esm/constructors.d.ts.map +1 -0
  93. package/dist/esm/constructors.js +53 -0
  94. package/dist/esm/constructors.js.map +1 -0
  95. package/dist/esm/db/checkpointDB.d.ts +87 -0
  96. package/dist/esm/db/checkpointDB.d.ts.map +1 -0
  97. package/dist/esm/db/checkpointDB.js +254 -0
  98. package/dist/esm/db/checkpointDB.js.map +1 -0
  99. package/dist/esm/db/index.d.ts +2 -0
  100. package/dist/esm/db/index.d.ts.map +1 -0
  101. package/dist/esm/db/index.js +2 -0
  102. package/dist/esm/db/index.js.map +1 -0
  103. package/dist/esm/index.d.ts +8 -0
  104. package/dist/esm/index.d.ts.map +1 -0
  105. package/dist/esm/index.js +8 -0
  106. package/dist/esm/index.js.map +1 -0
  107. package/dist/esm/mpt.d.ts +261 -0
  108. package/dist/esm/mpt.d.ts.map +1 -0
  109. package/dist/esm/mpt.js +897 -0
  110. package/dist/esm/mpt.js.map +1 -0
  111. package/dist/esm/node/branch.d.ts +14 -0
  112. package/dist/esm/node/branch.d.ts.map +1 -0
  113. package/dist/esm/node/branch.js +48 -0
  114. package/dist/esm/node/branch.js.map +1 -0
  115. package/dist/esm/node/extension.d.ts +7 -0
  116. package/dist/esm/node/extension.d.ts.map +1 -0
  117. package/dist/esm/node/extension.js +10 -0
  118. package/dist/esm/node/extension.js.map +1 -0
  119. package/dist/esm/node/extensionOrLeafNodeBase.d.ts +15 -0
  120. package/dist/esm/node/extensionOrLeafNodeBase.d.ts.map +1 -0
  121. package/dist/esm/node/extensionOrLeafNodeBase.js +38 -0
  122. package/dist/esm/node/extensionOrLeafNodeBase.js.map +1 -0
  123. package/dist/esm/node/index.d.ts +5 -0
  124. package/dist/esm/node/index.d.ts.map +1 -0
  125. package/dist/esm/node/index.js +5 -0
  126. package/dist/esm/node/index.js.map +1 -0
  127. package/dist/esm/node/leaf.d.ts +7 -0
  128. package/dist/esm/node/leaf.d.ts.map +1 -0
  129. package/dist/esm/node/leaf.js +10 -0
  130. package/dist/esm/node/leaf.js.map +1 -0
  131. package/dist/esm/node/util.d.ts +8 -0
  132. package/dist/esm/node/util.d.ts.map +1 -0
  133. package/dist/esm/node/util.js +33 -0
  134. package/dist/esm/node/util.js.map +1 -0
  135. package/dist/esm/package.json +3 -0
  136. package/dist/esm/proof/index.d.ts +3 -0
  137. package/dist/esm/proof/index.d.ts.map +1 -0
  138. package/dist/esm/proof/index.js +3 -0
  139. package/dist/esm/proof/index.js.map +1 -0
  140. package/dist/esm/proof/proof.d.ts +41 -0
  141. package/dist/esm/proof/proof.d.ts.map +1 -0
  142. package/dist/esm/proof/proof.js +113 -0
  143. package/dist/esm/proof/proof.js.map +1 -0
  144. package/dist/esm/proof/range.d.ts +35 -0
  145. package/dist/esm/proof/range.d.ts.map +1 -0
  146. package/dist/esm/proof/range.js +453 -0
  147. package/dist/esm/proof/range.js.map +1 -0
  148. package/dist/esm/types.d.ts +110 -0
  149. package/dist/esm/types.d.ts.map +1 -0
  150. package/dist/esm/types.js +3 -0
  151. package/dist/esm/types.js.map +1 -0
  152. package/dist/esm/util/asyncWalk.d.ts +20 -0
  153. package/dist/esm/util/asyncWalk.d.ts.map +1 -0
  154. package/dist/esm/util/asyncWalk.js +47 -0
  155. package/dist/esm/util/asyncWalk.js.map +1 -0
  156. package/dist/esm/util/encoding.d.ts +31 -0
  157. package/dist/esm/util/encoding.d.ts.map +1 -0
  158. package/dist/esm/util/encoding.js +188 -0
  159. package/dist/esm/util/encoding.js.map +1 -0
  160. package/dist/esm/util/genesisState.d.ts +6 -0
  161. package/dist/esm/util/genesisState.d.ts.map +1 -0
  162. package/dist/esm/util/genesisState.js +42 -0
  163. package/dist/esm/util/genesisState.js.map +1 -0
  164. package/dist/esm/util/hex.d.ts +20 -0
  165. package/dist/esm/util/hex.d.ts.map +1 -0
  166. package/dist/esm/util/hex.js +43 -0
  167. package/dist/esm/util/hex.js.map +1 -0
  168. package/dist/esm/util/index.d.ts +4 -0
  169. package/dist/esm/util/index.d.ts.map +1 -0
  170. package/dist/esm/util/index.js +4 -0
  171. package/dist/esm/util/index.js.map +1 -0
  172. package/dist/esm/util/nibbles.d.ts +30 -0
  173. package/dist/esm/util/nibbles.d.ts.map +1 -0
  174. package/dist/esm/util/nibbles.js +73 -0
  175. package/dist/esm/util/nibbles.js.map +1 -0
  176. package/dist/esm/util/walkController.d.ts +72 -0
  177. package/dist/esm/util/walkController.d.ts.map +1 -0
  178. package/dist/esm/util/walkController.js +134 -0
  179. package/dist/esm/util/walkController.js.map +1 -0
  180. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  181. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  182. package/package.json +85 -0
  183. package/src/constructors.ts +71 -0
  184. package/src/db/checkpointDB.ts +298 -0
  185. package/src/db/index.ts +1 -0
  186. package/src/index.ts +7 -0
  187. package/src/mpt.ts +1090 -0
  188. package/src/node/branch.ts +60 -0
  189. package/src/node/extension.ts +13 -0
  190. package/src/node/extensionOrLeafNodeBase.ts +54 -0
  191. package/src/node/index.ts +4 -0
  192. package/src/node/leaf.ts +13 -0
  193. package/src/node/util.ts +35 -0
  194. package/src/proof/index.ts +2 -0
  195. package/src/proof/proof.ts +135 -0
  196. package/src/proof/range.ts +542 -0
  197. package/src/types.ts +151 -0
  198. package/src/util/asyncWalk.ts +60 -0
  199. package/src/util/encoding.ts +209 -0
  200. package/src/util/genesisState.ts +52 -0
  201. package/src/util/hex.ts +47 -0
  202. package/src/util/index.ts +3 -0
  203. package/src/util/nibbles.ts +80 -0
  204. package/src/util/walkController.ts +172 -0
@@ -0,0 +1,298 @@
1
+ import {
2
+ KeyEncoding,
3
+ ValueEncoding,
4
+ bytesToUnprefixedHex,
5
+ unprefixedHexToBytes,
6
+ } from '@feelyourprotocol/util'
7
+ import { LRUCache } from 'lru-cache'
8
+
9
+ import type { BatchDBOp, DB, EncodingOpts } from '@feelyourprotocol/util'
10
+ import type { Checkpoint, CheckpointDBOpts } from '../types.ts'
11
+
12
+ /**
13
+ * DB is a thin wrapper around the underlying levelup db,
14
+ * which validates inputs and sets encoding type.
15
+ */
16
+ export class CheckpointDB implements DB {
17
+ public checkpoints: Checkpoint[]
18
+ public db: DB<string, string | Uint8Array>
19
+ public readonly cacheSize: number
20
+ private readonly valueEncoding: ValueEncoding
21
+
22
+ // Starting with lru-cache v8 undefined and null are not allowed any more
23
+ // as cache values. At the same time our design works well, since undefined
24
+ // indicates for us that we know that the value is not present in the
25
+ // underlying trie database as well (so it carries real value).
26
+ //
27
+ // Solution here seems therefore adequate, other solutions would rather
28
+ // be some not so clean workaround.
29
+ //
30
+ // (note that @ts-ignore doesn't work since stripped on declaration (.d.ts) files)
31
+ protected _cache?: LRUCache<string, Uint8Array>
32
+ // protected _cache?: LRUCache<string, Uint8Array | undefined>
33
+
34
+ _stats = {
35
+ cache: {
36
+ reads: 0,
37
+ hits: 0,
38
+ writes: 0,
39
+ },
40
+ db: {
41
+ reads: 0,
42
+ hits: 0,
43
+ writes: 0,
44
+ },
45
+ }
46
+
47
+ /**
48
+ * Initialize a DB instance.
49
+ */
50
+ constructor(opts: CheckpointDBOpts) {
51
+ this.db = opts.db
52
+ this.cacheSize = opts.cacheSize ?? 0
53
+ this.valueEncoding = opts.valueEncoding ?? ValueEncoding.String
54
+ // Roots of trie at the moment of checkpoint
55
+ this.checkpoints = []
56
+
57
+ if (this.cacheSize > 0) {
58
+ this._cache = new LRUCache({
59
+ max: this.cacheSize,
60
+ updateAgeOnGet: true,
61
+ })
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Flush the checkpoints and use the given checkpoints instead.
67
+ * @param {Checkpoint[]} checkpoints
68
+ */
69
+ setCheckpoints(checkpoints: Checkpoint[]) {
70
+ this.checkpoints = []
71
+
72
+ for (let i = 0; i < checkpoints.length; i++) {
73
+ this.checkpoints.push({
74
+ root: checkpoints[i].root,
75
+ keyValueMap: new Map(checkpoints[i].keyValueMap),
76
+ })
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Is the DB during a checkpoint phase?
82
+ */
83
+ hasCheckpoints() {
84
+ return this.checkpoints.length > 0
85
+ }
86
+
87
+ /**
88
+ * Adds a new checkpoint to the stack
89
+ * @param root
90
+ */
91
+ checkpoint(root: Uint8Array) {
92
+ this.checkpoints.push({ keyValueMap: new Map<string, Uint8Array>(), root })
93
+ }
94
+
95
+ /**
96
+ * Commits the latest checkpoint
97
+ */
98
+ async commit() {
99
+ const { keyValueMap } = this.checkpoints.pop()!
100
+ if (!this.hasCheckpoints()) {
101
+ // This was the final checkpoint, we should now commit and flush everything to disk
102
+ const batchOp: BatchDBOp[] = []
103
+ for (const [key, value] of keyValueMap.entries()) {
104
+ if (value === undefined) {
105
+ batchOp.push({
106
+ type: 'del',
107
+ key: unprefixedHexToBytes(key),
108
+ })
109
+ } else {
110
+ batchOp.push({
111
+ type: 'put',
112
+ key: unprefixedHexToBytes(key),
113
+ value,
114
+ })
115
+ }
116
+ }
117
+ await this.batch(batchOp)
118
+ } else {
119
+ // dump everything into the current (higher level) diff cache
120
+ const currentKeyValueMap = this.checkpoints[this.checkpoints.length - 1].keyValueMap
121
+ for (const [key, value] of keyValueMap.entries()) {
122
+ currentKeyValueMap.set(key, value)
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Reverts the latest checkpoint
129
+ */
130
+ async revert() {
131
+ const { root } = this.checkpoints.pop()!
132
+ return root
133
+ }
134
+
135
+ /**
136
+ * @inheritDoc
137
+ */
138
+ async get(key: Uint8Array): Promise<Uint8Array | undefined> {
139
+ // Using deprecated bytesToUnprefixedHex for performance: used as cache/database keys (string encoding).
140
+ const keyHex = bytesToUnprefixedHex(key)
141
+ if (this._cache !== undefined) {
142
+ const value = this._cache.get(keyHex)
143
+ this._stats.cache.reads += 1
144
+ if (value !== undefined) {
145
+ this._stats.cache.hits += 1
146
+ return value
147
+ }
148
+ }
149
+
150
+ // Lookup the value in our diff cache. We return the latest checkpointed value (which should be the value on disk)
151
+ for (let index = this.checkpoints.length - 1; index >= 0; index--) {
152
+ if (this.checkpoints[index].keyValueMap.has(keyHex)) {
153
+ return this.checkpoints[index].keyValueMap.get(keyHex)
154
+ }
155
+ }
156
+ // Nothing has been found in diff cache, look up from disk
157
+ const value = await this.db.get(keyHex, {
158
+ keyEncoding: KeyEncoding.String,
159
+ valueEncoding: this.valueEncoding,
160
+ })
161
+ this._stats.db.reads += 1
162
+ if (value !== undefined) {
163
+ this._stats.db.hits += 1
164
+ }
165
+ const returnValue =
166
+ value !== undefined
167
+ ? value instanceof Uint8Array
168
+ ? value
169
+ : unprefixedHexToBytes(value as string)
170
+ : undefined
171
+ this._cache?.set(keyHex, returnValue)
172
+ if (this.hasCheckpoints()) {
173
+ // Since we are a checkpoint, put this value in diff cache,
174
+ // so future `get` calls will not look the key up again from disk.
175
+ this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, returnValue)
176
+ }
177
+
178
+ return returnValue
179
+ }
180
+
181
+ /**
182
+ * @inheritDoc
183
+ */
184
+ async put(key: Uint8Array, value: Uint8Array): Promise<void> {
185
+ // Using deprecated bytesToUnprefixedHex for performance: used as cache/database keys and values (string encoding).
186
+ const keyHex = bytesToUnprefixedHex(key)
187
+ if (this.hasCheckpoints()) {
188
+ // put value in diff cache
189
+ this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, value)
190
+ } else {
191
+ const valuePut =
192
+ this.valueEncoding === ValueEncoding.Bytes ? value : bytesToUnprefixedHex(value)
193
+ await this.db.put(keyHex, valuePut, {
194
+ keyEncoding: KeyEncoding.String,
195
+ valueEncoding: this.valueEncoding,
196
+ })
197
+ this._stats.db.writes += 1
198
+
199
+ if (this._cache !== undefined) {
200
+ this._cache.set(keyHex, value)
201
+ this._stats.cache.writes += 1
202
+ }
203
+ }
204
+ }
205
+
206
+ /**
207
+ * @inheritDoc
208
+ */
209
+ async del(key: Uint8Array): Promise<void> {
210
+ // Using deprecated bytesToUnprefixedHex for performance: used as cache/database keys (string encoding).
211
+ const keyHex = bytesToUnprefixedHex(key)
212
+ if (this.hasCheckpoints()) {
213
+ // delete the value in the current diff cache
214
+ this.checkpoints[this.checkpoints.length - 1].keyValueMap.set(keyHex, undefined)
215
+ } else {
216
+ // delete the value on disk
217
+ await this.db.del(keyHex, {
218
+ keyEncoding: KeyEncoding.String,
219
+ })
220
+ this._stats.db.writes += 1
221
+
222
+ if (this._cache !== undefined) {
223
+ this._cache.set(keyHex, undefined)
224
+ this._stats.cache.writes += 1
225
+ }
226
+ }
227
+ }
228
+
229
+ /**
230
+ * @inheritDoc
231
+ */
232
+ async batch(opStack: BatchDBOp[]): Promise<void> {
233
+ if (this.hasCheckpoints()) {
234
+ for (const op of opStack) {
235
+ if (op.type === 'put') {
236
+ await this.put(op.key, op.value)
237
+ } else if (op.type === 'del') {
238
+ await this.del(op.key)
239
+ }
240
+ }
241
+ } else {
242
+ // Using deprecated bytesToUnprefixedHex for performance: used as database keys/values (string encoding).
243
+ const convertedOps = opStack.map((op) => {
244
+ const convertedOp: {
245
+ key: string
246
+ value: Uint8Array | string | undefined
247
+ type: 'put' | 'del'
248
+ opts?: EncodingOpts
249
+ } = {
250
+ key: bytesToUnprefixedHex(op.key),
251
+ value: op.type === 'put' ? op.value : undefined,
252
+ type: op.type,
253
+ opts: { ...op.opts, ...{ valueEncoding: this.valueEncoding } },
254
+ }
255
+ this._stats.db.writes += 1
256
+ if (op.type === 'put' && this.valueEncoding === ValueEncoding.String) {
257
+ convertedOp.value = bytesToUnprefixedHex(convertedOp.value as Uint8Array)
258
+ }
259
+ return convertedOp
260
+ })
261
+ await this.db.batch(convertedOps as any)
262
+ }
263
+ }
264
+
265
+ stats(reset = true) {
266
+ const stats = { ...this._stats, size: this._cache?.size ?? 0 }
267
+ if (reset) {
268
+ this._stats = {
269
+ cache: {
270
+ reads: 0,
271
+ hits: 0,
272
+ writes: 0,
273
+ },
274
+ db: {
275
+ reads: 0,
276
+ hits: 0,
277
+ writes: 0,
278
+ },
279
+ }
280
+ }
281
+ return stats
282
+ }
283
+
284
+ /**
285
+ * @inheritDoc
286
+ */
287
+ shallowCopy(): CheckpointDB {
288
+ return new CheckpointDB({
289
+ db: this.db,
290
+ cacheSize: this.cacheSize,
291
+ valueEncoding: this.valueEncoding,
292
+ })
293
+ }
294
+
295
+ open() {
296
+ return Promise.resolve()
297
+ }
298
+ }
@@ -0,0 +1 @@
1
+ export * from './checkpointDB.ts'
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './constructors.ts'
2
+ export * from './db/index.ts'
3
+ export * from './mpt.ts'
4
+ export * from './node/index.ts'
5
+ export * from './proof/index.ts'
6
+ export * from './types.ts'
7
+ export * from './util/index.ts'