@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.
- package/dist/cache/CacheManifest.d.ts +11 -0
- package/dist/cache/CacheManifest.d.ts.map +1 -0
- package/dist/cache/CacheManifest.js +56 -0
- package/dist/cache/CacheManifest.js.map +1 -0
- package/dist/cache/ProxyCache.d.ts +13 -0
- package/dist/cache/ProxyCache.d.ts.map +1 -0
- package/dist/cache/ProxyCache.js +24 -0
- package/dist/cache/ProxyCache.js.map +1 -0
- package/dist/cache/RemoteCache.d.ts +8 -0
- package/dist/cache/RemoteCache.d.ts.map +1 -0
- package/dist/cache/RemoteCache.js +2 -0
- package/dist/cache/RemoteCache.js.map +1 -0
- package/dist/cache/RemoteCacheCompiler.d.ts +16 -0
- package/dist/cache/RemoteCacheCompiler.d.ts.map +1 -0
- package/dist/cache/RemoteCacheCompiler.js +104 -0
- package/dist/cache/RemoteCacheCompiler.js.map +1 -0
- package/dist/compiling/AtomicCompileHelper.d.ts +15 -0
- package/dist/compiling/AtomicCompileHelper.d.ts.map +1 -0
- package/dist/compiling/AtomicCompileHelper.js +61 -0
- package/dist/compiling/AtomicCompileHelper.js.map +1 -0
- package/dist/compiling/CompilableModule.d.ts +6 -0
- package/dist/compiling/CompilableModule.d.ts.map +1 -0
- package/dist/compiling/CompilableModule.js +2 -0
- package/dist/compiling/CompilableModule.js.map +1 -0
- package/dist/compiling/CompileRegistry.d.ts +25 -0
- package/dist/compiling/CompileRegistry.d.ts.map +1 -0
- package/dist/compiling/CompileRegistry.js +62 -0
- package/dist/compiling/CompileRegistry.js.map +1 -0
- package/dist/compiling/services/ChildVerificationKeyService.d.ts +10 -0
- package/dist/compiling/services/ChildVerificationKeyService.d.ts.map +1 -0
- package/dist/compiling/services/ChildVerificationKeyService.js +27 -0
- package/dist/compiling/services/ChildVerificationKeyService.js.map +1 -0
- package/dist/config/ChildContainerCreatable.d.ts +5 -0
- package/dist/config/ChildContainerCreatable.d.ts.map +1 -0
- package/dist/config/ChildContainerCreatable.js +2 -0
- package/dist/config/ChildContainerCreatable.js.map +1 -0
- package/dist/config/ChildContainerProvider.d.ts +5 -0
- package/dist/config/ChildContainerProvider.d.ts.map +1 -0
- package/dist/config/ChildContainerProvider.js +2 -0
- package/dist/config/ChildContainerProvider.js.map +1 -0
- package/dist/config/ConfigurableModule.d.ts +6 -2
- package/dist/config/ConfigurableModule.d.ts.map +1 -1
- package/dist/config/ConfigurableModule.js +5 -0
- package/dist/config/ConfigurableModule.js.map +1 -0
- package/dist/config/ModuleContainer.d.ts +70 -23
- package/dist/config/ModuleContainer.d.ts.map +1 -1
- package/dist/config/ModuleContainer.js +164 -31
- package/dist/config/ModuleContainer.js.map +1 -0
- package/dist/config/Startable.d.ts +4 -0
- package/dist/config/Startable.d.ts.map +1 -0
- package/dist/config/Startable.js +2 -0
- package/dist/config/Startable.js.map +1 -0
- package/dist/config/injectAlias.d.ts +18 -0
- package/dist/config/injectAlias.d.ts.map +1 -0
- package/dist/config/injectAlias.js +47 -0
- package/dist/config/injectAlias.js.map +1 -0
- package/dist/dependencyFactory/DependencyFactory.d.ts +14 -9
- package/dist/dependencyFactory/DependencyFactory.d.ts.map +1 -1
- package/dist/dependencyFactory/DependencyFactory.js +2 -96
- package/dist/dependencyFactory/DependencyFactory.js.map +1 -0
- package/dist/dependencyFactory/injectOptional.d.ts +16 -0
- package/dist/dependencyFactory/injectOptional.d.ts.map +1 -0
- package/dist/dependencyFactory/injectOptional.js +40 -0
- package/dist/dependencyFactory/injectOptional.js.map +1 -0
- package/dist/dummyVerificationKey.d.ts +3 -0
- package/dist/dummyVerificationKey.d.ts.map +1 -0
- package/dist/dummyVerificationKey.js +8 -0
- package/dist/dummyVerificationKey.js.map +1 -0
- package/dist/events/EventEmitter.d.ts +19 -0
- package/dist/events/EventEmitter.d.ts.map +1 -0
- package/dist/events/EventEmitter.js +35 -0
- package/dist/events/EventEmitter.js.map +1 -0
- package/dist/events/EventEmitterProxy.d.ts +18 -0
- package/dist/events/EventEmitterProxy.d.ts.map +1 -0
- package/dist/events/EventEmitterProxy.js +35 -0
- package/dist/events/EventEmitterProxy.js.map +1 -0
- package/dist/events/EventEmittingComponent.d.ts +9 -0
- package/dist/events/EventEmittingComponent.d.ts.map +1 -0
- package/dist/events/EventEmittingComponent.js +2 -0
- package/dist/events/EventEmittingComponent.js.map +1 -0
- package/dist/events/ReplayingSingleUseEventEmitter.d.ts +17 -0
- package/dist/events/ReplayingSingleUseEventEmitter.d.ts.map +1 -0
- package/dist/events/ReplayingSingleUseEventEmitter.js +34 -0
- package/dist/events/ReplayingSingleUseEventEmitter.js.map +1 -0
- package/dist/index.d.ts +27 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/index.js.map +1 -0
- package/dist/log.d.ts +37 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +117 -0
- package/dist/log.js.map +1 -0
- package/dist/trees/InMemoryLinkedLeafStore.d.ts +21 -0
- package/dist/trees/InMemoryLinkedLeafStore.d.ts.map +1 -0
- package/dist/trees/InMemoryLinkedLeafStore.js +26 -0
- package/dist/trees/InMemoryLinkedLeafStore.js.map +1 -0
- package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
- package/dist/trees/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
- package/dist/trees/InMemoryLinkedMerkleLeafStore.js +6 -0
- package/dist/trees/InMemoryLinkedMerkleLeafStore.js.map +1 -0
- package/dist/trees/InMemoryMerkleTreeStorage.d.ts +11 -0
- package/dist/trees/InMemoryMerkleTreeStorage.d.ts.map +1 -0
- package/dist/trees/InMemoryMerkleTreeStorage.js +13 -0
- package/dist/trees/InMemoryMerkleTreeStorage.js.map +1 -0
- package/dist/trees/LinkedMerkleTree.d.ts +345 -0
- package/dist/trees/LinkedMerkleTree.d.ts.map +1 -0
- package/dist/trees/LinkedMerkleTree.js +337 -0
- package/dist/trees/LinkedMerkleTree.js.map +1 -0
- package/dist/trees/LinkedMerkleTreeStore.d.ts +24 -0
- package/dist/trees/LinkedMerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/LinkedMerkleTreeStore.js +2 -0
- package/dist/trees/LinkedMerkleTreeStore.js.map +1 -0
- package/dist/trees/MerkleTreeStore.d.ts +5 -0
- package/dist/trees/MerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/MerkleTreeStore.js +2 -0
- package/dist/trees/MerkleTreeStore.js.map +1 -0
- package/dist/trees/MockAsyncMerkleStore.d.ts +9 -0
- package/dist/trees/MockAsyncMerkleStore.d.ts.map +1 -0
- package/dist/trees/MockAsyncMerkleStore.js +20 -0
- package/dist/trees/MockAsyncMerkleStore.js.map +1 -0
- package/dist/trees/RollupMerkleTree.d.ts +147 -0
- package/dist/trees/RollupMerkleTree.d.ts.map +1 -0
- package/dist/trees/RollupMerkleTree.js +218 -0
- package/dist/trees/RollupMerkleTree.js.map +1 -0
- package/dist/trees/VirtualMerkleTreeStore.d.ts +13 -0
- package/dist/trees/VirtualMerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/VirtualMerkleTreeStore.js +18 -0
- package/dist/trees/VirtualMerkleTreeStore.js.map +1 -0
- package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts +288 -0
- package/dist/trees/lmt/AbstractLinkedMerkleTree.d.ts.map +1 -0
- package/dist/trees/lmt/AbstractLinkedMerkleTree.js +22 -0
- package/dist/trees/lmt/AbstractLinkedMerkleTree.js.map +1 -0
- package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts +21 -0
- package/dist/trees/lmt/InMemoryLinkedLeafStore.d.ts.map +1 -0
- package/dist/trees/lmt/InMemoryLinkedLeafStore.js +26 -0
- package/dist/trees/lmt/InMemoryLinkedLeafStore.js.map +1 -0
- package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts +7 -0
- package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.d.ts.map +1 -0
- package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js +6 -0
- package/dist/trees/lmt/InMemoryLinkedMerkleLeafStore.js.map +1 -0
- package/dist/trees/lmt/LinkedLeafStore.d.ts +16 -0
- package/dist/trees/lmt/LinkedLeafStore.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedLeafStore.js +2 -0
- package/dist/trees/lmt/LinkedLeafStore.js.map +1 -0
- package/dist/trees/lmt/LinkedLinkedStore.d.ts +16 -0
- package/dist/trees/lmt/LinkedLinkedStore.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedLinkedStore.js +2 -0
- package/dist/trees/lmt/LinkedLinkedStore.js.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTree.d.ts +11 -0
- package/dist/trees/lmt/LinkedMerkleTree.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTree.js +241 -0
- package/dist/trees/lmt/LinkedMerkleTree.js.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts +113 -0
- package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js +113 -0
- package/dist/trees/lmt/LinkedMerkleTreeCircuitOps.js.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts +7 -0
- package/dist/trees/lmt/LinkedMerkleTreeDatabase.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeDatabase.js +2 -0
- package/dist/trees/lmt/LinkedMerkleTreeDatabase.js.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts +16 -0
- package/dist/trees/lmt/LinkedMerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeStore.js +2 -0
- package/dist/trees/lmt/LinkedMerkleTreeStore.js.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts +74 -0
- package/dist/trees/lmt/LinkedMerkleTreeTypes.d.ts.map +1 -0
- package/dist/trees/lmt/LinkedMerkleTreeTypes.js +50 -0
- package/dist/trees/lmt/LinkedMerkleTreeTypes.js.map +1 -0
- package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts +11 -0
- package/dist/trees/sparse/InMemoryMerkleTreeStorage.d.ts.map +1 -0
- package/dist/trees/sparse/InMemoryMerkleTreeStorage.js +13 -0
- package/dist/trees/sparse/InMemoryMerkleTreeStorage.js.map +1 -0
- package/dist/trees/sparse/MerkleTreeStore.d.ts +5 -0
- package/dist/trees/sparse/MerkleTreeStore.d.ts.map +1 -0
- package/dist/trees/sparse/MerkleTreeStore.js +2 -0
- package/dist/trees/sparse/MerkleTreeStore.js.map +1 -0
- package/dist/trees/sparse/MockAsyncMerkleStore.d.ts +9 -0
- package/dist/trees/sparse/MockAsyncMerkleStore.d.ts.map +1 -0
- package/dist/trees/sparse/MockAsyncMerkleStore.js +20 -0
- package/dist/trees/sparse/MockAsyncMerkleStore.js.map +1 -0
- package/dist/trees/sparse/RollupMerkleTree.d.ts +158 -0
- package/dist/trees/sparse/RollupMerkleTree.d.ts.map +1 -0
- package/dist/trees/sparse/RollupMerkleTree.js +330 -0
- package/dist/trees/sparse/RollupMerkleTree.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -1
- package/dist/types.js.map +1 -0
- package/dist/union/union.d.ts +177 -0
- package/dist/union/union.d.ts.map +1 -0
- package/dist/union/union.js +35 -0
- package/dist/union/union.js.map +1 -0
- package/dist/utils.d.ts +57 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +153 -4
- package/dist/utils.js.map +1 -0
- package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts +4 -3
- package/dist/zkProgrammable/ProvableMethodExecutionContext.d.ts.map +1 -1
- package/dist/zkProgrammable/ProvableMethodExecutionContext.js +2 -3
- package/dist/zkProgrammable/ProvableMethodExecutionContext.js.map +1 -0
- package/dist/zkProgrammable/ZkProgrammable.d.ts +32 -11
- package/dist/zkProgrammable/ZkProgrammable.d.ts.map +1 -1
- package/dist/zkProgrammable/ZkProgrammable.js +36 -17
- package/dist/zkProgrammable/ZkProgrammable.js.map +1 -0
- package/dist/zkProgrammable/provableMethod.d.ts +7 -4
- package/dist/zkProgrammable/provableMethod.d.ts.map +1 -1
- package/dist/zkProgrammable/provableMethod.js +30 -14
- package/dist/zkProgrammable/provableMethod.js.map +1 -0
- package/jest.config.cjs +12 -1
- package/package.json +9 -7
- package/src/cache/CacheManifest.ts +57 -0
- package/src/cache/ProxyCache.ts +30 -0
- package/src/cache/RemoteCache.ts +9 -0
- package/src/cache/RemoteCacheCompiler.ts +131 -0
- package/src/compiling/AtomicCompileHelper.ts +71 -0
- package/src/compiling/CompilableModule.ts +6 -0
- package/src/compiling/CompileRegistry.ts +64 -0
- package/src/compiling/services/ChildVerificationKeyService.ts +26 -0
- package/src/config/ChildContainerCreatable.ts +5 -0
- package/src/config/ChildContainerProvider.ts +5 -0
- package/src/config/ConfigurableModule.ts +15 -2
- package/src/config/ModuleContainer.ts +286 -58
- package/src/config/Startable.ts +3 -0
- package/src/config/injectAlias.ts +70 -0
- package/src/dependencyFactory/DependencyFactory.ts +34 -109
- package/src/dummyVerificationKey.ts +10 -0
- package/src/events/EventEmitter.ts +61 -0
- package/src/events/EventEmitterProxy.ts +81 -0
- package/src/events/EventEmittingComponent.ts +11 -0
- package/src/events/ReplayingSingleUseEventEmitter.ts +42 -0
- package/src/index.ts +27 -2
- package/src/log.ts +145 -0
- package/src/trees/lmt/AbstractLinkedMerkleTree.ts +102 -0
- package/src/trees/lmt/InMemoryLinkedLeafStore.ts +42 -0
- package/src/trees/lmt/LinkedLeafStore.ts +13 -0
- package/src/trees/lmt/LinkedMerkleTree.ts +335 -0
- package/src/trees/lmt/LinkedMerkleTreeCircuitOps.ts +188 -0
- package/src/trees/lmt/LinkedMerkleTreeTypes.ts +53 -0
- package/src/trees/sparse/InMemoryMerkleTreeStorage.ts +17 -0
- package/src/trees/sparse/MerkleTreeStore.ts +5 -0
- package/src/trees/sparse/MockAsyncMerkleStore.ts +30 -0
- package/src/trees/sparse/RollupMerkleTree.ts +512 -0
- package/src/types.ts +53 -2
- package/src/utils.ts +281 -5
- package/src/zkProgrammable/ProvableMethodExecutionContext.ts +6 -6
- package/src/zkProgrammable/ZkProgrammable.ts +90 -35
- package/src/zkProgrammable/provableMethod.ts +50 -23
- package/test/config/ContainerEvents.test.ts +65 -0
- package/test/config/ModuleContainer.test.ts +146 -15
- package/test/config/injectAlias.test.ts +28 -0
- package/test/trees/LinkedMerkleTree.test.ts +124 -0
- package/test/trees/LinkedMerkleTreeCircuitOps.test.ts +147 -0
- package/test/trees/MerkleTree.test.ts +251 -0
- package/test/tsconfig.json +5 -2
- package/test/zkProgrammable/ZkProgrammable.test.ts +145 -119
- package/tsconfig.json +1 -1
- package/LICENSE.md +0 -201
- package/tsconfig.test.json +0 -9
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { Bool, Field, Poseidon, Provable, Struct } from "o1js";
|
|
2
|
+
import uniqBy from "lodash/uniqBy";
|
|
3
|
+
|
|
4
|
+
import { range } from "../../utils";
|
|
5
|
+
import { TypedClass } from "../../types";
|
|
6
|
+
|
|
7
|
+
import { MerkleTreeStore } from "./MerkleTreeStore";
|
|
8
|
+
import { InMemoryMerkleTreeStorage } from "./InMemoryMerkleTreeStorage";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* More efficient version of `maybeSwapBad` which
|
|
12
|
+
* reuses an intermediate variable
|
|
13
|
+
*/
|
|
14
|
+
export function maybeSwap(b: Bool, x: Field, y: Field): [Field, Field] {
|
|
15
|
+
const m = b.toField().mul(x.sub(y)); // b*(x - y)
|
|
16
|
+
const x1 = y.add(m); // y + b*(x - y)
|
|
17
|
+
const y2 = x.sub(m); // x - b*(x - y) = x + b*(y - x)
|
|
18
|
+
return [x1, y2];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class StructTemplate extends Struct({
|
|
22
|
+
path: Provable.Array(Field, 0),
|
|
23
|
+
isLeft: Provable.Array(Bool, 0),
|
|
24
|
+
}) {}
|
|
25
|
+
|
|
26
|
+
export interface AbstractMerkleWitness extends StructTemplate {
|
|
27
|
+
height(): number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Calculates a root depending on the leaf value.
|
|
31
|
+
* @param hash Value of the leaf node that belongs to this Witness.
|
|
32
|
+
* @returns The calculated root.
|
|
33
|
+
*/
|
|
34
|
+
calculateRoot(hash: Field): Field;
|
|
35
|
+
|
|
36
|
+
calculateRootIncrement(
|
|
37
|
+
index: Field,
|
|
38
|
+
leaf: Field
|
|
39
|
+
): [Field, AbstractMerkleWitness];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Calculates the index of the leaf node that belongs to this Witness.
|
|
43
|
+
* @returns Index of the leaf.
|
|
44
|
+
*/
|
|
45
|
+
calculateIndex(): Field;
|
|
46
|
+
|
|
47
|
+
checkMembership(root: Field, key: Field, value: Field): Bool;
|
|
48
|
+
|
|
49
|
+
checkMembershipSimple(root: Field, value: Field): Bool;
|
|
50
|
+
|
|
51
|
+
checkMembershipGetRoots(
|
|
52
|
+
root: Field,
|
|
53
|
+
key: Field,
|
|
54
|
+
value: Field
|
|
55
|
+
): [Bool, Field, Field];
|
|
56
|
+
|
|
57
|
+
toShortenedEntries(): string[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface AbstractMerkleTree {
|
|
61
|
+
store: MerkleTreeStore;
|
|
62
|
+
readonly leafCount: bigint;
|
|
63
|
+
|
|
64
|
+
assertIndexRange(index: bigint): void;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns a node which lives at a given index and level.
|
|
68
|
+
* @param level Level of the node.
|
|
69
|
+
* @param index Index of the node.
|
|
70
|
+
* @returns The data of the node.
|
|
71
|
+
*/
|
|
72
|
+
getNode(level: number, index: bigint): Field;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns the root of the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree).
|
|
76
|
+
* @returns The root of the Merkle Tree.
|
|
77
|
+
*/
|
|
78
|
+
getRoot(): Field;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sets the value of a leaf node at a given index to a given value.
|
|
82
|
+
* @param index Position of the leaf node.
|
|
83
|
+
* @param leaf New value.
|
|
84
|
+
*/
|
|
85
|
+
setLeaf(index: bigint, leaf: Field): void;
|
|
86
|
+
|
|
87
|
+
setLeaves(updates: { index: bigint; leaf: Field }[]): void;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Returns the witness (also known as
|
|
91
|
+
* [Merkle Proof or Merkle Witness](https://computersciencewiki.org/index.php/Merkle_proof))
|
|
92
|
+
* for the leaf at the given index.
|
|
93
|
+
* @param index Position of the leaf node.
|
|
94
|
+
* @returns The witness that belongs to the leaf.
|
|
95
|
+
*/
|
|
96
|
+
getWitness(index: bigint): AbstractMerkleWitness;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Fills all leaves of the tree.
|
|
100
|
+
* @param leaves Values to fill the leaves with.
|
|
101
|
+
*/
|
|
102
|
+
fill(leaves: Field[]): void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface AbstractMerkleTreeClass {
|
|
106
|
+
new (store: MerkleTreeStore): AbstractMerkleTree;
|
|
107
|
+
|
|
108
|
+
WITNESS: TypedClass<AbstractMerkleWitness> &
|
|
109
|
+
typeof StructTemplate & { dummy: () => AbstractMerkleWitness };
|
|
110
|
+
|
|
111
|
+
HEIGHT: number;
|
|
112
|
+
|
|
113
|
+
EMPTY_ROOT: bigint;
|
|
114
|
+
|
|
115
|
+
get leafCount(): bigint;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* A [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) is a binary tree in
|
|
120
|
+
* which every leaf is the cryptography hash of a piece of data,
|
|
121
|
+
* and every node is the hash of the concatenation of its two child nodes.
|
|
122
|
+
*
|
|
123
|
+
* A Merkle Tree allows developers to easily and securely verify
|
|
124
|
+
* the integrity of large amounts of data.
|
|
125
|
+
*
|
|
126
|
+
* Take a look at our [documentation](https://docs.minaprotocol.com/en/zkapps)
|
|
127
|
+
* on how to use Merkle Trees in combination with zkApps and
|
|
128
|
+
* zero knowledge programming!
|
|
129
|
+
*
|
|
130
|
+
* Levels are indexed from leaves (level 0) to root (level N - 1).
|
|
131
|
+
*
|
|
132
|
+
* This function takes a height as argument and returns a class
|
|
133
|
+
* that implements a merkletree with that specified height.
|
|
134
|
+
*
|
|
135
|
+
* It also holds the Witness class under tree.WITNESS
|
|
136
|
+
*/
|
|
137
|
+
export function createMerkleTree(height: number): AbstractMerkleTreeClass {
|
|
138
|
+
function generateZeroes() {
|
|
139
|
+
const zeroes = [0n];
|
|
140
|
+
for (let index = 1; index < height; index += 1) {
|
|
141
|
+
const previousLevel = Field(zeroes[index - 1]);
|
|
142
|
+
zeroes.push(Poseidon.hash([previousLevel, previousLevel]).toBigInt());
|
|
143
|
+
}
|
|
144
|
+
return zeroes;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let zeroCache: bigint[] | undefined = undefined;
|
|
148
|
+
|
|
149
|
+
function getZeroes() {
|
|
150
|
+
if (zeroCache === undefined) {
|
|
151
|
+
zeroCache = generateZeroes();
|
|
152
|
+
}
|
|
153
|
+
return zeroCache;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* The {@link RollupMerkleWitness} class defines a circuit-compatible base class
|
|
158
|
+
* for [Merkle Witness'](https://computersciencewiki.org/index.php/Merkle_proof).
|
|
159
|
+
*/
|
|
160
|
+
class RollupMerkleWitness
|
|
161
|
+
extends Struct({
|
|
162
|
+
path: Provable.Array(Field, height - 1),
|
|
163
|
+
isLeft: Provable.Array(Bool, height - 1),
|
|
164
|
+
})
|
|
165
|
+
implements AbstractMerkleWitness
|
|
166
|
+
{
|
|
167
|
+
public static height = height;
|
|
168
|
+
|
|
169
|
+
public height(): number {
|
|
170
|
+
return RollupMerkleWitness.height;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Calculates a root depending on the leaf value.
|
|
175
|
+
* @param leaf Value of the leaf node that belongs to this Witness.
|
|
176
|
+
* @returns The calculated root.
|
|
177
|
+
*/
|
|
178
|
+
public calculateRoot(leaf: Field): Field {
|
|
179
|
+
let hash = leaf;
|
|
180
|
+
const n = this.height();
|
|
181
|
+
|
|
182
|
+
for (let index = 1; index < n; ++index) {
|
|
183
|
+
const isLeft = this.isLeft[index - 1];
|
|
184
|
+
|
|
185
|
+
const [left, right] = maybeSwap(isLeft, hash, this.path[index - 1]);
|
|
186
|
+
hash = Poseidon.hash([left, right]);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return hash;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public calculateRootIncrement(
|
|
193
|
+
leafIndex: Field,
|
|
194
|
+
leaf: Field
|
|
195
|
+
): [Field, RollupMerkleWitness] {
|
|
196
|
+
const root = this.calculateRoot(leaf);
|
|
197
|
+
|
|
198
|
+
const newWitness = Provable.witness(RollupMerkleWitness, () => {
|
|
199
|
+
const zero = getZeroes();
|
|
200
|
+
|
|
201
|
+
if (zero.length === 0) {
|
|
202
|
+
throw new Error("Zeroes not initialized");
|
|
203
|
+
}
|
|
204
|
+
const zeroes = zero.map((x) => Field(x));
|
|
205
|
+
|
|
206
|
+
let hash = leaf;
|
|
207
|
+
const n = this.height();
|
|
208
|
+
|
|
209
|
+
let notDiverged = true;
|
|
210
|
+
const newPath = leafIndex.add(1).toBits();
|
|
211
|
+
newPath.push(Bool(false));
|
|
212
|
+
|
|
213
|
+
const newSiblings: Field[] = [];
|
|
214
|
+
const newIsLefts: Bool[] = [];
|
|
215
|
+
|
|
216
|
+
for (let index = 0; index < n - 1; ++index) {
|
|
217
|
+
const isLeft = this.isLeft[index];
|
|
218
|
+
const sibling = this.path[index];
|
|
219
|
+
|
|
220
|
+
const newIsLeft = newPath[index].not();
|
|
221
|
+
|
|
222
|
+
// Bool(true) default for root level
|
|
223
|
+
let convergesNextLevel = true;
|
|
224
|
+
if (index < n - 2) {
|
|
225
|
+
convergesNextLevel = newPath[index + 1]
|
|
226
|
+
.equals(this.isLeft[index + 1])
|
|
227
|
+
.not()
|
|
228
|
+
.toBoolean();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const nextSibling =
|
|
232
|
+
// eslint-disable-next-line no-nested-ternary
|
|
233
|
+
convergesNextLevel && notDiverged
|
|
234
|
+
? hash
|
|
235
|
+
: notDiverged
|
|
236
|
+
? zeroes[index]
|
|
237
|
+
: sibling;
|
|
238
|
+
|
|
239
|
+
notDiverged = notDiverged && !convergesNextLevel;
|
|
240
|
+
|
|
241
|
+
newSiblings.push(nextSibling);
|
|
242
|
+
newIsLefts.push(newIsLeft);
|
|
243
|
+
|
|
244
|
+
const [left, right] = maybeSwap(isLeft, hash, sibling);
|
|
245
|
+
hash = Poseidon.hash([left, right]);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return new RollupMerkleWitness({
|
|
249
|
+
isLeft: newIsLefts,
|
|
250
|
+
path: newSiblings,
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
newWitness.calculateIndex().assertEquals(leafIndex.add(1));
|
|
255
|
+
|
|
256
|
+
return [root, newWitness];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Calculates the index of the leaf node that belongs to this Witness.
|
|
261
|
+
* @returns Index of the leaf.
|
|
262
|
+
*/
|
|
263
|
+
public calculateIndex(): Field {
|
|
264
|
+
let powerOfTwo = Field(1);
|
|
265
|
+
let index = Field(0);
|
|
266
|
+
const n = this.height();
|
|
267
|
+
|
|
268
|
+
for (let i = 1; i < n; ++i) {
|
|
269
|
+
index = Provable.if(this.isLeft[i - 1], index, index.add(powerOfTwo));
|
|
270
|
+
powerOfTwo = powerOfTwo.mul(2);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return index;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
public checkMembership(root: Field, key: Field, value: Field): Bool {
|
|
277
|
+
const calculatedRoot = this.calculateRoot(value);
|
|
278
|
+
const calculatedKey = this.calculateIndex();
|
|
279
|
+
// We don't have to range-check the key, because if it would be greater
|
|
280
|
+
// than leafCount, it would not match the computedKey
|
|
281
|
+
key.assertEquals(calculatedKey, "Keys of MerkleWitness does not match");
|
|
282
|
+
return root.equals(calculatedRoot);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public checkMembershipSimple(root: Field, value: Field): Bool {
|
|
286
|
+
const calculatedRoot = this.calculateRoot(value);
|
|
287
|
+
return root.equals(calculatedRoot);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
public checkMembershipGetRoots(
|
|
291
|
+
root: Field,
|
|
292
|
+
key: Field,
|
|
293
|
+
value: Field
|
|
294
|
+
): [Bool, Field, Field] {
|
|
295
|
+
const calculatedRoot = this.calculateRoot(value);
|
|
296
|
+
const calculatedKey = this.calculateIndex();
|
|
297
|
+
key.assertEquals(calculatedKey, "Keys of MerkleWitness does not match");
|
|
298
|
+
return [root.equals(calculatedRoot), root, calculatedRoot];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public toShortenedEntries() {
|
|
302
|
+
return range(0, 5)
|
|
303
|
+
.concat(range(this.height() - 4, this.height()))
|
|
304
|
+
.map((index) =>
|
|
305
|
+
[
|
|
306
|
+
this.path[index].toString(),
|
|
307
|
+
this.isLeft[index].toString(),
|
|
308
|
+
].toString()
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
public static dummy() {
|
|
313
|
+
return new RollupMerkleWitness({
|
|
314
|
+
isLeft: Array<Bool>(this.height - 1).fill(Bool(true)),
|
|
315
|
+
path: Array<Field>(this.height - 1).fill(Field(0)),
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return class AbstractRollupMerkleTree implements AbstractMerkleTree {
|
|
321
|
+
public static HEIGHT = height;
|
|
322
|
+
|
|
323
|
+
public static EMPTY_ROOT = new AbstractRollupMerkleTree(
|
|
324
|
+
new InMemoryMerkleTreeStorage()
|
|
325
|
+
)
|
|
326
|
+
.getRoot()
|
|
327
|
+
.toBigInt();
|
|
328
|
+
|
|
329
|
+
public static get leafCount(): bigint {
|
|
330
|
+
return 2n ** BigInt(AbstractRollupMerkleTree.HEIGHT - 1);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
public static WITNESS = RollupMerkleWitness;
|
|
334
|
+
|
|
335
|
+
// private in interface
|
|
336
|
+
// TODO Cache this in some static variable so that we don't recompute it every time
|
|
337
|
+
readonly zeroes: bigint[];
|
|
338
|
+
|
|
339
|
+
readonly store: MerkleTreeStore;
|
|
340
|
+
|
|
341
|
+
public constructor(store: MerkleTreeStore) {
|
|
342
|
+
this.store = store;
|
|
343
|
+
this.zeroes = generateZeroes();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
public assertIndexRange(index: bigint) {
|
|
347
|
+
if (index > this.leafCount) {
|
|
348
|
+
throw new Error("Index greater than maximum leaf number");
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Returns a node which lives at a given index and level.
|
|
354
|
+
* @param level Level of the node.
|
|
355
|
+
* @param index Index of the node.
|
|
356
|
+
* @returns The data of the node.
|
|
357
|
+
*/
|
|
358
|
+
public getNode(level: number, index: bigint): Field {
|
|
359
|
+
this.assertIndexRange(index);
|
|
360
|
+
return Field(this.store.getNode(index, level) ?? this.zeroes[level]);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Returns the root of the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree).
|
|
365
|
+
* @returns The root of the Merkle Tree.
|
|
366
|
+
*/
|
|
367
|
+
public getRoot(): Field {
|
|
368
|
+
return this.getNode(AbstractRollupMerkleTree.HEIGHT - 1, 0n).toConstant();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// private in interface
|
|
372
|
+
private setNode(level: number, index: bigint, value: Field) {
|
|
373
|
+
this.store.setNode(index, level, value.toBigInt());
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Sets the value of a leaf node at a given index to a given value.
|
|
378
|
+
* @param index Position of the leaf node.
|
|
379
|
+
* @param leaf New value.
|
|
380
|
+
*/
|
|
381
|
+
public setLeaf(index: bigint, leaf: Field) {
|
|
382
|
+
this.assertIndexRange(index);
|
|
383
|
+
|
|
384
|
+
this.setNode(0, index, leaf);
|
|
385
|
+
let currentIndex = index;
|
|
386
|
+
for (let level = 1; level < AbstractRollupMerkleTree.HEIGHT; level += 1) {
|
|
387
|
+
currentIndex /= 2n;
|
|
388
|
+
|
|
389
|
+
const left = this.getNode(level - 1, currentIndex * 2n);
|
|
390
|
+
const right = this.getNode(level - 1, currentIndex * 2n + 1n);
|
|
391
|
+
|
|
392
|
+
this.setNode(level, currentIndex, Poseidon.hash([left, right]));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
public setLeaves(updates: { index: bigint; leaf: Field }[]) {
|
|
397
|
+
updates.forEach(({ index }) => this.assertIndexRange(index));
|
|
398
|
+
|
|
399
|
+
type Change = { level: number; index: bigint; value: Field };
|
|
400
|
+
const changes: Change[] = [];
|
|
401
|
+
|
|
402
|
+
// We have to reverse here, because uniqBy only takes the first occurrence of every entry,
|
|
403
|
+
// but we need the last one (since that semantically overwrites the previous one,
|
|
404
|
+
// so we can ignore it)
|
|
405
|
+
let levelChanges = uniqBy(updates.reverse(), "index")
|
|
406
|
+
// we can assume no index is in this list twice, so we don't care about the 0 case
|
|
407
|
+
// This is in reverse order, so its a queue
|
|
408
|
+
.sort((a, b) => (a.index < b.index ? 1 : -1));
|
|
409
|
+
|
|
410
|
+
changes.push(
|
|
411
|
+
...levelChanges
|
|
412
|
+
.map(({ leaf, index }) => ({
|
|
413
|
+
level: 0,
|
|
414
|
+
index,
|
|
415
|
+
value: leaf,
|
|
416
|
+
}))
|
|
417
|
+
.reverse()
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
for (let level = 1; level < AbstractRollupMerkleTree.HEIGHT; level += 1) {
|
|
421
|
+
const nextLevelChanges: typeof levelChanges = [];
|
|
422
|
+
while (levelChanges.length > 0) {
|
|
423
|
+
const node = levelChanges.pop()!;
|
|
424
|
+
|
|
425
|
+
let newNode;
|
|
426
|
+
if (node.index % 2n === 0n) {
|
|
427
|
+
let sibling;
|
|
428
|
+
const potentialSibling = levelChanges.at(-1);
|
|
429
|
+
if (
|
|
430
|
+
potentialSibling !== undefined &&
|
|
431
|
+
potentialSibling.index === node.index + 1n
|
|
432
|
+
) {
|
|
433
|
+
sibling = potentialSibling.leaf;
|
|
434
|
+
levelChanges.pop();
|
|
435
|
+
} else {
|
|
436
|
+
sibling = Field(this.getNode(level - 1, node.index + 1n));
|
|
437
|
+
}
|
|
438
|
+
newNode = Poseidon.hash([node.leaf, sibling]);
|
|
439
|
+
} else {
|
|
440
|
+
const sibling = Field(this.getNode(level - 1, node.index - 1n));
|
|
441
|
+
newNode = Poseidon.hash([sibling, node.leaf]);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const nextLevelIndex = node.index / 2n;
|
|
445
|
+
changes.push({ level, index: nextLevelIndex, value: newNode });
|
|
446
|
+
nextLevelChanges.push({ index: nextLevelIndex, leaf: newNode });
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
levelChanges = nextLevelChanges.reverse();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
changes.forEach(({ level, index, value }) => {
|
|
453
|
+
this.setNode(level, index, value);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Returns the witness (also known as
|
|
459
|
+
* [Merkle Proof or Merkle Witness](https://computersciencewiki.org/index.php/Merkle_proof))
|
|
460
|
+
* for the leaf at the given index.
|
|
461
|
+
* @param index Position of the leaf node.
|
|
462
|
+
* @returns The witness that belongs to the leaf.
|
|
463
|
+
*/
|
|
464
|
+
public getWitness(index: bigint): RollupMerkleWitness {
|
|
465
|
+
this.assertIndexRange(index);
|
|
466
|
+
|
|
467
|
+
const path = [];
|
|
468
|
+
const isLefts = [];
|
|
469
|
+
let currentIndex = index;
|
|
470
|
+
for (
|
|
471
|
+
let level = 0;
|
|
472
|
+
level < AbstractRollupMerkleTree.HEIGHT - 1;
|
|
473
|
+
level += 1
|
|
474
|
+
) {
|
|
475
|
+
const isLeft = currentIndex % 2n === 0n;
|
|
476
|
+
const sibling = this.getNode(
|
|
477
|
+
level,
|
|
478
|
+
isLeft ? currentIndex + 1n : currentIndex - 1n
|
|
479
|
+
);
|
|
480
|
+
isLefts.push(Bool(isLeft));
|
|
481
|
+
path.push(sibling);
|
|
482
|
+
currentIndex /= 2n;
|
|
483
|
+
}
|
|
484
|
+
return new RollupMerkleWitness({
|
|
485
|
+
isLeft: isLefts,
|
|
486
|
+
path,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// TODO: should this take an optional offset? should it fail if the array is too long?
|
|
491
|
+
/**
|
|
492
|
+
* Fills all leaves of the tree.
|
|
493
|
+
* @param leaves Values to fill the leaves with.
|
|
494
|
+
*/
|
|
495
|
+
public fill(leaves: Field[]) {
|
|
496
|
+
leaves.forEach((value, index) => {
|
|
497
|
+
this.setLeaf(BigInt(index), value);
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Returns the amount of leaf nodes.
|
|
503
|
+
* @returns Amount of leaf nodes.
|
|
504
|
+
*/
|
|
505
|
+
public get leafCount(): bigint {
|
|
506
|
+
return AbstractRollupMerkleTree.leafCount;
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export class RollupMerkleTree extends createMerkleTree(256) {}
|
|
512
|
+
export class RollupMerkleTreeWitness extends RollupMerkleTree.WITNESS {}
|
package/src/types.ts
CHANGED
|
@@ -1,17 +1,68 @@
|
|
|
1
1
|
// allows to reference interfaces as 'classes' rather than instances
|
|
2
|
+
import {
|
|
3
|
+
Bool,
|
|
4
|
+
DynamicProof,
|
|
5
|
+
Field,
|
|
6
|
+
Proof,
|
|
7
|
+
ProofBase,
|
|
8
|
+
PublicKey,
|
|
9
|
+
Option,
|
|
10
|
+
} from "o1js";
|
|
11
|
+
|
|
2
12
|
export type TypedClass<Class> = new (...args: any[]) => Class;
|
|
3
13
|
|
|
14
|
+
export type UnTypedClass = new (...args: any[]) => unknown;
|
|
15
|
+
|
|
4
16
|
/**
|
|
5
17
|
* Using simple `keyof Target` would result into the key
|
|
6
18
|
* being `string | number | symbol`, but we want just a `string`
|
|
7
19
|
*/
|
|
8
20
|
export type StringKeyOf<Target extends object> = Extract<keyof Target, string> &
|
|
9
21
|
string;
|
|
10
|
-
// export type StringKeyOf<Target extends object> = keyof Target
|
|
11
22
|
|
|
12
23
|
/**
|
|
13
24
|
* Utility type to infer element type from an array type
|
|
14
25
|
*/
|
|
15
26
|
export type ArrayElement<ArrayType extends readonly unknown[]> =
|
|
16
|
-
// eslint-disable-next-line putout/putout
|
|
17
27
|
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Transforms X | Y => X & Y
|
|
31
|
+
*/
|
|
32
|
+
export type UnionToIntersection<Union> = (
|
|
33
|
+
Union extends any ? (x: Union) => void : never
|
|
34
|
+
) extends (x: infer Intersection) => void
|
|
35
|
+
? Intersection
|
|
36
|
+
: never;
|
|
37
|
+
|
|
38
|
+
export type MergeObjects<Input extends Record<string, unknown>> =
|
|
39
|
+
UnionToIntersection<Input[keyof Input]>;
|
|
40
|
+
|
|
41
|
+
export type OmitKeys<Record, Keys> = {
|
|
42
|
+
[Key in keyof Record as Key extends Keys ? never : Key]: Record[Key];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Because Publickey.empty() is not usable in combination with real
|
|
46
|
+
// cryptographic operations because it's group evaluation isn't defined in Fp,
|
|
47
|
+
// we use some other arbitrary point which we treat as "empty" in our circuits
|
|
48
|
+
// other arbitrary point
|
|
49
|
+
export const EMPTY_PUBLICKEY_X = Field(4600);
|
|
50
|
+
export const EMPTY_PUBLICKEY = PublicKey.fromObject({
|
|
51
|
+
x: EMPTY_PUBLICKEY_X,
|
|
52
|
+
isOdd: Bool(true),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export type OverwriteObjectType<Base, New> = {
|
|
56
|
+
[Key in keyof Base]: Key extends keyof New ? New[Key] : Base[Key];
|
|
57
|
+
} & New;
|
|
58
|
+
|
|
59
|
+
export type InferProofBase<
|
|
60
|
+
ProofType extends Proof<any, any> | DynamicProof<any, any>,
|
|
61
|
+
> =
|
|
62
|
+
ProofType extends Proof<infer PI, infer PO>
|
|
63
|
+
? ProofBase<PI, PO>
|
|
64
|
+
: ProofType extends DynamicProof<infer PI, infer PO>
|
|
65
|
+
? ProofBase<PI, PO>
|
|
66
|
+
: undefined;
|
|
67
|
+
|
|
68
|
+
export class O1PublicKeyOption extends Option(PublicKey) {}
|