Using publics

Public values are a small but important part of verifying ZK proofs. Often, a verifier is interested inputs and/or outputs to a public function.

In the toy example below the prover can show that they know the square root of a public value that is published with the proof.

machine Square with degree: 8 {
    reg pc[@pc];
    reg X[<=];
    reg Y[<=];
    reg A;

    // Expose the register value of A in the last time step
    public N = A(7);

    instr square X -> Y {
        Y = X * X
    }
	
    function main {
        A <=X= ${ std::prover::Query::Input(0) };
        A <== square(A);
    }
}

This example uses a small VM with jump and a square instructions. The program reads the private input from the prover, squares it, and enters an infinite loop to ensure that all the remaining rows are filled with the result of A^2. Since the length of our execution trace is fixed and equals 8, we can tag the 8-th row of A (A[7]) as the publicly exposed number.

Let's run all steps needed to generate and verify a proof that 32 = 9:

  1. Setup step:
powdr setup 8 --backend halo2 --field bn254
  1. Witness generation:
powdr pil test_data/asm/sqrt_with_public.asm --field bn254 -i 3
  1. Verification Key generation:
powdr verification-key test_data/asm/sqrt_with_public.asm --field bn254 --backend halo2 --params params.bin
  1. Proof generation:
powdr prove test_data/asm/sqrt_with_public.asm --field bn254 --backend halo2 --params params.bin --vkey vkey.bin
  1. Proof verification:
powdr verify test_data/asm/sqrt_with_public.asm --field bn254 --backend halo2 --params params.bin --vkey vkey.bin --proof sqrt_with_public_proof.bin --publics 9