pepper-project / pequin

A system for verifying outsourced computations, and applying SNARKs. Simplified release of the main Pepper codebase.
Other
122 stars 46 forks source link

Change to zkSNARKs based on groth's generic group construction probably breaks something #55

Open noresistence opened 5 years ago

noresistence commented 5 years ago

When submitting #53, my code used pequin @ 8813e516cb2827e8a8752f7d025081fa9aefa161. After the fix for #53, I rebuilt the docker container for the current version @ 312e37eba2b29d9f694e6c89ab2c2a6737ab3839. But there, the same basic example that I used in #53 does compile, but proving fails with the following message:

pepper_prover_example: ../thirdparty/libsnark/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.tcc:406: libsnark::r1cs_gg_ppzksnark_proof<ppT> libsnark::r1cs_gg_ppzksnark_prover(const libsnark::r1cs_gg_ppzksnark_proving_key<ppT>&, libsnark::r1cs_gg_ppzksnark_primary_input<ppT>&, libsnark::r1cs_gg_ppzksnark_auxiliary_input<ppT>&) [with ppT = libff::bn128_pp; libsnark::r1cs_gg_ppzksnark_primary_input<ppT> = std::vector<libff::Fp_model<4l, ((const libff::bigint<4l>&)(& libff::bn128_modulus_r))>, std::allocator<libff::Fp_model<4l, ((const libff::bigint<4l>&)(& libff::bn128_modulus_r))> > >; typename EC_ppT::Fp_type = libff::Fp_model<4l, ((const libff::bigint<4l>&)(& libff::bn128_modulus_r))>; libsnark::r1cs_gg_ppzksnark_auxiliary_input<ppT> = std::vector<libff::Fp_model<4l, ((const libff::bigint<4l>&)(& libff::bn128_modulus_r))>, std::allocator<libff::Fp_model<4l, ((const libff::bigint<4l>&)(& libff::bn128_modulus_r))> > >]: Assertion `!qap_wit.coefficients_for_H[qap_wit.degree()-2].is_zero()' failed.
./docker_execution.sh: line 57:    34 Aborted                 (core dumped) ./bin/pepper_prover_$PROG prove $PROG.pkey $PROG.inputs $PROG.outputs $PROG.proof
noresistence commented 5 years ago

For completeness, this is the example code from #53:

example.h:

#include <stdint.h>

struct In {
    uint8_t input;
};

struct Out {
    uint8_t out;
};

static const uint32_t k[2] = {0x428a2f98,0x71374491};

example.c:

#include <example.h>

void sha256_transform() {
    uint32_t i, t;
    for (i = 0; i < 2; ++i) {
        t = k[i];
    }
}

void sha256_final() {
    sha256_transform();
}

void compute(struct In *input, struct Out *output) {
    uint32_t k;                               /* for-loop index variable */
    sha256_final();
}
noresistence commented 5 years ago

When instead using pequin at 8813e516cb2827e8a8752f7d025081fa9aefa161 and cherry-picking f4af28fdb1ea697bf1db785d0650063016ea3134 on top, the prove will be executed successfully without the error above.

maxhowald commented 5 years ago

The assertion that is failing is here:

https://github.com/scipr-lab/libsnark/blob/bd2a6ca07d4fb72f7b1174d478852234f45ce0b6/libsnark/zk_proof_systems/ppzksnark/r1cs_gg_ppzksnark/r1cs_gg_ppzksnark.tcc#L406

I suspect that when a computation has no constraints with degree 2, the polynomial H degenerates, which causes the assertion to fail.

For example, adding this line to example.c:

output->out = input->input * input->input;

causes the program to run without error, with the output as expected. Commenting out the assertion also makes the original computation work. So this may be a bug in the libsnark library; perhaps the assertion should be removed or conditional on the constraint system containing at least one degree-2 constraint.