Skip to content

Commit 3a00f3a

Browse files
authored
Merge pull request #1962 from rpanic/rpanic/fix/zkprogram-typing
Fix correctness issue in ZkProgram typing
2 parents dea2a1f + c5af950 commit 3a00f3a

File tree

2 files changed

+44
-44
lines changed

2 files changed

+44
-44
lines changed

src/lib/proof-system/zkprogram.ts

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,35 @@ let SideloadedTag = {
201201
},
202202
};
203203

204+
type ConfigBaseType = {
205+
publicInput?: ProvableType;
206+
publicOutput?: ProvableType;
207+
methods: {
208+
[I in string]: {
209+
privateInputs: Tuple<PrivateInput>;
210+
auxiliaryOutput?: ProvableType;
211+
};
212+
};
213+
};
214+
215+
type InferMethodSignatures<Config extends ConfigBaseType> = Config['methods'];
216+
type InferPrivateInput<Config extends ConfigBaseType> = {
217+
[I in keyof Config['methods']]: Config['methods'][I]['privateInputs'];
218+
};
219+
type InferAuxiliaryOutputs<Config extends ConfigBaseType> = {
220+
[I in keyof InferMethodSignatures<Config>]: Get<
221+
InferMethodSignatures<Config>[I],
222+
'auxiliaryOutput'
223+
>;
224+
};
225+
type InferMethodType<Config extends ConfigBaseType> = {
226+
[I in keyof Config['methods']]: Method<
227+
InferProvableOrUndefined<Get<Config, 'publicInput'>>,
228+
InferProvableOrVoid<Get<Config, 'publicOutput'>>,
229+
Config['methods'][I]
230+
>;
231+
};
232+
204233
/**
205234
* Wraps config + provable code into a program capable of producing {@link Proof}s.
206235
*
@@ -229,40 +258,13 @@ let SideloadedTag = {
229258
* @returns an object that can be used to compile, prove, and verify the program.
230259
*/
231260
function ZkProgram<
232-
Config extends {
233-
publicInput?: ProvableType;
234-
publicOutput?: ProvableType;
235-
methods: {
236-
[I in string]: {
237-
privateInputs: Tuple<PrivateInput>;
238-
auxiliaryOutput?: ProvableType;
239-
};
240-
};
241-
},
242-
Methods extends {
243-
[I in keyof Config['methods']]: Method<
244-
InferProvableOrUndefined<Get<Config, 'publicInput'>>,
245-
InferProvableOrVoid<Get<Config, 'publicOutput'>>,
246-
Config['methods'][I]
247-
>;
248-
},
249-
// derived types for convenience
250-
MethodSignatures extends Config['methods'] = Config['methods'],
251-
PrivateInputs extends {
252-
[I in keyof Config['methods']]: Config['methods'][I]['privateInputs'];
253-
} = {
254-
[I in keyof Config['methods']]: Config['methods'][I]['privateInputs'];
255-
},
256-
AuxiliaryOutputs extends {
257-
[I in keyof MethodSignatures]: Get<MethodSignatures[I], 'auxiliaryOutput'>;
258-
} = {
259-
[I in keyof MethodSignatures]: Get<MethodSignatures[I], 'auxiliaryOutput'>;
260-
}
261+
Config extends ConfigBaseType,
262+
_ extends unknown = unknown // weird hack that makes methods infer correctly when their inputs are not annotated
261263
>(
262264
config: Config & {
263265
name: string;
264266
methods: {
265-
[I in keyof Config['methods']]: Methods[I];
267+
[I in keyof Config['methods']]: InferMethodType<Config>[I];
266268
};
267269
overrideWrapDomain?: 0 | 1 | 2;
268270
}
@@ -292,10 +294,10 @@ function ZkProgram<
292294

293295
publicInputType: ProvableOrUndefined<Get<Config, 'publicInput'>>;
294296
publicOutputType: ProvableOrVoid<Get<Config, 'publicOutput'>>;
295-
privateInputTypes: PrivateInputs;
296-
auxiliaryOutputTypes: AuxiliaryOutputs;
297+
privateInputTypes: InferPrivateInput<Config>;
298+
auxiliaryOutputTypes: InferAuxiliaryOutputs<Config>;
297299
rawMethods: {
298-
[I in keyof Config['methods']]: Methods[I]['method'];
300+
[I in keyof Config['methods']]: InferMethodType<Config>[I]['method'];
299301
};
300302

301303
Proof: typeof Proof<
@@ -309,10 +311,15 @@ function ZkProgram<
309311
[I in keyof Config['methods']]: Prover<
310312
InferProvableOrUndefined<Get<Config, 'publicInput'>>,
311313
InferProvableOrVoid<Get<Config, 'publicOutput'>>,
312-
PrivateInputs[I],
313-
InferProvableOrUndefined<AuxiliaryOutputs[I]>
314+
InferPrivateInput<Config>[I],
315+
InferProvableOrUndefined<InferAuxiliaryOutputs<Config>[I]>
314316
>;
315317
} {
318+
// derived types for convenience
319+
type Methods = InferMethodSignatures<Config>;
320+
type PrivateInputs = InferPrivateInput<Config>;
321+
type AuxiliaryOutputs = InferAuxiliaryOutputs<Config>;
322+
316323
let doProving = true;
317324

318325
let methods = config.methods;
@@ -626,15 +633,8 @@ type ZkProgram<
626633
auxiliaryOutput?: ProvableType;
627634
};
628635
};
629-
},
630-
Methods extends {
631-
[I in keyof Config['methods']]: Method<
632-
InferProvableOrUndefined<Get<Config, 'publicInput'>>,
633-
InferProvableOrVoid<Get<Config, 'publicOutput'>>,
634-
Config['methods'][I]
635-
>;
636636
}
637-
> = ReturnType<typeof ZkProgram<Config, Methods>>;
637+
> = ReturnType<typeof ZkProgram<Config>>;
638638

639639
/**
640640
* A class representing the type of Proof produced by the {@link ZkProgram} in which it is used.

src/lib/testing/constraint-system.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ constraintSystem.fromZkProgram = function fromZkProgram<
114114
methodName: K,
115115
test: ConstraintSystemTest
116116
) {
117-
let program_: ZkProgram<any, any> = program as any;
117+
let program_: ZkProgram<any> = program as any;
118118
let from: any = [...program_.privateInputTypes[methodName]];
119119
if (program_.publicInputType !== Undefined) {
120120
from.unshift(program_.publicInputType);

0 commit comments

Comments
 (0)