@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,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,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
|
+
}
|