Skip to content
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

How to specify the verification key and public / private inputs #369

Closed
imikushin opened this issue May 25, 2024 · 6 comments
Closed

How to specify the verification key and public / private inputs #369

imikushin opened this issue May 25, 2024 · 6 comments

Comments

@imikushin
Copy link
Contributor

imikushin commented May 25, 2024

RV32IJoltVM::verify requires a JoltPreprocessing, which I guess is easy to obtain by calling RV32IJoltVM::preprocess with the bytecode of the program we're tryin to verify. Is this the recommended way at the moment?

Also, how do we specify public inputs when verifying a function run?

For example, we have a guest function:

#[jolt::provable]
fn correct_factors(p: i32, a: i32, b: i32) -> bool {
    p == a * b
}

In this example, I'd like to specify the value of p as public input when verifying this function for a set of arguments, some of which I'd like to keep private (a and b).

I can't figure if this is currently possible. This is the flow as I currently see it:

    let p = 15;
    let (a, b) = (5, 3);

    // Preprocess the program, prove its execution.
    let (prog, preproc) = guest::preprocess_correct_factors();
    let (output, proof) = guest::prove_correct_factors(prog, preproc.clone(), p, a, b);

    // Transmit the proof to the verifier
    // ...

    // Load the proof
    // ...

    // Preprocess the program on the verifier side, verify the proof.
    let (_, preproc) = guest::preprocess_correct_factors();
    let is_valid = RV32IJoltVM::verify(preproc, proof.proof, proof.commitments).is_ok();

What I can't see is how I can verify the proof against the particular public input value (p == 15)

@imikushin imikushin changed the title What's the verification key? How to specify the verification key and public / private inputs May 26, 2024
@imikushin
Copy link
Contributor Author

Okay, found the way to get all inputs and outputs from the proof, and also a bug!

Adding these lines just after generating the proof:

    println!("proof.proof.program_io.inputs: {:?}", &proof.proof.program_io.inputs);
    println!("proof.proof.program_io.outputs: {:?}", &proof.proof.program_io.outputs);

prints out:

proof.proof.program_io.inputs: [30, 10, 6]
proof.proof.program_io.outputs: [1]

So, questions:

  1. Should it print [15, 5, 3] instead of [30, 10, 6]? (30 != 10 * 6)
  2. How does the proof still verify successfully, even though these are clearly the wrong numbers?
  3. Is there a way to hide some of the inputs?

Pushed the above example here: imikushin@0ca5de1

@moodlezoup
Copy link
Collaborator

Hi Ivan,

Good question, and thanks for flagging. Currently there is no way to hide some of the inputs; Jolt currently isn't "hiding" (and probably won't be until we compose the prover with Groth16).

Re: the example linked, the program_io.inputs is the serialized version of the program inputs so there's a type mismatch here: p, a and b have type i32, while program_io.inputs has type Vec<u8>.

It's still kind of strange to me that the raw byte representation would be [30, 10, 6], @ncitron does this look right to you?

@ncitron
Copy link
Contributor

ncitron commented May 28, 2024

The byte representation of the inputs and outputs is from encoding using the postman crate. In postman, then do run length encoding of the integers, where each byte is represented a 7 bits with one bit saved to represent whether the integer is complete, or needs to be extended another byte. This is done to save space, although arguably it might not be the most efficient for jolt (but compared to other encoding libraries postman meets are needs best).

@imikushin
Copy link
Contributor Author

Thanks @ncitron!
Indeed, when using postcard (as Jolt does internally to encode these), inputs and outputs are decoded correctly:

    let (proof_p, proof_a, proof_b): (i32, i32, i32) = postcard::from_bytes(&proof.proof.program_io.inputs).unwrap();
    let proof_output: bool = postcard::from_bytes(&proof.proof.program_io.outputs).unwrap();
    println!("(proof_p, proof_a, proof_b): {:?}", (proof_p, proof_a, proof_b));
    println!("proof_output: {:?}", proof_output);

prints:

(proof_p, proof_a, proof_b): (15, 5, 3)
proof_output: true

@imikushin
Copy link
Contributor Author

The original issue, boiling down to marking some of the inputs as private and omitting them from the proof, still stands though. I'm willing to help address it.

@imikushin
Copy link
Contributor Author

Opened a new issue: #371

Closing this one as I feel it's resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants