From b74dae4f26b3a3fda3c9d3cf73eecf5eb1b18c05 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sat, 17 Jan 2026 17:02:05 +0100 Subject: [PATCH 01/18] Enabled proven.test --- .../sequencer/test/integration/Proven.test.ts | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts index bca7f53a..8ccbf556 100644 --- a/packages/sequencer/test/integration/Proven.test.ts +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -14,7 +14,6 @@ import { ContractArgsRegistry, DispatchSmartContract, Protocol, - SettlementContractModule, } from "@proto-kit/protocol"; import { VanillaProtocolModules } from "@proto-kit/library"; import { container } from "tsyringe"; @@ -22,24 +21,20 @@ import { PrivateKey, UInt64 } from "o1js"; import { testingSequencerModules } from "../TestingSequencer"; import { - MinaBaseLayer, ProvenSettlementPermissions, Sequencer, - SettlementModule, - SettlementProvingTask, VanillaTaskWorkerModules, AppChain, InMemoryAreProofsEnabled, } from "../../src"; import { SettlementStartupModule } from "../../src/sequencer/SettlementStartupModule"; -import { ProtocolStateTestHook } from "./mocks/ProtocolStateTestHook"; import { BlockTestService } from "./services/BlockTestService"; import { ProvenBalance } from "./mocks/ProvenBalance"; const timeout = 300000; -describe.skip("Proven", () => { +describe("Proven", () => { let test: BlockTestService; let appChain: ReturnType; @@ -52,11 +47,11 @@ describe.skip("Proven", () => { const sequencerClass = Sequencer.from( testingSequencerModules( { - BaseLayer: MinaBaseLayer, - SettlementModule, + // BaseLayer: MinaBaseLayer, + // SettlementModule, }, { - SettlementProvingTask, + // SettlementProvingTask, } ) ); @@ -64,14 +59,14 @@ describe.skip("Proven", () => { // TODO Analyze how we can get rid of the library import for mandatory modules const protocolClass = Protocol.from({ ...VanillaProtocolModules.mandatoryModules({ - ProtocolStateTestHook, + // ProtocolStateTestHook, // ProtocolStateTestHook2, }), - SettlementContractModule: SettlementContractModule.from({ - ...SettlementContractModule.settlementAndBridging(), - // FungibleToken: FungibleTokenContractModule, - // FungibleTokenAdmin: FungibleTokenAdminContractModule, - }), + // SettlementContractModule: SettlementContractModule.from({ + // ...SettlementContractModule.settlementAndBridging(), + // FungibleToken: FungibleTokenContractModule, + // FungibleTokenAdmin: FungibleTokenAdminContractModule, + // }), // modules: VanillaProtocolModules.with({}), }); @@ -82,6 +77,10 @@ describe.skip("Proven", () => { }); } + afterAll(async () => { + await appChain.close(); + }); + it( "should start up and compile", async () => { @@ -101,27 +100,27 @@ describe.skip("Proven", () => { FeeStrategy: {}, SequencerStartupModule: {}, BaseLayer: { - network: { - type: "local", - }, + // network: { + // type: "local", + // }, }, - SettlementModule: {}, + // SettlementModule: {}, }, Runtime: { Balances: {}, }, Protocol: { ...Protocol.defaultConfig(), - ProtocolStateTestHook: {}, - SettlementContractModule: { - SettlementContract: {}, - BridgeContract: {}, - DispatchContract: { - incomingMessagesMethods: { - deposit: "Balances.deposit", - }, - }, - }, + // ProtocolStateTestHook: {}, + // SettlementContractModule: { + // SettlementContract: {}, + // BridgeContract: {}, + // DispatchContract: { + // incomingMessagesMethods: { + // deposit: "Balances.deposit", + // }, + // }, + // }, // ProtocolStateTestHook2: {}, }, }); @@ -129,7 +128,7 @@ describe.skip("Proven", () => { try { // Start AppChain const childContainer = container.createChildContainer(); - await app.start(true, childContainer); + await app.start(false, childContainer); test = app.sequencer.dependencyContainer.resolve(BlockTestService); @@ -142,7 +141,7 @@ describe.skip("Proven", () => { timeout ); - it("should compile settlement contracts", async () => { + it.skip("should compile settlement contracts", async () => { const module = appChain.sequencer.dependencyContainer.resolve( SettlementStartupModule ); From 9f61dde643723b76527f2d214842448abf770ef7 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 23 Jan 2026 13:14:11 +0100 Subject: [PATCH 02/18] Added devnet proven test --- .../Settlement-devnet.test.ts | 42 +++++++++++++++++++ .../sequencer/test/settlement/Settlement.ts | 9 ++-- 2 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 packages/sequencer/test-integration/Settlement-devnet.test.ts diff --git a/packages/sequencer/test-integration/Settlement-devnet.test.ts b/packages/sequencer/test-integration/Settlement-devnet.test.ts new file mode 100644 index 00000000..2264c4a4 --- /dev/null +++ b/packages/sequencer/test-integration/Settlement-devnet.test.ts @@ -0,0 +1,42 @@ +import { describe } from "@jest/globals"; +import { settlementTestFn } from "../test/settlement/Settlement"; +import { MinaBaseLayerConfig } from "../src"; +import { FungibleToken } from "mina-fungible-token"; +import { PrivateKey } from "o1js"; + +describe("Settlement - Devnet", () => { + const network: MinaBaseLayerConfig = { + network: { + type: "remote", + graphql: "https://api.minascan.io/node/devnet/v1/graphql", + archive: "https://api.minascan.io/archive/devnet/v1/graphql", + // type: "local" + }, + }; + + const sequencerKey = PrivateKey.fromBase58( + "EKFBrGinEnesgbsNJMHikKVSJxxcRQBaSUEi55jD5YfQeRxVLBKN" + ); + + it.skip("Random pk", () => { + const pk = PrivateKey.random(); + console.log(pk.toBase58()); + console.log(pk.toPublicKey().toBase58()); + }); + + describe("Default token", () => { + settlementTestFn("proven", network, undefined, 500_000, sequencerKey); + }); + + describe("Custom token", () => { + settlementTestFn( + "proven", + network, + { + tokenOwner: FungibleToken, + }, + 500_000, + sequencerKey + ); + }); +}); diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index 0b89e887..389e4d67 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -76,11 +76,12 @@ export const settlementTestFn = ( tokenConfig?: { tokenOwner: TypedClass & typeof SmartContract; }, - timeout: number = 120_000 + timeout: number = 120_000, + sequencerKeyInput?: PrivateKey ) => { let testAccounts: PrivateKey[] = []; - const sequencerKey = PrivateKey.random(); + const sequencerKey = sequencerKeyInput ?? PrivateKey.random(); const settlementKey = PrivateKey.random(); const dispatchKey = PrivateKey.random(); const minaBridgeKey = PrivateKey.random(); @@ -301,7 +302,9 @@ export const settlementTestFn = ( `Funding ${sequencerKey.toPublicKey().toBase58()} from ${accs[0].toPublicKey().toBase58()}` ); - await networkUtils.faucet(sequencerKey.toPublicKey(), 20 * 1e9); + if (sequencerKeyInput === undefined) { + await networkUtils.faucet(sequencerKey.toPublicKey(), 20 * 1e9); + } }, timeout * 3); afterAll(async () => { From 30905aa45ff63b182e1e2482bd32df75f3ca0fdf Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 23 Jan 2026 13:34:34 +0100 Subject: [PATCH 03/18] adaptations --- .../Settlement-devnet.test.ts | 13 ++++-- .../sequencer/test/settlement/Settlement.ts | 41 ++++++++++++------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/packages/sequencer/test-integration/Settlement-devnet.test.ts b/packages/sequencer/test-integration/Settlement-devnet.test.ts index 2264c4a4..b431d05d 100644 --- a/packages/sequencer/test-integration/Settlement-devnet.test.ts +++ b/packages/sequencer/test-integration/Settlement-devnet.test.ts @@ -18,14 +18,21 @@ describe("Settlement - Devnet", () => { "EKFBrGinEnesgbsNJMHikKVSJxxcRQBaSUEi55jD5YfQeRxVLBKN" ); - it.skip("Random pk", () => { + const userKey = PrivateKey.fromBase58( + "EKE6jLyNZePXufcRDrJ8HbtWvTqoJKXFwKsd2ZG3iUeHxJ2xegHp" + ); + + it("Random pk", () => { const pk = PrivateKey.random(); console.log(pk.toBase58()); console.log(pk.toPublicKey().toBase58()); }); describe("Default token", () => { - settlementTestFn("proven", network, undefined, 500_000, sequencerKey); + settlementTestFn("proven", network, undefined, 500_000, [ + sequencerKey, + userKey, + ]); }); describe("Custom token", () => { @@ -36,7 +43,7 @@ describe("Settlement - Devnet", () => { tokenOwner: FungibleToken, }, 500_000, - sequencerKey + [sequencerKey, userKey] ); }); }); diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index 389e4d67..0fa73ba5 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -77,11 +77,11 @@ export const settlementTestFn = ( tokenOwner: TypedClass & typeof SmartContract; }, timeout: number = 120_000, - sequencerKeyInput?: PrivateKey + fundedKeysInput: PrivateKey[] = [] ) => { - let testAccounts: PrivateKey[] = []; + let testAccounts: PrivateKey[] = fundedKeysInput.slice(1); - const sequencerKey = sequencerKeyInput ?? PrivateKey.random(); + const sequencerKey = fundedKeysInput[0] ?? PrivateKey.random(); const settlementKey = PrivateKey.random(); const dispatchKey = PrivateKey.random(); const minaBridgeKey = PrivateKey.random(); @@ -265,6 +265,10 @@ export const settlementTestFn = ( return result; } + let nonceCounter = 0; + let user0Nonce = 0; + let acc0L2Nonce = 0; + beforeAll(async () => { appChain = setupAppChain(); @@ -293,17 +297,30 @@ export const settlementTestFn = ( appChain.sequencer.dependencyContainer.resolve( "NetworkUtils" ); - const accs = await networkUtils.getFundedAccounts(3); - testAccounts = accs.slice(1); - await networkUtils.waitForNetwork(); - console.log( - `Funding ${sequencerKey.toPublicKey().toBase58()} from ${accs[0].toPublicKey().toBase58()}` - ); + if (fundedKeysInput.length === 0) { + const accs = await networkUtils.getFundedAccounts(2); + testAccounts = accs.slice(1); + + console.log( + `Funding ${sequencerKey.toPublicKey().toBase58()} from ${accs[0].toPublicKey().toBase58()}` + ); - if (sequencerKeyInput === undefined) { await networkUtils.faucet(sequencerKey.toPublicKey(), 20 * 1e9); + } else { + const sequencerAccount = await fetchAccount({ + publicKey: fundedKeysInput[0].toPublicKey(), + }); + nonceCounter = parseInt( + sequencerAccount.account?.nonce.toString() ?? "0", + 10 + ); + + const account = await fetchAccount({ + publicKey: testAccounts[0].toPublicKey(), + }); + user0Nonce = parseInt(account.account?.nonce.toString() ?? "0", 10); } }, timeout * 3); @@ -313,10 +330,6 @@ export const settlementTestFn = ( await appChain.close(); }); - let nonceCounter = 0; - let user0Nonce = 0; - let acc0L2Nonce = 0; - it.skip("Print constraint summary", async () => { await appChain.protocol.dependencyContainer .resolve(CircuitAnalysisModule) From 2855b03983198b4050cfc26a7d93e437f360265f Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sat, 24 Jan 2026 18:05:31 +0100 Subject: [PATCH 04/18] Added large tx amount proven test --- .../sequencer/test/integration/Proven.test.ts | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts index 8ccbf556..49161b73 100644 --- a/packages/sequencer/test/integration/Proven.test.ts +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -5,6 +5,7 @@ import { MOCK_VERIFICATION_KEY, ChildVerificationKeyService, CompileRegistry, + range, } from "@proto-kit/common"; import { Runtime } from "@proto-kit/module"; import { @@ -94,7 +95,9 @@ describe("Proven", () => { BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - BlockProducerModule: {}, + BlockProducerModule: { + maximumBlockSize: 5, + }, LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), TaskQueue: {}, FeeStrategy: {}, @@ -190,7 +193,7 @@ describe("Proven", () => { } }, 500000); - it( + it.skip( "should produce simple block", async () => { expect.assertions(6); @@ -216,9 +219,48 @@ describe("Proven", () => { console.log(batch.proof); - expect(batch.proof.proof.length).toBeGreaterThan(50); expect(batch.blockHashes).toHaveLength(1); + expect(batch.proof.proof.length).toBeGreaterThan(50); }, timeout ); + + it( + "should produce large block", + async () => { + log.setLevel("INFO"); + + const privateKey = PrivateKey.random(); + + for (const i of range(0, 30)) { + await test.addTransaction({ + method: ["Balances", "addBalance"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], + }); + } + + // Produce 6 blocks, 5 txs each into 1 batch + const block = await test.produceBlock(); + + expectDefined(block); + expect(block.transactions).toHaveLength(5); + expect(block.transactions[0].status.toBoolean()).toBe(true); + + await test.produceBlock(); + await test.produceBlock(); + await test.produceBlock(); + await test.produceBlock(); + // await test.produceBlock(); + const batch = await test.produceBatch(); + + expectDefined(batch); + + console.log(batch.proof); + + expect(batch.blockHashes).toHaveLength(6); + expect(batch.proof.proof.length).toBeGreaterThan(50); + }, + timeout * 10 + ); }); From 7588df2f9a716b2ec5375da3c7afab3a6e7ca464 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sat, 24 Jan 2026 19:36:59 +0100 Subject: [PATCH 05/18] Added back 6th proven block --- packages/sequencer/test/integration/Proven.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts index 49161b73..9fd465f5 100644 --- a/packages/sequencer/test/integration/Proven.test.ts +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -251,7 +251,7 @@ describe("Proven", () => { await test.produceBlock(); await test.produceBlock(); await test.produceBlock(); - // await test.produceBlock(); + await test.produceBlock(); const batch = await test.produceBatch(); expectDefined(batch); From 7d40b7bdc1f352ac167117ce194736d898003eb8 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sun, 25 Jan 2026 16:55:13 +0100 Subject: [PATCH 06/18] Added sanity check to block task --- .../sequencer/src/protocol/production/tasks/NewBlockTask.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index 5b883da5..427ee0ca 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -14,6 +14,7 @@ import { BlockArguments, BlockArgumentsBatch, BlockProverStateInput, + BLOCK_ARGUMENT_BATCH_SIZE, } from "@proto-kit/protocol"; import { Bool } from "o1js"; import { @@ -111,6 +112,10 @@ export class NewBlockTask blocks, } = parameters; + if (blocks.length !== BLOCK_ARGUMENT_BATCH_SIZE) { + throw new Error("Given block argument length not exactly batch size"); + } + const blockArgumentBatch = new BlockArgumentsBatch({ batch: blocks.map((block) => block.args), }); From 83aeeaa8c6ab47e7c99946f48c625df97d300a3b Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Wed, 28 Jan 2026 17:30:40 +0100 Subject: [PATCH 07/18] Made workers test run multiple workers --- .../workers/ChildProcessWorker.ts | 8 ++- .../test-integration/workers/modules.ts | 6 +-- .../workers/workers-proven.test.ts | 54 ++++++++++++++----- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts index d27ba956..2c5d737c 100644 --- a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts +++ b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts @@ -3,7 +3,11 @@ import { spawn, ChildProcess } from "node:child_process"; export class ChildProcessWorker { process?: ChildProcess; - start(forwardLogs: boolean = true, env_args: Record = {}) { + start( + name: string, + forwardLogs: boolean = true, + env_args: Record = {} + ) { const s = spawn( "node", [ @@ -26,11 +30,13 @@ export class ChildProcessWorker { }); if (forwardLogs) { s.stdout.on("data", (data) => { + process.stdout.write(`${name}: `); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument process.stdout.write(data); }); } s.stderr.on("data", (data) => { + process.stderr.write(`${name}: `); // eslint-disable-next-line @typescript-eslint/no-unsafe-argument process.stderr.write(data); }); diff --git a/packages/sequencer/test-integration/workers/modules.ts b/packages/sequencer/test-integration/workers/modules.ts index d65204c0..64fbf290 100644 --- a/packages/sequencer/test-integration/workers/modules.ts +++ b/packages/sequencer/test-integration/workers/modules.ts @@ -27,11 +27,7 @@ export const runtimeProtocolConfig: ModulesConfig<{ Balance: {}, }, Protocol: { - AccountState: {}, - BlockProver: {}, - StateTransitionProver: {}, - BlockHeight: {}, - LastStateRoot: {}, + ...Protocol.defaultConfig(), ProtocolStateTestHook: {}, }, }; diff --git a/packages/sequencer/test-integration/workers/workers-proven.test.ts b/packages/sequencer/test-integration/workers/workers-proven.test.ts index f914473e..396f8504 100644 --- a/packages/sequencer/test-integration/workers/workers-proven.test.ts +++ b/packages/sequencer/test-integration/workers/workers-proven.test.ts @@ -29,21 +29,30 @@ const timeout = 300000; const proofsEnabled = false; +const numWorkers = 4; + describe("worker-proven", () => { describe("sequencer", () => { let test: BlockTestService; - let worker: ChildProcessWorker; + const workers: ChildProcessWorker[] = []; let appChain: AppChain; beforeAll(async () => { - worker = new ChildProcessWorker(); - worker.start(true, { PROOFS_ENABLED: `${proofsEnabled}` }); + for (let i = 0; i < numWorkers; i++) { + const worker = new ChildProcessWorker(); + worker.start(`worker-${i}`, true, { + PROOFS_ENABLED: `${proofsEnabled}`, + }); + workers.push(worker); + } }); afterAll(async () => { - worker.kill(); + workers.forEach((worker) => { + worker.kill(); + }); await appChain.close(); }); @@ -77,7 +86,9 @@ describe("worker-proven", () => { BlockTrigger: {}, Mempool: {}, BatchProducerModule: {}, - BlockProducerModule: {}, + BlockProducerModule: { + maximumBlockSize: 5, + }, // BaseLayer: {}, TaskQueue: BullConfig, FeeStrategy: {}, @@ -109,17 +120,21 @@ describe("worker-proven", () => { const privateKey = PrivateKey.random(); - await test.addTransaction({ - method: ["Balance", "addBalance"], - privateKey, - args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], - }); + const txs = 4; + + for (let i = 0; i < txs; i++) { + await test.addTransaction({ + method: ["Balance", "addBalance"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], + }); + } const [block, batch] = await test.produceBlockAndBatch(); expectDefined(block); - expect(block.transactions).toHaveLength(1); + expect(block.transactions).toHaveLength(txs); expect(block.transactions[0].status.toBoolean()).toBe(true); expectDefined(batch); @@ -134,9 +149,22 @@ describe("worker-proven", () => { timeout ); - it.each([5, 14, 20])( + it.each([ + [5, 4], + [14, 10], + ])( "should produce a batch of a %s of blocks", - async (numBlocks) => { + async (numBlocks, txs) => { + const privateKey = PrivateKey.random(); + + for (let i = 0; i < txs; i++) { + await test.addTransaction({ + method: ["Balance", "addBalance"], + privateKey, + args: [PrivateKey.random().toPublicKey(), UInt64.from(100)], + }); + } + for (let i = 0; i < numBlocks; i++) { await test.produceBlock(); } From bf77b355017944842f513d3bc67a9954ff19f119 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Wed, 28 Jan 2026 18:02:20 +0100 Subject: [PATCH 08/18] Added master check for initialization queue draining --- packages/deployment/src/queue/BullQueue.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index 179003e4..706c89d4 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -1,5 +1,5 @@ import { MetricsTime, Queue, QueueEvents, Worker } from "bullmq"; -import { log } from "@proto-kit/common"; +import { log, ModuleContainerLike } from "@proto-kit/common"; import { TaskPayload, Closeable, @@ -10,6 +10,7 @@ import { } from "@proto-kit/sequencer"; import { InstantiatedBullQueue } from "./InstantiatedBullQueue"; +import { inject } from "tsyringe"; export interface BullQueueConfig { redis: { @@ -30,6 +31,12 @@ export class BullQueue extends AbstractTaskQueue implements TaskQueue, Closeable { + public constructor( + @inject("ParentContainer") private parent: ModuleContainerLike + ) { + super(); + } + private activePromise?: Promise; public createWorker( @@ -101,9 +108,16 @@ export class BullQueue }); } + private isMaster() { + return this.parent.dependencyContainer.isRegistered("BatchProducerModule"); + } + public async start() { - // Drain all queues to clear stale tasks from previous sequencer instances - await this.drainAllQueues(); + if (this.isMaster()) { + log.debug("Instance is master, draining queue"); + // Drain all queues to clear stale tasks from previous sequencer instances + await this.drainAllQueues(); + } } public async close() { From 9fe306fd16c329d07e040812d96cef8ee89a67ac Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Wed, 28 Jan 2026 18:10:34 +0100 Subject: [PATCH 09/18] Fixed NewBlockTask compile --- .../sequencer/src/protocol/production/tasks/NewBlockTask.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index dfa151ea..486a9ae5 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -169,7 +169,10 @@ export class NewBlockTask } public async prepare(): Promise { - // Compile await this.transactionProver.compile(this.compileRegistry); + await this.stateTransitionProver.compile(this.compileRegistry); + await this.compileRegistry.forceProverExists(async (registry) => { + await this.blockProver.compile(registry); + }); } } From 639121f0bd6b8054c57614b871b76d79079d0186 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Wed, 28 Jan 2026 18:13:18 +0100 Subject: [PATCH 10/18] Added missing decorator to BullQueue --- packages/deployment/src/queue/BullQueue.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index 706c89d4..eaffd9e3 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -7,6 +7,7 @@ import { TaskQueue, AbstractTaskQueue, closeable, + sequencerModule, } from "@proto-kit/sequencer"; import { InstantiatedBullQueue } from "./InstantiatedBullQueue"; @@ -27,6 +28,7 @@ export interface BullQueueConfig { * TaskQueue implementation for BullMQ */ @closeable() +@sequencerModule() export class BullQueue extends AbstractTaskQueue implements TaskQueue, Closeable From c4a37bd303b471cacba5115ba8e096c47f5dfbb7 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Thu, 29 Jan 2026 11:49:10 +0100 Subject: [PATCH 11/18] Removed unnecessary compile calls --- .../sequencer/src/protocol/production/tasks/NewBlockTask.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index 486a9ae5..d4da5471 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -169,10 +169,6 @@ export class NewBlockTask } public async prepare(): Promise { - await this.transactionProver.compile(this.compileRegistry); - await this.stateTransitionProver.compile(this.compileRegistry); - await this.compileRegistry.forceProverExists(async (registry) => { - await this.blockProver.compile(registry); - }); + await this.blockProver.compile(this.compileRegistry); } } From e3f2afaffa46ce913375f701aa1c21e7dc8ed7c1 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 16:33:43 +0100 Subject: [PATCH 12/18] Bunch of queue fixes --- packages/deployment/src/queue/BullQueue.ts | 17 ++++++++-- packages/sequencer/src/worker/flow/Flow.ts | 1 + .../src/worker/queue/LocalTaskQueue.ts | 34 ++++++++++++++++--- .../src/worker/worker/FlowTaskWorker.ts | 8 +++++ .../worker/startup/WorkerRegistrationTask.ts | 4 ++- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index eaffd9e3..fa1b22fd 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -41,6 +41,10 @@ export class BullQueue private activePromise?: Promise; + private workers: Worker[] = []; + + private jobsInProgress = 0; + public createWorker( name: string, executor: (data: TaskPayload) => Promise, @@ -54,7 +58,9 @@ export class BullQueue // computing them, so that leads to bad performance over multiple workers. // For that we need to restructure tasks to be flowing through a single queue however - // TODO Use worker.pause() + this.jobsInProgress += 1; + await Promise.all(this.workers.map((w) => w.pause())); + while (this.activePromise !== undefined) { // eslint-disable-next-line no-await-in-loop await this.activePromise; @@ -70,18 +76,25 @@ export class BullQueue this.activePromise = undefined; void resOutside(); + this.jobsInProgress -= 1; + if (this.jobsInProgress === 0) { + this.workers.map((w) => w.resume()); + } + return result; }, { concurrency: options?.concurrency ?? 1, connection: this.config.redis, stalledInterval: 60000, // 1 minute - lockDuration: 60000, // 1 minute + lockDuration: 60000 * 5, // 5 minutes metrics: { maxDataPoints: MetricsTime.ONE_HOUR * 24 }, } ); + this.workers.push(worker); + // We have to do this, because we want to prevent the worker from crashing worker.on("error", (error) => { log.error("Worker threw error:"); diff --git a/packages/sequencer/src/worker/flow/Flow.ts b/packages/sequencer/src/worker/flow/Flow.ts index 6dd7d5e0..3c4f4310 100644 --- a/packages/sequencer/src/worker/flow/Flow.ts +++ b/packages/sequencer/src/worker/flow/Flow.ts @@ -112,6 +112,7 @@ export class Flow implements Closeable { completed?: CompletedCallback, overrides?: { taskName?: string; + maxRetries?: number; } ): Promise { // We wrap this in a try-catch here, because the flow architecture diff --git a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts index e325508c..5ce6826f 100644 --- a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts +++ b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts @@ -15,12 +15,14 @@ interface QueueListener { export interface LocalTaskQueueConfig { simulatedDuration?: number; + retryAttempts?: number; } class InMemoryInstantiatedQueue implements InstantiatedQueue { public constructor( public readonly name: string, - public taskQueue: LocalTaskQueue + public taskQueue: LocalTaskQueue, + private readonly retries: number ) {} private id = 0; @@ -35,7 +37,11 @@ class InMemoryInstantiatedQueue implements InstantiatedQueue { ): Promise<{ taskId: string }> { this.id += 1; const nextId = taskId ?? String(this.id).toString(); - this.taskQueue.queuedTasks[this.name].push({ payload, taskId: nextId }); + this.taskQueue.queuedTasks[this.name].push({ + payload, + taskId: nextId, + retries: this.retries, + }); void this.taskQueue.workNextTasks(); @@ -74,7 +80,7 @@ export class LocalTaskQueue implements TaskQueue { public queuedTasks: { - [key: string]: { payload: TaskPayload; taskId: string }[]; + [key: string]: { payload: TaskPayload; taskId: string; retries: number }[]; } = {}; private workers: { @@ -117,6 +123,22 @@ export class LocalTaskQueue } log.trace("LocalTaskQueue got", JSON.stringify(payload)); + if (payload.status === "error" && task.retries >= 1) { + log.info( + `Task ${task.taskId} ${task.payload.name} failed, retrying` + ); + + // TODO Not sounds yet, iterator iterates over old entries without + // this new task + this.queuedTasks[queueName].push({ + payload: task.payload, + taskId: task.taskId, + retries: task.retries - 1, + }); + + return; + } + // Notify listeners about result const listenerPromises = this.listeners[queueName]?.map( async (listener) => { @@ -187,7 +209,11 @@ export class LocalTaskQueue public async getQueue(queueName: string): Promise { return this.createOrGetQueue(queueName, (name) => { this.queuedTasks[name] = []; - return new InMemoryInstantiatedQueue(name, this); + return new InMemoryInstantiatedQueue( + name, + this, + this.config.retryAttempts ?? 2 + ); }); } diff --git a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts index d0714289..0a131e31 100644 --- a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts +++ b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts @@ -142,6 +142,13 @@ export class FlowTaskWorker[]> this.preparePromise = preparePromise; if (startupTasks.length > 0) { + for (const task of startupTasks) { + log.info(`Preparing task ${task.constructor.name}`); + // eslint-disable-next-line no-await-in-loop + await task.prepare(); + log.debug(`${task.constructor.name} prepared`); + } + this.workers = Object.fromEntries( unpreparingTasks .concat(startupTasks) @@ -161,6 +168,7 @@ export class FlowTaskWorker[]> } }); }); + log.debug(`Waiting on ${startupTasks.length} startup tasks to be called`); } else { await this.prepareTasks(normalTasks.concat(unpreparingTasks)); } diff --git a/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts index 30339d0f..c1cc8a3f 100644 --- a/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts +++ b/packages/sequencer/src/worker/worker/startup/WorkerRegistrationTask.ts @@ -58,7 +58,7 @@ export class WorkerRegistrationTask public name = "worker-registration"; public async prepare() { - noop(); + log.info("Waiting on sequencer to send registration info..."); } public async compute(input: WorkerStartupPayload) { @@ -115,6 +115,8 @@ export class WorkerRegistrationTask this.events.emit("startup-task-finished"); + log.info("Worker registration completed"); + this.done = true; return true; } From 993c8d353150e42b30326b40324df3bd7bcb0a83 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 16:33:53 +0100 Subject: [PATCH 13/18] Added new lightnet worker test --- package-lock.json | 254 +++++++++++++++++- package.json | 2 + .../Settlement-devnet.test.ts | 5 +- .../Settlement-lightnet-worker.test.ts | 67 +++++ .../test-integration/settlement-worker.ts | 73 +++++ .../sequencer/test-integration/tsconfig.json | 10 + .../workers/ChildProcessWorker.ts | 21 +- .../test-integration/workers/worker.test.ts | 74 ----- .../test-integration/workers/worker.ts | 73 +++++ .../workers/workers-proven.test.ts | 13 +- .../sequencer/test/settlement/Settlement.ts | 125 +++++---- 11 files changed, 580 insertions(+), 137 deletions(-) create mode 100644 packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts create mode 100644 packages/sequencer/test-integration/settlement-worker.ts delete mode 100644 packages/sequencer/test-integration/workers/worker.test.ts create mode 100644 packages/sequencer/test-integration/workers/worker.ts diff --git a/package-lock.json b/package-lock.json index f5626d39..9f35a71f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,8 @@ }, "devDependencies": { "@nrwl/nx-cloud": "latest", + "@swc/core": "^1.15.11", + "@swc/wasm": "^1.15.11", "@types/jest": "^29.4.0", "@types/node": "^20.2.5", "@typescript-eslint/eslint-plugin": "^7.3.1", @@ -6866,6 +6868,215 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@swc/core": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.11.tgz", + "integrity": "sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.25" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.15.11", + "@swc/core-darwin-x64": "1.15.11", + "@swc/core-linux-arm-gnueabihf": "1.15.11", + "@swc/core-linux-arm64-gnu": "1.15.11", + "@swc/core-linux-arm64-musl": "1.15.11", + "@swc/core-linux-x64-gnu": "1.15.11", + "@swc/core-linux-x64-musl": "1.15.11", + "@swc/core-win32-arm64-msvc": "1.15.11", + "@swc/core-win32-ia32-msvc": "1.15.11", + "@swc/core-win32-x64-msvc": "1.15.11" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.11.tgz", + "integrity": "sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.11.tgz", + "integrity": "sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.11.tgz", + "integrity": "sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.11.tgz", + "integrity": "sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.11.tgz", + "integrity": "sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.11.tgz", + "integrity": "sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.11.tgz", + "integrity": "sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.11.tgz", + "integrity": "sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.11.tgz", + "integrity": "sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.11.tgz", + "integrity": "sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -6873,15 +7084,34 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", + "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.25", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", + "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", + "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" + "@swc/counter": "^0.1.3" } }, + "node_modules/@swc/wasm": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/@swc/wasm/-/wasm-1.15.11.tgz", + "integrity": "sha512-230rdYZf8ux3nIwISOQNCFrxzxpL/UFY4Khv/3UsvpEdo709j/+Tg80yXWW3DXETeZNPBV72QpvEBhXsl7Lc9g==", + "devOptional": true, + "license": "Apache-2.0" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "dev": true, @@ -21035,6 +21265,16 @@ } } }, + "node_modules/next/node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -26850,7 +27090,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tsscmp": { diff --git a/package.json b/package.json index a27f72dc..41ced0d5 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "private": true, "devDependencies": { "@nrwl/nx-cloud": "latest", + "@swc/core": "^1.15.11", + "@swc/wasm": "^1.15.11", "@types/jest": "^29.4.0", "@types/node": "^20.2.5", "@typescript-eslint/eslint-plugin": "^7.3.1", diff --git a/packages/sequencer/test-integration/Settlement-devnet.test.ts b/packages/sequencer/test-integration/Settlement-devnet.test.ts index b431d05d..f02d7563 100644 --- a/packages/sequencer/test-integration/Settlement-devnet.test.ts +++ b/packages/sequencer/test-integration/Settlement-devnet.test.ts @@ -4,7 +4,7 @@ import { MinaBaseLayerConfig } from "../src"; import { FungibleToken } from "mina-fungible-token"; import { PrivateKey } from "o1js"; -describe("Settlement - Devnet", () => { +describe.skip("Settlement - Devnet", () => { const network: MinaBaseLayerConfig = { network: { type: "remote", @@ -29,7 +29,7 @@ describe("Settlement - Devnet", () => { }); describe("Default token", () => { - settlementTestFn("proven", network, undefined, 500_000, [ + settlementTestFn("proven", network, undefined, 500_000, undefined, [ sequencerKey, userKey, ]); @@ -43,6 +43,7 @@ describe("Settlement - Devnet", () => { tokenOwner: FungibleToken, }, 500_000, + undefined, [sequencerKey, userKey] ); }); diff --git a/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts new file mode 100644 index 00000000..93cd9208 --- /dev/null +++ b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts @@ -0,0 +1,67 @@ +import { PrivateKey } from "o1js"; +import { log } from "@proto-kit/common"; +import { FungibleToken } from "mina-fungible-token"; +import { BullQueueConfig } from "@proto-kit/deployment"; +import { afterAll, beforeAll } from "@jest/globals"; + +import { settlementTestFn } from "../test/settlement/Settlement"; + +import { ChildProcessWorker } from "./workers/ChildProcessWorker"; +import { BullConfig } from "./workers/modules"; + +console.log(PrivateKey.random().toPublicKey().toBase58()); + +log.setLevel("DEBUG"); + +describe.each(["signed"] as const)( + "settlement contracts: workers + lightnet - %s", + (type) => { + const network = { + network: { + type: "lightnet", + graphql: "http://127.0.0.1:8080/graphql", + archive: "http://127.0.0.1:8282", + accountManager: "http://127.0.0.1:8181", + }, + } as const; + + const queue: BullQueueConfig = { + redis: BullConfig.redis, + retryAttempts: 2, + }; + + const worker = new ChildProcessWorker(); + + beforeAll(() => { + console.error("Starting"); + worker.start( + "worker-0", + "./test-integration/settlement-worker.ts", + true, + { + PROOFS_ENABLED: "false", + } + ); + }); + + afterAll(() => { + worker.kill(); + }); + + describe("Default token", () => { + settlementTestFn(type, network, undefined, 360_000, queue); + }); + + describe.skip("Custom token", () => { + settlementTestFn( + type, + network, + { + tokenOwner: FungibleToken, + }, + 360_000, + queue + ); + }); + } +); diff --git a/packages/sequencer/test-integration/settlement-worker.ts b/packages/sequencer/test-integration/settlement-worker.ts new file mode 100644 index 00000000..b630507a --- /dev/null +++ b/packages/sequencer/test-integration/settlement-worker.ts @@ -0,0 +1,73 @@ +#!/usr/bin/env ts-node + +import "reflect-metadata"; + +// eslint-disable-next-line import/no-extraneous-dependencies +import { BullQueue } from "@proto-kit/deployment"; +import { log } from "@proto-kit/common"; +import { container } from "tsyringe"; +import { Runtime } from "@proto-kit/module"; +import { Protocol } from "@proto-kit/protocol"; + +import { + protocolModules, + protocolModulesConfig, + runtimeModules, + runtimeModulesConfig, +} from "../test/settlement/Settlement"; +import { + AppChain, + LocalTaskWorkerModule, + Sequencer, + VanillaTaskWorkerModules, +} from "../src"; + +import { MinimumWorkerModules } from "./workers/WorkerModules"; +import { BullConfig } from "./workers/modules"; + +/* eslint-disable no-console */ +async function main() { + const proofsEnabled = process.env.PROOFS_ENABLED === "true"; + // const settlementEnabled = process.env.SETTLEMENT_ENABLED === "true"; + + console.log("Starting worker..."); + console.log(`Worker proofs enabled: ${proofsEnabled}`); + // console.log(`Worker settlement enabled: ${settlementEnabled}`); + + log.setLevel("DEBUG"); + + const sequencerClass = Sequencer.from({ + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + // settlementEnabled + VanillaTaskWorkerModules.allTasks() + // : VanillaTaskWorkerModules.withoutSettlement() + ), + } satisfies MinimumWorkerModules); + + const app = AppChain.from({ + Runtime: Runtime.from(runtimeModules), + Sequencer: sequencerClass, + Protocol: Protocol.from(protocolModules), + }); + + app.configure({ + Runtime: runtimeModulesConfig, + Protocol: protocolModulesConfig, + Sequencer: { + TaskQueue: BullConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }, + }); + + log.setLevel("DEBUG"); + + await app.start(proofsEnabled, container.createChildContainer()); +} + +const isSpawned = process.env.IS_SPAWNED_PROCESS === "true"; + +if (isSpawned) { + await main(); +} +/* eslint-enable no-console */ diff --git a/packages/sequencer/test-integration/tsconfig.json b/packages/sequencer/test-integration/tsconfig.json index c5362058..0a123c90 100644 --- a/packages/sequencer/test-integration/tsconfig.json +++ b/packages/sequencer/test-integration/tsconfig.json @@ -3,5 +3,15 @@ "compilerOptions": { "experimentalDecorators": true }, + "ts-node": { + "experimentalSpecifierResolution": "node", + "esm": true, + "experimentalResolver": true, + "transpileOnly": true, + "swc": true, + "compilerOptions": { + "skipLibCheck": true, + } + }, "include": ["./**/*.ts", "./**/*.test.ts", "./*.ts", "./*.ts"] } diff --git a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts index 2c5d737c..91bf802c 100644 --- a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts +++ b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts @@ -5,16 +5,21 @@ export class ChildProcessWorker { start( name: string, + file: string, forwardLogs: boolean = true, env_args: Record = {} ) { + console.log("Spawning process"); + const s = spawn( "node", [ + "--loader", + "ts-node/esm", "--experimental-vm-modules", "--experimental-wasm-modules", - "../../node_modules/jest/bin/jest.js", - "./test-integration/workers/worker.test.ts", + "--es-module-specifier-resolution=node", + file, ], { env: { @@ -24,6 +29,18 @@ export class ChildProcessWorker { }, } ); + + [ + "exit", + "SIGINT", + "SIGUSR1", + "SIGUSR2", + "uncaughtException", + "SIGTERM", + ].forEach((eventType) => { + process.on(eventType, () => this.kill()); + }); + s.on("error", (err) => { // eslint-disable-next-line no-console console.error(err); diff --git a/packages/sequencer/test-integration/workers/worker.test.ts b/packages/sequencer/test-integration/workers/worker.test.ts deleted file mode 100644 index 7d599915..00000000 --- a/packages/sequencer/test-integration/workers/worker.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import "reflect-metadata"; -import { BullQueue } from "@proto-kit/deployment"; -import { container } from "tsyringe"; -import { log, sleep } from "@proto-kit/common"; - -import { - AppChain, - LocalTaskWorkerModule, - Sequencer, - VanillaTaskWorkerModules, -} from "../../src"; - -import { - BullConfig, - protocolClass, - runtimeClass, - runtimeProtocolConfig, -} from "./modules"; -import { MinimumWorkerModules } from "./WorkerModules"; - -describe("worker", () => { - const isSpawned = process.env.IS_SPAWNED_PROCESS === "true"; - - it("spin up and wait", async () => { - if (!isSpawned) { - return; - } - - const proofsEnabled = process.env.PROOFS_ENABLED === "true"; - - const sequencerClass = Sequencer.from({ - TaskQueue: BullQueue, - LocalTaskWorkerModule: LocalTaskWorkerModule.from( - VanillaTaskWorkerModules.withoutSettlement() - ), - } satisfies MinimumWorkerModules); - - const app = AppChain.from({ - Runtime: runtimeClass, - Sequencer: sequencerClass, - Protocol: protocolClass, - }); - - app.configure({ - ...runtimeProtocolConfig, - Sequencer: { - TaskQueue: BullConfig, - LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), - }, - }); - - console.log("Starting worker..."); - console.log(`Worker proofs enabled: ${proofsEnabled}`); - - log.setLevel("DEBUG"); - - await app.start(proofsEnabled, container.createChildContainer()); - - console.log("Worker started..."); - - const ready = await new Promise((res) => { - app - .resolve("Sequencer") - .resolve("LocalTaskWorkerModule") - .containerEvents.on("ready", res); - }); - - expect(ready).toBe(true); - - console.log("Ready received!"); - - await sleep(10000000); - }, 10000000); -}); diff --git a/packages/sequencer/test-integration/workers/worker.ts b/packages/sequencer/test-integration/workers/worker.ts new file mode 100644 index 00000000..d75cf9f5 --- /dev/null +++ b/packages/sequencer/test-integration/workers/worker.ts @@ -0,0 +1,73 @@ +import "reflect-metadata"; +// eslint-disable-next-line import/no-extraneous-dependencies +import { BullQueue } from "@proto-kit/deployment"; +import { container } from "tsyringe"; +import { log, sleep } from "@proto-kit/common"; + +import { + AppChain, + LocalTaskWorkerModule, + Sequencer, + VanillaTaskWorkerModules, +} from "../../src"; + +import { + BullConfig, + protocolClass, + runtimeClass, + runtimeProtocolConfig, +} from "./modules"; +import { MinimumWorkerModules } from "./WorkerModules"; + +async function main() { + const proofsEnabled = process.env.PROOFS_ENABLED === "true"; + + const sequencerClass = Sequencer.from({ + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.withoutSettlement() + ), + } satisfies MinimumWorkerModules); + + const app = AppChain.from({ + Runtime: runtimeClass, + Sequencer: sequencerClass, + Protocol: protocolClass, + }); + + app.configure({ + ...runtimeProtocolConfig, + Sequencer: { + TaskQueue: BullConfig, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig(), + }, + }); + + console.log("Starting worker..."); + console.log(`Worker proofs enabled: ${proofsEnabled}`); + + log.setLevel("DEBUG"); + + await app.start(proofsEnabled, container.createChildContainer()); + + console.log("Worker started..."); + + const ready = await new Promise((res) => { + app + .resolve("Sequencer") + .resolve("LocalTaskWorkerModule") + .containerEvents.on("ready", res); + }); + + expect(ready).toBe(true); + + console.log("Ready received!"); + + await sleep(10000000); +} + +const isSpawned = process.env.IS_SPAWNED_PROCESS === "true"; + +if (isSpawned) { + await main(); +} diff --git a/packages/sequencer/test-integration/workers/workers-proven.test.ts b/packages/sequencer/test-integration/workers/workers-proven.test.ts index 396f8504..9bc774e2 100644 --- a/packages/sequencer/test-integration/workers/workers-proven.test.ts +++ b/packages/sequencer/test-integration/workers/workers-proven.test.ts @@ -29,7 +29,7 @@ const timeout = 300000; const proofsEnabled = false; -const numWorkers = 4; +const numWorkers = 1; describe("worker-proven", () => { describe("sequencer", () => { @@ -42,9 +42,14 @@ describe("worker-proven", () => { beforeAll(async () => { for (let i = 0; i < numWorkers; i++) { const worker = new ChildProcessWorker(); - worker.start(`worker-${i}`, true, { - PROOFS_ENABLED: `${proofsEnabled}`, - }); + worker.start( + `worker-${i}`, + "./test-integration/workers/worker.ts", + true, + { + PROOFS_ENABLED: `${proofsEnabled}`, + } + ); workers.push(worker); } }); diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index 0fa73ba5..532d1b8e 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -3,6 +3,7 @@ import { mapSequential, TypedClass, LinkedMerkleTree, + ModulesConfig, } from "@proto-kit/common"; import { VanillaProtocolModules } from "@proto-kit/library"; import { Runtime } from "@proto-kit/module"; @@ -40,6 +41,7 @@ import { import "reflect-metadata"; import { container } from "tsyringe"; import { FungibleToken, FungibleTokenAdmin } from "mina-fungible-token"; +import { BullQueue, BullQueueConfig } from "@proto-kit/deployment"; import { ManualBlockTrigger, @@ -48,7 +50,6 @@ import { BlockQueue, SettlementModule, MinaBaseLayer, - SettlementProvingTask, MinaTransactionSender, MinaBaseLayerConfig, SignedSettlementPermissions, @@ -57,9 +58,15 @@ import { Sequencer, InMemoryMinaSigner, CircuitAnalysisModule, + LocalTaskWorkerModule, + InMemoryDatabase, + BatchProducerModule, + BlockProducerModule, + LocalTaskQueue, + ConstantFeeStrategy, + SequencerStartupModule, } from "../../src"; import { BlockProofSerializer } from "../../src/protocol/production/tasks/serializers/BlockProofSerializer"; -import { testingSequencerModules } from "../TestingSequencer"; import { createTransaction } from "../integration/utils"; import { FeeStrategy } from "../../src/protocol/baselayer/fees/FeeStrategy"; import { BridgingModule } from "../../src/settlement/BridgingModule"; @@ -70,6 +77,44 @@ import { MinaNetworkUtils } from "../../src/protocol/baselayer/network-utils/Min import { Balances, BalancesKey } from "./mocks/Balances"; import { WithdrawalMessageProcessor, Withdrawals } from "./mocks/Withdrawals"; +export const runtimeModules = { + Balances, + Withdrawals, +}; + +export const runtimeModulesConfig = { + Balances: { + totalSupply: UInt64.from(1000), + }, + Withdrawals: {}, +} satisfies ModulesConfig; + +export const protocolModules = { + ...VanillaProtocolModules.mandatoryModules({}), + SettlementContractModule: SettlementContractModule.from({ + ...SettlementContractModule.settlementAndBridging(), + FungibleToken: FungibleTokenContractModule, + FungibleTokenAdmin: FungibleTokenAdminContractModule, + }), + WithdrawalMessageProcessor, +}; + +export const protocolModulesConfig = { + ...Protocol.defaultConfig(), + SettlementContractModule: { + SettlementContract: {}, + BridgeContract: {}, + DispatchContract: { + incomingMessagesMethods: { + deposit: "Balances.deposit", + }, + }, + FungibleToken: {}, + FungibleTokenAdmin: {}, + }, + WithdrawalMessageProcessor: {}, +} satisfies ModulesConfig; + export const settlementTestFn = ( settlementType: "signed" | "mock-proofs" | "proven", baseLayerConfig: MinaBaseLayerConfig, @@ -77,6 +122,7 @@ export const settlementTestFn = ( tokenOwner: TypedClass & typeof SmartContract; }, timeout: number = 120_000, + bullQueueConfig?: BullQueueConfig, fundedKeysInput: PrivateKey[] = [] ) => { let testAccounts: PrivateKey[] = fundedKeysInput.slice(1); @@ -118,42 +164,41 @@ export const settlementTestFn = ( tokenConfig === undefined ? TokenId.default : tokenOwner!.deriveTokenId(); function setupAppChain() { - const runtime = Runtime.from({ - Balances, - Withdrawals, - }); + const runtime = Runtime.from(runtimeModules); // eslint-disable-next-line @typescript-eslint/dot-notation MinaBaseLayer.prototype["isSignedSettlement"] = () => settlementType === "signed"; - const sequencer = Sequencer.from( - testingSequencerModules( - { - BaseLayer: MinaBaseLayer, - SettlementModule: SettlementModule, - BridgingModule: BridgingModule, - SettlementSigner: InMemoryMinaSigner, - }, - { - SettlementProvingTask, - } - ) + const taskWorkerModule = LocalTaskWorkerModule.from( + VanillaTaskWorkerModules.allTasks() ); + const sequencer = Sequencer.from({ + Database: InMemoryDatabase, + Mempool: PrivateMempool, + BatchProducerModule, + BlockProducerModule, + BlockTrigger: ManualBlockTrigger, + TaskQueue: bullQueueConfig !== undefined ? BullQueue : LocalTaskQueue, + FeeStrategy: ConstantFeeStrategy, + BaseLayer: MinaBaseLayer, + SettlementModule: SettlementModule, + BridgingModule: BridgingModule, + SettlementSigner: InMemoryMinaSigner, + ...(bullQueueConfig !== undefined + ? {} + : { + LocalTaskWorkerModule: taskWorkerModule, + }), + SequencerStartupModule, + }); + const appchain = ClientAppChain.from({ Runtime: runtime, Sequencer: sequencer, - Protocol: Protocol.from({ - ...VanillaProtocolModules.mandatoryModules({}), - SettlementContractModule: SettlementContractModule.from({ - ...SettlementContractModule.settlementAndBridging(), - FungibleToken: FungibleTokenContractModule, - FungibleTokenAdmin: FungibleTokenAdminContractModule, - }), - WithdrawalMessageProcessor, - }), + Protocol: Protocol.from(protocolModules), Signer: InMemorySigner, TransactionSender: InMemoryTransactionSender, @@ -163,12 +208,7 @@ export const settlementTestFn = ( }); appchain.configure({ - Runtime: { - Balances: { - totalSupply: UInt64.from(1000), - }, - Withdrawals: {}, - }, + Runtime: runtimeModulesConfig, Sequencer: { Database: {}, @@ -194,25 +234,11 @@ export const settlementTestFn = ( BridgingModule: {}, SequencerStartupModule: {}, - TaskQueue: { + TaskQueue: bullQueueConfig ?? { simulatedDuration: 0, }, }, - Protocol: { - ...Protocol.defaultConfig(), - SettlementContractModule: { - SettlementContract: {}, - BridgeContract: {}, - DispatchContract: { - incomingMessagesMethods: { - deposit: "Balances.deposit", - }, - }, - FungibleToken: {}, - FungibleTokenAdmin: {}, - }, - WithdrawalMessageProcessor: {}, - }, + Protocol: protocolModulesConfig, TransactionSender: {}, QueryTransportModule: {}, Signer: { @@ -624,6 +650,7 @@ export const settlementTestFn = ( signingWithSignatureCheck: [ tokenOwnerPubKeys.tokenOwner, settlementModule.getSettlementContractAddress(), + bridgingModule.getDispatchContractAddress(), ], signingPublicKeys: [userPublicKey], preventNoncePreconditionFor: [dispatch.address], From 68fa32a843067f0b172b6c7515c674686536df9a Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 16:34:22 +0100 Subject: [PATCH 14/18] Skip new test by default --- .../test-integration/Settlement-lightnet-worker.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts index 93cd9208..d5e4ee71 100644 --- a/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts +++ b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts @@ -13,7 +13,7 @@ console.log(PrivateKey.random().toPublicKey().toBase58()); log.setLevel("DEBUG"); -describe.each(["signed"] as const)( +describe.skip.each(["signed"] as const)( "settlement contracts: workers + lightnet - %s", (type) => { const network = { From 6cd881c704fb7ecb7bc44930742ebbaa20646b5f Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 16:44:29 +0100 Subject: [PATCH 15/18] Fixed missing proofs_enabled flag --- .../test-integration/Settlement-lightnet-worker.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts index d5e4ee71..4d0c71f9 100644 --- a/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts +++ b/packages/sequencer/test-integration/Settlement-lightnet-worker.test.ts @@ -39,7 +39,7 @@ describe.skip.each(["signed"] as const)( "./test-integration/settlement-worker.ts", true, { - PROOFS_ENABLED: "false", + PROOFS_ENABLED: `${(type as string) === "proven"}`, } ); }); From d61895b067b733c9b634777756daf483c2ba2a08 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 17:26:01 +0100 Subject: [PATCH 16/18] Added archive endpoint to tx proving task --- .../src/settlement/tasks/SettlementProvingTask.ts | 11 +++++++++-- .../settlement/transactions/MinaTransactionSender.ts | 2 ++ .../test-integration/workers/ChildProcessWorker.ts | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts index 48dce299..3a8cb231 100644 --- a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts +++ b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts @@ -47,6 +47,7 @@ type Account = ReturnType; export type ChainStateTaskArgs = { accounts: Account[]; graphql: string | undefined; + archive: string | undefined; }; export type TransactionTaskArgs = { @@ -106,7 +107,7 @@ export class SettlementProvingTask state: ChainStateTaskArgs, f: () => Promise ): Promise { - const { graphql, accounts } = state; + const { accounts, graphql, archive } = state; // For this, we assume that remote networks will only be used with separate // worker instances, since they only work with proofs enabled. For @@ -116,7 +117,10 @@ export class SettlementProvingTask if (graphql !== undefined) { const oldInstance = Mina.activeInstance; - const newInstance = Mina.Network(graphql); + const newInstance = Mina.Network({ + mina: graphql, + archive, + }); newInstance.proofsEnabled = this.areProofsEnabled.areProofsEnabled; Mina.setActiveInstance(newInstance); @@ -223,6 +227,7 @@ export class SettlementProvingTask lazyProofs: (LazyProofJson | null)[]; chainState: { graphql: string | undefined | null; + archive: string | undefined | null; accounts: AccountJson[]; }; }; @@ -323,6 +328,7 @@ export class SettlementProvingTask transaction, chainState: { graphql: jsonObject.chainState.graphql ?? undefined, + archive: jsonObject.chainState.archive ?? undefined, accounts: jsonObject.chainState.accounts.map((account) => Types.Account.fromJSON(account) ), @@ -414,6 +420,7 @@ export class SettlementProvingTask lazyProofs, chainState: { graphql: input.chainState.graphql, + archive: input.chainState.archive, accounts: input.chainState.accounts.map((account) => Types.Account.toJSON(account) ), diff --git a/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts b/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts index a594d85c..32c59ea8 100644 --- a/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts +++ b/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts @@ -157,6 +157,7 @@ export class MinaTransactionSender { const { network } = this.baseLayer.config; const graphql = network.type === "local" ? undefined : network.graphql; + const archive = network.type === "local" ? undefined : network.archive; const resultPromise = flow.withFlow( async (resolve, reject) => { @@ -166,6 +167,7 @@ export class MinaTransactionSender { transaction, chainState: { graphql, + archive, accounts: accounts .map((r) => r.account) .filter(filterNonUndefined), diff --git a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts index 91bf802c..32eb74c2 100644 --- a/packages/sequencer/test-integration/workers/ChildProcessWorker.ts +++ b/packages/sequencer/test-integration/workers/ChildProcessWorker.ts @@ -19,6 +19,7 @@ export class ChildProcessWorker { "--experimental-vm-modules", "--experimental-wasm-modules", "--es-module-specifier-resolution=node", + "--no-warnings", file, ], { From 269a9bcd21381f99c3797ca076a82c0344dae5fa Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 17:31:41 +0100 Subject: [PATCH 17/18] Fixed edge case in witness block depth recording --- .../protocol/src/state/WitnessBlockContext.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/protocol/src/state/WitnessBlockContext.ts b/packages/protocol/src/state/WitnessBlockContext.ts index aafbfd24..ee9ce388 100644 --- a/packages/protocol/src/state/WitnessBlockContext.ts +++ b/packages/protocol/src/state/WitnessBlockContext.ts @@ -19,9 +19,11 @@ const asyncProxyWitnessFunction = < return async (...args: Parameters) => { const context = container.resolve(WitnessBlockContext); context.witnessBlockDepth += 1; - const ret = await originalFuncDef(...args); - context.witnessBlockDepth -= 1; - return ret; + try { + return await originalFuncDef(...args); + } finally { + context.witnessBlockDepth -= 1; + } }; }; @@ -35,9 +37,11 @@ const proxySyncWitnessFunction = < return (...args: Params): Ret => { const context = container.resolve(WitnessBlockContext); context.witnessBlockDepth += 1; - const ret = originalFuncDef(...args); - context.witnessBlockDepth -= 1; - return ret; + try { + return originalFuncDef(...args); + } finally { + context.witnessBlockDepth -= 1; + } }; }; From a5ca0c74122af4e1b0e5639dac341b69d228d4dd Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Fri, 30 Jan 2026 17:46:36 +0100 Subject: [PATCH 18/18] Tried fix for concurrency issue --- packages/deployment/src/queue/BullQueue.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/deployment/src/queue/BullQueue.ts b/packages/deployment/src/queue/BullQueue.ts index fa1b22fd..69d10a73 100644 --- a/packages/deployment/src/queue/BullQueue.ts +++ b/packages/deployment/src/queue/BullQueue.ts @@ -58,13 +58,11 @@ export class BullQueue // computing them, so that leads to bad performance over multiple workers. // For that we need to restructure tasks to be flowing through a single queue however - this.jobsInProgress += 1; - await Promise.all(this.workers.map((w) => w.pause())); - while (this.activePromise !== undefined) { // eslint-disable-next-line no-await-in-loop await this.activePromise; } + let resOutside: () => void = () => {}; // TODO Use Promise.withResolvers() for that const promise = new Promise((res) => { @@ -72,6 +70,9 @@ export class BullQueue }); this.activePromise = promise; + this.jobsInProgress += 1; + await Promise.all(this.workers.map((w) => w.pause())); + const result = await executor(job.data); this.activePromise = undefined; void resOutside();