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

Difficulty with separate witness/output computation. #34

Open
alex-ozdemir opened this issue Jul 17, 2019 · 1 comment
Open

Difficulty with separate witness/output computation. #34

alex-ozdemir opened this issue Jul 17, 2019 · 1 comment

Comments

@alex-ozdemir
Copy link

alex-ozdemir commented Jul 17, 2019

First of all, thanks for making this great tool!

One of circom's strengths is the ability to compute output/witness values using machine operations (efficient on a computer), and check the correctness of those values using rank-1 constraints (efficient in the SNARK).

The Num2Bits example in the README shows this capability:

template Num2Bits(n) {
    signal input in;
    signal output out[n];
    var lc1=0;

    for (var i = 0; i<n; i++) {
        out[i] <-- (in >> i) & 1;
        out[i] * (out[i] -1 ) === 0;
        lc1 += out[i] * 2**i;
    }

    lc1 === in;
}

Notice that out[i] is assigned to as a witness value, and part of constraint equations.

Given that Num2Bits works, I thought that my circuit, PolynomialMultiplier would also work:

template PolynomialMultiplier(d) {
    signal input a[d];
    signal input b[d];

    // Output value.
    signal output prod[2 * d - 1];

    // Output computation.
    var acc;
    for (var i = 0; i < 2 * d - 1; i++) {
        acc = 0;
        for (var j = 0; j < d; j++) {
            for (var k = 0; k < d; k++) {
                if (j + k == i) {
                    acc += a[j] * b[k];
                }
            }
        }
        prod[i] <-- acc;
    }

    // Conditions.
    var aAcc;
    var bAcc;
    var pAcc;
    for (var c = 0; c < 2 * d - 1; c++) {
        aAcc = 0;
        bAcc = 0;
        pAcc = 0;
        for (var i = 0; i < d; i++) {
            aAcc += (c + 1) ** i * a[i];
            bAcc += (c + 1) ** i * b[i];
        }
        for (var i = 0; i < 2 * d - 1; i++) {
            pAcc += (c + 1) ** i * prod[i];
        }
        aAcc * bAcc === pAcc;
    }
}

However, it doesn't, with the expression acc += a[j] * b[k] causing a QEQ + QEQ error. circom seems to think that I'm constructing an illegal (not R1CS) constraint, but actually, I'm trying to compute a value.

Is there a way to express "I'm building a value, not a constraint"?

@alex-ozdemir alex-ozdemir changed the title Limitation with Regards to separate witness computation. Difficulty with separate witness/output computation. Jul 17, 2019
@alex-ozdemir
Copy link
Author

alex-ozdemir commented Jul 17, 2019

One potential fix to this is located here. Should I submit a PR?

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

1 participant