From 1bcf36ef3e35932cc29adc8d7b477eb8ed3e21d0 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Mon, 9 Mar 2026 21:28:17 -0300 Subject: [PATCH 1/4] Made Compile modules definable per protocol module --- .../tasks/compile/CircuitCompileTask.ts | 8 +++--- .../tasks/compile/ProtocolCompileTask.ts | 27 ++++++++++++++++--- .../src/sequencer/SequencerStartupModule.ts | 12 ++++++--- .../src/worker/flow/UnpreparingTask.ts | 6 ++--- .../worker/worker/LocalTaskWorkerModule.ts | 13 ++++++--- .../src/worker/worker/TaskWorkerModule.ts | 4 ++- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/packages/sequencer/src/protocol/production/tasks/compile/CircuitCompileTask.ts b/packages/sequencer/src/protocol/production/tasks/compile/CircuitCompileTask.ts index b6cdc656c..aa1218a6d 100644 --- a/packages/sequencer/src/protocol/production/tasks/compile/CircuitCompileTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/compile/CircuitCompileTask.ts @@ -5,6 +5,7 @@ import { CompileRegistry, CompilableModule, safeParseJson, + NoConfig, } from "@proto-kit/common"; import { Protocol, @@ -29,10 +30,9 @@ export type CompilerTaskParams = { isSignedSettlement?: boolean; }; -export abstract class CircuitCompileTask extends UnpreparingTask< - CompilerTaskParams, - ArtifactRecord -> { +export abstract class CircuitCompileTask< + Config = NoConfig, +> extends UnpreparingTask { protected constructor( protected readonly protocol: Protocol, protected readonly compileRegistry: CompileRegistry, diff --git a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts index fba628ca9..dd33e6a44 100644 --- a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts @@ -1,4 +1,4 @@ -import { inject, injectable, Lifecycle, scoped } from "tsyringe"; +import { inject, injectable } from "tsyringe"; import { CompilableModule, CompileRegistry } from "@proto-kit/common"; import { ContractArgsRegistry, @@ -9,9 +9,8 @@ import { import { CircuitCompileTask } from "./CircuitCompileTask"; @injectable() -@scoped(Lifecycle.ContainerScoped) export class ProtocolCompileTask extends CircuitCompileTask { - public name = "compile-protocol"; + public name = "undefined"; public constructor( @inject("Protocol") @@ -20,9 +19,29 @@ export class ProtocolCompileTask extends CircuitCompileTask { contractArgsRegistry: ContractArgsRegistry ) { super(protocol, compileRegistry, contractArgsRegistry); + + this.name = `compile-${this.getTargetProtocolModule()}`; + } + + public getTargetProtocolModule(): string { + throw new Error(""); } public async getTargets(): Promise { - return [this.protocol.blockProver]; + return [this.protocol.resolveOrFail(this.getTargetProtocolModule())]; + } +} + +@injectable() +export class BlockProverCompileTask extends ProtocolCompileTask { + public getTargetProtocolModule() { + return "BlockProver"; + } +} + +@injectable() +export class STProverCompileTask extends ProtocolCompileTask { + public getTargetProtocolModule() { + return "StateTransitionProver"; } } diff --git a/packages/sequencer/src/sequencer/SequencerStartupModule.ts b/packages/sequencer/src/sequencer/SequencerStartupModule.ts index 2e37e8bf1..399148f02 100644 --- a/packages/sequencer/src/sequencer/SequencerStartupModule.ts +++ b/packages/sequencer/src/sequencer/SequencerStartupModule.ts @@ -13,6 +13,7 @@ import { CompileRegistry, AreProofsEnabled, CompileArtifact, + ChildContainerProvider, } from "@proto-kit/common"; import { Flow, FlowCreator } from "../worker/flow/Flow"; @@ -21,11 +22,11 @@ import { VerificationKeyService } from "../protocol/runtime/RuntimeVerificationK import type { MinaBaseLayer } from "../protocol/baselayer/MinaBaseLayer"; import { NoopBaseLayer } from "../protocol/baselayer/NoopBaseLayer"; import { RuntimeCompileTask } from "../protocol/production/tasks/compile/RuntimeCompileTask"; -import { ProtocolCompileTask } from "../protocol/production/tasks/compile/ProtocolCompileTask"; import { SettlementCompileTask } from "../protocol/production/tasks/compile/SettlementCompileTask"; import { CompilerTaskParams } from "../protocol/production/tasks/compile/CircuitCompileTask"; import { Task } from "../worker/flow/Task"; import { SettlementModule } from "../settlement/SettlementModule"; +import { BlockProverCompileTask } from "../protocol/production/tasks/compile/ProtocolCompileTask"; import { SequencerModule, sequencerModule } from "./builder/SequencerModule"; import { Closeable, closeable } from "./builder/Closeable"; @@ -41,7 +42,7 @@ export class SequencerStartupModule @inject("Protocol") private readonly protocol: Protocol, private readonly runtimeCompilerTask: RuntimeCompileTask, - private readonly protocolCompilerTask: ProtocolCompileTask, + private readonly blockProverCompilerTask: BlockProverCompileTask, private readonly settlementCompilerTask: SettlementCompileTask, private readonly verificationKeyService: VerificationKeyService, private readonly registrationFlow: WorkerRegistrationFlow, @@ -57,6 +58,11 @@ export class SequencerStartupModule super(); } + public create(childContainerProvider: ChildContainerProvider) { + this.blockProverCompilerTask.config = { target: "BlockProver" }; + this.blockProverCompilerTask.create(childContainerProvider); + } + private async pushCompileTask( flow: Flow<{}>, task: Task, @@ -114,7 +120,7 @@ export class SequencerStartupModule private async compileProtocol(flow: Flow<{}>, runtimeVkTreeRoot: bigint) { const result = await flow.withFlow(async (res, rej) => { await flow.pushTask( - this.protocolCompilerTask, + this.blockProverCompilerTask, { existingArtifacts: this.compileRegistry.getAllArtifacts(), runtimeVKRoot: runtimeVkTreeRoot.toString(), diff --git a/packages/sequencer/src/worker/flow/UnpreparingTask.ts b/packages/sequencer/src/worker/flow/UnpreparingTask.ts index 4ec71f076..c6eb3ff93 100644 --- a/packages/sequencer/src/worker/flow/UnpreparingTask.ts +++ b/packages/sequencer/src/worker/flow/UnpreparingTask.ts @@ -1,4 +1,4 @@ -import { noop } from "@proto-kit/common"; +import { NoConfig, noop } from "@proto-kit/common"; import { TaskWorkerModule } from "../worker/TaskWorkerModule"; @@ -8,8 +8,8 @@ import { Task, TaskSerializer } from "./Task"; * Contract: * Doesn't implement prepare() */ -export abstract class UnpreparingTask - extends TaskWorkerModule +export abstract class UnpreparingTask + extends TaskWorkerModule implements Task { abstract name: string; diff --git a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts index 715ad045b..b77c666fd 100644 --- a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts +++ b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts @@ -30,8 +30,11 @@ import { BlockReductionTask } from "../../protocol/production/tasks/BlockReducti import { TransactionReductionTask } from "../../protocol/production/tasks/TransactionReductionTask"; import { WorkerRegistrationTask } from "../startup/WorkerRegistrationTask"; import { RuntimeCompileTask } from "../../protocol/production/tasks/compile/RuntimeCompileTask"; -import { ProtocolCompileTask } from "../../protocol/production/tasks/compile/ProtocolCompileTask"; import { SettlementCompileTask } from "../../protocol/production/tasks/compile/SettlementCompileTask"; +import { + BlockProverCompileTask, + STProverCompileTask, +} from "../../protocol/production/tasks/compile/ProtocolCompileTask"; import { FlowTaskWorker } from "./FlowTaskWorker"; import { TaskWorkerModule } from "./TaskWorkerModule"; @@ -43,7 +46,7 @@ export { TypedClass }; export type TaskWorkerModulesRecord = ModulesRecord< // TODO any -> unknown - TypedClass> + TypedClass & Task> >; type LocalTaskWorkerModuleEvents = { ready: [boolean] }; @@ -143,7 +146,8 @@ export class VanillaTaskWorkerModules { NewBlockTask, WorkerRegistrationTask, RuntimeCompileTask, - ProtocolCompileTask, + STProverCompileTask, + BlockProverCompileTask, } satisfies TaskWorkerModulesRecord; } @@ -167,8 +171,9 @@ export class VanillaTaskWorkerModules { SettlementProvingTask: {}, WorkerRegistrationTask: {}, RuntimeCompileTask: {}, - ProtocolCompileTask: {}, SettlementCompileTask: {}, + STProverCompileTask: {}, + BlockProverCompileTask: {}, } satisfies ModulesConfig< ReturnType >; diff --git a/packages/sequencer/src/worker/worker/TaskWorkerModule.ts b/packages/sequencer/src/worker/worker/TaskWorkerModule.ts index 35ca7b3f8..d2f46144d 100644 --- a/packages/sequencer/src/worker/worker/TaskWorkerModule.ts +++ b/packages/sequencer/src/worker/worker/TaskWorkerModule.ts @@ -1,3 +1,5 @@ import { ConfigurableModule, NoConfig } from "@proto-kit/common"; -export abstract class TaskWorkerModule extends ConfigurableModule {} +export abstract class TaskWorkerModule< + Config = NoConfig, +> extends ConfigurableModule {} From 18e1cf260c4b363d746b3a901d728cb727f63e36 Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Mon, 9 Mar 2026 21:28:31 -0300 Subject: [PATCH 2/4] Made STProof sideloaded --- .../src/prover/block/BlockProvable.ts | 29 +++++++++-- .../protocol/src/prover/block/BlockProver.ts | 48 +++++++++++-------- .../contracts/settlement/SettlementBase.ts | 2 +- .../protocol/production/tasks/NewBlockTask.ts | 4 +- 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/packages/protocol/src/prover/block/BlockProvable.ts b/packages/protocol/src/prover/block/BlockProvable.ts index 7ceef4e5a..46ac62eca 100644 --- a/packages/protocol/src/prover/block/BlockProvable.ts +++ b/packages/protocol/src/prover/block/BlockProvable.ts @@ -1,7 +1,19 @@ -import { Bool, Field, Poseidon, Proof, Provable, Struct } from "o1js"; +// eslint-disable-next-line max-classes-per-file +import { + Bool, + DynamicProof, + Field, + Poseidon, + Proof, + Provable, + Struct, +} from "o1js"; import { CompilableModule, WithZkProgrammable } from "@proto-kit/common"; -import { StateTransitionProof } from "../statetransition/StateTransitionProvable"; +import { + StateTransitionProverPublicInput, + StateTransitionProverPublicOutput, +} from "../statetransition/StateTransitionProvable"; import { NetworkState } from "../../model/network/NetworkState"; import { TransactionHashList } from "../accumulators/TransactionHashList"; import { MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList"; @@ -345,6 +357,17 @@ export class BlockProverState { } } +export class DynamicSTProof extends DynamicProof< + StateTransitionProverPublicInput, + StateTransitionProverPublicOutput +> { + static publicInputType = StateTransitionProverPublicInput; + + static publicOutputType = StateTransitionProverPublicOutput; + + static maxProofsVerified = 2 as const; +} + export type BlockProof = Proof; export interface BlockProvable @@ -368,7 +391,7 @@ export interface BlockProvable batch: BlockArgumentsBatch, deferSTProof: Bool, deferTransactionProof: Bool, - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, transactionProof: TransactionProof ) => Promise; diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts index 6f600d896..bea06655e 100644 --- a/packages/protocol/src/prover/block/BlockProver.ts +++ b/packages/protocol/src/prover/block/BlockProver.ts @@ -2,6 +2,7 @@ import { Bool, Field, Provable, SelfProof, ZkProgram } from "o1js"; import { container, inject, injectable, injectAll } from "tsyringe"; import { AreProofsEnabled, + ChildVerificationKeyService, CompilableModule, CompileArtifact, CompileRegistry, @@ -16,7 +17,6 @@ import { import { ProtocolModule } from "../../protocol/ProtocolModule"; import { - StateTransitionProof, StateTransitionProvable, StateTransitionProverPublicInput, StateTransitionProverPublicOutput, @@ -51,6 +51,7 @@ import { BlockProverPublicOutput, BlockProverState, BlockProverStateInput, + DynamicSTProof, } from "./BlockProvable"; import { BlockHashMerkleTreeWitness, @@ -74,16 +75,13 @@ export class BlockProverProgrammable extends ZkProgrammable< > { public constructor( private readonly prover: BlockProver, - public readonly stateTransitionProver: ZkProgrammable< - StateTransitionProverPublicInput, - StateTransitionProverPublicOutput - >, public readonly transactionProver: ZkProgrammable< TransactionProverPublicInput, TransactionProverPublicOutput >, private readonly blockHooks: ProvableBlockHook[], - private readonly stateServiceProvider: StateServiceProvider + private readonly stateServiceProvider: StateServiceProvider, + private readonly childVerificationKeyService: ChildVerificationKeyService ) { super(); } @@ -141,7 +139,7 @@ export class BlockProverProgrammable extends ZkProgrammable< } public includeSTProof( - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, apply: Bool, stateRoot: Field, pendingSTBatchesHash: Field, @@ -224,7 +222,7 @@ export class BlockProverProgrammable extends ZkProgrammable< private verifySTProof( state: BlockProverState, - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, deferSTProof: Bool ) { // Verify ST Proof only if STs have been emitted, @@ -233,7 +231,15 @@ export class BlockProverProgrammable extends ZkProgrammable< const batchesEmpty = state.pendingSTBatches.commitment.equals(Field(0)); const verifyStProof = deferSTProof.not().and(batchesEmpty.not()); log.provable.debug("Verify STProof", verifyStProof); - stateTransitionProof.verifyIf(verifyStProof); + + // Brought in as a constant + const stProofVk = this.childVerificationKeyService.getVerificationKey( + "StateTransitionProver" + ); + if (!stProofVk.hash.isConstant()) { + throw new Error("Sanity check - vk hash has to be constant"); + } + stateTransitionProof.verifyIf(stProofVk, verifyStProof); // Apply STProof if not deferred const stateProofResult = this.includeSTProof( @@ -402,7 +408,7 @@ export class BlockProverProgrammable extends ZkProgrammable< batch: BlockArgumentsBatch, deferSTProof: Bool, deferTransactionProof: Bool, - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, transactionProof: TransactionProof ) { const finalize = deferTransactionProof.or(deferSTProof).not(); @@ -432,7 +438,7 @@ export class BlockProverProgrammable extends ZkProgrammable< deferSTProof: Bool, deferTransactionProof: Bool, finalize: Bool, - stateTransitionProof?: StateTransitionProof, + stateTransitionProof?: DynamicSTProof, transactionProof?: TransactionProof ): Promise { let state = this.parseState( @@ -621,8 +627,7 @@ export class BlockProverProgrammable extends ZkProgrammable< BlockProverPublicInput, BlockProverPublicOutput >[] { - const { prover, stateTransitionProver, transactionProver } = this; - const StateTransitionProofClass = stateTransitionProver.zkProgram[0].Proof; + const { prover, transactionProver } = this; const TransactionProofClass = transactionProver.zkProgram[0].Proof; const proveBlockBatchWithProofs = prover.proveBlockBatchWithProofs.bind(prover); @@ -643,7 +648,7 @@ export class BlockProverProgrammable extends ZkProgrammable< BlockArgumentsBatch, Bool, Bool, - StateTransitionProofClass, + DynamicSTProof, TransactionProofClass, ], async method( @@ -654,7 +659,7 @@ export class BlockProverProgrammable extends ZkProgrammable< batch: BlockArgumentsBatch, deferSTProof: Bool, deferTransactionProof: Bool, - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, transactionProof: TransactionProof ) { return { @@ -768,23 +773,26 @@ export class BlockProver @injectAll("ProvableBlockHook") blockHooks: ProvableBlockHook[], @inject("StateServiceProvider") - stateServiceProvider: StateServiceProvider + stateServiceProvider: StateServiceProvider, + childVerificationKeyService: ChildVerificationKeyService ) { super(); this.zkProgrammable = new BlockProverProgrammable( this, - stateTransitionProver.zkProgrammable, transactionProver.zkProgrammable, blockHooks, - stateServiceProvider + stateServiceProvider, + childVerificationKeyService ); } public async compile( registry: CompileRegistry ): Promise | undefined> { - return await registry.proverNeeded(async () => { + await registry.sideloaded(async () => { await this.stateTransitionProver.compile(registry); + }); + return await registry.proverNeeded(async () => { await this.transactionProver.compile(registry); return await this.zkProgrammable.compile(registry); }); @@ -816,7 +824,7 @@ export class BlockProver batch: BlockArgumentsBatch, deferSTProof: Bool, deferTransactionProof: Bool, - stateTransitionProof: StateTransitionProof, + stateTransitionProof: DynamicSTProof, transactionProof: TransactionProof ): Promise { return this.zkProgrammable.proveBlockBatchWithProofs( diff --git a/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts index 050543b5f..c44857d1b 100644 --- a/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts +++ b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts @@ -150,8 +150,8 @@ export abstract class SettlementBase throw new Error("Sanity check - vk hash has to be constant"); } // Verify the blockproof - blockProof.verify(blockProofVk); + // Get and assert on-chain values const stateRoot = this.stateRoot.getAndRequireEquals(); const networkStateHash = this.networkStateHash.getAndRequireEquals(); diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index bac58cf3c..58e704591 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -15,6 +15,7 @@ import { BlockArgumentsBatch, BlockProverStateInput, ProtocolConstants, + DynamicSTProof, } from "@proto-kit/protocol"; import { Bool } from "o1js"; import { @@ -143,6 +144,7 @@ export class NewBlockTask // deferSTProof.or(deferTransactionProof) ); } else { + const stProof = DynamicSTProof.fromProof(input1); await this.blockProver.proveBlockBatchWithProofs( publicInput, stateWitness, @@ -151,7 +153,7 @@ export class NewBlockTask blockArgumentBatch, deferSTProof, deferTransactionProof, - input1, + stProof, input2 ); } From 7c93047e832fec7c986500209006f1d0004d03bf Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Mon, 9 Mar 2026 22:42:11 -0300 Subject: [PATCH 3/4] Made TransactionProof sideloaded in BlockProver --- .../services/ChildVerificationKeyService.ts | 8 ++++ .../src/prover/block/BlockProvable.ts | 18 ++++++- .../protocol/src/prover/block/BlockProver.ts | 35 ++++++-------- .../sdk/src/query/StateServiceQueryModule.ts | 2 +- .../protocol/production/tasks/NewBlockTask.ts | 4 +- .../tasks/compile/ProtocolCompileTask.ts | 7 +++ .../src/sequencer/SequencerStartupModule.ts | 47 ++++++++++++------- .../worker/worker/LocalTaskWorkerModule.ts | 5 +- 8 files changed, 85 insertions(+), 41 deletions(-) diff --git a/packages/common/src/compiling/services/ChildVerificationKeyService.ts b/packages/common/src/compiling/services/ChildVerificationKeyService.ts index 1e90738d1..526b522ef 100644 --- a/packages/common/src/compiling/services/ChildVerificationKeyService.ts +++ b/packages/common/src/compiling/services/ChildVerificationKeyService.ts @@ -23,4 +23,12 @@ export class ChildVerificationKeyService { } return artifact.verificationKey; } + + public getAsConstant(name: string) { + const vk = this.getVerificationKey(name); + if (!vk.hash.isConstant()) { + throw new Error("Sanity check - vk hash has to be constant"); + } + return vk; + } } diff --git a/packages/protocol/src/prover/block/BlockProvable.ts b/packages/protocol/src/prover/block/BlockProvable.ts index 46ac62eca..361df387e 100644 --- a/packages/protocol/src/prover/block/BlockProvable.ts +++ b/packages/protocol/src/prover/block/BlockProvable.ts @@ -22,7 +22,10 @@ import { WitnessedRootHashList, WitnessedRootWitness, } from "../accumulators/WitnessedRootHashList"; -import { TransactionProof } from "../transaction/TransactionProvable"; +import { + TransactionProverPublicInput, + TransactionProverPublicOutput, +} from "../transaction/TransactionProvable"; import { BundleHashList, FieldTransition } from "../accumulators/BlockHashList"; import { NonMethods } from "../../utils/utils"; import { Constants } from "../../Constants"; @@ -368,6 +371,17 @@ export class DynamicSTProof extends DynamicProof< static maxProofsVerified = 2 as const; } +export class DynamicTransactionProof extends DynamicProof< + TransactionProverPublicInput, + TransactionProverPublicOutput +> { + static publicInputType = TransactionProverPublicInput; + + static publicOutputType = TransactionProverPublicOutput; + + static maxProofsVerified = 2 as const; +} + export type BlockProof = Proof; export interface BlockProvable @@ -392,7 +406,7 @@ export interface BlockProvable deferSTProof: Bool, deferTransactionProof: Bool, stateTransitionProof: DynamicSTProof, - transactionProof: TransactionProof + transactionProof: DynamicTransactionProof ) => Promise; merge: ( diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts index bea06655e..643229794 100644 --- a/packages/protocol/src/prover/block/BlockProver.ts +++ b/packages/protocol/src/prover/block/BlockProver.ts @@ -35,7 +35,6 @@ import { assertEqualsIf } from "../../utils/utils"; import { StateServiceProvider } from "../../state/StateServiceProvider"; import { executeHooks } from "../utils"; import { - TransactionProof, TransactionProvable, TransactionProverPublicInput, TransactionProverPublicOutput, @@ -52,6 +51,7 @@ import { BlockProverState, BlockProverStateInput, DynamicSTProof, + DynamicTransactionProof, } from "./BlockProvable"; import { BlockHashMerkleTreeWitness, @@ -75,10 +75,6 @@ export class BlockProverProgrammable extends ZkProgrammable< > { public constructor( private readonly prover: BlockProver, - public readonly transactionProver: ZkProgrammable< - TransactionProverPublicInput, - TransactionProverPublicOutput - >, private readonly blockHooks: ProvableBlockHook[], private readonly stateServiceProvider: StateServiceProvider, private readonly childVerificationKeyService: ChildVerificationKeyService @@ -233,12 +229,9 @@ export class BlockProverProgrammable extends ZkProgrammable< log.provable.debug("Verify STProof", verifyStProof); // Brought in as a constant - const stProofVk = this.childVerificationKeyService.getVerificationKey( + const stProofVk = this.childVerificationKeyService.getAsConstant( "StateTransitionProver" ); - if (!stProofVk.hash.isConstant()) { - throw new Error("Sanity check - vk hash has to be constant"); - } stateTransitionProof.verifyIf(stProofVk, verifyStProof); // Apply STProof if not deferred @@ -256,7 +249,7 @@ export class BlockProverProgrammable extends ZkProgrammable< private verifyTransactionProof( state: BlockProverState, - transactionProof: TransactionProof, + transactionProof: DynamicTransactionProof, deferTransactionProof: Bool ) { // Verify Transaction proof if it has at least 1 tx and it isn't deferred @@ -265,7 +258,11 @@ export class BlockProverProgrammable extends ZkProgrammable< state.bundleList.isEmpty().not() ); - transactionProof.verifyIf(verifyTransactionProof); + // Brought in as a constant + const transactionProofVk = this.childVerificationKeyService.getAsConstant( + "StateTransitionProver" + ); + transactionProof.verifyIf(transactionProofVk, verifyTransactionProof); // Fast-forward transaction trackers by the results of the aggregated transaction proof // Implicitly, the 'from' values here are asserted against the publicInput, since the hashlists @@ -409,7 +406,7 @@ export class BlockProverProgrammable extends ZkProgrammable< deferSTProof: Bool, deferTransactionProof: Bool, stateTransitionProof: DynamicSTProof, - transactionProof: TransactionProof + transactionProof: DynamicTransactionProof ) { const finalize = deferTransactionProof.or(deferSTProof).not(); @@ -439,7 +436,7 @@ export class BlockProverProgrammable extends ZkProgrammable< deferTransactionProof: Bool, finalize: Bool, stateTransitionProof?: DynamicSTProof, - transactionProof?: TransactionProof + transactionProof?: DynamicTransactionProof ): Promise { let state = this.parseState( publicInput, @@ -627,8 +624,7 @@ export class BlockProverProgrammable extends ZkProgrammable< BlockProverPublicInput, BlockProverPublicOutput >[] { - const { prover, transactionProver } = this; - const TransactionProofClass = transactionProver.zkProgram[0].Proof; + const { prover } = this; const proveBlockBatchWithProofs = prover.proveBlockBatchWithProofs.bind(prover); const proveBlockBatchNoProofs = prover.proveBlockBatchNoProofs.bind(prover); @@ -649,7 +645,7 @@ export class BlockProverProgrammable extends ZkProgrammable< Bool, Bool, DynamicSTProof, - TransactionProofClass, + DynamicTransactionProof, ], async method( publicInput: BlockProverPublicInput, @@ -660,7 +656,7 @@ export class BlockProverProgrammable extends ZkProgrammable< deferSTProof: Bool, deferTransactionProof: Bool, stateTransitionProof: DynamicSTProof, - transactionProof: TransactionProof + transactionProof: DynamicTransactionProof ) { return { publicOutput: await proveBlockBatchWithProofs( @@ -779,7 +775,6 @@ export class BlockProver super(); this.zkProgrammable = new BlockProverProgrammable( this, - transactionProver.zkProgrammable, blockHooks, stateServiceProvider, childVerificationKeyService @@ -791,9 +786,9 @@ export class BlockProver ): Promise | undefined> { await registry.sideloaded(async () => { await this.stateTransitionProver.compile(registry); + await this.transactionProver.compile(registry); }); return await registry.proverNeeded(async () => { - await this.transactionProver.compile(registry); return await this.zkProgrammable.compile(registry); }); } @@ -825,7 +820,7 @@ export class BlockProver deferSTProof: Bool, deferTransactionProof: Bool, stateTransitionProof: DynamicSTProof, - transactionProof: TransactionProof + transactionProof: DynamicTransactionProof ): Promise { return this.zkProgrammable.proveBlockBatchWithProofs( publicInput, diff --git a/packages/sdk/src/query/StateServiceQueryModule.ts b/packages/sdk/src/query/StateServiceQueryModule.ts index 399fdb617..8d91da199 100644 --- a/packages/sdk/src/query/StateServiceQueryModule.ts +++ b/packages/sdk/src/query/StateServiceQueryModule.ts @@ -31,7 +31,7 @@ export class StateServiceQueryModule } public get treeStore(): AsyncLinkedLeafStore { - return this.sequencer.dependencyContainer.resolve("AsyncLinkedMerkleStore"); + return this.sequencer.dependencyContainer.resolve("AsyncLinkedLeafStore"); } public get(key: Field) { diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index 58e704591..ff85dafb2 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -16,6 +16,7 @@ import { BlockProverStateInput, ProtocolConstants, DynamicSTProof, + DynamicTransactionProof, } from "@proto-kit/protocol"; import { Bool } from "o1js"; import { @@ -145,6 +146,7 @@ export class NewBlockTask ); } else { const stProof = DynamicSTProof.fromProof(input1); + const txProof = DynamicTransactionProof.fromProof(input2); await this.blockProver.proveBlockBatchWithProofs( publicInput, stateWitness, @@ -154,7 +156,7 @@ export class NewBlockTask deferSTProof, deferTransactionProof, stProof, - input2 + txProof ); } } diff --git a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts index dd33e6a44..a8e6040a0 100644 --- a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts @@ -45,3 +45,10 @@ export class STProverCompileTask extends ProtocolCompileTask { return "StateTransitionProver"; } } + +@injectable() +export class TransactionProverCompileTask extends ProtocolCompileTask { + public getTargetProtocolModule() { + return "TransactionProver"; + } +} diff --git a/packages/sequencer/src/sequencer/SequencerStartupModule.ts b/packages/sequencer/src/sequencer/SequencerStartupModule.ts index 399148f02..27e3849e9 100644 --- a/packages/sequencer/src/sequencer/SequencerStartupModule.ts +++ b/packages/sequencer/src/sequencer/SequencerStartupModule.ts @@ -13,7 +13,7 @@ import { CompileRegistry, AreProofsEnabled, CompileArtifact, - ChildContainerProvider, + mapSequential, } from "@proto-kit/common"; import { Flow, FlowCreator } from "../worker/flow/Flow"; @@ -23,10 +23,17 @@ import type { MinaBaseLayer } from "../protocol/baselayer/MinaBaseLayer"; import { NoopBaseLayer } from "../protocol/baselayer/NoopBaseLayer"; import { RuntimeCompileTask } from "../protocol/production/tasks/compile/RuntimeCompileTask"; import { SettlementCompileTask } from "../protocol/production/tasks/compile/SettlementCompileTask"; -import { CompilerTaskParams } from "../protocol/production/tasks/compile/CircuitCompileTask"; +import { + CircuitCompileTask, + CompilerTaskParams, +} from "../protocol/production/tasks/compile/CircuitCompileTask"; import { Task } from "../worker/flow/Task"; import { SettlementModule } from "../settlement/SettlementModule"; -import { BlockProverCompileTask } from "../protocol/production/tasks/compile/ProtocolCompileTask"; +import { + BlockProverCompileTask, + STProverCompileTask, + TransactionProverCompileTask, +} from "../protocol/production/tasks/compile/ProtocolCompileTask"; import { SequencerModule, sequencerModule } from "./builder/SequencerModule"; import { Closeable, closeable } from "./builder/Closeable"; @@ -41,9 +48,11 @@ export class SequencerStartupModule private readonly flowCreator: FlowCreator, @inject("Protocol") private readonly protocol: Protocol, - private readonly runtimeCompilerTask: RuntimeCompileTask, - private readonly blockProverCompilerTask: BlockProverCompileTask, - private readonly settlementCompilerTask: SettlementCompileTask, + private readonly runtimeCompileTask: RuntimeCompileTask, + private readonly stProverCompileTask: STProverCompileTask, + private readonly transactionProverCompileTask: TransactionProverCompileTask, + private readonly blockProverCompileTask: BlockProverCompileTask, + private readonly settlementCompileTask: SettlementCompileTask, private readonly verificationKeyService: VerificationKeyService, private readonly registrationFlow: WorkerRegistrationFlow, private readonly compileRegistry: CompileRegistry, @@ -58,11 +67,6 @@ export class SequencerStartupModule super(); } - public create(childContainerProvider: ChildContainerProvider) { - this.blockProverCompilerTask.config = { target: "BlockProver" }; - this.blockProverCompilerTask.create(childContainerProvider); - } - private async pushCompileTask( flow: Flow<{}>, task: Task, @@ -78,7 +82,7 @@ export class SequencerStartupModule public async compileRuntime(flow: Flow<{}>) { const artifacts = await this.pushCompileTask( flow, - this.runtimeCompilerTask, + this.runtimeCompileTask, { existingArtifacts: {}, runtimeVKRoot: undefined, @@ -102,7 +106,7 @@ export class SequencerStartupModule private async compileBridge(flow: Flow<{}>, isSignedSettlement?: boolean) { const result = await flow.withFlow(async (res, rej) => { await flow.pushTask( - this.settlementCompilerTask, + this.settlementCompileTask, { existingArtifacts: this.compileRegistry.getAllArtifacts(), runtimeVKRoot: undefined, @@ -117,10 +121,14 @@ export class SequencerStartupModule return result; } - private async compileProtocol(flow: Flow<{}>, runtimeVkTreeRoot: bigint) { + private async compileProtocol( + flow: Flow<{}>, + task: CircuitCompileTask, + runtimeVkTreeRoot: bigint + ) { const result = await flow.withFlow(async (res, rej) => { await flow.pushTask( - this.blockProverCompilerTask, + task, { existingArtifacts: this.compileRegistry.getAllArtifacts(), runtimeVKRoot: runtimeVkTreeRoot.toString(), @@ -159,7 +167,14 @@ export class SequencerStartupModule const root = await this.compileRuntime(flow); - await this.compileProtocol(flow, root); + const tasks = [ + this.transactionProverCompileTask, + this.stProverCompileTask, + this.blockProverCompileTask, + ]; + await mapSequential(tasks, async (task) => { + await this.compileProtocol(flow, task, root); + }); let bridgeVk: CompileArtifact | undefined = undefined; diff --git a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts index b77c666fd..fc81159e8 100644 --- a/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts +++ b/packages/sequencer/src/worker/worker/LocalTaskWorkerModule.ts @@ -34,6 +34,7 @@ import { SettlementCompileTask } from "../../protocol/production/tasks/compile/S import { BlockProverCompileTask, STProverCompileTask, + TransactionProverCompileTask, } from "../../protocol/production/tasks/compile/ProtocolCompileTask"; import { FlowTaskWorker } from "./FlowTaskWorker"; @@ -148,6 +149,7 @@ export class VanillaTaskWorkerModules { RuntimeCompileTask, STProverCompileTask, BlockProverCompileTask, + TransactionProverCompileTask, } satisfies TaskWorkerModulesRecord; } @@ -171,9 +173,10 @@ export class VanillaTaskWorkerModules { SettlementProvingTask: {}, WorkerRegistrationTask: {}, RuntimeCompileTask: {}, - SettlementCompileTask: {}, STProverCompileTask: {}, BlockProverCompileTask: {}, + TransactionProverCompileTask: {}, + SettlementCompileTask: {}, } satisfies ModulesConfig< ReturnType >; From be3a79ada83b6038d63062d83b8d68a8b9b6c2cc Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Mon, 9 Mar 2026 23:17:02 -0300 Subject: [PATCH 4/4] Fixed bug in localtaskqueue for quick sequential tasks --- .../production/tasks/compile/ProtocolCompileTask.ts | 2 +- .../src/sequencer/SequencerStartupModule.ts | 4 ++-- .../sequencer/src/worker/queue/LocalTaskQueue.ts | 12 +++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts index a8e6040a0..dc2b59001 100644 --- a/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/compile/ProtocolCompileTask.ts @@ -20,7 +20,7 @@ export class ProtocolCompileTask extends CircuitCompileTask { ) { super(protocol, compileRegistry, contractArgsRegistry); - this.name = `compile-${this.getTargetProtocolModule()}`; + this.name = `compile-${this.getTargetProtocolModule().toLowerCase()}`; } public getTargetProtocolModule(): string { diff --git a/packages/sequencer/src/sequencer/SequencerStartupModule.ts b/packages/sequencer/src/sequencer/SequencerStartupModule.ts index 27e3849e9..1f7aaec7b 100644 --- a/packages/sequencer/src/sequencer/SequencerStartupModule.ts +++ b/packages/sequencer/src/sequencer/SequencerStartupModule.ts @@ -168,9 +168,9 @@ export class SequencerStartupModule const root = await this.compileRuntime(flow); const tasks = [ - this.transactionProverCompileTask, - this.stProverCompileTask, this.blockProverCompileTask, + this.stProverCompileTask, + this.transactionProverCompileTask, ]; await mapSequential(tasks, async (task) => { await this.compileProtocol(flow, task, root); diff --git a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts index 5ce6826f3..df03e90a3 100644 --- a/packages/sequencer/src/worker/queue/LocalTaskQueue.ts +++ b/packages/sequencer/src/worker/queue/LocalTaskQueue.ts @@ -149,6 +149,10 @@ export class LocalTaskQueue }); this.queuedTasks[queueName] = []; return functions; + } else if (tasks.length > 0) { + log.warn( + `Tasks found in queue ${queueName} but no worker registered` + ); } return []; @@ -161,11 +165,17 @@ export class LocalTaskQueue this.taskInProgress = false; // In case new tasks came up in the meantime, execute them as well - if (tasksToExecute.length > 0) { + if (this.hasTasksQueued()) { await this.workNextTasks(); } } + private hasTasksQueued() { + return Object.entries(this.queuedTasks).some( + ([, tasks]) => tasks.length > 0 + ); + } + public createWorker( queueName: string, executor: (data: TaskPayload) => Promise,