akosba / jsnark

A Java library for zk-SNARK circuits
MIT License
207 stars 85 forks source link

How to recover circuit output from two files #26

Open stark1092 opened 3 years ago

stark1092 commented 3 years ago

I know that jsnark uses prepFiles() to generate .arith and .in files, but how can verifiers recover the circuit outputs from these two files? For example, a prover generates a rsa circuit, uses pubkey to encrypt a plaintext and provides two files. A verifier can easily use runLibsnark() for verification, but how can he get the pubkey value and cipherText from the two files?

akosba commented 3 years ago

Hello,

A verifier can easily use runLibsnark() for verification

First, please note that runLibsnark() is not related to the verifier only. This method runs the jsnark-libsnark interface, which reads the files and computes the values of all variables, including the output variables, then calls libsnark::run_r1cs_ppzksnark or libsnark::run_r1cs_gg_ppzksnark  which run all the three algorithms: key generation, proving and verification algorithms that are provided by libsnark. This all happens in a single call (just for demonstration and performance measurement purposes).  In practice, these algorithms will have to be separated, because key generation, proving and verification will be done at different times by different parties. The separation is not provided in this version of jsnark.

With respect to the outputs and all other intermediate variables, they are not written to a file. They are computed during execution in two places:

If you would like to generate a file with the output values, a method can be added to jsnark's CircuitEvaluator class.

public void writeOutputFile() {
        try {
            LinkedHashMap<Instruction, Instruction> evalSequence = circuitGenerator.getEvaluationQueue();

            PrintWriter printWriter = new PrintWriter(circuitGenerator.getName() + ".out");
            for (Instruction e : evalSequence.keySet()) {
                if (e instanceof WireLabelInstruction) {
                    WireLabelInstruction inst = (WireLabelInstruction) e;
                    if (inst.getType() == LabelType.output) {
                        int id = ((WireLabelInstruction) e).getWire().getWireId();
                        printWriter.println(id + " " + valueAssignment[id].toString(16) + (inst.getDesc().length() > 0 ? (" \t\t# " + inst.getDesc()) : ""));
                    }
                }
            }
            printWriter.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

This will also print any available labels for the output wires beside its value. The above will require adding another method in the WireLabelInstruction class

public String getDesc() {
    return desc;
}

And finally add a call to circuitEvaluator.writeOutputFile(); to prepFiles() of the CircuitGenerator class.

The output values can also be provided to the verifier through other means. For example, the prover could call standard cryptographic libraries and send their outputs in the scenario you mentioned, i.e., the prover does not have to get that from the circuit. (We will need to be sure though that the circuit implements the same algorithm and to format the output properly).

Note that in order to use the above in a meaningful scenario, I think that the separation I referred to above might need to be implemented. For example, this could be done by adding support for a method, e.g., runLibsnarkVerifier, that will call a libsnark executable that takes public input and output values and a verification key. ( The .in file includes both public and prover private inputs. The verifier will only need the public inputs.)

stark1092 commented 3 years ago

@akosba Thanks for your reply! This is very helpful, let me understand more about jsnark. So if I want a prover to provide the public input(public key) and public output(proof value, cipherText) of a encryption process, and a verifier to verify these, I need to generate corresponding parameters and call libsnark? I need to use jsnark to write circuit and generate files(.arith & .in) first, and then split prove/verify in the step of calling libsnark?

thomaslavaur commented 2 years ago

Has anyone already implemented a runLibsnarkVerifier or runLibsnarkProver to avoid the execution of the three algorithms ?