Consensys / gnark

gnark is a fast zk-SNARK library that offers a high-level API to design circuits. The library is open source and developed under the Apache 2.0 license
https://hackmd.io/@gnark
Apache License 2.0
1.44k stars 369 forks source link

question: An error happens when using public inputs with Variable-length array #1013

Closed xiyu1984 closed 9 months ago

xiyu1984 commented 9 months ago

Hi,

The error message is: can't set fr.Element from type expr.Term

Here is the full source code

When setting the member X as gnark:",public" as below:

https://github.com/xiyu1984/cook-gnark/blob/ffdd647cf66f975e5468fc0528200f6b33a378f9/circuit/tcircuit.go#L8


type TCircuit struct {
    X []frontend.Variable `gnark:",public"`
    S frontend.Variable   `gnark:"S,secret"`
    Y frontend.Variable   `gnark:",public"`
}

I met the error as above when setting the witness here

But if I set it to be secret as below,

type TCircuit struct {
    X []frontend.Variable `gnark:"-"`
    S frontend.Variable   `gnark:"S,secret"`
    Y frontend.Variable   `gnark:",public"`
}

Everything's OK.

What's the reason of it? Did I make some mistakes?

Thanks for anyone to help.

readygo67 commented 9 months ago

Please check the following code with allocating space for the TCircuit.X.

import (
    "fmt"
    "github.com/consensys/gnark-crypto/ecc"
    "github.com/consensys/gnark/backend/plonk"
    "github.com/consensys/gnark/frontend"
    "github.com/consensys/gnark/frontend/cs/scs"
    "github.com/consensys/gnark/test"
    "github.com/consensys/gnark/test/unsafekzg"
    "testing"
)

type TCircuit struct {
    X []frontend.Variable `gnark:",public"`
    S frontend.Variable   `gnark:"S,secret"`
    Y frontend.Variable   `gnark:",public"`
}

func (circuit *TCircuit) Define(api frontend.API) error {
    res := circuit.X[0]
    for i := 1; i < len(circuit.X); i++ {
        res = api.Mul(res, circuit.X[i])
    }

    res = api.Add(res, circuit.S)
    api.AssertIsEqual(circuit.Y, res)
    return nil
}

func TestSlice_Plonk_BN254(t *testing.T) {
    assert := test.NewAssert(t)
    field := ecc.BN254.ScalarField()

    var x_vec []frontend.Variable
    x_len := 5
    res := 1
    for i := 0; i < x_len; i++ {
        x_vec = append(x_vec, frontend.Variable(i+1))
        res *= (i + 1)
    }

    s := 5
    res += s

    circuit := &TCircuit{
        X: make([]frontend.Variable, x_len),  //SHOULD ALLOCATE HERE
    }

    assignment := &TCircuit{
        X: x_vec,
        S: frontend.Variable(s),
        Y: frontend.Variable(res),
    }

    ccs, err := frontend.Compile(field, scs.NewBuilder, circuit)
    assert.NoError(err)

    // NB! UNSAFE! Use MPC.
    srs, srsLagrange, err := unsafekzg.NewSRS(ccs)
    assert.NoError(err)

    pk, vk, err := plonk.Setup(ccs, srs, srsLagrange)
    assert.NoError(err)

    witness, err := frontend.NewWitness(assignment, field)

    proof, err := plonk.Prove(ccs, pk, witness)
    assert.NoError(err)

    publicWitness, err := witness.Public()
    assert.NoError(err)

    err = plonk.Verify(proof, vk, publicWitness)
    assert.NoError(err)
}
readygo67 commented 9 months ago

please refer https://github.com/Consensys/gnark/issues/970

xiyu1984 commented 9 months ago

Thanks to @readygo67 , it works.