Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update State Storage to use Linked Merkle Tree #211

Open
wants to merge 109 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
febf242
Start implementation
ejMina226 Oct 25, 2024
7dcca53
Define Leaf
ejMina226 Oct 25, 2024
11922ac
Start LinkedMerkleTree
ejMina226 Oct 25, 2024
e78afb7
Start LinkedMerkleTree
ejMina226 Oct 25, 2024
36d07bc
Create LinkedMerkleTreeStore
ejMina226 Oct 25, 2024
fba3f7c
Update LinkedMerkleTreeStore
ejMina226 Oct 28, 2024
da6d00c
Update interface with types.
ejMina226 Oct 28, 2024
da3f1ab
Update interface and get implementation for in memory linked merkle tree
ejMina226 Oct 29, 2024
ae09af0
Update interface
ejMina226 Oct 29, 2024
1c1ab2d
Working on LinkedMerkleTree
ejMina226 Oct 29, 2024
13f61a1
Add in getClosestPath
ejMina226 Oct 30, 2024
69dbaaa
Update GetWitness
ejMina226 Oct 30, 2024
d8930c0
Added in code to set leaf
ejMina226 Oct 30, 2024
162ab7d
Remove deleted reference
ejMina226 Oct 30, 2024
4527044
Set up constructor
ejMina226 Oct 30, 2024
ba198a9
Set up constructor and fix initialisation
ejMina226 Oct 31, 2024
671f563
Add in private
ejMina226 Oct 31, 2024
7c7c791
Update comment
ejMina226 Oct 31, 2024
bffd5d4
Update comment
ejMina226 Oct 31, 2024
743935d
Change confusing method name
ejMina226 Oct 31, 2024
1dfdcb4
Adding setValue
ejMina226 Oct 31, 2024
2423256
Changing setValue to insert and update
ejMina226 Oct 31, 2024
c1dc6ee
Change getPathLessOrEqual to include equal
ejMina226 Oct 31, 2024
1c3e27e
Change types as path and nextPath are bigint and not number
ejMina226 Oct 31, 2024
af96307
Update state transition prover to use LinkedMerkleTree
ejMina226 Nov 1, 2024
396c01f
Add types
ejMina226 Nov 5, 2024
5f3f6a2
Remove unnecessary code
ejMina226 Nov 5, 2024
72011b4
Add in-circuit checks for reading
ejMina226 Nov 6, 2024
cb39718
Add in-circuit checks for reading
ejMina226 Nov 6, 2024
2258c69
Update code for insertion (WIP)
ejMina226 Nov 6, 2024
b31c506
Merge develop
ejMina226 Nov 11, 2024
27f0220
Update code to reflect LinkedMerkleWitness
ejMina226 Nov 11, 2024
99ec28f
Update code for witnesses.
ejMina226 Nov 11, 2024
09874c3
Remove unuesed reference
ejMina226 Nov 11, 2024
e0d5f6e
Change order of witnesses.
ejMina226 Nov 11, 2024
279c5cc
Add spacing.
ejMina226 Nov 11, 2024
6c53d7d
Fix getWitness
ejMina226 Nov 12, 2024
9fedff9
Fix getWitness
ejMina226 Nov 12, 2024
c31d461
Get code compiling
ejMina226 Nov 12, 2024
64c38f0
Linting
ejMina226 Nov 12, 2024
1f97c28
Code review changes
ejMina226 Nov 12, 2024
648a5e3
Change STProver to cover update case.
ejMina226 Nov 12, 2024
7fa5638
Update MerkleTree.test.ts
ejMina226 Nov 13, 2024
7abadda
Update MerkleTree.test.ts
ejMina226 Nov 13, 2024
97328b0
Fix tests
ejMina226 Nov 13, 2024
b050d0e
Rename setValue to setLeaf in MerkleTree and setLeaf to setMerkleLeaf
ejMina226 Nov 13, 2024
7fbc30d
ImplementAsyncLinkedMerkleTreeStore
ejMina226 Nov 14, 2024
9c36f5d
Update index to make type available.
ejMina226 Nov 14, 2024
f2b9746
Started implementing CachedMerkleTreeStore
ejMina226 Nov 14, 2024
5aa8e85
Fix preload keys method.
ejMina226 Nov 14, 2024
13f074d
Change WriteLeaves method. Commented out old.
ejMina226 Nov 14, 2024
f82b91d
Commented out unneeded code.
ejMina226 Nov 14, 2024
94c34c7
Move changes to new file and restore original CachedMerkleTreeStore
ejMina226 Nov 14, 2024
02c9c69
Update types
ejMina226 Nov 14, 2024
bce8255
Add comments to STProver
ejMina226 Nov 15, 2024
708ef4b
Move LinekdMerkleTree test to own file.
ejMina226 Nov 15, 2024
a1d81d2
Created SyncCachedMerkleTree
ejMina226 Nov 15, 2024
a591f7b
Written InMemoryAsyncLinkedMerkleTreeStore.ts
ejMina226 Nov 15, 2024
fd75b34
Update tsyringe to fetch new types
ejMina226 Nov 15, 2024
b33b393
Add test suite. Fix error.
ejMina226 Nov 15, 2024
479eaef
Fix comment
ejMina226 Nov 15, 2024
f834493
Add tests and fixes.
ejMina226 Nov 18, 2024
a28a02b
Don't preload.
ejMina226 Nov 18, 2024
55dda23
Don't preload.
ejMina226 Nov 18, 2024
d0beafd
Get first few tests passing.
ejMina226 Nov 18, 2024
fe2ac0e
Get first test passing
ejMina226 Nov 19, 2024
fa5a44a
Undo test change.
ejMina226 Nov 19, 2024
0382057
Always preLoad last index to ensure later nodes are added afterwards
ejMina226 Nov 19, 2024
79c3688
Make constructor private and change code to accept static new
ejMina226 Nov 19, 2024
00dda91
Remove getPathClose in LinkedMerkleTree
ejMina226 Nov 19, 2024
9e3630c
Change how getPathLessOrEqual works
ejMina226 Nov 19, 2024
102f95e
Move changes to getNearestPath to another method on the cache and cal…
ejMina226 Nov 19, 2024
35cd1fa
Got syncedCachedLinkedMerkleTreeStoreWorking
ejMina226 Nov 20, 2024
adf4a87
Add in template for RedisLinkedMerkleTreeStore
ejMina226 Nov 20, 2024
a530f18
Change Max Field Value and update test
ejMina226 Nov 21, 2024
8f015bc
Max field, and other minor changes
ejMina226 Nov 21, 2024
0fb80ec
Update tests after code changes.
ejMina226 Nov 21, 2024
5eb3f5f
Add in more tests
ejMina226 Nov 21, 2024
14657c8
Change STProver
ejMina226 Nov 22, 2024
fc9768f
Change STProver
ejMina226 Nov 22, 2024
905cb39
Change STProver
ejMina226 Nov 22, 2024
5c11506
Change STProver
ejMina226 Nov 22, 2024
95af2e1
Update TxTraceService to take witnesses from setLeaf
ejMina226 Nov 22, 2024
7a85f8a
Update TxTraceService to pass in undefined
ejMina226 Nov 22, 2024
9601c1f
Fix error.
ejMina226 Nov 22, 2024
b908f25
Fix STProver to handle when we have dummies
ejMina226 Nov 22, 2024
dac7976
Circuits rewrite
ejMina226 Nov 25, 2024
4265bac
Fix STProver with extra clause.
ejMina226 Nov 25, 2024
585bf0e
Refactoring.
ejMina226 Nov 26, 2024
47c4401
Refactoring and getting LinkedTree to build
ejMina226 Nov 27, 2024
8a9835b
Fix error in tree,
ejMina226 Nov 27, 2024
eb4a6e1
Update interfaces
ejMina226 Nov 27, 2024
55fba98
Update return type for getLeafLessOrEqual
ejMina226 Nov 27, 2024
271d9e4
Update Linked Leaf with hash functionality
ejMina226 Nov 28, 2024
7aa5320
Update test
ejMina226 Nov 28, 2024
9ffba44
Remove comment
ejMina226 Nov 28, 2024
9b704b1
Get BlockProductionTest working.
ejMina226 Nov 28, 2024
fcf4409
Add new MerkleStore Test
ejMina226 Nov 28, 2024
aab6feb
Make code async and remove log
ejMina226 Nov 29, 2024
a21fe8d
Update LinkedMerkleTree amd change tests
ejMina226 Nov 29, 2024
77441fb
Fix to get BP working.
ejMina226 Nov 29, 2024
3c1385c
Merge develop
ejMina226 Nov 29, 2024
1f71c03
Mixer missing from dependencies
ejMina226 Nov 29, 2024
984d298
Add in code to get GraphQL running
ejMina226 Dec 2, 2024
d084e80
Fix test error
ejMina226 Dec 2, 2024
21a0749
Get old merkle tree test working
ejMina226 Dec 3, 2024
7671c79
Change code in server.ts for merkleWitness
ejMina226 Dec 4, 2024
1e7d420
Settlement changes
ejMina226 Dec 4, 2024
4261288
Remove unneeded code
ejMina226 Dec 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions docs/sequencer/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
## Merkle Tree Stores

Object we need to store:
(Nodes, Leaves, MaximumIndex)

Level 1:
Async stores: (InMemory*, Redis*)

Schema:
Record<path, { leaf, index }>

write<object>
get<object>Async
getMaximumIndexAsync
getLeafLessOrEqualAsync(path) (gives us either our current leaf or previous leaf in case of insert)

openTransaction()
commit()

( getLeafByIndex )

Level 2:
CachedStore: implements Sync, parent: Async

Sync:
set<object>
getNode
getLeaf(path) => { leaf: LinkedLeaf, index: bigint }
getMaximumIndex
getLeafLessOrEqual(path) => { leaf: LinkedLeaf, index: bigint }

Cached:
preloadMerkleWitness(index)
preloadKeys(paths: string[])
mergeIntoParent()

Level 3:
SyncCachedStore: implements Sync, parent: Sync
mergeIntoParent()

preLoading:
input: path
```
const leaf = parent.getLeaf(path)
if(leaf !== undefined) {
super.cache(leaf);
// Update
preloadMerkleWitness(leaf.index);
} else {
// Insert
const previousLeaf = parent.getLeafLessOrEqual(path);
super.cache(previousLeaf);
preloadMerkleWitness(previousLeaf.index);
const maximumIndex = this.preloadAndGetMaximumINndex(); // super.getMaximumINdex() ?? await parent.getMaximumIndexASync()
preloadMerkleWitness(maximumIndex);
}

```

Sync interface:
Union of LinkedMerkleTreeStore (rename to LinkedLeafStore) + MerkleTreeStore

Async
Level 1 methods

InMemoryLeafStore - subset that does leafs + maximumindex
InMemoryMerkleStore - subset that does only merkle nodes

-> future Redis

InMemoryAsyncLinkedMerkleTreeStore - implements Async
uses inmemory implementations




2 changes: 1 addition & 1 deletion packages/api/src/graphql/VanillaGraphqlModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { QueryGraphqlModule } from "./modules/QueryGraphqlModule";
import { BatchStorageResolver } from "./modules/BatchStorageResolver";
import { NodeStatusResolver } from "./modules/NodeStatusResolver";
import { BlockResolver } from "./modules/BlockResolver";
import { MerkleWitnessResolver } from "./modules/MerkleWitnessResolver";
import { LinkedMerkleWitnessResolver as MerkleWitnessResolver } from "./modules/LinkedMerkleWitnessResolver";

export type VanillaGraphqlModulesRecord = {
MempoolResolver: typeof MempoolResolver;
Expand Down
28 changes: 28 additions & 0 deletions packages/api/src/graphql/modules/LeafResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Field, ObjectType } from "type-graphql";
import { LinkedLeafStruct } from "@proto-kit/common";

@ObjectType()
export class LeafDTO {
public static fromServiceLayerModel(leaf: LinkedLeafStruct) {
return new LeafDTO(
leaf.value.toString(),
leaf.path.toString(),
leaf.nextPath.toString()
);
}

@Field()
value: string;

@Field()
path: string;

@Field()
nextPath: string;

private constructor(value: string, path: string, nextPath: string) {
this.value = value;
this.path = path;
this.nextPath = nextPath;
}
}
62 changes: 62 additions & 0 deletions packages/api/src/graphql/modules/LinkedMerkleWitnessResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Arg, Field, ObjectType, Query } from "type-graphql";
import { inject } from "tsyringe";
import {
LinkedLeafAndMerkleWitness,
LinkedMerkleTree,
} from "@proto-kit/common";
import { CachedLinkedMerkleTreeStore } from "@proto-kit/sequencer/dist/state/merkle/CachedLinkedMerkleTreeStore";
import { AsyncLinkedMerkleTreeStore } from "@proto-kit/sequencer/dist/state/async/AsyncLinkedMerkleTreeStore";

import { GraphqlModule, graphqlModule } from "../GraphqlModule";

import { MerkleWitnessDTO } from "./MerkleWitnessResolver";
import { LeafDTO } from "./LeafResolver";

@ObjectType()
export class LinkedMerkleWitnessDTO {
public static fromServiceLayerObject(witness: LinkedLeafAndMerkleWitness) {
const { leaf, merkleWitness } = witness;
const leafDTO = LeafDTO.fromServiceLayerModel(leaf);
const witnessDTO = MerkleWitnessDTO.fromServiceLayerObject(merkleWitness);
return new LinkedMerkleWitnessDTO(leafDTO, witnessDTO);
}

public constructor(leaf: LeafDTO, witness: MerkleWitnessDTO) {
this.leaf = leaf;
this.merkleWitness = new MerkleWitnessDTO(
witness.siblings,
witness.isLefts
);
}

@Field(() => LeafDTO)
public leaf: LeafDTO;

@Field(() => MerkleWitnessDTO)
public merkleWitness: MerkleWitnessDTO;
}

@graphqlModule()
export class LinkedMerkleWitnessResolver extends GraphqlModule<object> {
public constructor(
@inject("AsyncMerkleStore")
private readonly treeStore: AsyncLinkedMerkleTreeStore
) {
super();
}

@Query(() => LinkedMerkleWitnessDTO, {
description:
"Allows retrieval of merkle witnesses corresponding to a specific path in the appchain's state tree. These proves are generally retrieved from the current 'proven' state",
})
public async witness(@Arg("path") path: string) {
const syncStore = await CachedLinkedMerkleTreeStore.new(this.treeStore);

const tree = new LinkedMerkleTree(syncStore);
await syncStore.preloadKey(BigInt(path));

const witness = tree.getWitness(BigInt(path));

return LinkedMerkleWitnessDTO.fromServiceLayerObject(witness);
}
}
1 change: 1 addition & 0 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export * from "./graphql/modules/NodeStatusResolver";
export * from "./graphql/modules/AdvancedNodeStatusResolver";
export * from "./graphql/services/NodeStatusService";
export * from "./graphql/modules/MerkleWitnessResolver";
export * from "./graphql/modules/LinkedMerkleWitnessResolver";
export * from "./graphql/VanillaGraphqlModules";
3 changes: 2 additions & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"lodash": "^4.17.21",
"loglevel": "^1.8.1",
"reflect-metadata": "^0.1.13",
"typescript-memoize": "^1.1.1"
"typescript-memoize": "^1.1.1",
"ts-mixer": "^6.0.3"
},
"peerDependencies": {
"o1js": "^1.1.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export * from "./log";
export * from "./events/EventEmittingComponent";
export * from "./events/EventEmitter";
export * from "./trees/MerkleTreeStore";
export * from "./trees/LinkedMerkleTreeStore";
export * from "./trees/InMemoryMerkleTreeStorage";
export * from "./trees/RollupMerkleTree";
export * from "./trees/LinkedMerkleTree";
export * from "./trees/InMemoryLinkedLeafStore";
export * from "./events/EventEmitterProxy";
export * from "./trees/MockAsyncMerkleStore";
export * from "./trees/InMemoryLinkedMerkleLeafStore";
40 changes: 40 additions & 0 deletions packages/common/src/trees/InMemoryLinkedLeafStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { LinkedLeafStore, LinkedLeaf } from "./LinkedMerkleTreeStore";

export class InMemoryLinkedLeafStore implements LinkedLeafStore {
public leaves: {
[key: string]: { leaf: LinkedLeaf; index: bigint };
} = {};

public maximumIndex?: bigint;

public getLeaf(
path: bigint
): { leaf: LinkedLeaf; index: bigint } | undefined {
return this.leaves[path.toString()];
}

public setLeaf(index: bigint, value: LinkedLeaf): void {
const leaf = this.getLeaf(value.path);
if (leaf !== undefined && leaf?.index !== index) {
throw new Error("Cannot change index of existing leaf");
}
this.leaves[value.path.toString()] = { leaf: value, index: index };
if (this.maximumIndex === undefined || index > this.maximumIndex) {
this.maximumIndex = index;
}
}

public getMaximumIndex(): bigint | undefined {
return this.maximumIndex;
}

// This gets the leaf with the closest path.
public getLeafLessOrEqual(
path: bigint
): { leaf: LinkedLeaf; index: bigint } | undefined {
return Object.values(this.leaves).find(
(storedLeaf) =>
storedLeaf.leaf.nextPath > path && storedLeaf.leaf.path <= path
);
}
}
9 changes: 9 additions & 0 deletions packages/common/src/trees/InMemoryLinkedMerkleLeafStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Mixin } from "ts-mixer";

import { InMemoryLinkedLeafStore } from "./InMemoryLinkedLeafStore";
import { InMemoryMerkleTreeStorage } from "./InMemoryMerkleTreeStorage";

export class InMemoryLinkedMerkleLeafStore extends Mixin(
InMemoryLinkedLeafStore,
InMemoryMerkleTreeStorage
) {}
2 changes: 1 addition & 1 deletion packages/common/src/trees/InMemoryMerkleTreeStorage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MerkleTreeStore } from "./MerkleTreeStore";

export class InMemoryMerkleTreeStorage implements MerkleTreeStore {
protected nodes: {
public nodes: {
[key: number]: {
[key: string]: bigint;
};
Expand Down
Loading
Loading