@proto-kit/common 0.1.1-develop.211 → 0.1.1-develop.2137

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 (258) hide show
  1. package/dist/cache/CacheManifest.d.ts +11 -0
  2. package/dist/cache/CacheManifest.d.ts.map +1 -0
  3. package/dist/cache/CacheManifest.js +56 -0
  4. package/dist/cache/CacheManifest.js.map +1 -0
  5. package/dist/cache/ProxyCache.d.ts +13 -0
  6. package/dist/cache/ProxyCache.d.ts.map +1 -0
  7. package/dist/cache/ProxyCache.js +24 -0
  8. package/dist/cache/ProxyCache.js.map +1 -0
  9. package/dist/cache/RemoteCache.d.ts +8 -0
  10. package/dist/cache/RemoteCache.d.ts.map +1 -0
  11. package/dist/cache/RemoteCache.js +2 -0
  12. package/dist/cache/RemoteCache.js.map +1 -0
  13. package/dist/cache/RemoteCacheCompiler.d.ts +16 -0
  14. package/dist/cache/RemoteCacheCompiler.d.ts.map +1 -0
  15. package/dist/cache/RemoteCacheCompiler.js +104 -0
  16. package/dist/cache/RemoteCacheCompiler.js.map +1 -0
  17. package/dist/compiling/AtomicCompileHelper.d.ts +15 -0
  18. package/dist/compiling/AtomicCompileHelper.d.ts.map +1 -0
  19. package/dist/compiling/AtomicCompileHelper.js +61 -0
  20. package/dist/compiling/AtomicCompileHelper.js.map +1 -0
  21. package/dist/compiling/CompilableModule.d.ts +6 -0
  22. package/dist/compiling/CompilableModule.d.ts.map +1 -0
  23. package/dist/compiling/CompilableModule.js +2 -0
  24. package/dist/compiling/CompilableModule.js.map +1 -0
  25. package/dist/compiling/CompileRegistry.d.ts +25 -0
  26. package/dist/compiling/CompileRegistry.d.ts.map +1 -0
  27. package/dist/compiling/CompileRegistry.js +62 -0
  28. package/dist/compiling/CompileRegistry.js.map +1 -0
  29. package/dist/compiling/services/ChildVerificationKeyService.d.ts +10 -0
  30. package/dist/compiling/services/ChildVerificationKeyService.d.ts.map +1 -0
  31. package/dist/compiling/services/ChildVerificationKeyService.js +27 -0
  32. package/dist/compiling/services/ChildVerificationKeyService.js.map +1 -0
  33. package/dist/config/ChildContainerCreatable.d.ts +5 -0
  34. package/dist/config/ChildContainerCreatable.d.ts.map +1 -0
  35. package/dist/config/ChildContainerCreatable.js +2 -0
  36. package/dist/config/ChildContainerCreatable.js.map +1 -0
  37. package/dist/config/ChildContainerProvider.d.ts +5 -0
  38. package/dist/config/ChildContainerProvider.d.ts.map +1 -0
  39. package/dist/config/ChildContainerProvider.js +2 -0
  40. package/dist/config/ChildContainerProvider.js.map +1 -0
  41. package/dist/config/ConfigurableModule.d.ts +6 -2
  42. package/dist/config/ConfigurableModule.d.ts.map +1 -1
  43. package/dist/config/ConfigurableModule.js +5 -0
  44. package/dist/config/ConfigurableModule.js.map +1 -0
  45. package/dist/config/ModuleContainer.d.ts +70 -23
  46. package/dist/config/ModuleContainer.d.ts.map +1 -1
  47. package/dist/config/ModuleContainer.js +164 -31
  48. package/dist/config/ModuleContainer.js.map +1 -0
  49. package/dist/config/Startable.d.ts +4 -0
  50. package/dist/config/Startable.d.ts.map +1 -0
  51. package/dist/config/Startable.js +2 -0
  52. package/dist/config/Startable.js.map +1 -0
  53. package/dist/config/injectAlias.d.ts +18 -0
  54. package/dist/config/injectAlias.d.ts.map +1 -0
  55. package/dist/config/injectAlias.js +47 -0
  56. package/dist/config/injectAlias.js.map +1 -0
  57. package/dist/dependencyFactory/DependencyFactory.d.ts +14 -9
  58. package/dist/dependencyFactory/DependencyFactory.d.ts.map +1 -1
  59. package/dist/dependencyFactory/DependencyFactory.js +2 -96
  60. package/dist/dependencyFactory/DependencyFactory.js.map +1 -0
  61. package/dist/dependencyFactory/injectOptional.d.ts +16 -0
  62. package/dist/dependencyFactory/injectOptional.d.ts.map +1 -0
  63. package/dist/dependencyFactory/injectOptional.js +40 -0
  64. package/dist/dependencyFactory/injectOptional.js.map +1 -0
  65. package/dist/dummyVerificationKey.d.ts +3 -0
  66. package/dist/dummyVerificationKey.d.ts.map +1 -0
  67. package/dist/dummyVerificationKey.js +8 -0
  68. package/dist/dummyVerificationKey.js.map +1 -0
  69. package/dist/events/EventEmitter.d.ts +19 -0
  70. package/dist/events/EventEmitter.d.ts.map +1 -0
  71. package/dist/events/EventEmitter.js +35 -0
  72. package/dist/events/EventEmitter.js.map +1 -0
  73. package/dist/events/EventEmitterProxy.d.ts +18 -0
  74. package/dist/events/EventEmitterProxy.d.ts.map +1 -0
  75. package/dist/events/EventEmitterProxy.js +35 -0
  76. package/dist/events/EventEmitterProxy.js.map +1 -0
  77. package/dist/events/EventEmittingComponent.d.ts +9 -0
  78. package/dist/events/EventEmittingComponent.d.ts.map +1 -0
  79. package/dist/events/EventEmittingComponent.js +2 -0
  80. package/dist/events/EventEmittingComponent.js.map +1 -0
  81. package/dist/events/ReplayingSingleUseEventEmitter.d.ts +17 -0
  82. package/dist/events/ReplayingSingleUseEventEmitter.d.ts.map +1 -0
  83. package/dist/events/ReplayingSingleUseEventEmitter.js +34 -0
  84. package/dist/events/ReplayingSingleUseEventEmitter.js.map +1 -0
  85. package/dist/index.d.ts +27 -1
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +28 -2
  88. package/dist/index.js.map +1 -0
  89. package/dist/log.d.ts +37 -0
  90. package/dist/log.d.ts.map +1 -0
  91. package/dist/log.js +117 -0
  92. package/dist/log.js.map +1 -0
  93. package/dist/trees/InMemoryLinkedLeafStore.d.ts +21 -0
  94. package/dist/trees/InMemoryLinkedLeafStore.d.ts.map +1 -0
  95. package/dist/trees/InMemoryLinkedLeafStore.js +26 -0
  96. package/dist/trees/InMemoryLinkedLeafStore.js.map +1 -0
  97. package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
  98. package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
  99. package/dist/trees/InMemoryLinkedMerkleLeafStore.js +6 -0
  100. package/dist/trees/InMemoryLinkedMerkleLeafStore.js.map +1 -0
  101. package/dist/trees/InMemoryMerkleTreeStorage.d.ts +11 -0
  102. package/dist/trees/InMemoryMerkleTreeStorage.d.ts.map +1 -0
  103. package/dist/trees/InMemoryMerkleTreeStorage.js +13 -0
  104. package/dist/trees/InMemoryMerkleTreeStorage.js.map +1 -0
  105. package/dist/trees/LinkedMerkleTree.d.ts +345 -0
  106. package/dist/trees/LinkedMerkleTree.d.ts.map +1 -0
  107. package/dist/trees/LinkedMerkleTree.js +337 -0
  108. package/dist/trees/LinkedMerkleTree.js.map +1 -0
  109. package/dist/trees/LinkedMerkleTreeStore.d.ts +24 -0
  110. package/dist/trees/LinkedMerkleTreeStore.d.ts.map +1 -0
  111. package/dist/trees/LinkedMerkleTreeStore.js +2 -0
  112. package/dist/trees/LinkedMerkleTreeStore.js.map +1 -0
  113. package/dist/trees/MerkleTreeStore.d.ts +5 -0
  114. package/dist/trees/MerkleTreeStore.d.ts.map +1 -0
  115. package/dist/trees/MerkleTreeStore.js +2 -0
  116. package/dist/trees/MerkleTreeStore.js.map +1 -0
  117. package/dist/trees/MockAsyncMerkleStore.d.ts +9 -0
  118. package/dist/trees/MockAsyncMerkleStore.d.ts.map +1 -0
  119. package/dist/trees/MockAsyncMerkleStore.js +20 -0
  120. package/dist/trees/MockAsyncMerkleStore.js.map +1 -0
  121. package/dist/trees/RollupMerkleTree.d.ts +147 -0
  122. package/dist/trees/RollupMerkleTree.d.ts.map +1 -0
  123. package/dist/trees/RollupMerkleTree.js +218 -0
  124. package/dist/trees/RollupMerkleTree.js.map +1 -0
  125. package/dist/trees/VirtualMerkleTreeStore.d.ts +13 -0
  126. package/dist/trees/VirtualMerkleTreeStore.d.ts.map +1 -0
  127. package/dist/trees/VirtualMerkleTreeStore.js +18 -0
  128. package/dist/trees/VirtualMerkleTreeStore.js.map +1 -0
  129. package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts +288 -0
  130. package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts.map +1 -0
  131. package/dist/trees/lmt/AbstractLinkedMerkleTree.js +22 -0
  132. package/dist/trees/lmt/AbstractLinkedMerkleTree.js.map +1 -0
  133. package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts +21 -0
  134. package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts.map +1 -0
  135. package/dist/trees/lmt/InMemoryLinkedLeafStore.js +26 -0
  136. package/dist/trees/lmt/InMemoryLinkedLeafStore.js.map +1 -0
  137. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
  138. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
  139. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js +6 -0
  140. package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js.map +1 -0
  141. package/dist/trees/lmt/LinkedLeafStore.d.ts +16 -0
  142. package/dist/trees/lmt/LinkedLeafStore.d.ts.map +1 -0
  143. package/dist/trees/lmt/LinkedLeafStore.js +2 -0
  144. package/dist/trees/lmt/LinkedLeafStore.js.map +1 -0
  145. package/dist/trees/lmt/LinkedLinkedStore.d.ts +16 -0
  146. package/dist/trees/lmt/LinkedLinkedStore.d.ts.map +1 -0
  147. package/dist/trees/lmt/LinkedLinkedStore.js +2 -0
  148. package/dist/trees/lmt/LinkedLinkedStore.js.map +1 -0
  149. package/dist/trees/lmt/LinkedMerkleTree.d.ts +11 -0
  150. package/dist/trees/lmt/LinkedMerkleTree.d.ts.map +1 -0
  151. package/dist/trees/lmt/LinkedMerkleTree.js +241 -0
  152. package/dist/trees/lmt/LinkedMerkleTree.js.map +1 -0
  153. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts +113 -0
  154. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts.map +1 -0
  155. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js +113 -0
  156. package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js.map +1 -0
  157. package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts +7 -0
  158. package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts.map +1 -0
  159. package/dist/trees/lmt/LinkedMerkleTreeDatabase.js +2 -0
  160. package/dist/trees/lmt/LinkedMerkleTreeDatabase.js.map +1 -0
  161. package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts +16 -0
  162. package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts.map +1 -0
  163. package/dist/trees/lmt/LinkedMerkleTreeStore.js +2 -0
  164. package/dist/trees/lmt/LinkedMerkleTreeStore.js.map +1 -0
  165. package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts +74 -0
  166. package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts.map +1 -0
  167. package/dist/trees/lmt/LinkedMerkleTreeTypes.js +50 -0
  168. package/dist/trees/lmt/LinkedMerkleTreeTypes.js.map +1 -0
  169. package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts +11 -0
  170. package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts.map +1 -0
  171. package/dist/trees/sparse/InMemoryMerkleTreeStorage.js +13 -0
  172. package/dist/trees/sparse/InMemoryMerkleTreeStorage.js.map +1 -0
  173. package/dist/trees/sparse/MerkleTreeStore.d.ts +5 -0
  174. package/dist/trees/sparse/MerkleTreeStore.d.ts.map +1 -0
  175. package/dist/trees/sparse/MerkleTreeStore.js +2 -0
  176. package/dist/trees/sparse/MerkleTreeStore.js.map +1 -0
  177. package/dist/trees/sparse/MockAsyncMerkleStore.d.ts +9 -0
  178. package/dist/trees/sparse/MockAsyncMerkleStore.d.ts.map +1 -0
  179. package/dist/trees/sparse/MockAsyncMerkleStore.js +20 -0
  180. package/dist/trees/sparse/MockAsyncMerkleStore.js.map +1 -0
  181. package/dist/trees/sparse/RollupMerkleTree.d.ts +158 -0
  182. package/dist/trees/sparse/RollupMerkleTree.d.ts.map +1 -0
  183. package/dist/trees/sparse/RollupMerkleTree.js +330 -0
  184. package/dist/trees/sparse/RollupMerkleTree.js.map +1 -0
  185. package/dist/types.d.ts +62 -0
  186. package/dist/types.d.ts.map +1 -1
  187. package/dist/types.js +14 -1
  188. package/dist/types.js.map +1 -0
  189. package/dist/union/union.d.ts +177 -0
  190. package/dist/union/union.d.ts.map +1 -0
  191. package/dist/union/union.js +35 -0
  192. package/dist/union/union.js.map +1 -0
  193. package/dist/utils.d.ts +57 -2
  194. package/dist/utils.d.ts.map +1 -1
  195. package/dist/utils.js +153 -4
  196. package/dist/utils.js.map +1 -0
  197. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts +4 -3
  198. package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts.map +1 -1
  199. package/dist/zkProgrammable/ProvableMethodExecutionContext.js +2 -3
  200. package/dist/zkProgrammable/ProvableMethodExecutionContext.js.map +1 -0
  201. package/dist/zkProgrammable/ZkProgrammable.d.ts +32 -11
  202. package/dist/zkProgrammable/ZkProgrammable.d.ts.map +1 -1
  203. package/dist/zkProgrammable/ZkProgrammable.js +36 -17
  204. package/dist/zkProgrammable/ZkProgrammable.js.map +1 -0
  205. package/dist/zkProgrammable/provableMethod.d.ts +7 -4
  206. package/dist/zkProgrammable/provableMethod.d.ts.map +1 -1
  207. package/dist/zkProgrammable/provableMethod.js +30 -14
  208. package/dist/zkProgrammable/provableMethod.js.map +1 -0
  209. package/jest.config.cjs +12 -1
  210. package/package.json +9 -7
  211. package/src/cache/CacheManifest.ts +57 -0
  212. package/src/cache/ProxyCache.ts +30 -0
  213. package/src/cache/RemoteCache.ts +9 -0
  214. package/src/cache/RemoteCacheCompiler.ts +131 -0
  215. package/src/compiling/AtomicCompileHelper.ts +71 -0
  216. package/src/compiling/CompilableModule.ts +6 -0
  217. package/src/compiling/CompileRegistry.ts +64 -0
  218. package/src/compiling/services/ChildVerificationKeyService.ts +26 -0
  219. package/src/config/ChildContainerCreatable.ts +5 -0
  220. package/src/config/ChildContainerProvider.ts +5 -0
  221. package/src/config/ConfigurableModule.ts +15 -2
  222. package/src/config/ModuleContainer.ts +286 -58
  223. package/src/config/Startable.ts +3 -0
  224. package/src/config/injectAlias.ts +70 -0
  225. package/src/dependencyFactory/DependencyFactory.ts +34 -109
  226. package/src/dummyVerificationKey.ts +10 -0
  227. package/src/events/EventEmitter.ts +61 -0
  228. package/src/events/EventEmitterProxy.ts +81 -0
  229. package/src/events/EventEmittingComponent.ts +11 -0
  230. package/src/events/ReplayingSingleUseEventEmitter.ts +42 -0
  231. package/src/index.ts +27 -2
  232. package/src/log.ts +145 -0
  233. package/src/trees/lmt/AbstractLinkedMerkleTree.ts +102 -0
  234. package/src/trees/lmt/InMemoryLinkedLeafStore.ts +42 -0
  235. package/src/trees/lmt/LinkedLeafStore.ts +13 -0
  236. package/src/trees/lmt/LinkedMerkleTree.ts +335 -0
  237. package/src/trees/lmt/LinkedMerkleTreeCircuitOps.ts +188 -0
  238. package/src/trees/lmt/LinkedMerkleTreeTypes.ts +53 -0
  239. package/src/trees/sparse/InMemoryMerkleTreeStorage.ts +17 -0
  240. package/src/trees/sparse/MerkleTreeStore.ts +5 -0
  241. package/src/trees/sparse/MockAsyncMerkleStore.ts +30 -0
  242. package/src/trees/sparse/RollupMerkleTree.ts +512 -0
  243. package/src/types.ts +53 -2
  244. package/src/utils.ts +281 -5
  245. package/src/zkProgrammable/ProvableMethodExecutionContext.ts +6 -6
  246. package/src/zkProgrammable/ZkProgrammable.ts +90 -35
  247. package/src/zkProgrammable/provableMethod.ts +50 -23
  248. package/test/config/ContainerEvents.test.ts +65 -0
  249. package/test/config/ModuleContainer.test.ts +146 -15
  250. package/test/config/injectAlias.test.ts +28 -0
  251. package/test/trees/LinkedMerkleTree.test.ts +124 -0
  252. package/test/trees/LinkedMerkleTreeCircuitOps.test.ts +147 -0
  253. package/test/trees/MerkleTree.test.ts +251 -0
  254. package/test/tsconfig.json +5 -2
  255. package/test/zkProgrammable/ZkProgrammable.test.ts +145 -119
  256. package/tsconfig.json +1 -1
  257. package/LICENSE.md +0 -201
  258. package/tsconfig.test.json +0 -9
@@ -0,0 +1,42 @@
1
+ import { LinkedLeafStore, LinkedLeaf } from "./LinkedLeafStore";
2
+
3
+ export class InMemoryLinkedLeafStore implements LinkedLeafStore {
4
+ public leaves: {
5
+ [key: string]: { leaf: LinkedLeaf; index: bigint };
6
+ } = {};
7
+
8
+ public maximumIndex?: bigint;
9
+
10
+ public getLeaf(
11
+ path: bigint
12
+ ): { leaf: LinkedLeaf; index: bigint } | undefined {
13
+ return this.leaves[path.toString()];
14
+ }
15
+
16
+ public setLeaf(index: bigint, value: LinkedLeaf): void {
17
+ const leaf = this.getLeaf(value.path);
18
+
19
+ if (leaf !== undefined && leaf?.index !== index) {
20
+ throw new Error("Cannot change index of existing leaf");
21
+ }
22
+
23
+ this.leaves[value.path.toString()] = { leaf: value, index: index };
24
+ if (index > (this.maximumIndex ?? -1)) {
25
+ this.maximumIndex = index;
26
+ }
27
+ }
28
+
29
+ public getMaximumIndex(): bigint | undefined {
30
+ return this.maximumIndex;
31
+ }
32
+
33
+ // This gets the leaf with the closest path.
34
+ public getPreviousLeaf(
35
+ path: bigint
36
+ ): { leaf: LinkedLeaf; index: bigint } | undefined {
37
+ return Object.values(this.leaves).find(
38
+ (storedLeaf) =>
39
+ storedLeaf.leaf.nextPath > path && storedLeaf.leaf.path < path
40
+ );
41
+ }
42
+ }
@@ -0,0 +1,13 @@
1
+ export type LinkedLeaf = { value: bigint; path: bigint; nextPath: bigint };
2
+
3
+ export type StoredLeaf = { leaf: LinkedLeaf; index: bigint };
4
+
5
+ export interface LinkedLeafStore {
6
+ setLeaf: (index: bigint, value: LinkedLeaf) => void;
7
+
8
+ getLeaf: (path: bigint) => StoredLeaf | undefined;
9
+
10
+ getPreviousLeaf: (path: bigint) => StoredLeaf | undefined;
11
+
12
+ getMaximumIndex: () => bigint | undefined;
13
+ }
@@ -0,0 +1,335 @@
1
+ import { Field, Struct } from "o1js";
2
+
3
+ import { createMerkleTree, RollupMerkleTree } from "../sparse/RollupMerkleTree";
4
+ import { MerkleTreeStore } from "../sparse/MerkleTreeStore";
5
+ import { InMemoryMerkleTreeStorage } from "../sparse/InMemoryMerkleTreeStorage";
6
+
7
+ import { InMemoryLinkedLeafStore } from "./InMemoryLinkedLeafStore";
8
+ import { LinkedLeaf, LinkedLeafStore } from "./LinkedLeafStore";
9
+ import { LinkedLeafStruct } from "./LinkedMerkleTreeTypes";
10
+ import {
11
+ AbstractLinkedMerkleTree,
12
+ AbstractLinkedMerkleTreeClass,
13
+ } from "./AbstractLinkedMerkleTree";
14
+
15
+ type LeafOperationInstruction = {
16
+ witness: bigint;
17
+ witnessLeaf: LinkedLeafStruct;
18
+ write: { index: bigint; leaf: Field };
19
+ };
20
+
21
+ type SetLeafMetadata = {
22
+ leafPrevious: LeafOperationInstruction | "dummy";
23
+ leafCurrent: LeafOperationInstruction;
24
+ };
25
+
26
+ export function createLinkedMerkleTree(
27
+ height: number
28
+ ): AbstractLinkedMerkleTreeClass {
29
+ const SparseTreeClass = createMerkleTree(height);
30
+
31
+ class LinkedLeafAndMerkleWitness extends Struct({
32
+ leaf: LinkedLeafStruct,
33
+ merkleWitness: SparseTreeClass.WITNESS,
34
+ }) {
35
+ public checkMembership(root: Field, path: Field, value: Field) {
36
+ const pathEquals = path.equals(this.leaf.path);
37
+
38
+ return this.merkleWitness
39
+ .calculateRoot(
40
+ new LinkedLeafStruct({
41
+ ...this.leaf,
42
+ value,
43
+ }).hash()
44
+ )
45
+ .equals(root)
46
+ .and(pathEquals);
47
+ }
48
+ }
49
+
50
+ class LinkedOperationWitness extends Struct({
51
+ leafPrevious: LinkedLeafAndMerkleWitness,
52
+ leafCurrent: LinkedLeafAndMerkleWitness,
53
+ }) {
54
+ // implements LinkedStructTemplate
55
+ public static fromReadWitness(readWitness: LinkedLeafAndMerkleWitness) {
56
+ return new LinkedOperationWitness({
57
+ leafPrevious: new LinkedLeafAndMerkleWitness({
58
+ merkleWitness: SparseTreeClass.WITNESS.dummy(),
59
+ leaf: LinkedLeafStruct.dummy(),
60
+ }),
61
+ leafCurrent: readWitness,
62
+ });
63
+ }
64
+ }
65
+
66
+ return class AbstractLinkedRollupMerkleTree
67
+ implements AbstractLinkedMerkleTree
68
+ {
69
+ public static HEIGHT = height;
70
+
71
+ public static EMPTY_ROOT = new AbstractLinkedRollupMerkleTree(
72
+ new InMemoryMerkleTreeStorage(),
73
+ new InMemoryLinkedLeafStore()
74
+ ).getRoot();
75
+
76
+ public static READ_WITNESS = LinkedLeafAndMerkleWitness;
77
+
78
+ public static WITNESS = LinkedOperationWitness;
79
+
80
+ readonly tree: RollupMerkleTree;
81
+
82
+ readonly leafStore: LinkedLeafStore;
83
+
84
+ public constructor(store: MerkleTreeStore, leafStore: LinkedLeafStore) {
85
+ this.leafStore = leafStore;
86
+
87
+ this.tree = new SparseTreeClass(store);
88
+
89
+ // We only do the leaf initialisation when the store
90
+ // has no values. Otherwise, we leave the store
91
+ // as is to not overwrite any data.
92
+ if (this.leafStore.getLeaf(0n) === undefined) {
93
+ this.setLeafInitialisation();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Returns leaf which lives at a given path.
99
+ * Errors if the path is not defined.
100
+ * @param path path of the node.
101
+ * @returns The data of the node.
102
+ */
103
+ public getLeaf(path: bigint): LinkedLeafStruct | undefined {
104
+ const storedLeaf = this.leafStore.getLeaf(path);
105
+ if (storedLeaf === undefined) {
106
+ return undefined;
107
+ }
108
+ return new LinkedLeafStruct({
109
+ value: Field(storedLeaf.leaf.value),
110
+ path: Field(storedLeaf.leaf.path),
111
+ nextPath: Field(storedLeaf.leaf.nextPath),
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Returns the root of the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree).
117
+ * @returns The root of the Merkle Tree.
118
+ */
119
+ public getRoot(): Field {
120
+ return this.tree.getRoot().toConstant();
121
+ }
122
+
123
+ private writeLeaf(index: bigint, leaf: LinkedLeaf) {
124
+ this.leafStore.setLeaf(index, leaf);
125
+
126
+ const leafHash = new LinkedLeafStruct(
127
+ LinkedLeafStruct.fromValue(leaf)
128
+ ).hash();
129
+
130
+ return {
131
+ index,
132
+ leaf: leafHash,
133
+ };
134
+ }
135
+
136
+ private setLeafInternal(path: bigint, value: bigint): SetLeafMetadata {
137
+ const storedLeaf = this.leafStore.getLeaf(path);
138
+
139
+ if (storedLeaf === undefined) {
140
+ // Insert case
141
+ // The above means the path doesn't already exist, and we are inserting, not updating.
142
+ // This requires us to update the node with the previous path, as well.
143
+ const tempIndex = this.leafStore.getMaximumIndex();
144
+ if (tempIndex === undefined) {
145
+ throw Error("Store Max Index not defined");
146
+ }
147
+ if (tempIndex + 1n >= 2 ** height) {
148
+ throw new Error("Index greater than maximum leaf number");
149
+ }
150
+ const nextFreeIndex = tempIndex + 1n;
151
+
152
+ const previousLeaf = this.leafStore.getPreviousLeaf(path);
153
+
154
+ if (previousLeaf === undefined) {
155
+ throw Error(`Prev leaf shouldn't be undefined (path ${path})`);
156
+ }
157
+
158
+ const newPrevLeaf = {
159
+ ...previousLeaf.leaf,
160
+ nextPath: path,
161
+ };
162
+ const treeWrite1 = this.writeLeaf(previousLeaf.index, newPrevLeaf);
163
+
164
+ const newLeaf = {
165
+ path,
166
+ value,
167
+ nextPath: previousLeaf.leaf.nextPath,
168
+ };
169
+ const treeWrite2 = this.writeLeaf(nextFreeIndex, newLeaf);
170
+
171
+ return {
172
+ leafPrevious: {
173
+ witness: previousLeaf.index,
174
+ witnessLeaf: new LinkedLeafStruct(
175
+ LinkedLeafStruct.fromValue(previousLeaf.leaf)
176
+ ),
177
+ write: treeWrite1,
178
+ },
179
+ leafCurrent: {
180
+ witness: nextFreeIndex,
181
+ witnessLeaf: LinkedLeafStruct.dummy(),
182
+ write: treeWrite2,
183
+ },
184
+ };
185
+ } else {
186
+ // Update case
187
+ const updatedLeaf = {
188
+ ...storedLeaf.leaf,
189
+ value: value,
190
+ };
191
+
192
+ const treeWrite = this.writeLeaf(storedLeaf.index, updatedLeaf);
193
+
194
+ return {
195
+ leafPrevious: "dummy",
196
+ leafCurrent: {
197
+ witness: storedLeaf.index,
198
+ witnessLeaf: new LinkedLeafStruct(
199
+ LinkedLeafStruct.fromValue(storedLeaf.leaf)
200
+ ),
201
+ write: treeWrite,
202
+ },
203
+ };
204
+ }
205
+ }
206
+
207
+ private applyOperationInstruction(
208
+ instruction: LeafOperationInstruction | "dummy"
209
+ ): LinkedLeafAndMerkleWitness {
210
+ if (instruction === "dummy") {
211
+ return AbstractLinkedRollupMerkleTree.dummyReadWitness();
212
+ }
213
+
214
+ const merkleWitness = this.tree.getWitness(instruction.witness);
215
+
216
+ this.tree.setLeaf(instruction.write.index, instruction.write.leaf);
217
+
218
+ return new LinkedLeafAndMerkleWitness({
219
+ merkleWitness,
220
+ leaf: instruction.witnessLeaf,
221
+ });
222
+ }
223
+
224
+ /**
225
+ * Sets the value of a node at a given index to a given value.
226
+ * @param path Position of the leaf node.
227
+ * @param value New value.
228
+ */
229
+ public setLeaf(path: bigint, value: bigint): LinkedOperationWitness {
230
+ const {
231
+ leafPrevious: previousLeafInstruction,
232
+ leafCurrent: currentLeafInstruction,
233
+ } = this.setLeafInternal(path, value);
234
+
235
+ const leafPrevious = this.applyOperationInstruction(
236
+ previousLeafInstruction
237
+ );
238
+ const leafCurrent = this.applyOperationInstruction(
239
+ currentLeafInstruction
240
+ );
241
+
242
+ return { leafPrevious, leafCurrent };
243
+ }
244
+
245
+ public setLeaves(batch: { path: bigint; value: bigint }[]) {
246
+ if (batch.length > 0) {
247
+ const witnesses = batch.map(({ path, value }) =>
248
+ this.setLeafInternal(path, value)
249
+ );
250
+
251
+ // tree.setLeafBatch internally takes care of making the writes unique to optimize
252
+ this.tree.setLeaves(
253
+ witnesses.flatMap(({ leafPrevious, leafCurrent }) =>
254
+ (leafPrevious === "dummy" ? [] : [leafPrevious.write]).concat(
255
+ leafCurrent.write
256
+ )
257
+ )
258
+ );
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Sets the value of a leaf node at initialisation,
264
+ * i.e. {vale: 0, path: 0, nextPath: Field.Max}
265
+ */
266
+ private setLeafInitialisation() {
267
+ // This is the maximum value of the hash
268
+ const MAX_FIELD_VALUE: bigint = Field.ORDER - 1n;
269
+ const zeroLeaf = {
270
+ value: 0n,
271
+ path: 0n,
272
+ nextPath: MAX_FIELD_VALUE,
273
+ };
274
+ this.leafStore.setLeaf(0n, zeroLeaf);
275
+ // We now set the leafs in the merkle tree to cascade the values up
276
+ // the tree.
277
+ this.tree.setLeaf(
278
+ 0n,
279
+ new LinkedLeafStruct(LinkedLeafStruct.fromValue(zeroLeaf)).hash()
280
+ );
281
+ }
282
+
283
+ /**
284
+ * Returns the witness (also known as
285
+ * [Merkle Proof or Merkle Witness](https://computersciencewiki.org/index.php/Merkle_proof))
286
+ * for the leaf at the given path, otherwise returns a witness for the first unused index.
287
+ * @param path of the leaf node.
288
+ * @returns The witness that belongs to the leaf.
289
+ */
290
+ public getReadWitness(path: bigint): LinkedLeafAndMerkleWitness {
291
+ const storedLeaf = this.leafStore.getLeaf(path);
292
+ let leaf;
293
+ let currentIndex: bigint;
294
+
295
+ if (storedLeaf === undefined) {
296
+ const storeIndex = this.leafStore.getMaximumIndex();
297
+ if (storeIndex === undefined) {
298
+ throw new Error("Store undefined");
299
+ }
300
+ currentIndex = storeIndex + 1n;
301
+ leaf = LinkedLeafStruct.dummy();
302
+ } else {
303
+ leaf = new LinkedLeafStruct(
304
+ LinkedLeafStruct.fromValue(storedLeaf.leaf)
305
+ );
306
+ currentIndex = storedLeaf.index;
307
+ }
308
+
309
+ const merkleWitness = this.tree.getWitness(currentIndex);
310
+
311
+ return new LinkedLeafAndMerkleWitness({
312
+ merkleWitness,
313
+ leaf,
314
+ });
315
+ }
316
+
317
+ public static dummyReadWitness(): LinkedLeafAndMerkleWitness {
318
+ return new LinkedLeafAndMerkleWitness({
319
+ merkleWitness: SparseTreeClass.WITNESS.dummy(),
320
+ leaf: LinkedLeafStruct.dummy(),
321
+ });
322
+ }
323
+
324
+ public static dummyWitness() {
325
+ return new LinkedOperationWitness({
326
+ leafPrevious: AbstractLinkedRollupMerkleTree.dummyReadWitness(),
327
+ leafCurrent: AbstractLinkedRollupMerkleTree.dummyReadWitness(),
328
+ });
329
+ }
330
+ };
331
+ }
332
+
333
+ export class LinkedMerkleTree extends createLinkedMerkleTree(40) {}
334
+ export class LinkedMerkleTreeWitness extends LinkedMerkleTree.WITNESS {}
335
+ export class LinkedMerkleTreeReadWitness extends LinkedMerkleTree.READ_WITNESS {}
@@ -0,0 +1,188 @@
1
+ import { Bool, Field, Provable, Struct } from "o1js";
2
+
3
+ import { LinkedMerkleTreeWitness } from "./LinkedMerkleTree";
4
+ import { LinkedLeafStruct } from "./LinkedMerkleTreeTypes";
5
+
6
+ /* eslint-disable no-inner-declarations */
7
+ // TODO Add a struct that captures the errors monad-style
8
+
9
+ export type TreeWrite = {
10
+ path: Field;
11
+ from: Field;
12
+ to: Field;
13
+ };
14
+
15
+ export namespace LinkedMerkleTreeCircuitOps {
16
+ function boolAllTrue(...args: Bool[]): Bool {
17
+ return args.reduce((a, b, i) => {
18
+ // if (!b.toBoolean()) {
19
+ // console.log();
20
+ // }
21
+ return a.and(b);
22
+ });
23
+ }
24
+
25
+ export class ComputeRootInstruction extends Struct({
26
+ newPreviousLeaf: LinkedLeafStruct,
27
+ newCurrentLeaf: LinkedLeafStruct,
28
+ allChecksMet: Bool,
29
+ }) {}
30
+
31
+ function chooseInstruction(
32
+ isUpdate: Bool,
33
+ updateInstruction: ComputeRootInstruction,
34
+ insertInstruction: ComputeRootInstruction
35
+ ): ComputeRootInstruction {
36
+ return Provable.if(
37
+ isUpdate,
38
+ ComputeRootInstruction,
39
+ updateInstruction,
40
+ insertInstruction
41
+ );
42
+ }
43
+
44
+ /**
45
+ * verifyWitness(current.merkleWitness, current.leaf)
46
+ *
47
+ * st.path == current.leaf.path
48
+ * st.from.value == current.leaf.value
49
+ * ```
50
+ *
51
+ * updates:
52
+ * ```
53
+ * current := { current.path, current.nextPath, value: st.to.value }
54
+ */
55
+ function update(
56
+ { leafCurrent, leafPrevious }: LinkedMerkleTreeWitness,
57
+ { to, from, path }: TreeWrite
58
+ ): ComputeRootInstruction {
59
+ const allChecksMet = boolAllTrue(
60
+ path.equals(leafCurrent.leaf.path),
61
+ leafCurrent.leaf.value.equals(from)
62
+ );
63
+
64
+ return {
65
+ newPreviousLeaf: leafPrevious.leaf,
66
+ newCurrentLeaf: new LinkedLeafStruct({
67
+ ...leafCurrent.leaf,
68
+ value: to,
69
+ }),
70
+ allChecksMet,
71
+ };
72
+ }
73
+
74
+ /**
75
+ * st.path == current.leaf.path
76
+ *
77
+ * previous.leaf.nextPath > current.leaf.path
78
+ * previous.leaf.path < current.leaf.path
79
+ * previous.leaf.nextPath == current.leaf.nextPath
80
+ *
81
+ * index(current.merkleWitness) == nextFreeIndex
82
+ *
83
+ * updates:
84
+ * previous := { previous.path, previous.value, nextPath: current.path }
85
+ * current := current.leaf
86
+ */
87
+ function insert(
88
+ witness: LinkedMerkleTreeWitness,
89
+ { path, to }: TreeWrite
90
+ ): ComputeRootInstruction {
91
+ const { leafPrevious: previous, leafCurrent: current } = witness;
92
+
93
+ const allChecksMet = boolAllTrue(
94
+ // Already covered in general checks
95
+ // path.equals(current.leaf.path),
96
+ current.leaf.isDummy(),
97
+ previous.leaf.nextPath.greaterThan(path),
98
+ previous.leaf.path.lessThan(path)
99
+ );
100
+
101
+ return {
102
+ newPreviousLeaf: new LinkedLeafStruct({
103
+ ...previous.leaf,
104
+ nextPath: path,
105
+ }),
106
+ newCurrentLeaf: new LinkedLeafStruct({
107
+ path,
108
+ value: to,
109
+ nextPath: previous.leaf.nextPath,
110
+ }),
111
+ allChecksMet,
112
+ };
113
+ }
114
+
115
+ function computeRoot(
116
+ witness: LinkedMerkleTreeWitness,
117
+ newPreviousLeaf: LinkedLeafStruct,
118
+ newCurrentLeaf: LinkedLeafStruct,
119
+ isUpdate: Bool,
120
+ isDummy: Bool,
121
+ root: Field
122
+ ) {
123
+ const { leafPrevious, leafCurrent } = witness;
124
+
125
+ leafPrevious.merkleWitness
126
+ .calculateRoot(leafPrevious.leaf.hash())
127
+ .equals(root)
128
+ .or(isUpdate)
129
+ .assertTrue("Previous leaf calculation not matching");
130
+
131
+ const root1 = leafPrevious.merkleWitness.calculateRoot(
132
+ newPreviousLeaf.hash()
133
+ );
134
+
135
+ const intermediateRoot = Provable.if(isUpdate, root, root1);
136
+
137
+ // TODO Make this Provable.if more efficient
138
+ const leafCurrentLeaf = Provable.if(
139
+ isUpdate,
140
+ leafCurrent.leaf.hash(),
141
+ Field(0)
142
+ );
143
+ leafCurrent.merkleWitness
144
+ .calculateRoot(leafCurrentLeaf)
145
+ .equals(intermediateRoot)
146
+ .or(isDummy)
147
+ .assertTrue("Current leaf witness invalid");
148
+
149
+ return leafCurrent.merkleWitness.calculateRoot(newCurrentLeaf.hash());
150
+ }
151
+
152
+ export function applyTreeWrite(
153
+ root: Field,
154
+ witness: LinkedMerkleTreeWitness,
155
+ treeWrite: TreeWrite,
156
+ index: number
157
+ ): Field {
158
+ const { leafPrevious, leafCurrent } = witness;
159
+
160
+ const isUpdate = leafPrevious.leaf.isDummy();
161
+ const isDummy = leafCurrent.leaf.isDummy().and(isUpdate);
162
+
163
+ // For read-only and update
164
+ const updateState = update(witness, treeWrite);
165
+
166
+ // For insert
167
+ const insertState = insert(witness, treeWrite);
168
+
169
+ const instruction = chooseInstruction(isUpdate, updateState, insertState);
170
+
171
+ instruction.allChecksMet
172
+ .or(isDummy)
173
+ .assertTrue(`Not all witness checks have been met: ${index}`);
174
+
175
+ const newRoot = computeRoot(
176
+ witness,
177
+ instruction.newPreviousLeaf,
178
+ instruction.newCurrentLeaf,
179
+ isUpdate,
180
+ isDummy,
181
+ root
182
+ );
183
+
184
+ return Provable.if(isDummy, root, newRoot);
185
+ }
186
+ }
187
+
188
+ /* eslint-enable no-inner-declarations */
@@ -0,0 +1,53 @@
1
+ import { Field, Poseidon, Provable, Struct } from "o1js";
2
+
3
+ export class LinkedLeafStruct extends Struct({
4
+ value: Field,
5
+ path: Field,
6
+ nextPath: Field,
7
+ }) {
8
+ public isDummy() {
9
+ return this.path.equals(0).and(this.nextPath.equals(0));
10
+ }
11
+
12
+ public hash(): Field {
13
+ const hash = Poseidon.hash(LinkedLeafStruct.toFields(this));
14
+ return Provable.if(this.isDummy(), Field(0), hash);
15
+ }
16
+
17
+ public static dummy(): LinkedLeafStruct {
18
+ return new LinkedLeafStruct({
19
+ value: Field(0),
20
+ path: Field(0),
21
+ nextPath: Field(0),
22
+ });
23
+ }
24
+ }
25
+
26
+ // export class LinkedMerkleTreeGlobalState extends Struct({
27
+ // root: Field,
28
+ // lastOccupiedIndex: Field,
29
+ // }) {
30
+ // public static equals(
31
+ // state1: LinkedMerkleTreeGlobalState,
32
+ // state2: LinkedMerkleTreeGlobalState
33
+ // ): Bool {
34
+ // return state1.root
35
+ // .equals(state2.root)
36
+ // .and(state1.lastOccupiedIndex.equals(state2.lastOccupiedIndex));
37
+ // }
38
+ //
39
+ // public static assertEquals(
40
+ // state1: LinkedMerkleTreeGlobalState,
41
+ // state2: LinkedMerkleTreeGlobalState,
42
+ // msg?: string
43
+ // ) {
44
+ // state1.root.assertEquals(
45
+ // state2.root,
46
+ // msg !== undefined ? `${msg}: root` : msg
47
+ // );
48
+ // state1.lastOccupiedIndex.assertEquals(
49
+ // state2.lastOccupiedIndex,
50
+ // msg !== undefined ? `${msg}: lastOccupiedIndex` : msg
51
+ // );
52
+ // }
53
+ // }
@@ -0,0 +1,17 @@
1
+ import { MerkleTreeStore } from "./MerkleTreeStore";
2
+
3
+ export class InMemoryMerkleTreeStorage implements MerkleTreeStore {
4
+ public nodes: {
5
+ [key: number]: {
6
+ [key: string]: bigint;
7
+ };
8
+ } = {};
9
+
10
+ public getNode(key: bigint, level: number): bigint | undefined {
11
+ return this.nodes[level]?.[key.toString()];
12
+ }
13
+
14
+ public setNode(key: bigint, level: number, value: bigint): void {
15
+ (this.nodes[level] ??= {})[key.toString()] = value;
16
+ }
17
+ }
@@ -0,0 +1,5 @@
1
+ export interface MerkleTreeStore {
2
+ setNode: (key: bigint, level: number, value: bigint) => void;
3
+
4
+ getNode: (key: bigint, level: number) => bigint | undefined;
5
+ }
@@ -0,0 +1,30 @@
1
+ import { noop } from "../../utils";
2
+
3
+ import { InMemoryMerkleTreeStorage } from "./InMemoryMerkleTreeStorage";
4
+
5
+ export class MockAsyncMerkleTreeStore {
6
+ public readonly store = new InMemoryMerkleTreeStorage();
7
+
8
+ public commit(): void {
9
+ noop();
10
+ }
11
+
12
+ public openTransaction(): void {
13
+ noop();
14
+ }
15
+
16
+ public async getNodeAsync(
17
+ key: bigint,
18
+ level: number
19
+ ): Promise<bigint | undefined> {
20
+ return this.store.getNode(key, level);
21
+ }
22
+
23
+ public async setNodeAsync(
24
+ key: bigint,
25
+ level: number,
26
+ value: bigint
27
+ ): Promise<void> {
28
+ this.store.setNode(key, level, value);
29
+ }
30
+ }