libsnark icon indicating copy to clipboard operation
libsnark copied to clipboard

gadgetlib2 to r1cs_constraint_system conversion issue

Open benma opened this issue 9 years ago • 2 comments

Hi

I am playing with gadgetlib2 and have a weird issue: after converting it to an r1cs constraint system, the is_valid() function returns false.

The demo is using the Comparison_Gadget to compare two numbers (5 <=5`):

#include <iostream>

#include <gadgetlib2/gadget.hpp>
#include <gadgetlib2/integration.hpp>

using namespace libsnark;

int main() {
    typedef Fr<default_ec_pp> FieldT;

    gadgetlib2::initPublicParamsFromDefaultPp();
    auto pb = gadgetlib2::Protoboard::create(gadgetlib2::R1P);
    size_t size =  100;
    const gadgetlib2::PackedWord lhs;
    const gadgetlib2::PackedWord rhs;
    const gadgetlib2::FlagVariable less;
    const gadgetlib2::FlagVariable lessOrEqual;
    auto g = gadgetlib2::Comparison_Gadget::create(pb, 3, lhs, rhs, less, lessOrEqual);
    g->generateConstraints();
    pb->val(lhs) = 5;
    pb->val(rhs) = 5;
    g->generateWitness();
    assert(pb->isSatisfied());
    assert(pb->val(less) == 0);
    assert(pb->val(lessOrEqual) == 1);
    // translate constraint system to libsnark format.
    r1cs_constraint_system<FieldT> cs = get_constraint_system_from_gadgetlib2(*pb);
    // translate full variable assignment to libsnark format
    const r1cs_variable_assignment<FieldT> full_assignment = get_variable_assignment_from_gadgetlib2(*pb);
    // extract primary and auxiliary input
    const r1cs_primary_input<FieldT> primary_input(full_assignment.begin(), full_assignment.begin() + cs.num_inputs());
    const r1cs_auxiliary_input<FieldT> auxiliary_input(full_assignment.begin() + cs.num_inputs(), full_assignment.end());

    assert(cs.is_satisfied(primary_input, auxiliary_input));
    assert(cs.is_valid()); // FAILS
}

(The Makefile I used to compile the above is here: https://github.com/benma/libsnark/blob/6be0121cbeedefc2bffd4b89e7ef268a7da90efe/link_example/Makefile)

g++ main.cpp -o main -std=c++11 -L./lib -lsnark -lsupercop -lgmp -lgmpxx -I./include -I./include/libsnark -DCURVE_BN128
LD_LIBRARY_PATH=./lib ./main
main: main.cpp:35: int main(): Assertion `cs.is_valid()' failed.
Aborted (core dumped)

Even though the protoboard behaves correctly (see the three asserts after g->generateWitness();), the derived r1cs system is invalid. Interestingly, cs.is_satisfied also behaves as expected.

I am not sure whether I did something wrong in the setup / conversion, or if there is a bug in get_constraint_system_from_gadgetlib2 or in the implementation of is_valid().

The same happens if I try to convert the first example of the gadgetlib2 tutorial (https://github.com/scipr-lab/libsnark/blob/e2c8bf06c7cbec7b5e2c6134d6dabd4573382bfd/src/gadgetlib2/examples/tutorial.cpp#L46-L82).

It doesn't happen this example: https://github.com/scipr-lab/libsnark/blob/e2c8bf06c7cbec7b5e2c6134d6dabd4573382bfd/src/gadgetlib2/examples/simple_example.cpp#L50

I'd appreciate any hints.

benma avatar Aug 10 '16 13:08 benma

Similarly, if you add assert(pb.get_constraint_system().is_valid()); here:

https://github.com/scipr-lab/libsnark/blob/e2c8bf06c7cbec7b5e2c6134d6dabd4573382bfd/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp#L39

The test will fail.

benma avatar Aug 10 '16 14:08 benma

I encountered this bug during my testing too, iirc I debugged as far as determining that there is an off-by-one error when checking the number of variables (although I don't know where).

This isn't an issue for most of the built-in examples, as they will often assign too many variables. A somewhat sketchy workaround is to just assign a dummy variable, and don't use it. (Or just don't call is_valid)

tkerber avatar Oct 16 '17 17:10 tkerber