UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

329 lines (328 loc) 15.9 kB
import { Base64ProofString, Base64VerificationKeyString } 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 { ConstraintSystemSummary } from '../provable/core/provable-context.js'; import { FieldConst } from '../provable/core/fieldvar.js'; import { Cache } from './cache.js'; import { ProvableType, ToProvable } from '../provable/types/provable-intf.js'; import { Subclass, Tuple } from '../util/types.js'; import { Proof, ProofBase, ProofClass, ProofValue } from './proof.js'; import { From, InferValue } from '../../bindings/lib/provable-generic.js'; import { VerificationKey } from './verification-key.js'; export { SelfProof, JsonProof, ZkProgram, verify, Empty, Undefined, Void, Method }; export { CompiledTag, sortMethodArguments, MethodInterface, MethodReturnType, picklesRuleFromFunction, compileProgram, analyzeMethod, Prover, dummyBase64Proof, computeMaxProofsVerified, RegularProver, TupleToInstances, PrivateInput, Proof, inCircuitVkHash, }; type Undefined = undefined; declare const Undefined: ProvablePureExtended<undefined, undefined, null>; type Empty = Undefined; declare const Empty: ProvablePureExtended<undefined, undefined, null>; type Void = undefined; declare const Void: ProvablePureExtended<void, void, null>; type MethodAnalysis = ConstraintSystemSummary & { proofs: ProofClass[]; }; declare function createProgramState(): { setNonPureOutput(value: any[]): void; getNonPureOutput(): any[]; setAuxiliaryOutput(value: unknown, methodName: string): void; getAuxiliaryOutput(methodName: string): unknown; reset(key: string): void; }; /** * Initializes Pickles bindings, serializes the input proof and verification key for use in OCaml, then calls into the Pickles verify function and returns the result. * * @note This function is meant to be called in JavaScript, not for use in a circuit. The verification key data and hash are not confirmed to match. * @param proof Either a `Proof` instance or a serialized JSON proof * @param verificationKey Either a base64 serialized verification key or a `VerificationKey` instance which will be base64 serialized for use in the bindings. * @returns A promise that resolves to a boolean indicating whether the proof is valid. */ declare function verify(proof: ProofBase<any, any> | JsonProof, verificationKey: Base64VerificationKeyString | VerificationKey): Promise<boolean>; /** * Serializable representation of a Pickles proof, useful for caching compiled proofs. */ type JsonProof = { /** Array of string, where each string is a `Field` in the publicInput of this proof */ publicInput: string[]; /** Array of string, where each string is a `Field` in the publicOutput of this proof */ publicOutput: string[]; maxProofsVerified: 0 | 1 | 2; proof: Base64ProofString; }; type CompiledTag = unknown; declare let CompiledTag: { get(tag: any): CompiledTag | undefined; store(tag: any, compiledTag: CompiledTag): void; }; type ConfigBaseType = { publicInput?: ProvableType; publicOutput?: ProvableType; methods: { [I in string]: { privateInputs: Tuple<PrivateInput>; auxiliaryOutput?: ProvableType; }; }; }; type InferMethodSignatures<Config extends ConfigBaseType> = Config['methods']; type InferPrivateInput<Config extends ConfigBaseType> = { [I in keyof Config['methods']]: Config['methods'][I]['privateInputs']; }; type InferAuxiliaryOutputs<Config extends ConfigBaseType> = { [I in keyof InferMethodSignatures<Config>]: Get<InferMethodSignatures<Config>[I], 'auxiliaryOutput'>; }; type InferMethodType<Config extends ConfigBaseType> = { [I in keyof Config['methods']]: Method<InferProvableOrUndefined<Get<Config, 'publicInput'>>, InferProvableOrVoid<Get<Config, 'publicOutput'>>, Config['methods'][I]>; }; /** * Wraps config + provable code into a program capable of producing {@link Proof}s. * * @example * ```ts * const ExampleProgram = ZkProgram({ * name: 'ExampleProgram', * publicOutput: Int64, * methods: { * // Prove that I know 2 numbers less than 100 each, whose product is greater than 1000 * provableMultiply: { * privateInputs: [Int64, Int64], * method: async (n1: Int64, n2: Int64) => { * n1.assertLessThan(100); * n2.assertLessThan(100); * const publicOutput = n1.mul(n2); * publicOutput.assertGreaterThan(1000); * return { publicOutput: n1.mul(n2) } * } * } * } * }); * ``` * * @param config The configuration of the program, describing the type of the public input and public output, as well as defining the methods which can be executed provably. * @returns an object that can be used to compile, prove, and verify the program. */ declare function ZkProgram<Config extends ConfigBaseType, _ extends unknown = unknown>(config: Config & { name: string; methods: { [I in keyof Config['methods']]: InferMethodType<Config>[I]; }; overrideWrapDomain?: 0 | 1 | 2; numChunks?: number; }): { name: string; maxProofsVerified(): Promise<0 | 1 | 2>; compile: (options?: { cache?: Cache; forceRecompile?: boolean; proofsEnabled?: boolean; withRuntimeTables?: boolean; numChunks?: number; lazyMode?: boolean; }) => Promise<{ verificationKey: { data: string; hash: Field; }; }>; verify: (proof: Proof<InferProvableOrUndefined<Get<Config, 'publicInput'>>, InferProvableOrVoid<Get<Config, 'publicOutput'>>>) => Promise<boolean>; digest: () => Promise<string>; /** * Analyze the constraint system created by each method in the program. * Every method is executed in a circuit, and the constraints are analyzed. * * @returns A summary of this ZkProgram, keyed by the method name, with a value of the {@link MethodAnalysis} for that method */ analyzeMethods: () => Promise<{ [I in keyof Config['methods']]: MethodAnalysis; }>; /** * Analyze the constraint system created by a single method in the program without analyzing any other methods and executing them. * * @returns A summary of this method, with a value of the {@link MethodAnalysis} for that method */ analyzeSingleMethod<K extends keyof Config['methods']>(methodName: K): Promise<MethodAnalysis>; publicInputType: ProvableOrUndefined<Get<Config, 'publicInput'>>; publicOutputType: ProvableOrVoid<Get<Config, 'publicOutput'>>; privateInputTypes: InferPrivateInput<Config>; auxiliaryOutputTypes: InferAuxiliaryOutputs<Config>; rawMethods: { [I in keyof Config['methods']]: InferMethodType<Config>[I]['method']; }; Proof: typeof Proof<InferProvableOrUndefined<Get<Config, 'publicInput'>>, InferProvableOrVoid<Get<Config, 'publicOutput'>>>; proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { [I in keyof Config['methods']]: Prover<InferProvableOrUndefined<Get<Config, 'publicInput'>>, ProvableOrUndefined<Get<Config, 'publicInput'>>, InferProvableOrVoid<Get<Config, 'publicOutput'>>, InferPrivateInput<Config>[I], InferProvableOrUndefined<InferAuxiliaryOutputs<Config>[I]>>; }; declare namespace ZkProgram { var Proof: <PublicInputType extends FlexibleProvable<any>, PublicOutputType extends FlexibleProvable<any>>(program: { name: string; publicInputType: PublicInputType; publicOutputType: PublicOutputType; }) => { new ({ proof, publicInput, publicOutput, maxProofsVerified, }: { proof: unknown; publicInput: InferProvable<PublicInputType>; publicOutput: InferProvable<PublicOutputType>; maxProofsVerified: 0 | 2 | 1; }): Proof<InferProvable<PublicInputType>, InferProvable<PublicOutputType>>; fromJSON<S extends Subclass<typeof import("./proof.js").Proof>>(this: S, { maxProofsVerified, proof: proofString, publicInput: publicInputJson, publicOutput: publicOutputJson, }: JsonProof): Promise<Proof<InferProvable<S["publicInputType"]>, InferProvable<S["publicOutputType"]>>>; dummy<Input, OutPut>(publicInput: Input, publicOutput: OutPut, maxProofsVerified: 0 | 2 | 1, domainLog2?: number): Promise<Proof<Input, OutPut>>; readonly provable: { toFields: (value: Proof<any, any>) => import("../provable/field.js").Field[]; toAuxiliary: (value?: Proof<any, any> | undefined) => any[]; fromFields: (fields: import("../provable/field.js").Field[], aux: any[]) => Proof<any, any>; sizeInFields(): number; check: (value: Proof<any, any>) => void; toValue: (x: Proof<any, any>) => ProofValue<any, any>; fromValue: (x: Proof<any, any> | ProofValue<any, any>) => Proof<any, any>; toCanonical?: ((x: Proof<any, any>) => Proof<any, any>) | undefined; }; publicInputType: FlexibleProvable<any>; publicOutputType: FlexibleProvable<any>; tag: () => { name: string; }; publicFields(value: ProofBase<any, any>): { input: import("../provable/field.js").Field[]; output: import("../provable/field.js").Field[]; }; _proofFromBase64(proofString: string, maxProofsVerified: 0 | 2 | 1): unknown; _proofToBase64(proof: unknown, maxProofsVerified: 0 | 2 | 1): string; } & { provable: Provable<Proof<InferProvable<PublicInputType>, InferProvable<PublicOutputType>>, ProofValue<InferValue<PublicInputType>, InferValue<PublicOutputType>>>; }; } type ZkProgram<Config extends { publicInput?: ProvableType; publicOutput?: ProvableType; methods: { [I in string]: { privateInputs: Tuple<PrivateInput>; auxiliaryOutput?: ProvableType; }; }; }> = ReturnType<typeof ZkProgram<Config>>; /** * A class representing the type of Proof produced by the {@link ZkProgram} in which it is used. * * @example * ```ts * const ExampleProgram = ZkProgram({ * name: 'ExampleProgram', * publicOutput: Field, * methods: { * baseCase: { * privateInputs: [], * method: async () => { * return { publicOutput: Field(0) } * } * }, * add: { * privateInputs: [SelfProof, Field], * // `previous` is the type of proof produced by ExampleProgram * method: async (previous: SelfProof<undefined, Field>, f: Field) => { * previous.verify(); * return { publicOutput: previous.publicOutput.add(f) } * } * } * } * }); * ``` */ declare class SelfProof<PublicInput, PublicOutput> extends Proof<PublicInput, PublicOutput> { } declare function sortMethodArguments(programName: string, methodName: string, privateInputs: unknown[], auxiliaryType: Provable<any> | undefined, selfProof: Subclass<typeof Proof>): MethodInterface; type MethodInterface = { methodName: string; args: ProvableType<unknown>[]; returnType?: Provable<any>; auxiliaryType?: Provable<any>; }; declare function compileProgram({ publicInputType, publicOutputType, methodIntfs, methods, gates, proofs, proofSystemTag, cache, forceRecompile, overrideWrapDomain, numChunks, state, withRuntimeTables, lazyMode, }: { publicInputType: Provable<any>; publicOutputType: Provable<any>; methodIntfs: MethodInterface[]; methods: ((...args: any) => unknown)[]; gates: Gate[][]; proofs: ProofClass[][]; proofSystemTag: { name: string; }; cache: Cache; forceRecompile: boolean; overrideWrapDomain?: 0 | 1 | 2; numChunks?: number; state?: ReturnType<typeof createProgramState>; withRuntimeTables?: boolean; lazyMode?: boolean; }): Promise<{ verificationKey: { data: string; hash: import("../provable/field.js").Field; }; provers: Pickles.Prover[]; verify: (statement: Pickles.Statement<FieldConst>, proof: Pickles.Proof) => Promise<boolean>; tag: unknown; }>; declare function analyzeMethod(publicInputType: Provable<any>, methodIntf: MethodInterface, method: (...args: any) => unknown): Promise<MethodAnalysis>; declare function inCircuitVkHash(inCircuitVk: unknown): Field; declare function picklesRuleFromFunction(publicInputType: Provable<unknown>, publicOutputType: Provable<unknown>, func: (...args: unknown[]) => unknown, proofSystemTag: { name: string; }, { methodName, args, auxiliaryType }: MethodInterface, gates: Gate[], verifiedProofs: ProofClass[], state?: ReturnType<typeof createProgramState>, withRuntimeTables?: boolean): Pickles.Rule; declare function computeMaxProofsVerified(proofs: number[]): 0 | 2 | 1; declare function dummyBase64Proof(): Promise<string>; declare function Prover<ProverData>(): { run<Result>(witnesses: unknown[], proverData: ProverData, callback: () => Promise<Result>): Promise<Result>; getData(): ProverData; }; type Infer<T> = T extends Subclass<typeof ProofBase> ? InstanceType<T> : T extends ProvableType ? InferProvableType<T> : never; type TupleToInstances<T> = { [I in keyof T]: Infer<T[I]>; }; type TupleFrom<T> = { [I in keyof T]: From<T[I]>; }; type PrivateInput = ProvableType | Subclass<typeof ProofBase>; type MethodReturnType<PublicOutput, AuxiliaryOutput> = PublicOutput extends void ? AuxiliaryOutput extends undefined ? void : { auxiliaryOutput: AuxiliaryOutput; } : AuxiliaryOutput extends undefined ? { publicOutput: PublicOutput; } : { publicOutput: PublicOutput; auxiliaryOutput: AuxiliaryOutput; }; type Method<PublicInput, PublicOutput, MethodSignature extends { privateInputs: Tuple<PrivateInput>; auxiliaryOutput?: ProvableType; }> = PublicInput extends undefined ? { method(...args: TupleToInstances<MethodSignature['privateInputs']>): Promise<MethodReturnType<PublicOutput, InferProvableOrUndefined<Get<MethodSignature, 'auxiliaryOutput'>>>>; } : { method(publicInput: PublicInput, ...args: TupleToInstances<MethodSignature['privateInputs']>): Promise<MethodReturnType<PublicOutput, InferProvableOrUndefined<Get<MethodSignature, 'auxiliaryOutput'>>>>; }; type RegularProver<PublicInput, PublicInputType, PublicOutput, Args extends Tuple<PrivateInput>, AuxiliaryOutput> = (publicInput: From<PublicInputType>, ...args: TupleFrom<Args>) => Promise<{ proof: Proof<PublicInput, PublicOutput>; auxiliaryOutput: AuxiliaryOutput; }>; type Prover<PublicInput, PublicInputType, PublicOutput, Args extends Tuple<PrivateInput>, AuxiliaryOutput> = PublicInput extends undefined ? (...args: TupleFrom<Args>) => Promise<{ proof: Proof<PublicInput, PublicOutput>; auxiliaryOutput: AuxiliaryOutput; }> : (publicInput: From<PublicInputType>, ...args: TupleFrom<Args>) => Promise<{ proof: Proof<PublicInput, PublicOutput>; auxiliaryOutput: AuxiliaryOutput; }>; type ProvableOrUndefined<A> = A extends undefined ? typeof Undefined : ToProvable<A>; type ProvableOrVoid<A> = A extends undefined ? typeof Void : ToProvable<A>; type InferProvableOrUndefined<A> = A extends undefined ? undefined : A extends ProvableType ? InferProvable<A> : InferProvable<A> | undefined; type InferProvableOrVoid<A> = A extends undefined ? void : InferProvable<A>; /** * helper to get property type from an object, in place of `T[Key]` * * assume `T extends { Key?: Something }`. * if we use `Get<T, Key>` instead of `T[Key]`, we allow `T` to be inferred _without_ the `Key` key, * and thus retain the precise type of `T` during inference */ type Get<T, Key extends string> = T extends { [K in Key]: infer _Value; } ? _Value : undefined;