From c0b9a6fff2a40f4f7204281f8f55f3b272fad0f7 Mon Sep 17 00:00:00 2001 From: Florian Kluge Date: Thu, 22 Feb 2024 11:24:59 +0100 Subject: [PATCH 1/3] make proof provable --- src/examples/zkprogram/witness-proof.ts | 56 +++++++++++++++++++++++++ src/lib/proof-system.ts | 13 +++++- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/examples/zkprogram/witness-proof.ts diff --git a/src/examples/zkprogram/witness-proof.ts b/src/examples/zkprogram/witness-proof.ts new file mode 100644 index 0000000000..320cf140ed --- /dev/null +++ b/src/examples/zkprogram/witness-proof.ts @@ -0,0 +1,56 @@ +import { + SelfProof, + Field, + ZkProgram, + verify, + isReady, + Proof, + JsonProof, + Provable, + Empty, +} from 'o1js'; + +await isReady; + +let MyProgram = ZkProgram({ + name: 'example-with-output', + publicOutput: Field, + + methods: { + baseCase: { + privateInputs: [], + method() { + return Field(0); + }, + }, + }, +}); + +class ProgramProof extends ZkProgram.Proof(MyProgram) {} + +await MyProgram.compile(); + +let proof = await MyProgram.baseCase(); + +let MyProgram2 = ZkProgram({ + name: 'example-with-output2', + + methods: { + baseCase: { + privateInputs: [], + method() { + let p = Provable.witness(ProgramProof.provable, () => { + proof.publicOutput = Field(5); + + return proof; + }); + p.verify(); + // should say 0 and fail verification + Provable.log(proof.publicOutput); + }, + }, + }, +}); + +await MyProgram2.compile(); +await MyProgram2.baseCase(); diff --git a/src/lib/proof-system.ts b/src/lib/proof-system.ts index 4682e42a97..a1a3f5f106 100644 --- a/src/lib/proof-system.ts +++ b/src/lib/proof-system.ts @@ -19,6 +19,7 @@ import { InferProvable, ProvablePureExtended, Struct, + Unconstrained, provable, provablePure, toConstant, @@ -37,6 +38,7 @@ import { parseHeader, } from './proof-system/prover-keys.js'; import { setSrsCache, unsetSrsCache } from '../bindings/crypto/bindings/srs.js'; +import { provableFromClass } from '../bindings/lib/provable-snarky.js'; // public API export { @@ -90,7 +92,7 @@ class Proof { }; publicInput: Input; publicOutput: Output; - proof: Pickles.Proof; + proof: Unconstrained; maxProofsVerified: 0 | 1 | 2; shouldVerify = Bool(false); @@ -146,7 +148,7 @@ class Proof { }) { this.publicInput = publicInput; this.publicOutput = publicOutput; - this.proof = proof; // TODO optionally convert from string? + this.proof = Unconstrained.from(proof); // TODO optionally convert from string? this.maxProofsVerified = maxProofsVerified; } @@ -940,6 +942,13 @@ ZkProgram.Proof = function < static publicInputType = program.publicInputType; static publicOutputType = program.publicOutputType; static tag = () => program; + static get provable() { + return provableFromClass(ZkProgramProof, { + publicInput: program.publicInputType, + publicOutput: program.publicOutputType, + proof: Unconstrained.provable, + }); + } }; }; ExperimentalZkProgram.Proof = ZkProgram.Proof; From df6173e1908c7058b7a6d2bc5563b71834dbfad1 Mon Sep 17 00:00:00 2001 From: Florian Kluge Date: Sat, 24 Feb 2024 14:08:12 +0100 Subject: [PATCH 2/3] playing around --- src/examples/zkprogram/witness-proof.ts | 4 +- src/lib/gadgets/ecdsa.unit-test.ts | 2 +- src/lib/proof-system.ts | 129 ++++++++++++++++++++++-- src/lib/proof-system.unit-test.ts | 1 + src/lib/provable-context.ts | 25 ++++- src/lib/zkapp.ts | 9 +- 6 files changed, 154 insertions(+), 16 deletions(-) diff --git a/src/examples/zkprogram/witness-proof.ts b/src/examples/zkprogram/witness-proof.ts index 320cf140ed..ceb29c9a07 100644 --- a/src/examples/zkprogram/witness-proof.ts +++ b/src/examples/zkprogram/witness-proof.ts @@ -44,6 +44,7 @@ let MyProgram2 = ZkProgram({ return proof; }); + ProgramProof.declare(p); p.verify(); // should say 0 and fail verification Provable.log(proof.publicOutput); @@ -51,6 +52,7 @@ let MyProgram2 = ZkProgram({ }, }, }); - +console.log('GOING INTO SECOND ZKPROGRAM'); await MyProgram2.compile(); +console.log('PROVING'); await MyProgram2.baseCase(); diff --git a/src/lib/gadgets/ecdsa.unit-test.ts b/src/lib/gadgets/ecdsa.unit-test.ts index e008a011ef..8cb4124a8e 100644 --- a/src/lib/gadgets/ecdsa.unit-test.ts +++ b/src/lib/gadgets/ecdsa.unit-test.ts @@ -175,7 +175,7 @@ Provable.runAndCheck(program.rawMethods.ecdsa); console.timeEnd('ecdsa verify (witness gen / check)'); console.time('ecdsa verify (build constraint system)'); -let cs = program.analyzeMethods().ecdsa; +let cs = program.analyzeMethods().ecdsa.cs; console.timeEnd('ecdsa verify (build constraint system)'); console.log(cs.summary()); diff --git a/src/lib/proof-system.ts b/src/lib/proof-system.ts index a1a3f5f106..99ab015f3e 100644 --- a/src/lib/proof-system.ts +++ b/src/lib/proof-system.ts @@ -26,7 +26,12 @@ import { } from './circuit-value.js'; import { Provable } from './provable.js'; import { assert, prettifyStacktracePromise } from './errors.js'; -import { snarkContext } from './provable-context.js'; +import { + CircuitContext, + circuitContext, + inAnalyze, + snarkContext, +} from './provable-context.js'; import { hashConstant } from './hash.js'; import { MlArray, MlBool, MlResult, MlPair } from './ml/base.js'; import { MlFieldArray, MlFieldConstArray } from './ml/fields.js'; @@ -56,6 +61,8 @@ export { // internal API export { + isProof, + Subclass, CompiledTag, sortMethodArguments, getPreviousProofsForProver, @@ -329,7 +336,7 @@ function ZkProgram< return Object.fromEntries( methodIntfs.map((methodEntry, i) => [ methodEntry.methodName, - analyzeMethod(publicInputType, methodEntry, methodFunctions[i]), + analyzeMethod(publicInputType, methodEntry, methodFunctions[i]).cs, ]) ) as any as { [I in keyof Types]: ReturnType; @@ -353,7 +360,8 @@ function ZkProgram< let methodsMeta = methodIntfs.map((methodEntry, i) => analyzeMethod(publicInputType, methodEntry, methodFunctions[i]) ); - let gates = methodsMeta.map((m) => m.gates); + let witnessedProofs = methodsMeta.map((m) => m.proofData); + let gates = methodsMeta.map((m) => m.cs.gates); let { provers, verify, verificationKey } = await compileProgram({ publicInputType, publicOutputType, @@ -364,6 +372,7 @@ function ZkProgram< cache, forceRecompile, overrideWrapDomain: config.overrideWrapDomain, + witnessedProofs, }); compileOutput = { provers, verify }; return { verificationKey }; @@ -385,8 +394,11 @@ function ZkProgram< ); } let publicInputFields = toFieldConsts(publicInputType, publicInput); + + let ctx = circuitContext.get()!; + let previousProofs = MlArray.to( - getPreviousProofsForProver(args, methodIntfs[i]) + getPreviousProofsForProver(args, methodIntfs[i], ctx.proofs) ); let id = snarkContext.enter({ witnesses: args, inProver: true }); @@ -440,8 +452,9 @@ function ZkProgram< } function digest() { - let methodData = methodIntfs.map((methodEntry, i) => - analyzeMethod(publicInputType, methodEntry, methodFunctions[i]) + let methodData = methodIntfs.map( + (methodEntry, i) => + analyzeMethod(publicInputType, methodEntry, methodFunctions[i]).cs ); let hash = hashConstant( Object.values(methodData).map((d) => Field(BigInt('0x' + d.digest))) @@ -565,7 +578,12 @@ function isProof(type: unknown): type is typeof Proof { function getPreviousProofsForProver( methodArgs: any[], - { allArgs }: MethodInterface + { allArgs }: MethodInterface, + witnessedProofs: { + proof: Subclass; + input: ProvablePure; + output: ProvablePure; + }[] ) { let previousProofs: Pickles.Proof[] = []; for (let i = 0; i < allArgs.length; i++) { @@ -574,6 +592,11 @@ function getPreviousProofsForProver( previousProofs[arg.index] = (methodArgs[i] as Proof).proof; } } + + for (let i = 0; i < witnessedProofs.length; i++) { + previousProofs.push(witnessedProofs[i].proof); + } + return previousProofs; } @@ -599,6 +622,7 @@ async function compileProgram({ proofSystemTag, cache, forceRecompile, + witnessedProofs, overrideWrapDomain, }: { publicInputType: ProvablePure; @@ -609,6 +633,11 @@ async function compileProgram({ proofSystemTag: { name: string }; cache: Cache; forceRecompile: boolean; + witnessedProofs: { + proof: Subclass; + input: ProvablePure; + output: ProvablePure; + }[][]; overrideWrapDomain?: 0 | 1 | 2; }) { let rules = methodIntfs.map((methodEntry, i) => @@ -618,9 +647,11 @@ async function compileProgram({ methods[i], proofSystemTag, methodEntry, - gates[i] + gates[i], + witnessedProofs[i] ) ); + let maxProofs = getMaxProofsVerified(methodIntfs); overrideWrapDomain ??= maxProofsToWrapDomain[maxProofs]; @@ -705,13 +736,26 @@ function analyzeMethod( methodIntf: MethodInterface, method: (...args: any) => T ) { - return Provable.constraintSystem(() => { + console.log('ANALYZING METHOD, ENTERING CONTEXT'); + //console.log(circuitContext.get()); + let { context } = CircuitContext.enter(methodIntf.methodName); + let id = circuitContext.enter(context); + console.log('ENTERED CONTEXT ID ', id); + console.log(circuitContext.get()); + let cs = Provable.constraintSystem(() => { let args = synthesizeMethodArguments(methodIntf, true); + let publicInput = emptyWitness(publicInputType); if (publicInputType === Undefined || publicInputType === Void) return method(...args); return method(publicInput, ...args); }); + // TODO moose + console.log('LEAVING CONTEXT; BUT PRITING'); + console.log(context); + let proofData = context.proofs; + circuitContext.leave(id); + return { cs, proofData }; } function picklesRuleFromFunction( @@ -720,7 +764,12 @@ function picklesRuleFromFunction( func: (...args: unknown[]) => any, proofSystemTag: { name: string }, { methodName, witnessArgs, proofArgs, allArgs }: MethodInterface, - gates: Gate[] + gates: Gate[], + witnessedProofs: { + proof: Subclass; + input: ProvablePure; + output: ProvablePure; + }[] ): Pickles.Rule { function main(publicInput: MlFieldArray): ReturnType { let { witnesses: argsWithoutPublicInput, inProver } = snarkContext.get(); @@ -731,12 +780,16 @@ function picklesRuleFromFunction( for (let i = 0; i < allArgs.length; i++) { let arg = allArgs[i]; if (arg.type === 'witness') { + console.log('witness', arg); let type = witnessArgs[arg.index]; finalArgs[i] = Provable.witness(type, () => { return argsWithoutPublicInput?.[i] ?? emptyValue(type); }); } else if (arg.type === 'proof') { + console.log('proof', arg); + let Proof = proofArgs[arg.index]; + Provable.log(Proof); let type = getStatementType(Proof); let proof_ = (argsWithoutPublicInput?.[i] as Proof) ?? { proof: undefined, @@ -746,6 +799,8 @@ function picklesRuleFromFunction( let { proof, publicInput, publicOutput } = proof_; publicInput = Provable.witness(type.input, () => publicInput); publicOutput = Provable.witness(type.output, () => publicOutput); + Provable.log(publicInput); + Provable.log(publicOutput); let proofInstance = new Proof({ publicInput, publicOutput, proof }); finalArgs[i] = proofInstance; proofs.push(proofInstance); @@ -754,6 +809,40 @@ function picklesRuleFromFunction( previousStatements.push(MlPair(input, output)); } } + + for (let i = 0; i < witnessedProofs.length; i++) { + console.log('WE ARE WITNESSING A PROOF'); + + let ProofData = witnessedProofs[i]; + let Proof = ProofData.proof; + let type = getStatementType(Proof); + Provable.log(Proof); + + let { input: input_, output: output_ } = ProofData; + Provable.log(input_); + console.log('---------'); + let proof_ = { + proof: undefined, + publicInput: emptyValue(type.input), + publicOutput: emptyValue(type.output), + }; + let { proof, publicInput, publicOutput } = proof_; + Provable.log(publicInput); + Provable.log(publicOutput); + publicInput = Provable.witness(type.input, () => publicInput); + publicOutput = Provable.witness(type.output, () => publicOutput); + let proofInstance = new Proof({ + publicInput, + publicOutput, + proof, + }); + //finalArgs[i] = proofInstance; + proofs.push(proofInstance); + let input = toFieldVars(type.input, publicInput); + let output = toFieldVars(type.output, publicOutput); + previousStatements.push(MlPair(input, output)); + } + let result: any; if (publicInputType === Undefined || publicInputType === Void) { result = func(...finalArgs); @@ -764,6 +853,7 @@ function picklesRuleFromFunction( // if the public output is empty, we don't evaluate `toFields(result)` to allow the function to return something else in that case let hasPublicOutput = publicOutputType.sizeInFields() !== 0; let publicOutput = hasPublicOutput ? publicOutputType.toFields(result) : []; + console.log('------ COMPILE DONE ------'); return { publicOutput: MlFieldArray.to(publicOutput), previousStatements: MlArray.to(previousStatements), @@ -942,6 +1032,18 @@ ZkProgram.Proof = function < static publicInputType = program.publicInputType; static publicOutputType = program.publicOutputType; static tag = () => program; + + static declare(proof: Proof) { + if (inAnalyze()) { + let ctx = circuitContext.get()!; + ctx.proofs.push({ + proof: this, + input: proof.publicInput, + output: proof.publicOutput, + }); + } + } + static get provable() { return provableFromClass(ZkProgramProof, { publicInput: program.publicInputType, @@ -949,6 +1051,13 @@ ZkProgram.Proof = function < proof: Unconstrained.provable, }); } + static witness( + cb: () => Proof + ): Proof { + let p = Provable.witness(this.provable, cb); + + return cb(); + } }; }; ExperimentalZkProgram.Proof = ZkProgram.Proof; diff --git a/src/lib/proof-system.unit-test.ts b/src/lib/proof-system.unit-test.ts index d9572e54d4..35f471b777 100644 --- a/src/lib/proof-system.unit-test.ts +++ b/src/lib/proof-system.unit-test.ts @@ -61,6 +61,7 @@ it('pickles rule creation', async () => { main as AnyFunction, { name: 'mock' }, methodIntf, + [], [] ); diff --git a/src/lib/provable-context.ts b/src/lib/provable-context.ts index 9779fa2ab1..254c449694 100644 --- a/src/lib/provable-context.ts +++ b/src/lib/provable-context.ts @@ -1,11 +1,15 @@ import { Context } from './global-context.js'; -import { Gate, GateType, JsonGate, Snarky } from '../snarky.js'; +import { Gate, GateType, JsonGate, ProvablePure, Snarky } from '../snarky.js'; import { parseHexString32 } from '../bindings/crypto/bigint-helpers.js'; import { prettifyStacktrace } from './errors.js'; import { Fp } from '../bindings/crypto/finite-field.js'; +import { FlexibleProvablePure } from './circuit-value.js'; +import { Proof, Subclass } from './proof-system.js'; // internal API export { + circuitContext, + CircuitContext, snarkContext, SnarkContext, asProver, @@ -23,6 +27,25 @@ export { // global circuit-related context +// context that observes and collects meta data about circuits and their methods +type CircuitContext = { + methodName: string; + proofs: { + proof: Subclass; + input: ProvablePure; + output: ProvablePure; + }[]; +}; +let circuitContext = Context.create({}); + +const CircuitContext = { + enter(methodName: string) { + let context: CircuitContext = { methodName, proofs: [] }; + let id = circuitContext.enter(context); + return { id, context }; + }, +}; + type SnarkContext = { witnesses?: unknown[]; proverData?: any; diff --git a/src/lib/zkapp.ts b/src/lib/zkapp.ts index de5386fa21..421bf81389 100644 --- a/src/lib/zkapp.ts +++ b/src/lib/zkapp.ts @@ -285,7 +285,8 @@ function wrapMethod( // proofs actually don't have to be cloned previousProofs: getPreviousProofsForProver( actualArgs, - methodIntf + methodIntf, + [] ), ZkappClass, memoized, @@ -390,7 +391,8 @@ function wrapMethod( args: constantArgs, previousProofs: getPreviousProofsForProver( constantArgs, - methodIntf + methodIntf, + [] ), ZkappClass, memoized, @@ -607,6 +609,7 @@ class SmartContract extends SmartContractBase { proofSystemTag: this, cache, forceRecompile, + witnessedProofs: [], }); this._provers = provers; this._verificationKey = verificationKey; @@ -1111,7 +1114,7 @@ super.init(); accountUpdate = instance.#executionState!.accountUpdate; return result; } - ); + ).cs; methodMetadata[methodIntf.methodName] = { actions: accountUpdate!.body.actions.data.length, rows, From 054036722c9591bc3b1239d75de4c9dd8ca11d22 Mon Sep 17 00:00:00 2001 From: Florian Kluge Date: Tue, 27 Feb 2024 12:56:28 +0100 Subject: [PATCH 3/3] close --- src/examples/zkprogram/witness-proof-2.ts | 54 +++++++++++++ src/examples/zkprogram/witness-proof.ts | 2 +- src/lib/proof-system.ts | 96 +++++++++++++---------- src/lib/provable-context.ts | 16 ++-- 4 files changed, 122 insertions(+), 46 deletions(-) create mode 100644 src/examples/zkprogram/witness-proof-2.ts diff --git a/src/examples/zkprogram/witness-proof-2.ts b/src/examples/zkprogram/witness-proof-2.ts new file mode 100644 index 0000000000..0991bcd375 --- /dev/null +++ b/src/examples/zkprogram/witness-proof-2.ts @@ -0,0 +1,54 @@ +import { + SelfProof, + Field, + ZkProgram, + verify, + isReady, + Proof, + JsonProof, + Provable, + Empty, +} from 'o1js'; + +await isReady; + +let MyProgram = ZkProgram({ + name: 'example-with-output', + publicOutput: Field, + + methods: { + baseCase: { + privateInputs: [], + method() { + return Field(0); + }, + }, + }, +}); + +class ProgramProof extends ZkProgram.Proof(MyProgram) {} + +await MyProgram.compile(); + +let proof = await MyProgram.baseCase(); + +let MyProgram2 = ZkProgram({ + name: 'example-with-output2', + + methods: { + baseCase: { + privateInputs: [ProgramProof], + method(p: ProgramProof) { + p.verify(); + + // should say 0 and fail verification + Provable.log(proof.publicOutput); + }, + }, + }, +}); +console.log('GOING INTO SECOND ZKPROGRAM'); +await MyProgram2.compile(); +console.log('PROVING'); + +await MyProgram2.baseCase(proof); diff --git a/src/examples/zkprogram/witness-proof.ts b/src/examples/zkprogram/witness-proof.ts index ceb29c9a07..b36fc89dee 100644 --- a/src/examples/zkprogram/witness-proof.ts +++ b/src/examples/zkprogram/witness-proof.ts @@ -41,9 +41,9 @@ let MyProgram2 = ZkProgram({ method() { let p = Provable.witness(ProgramProof.provable, () => { proof.publicOutput = Field(5); - return proof; }); + ProgramProof.declare(p); p.verify(); // should say 0 and fail verification diff --git a/src/lib/proof-system.ts b/src/lib/proof-system.ts index 99ab015f3e..d6ef0f33ce 100644 --- a/src/lib/proof-system.ts +++ b/src/lib/proof-system.ts @@ -17,6 +17,7 @@ import { FlexibleProvable, FlexibleProvablePure, InferProvable, + ProvableExtended, ProvablePureExtended, Struct, Unconstrained, @@ -28,8 +29,11 @@ import { Provable } from './provable.js'; import { assert, prettifyStacktracePromise } from './errors.js'; import { CircuitContext, + ProofContext, circuitContext, inAnalyze, + inCompile, + inProver, snarkContext, } from './provable-context.js'; import { hashConstant } from './hash.js'; @@ -115,7 +119,7 @@ class Proof { publicInput: type.input.toFields(this.publicInput).map(String), publicOutput: type.output.toFields(this.publicOutput).map(String), maxProofsVerified: this.maxProofsVerified, - proof: Pickles.proofToBase64([this.maxProofsVerified, this.proof]), + proof: Pickles.proofToBase64([this.maxProofsVerified, this.proof.get()]), }; } static fromJSON>( @@ -137,7 +141,7 @@ class Proof { return new this({ publicInput, publicOutput, - proof, + proof: Unconstrained.from(proof), maxProofsVerified, }) as any; } @@ -353,6 +357,8 @@ function ZkProgram< } | undefined; + let witnessedProofs: ProofContext[][] = []; + async function compile({ cache = Cache.FileSystemDefault, forceRecompile = false, @@ -360,7 +366,8 @@ function ZkProgram< let methodsMeta = methodIntfs.map((methodEntry, i) => analyzeMethod(publicInputType, methodEntry, methodFunctions[i]) ); - let witnessedProofs = methodsMeta.map((m) => m.proofData); + witnessedProofs = methodsMeta.map((m) => m.proofData); + console.log('Witnessed proofs in compile', witnessedProofs); let gates = methodsMeta.map((m) => m.cs.gates); let { provers, verify, verificationKey } = await compileProgram({ publicInputType, @@ -395,10 +402,13 @@ function ZkProgram< } let publicInputFields = toFieldConsts(publicInputType, publicInput); - let ctx = circuitContext.get()!; + console.log( + 'CONTEXT', + witnessedProofs[0].map((p) => console.log(p)) + ); let previousProofs = MlArray.to( - getPreviousProofsForProver(args, methodIntfs[i], ctx.proofs) + getPreviousProofsForProver(args, methodIntfs[i], witnessedProofs[i]) ); let id = snarkContext.enter({ witnesses: args, inProver: true }); @@ -579,12 +589,10 @@ function isProof(type: unknown): type is typeof Proof { function getPreviousProofsForProver( methodArgs: any[], { allArgs }: MethodInterface, - witnessedProofs: { - proof: Subclass; - input: ProvablePure; - output: ProvablePure; - }[] + witnessedProofs: ProofContext[] ) { + console.log('ARGS', allArgs); + console.log('PREVIOUS POROOF', methodArgs); let previousProofs: Pickles.Proof[] = []; for (let i = 0; i < allArgs.length; i++) { let arg = allArgs[i]; @@ -592,9 +600,11 @@ function getPreviousProofsForProver( previousProofs[arg.index] = (methodArgs[i] as Proof).proof; } } + console.log('witnessedProofs POROOF', witnessedProofs[0]); for (let i = 0; i < witnessedProofs.length; i++) { - previousProofs.push(witnessedProofs[i].proof); + console.log('Unconstrained proof', witnessedProofs[i].proof); + previousProofs.push(witnessedProofs[i].proof as Unconstrained); } return previousProofs; @@ -633,11 +643,7 @@ async function compileProgram({ proofSystemTag: { name: string }; cache: Cache; forceRecompile: boolean; - witnessedProofs: { - proof: Subclass; - input: ProvablePure; - output: ProvablePure; - }[][]; + witnessedProofs: ProofContext[][]; overrideWrapDomain?: 0 | 1 | 2; }) { let rules = methodIntfs.map((methodEntry, i) => @@ -737,11 +743,9 @@ function analyzeMethod( method: (...args: any) => T ) { console.log('ANALYZING METHOD, ENTERING CONTEXT'); - //console.log(circuitContext.get()); let { context } = CircuitContext.enter(methodIntf.methodName); let id = circuitContext.enter(context); - console.log('ENTERED CONTEXT ID ', id); - console.log(circuitContext.get()); + let cs = Provable.constraintSystem(() => { let args = synthesizeMethodArguments(methodIntf, true); @@ -751,8 +755,8 @@ function analyzeMethod( return method(publicInput, ...args); }); // TODO moose - console.log('LEAVING CONTEXT; BUT PRITING'); - console.log(context); + console.log(context.proofs); + console.log(' analyzed methods, dopne'); let proofData = context.proofs; circuitContext.leave(id); return { cs, proofData }; @@ -765,11 +769,7 @@ function picklesRuleFromFunction( proofSystemTag: { name: string }, { methodName, witnessArgs, proofArgs, allArgs }: MethodInterface, gates: Gate[], - witnessedProofs: { - proof: Subclass; - input: ProvablePure; - output: ProvablePure; - }[] + witnessedProofs: ProofContext[] ): Pickles.Rule { function main(publicInput: MlFieldArray): ReturnType { let { witnesses: argsWithoutPublicInput, inProver } = snarkContext.get(); @@ -813,12 +813,13 @@ function picklesRuleFromFunction( for (let i = 0; i < witnessedProofs.length; i++) { console.log('WE ARE WITNESSING A PROOF'); - let ProofData = witnessedProofs[i]; - let Proof = ProofData.proof; - let type = getStatementType(Proof); + let proofContext = witnessedProofs[i]; + console.log('proofContext', proofContext.proof); + let ProofClass = proofContext.proofClass; + let type = getStatementType(proofContext.proofClass); Provable.log(Proof); - let { input: input_, output: output_ } = ProofData; + let { publicInput: input_, publicOutput: output_ } = proofContext; Provable.log(input_); console.log('---------'); let proof_ = { @@ -831,11 +832,12 @@ function picklesRuleFromFunction( Provable.log(publicOutput); publicInput = Provable.witness(type.input, () => publicInput); publicOutput = Provable.witness(type.output, () => publicOutput); - let proofInstance = new Proof({ + let proofInstance = new ProofClass({ publicInput, publicOutput, proof, }); + proofInstance.shouldVerify = Bool(true); //finalArgs[i] = proofInstance; proofs.push(proofInstance); let input = toFieldVars(type.input, publicInput); @@ -1034,22 +1036,36 @@ ZkProgram.Proof = function < static tag = () => program; static declare(proof: Proof) { - if (inAnalyze()) { - let ctx = circuitContext.get()!; - ctx.proofs.push({ - proof: this, - input: proof.publicInput, - output: proof.publicOutput, - }); - } + console.log('inProver', inProver()); + + let ctx = circuitContext.get()!; + + console.log('declaring', { + proof: proof.proof, + publicInput: proof.publicInput, + publicOutput: proof.publicOutput, + maxProofsVerified: proof.maxProofsVerified, + proofClass: this, + shouldVerify: proof.shouldVerify, + }); + ctx.proofs.push({ + proof: proof.proof, + publicInput: proof.publicInput, + publicOutput: proof.publicOutput, + maxProofsVerified: proof.maxProofsVerified, + proofClass: this, + shouldVerify: proof.shouldVerify, + }); } static get provable() { + // ^? + return provableFromClass(ZkProgramProof, { publicInput: program.publicInputType, publicOutput: program.publicOutputType, proof: Unconstrained.provable, - }); + }) satisfies ProvableExtended; } static witness( cb: () => Proof diff --git a/src/lib/provable-context.ts b/src/lib/provable-context.ts index 254c449694..ec5c1a660a 100644 --- a/src/lib/provable-context.ts +++ b/src/lib/provable-context.ts @@ -5,9 +5,11 @@ import { prettifyStacktrace } from './errors.js'; import { Fp } from '../bindings/crypto/finite-field.js'; import { FlexibleProvablePure } from './circuit-value.js'; import { Proof, Subclass } from './proof-system.js'; +import { Bool } from './bool.js'; // internal API export { + ProofContext, circuitContext, CircuitContext, snarkContext, @@ -27,14 +29,18 @@ export { // global circuit-related context +type ProofContext = { + proofClass: Subclass; + publicInput: ProvablePure; + publicOutput: ProvablePure; + proof: unknown; + shouldVerify: Bool; + maxProofsVerified: number; +}; // context that observes and collects meta data about circuits and their methods type CircuitContext = { methodName: string; - proofs: { - proof: Subclass; - input: ProvablePure; - output: ProvablePure; - }[]; + proofs: ProofContext[]; }; let circuitContext = Context.create({});