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.41k stars 361 forks source link

Generating witness from simple eddsa circuit give error "can't set fr.Element from type expr.LinearExpression". #1084

Closed drakstik closed 6 months ago

drakstik commented 6 months ago

Hi, I wrote a simple eddsa verifying circuit to test with, however, I'm getting the error "can't set fr.Element from type expr.LinearExpression" when running it (Gnark v0.9.1). I suspect it's not a bug and I'm doing something wrong, but I cannot find what for the love of me. Would appreciate a hint!

Here is the code:

package main

import (
    crand "crypto/rand"

    ctwistededwards "github.com/consensys/gnark-crypto/ecc/twistededwards"

    ceddsa "github.com/consensys/gnark-crypto/signature/eddsa"
)

type Circuit struct {
    PublicKey_out eddsa.PublicKey      `gnark:",public"`
    Signature     eddsa.Signature      `gnark:",secret"`
    Message_out   frontend.Variable    `gnark:",public"`
}

func (circuit *Circuit) Define(api frontend.API) error {

    // set the twisted ewards curve to use
    curve, err := twistededwards.NewEdCurve(api, ctwistededwards.BN254)
    if err != nil {
        return err
    }

    // hash function
    mimc, err := mimc.NewMiMC(api)
    if err != nil {
        return err
    }

    // verify the EdDSA signature
    eddsa.Verify(curve, circuit.Signature, circuit.Message_out, circuit.PublicKey_out, &mimc)

    return nil
}

type Msg struct {
    Matrix   [][]frontend.Variable  `json:"matrix"` // Each group of three
    Metadata map[string]interface{} `json:"metadata"`
}

func CreateMsg() Msg {
    N := 16

    // create a 2D array of size N*N
    arr2D := make([][]frontend.Variable, N)

    // Set random integers in the 2D array
    for i := range arr2D {
        arr2D[i] = make([]frontend.Variable, N)
        for j := range arr2D[i] {
            // Seed the random number generator
            rand.New(rand.NewSource(time.Now().UnixNano()))

            arr2D[i][j] = rand.Intn(256)
        }
    }

    // Instantiate message
    msg := Msg{Matrix: arr2D, Metadata: make(map[string]interface{})}

    // Adding metadata to the msg
    msg.Metadata["author"] = "Drakstik"
    msg.Metadata["length"] = 5
    msg.Metadata["height"] = 5
    msg.Metadata["permissibleT"] = [2]frontend.Variable{0, 1}

    return msg
}

func Bytes_to_big_endian(bytes []byte) []byte {
    var msgFr fr.Element // Define a field element

    // (https://pkg.go.dev/github.com/consensys/gnark-crypto@v0.9.1/ecc/bn254/fr#Element.SetBytes)
    msgFr.SetBytes(bytes)               // Set the JSON encoded image as the z value for the fr.Element
    big_endian_bytes := msgFr.Marshal() // Convert z value to a big endian slice

    return big_endian_bytes
}

func main() {
    msg := CreateMsg() // create the message

    /* Sign message (Done by generator) */

    // JSON encode the message
    JSON_msg := msg.JSON_Encode_Msg()

    msg_big_endian_bytes := Bytes_to_big_endian(JSON_msg)

    // Generate a signing key
    privKey, err := ceddsa.New(1, crand.Reader)
    if err != nil {
        fmt.Println("Error: " + err.Error())
    }

    // Sign the msg
    signature, err := privKey.Sign(msg_big_endian_bytes, hash.MIMC_BN254.New())
    if err != nil {
        fmt.Println("Error: " + err.Error())
    }

    // Generate a public signature verification key
    publicKey := privKey.Public()

    // Check if signature is working as expected
    checkSig, err := publicKey.Verify(signature, msg_big_endian_bytes, hash.MIMC_BN254.New())
    if err != nil {
        fmt.Println("ERROR: " + err.Error())
    } else if checkSig {
        fmt.Println("SUCCESS: Signature and public key are working as expected")
    }

    // Instantiate a Circuit
    var circuit Circuit

    // assign values to the Circuit's fields
    circuit.Message_out = msg_big_endian_bytes
    circuit.PublicKey_out.Assign(ctwistededwards.ID(ecc.BN254), publicKey.Bytes())
    circuit.Signature.Assign(ctwistededwards.ID(ecc.BN254), signature)

    /* Compiling the constraint system */
    r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
    if err != nil {
        fmt.Println(err.Error())
    }

    /* Generate the witness */
    witness, err := frontend.NewWitness(&circuit, ecc.BN254.ScalarField())
    if err != nil {
        fmt.Println("ERROR 1: " + err.Error())
        return
    }

    fmt.Println("Success", r1cs, witness)
}

This is the output when I run it (I'm catching the error as "ERROR 1", and it's when I'm generating the witness in main function).

15:04:35 INF compiling circuit
15:04:35 INF parsed circuit inputs nbPublic=5 nbSecret=7
15:04:35 INF building constraint builder nbConstraints=7003
ERROR 1: can't set fr.Element from type expr.LinearExpression

Please help. I could not find much help in other discussions and issues.

ivokub commented 6 months ago

See https://github.com/Consensys/gnark/discussions/1078. It seems the issues are related, I'm closing to keep the discussion about gnark usage in the referenced issue as we use issues for bug tracking and tracking feature requests.