o1js
Version:
TypeScript framework for zk-SNARKs and zkApps
329 lines (328 loc) • 15.9 kB
TypeScript
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;