From 684b62170b566cca8a99e0e9797633b65369c55e Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sat, 9 Nov 2024 23:52:49 +0700 Subject: [PATCH 1/2] Enabled proven settlement --- .../common/src/compiling/CompileRegistry.ts | 7 +- packages/common/src/utils.ts | 4 + .../src/protocol/baselayer/MinaBaseLayer.ts | 23 ++- .../production/BlockTaskFlowService.ts | 8 +- .../production/tasks/CircuitCompilerTask.ts | 21 ++- .../src/sequencer/SequencerStartupModule.ts | 10 -- .../src/sequencer/SettlementStartupModule.ts | 77 ++++++++++ .../src/settlement/SettlementModule.ts | 16 ++- .../settlement/tasks/SettlementProvingTask.ts | 132 +++++++++++------- .../transactions/MinaTransactionSender.ts | 2 + .../src/worker/worker/FlowTaskWorker.ts | 3 +- .../Settlement-proven.test.ts | 28 ++++ .../sequencer/test/integration/Proven.test.ts | 18 +++ .../test/settlement/Settlement.test.ts | 6 +- .../sequencer/test/settlement/Settlement.ts | 11 +- 15 files changed, 280 insertions(+), 86 deletions(-) create mode 100644 packages/sequencer/src/sequencer/SettlementStartupModule.ts create mode 100644 packages/sequencer/test-integration/Settlement-proven.test.ts diff --git a/packages/common/src/compiling/CompileRegistry.ts b/packages/common/src/compiling/CompileRegistry.ts index c43c50a94..9df6cefd8 100644 --- a/packages/common/src/compiling/CompileRegistry.ts +++ b/packages/common/src/compiling/CompileRegistry.ts @@ -1,6 +1,9 @@ import { inject, injectable, singleton } from "tsyringe"; -import { AreProofsEnabled } from "../zkProgrammable/ZkProgrammable"; +import { + AreProofsEnabled, + CompileArtifact, +} from "../zkProgrammable/ZkProgrammable"; import { ArtifactRecord, @@ -38,7 +41,7 @@ export class CompileRegistry { return this.artifacts[target.name]; } - public getArtifact(name: string) { + public getArtifact(name: string): CompileArtifact | undefined { if (this.artifacts[name] === undefined) { throw new Error( `Artifact for ${name} not available, did you compile it via the CompileRegistry?` diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index 23b351d0c..dab816a1a 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -176,6 +176,10 @@ export function isSubtypeOfName( clas: TypedClass, name: string ): boolean { + if (clas === undefined || clas === null) { + return false; + } + if (clas.name === name) { return true; } diff --git a/packages/sequencer/src/protocol/baselayer/MinaBaseLayer.ts b/packages/sequencer/src/protocol/baselayer/MinaBaseLayer.ts index 2dca724b4..8d60cbbd7 100644 --- a/packages/sequencer/src/protocol/baselayer/MinaBaseLayer.ts +++ b/packages/sequencer/src/protocol/baselayer/MinaBaseLayer.ts @@ -1,9 +1,13 @@ -import { DependencyFactory } from "@proto-kit/common"; +import { AreProofsEnabled, DependencyFactory } from "@proto-kit/common"; import { Mina } from "o1js"; import { match } from "ts-pattern"; +import { inject } from "tsyringe"; import { MinaIncomingMessageAdapter } from "../../settlement/messages/MinaIncomingMessageAdapter"; -import { SequencerModule } from "../../sequencer/builder/SequencerModule"; +import { + sequencerModule, + SequencerModule, +} from "../../sequencer/builder/SequencerModule"; import { MinaTransactionSender } from "../../settlement/transactions/MinaTransactionSender"; import { WithdrawalQueue } from "../../settlement/messages/WithdrawalQueue"; @@ -27,6 +31,7 @@ export interface MinaBaseLayerConfig { }; } +@sequencerModule() export class MinaBaseLayer extends SequencerModule implements BaseLayer, DependencyFactory @@ -35,6 +40,13 @@ export class MinaBaseLayer public originalNetwork?: Parameters[0]; + public constructor( + @inject("AreProofsEnabled") + private readonly areProofsEnabled: AreProofsEnabled + ) { + super(); + } + public dependencies() { return { IncomingMessageAdapter: { @@ -63,7 +75,10 @@ export class MinaBaseLayer const Network = await match(network) .with( { type: "local" }, - async () => await Mina.LocalBlockchain({ proofsEnabled: false }) + async () => + await Mina.LocalBlockchain({ + proofsEnabled: this.areProofsEnabled.areProofsEnabled, + }) ) .with({ type: "lightnet" }, async (lightnet) => { const net = Mina.Network({ @@ -71,7 +86,7 @@ export class MinaBaseLayer archive: lightnet.archive, lightnetAccountManager: lightnet.accountManager, }); - net.proofsEnabled = false; + net.proofsEnabled = this.areProofsEnabled.areProofsEnabled; return net; }) .with({ type: "remote" }, async (remote) => diff --git a/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts b/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts index 8733dc5bb..20cad8cc9 100644 --- a/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts +++ b/packages/sequencer/src/protocol/production/BlockTaskFlowService.ts @@ -9,7 +9,7 @@ import { Protocol, StateTransitionProof, } from "@proto-kit/protocol"; -import { log } from "@proto-kit/common"; +import { log, MOCK_PROOF } from "@proto-kit/common"; import { TaskQueue } from "../../worker/queue/TaskQueue"; import { Flow, FlowCreator } from "../../worker/flow/Flow"; @@ -194,7 +194,11 @@ export class BlockTaskFlowService { this.flowCreator ); blockMergingFlow.onCompletion(async (result) => { - log.debug(`Block generation finished, with proof ${result.proof}`); // TODO Remove result logging + const printableProof = + result.proof === MOCK_PROOF + ? result.proof + : result.toJSON().proof.slice(100); + log.debug(`Block generation finished, with proof ${printableProof}`); // TODO Remove result logging flow.resolve(result); }); blockMergingFlow.deferErrorsTo(flow); diff --git a/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts b/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts index 5d02c5e8f..c99c14255 100644 --- a/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/CircuitCompilerTask.ts @@ -8,6 +8,7 @@ import { CompileRegistry, CompilableModule, safeParseJson, + reduceSequential, } from "@proto-kit/common"; import { MandatorySettlementModulesRecord, @@ -132,11 +133,29 @@ export class CircuitCompilerTask extends UnpreparingTask< // eslint-disable-next-line @typescript-eslint/consistent-type-assertions settlementModule.moduleNames as StringKeyOf[]; - const modules = moduleNames.map((name) => [ + const modules = moduleNames.map<[string, CompilableModule]>((name) => [ `Settlement.${name}`, settlementModule.resolve(name), ]); + const sumModule = { + compile: async (registry: CompileRegistry) => { + await reduceSequential( + modules.map(([, module]) => module), + async (record, module) => { + const artifacts = await module.compile(registry); + return { + ...record, + ...artifacts, + }; + }, + {} + ); + }, + }; + + modules.push(["Settlement", sumModule]); + return Object.fromEntries(modules); } return {}; diff --git a/packages/sequencer/src/sequencer/SequencerStartupModule.ts b/packages/sequencer/src/sequencer/SequencerStartupModule.ts index 0c9b4a9c7..69ea8a890 100644 --- a/packages/sequencer/src/sequencer/SequencerStartupModule.ts +++ b/packages/sequencer/src/sequencer/SequencerStartupModule.ts @@ -136,16 +136,6 @@ export class SequencerStartupModule extends SequencerModule { bridgeVk.verificationKey; } - const record = await this.pushCompileTask(flow, { - existingArtifacts: this.compileRegistry.getAllArtifacts(), - targets: ["Settlement.SettlementContract"], - }); - - this.compileRegistry.addArtifactsRaw(record); - - // TODO Compile all contracts and retrieve artifacts to enable crafting of - // the deployments - edit: can also be done on-demand with the CompileTask - await this.registrationFlow.start({ runtimeVerificationKeyRoot: root, bridgeContractVerificationKey: bridgeVk?.verificationKey, diff --git a/packages/sequencer/src/sequencer/SettlementStartupModule.ts b/packages/sequencer/src/sequencer/SettlementStartupModule.ts new file mode 100644 index 000000000..e9c7f7f70 --- /dev/null +++ b/packages/sequencer/src/sequencer/SettlementStartupModule.ts @@ -0,0 +1,77 @@ +import { injectable } from "tsyringe"; +import { + ArtifactRecord, + CompileArtifact, + CompileRegistry, + log, +} from "@proto-kit/common"; + +import { FlowCreator } from "../worker/flow/Flow"; +import { CircuitCompilerTask } from "../protocol/production/tasks/CircuitCompilerTask"; + +@injectable() +export class SettlementStartupModule { + public constructor( + private readonly compileRegistry: CompileRegistry, + private readonly flowCreator: FlowCreator, + private readonly compileTask: CircuitCompilerTask + ) {} + + // TODO Compile only individual contracts - this however runs into the + // unlinkability issue from module name to artifact name + // although - the settlement proving task currently also only works if + // all contracts that a tx touches are compiled on that worker instance + private async compile() { + const flow = this.flowCreator.createFlow("compile-deploy", {}); + const artifacts = await flow.withFlow(async (res) => { + await flow.pushTask( + this.compileTask, + { + existingArtifacts: this.compileRegistry.getAllArtifacts(), + targets: ["Settlement"], + runtimeVKRoot: undefined, + }, + async (result) => res(result) + ); + }); + this.compileRegistry.addArtifactsRaw(artifacts); + return artifacts; + } + + private async getArtifacts(retry: boolean): Promise<{ + SettlementSmartContract: CompileArtifact; + DispatchSmartContract: CompileArtifact; + }> { + const settlementVerificationKey = this.compileRegistry.getArtifact( + "SettlementSmartContract" + ); + const dispatchVerificationKey = this.compileRegistry.getArtifact( + "DispatchSmartContract" + ); + + if ( + settlementVerificationKey === undefined || + dispatchVerificationKey === undefined + ) { + if (!retry) { + log.info( + "Settlement Contracts not yet compiled, initializing compilation" + ); + await this.compile(); + return await this.getArtifacts(true); + } + throw new Error( + "Settlement contract verification keys not available for deployment" + ); + } + + return { + SettlementSmartContract: settlementVerificationKey, + DispatchSmartContract: dispatchVerificationKey, + }; + } + + public async retrieveVerificationKeys() { + return await this.getArtifacts(false); + } +} diff --git a/packages/sequencer/src/settlement/SettlementModule.ts b/packages/sequencer/src/settlement/SettlementModule.ts index 1dd61dd37..ddad111ba 100644 --- a/packages/sequencer/src/settlement/SettlementModule.ts +++ b/packages/sequencer/src/settlement/SettlementModule.ts @@ -27,7 +27,6 @@ import { log, AreProofsEnabled, DependencyFactory, - CompileRegistry, } from "@proto-kit/common"; import truncate from "lodash/truncate"; @@ -41,6 +40,7 @@ import { Batch, SettleableBatch } from "../storage/model/Batch"; import { BlockProofSerializer } from "../protocol/production/helpers/BlockProofSerializer"; import { Settlement } from "../storage/model/Settlement"; import { FeeStrategy } from "../protocol/baselayer/fees/FeeStrategy"; +import { SettlementStartupModule } from "../sequencer/SettlementStartupModule"; import { IncomingMessageAdapter } from "./messages/IncomingMessageAdapter"; import { MinaTransactionSender } from "./transactions/MinaTransactionSender"; @@ -97,7 +97,7 @@ export class SettlementModule @inject("AreProofsEnabled") areProofsEnabled: AreProofsEnabled, @inject("FeeStrategy") private readonly feeStrategy: FeeStrategy, - private readonly compileRegistry: CompileRegistry + private readonly settlementStartupModule: SettlementStartupModule ) { super(); this.utils = new SettlementUtils(areProofsEnabled, baseLayer); @@ -253,8 +253,6 @@ export class SettlementModule const nonce = options?.nonce ?? 0; - // const verificationKey: - const sm = this.protocol.dependencyContainer.resolve< SettlementContractModule >("SettlementContractModule"); @@ -263,6 +261,9 @@ export class SettlementModule dispatch: dispatchKey.toPublicKey(), }); + const verificationsKeys = + await this.settlementStartupModule.retrieveVerificationKeys(); + const permissions = this.utils.isSignedSettlement() ? new SignedSettlementPermissions() : new ProvenSettlementPermissions(); @@ -277,13 +278,14 @@ export class SettlementModule async () => { AccountUpdate.fundNewAccount(feepayer, 2); await settlement.deploy({ - // TODO Create compilation task that generates those artifacts if proofs enabled - verificationKey: undefined, + verificationKey: + verificationsKeys.SettlementSmartContract.verificationKey, }); settlement.account.permissions.set(permissions.settlementContract()); await dispatch.deploy({ - verificationKey: undefined, + verificationKey: + verificationsKeys.DispatchSmartContract.verificationKey, }); dispatch.account.permissions.set(permissions.dispatchContract()); } diff --git a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts index 38782a60b..e5c2755b8 100644 --- a/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts +++ b/packages/sequencer/src/settlement/tasks/SettlementProvingTask.ts @@ -1,9 +1,10 @@ import { filterNonUndefined, - MOCK_PROOF, AreProofsEnabled, log, CompileRegistry, + mapSequential, + safeParseJson, } from "@proto-kit/common"; import { MandatoryProtocolModulesRecord, @@ -23,6 +24,9 @@ import { Transaction, Void, SmartContract, + ProofBase, + AccountUpdateForest, + AccountUpdate, } from "o1js"; import { inject, injectable, Lifecycle, scoped } from "tsyringe"; @@ -139,8 +143,7 @@ export class SettlementProvingTask return { transaction: provenTx }; } - // Subclass is not exported - private getProofSerializer(proofType: Subclass) { + private getProofSerializer(proofType: Subclass) { return proofType.prototype instanceof Proof ? new ProofTaskSerializer( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -157,7 +160,6 @@ export class SettlementProvingTask type LazyProofJson = { methodName: string; args: ({ fields: string[]; aux: string[] } | string)[]; - previousProofs: string[]; zkappClassName: string; memoized: { fields: string[]; aux: any[] }[]; blindingValue: string; @@ -214,42 +216,58 @@ export class SettlementProvingTask const proofTypes = method.proofArgs; let proofsDecoded = 0; - const args = lazyProof.args.map((encodedArg, argsIndex) => { - if (allArgs[argsIndex].type === "witness") { - // encodedArg is this type - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const arg = encodedArg as { fields: string[]; aux: string[] }; + // eslint-disable-next-line no-await-in-loop + const args = await mapSequential( + lazyProof.args, + async (encodedArg, argsIndex) => { + if (allArgs[argsIndex].type === "witness") { + const argType = witnessArgTypes[argsIndex - proofsDecoded]; + // encodedArg is this type + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + const arg = encodedArg as { fields: string[]; aux: string[] }; + + // Special case for AccountUpdateForest + if ( + arg.aux.length > 0 && + JSON.parse(arg.aux[0]).typeName === "AccountUpdateForest" + ) { + const [accountUpdatesJSON] = arg.aux.map((aux) => + safeParseJson<{ + accountUpdates: Types.Json.AccountUpdate[]; + typeName: "AccountUpdateForest"; + }>(aux) + ); + const accountUpdates = + accountUpdatesJSON.accountUpdates.map((auJSON) => + AccountUpdate.fromJSON(auJSON) + ); + return AccountUpdateForest.fromFlatArray(accountUpdates); + } - return witnessArgTypes[argsIndex - proofsDecoded].fromFields( - arg.fields.map((field) => Field(field)), - arg.aux.map((auxI) => JSON.parse(auxI)) + return argType.fromFields( + arg.fields.map((field) => Field(field)), + arg.aux.map((auxI) => JSON.parse(auxI)) + ); + } + // fields is JsonProof + const serializer = this.getProofSerializer( + proofTypes[proofsDecoded] ); - } - // fields is JsonProof - const serializer = this.getProofSerializer( - proofTypes[proofsDecoded] - ); - proofsDecoded += 1; - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - return serializer.fromJSON(encodedArg as string); - }); + proofsDecoded += 1; + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return await serializer.fromJSON(encodedArg as string); + } + ); - // eslint-disable-next-line no-await-in-loop - const previousProofs = await Promise.all( - lazyProof.previousProofs.map(async (proofString) => { - if (proofString === MOCK_PROOF) { - return MOCK_PROOF; - } + const proofArgIndizes = allArgs + .filter((arg) => arg.type === "proof") + .map((arg) => arg.index); - const p = await SomeProofSubclass.fromJSON({ - maxProofsVerified: 0, - publicInput: ["0"], - publicOutput: [], - proof: proofString, - }); - return p.proof; - }) + const previousProofs = proofArgIndizes.map( + (argIndex) => + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + (args[argIndex] as ProofBase).proof ); transaction.transaction.accountUpdates[index].lazyAuthorization = { @@ -293,7 +311,7 @@ export class SettlementProvingTask throw new Error("Method interface not found"); } - const allArgs = method.allArgs.slice(2); // .filter(arg => arg.type === "witness"); + const allArgs = method.allArgs.slice(2); const witnessArgTypes = method.witnessArgs.slice(2); const proofTypes = method.proofArgs; let proofsEncoded = 0; @@ -301,13 +319,34 @@ export class SettlementProvingTask const encodedArgs = lazyProof.args .map((arg, index) => { if (allArgs[index].type === "witness") { - const witness = witnessArgTypes[index - proofsEncoded]; - const fields = witness + const witnessType = + witnessArgTypes[index - proofsEncoded]; + + // Special case for AUForest + if (arg instanceof AccountUpdateForest) { + const accountUpdates = AccountUpdateForest.toFlatArray( + arg + ).map((update) => AccountUpdate.toJSON(update)); + + return { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + fields: [] as string[], + aux: [ + JSON.stringify({ + accountUpdates, + typeName: "AccountUpdateForest", + }), + ], + }; + } + + const fields = witnessType .toFields(arg) .map((f) => f.toString()); - const aux = witness + const aux = witnessType .toAuxiliary(arg) .map((x) => JSON.stringify(x)); + return { fields, aux, @@ -321,7 +360,7 @@ export class SettlementProvingTask // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return serializer.toJSON(arg); } - throw new Error("Generic parameters not supported"); + throw new Error("Non-provable parameters not supported"); }) .filter(filterNonUndefined); @@ -332,19 +371,6 @@ export class SettlementProvingTask blindingValue: lazyProof.blindingValue.toString(), memoized: [], - - previousProofs: lazyProof.previousProofs.map((proof) => { - if (proof === MOCK_PROOF) { - return MOCK_PROOF; - } - const p = new SomeProofSubclass({ - proof, - publicInput: Field(0), - publicOutput: undefined, - maxProofsVerified: 0, - }); - return p.toJSON().proof; - }), }; } return null; diff --git a/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts b/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts index acdbda034..551476616 100644 --- a/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts +++ b/packages/sequencer/src/settlement/transactions/MinaTransactionSender.ts @@ -162,6 +162,8 @@ export class MinaTransactionSender { log.debug("Tx proving complete, queueing for sending"); + log.trace(result.transaction.toPretty()); + const txStatus = await this.sendOrQueue(result.transaction); if (waitOnStatus !== "none") { diff --git a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts index 8db8a0c28..3bdc28b00 100644 --- a/packages/sequencer/src/worker/worker/FlowTaskWorker.ts +++ b/packages/sequencer/src/worker/worker/FlowTaskWorker.ts @@ -60,7 +60,8 @@ export class FlowTaskWorker[]> const payload = error instanceof Error ? error.message : JSON.stringify(error); - log.info("Error in worker (detailed trace): ", error); + log.info("Error in worker (detailed trace): "); + log.info(error); return { status: "error", diff --git a/packages/sequencer/test-integration/Settlement-proven.test.ts b/packages/sequencer/test-integration/Settlement-proven.test.ts new file mode 100644 index 000000000..f5cef4e8a --- /dev/null +++ b/packages/sequencer/test-integration/Settlement-proven.test.ts @@ -0,0 +1,28 @@ +import { FungibleToken } from "mina-fungible-token"; + +import { MinaBaseLayerConfig } from "../src"; +import { settlementTestFn } from "../test/settlement/Settlement"; + +// Disabled this for now since the CI for this will likely fail +describe.skip("Settlement contracts: local blockchain - proven", () => { + const network: MinaBaseLayerConfig = { + network: { + type: "local", + }, + }; + + describe("Default token", () => { + settlementTestFn("proven", network, undefined, 500_000); + }); + + describe("Custom token", () => { + settlementTestFn( + "proven", + network, + { + tokenOwner: FungibleToken, + }, + 500_000 + ); + }); +}); diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts index 4f0195b74..5911ce034 100644 --- a/packages/sequencer/test/integration/Proven.test.ts +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -28,6 +28,7 @@ import { SettlementProvingTask, WithdrawalQueue, } from "../../src"; +import { SettlementStartupModule } from "../../src/sequencer/SettlementStartupModule"; import { ProtocolStateTestHook } from "./mocks/ProtocolStateTestHook"; import { BlockTestService } from "./services/BlockTestService"; @@ -38,6 +39,8 @@ const timeout = 300000; describe("Proven", () => { let test: BlockTestService; + let appChain: AppChain; + it( "should start up and compile", async () => { @@ -136,6 +139,8 @@ describe("Proven", () => { await app.start(true, childContainer); test = app.sequencer.dependencyContainer.resolve(BlockTestService); + + appChain = app; } catch (e) { console.error(e); throw e; @@ -144,6 +149,19 @@ describe("Proven", () => { timeout ); + it("should compile settlement contracts", async () => { + const module = appChain.sequencer.dependencyContainer.resolve( + SettlementStartupModule + ); + + const vks = await module.retrieveVerificationKeys(); + + console.log(vks); + + expect(vks.DispatchSmartContract).toBeDefined(); + expect(vks.SettlementSmartContract).toBeDefined(); + }); + it.skip("Hello", async () => { try { const vkService = new ChildVerificationKeyService(); diff --git a/packages/sequencer/test/settlement/Settlement.test.ts b/packages/sequencer/test/settlement/Settlement.test.ts index 926fce456..fd7ee60c5 100644 --- a/packages/sequencer/test/settlement/Settlement.test.ts +++ b/packages/sequencer/test/settlement/Settlement.test.ts @@ -1,15 +1,17 @@ import { FungibleToken } from "mina-fungible-token"; +import { MinaBaseLayerConfig } from "../../src"; + import { settlementTestFn } from "./Settlement"; describe.each(["mock-proofs", "signed"] as const)( "Settlement contracts: local blockchain - %s", (type) => { - const network = { + const network: MinaBaseLayerConfig = { network: { type: "local", }, - } as const; + }; describe("Default token", () => { settlementTestFn(type, network); diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index c55d19449..b27b92e53 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -69,10 +69,8 @@ import { FungibleTokenAdminContractModule } from "../../src/settlement/utils/Fun import { Balances, BalancesKey } from "./mocks/Balances"; import { Withdrawals } from "./mocks/Withdrawals"; -log.setLevel("DEBUG"); - export const settlementTestFn = ( - settlementType: "signed" | "mock-proofs", + settlementType: "signed" | "mock-proofs" | "proven", baseLayerConfig: MinaBaseLayerConfig, tokenConfig?: { tokenOwner: TypedClass & typeof SmartContract; @@ -257,9 +255,14 @@ export const settlementTestFn = ( } beforeAll(async () => { + log.setLevel("DEBUG"); + appChain = setupAppChain(); - await appChain.start(false, container.createChildContainer()); + await appChain.start( + settlementType === "proven", + container.createChildContainer() + ); settlementModule = appChain.sequencer.resolve( "SettlementModule" From 4a3e15bffdb7b97311576b6fa398a5d2e085c4cc Mon Sep 17 00:00:00 2001 From: Raphael Panic Date: Sun, 10 Nov 2024 18:48:46 +0700 Subject: [PATCH 2/2] Added forceProverExists to protect against missing provers for non-sideloaded circuits --- .../common/src/compiling/CompileRegistry.ts | 18 ++++++++++++++++-- .../protocol/src/prover/block/BlockProver.ts | 6 ++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/common/src/compiling/CompileRegistry.ts b/packages/common/src/compiling/CompileRegistry.ts index 9df6cefd8..0b097284c 100644 --- a/packages/common/src/compiling/CompileRegistry.ts +++ b/packages/common/src/compiling/CompileRegistry.ts @@ -30,10 +30,24 @@ export class CompileRegistry { private artifacts: ArtifactRecord = {}; - // TODO Add possibility to force recompilation for non-sideloaded dependencies + private inForceProverBlock = false; + + /** + * This function forces compilation even if the artifact itself is in the registry. + * Basically the statement is: The artifact along is not enough, we need to + * actually have the prover compiled. + * This is true for non-sideloaded circuit dependencies. + */ + public async forceProverExists( + f: (registry: CompileRegistry) => Promise + ) { + this.inForceProverBlock = true; + await f(this); + this.inForceProverBlock = false; + } public async compile(target: CompileTarget) { - if (this.artifacts[target.name] === undefined) { + if (this.artifacts[target.name] === undefined || this.inForceProverBlock) { const artifact = await this.compiler.compileContract(target); this.artifacts[target.name] = artifact; return artifact; diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts index 344dad06b..239ecb49d 100644 --- a/packages/protocol/src/prover/block/BlockProver.ts +++ b/packages/protocol/src/prover/block/BlockProver.ts @@ -931,8 +931,10 @@ export class BlockProver public async compile( registry: CompileRegistry ): Promise | undefined> { - await this.stateTransitionProver.compile(registry); - await this.runtime.compile(registry); + await registry.forceProverExists(async () => { + await this.stateTransitionProver.compile(registry); + await this.runtime.compile(registry); + }); return await this.zkProgrammable.compile(registry); }