@@ -5,6 +5,7 @@ import { Tuple } from '../util/types.js';
55import { Proof } from './proof.js' ;
66import { mapObject , mapToObject , zip } from '../util/arrays.js' ;
77import { Undefined , Void } from './zkprogram.js' ;
8+ import { Bool } from '../provable/bool.js' ;
89
910export { Recursive } ;
1011
@@ -25,6 +26,7 @@ function Recursive<
2526 ...args : any
2627 ) => Promise < { publicOutput : InferProvable < PublicOutputType > } > ;
2728 } ;
29+ maxProofsVerified : ( ) => Promise < 0 | 1 | 2 > ;
2830 } & {
2931 [ Key in keyof PrivateInputs ] : ( ...args : any ) => Promise < {
3032 proof : Proof <
@@ -38,7 +40,13 @@ function Recursive<
3840 InferProvable < PublicInputType > ,
3941 InferProvable < PublicOutputType > ,
4042 PrivateInputs [ Key ]
41- > ;
43+ > & {
44+ if : ConditionalRecursiveProver <
45+ InferProvable < PublicInputType > ,
46+ InferProvable < PublicOutputType > ,
47+ PrivateInputs [ Key ]
48+ > ;
49+ } ;
4250} {
4351 type PublicInput = InferProvable < PublicInputType > ;
4452 type PublicOutput = InferProvable < PublicOutputType > ;
@@ -64,9 +72,15 @@ function Recursive<
6472
6573 let regularRecursiveProvers = mapToObject ( methodKeys , ( key ) => {
6674 return async function proveRecursively_ (
75+ conditionAndConfig : Bool | { condition : Bool ; domainLog2 ?: number } ,
6776 publicInput : PublicInput ,
6877 ...args : TupleToInstances < PrivateInputs [ MethodKey ] >
69- ) {
78+ ) : Promise < PublicOutput > {
79+ let condition =
80+ conditionAndConfig instanceof Bool
81+ ? conditionAndConfig
82+ : conditionAndConfig . condition ;
83+
7084 // create the base proof in a witness block
7185 let proof = await Provable . witnessAsync ( SelfProof , async ( ) => {
7286 // move method args to constants
@@ -78,6 +92,20 @@ function Recursive<
7892 Provable . toConstant ( type , arg )
7993 ) ;
8094
95+ if ( ! condition . toBoolean ( ) ) {
96+ let publicOutput : PublicOutput =
97+ ProvableType . synthesize ( publicOutputType ) ;
98+ let maxProofsVerified = await zkprogram . maxProofsVerified ( ) ;
99+ return SelfProof . dummy (
100+ publicInput ,
101+ publicOutput ,
102+ maxProofsVerified ,
103+ conditionAndConfig instanceof Bool
104+ ? undefined
105+ : conditionAndConfig . domainLog2
106+ ) ;
107+ }
108+
81109 let prover = zkprogram [ key ] ;
82110
83111 if ( hasPublicInput ) {
@@ -96,32 +124,48 @@ function Recursive<
96124
97125 // declare and verify the proof, and return its public output
98126 proof . declare ( ) ;
99- proof . verify ( ) ;
127+ proof . verifyIf ( condition ) ;
100128 return proof . publicOutput ;
101129 } ;
102130 } ) ;
103131
104- type RecursiveProver_ < K extends MethodKey > = RecursiveProver <
105- PublicInput ,
106- PublicOutput ,
107- PrivateInputs [ K ]
108- > ;
109- type RecursiveProvers = {
110- [ K in MethodKey ] : RecursiveProver_ < K > ;
111- } ;
112- let proveRecursively : RecursiveProvers = mapToObject (
113- methodKeys ,
114- ( key : MethodKey ) => {
132+ return mapObject (
133+ regularRecursiveProvers ,
134+ (
135+ prover
136+ ) : RecursiveProver < PublicInput , PublicOutput , PrivateInputs [ MethodKey ] > & {
137+ if : ConditionalRecursiveProver <
138+ PublicInput ,
139+ PublicOutput ,
140+ PrivateInputs [ MethodKey ]
141+ > ;
142+ } => {
115143 if ( ! hasPublicInput ) {
116- return ( ( ...args : any ) =>
117- regularRecursiveProvers [ key ] ( undefined as any , ...args ) ) as any ;
144+ return Object . assign (
145+ ( ( ...args : any ) =>
146+ prover ( new Bool ( true ) , undefined as any , ...args ) ) as any ,
147+ {
148+ if : (
149+ condition : Bool | { condition : Bool ; domainLog2 ?: number } ,
150+ ...args : any
151+ ) => prover ( condition , undefined as any , ...args ) ,
152+ }
153+ ) ;
118154 } else {
119- return regularRecursiveProvers [ key ] as any ;
155+ return Object . assign (
156+ ( ( pi : PublicInput , ...args : any ) =>
157+ prover ( new Bool ( true ) , pi , ...args ) ) as any ,
158+ {
159+ if : (
160+ condition : Bool | { condition : Bool ; domainLog2 ?: number } ,
161+ pi : PublicInput ,
162+ ...args : any
163+ ) => prover ( condition , pi , ...args ) ,
164+ }
165+ ) ;
120166 }
121167 }
122168 ) ;
123-
124- return proveRecursively ;
125169}
126170
127171type RecursiveProver <
@@ -135,6 +179,21 @@ type RecursiveProver<
135179 ...args : TupleToInstances < Args >
136180 ) => Promise < PublicOutput > ;
137181
182+ type ConditionalRecursiveProver <
183+ PublicInput ,
184+ PublicOutput ,
185+ Args extends Tuple < ProvableType >
186+ > = PublicInput extends undefined
187+ ? (
188+ condition : Bool | { condition : Bool ; domainLog2 ?: number } ,
189+ ...args : TupleToInstances < Args >
190+ ) => Promise < PublicOutput >
191+ : (
192+ condition : Bool | { condition : Bool ; domainLog2 ?: number } ,
193+ publicInput : PublicInput ,
194+ ...args : TupleToInstances < Args >
195+ ) => Promise < PublicOutput > ;
196+
138197type TupleToInstances < T > = {
139198 [ I in keyof T ] : InferProvable < T [ I ] > ;
140199} ;
0 commit comments