diff --git a/packages/api/src/graphql/modules/LinkedMerkleWitnessResolver.ts b/packages/api/src/graphql/modules/LinkedMerkleWitnessResolver.ts index 58a9b29c7..8f47aaaa9 100644 --- a/packages/api/src/graphql/modules/LinkedMerkleWitnessResolver.ts +++ b/packages/api/src/graphql/modules/LinkedMerkleWitnessResolver.ts @@ -6,6 +6,7 @@ import { } from "@proto-kit/common"; import { AsyncLinkedLeafStore, + AsyncMerkleTreeStore, CachedLinkedLeafStore, } from "@proto-kit/sequencer"; @@ -42,7 +43,9 @@ export class LinkedMerkleWitnessDTO { export class LinkedMerkleWitnessResolver extends GraphqlModule { public constructor( @inject("AsyncLinkedLeafStore") - private readonly treeStore: AsyncLinkedLeafStore + private readonly leafStore: AsyncLinkedLeafStore, + @inject("AsyncTreeStore") + private readonly treeStore: AsyncMerkleTreeStore ) { super(); } @@ -52,7 +55,10 @@ export class LinkedMerkleWitnessResolver extends GraphqlModule { "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 CachedLinkedLeafStore.new(this.treeStore); + const syncStore = await CachedLinkedLeafStore.new( + this.leafStore, + this.treeStore + ); const tree = new LinkedMerkleTree(syncStore.treeStore, syncStore); await syncStore.preloadKey(BigInt(path)); diff --git a/packages/api/src/graphql/modules/MerkleWitnessResolver.ts b/packages/api/src/graphql/modules/MerkleWitnessResolver.ts index a39324ab0..8464b9577 100644 --- a/packages/api/src/graphql/modules/MerkleWitnessResolver.ts +++ b/packages/api/src/graphql/modules/MerkleWitnessResolver.ts @@ -9,6 +9,7 @@ import { } from "@proto-kit/common"; import { AsyncLinkedLeafStore, + AsyncMerkleTreeStore, CachedLinkedLeafStore, } from "@proto-kit/sequencer"; @@ -92,7 +93,9 @@ export class LinkedTreeWitnessDTO { export class MerkleWitnessResolver extends GraphqlModule { public constructor( @inject("AsyncLinkedLeafStore") - private readonly treeStore: AsyncLinkedLeafStore + private readonly leafStore: AsyncLinkedLeafStore, + @inject("AsyncTreeStore") + private readonly treeStore: AsyncMerkleTreeStore ) { super(); } @@ -102,7 +105,10 @@ export class MerkleWitnessResolver extends GraphqlModule { "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 CachedLinkedLeafStore.new(this.treeStore); + const syncStore = await CachedLinkedLeafStore.new( + this.leafStore, + this.treeStore + ); await syncStore.preloadKey(BigInt(path)); const tree = new LinkedMerkleTree(syncStore.treeStore, syncStore); diff --git a/packages/persistance/src/PrismaDatabaseConnection.ts b/packages/persistance/src/PrismaDatabaseConnection.ts index 7195a810e..c59585419 100644 --- a/packages/persistance/src/PrismaDatabaseConnection.ts +++ b/packages/persistance/src/PrismaDatabaseConnection.ts @@ -13,6 +13,7 @@ import { PrismaBlockStorage } from "./services/prisma/PrismaBlockStorage"; import { PrismaSettlementStorage } from "./services/prisma/PrismaSettlementStorage"; import { PrismaMessageStorage } from "./services/prisma/PrismaMessageStorage"; import { PrismaTransactionStorage } from "./services/prisma/PrismaTransactionStorage"; +import { PrismaLinkedLeafStore } from "./services/prisma/PrismaLinkedLeafStore"; export interface PrismaDatabaseConfig { // Either object-based config or connection string @@ -57,7 +58,7 @@ export class PrismaDatabaseConnection StorageDependencyMinimumDependencies<{ readonly prisma: PrismaDatabaseConnection; }>, - "blockTreeStore" | "asyncLinkedLeafStore" | "unprovenLinkedLeafStore" + "blockTreeStore" | "asyncTreeStore" | "unprovenTreeStore" > { return { asyncStateService: { @@ -94,6 +95,26 @@ export class PrismaDatabaseConnection transactionStorage: { useClass: PrismaTransactionStorage, }, + + asyncLinkedLeafStore: { + useGenerated: (module) => { + return new PrismaLinkedLeafStore( + module.prisma, + module.prisma.tracer, + "batch" + ); + }, + }, + + unprovenLinkedLeafStore: { + useGenerated: (module) => { + return new PrismaLinkedLeafStore( + module.prisma, + module.prisma.tracer, + "block" + ); + }, + }, }; } diff --git a/packages/persistance/src/PrismaRedisDatabase.ts b/packages/persistance/src/PrismaRedisDatabase.ts index 87ef9af46..aab091ef2 100644 --- a/packages/persistance/src/PrismaRedisDatabase.ts +++ b/packages/persistance/src/PrismaRedisDatabase.ts @@ -22,7 +22,6 @@ import { RedisConnectionModule, RedisTransaction, } from "./RedisConnection"; -import { PrismaLinkedLeafStore } from "./services/prisma/PrismaLinkedLeafStore"; export interface PrismaRedisCombinedConfig { prisma: PrismaDatabaseConfig; @@ -68,28 +67,6 @@ export class PrismaRedisDatabase return { ...PrismaDatabaseConnection.dependencies(), ...RedisConnectionModule.dependencies(), - - asyncLinkedLeafStore: { - useGenerated: (module) => { - return new PrismaLinkedLeafStore( - module.prisma, - module.redis, - module.tracer, - "batch" - ); - }, - }, - - unprovenLinkedLeafStore: { - useGenerated: (module) => { - return new PrismaLinkedLeafStore( - module.prisma, - module.redis, - module.tracer, - "block" - ); - }, - }, }; } diff --git a/packages/persistance/src/RedisConnection.ts b/packages/persistance/src/RedisConnection.ts index ace9d9268..bd2b4bd03 100644 --- a/packages/persistance/src/RedisConnection.ts +++ b/packages/persistance/src/RedisConnection.ts @@ -43,14 +43,14 @@ export class RedisConnectionModule public static dependencies(): Pick< StorageDependencyMinimumDependencies<{ redis: RedisConnectionModule }>, - "asyncMerkleStore" | "blockTreeStore" | "unprovenMerkleStore" + "blockTreeStore" | "asyncTreeStore" | "unprovenTreeStore" > { return { - asyncMerkleStore: { + asyncTreeStore: { useGenerated: ({ redis }) => new RedisMerkleTreeStore(redis, redis.tracer), }, - unprovenMerkleStore: { + unprovenTreeStore: { useGenerated: ({ redis }) => new RedisMerkleTreeStore(redis, redis.tracer, "unproven"), }, diff --git a/packages/persistance/src/services/prisma/PrismaLinkedLeafStore.ts b/packages/persistance/src/services/prisma/PrismaLinkedLeafStore.ts index 8b25f1624..bd2c7cba3 100644 --- a/packages/persistance/src/services/prisma/PrismaLinkedLeafStore.ts +++ b/packages/persistance/src/services/prisma/PrismaLinkedLeafStore.ts @@ -1,11 +1,9 @@ import { noop, StoredLeaf } from "@proto-kit/common"; -import { AsyncLinkedLeafStore, Tracer } from "@proto-kit/sequencer"; +import { AsyncLinkedLeafStore, trace, Tracer } from "@proto-kit/sequencer"; import { injectable } from "tsyringe"; import { Prisma } from "@prisma/client"; -import { PrismaConnection } from "../../PrismaDatabaseConnection"; -import { RedisMerkleTreeStore } from "../redis/RedisMerkleTreeStore"; -import { RedisConnection } from "../../RedisConnection"; +import type { PrismaConnection } from "../../PrismaDatabaseConnection"; import { Decimal } from "./PrismaStateService"; @@ -13,24 +11,11 @@ import { Decimal } from "./PrismaStateService"; export class PrismaLinkedLeafStore implements AsyncLinkedLeafStore { private cache: StoredLeaf[] = []; - private readonly redisMerkleStore: RedisMerkleTreeStore; - public constructor( private readonly connection: PrismaConnection, - redisConnection: RedisConnection, - tracer: Tracer, + public readonly tracer: Tracer, private readonly mask: string = "base" - ) { - this.redisMerkleStore = new RedisMerkleTreeStore( - redisConnection, - tracer, - mask - ); - } - - public get treeStore() { - return this.redisMerkleStore; - } + ) {} private assertCacheEmpty() { if (this.cache.length > 0) { @@ -42,6 +27,7 @@ export class PrismaLinkedLeafStore implements AsyncLinkedLeafStore { noop(); } + @trace("LinkedLeafStore.commit") public async commit(): Promise { if (this.cache.length > 0) { const data = this.cache.map((entry) => ({ @@ -126,6 +112,7 @@ export class PrismaLinkedLeafStore implements AsyncLinkedLeafStore { : undefined; } + @trace("getPreviousLeaves", ([paths]) => ({ numPaths: paths.length })) public async getPreviousLeavesAsync(paths: bigint[]) { this.assertCacheEmpty(); diff --git a/packages/sdk/src/query/StateServiceQueryModule.ts b/packages/sdk/src/query/StateServiceQueryModule.ts index 8d91da199..bdcee959f 100644 --- a/packages/sdk/src/query/StateServiceQueryModule.ts +++ b/packages/sdk/src/query/StateServiceQueryModule.ts @@ -4,6 +4,7 @@ import { CachedLinkedLeafStore, AsyncLinkedLeafStore, AppChainModule, + AsyncMerkleTreeStore, } from "@proto-kit/sequencer"; import { Field } from "o1js"; import { inject, injectable } from "tsyringe"; @@ -30,10 +31,14 @@ export class StateServiceQueryModule ); } - public get treeStore(): AsyncLinkedLeafStore { + public get leafStore(): AsyncLinkedLeafStore { return this.sequencer.dependencyContainer.resolve("AsyncLinkedLeafStore"); } + public get treeStore(): AsyncMerkleTreeStore { + return this.sequencer.dependencyContainer.resolve("AsyncTreeStore"); + } + public get(key: Field) { return this.asyncStateService.get(key); } @@ -41,7 +46,10 @@ export class StateServiceQueryModule public async merkleWitness( path: Field ): Promise { - const syncStore = await CachedLinkedLeafStore.new(this.treeStore); + const syncStore = await CachedLinkedLeafStore.new( + this.leafStore, + this.treeStore + ); await syncStore.preloadKey(path.toBigInt()); const tree = new LinkedMerkleTree(syncStore.treeStore, syncStore); diff --git a/packages/sdk/test/stprover-emit-sts.test.ts b/packages/sdk/test/stprover-emit-sts.test.ts index ef9170aed..5283feaf9 100644 --- a/packages/sdk/test/stprover-emit-sts.test.ts +++ b/packages/sdk/test/stprover-emit-sts.test.ts @@ -64,7 +64,7 @@ describe("StateTransition", () => { await appChain.start(); appChain.setSigner(senderKey); - }); + }, 30_000); afterEach(async () => { await appChain.close(); diff --git a/packages/sequencer/src/protocol/production/BatchProducerModule.ts b/packages/sequencer/src/protocol/production/BatchProducerModule.ts index 6df8f2699..1dad75eaa 100644 --- a/packages/sequencer/src/protocol/production/BatchProducerModule.ts +++ b/packages/sequencer/src/protocol/production/BatchProducerModule.ts @@ -18,6 +18,7 @@ import type { Database } from "../../storage/Database"; import { AsyncLinkedLeafStore } from "../../state/async/AsyncLinkedLeafStore"; import { CachedLinkedLeafStore } from "../../state/lmt/CachedLinkedLeafStore"; import { ensureNotBusy } from "../../helpers/BusyGuard"; +import { AsyncMerkleTreeStore } from "../../state/async/AsyncMerkleTreeStore"; import { BlockProofSerializer } from "./tasks/serializers/BlockProofSerializer"; import { BatchTracingService } from "./tracing/BatchTracingService"; @@ -47,7 +48,9 @@ const errors = { export class BatchProducerModule extends SequencerModule { public constructor( @inject("AsyncLinkedLeafStore") - private readonly merkleStore: AsyncLinkedLeafStore, + private readonly leafStore: AsyncLinkedLeafStore, + @inject("AsyncTreeStore") + private readonly merkleStore: AsyncMerkleTreeStore, @inject("BatchStorage") private readonly batchStorage: BatchStorage, @inject("Database") private readonly database: Database, @@ -149,7 +152,10 @@ export class BatchProducerModule extends SequencerModule { throw errors.blockWithoutTxs(); } - const merkleTreeStore = await CachedLinkedLeafStore.new(this.merkleStore); + const merkleTreeStore = await CachedLinkedLeafStore.new( + this.leafStore, + this.merkleStore + ); const trace = await this.batchTraceService.traceBatch( blocks.map((block) => block), diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts index 9d0ed507c..e6dd9f294 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts @@ -44,6 +44,8 @@ export class BlockProducerModule extends SequencerModule { private readonly unprovenStateService: AsyncStateService, @inject("UnprovenLinkedLeafStore") private readonly unprovenLinkedLeafStore: AsyncLinkedLeafStore, + @inject("UnprovenTreeStore") + private readonly unprovenTreeStore: AsyncMerkleTreeStore, @inject("BlockQueue") private readonly blockQueue: BlockQueue, @inject("TransactionStorage") @@ -118,6 +120,7 @@ export class BlockProducerModule extends SequencerModule { await this.resultService.generateMetadataForNextBlock( block, this.unprovenLinkedLeafStore, + this.unprovenTreeStore, this.blockTreeStore, this.unprovenStateService ); diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts b/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts index 5419344bb..6afb098fa 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts @@ -188,7 +188,8 @@ export class BlockResultService { })) public async generateMetadataForNextBlock( block: Block, - merkleTreeStore: AsyncLinkedLeafStore, + leafStore: AsyncLinkedLeafStore, + treeStore: AsyncMerkleTreeStore, blockHashTreeStore: AsyncMerkleTreeStore, stateService: AsyncStateService ): Promise<{ @@ -202,7 +203,7 @@ export class BlockResultService { block.beforeBlockStateTransitions ); - const inMemoryStore = await CachedLinkedLeafStore.new(merkleTreeStore); + const inMemoryStore = await CachedLinkedLeafStore.new(leafStore, treeStore); const tree = await this.applyStateDiff(inMemoryStore, combinedDiff); diff --git a/packages/sequencer/src/settlement/BridgingModule.ts b/packages/sequencer/src/settlement/BridgingModule.ts index 79133bc73..1a5e735a2 100644 --- a/packages/sequencer/src/settlement/BridgingModule.ts +++ b/packages/sequencer/src/settlement/BridgingModule.ts @@ -56,6 +56,7 @@ import { AsyncLinkedLeafStore } from "../state/async/AsyncLinkedLeafStore"; import { CachedLinkedLeafStore } from "../state/lmt/CachedLinkedLeafStore"; import { SettleableBatch } from "../storage/model/Batch"; import { SequencerModule } from "../sequencer/builder/SequencerModule"; +import { AsyncMerkleTreeStore } from "../state/async/AsyncMerkleTreeStore"; import type { SettlementModule } from "./SettlementModule"; import { SettlementUtils } from "./utils/SettlementUtils"; @@ -114,6 +115,8 @@ export class BridgingModule extends SequencerModule { private readonly outgoingMessageCollector: OutgoingMessageCollector, @inject("AsyncLinkedLeafStore") private readonly linkedLeafStore: AsyncLinkedLeafStore, + @inject("AsyncTreeStore") + private readonly treeStore: AsyncMerkleTreeStore, @inject("FeeStrategy") private readonly feeStrategy: FeeStrategy, @inject("BaseLayer") private readonly baseLayer: MinaBaseLayer, @@ -590,7 +593,10 @@ export class BridgingModule extends SequencerModule { const bridgeContract = this.createBridgeContract(bridgeAddress, tokenId); - const cachedStore = await CachedLinkedLeafStore.new(this.linkedLeafStore); + const cachedStore = await CachedLinkedLeafStore.new( + this.linkedLeafStore, + this.treeStore + ); const tree = new LinkedMerkleTree(cachedStore.treeStore, cachedStore); // Create withdrawal batches and send them as L1 transactions diff --git a/packages/sequencer/src/state/async/AsyncLinkedLeafStore.ts b/packages/sequencer/src/state/async/AsyncLinkedLeafStore.ts index 5d9dcc0fb..b3ac3c6f4 100644 --- a/packages/sequencer/src/state/async/AsyncLinkedLeafStore.ts +++ b/packages/sequencer/src/state/async/AsyncLinkedLeafStore.ts @@ -1,10 +1,6 @@ import { StoredLeaf } from "@proto-kit/common"; -import { AsyncMerkleTreeStore } from "./AsyncMerkleTreeStore"; - export interface AsyncLinkedLeafStore { - treeStore: AsyncMerkleTreeStore; - openTransaction: () => Promise; commit: () => Promise; diff --git a/packages/sequencer/src/state/lmt/CachedLinkedLeafStore.ts b/packages/sequencer/src/state/lmt/CachedLinkedLeafStore.ts index b55c1b267..0ee781cc9 100644 --- a/packages/sequencer/src/state/lmt/CachedLinkedLeafStore.ts +++ b/packages/sequencer/src/state/lmt/CachedLinkedLeafStore.ts @@ -13,6 +13,7 @@ import groupBy from "lodash/groupBy"; import { AsyncLinkedLeafStore } from "../async/AsyncLinkedLeafStore"; import { CachedMerkleTreeStore } from "../merkle/CachedMerkleTreeStore"; +import { AsyncMerkleTreeStore } from "../async/AsyncMerkleTreeStore"; export class CachedLinkedLeafStore implements LinkedLeafStore { private writeCache: { @@ -23,8 +24,11 @@ export class CachedLinkedLeafStore implements LinkedLeafStore { private readonly treeCache: CachedMerkleTreeStore; - private constructor(private readonly parent: AsyncLinkedLeafStore) { - this.treeCache = new CachedMerkleTreeStore(parent.treeStore); + private constructor( + private readonly parent: AsyncLinkedLeafStore, + private readonly parentTreeStore: AsyncMerkleTreeStore + ) { + this.treeCache = new CachedMerkleTreeStore(parentTreeStore); } public get treeStore() { @@ -32,9 +36,10 @@ export class CachedLinkedLeafStore implements LinkedLeafStore { } public static async new( - parent: AsyncLinkedLeafStore + parent: AsyncLinkedLeafStore, + parentTreeStore: AsyncMerkleTreeStore ): Promise { - const cachedInstance = new CachedLinkedLeafStore(parent); + const cachedInstance = new CachedLinkedLeafStore(parent, parentTreeStore); await cachedInstance.preloadMaximumIndex(); await cachedInstance.preloadZeroNode(); return cachedInstance; diff --git a/packages/sequencer/src/storage/StorageDependencyFactory.ts b/packages/sequencer/src/storage/StorageDependencyFactory.ts index dab77170f..51b95a35f 100644 --- a/packages/sequencer/src/storage/StorageDependencyFactory.ts +++ b/packages/sequencer/src/storage/StorageDependencyFactory.ts @@ -26,6 +26,9 @@ export interface StorageDependencyMinimumDependencies< messageStorage: DependencyDeclaration; settlementStorage: DependencyDeclaration; transactionStorage: DependencyDeclaration; + + asyncTreeStore: DependencyDeclaration; + unprovenTreeStore: DependencyDeclaration; } export interface DatabaseDependencyFactory { diff --git a/packages/sequencer/src/storage/inmemory/InMemoryAsyncLinkedLeafStore.ts b/packages/sequencer/src/storage/inmemory/InMemoryAsyncLinkedLeafStore.ts index 382e2ca7a..c74f4ffdb 100644 --- a/packages/sequencer/src/storage/inmemory/InMemoryAsyncLinkedLeafStore.ts +++ b/packages/sequencer/src/storage/inmemory/InMemoryAsyncLinkedLeafStore.ts @@ -2,23 +2,9 @@ import { InMemoryLinkedLeafStore, LinkedLeaf, noop } from "@proto-kit/common"; import { AsyncLinkedLeafStore } from "../../state/async/AsyncLinkedLeafStore"; -import { InMemoryAsyncMerkleTreeStore } from "./InMemoryAsyncMerkleTreeStore"; - export class InMemoryAsyncLinkedLeafStore implements AsyncLinkedLeafStore { private readonly leafStore = new InMemoryLinkedLeafStore(); - private readonly nodeStore = new InMemoryAsyncMerkleTreeStore(); - - // public constructor() { - // const initialLeaf = initialLinkedLeaf(); - // this.leafStore.setLeaf(0n, initialLeaf); - // this.nodeStore.writeNodes([{ }]); - // } - - public get treeStore() { - return this.nodeStore; - } - public async openTransaction(): Promise { noop(); } diff --git a/packages/sequencer/src/storage/inmemory/InMemoryDatabase.ts b/packages/sequencer/src/storage/inmemory/InMemoryDatabase.ts index 3a20eff9c..c29f32f8b 100644 --- a/packages/sequencer/src/storage/inmemory/InMemoryDatabase.ts +++ b/packages/sequencer/src/storage/inmemory/InMemoryDatabase.ts @@ -56,6 +56,12 @@ export class InMemoryDatabase extends SequencerModule implements Database { transactionStorage: { useClass: InMemoryTransactionStorage, }, + unprovenTreeStore: { + useClass: InMemoryAsyncMerkleTreeStore, + }, + asyncTreeStore: { + useClass: InMemoryAsyncMerkleTreeStore, + }, }; } diff --git a/packages/sequencer/test/LinkedMerkleTreeIntegrity.ts b/packages/sequencer/test/LinkedMerkleTreeIntegrity.ts index c19a6f5d8..68e18ac33 100644 --- a/packages/sequencer/test/LinkedMerkleTreeIntegrity.ts +++ b/packages/sequencer/test/LinkedMerkleTreeIntegrity.ts @@ -1,10 +1,13 @@ import { Field } from "o1js"; import { LinkedLeafStruct, log } from "@proto-kit/common"; -import { AsyncLinkedLeafStore } from "../src/state/async/AsyncLinkedLeafStore"; +import { AsyncMerkleTreeStore, AsyncLinkedLeafStore } from "../src"; export namespace LinkedMerkleTreeIntegrity { - export async function checkIntegrity(store: AsyncLinkedLeafStore) { + export async function checkIntegrity( + store: AsyncLinkedLeafStore, + treeStore: AsyncMerkleTreeStore + ) { log.info("Checking tree integrity..."); let currentPath = 0n; @@ -18,7 +21,7 @@ export namespace LinkedMerkleTreeIntegrity { const leaf = leaves[0]!; - const treeValues = await store.treeStore.getNodesAsync([ + const treeValues = await treeStore.getNodesAsync([ { level: 0, key: leaf.index }, ]); if (treeValues.length === 0 || treeValues[0] === undefined) { diff --git a/packages/sequencer/test/integration/BlockProduction-test.ts b/packages/sequencer/test/integration/BlockProduction-test.ts index a2a97ebcf..d98a1fecb 100644 --- a/packages/sequencer/test/integration/BlockProduction-test.ts +++ b/packages/sequencer/test/integration/BlockProduction-test.ts @@ -36,6 +36,7 @@ import { AppChain, BlockProducerModule, DatabaseDependencyFactory, + AsyncMerkleTreeStore, } from "../../src"; import { DefaultTestingSequencerModules, @@ -116,6 +117,7 @@ export function testBlockProduction< let test: BlockTestService; let linkedLeafStore: AsyncLinkedLeafStore; + let treeStore: AsyncMerkleTreeStore; beforeEach(async () => { const runtimeClass = Runtime.from({ @@ -189,6 +191,10 @@ export function testBlockProduction< app.sequencer.dependencyContainer.resolve( "UnprovenLinkedLeafStore" ); + treeStore = + app.sequencer.dependencyContainer.resolve( + "UnprovenTreeStore" + ); }, 30000); afterEach(async () => { @@ -302,7 +308,7 @@ export function testBlockProduction< expect(UInt64.fromFields(state2!)).toStrictEqual(UInt64.from(200)); await expect( - LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore) + LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore, treeStore) ).resolves.toBe(true); }, 60_000); @@ -337,7 +343,7 @@ export function testBlockProduction< expect(newState).toBeUndefined(); await expect( - LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore) + LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore, treeStore) ).resolves.toBe(true); }, 30_000); @@ -420,7 +426,7 @@ export function testBlockProduction< expect(block2!.transactions[0].statusMessage).toBeUndefined(); await expect( - LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore) + LinkedMerkleTreeIntegrity.checkIntegrity(linkedLeafStore, treeStore) ).resolves.toBe(true); }, 60_000); diff --git a/packages/sequencer/test/merkle/CachedLinkedMerkleStore.test.ts b/packages/sequencer/test/merkle/CachedLinkedMerkleStore.test.ts index 5ceae2768..0df9e4d38 100644 --- a/packages/sequencer/test/merkle/CachedLinkedMerkleStore.test.ts +++ b/packages/sequencer/test/merkle/CachedLinkedMerkleStore.test.ts @@ -9,24 +9,30 @@ import { Field, Poseidon } from "o1js"; import { CachedLinkedLeafStore } from "../../src/state/lmt/CachedLinkedLeafStore"; import { InMemoryAsyncLinkedLeafStore } from "../../src/storage/inmemory/InMemoryAsyncLinkedLeafStore"; import { SyncCachedLinkedLeafStore } from "../../src/state/merkle/SyncCachedLinkedLeafStore"; +import { InMemoryAsyncMerkleTreeStore } from "../../src"; describe("cached linked merkle store", () => { let mainStore: InMemoryAsyncLinkedLeafStore; + let mainTreeStore: InMemoryAsyncMerkleTreeStore; let cache1: CachedLinkedLeafStore; let tree1: LinkedMerkleTree; beforeEach(async () => { mainStore = new InMemoryAsyncLinkedLeafStore(); + mainTreeStore = new InMemoryAsyncMerkleTreeStore(); - const cachedStore = await CachedLinkedLeafStore.new(mainStore); + const cachedStore = await CachedLinkedLeafStore.new( + mainStore, + mainTreeStore + ); const tmpTree = new LinkedMerkleTree(cachedStore.treeStore, cachedStore); tmpTree.setLeaf(5n, 10n); await cachedStore.mergeIntoParent(); - cache1 = await CachedLinkedLeafStore.new(mainStore); + cache1 = await CachedLinkedLeafStore.new(mainStore, mainTreeStore); tree1 = new LinkedMerkleTree(cache1.treeStore, cache1); }); @@ -307,7 +313,7 @@ describe("cached linked merkle store", () => { expectDefined(leaf1); expectDefined(storedLeaf1); await expect( - mainStore.treeStore.getNodesAsync([{ key: storedLeaf1.index, level: 0 }]) + mainTreeStore.getNodesAsync([{ key: storedLeaf1.index, level: 0 }]) ).resolves.toStrictEqual([ Poseidon.hash([leaf1.value, leaf1.path, leaf1.nextPath]).toBigInt(), ]); @@ -381,7 +387,10 @@ describe("cached linked merkle store", () => { // Now the mainstore has the new 15n root. await cache1.mergeIntoParent(); - const cachedStore = await CachedLinkedLeafStore.new(mainStore); + const cachedStore = await CachedLinkedLeafStore.new( + mainStore, + mainTreeStore + ); await cachedStore.preloadKey(15n); expect( @@ -395,7 +404,8 @@ describe("cached linked merkle store", () => { expect.assertions(16); const mStore = new InMemoryAsyncLinkedLeafStore(); - const mCache = await CachedLinkedLeafStore.new(mStore); + const mTreeStore = new InMemoryAsyncMerkleTreeStore(); + const mCache = await CachedLinkedLeafStore.new(mStore, mTreeStore); const mCache2 = new SyncCachedLinkedLeafStore(mCache); const treeCache1 = new LinkedMerkleTree(mCache.treeStore, mCache); const treeCache2 = new LinkedMerkleTree(mCache2.treeStore, mCache2); diff --git a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts index a670b41c6..f93224b74 100644 --- a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts +++ b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts @@ -19,6 +19,7 @@ import { StateTransitionProofParameters, ConsoleTracer, CachedLinkedLeafStore, + InMemoryAsyncMerkleTreeStore, } from "../../../src"; import { InMemoryAsyncLinkedLeafStore } from "../../../src/storage/inmemory/InMemoryAsyncLinkedLeafStore"; @@ -115,7 +116,8 @@ async function applyBatchesToTree( // return sequencer; // } -const service = new StateTransitionTracingService(new ConsoleTracer()); +const tracer = new ConsoleTracer(); +const service = new StateTransitionTracingService(tracer); describe("StateTransitionTracingService", () => { const cases: { @@ -163,11 +165,12 @@ describe("StateTransitionTracingService", () => { describe.each(cases)("tracing two chunks of STs", ({ batch, numSTs }) => { const store = new InMemoryAsyncLinkedLeafStore(); + const treeStore = new InMemoryAsyncMerkleTreeStore(); let trace: StateTransitionProofParameters[]; beforeAll(async () => { - const cached = await CachedLinkedLeafStore.new(store); + const cached = await CachedLinkedLeafStore.new(store, treeStore); trace = await service.createMerkleTrace(cached, batch); }); @@ -187,7 +190,7 @@ describe("StateTransitionTracingService", () => { it("should set second publicInput correctly", async () => { const tree = await applyBatchesToTree( batch.slice(0, 4), - await CachedLinkedLeafStore.new(store) + await CachedLinkedLeafStore.new(store, treeStore) ); expect(trace[1].publicInput.root.toString()).toStrictEqual( @@ -222,7 +225,7 @@ describe("StateTransitionTracingService", () => { const witnessedRootsList = new WitnessedRootHashList(); const tempTree = await applyBatchesToTree( batch.slice(0, 2), - await CachedLinkedLeafStore.new(store) + await CachedLinkedLeafStore.new(store, treeStore) ); witnessedRootsList.push({ @@ -242,6 +245,7 @@ describe("StateTransitionTracingService", () => { describe("tracing two separate sequences", () => { const store = new InMemoryAsyncLinkedLeafStore(); + const treeStore = new InMemoryAsyncMerkleTreeStore(); let cached: CachedLinkedLeafStore; let trace1: StateTransitionProofParameters[]; @@ -271,10 +275,10 @@ describe("StateTransitionTracingService", () => { ]; beforeAll(async () => { - cached = await CachedLinkedLeafStore.new(store); + cached = await CachedLinkedLeafStore.new(store, treeStore); trace1 = await service.createMerkleTrace(cached, batches[0]); - const cached2 = await CachedLinkedLeafStore.new(store); + const cached2 = await CachedLinkedLeafStore.new(store, treeStore); tree1 = await applyBatchesToTree(batches[0], cached2); trace2 = await service.createMerkleTrace(cached, batches[1]); @@ -304,6 +308,7 @@ describe("StateTransitionTracingService", () => { describe("should trace correctly", () => { const store = new InMemoryAsyncLinkedLeafStore(); + const treeStore = new InMemoryAsyncMerkleTreeStore(); let cached: CachedLinkedLeafStore; const batches: TracingStateTransitionBatch[] = [ @@ -327,7 +332,7 @@ describe("StateTransitionTracingService", () => { let trace: StateTransitionProofParameters[]; beforeAll(async () => { - cached = await CachedLinkedLeafStore.new(store); + cached = await CachedLinkedLeafStore.new(store, treeStore); trace = await service.createMerkleTrace(cached, batches); }); @@ -371,7 +376,7 @@ describe("StateTransitionTracingService", () => { it("check that STs have been applied to the tree store", async () => { const tracedTree = new LinkedMerkleTree(cached.treeStore, cached); - const cached2 = await CachedLinkedLeafStore.new(store); + const cached2 = await CachedLinkedLeafStore.new(store, treeStore); const tree = await applyBatchesToTree(batches, cached2); expect(tracedTree.getRoot().toString()).toStrictEqual( @@ -379,4 +384,8 @@ describe("StateTransitionTracingService", () => { ); }); }); + + afterAll(async () => { + await tracer.close(); + }); });