-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursion / proof composition RFC #89
Comments
Recursion RFCThe
|
not a fan of statement because IIUC in ZK theory it often refers to the tuple
Is this a legitimate usecase? I was thinking: what if they forget to call
it sounds to me like it might refer to proofs created with different proof systems (other than kimchi). Maybe kimchi circuits?
it confused me to no end the first time I read it. I don't have a suggestion but I don't like it |
Thanks for the feedback @mimoo!
Makes sense to me to use the public/private analogy with programming 👍🏻
I think it would be a shame not to support it, since there's no way for the developer to do conditional verification if we don't provide it, and it's already built into Pickles. We could throw an error if neither
Yeah, we shouldn't use "proof system" for this in the API I'm starting to think it could be less confusing if we separated the classes for I wouldn't just call it "kimchi circuits" since what we expose is less general than that -- it's always a step + a wrap circuit, so a more precise name could be The downside of separating
My current favorites are
|
Can’t we transform the function with the decorator to wrap it in the promise? I really like the “calling” the branches version. agree with your reasoning for reusing I like the version of Proof with the generic type parameter for the public input — this gives maximum power to consumers of the API if they want to do something crazy. Plus it keeps the knowledge of the public input shape in front when consuming one of those objects. I don’t have any great ideas about naming for proof vs the collection of recursive proofs, but this is something we should resolve here for sure. |
I researched a bit in the direction of not using classes. Correct typing without syntax contortions would get much easier if we would just use a function for the For example, I'm able to get this to type-check. In particular, see how the circuit becomes a prover with the same name, which returns a Promise, which holds a type that is inferred from the let myCircuit = MultiCircuit({
publicInput: UInt32,
circuits: {
someCircuit: {
privateInput: [Bool],
circuit(publicInput: UInt32, b: Bool) {
publicInput.add(9).equals(UInt32.from(10)).and(b).assertTrue();
},
},
},
});
let p: Proof<UInt32> = await myCircuit.someCircuit(UInt32.one, Bool.true);
p.verify();
p.publicInput; Everything has full intellisense. There aren't any weird hacks, lying to TS, assigning something which we don't need just to make TS happy, verbosity, ... Plus, we avoid all the problems people have with decorator support... Anyone in favor of seriously considering an approach like that? cc @bkase @mrmr1993 @imeckler EDIT: I modified the first version to pass in the public input to each circuit. We probably should allow for "public outputs" as well. If no-one speaks up, I might implement this for now, because I already got the types working and the implementation will be quickly transferable to any other API surface |
We should research that. My feeling was that you can't make TS diverge from the method signatures and prop types on a class |
We decided to go with the function-based (not class-based) approach for non-smart-contract proofs for now, as an "API experiment" to see how everyone likes this alternative. This could help inform general directions taken in our API. Here is an example of using recursive proofs with a new primitive called import { SelfProof, Field, Program } from 'snarkyjs';
let MyProgram = Program({
publicInput: Field,
methods: {
baseCase: {
privateInput: [],
method(publicInput: Field) {
publicInput.assertEquals(Field.zero);
},
},
inductiveCase: {
privateInput: [SelfProof],
method(publicInput: Field, earlierProof: SelfProof<Field>) {
earlierProof.verify();
earlierProof.publicInput.add(1).assertEquals(publicInput);
},
},
},
});
console.log('compiling MyProgram...');
await MyProgram.compile();
console.log('proving base case...');
let proof = await MyProgram.baseCase(Field.zero);
console.log('proving step 1...');
proof = await MyProgram.inductiveCase(Field.one, proof);
console.log('proving step 2...');
proof = await MyProgram.inductiveCase(Field(2), proof);
console.log('ok?', proof.publicInput.toString() === '2'); To use merge in from the Some smaller questions to bike-shed:
Function vs class-based proofsSpinning the last idea further, we could also ditch class definitions of proofs entirely. We could have: let MyProof = Proof(() => Program);
type MyProof = Proof<Field>; Currently we have the following general way of declaring a proof: class MyProof extends Proof<Field> {
static publicInputType = Field;
static tag = () => Program
} Or if we stick with class-based: Is "tag" a good name? In both those examples The tag needs to be passed in as function so you don't have a cyclic dependency of objects when you create a custom proof for a Program that references that proof itself. |
…_develop [develop] Update bindings for evaluated selectors
No description provided.
The text was updated successfully, but these errors were encountered: