Skip to content

Error when generating a proof for a circuit to which I did not add an extra initial public variable #544

Open
@ilitteri

Description

@ilitteri

The next piece of code proves that $x \cdot y = z$ where $x, z$ are public variables and $y$ is a private variable (witness):

func Example() {
    // [Y, Z]
    publicVariables := []fr_bn254.Element{fr_bn254.NewElement(2), fr_bn254.NewElement(6)}
    // [X]
    secretVariables := []fr_bn254.Element{fr_bn254.NewElement(3)

    /* R1CS Building */

    // (X * Y) == Z
    // X is secret
    // Y is public
    // Z is public
    r1cs := cs_bn254.NewR1CS(1)

    // Variables
    _ = r1cs.AddPublicVariable("1") // the ONE_WIRE
    Y := r1cs.AddPublicVariable("Y")
    Z := r1cs.AddPublicVariable("Z")
    X := r1cs.AddSecretVariable("X")

    // Coefficients
    COEFFICIENT_ONE := r1cs.FromInterface(1)

    // Constraints
    // (1 * X) * (1 * Y) == (1 * Z)
    constraint := constraint.R1C{
        L: constraint.LinearExpression{r1cs.MakeTerm(&COEFFICIENT_ONE, X)}, // 1 * X
        R: constraint.LinearExpression{r1cs.MakeTerm(&COEFFICIENT_ONE, Y)}, // 1 * Y
        O: constraint.LinearExpression{r1cs.MakeTerm(&COEFFICIENT_ONE, Z)}, // 1 * Z
    }
    r1cs.AddConstraint(constraint)

    constraints, r := r1cs.GetConstraints()

    for _, r1c := range constraints {
        fmt.Println(r1c.String(r))
    }

    /* Universal SRS Generation */

    pk, vk, _ := groth16.Setup(r1cs)

    /* Proving */

    rightWitness := buildWitnesses(r1cs, publicVariables, secretVariables)

    p, _ := groth16.Prove(r1cs, pk, rightWitness)

    /* Verification */

    publicWitness, _ := rightWitness.Public()

    verifies := groth16.Verify(p, vk, publicWitness)

    fmt.Println("Verifies with the right public values :", verifies == nil)

    wrongPublicVariables := []fr_bn254.Element{fr_bn254.NewElement(1), fr_bn254.NewElement(5)}
    wrongWitness := buildWitnesses(r1cs, wrongPublicVariables, secretVariables)
    wrongPublicWitness, _ := wrongWitness.Public()
    verifies = groth16.Verify(p, vk, wrongPublicWitness)

    fmt.Println("Verifies with the wrong public values :", verifies == nil)
}

For you to be able to run this, you'll need the buildWitness function:

func buildWitnesses(r1cs *cs_bn254.R1CS, publicVariables fr_bn254.Vector, privateVariables fr_bn254.Vector) witness.Witness {
    witnessValues := make(chan any)

    go func() {
        defer close(witnessValues)
        for _, publicVariable := range publicVariables {
            witnessValues <- publicVariable
        }
        for _, privateVariable := range privateVariables {
            witnessValues <- privateVariable
        }
    }()

    witness, err := witness.New(r1cs.CurveID().ScalarField())
    if err != nil {
        log.Fatal(err)
    }

    // -1 because the first variable is the ONE_WIRE.
    // This is a patch for the bug that I'm issuing that let this code work.
    witness.Fill(r1cs.GetNbPublicVariables()-1, r1cs.GetNbSecretVariables(), witnessValues)

    return witness
}

This code works but only because I added manually the following line:

_ = r1cs.AddPublicVariable("1") // the ONE_WIRE

If you remove this line and the -1 in the patch from the line:

witness.Fill(r1cs.GetNbPublicVariables()-1, r1cs.GetNbSecretVariables(), witnessValues)

you'll get the following error when proving:

18:32:36 ERR error="invalid witness size, got 3, expected 2 = 1 (public) + 1 (secret)" backend=groth16 nbConstraints=1

The error says that we are specting 2 variables (1 public and 1 private) when this is wrong. We've already declared 3 variables (2 public and 1 private).

Users mustn't be responsible for handling this like that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions