diff --git a/.prettierrc.cjs b/.prettierrc.cjs index 58f794c20..15e84ff65 100644 --- a/.prettierrc.cjs +++ b/.prettierrc.cjs @@ -13,4 +13,5 @@ module.exports = { }, }, ], + plugins: [require.resolve('prettier-plugin-organize-imports')], }; diff --git a/npmDepsHash b/npmDepsHash index ba059f12c..f8bcfc5ba 100644 --- a/npmDepsHash +++ b/npmDepsHash @@ -1 +1 @@ -sha256-CmWUZ+hMItoWISfwCwRNMkAgLm7E7jhUSxncSG/lkNI= +sha256-bk5zmCDgTNA7BOV7babhANh6psLbHvTuicF99lhPsgs= diff --git a/package-lock.json b/package-lock.json index 822437f53..a6021d3cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "oxlint": "^1.0.0", "pkg-pr-new": "^0.0.9", "prettier": "^3.6.2", + "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", "ts-jest": "^28.0.8", @@ -5897,6 +5898,23 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", diff --git a/package.json b/package.json index ea81ed103..847de3769 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "oxlint": "^1.0.0", "pkg-pr-new": "^0.0.9", "prettier": "^3.6.2", + "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", "ts-jest": "^28.0.8", diff --git a/src/lib/proof-system/zkdriver.ts b/src/lib/proof-system/zkdriver.ts new file mode 100644 index 000000000..b3c5c7fcd --- /dev/null +++ b/src/lib/proof-system/zkdriver.ts @@ -0,0 +1,18 @@ +import { CompileOptions, ConfigBaseType, ZkProgram, verify as zkprogramVerify } from './zkprogram.js'; + +class ZKDriverImpl { + _options: CompileOptions + + constructor(options: CompileOptions = {}) { + this._options = options + } + + verify = zkprogramVerify + compile(program: ZkProgram, userOptions: CompileOptions = {}) { + // locality takes precedence + const options = { ...this._options, ...userOptions } + return program.compile(options) + } +} + +export class ZKDriver extends ZKDriverImpl { }; \ No newline at end of file diff --git a/src/lib/proof-system/zkdriver.unit-test.ts b/src/lib/proof-system/zkdriver.unit-test.ts new file mode 100644 index 000000000..cb18b8240 --- /dev/null +++ b/src/lib/proof-system/zkdriver.unit-test.ts @@ -0,0 +1,31 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { Field } from 'o1js'; +import { ZKDriver } from "./zkdriver.js"; +import { ZkProgram } from "./zkprogram.js"; + + +const SimpleProgram = ZkProgram({ + name: "simple-program", + publicOutput: Field, + methods: { + baseCase: { + privateInputs: [], + async method() { + return { + publicOutput: Field(1), + } + } + } + } +}) + +describe("zkDriver", () => { + it("should drive properly with no options", async () => { + const driver = new ZKDriver() + const { verificationKey: vk } = await driver.compile(SimpleProgram) + const result = await SimpleProgram.baseCase(); + const ok = await driver.verify(result.proof, vk); + assert.equal(ok, true, "driver should prove properly"); + }) +}) \ No newline at end of file diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3ca3ba52e..cba88ea6f 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1,29 +1,33 @@ -import { EmptyUndefined, EmptyVoid } from '../../bindings/lib/generic.js'; import { Base64ProofString, Base64VerificationKeyString, - Snarky, + Gate, initializeBindings, + Pickles, + Snarky, withThreadPool, } from '../../bindings.js'; -import { Pickles, Gate } from '../../bindings.js'; -import { Field } from '../provable/wrapped.js'; -import { FlexibleProvable, InferProvable, ProvablePureExtended } from '../provable/types/struct.js'; -import { InferProvableType } from '../provable/types/provable-derivers.js'; -import { Provable } from '../provable/provable.js'; -import { assert, prettifyStacktracePromise } from '../util/errors.js'; +import { setSrsCache, unsetSrsCache } from '../../bindings/crypto/bindings/srs.js'; +import { prefixes } from '../../bindings/crypto/constants.js'; +import { prefixToField } from '../../bindings/lib/binable.js'; +import { EmptyUndefined, EmptyVoid } from '../../bindings/lib/generic.js'; +import { From, InferValue } from '../../bindings/lib/provable-generic.js'; +import { MlArray, MlBool, MlPair, MlResult } from '../ml/base.js'; +import { MlFieldArray, MlFieldConstArray } from '../ml/fields.js'; +import { FieldConst, FieldVar } from '../provable/core/fieldvar.js'; import { ConstraintSystemSummary, snarkContext } from '../provable/core/provable-context.js'; import { hashConstant } from '../provable/crypto/poseidon.js'; -import { MlArray, MlBool, MlResult, MlPair } from '../ml/base.js'; -import { MlFieldArray, MlFieldConstArray } from '../ml/fields.js'; -import { FieldVar, FieldConst } from '../provable/core/fieldvar.js'; -import { Cache, readCache, writeCache } from './cache.js'; -import { decodeProverKey, encodeProverKey, parseHeader } from './prover-keys.js'; -import { setSrsCache, unsetSrsCache } from '../../bindings/crypto/bindings/srs.js'; +import { Provable } from '../provable/provable.js'; +import { InferProvableType } from '../provable/types/provable-derivers.js'; import { ProvableType, ToProvable } from '../provable/types/provable-intf.js'; -import { prefixToField } from '../../bindings/lib/binable.js'; -import { prefixes } from '../../bindings/crypto/constants.js'; -import { Subclass, Tuple, Get } from '../util/types.js'; +import { FlexibleProvable, InferProvable, ProvablePureExtended } from '../provable/types/struct.js'; +import { emptyWitness } from '../provable/types/util.js'; +import { Field } from '../provable/wrapped.js'; +import { mapObject, mapToObject, zip } from '../util/arrays.js'; +import { assert, prettifyStacktracePromise } from '../util/errors.js'; +import { Get, Subclass, Tuple } from '../util/types.js'; +import { Cache, readCache, writeCache } from './cache.js'; +import { featureFlagsFromGates, featureFlagsToMlOption } from './feature-flags.js'; import { dummyProof, DynamicProof, @@ -34,33 +38,30 @@ import { ProofClass, ProofValue, } from './proof.js'; -import { featureFlagsFromGates, featureFlagsToMlOption } from './feature-flags.js'; -import { emptyWitness } from '../provable/types/util.js'; -import { From, InferValue } from '../../bindings/lib/provable-generic.js'; -import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; -import { mapObject, mapToObject, zip } from '../util/arrays.js'; +import { decodeProverKey, encodeProverKey, parseHeader } from './prover-keys.js'; import { VerificationKey } from './verification-key.js'; +import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; // public API -export { SelfProof, JsonProof, ZkProgram, verify, Empty, Undefined, Void, Method }; +export { Empty, JsonProof, Method, SelfProof, Undefined, verify, Void, ZkProgram }; // internal API export { + analyzeMethod, CompiledTag, - sortMethodArguments, + compileProgram, + computeMaxProofsVerified, + dummyBase64Proof, + inCircuitVkHash, MethodInterface, MethodReturnType, picklesRuleFromFunction, - compileProgram, - analyzeMethod, + PrivateInput, + Proof, Prover, - dummyBase64Proof, - computeMaxProofsVerified, RegularProver, + sortMethodArguments, TupleToInstances, - PrivateInput, - Proof, - inCircuitVkHash, }; type Undefined = undefined; @@ -167,7 +168,7 @@ let SideloadedTag = { }, }; -type ConfigBaseType = { +export type ConfigBaseType = { publicInput?: ProvableType; publicOutput?: ProvableType; methods: { @@ -196,6 +197,21 @@ type InferMethodType = { >; }; +export type CompileOptions = { + cache?: Cache; + forceRecompile?: boolean; + proofsEnabled?: boolean; + withRuntimeTables?: boolean; + lazyMode?: boolean; +}; +export const CompileOptionsDefault: Required = { + cache: Cache.FileSystemDefault, + forceRecompile: false, + proofsEnabled: false, + withRuntimeTables: false, + lazyMode: false, +}; + /** * Wraps config + provable code into a program capable of producing {@link Proof}s. * @@ -225,7 +241,7 @@ type InferMethodType = { */ function ZkProgram< Config extends ConfigBaseType, - _ extends unknown = unknown // weird hack that makes methods infer correctly when their inputs are not annotated + _ extends unknown = unknown, // weird hack that makes methods infer correctly when their inputs are not annotated >( config: Config & { name: string; @@ -239,14 +255,7 @@ function ZkProgram< name: string; maxProofsVerified(): Promise<0 | 1 | 2>; - compile: (options?: { - cache?: Cache; - forceRecompile?: boolean; - proofsEnabled?: boolean; - withRuntimeTables?: boolean; - numChunks?: number; - lazyMode?: boolean; - }) => Promise<{ + compile: (options?: CompileOptions) => Promise<{ verificationKey: { data: string; hash: Field }; }>; verify: ( @@ -378,13 +387,12 @@ function ZkProgram< const programState = createProgramState(); - async function compile({ - cache = Cache.FileSystemDefault, - forceRecompile = false, - proofsEnabled = undefined as boolean | undefined, - withRuntimeTables = false, - lazyMode = false, - } = {}) { + async function compile(options: CompileOptions = {}) { + const { cache, forceRecompile, proofsEnabled, withRuntimeTables, lazyMode } = { + ...CompileOptionsDefault, + ...options, + }; + doProving = proofsEnabled ?? doProving; if (doProving) { @@ -603,7 +611,7 @@ type ZkProgram< auxiliaryOutput?: ProvableType; }; }; - } + }, > = ReturnType>; /** @@ -1059,7 +1067,7 @@ function toFieldAndAuxConsts(type: Provable, value: T) { ZkProgram.Proof = function < PublicInputType extends FlexibleProvable, - PublicOutputType extends FlexibleProvable + PublicOutputType extends FlexibleProvable, >(program: { name: string; publicInputType: PublicInputType; @@ -1111,11 +1119,12 @@ function Prover() { // helper types -type Infer = T extends Subclass - ? InstanceType - : T extends ProvableType - ? InferProvableType - : never; +type Infer = + T extends Subclass + ? InstanceType + : T extends ProvableType + ? InferProvableType + : never; type TupleToInstances = { [I in keyof T]: Infer; @@ -1133,13 +1142,13 @@ type MethodReturnType = PublicOutput extends void auxiliaryOutput: AuxiliaryOutput; } : AuxiliaryOutput extends undefined - ? { - publicOutput: PublicOutput; - } - : { - publicOutput: PublicOutput; - auxiliaryOutput: AuxiliaryOutput; - }; + ? { + publicOutput: PublicOutput; + } + : { + publicOutput: PublicOutput; + auxiliaryOutput: AuxiliaryOutput; + }; type Method< PublicInput, @@ -1147,7 +1156,7 @@ type Method< MethodSignature extends { privateInputs: Tuple; auxiliaryOutput?: ProvableType; - } + }, > = PublicInput extends undefined ? { method( @@ -1176,7 +1185,7 @@ type RegularProver< PublicInputType, PublicOutput, Args extends Tuple, - AuxiliaryOutput + AuxiliaryOutput, > = ( publicInput: From, ...args: TupleFrom @@ -1190,7 +1199,7 @@ type Prover< PublicInputType, PublicOutput, Args extends Tuple, - AuxiliaryOutput + AuxiliaryOutput, > = PublicInput extends undefined ? (...args: TupleFrom) => Promise<{ proof: Proof; @@ -1210,8 +1219,8 @@ type ProvableOrVoid = A extends undefined ? typeof Void : ToProvable; type InferProvableOrUndefined = A extends undefined ? undefined : A extends ProvableType - ? InferProvable - : InferProvable | undefined; + ? InferProvable + : InferProvable | undefined; type InferProvableOrVoid = A extends undefined ? void : InferProvable; type UnwrapPromise

= P extends Promise ? T : never;