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.43k stars 369 forks source link

bug: ...The usage of func : api.AssertIsLessOrEqual() #1220

Closed George551556 closed 3 months ago

George551556 commented 3 months ago
  1. When i use the code "api.AssertIsLessOrEqual(v1, v2)", it always be true, even if the value of v1 is larger than v2.
  2. As forthe code "api.AssertIsLessOrEqual(v1, 100)",it can run correctly and it can return fail when v1 is larger than 100
  3. So I sense that the second argument of this func must be a constant_val, but why? It‘s a bug, or is it designed on purpose?
  4. 是故意的还是不小心?

Expected Behavior

Actual Behavior

Possible Fix

Steps to Reproduce

1. 2. 5. 6.

Context

Your Environment

readygo67 commented 3 months ago

I test the api.api.AssertIsLessOrEqual(v1, v2) in the following case. it works as expected. maybe you can submit your code for further discussion. my test gnark version is "commit c36ff9e8c58daf199a333c0f6c6fe6cacabc0bbb (HEAD -> master, origin/master, origin/HEAD)"

package less_or_equal

import (
    "fmt"
    "github.com/consensys/gnark-crypto/ecc"
    "github.com/consensys/gnark/backend/groth16"
    "github.com/consensys/gnark/frontend"
    "github.com/consensys/gnark/frontend/cs/r1cs"
    "github.com/consensys/gnark/test"
    "math/rand"
    "testing"
)

// Circuit defines a simple circuit
type Circuit struct {
    // struct tags on a variable is optional
    // default uses variable name and secret visibility.
    X frontend.Variable `gnark:"x"`
    Y frontend.Variable `gnark:"y"`
}

// Define declares the circuit constraints
func (circuit *Circuit) Define(api frontend.API) error {
    api.AssertIsLessOrEqual(circuit.X, circuit.Y)
    return nil
}

func TestCubic_LessOrEqual_BN254(t *testing.T) {
    field := ecc.BN254.ScalarField()
    assert := test.NewAssert(t)
    var circuit Circuit

    _r1cs, err := frontend.Compile(field, r1cs.NewBuilder, &circuit)
    assert.NoError(err)

    pk, vk, err := groth16.Setup(_r1cs)
    assert.NoError(err)

    //smaller success
    smaller := &Circuit{
        X: 3,
        Y: 4,
    }

    wit, err := frontend.NewWitness(smaller, ecc.BN254.ScalarField())
    assert.NoError(err)
    proof, err := groth16.Prove(_r1cs, pk, wit)
    assert.NoError(err)

    pubWit, err := wit.Public()
    assert.NoError(err)

    err = groth16.Verify(proof, vk, pubWit)
    if err != nil {
        fmt.Printf("err: %v\n", err)
    } else {
        fmt.Printf("verification pass\n")
    }

    //equal success
    equal := &Circuit{
        X: 3,
        Y: 3,
    }

    wit, err = frontend.NewWitness(equal, ecc.BN254.ScalarField())
    assert.NoError(err)
    proof, err = groth16.Prove(_r1cs, pk, wit)
    assert.NoError(err)

    pubWit, err = wit.Public()
    assert.NoError(err)

    err = groth16.Verify(proof, vk, pubWit)
    if err != nil {
        fmt.Printf("err: %v\n", err)
    } else {
        fmt.Printf("verification pass\n")
    }

    pubWit, err = wit.Public()
    assert.NoError(err)

    for i := 0; i < 100; i++ {
        y := rand.Int()
        x := rand.Intn(y + 1)
        fmt.Printf("i:%v, x: %v, y: %v\n", i, x, y)
        assignment := &Circuit{
            X: x,
            Y: y,
        }

        wit, err = frontend.NewWitness(assignment, ecc.BN254.ScalarField())
        assert.NoError(err)
        proof, err = groth16.Prove(_r1cs, pk, wit)
        assert.NoError(err)

        pubWit, err = wit.Public()
        assert.NoError(err)

        err = groth16.Verify(proof, vk, pubWit)
        if err != nil {
            fmt.Printf("err: %v\n", err)
        } else {
            fmt.Printf("verification pass\n")
        }
    }
}
ivokub commented 3 months ago

Yup, it would be better if you posted your non-working example.

PS! Converted to discussion as seems to be question about gnark usage, not an issue.