Today I have updated our base code to gnark-crypto@master, and suddenly a previously working circuit for ElGamal decryption, stop working...
After digging for I while, I think I have found the issue.
When performing a scalar multiplication on the Identity point (0, 1) of a Twisted Edwards curve (specifically tested on BN254/BabyJubJub), the result is (0, 0) instead of (0, 1).
The point (0, 0) is not a valid point on the twisted edwards curve equation. This issue seems to affects both the off-circuit gnark-crypto library and the in-circuit gnark standard library constraints.
Reproduction Steps (gnark-crypto)
package main
import (
"fmt"
"math/big"
"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
)
func main() {
// 1. Initialize Identity Point (0, 1)
p := &twistededwards.PointAffine{}
p.X.SetZero()
p.Y.SetOne()
fmt.Printf("Original: X=%s Y=%s\n", p.X.String(), p.Y.String())
// 2. Perform Scalar Multiplication by random scalar
scalar := big.NewInt(12345)
res := &twistededwards.PointAffine{}
res.ScalarMultiplication(p, scalar)
fmt.Printf("Result: X=%s Y=%s\n", res.X.String(), res.Y.String())
// 3. Check
if res.X.IsZero() && res.Y.IsZero() {
fmt.Println("FAIL: Result is (0,0) which is invalid.")
} else if res.X.IsZero() && res.Y.IsOne() {
fmt.Println("PASS: Result is Identity (0,1).")
} else {
fmt.Println("FAIL: Unexpected result.")
}
}
Using the current master branch
go get github.com/consensys/gnark-crypto@master
Original: X=0 Y=1
Result: X=0 Y=0
FAIL: Result is (0,0) which is invalid.
However, using the @latest release, the result is correct.
The in-circuit std/algebra/native/twistededwards implementation also fails when ScalarMul is called as an Identity witness, triggering an assertion failure.
package main
import (
testing
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/algebra/native/twistededwards"
"github.com/consensys/gnark/test"
)
type TestCircuit struct {
PointX frontend.Variable
PointY frontend.Variable
}
func (c *TestCircuit) Define(api frontend.API) error {
curve, _ := twistededwards.NewEdCurve(api, ecc.BN254)
p := twistededwards.Point{X: c.PointX, Y: c.PointY}
// This fails with "assertIsEqual 0 == 1" inside the scalar mul logic
_ = curve.ScalarMul(p, 12345)
return nil
}
func TestIdentityScalarMult(t *testing.T) {
assert := test.NewAssert(t)
witness := TestCircuit{PointX: 0, PointY: 1} // Identity
assert.CheckCircuit(&TestCircuit{}, test.WithValidAssignment(&witness))
}
Today I have updated our base code to gnark-crypto@master, and suddenly a previously working circuit for ElGamal decryption, stop working...
After digging for I while, I think I have found the issue.
When performing a scalar multiplication on the Identity point
(0, 1)of a Twisted Edwards curve (specifically tested on BN254/BabyJubJub), the result is(0, 0)instead of(0, 1).The point
(0, 0)is not a valid point on the twisted edwards curve equation. This issue seems to affects both the off-circuitgnark-cryptolibrary and the in-circuitgnarkstandard library constraints.Reproduction Steps (gnark-crypto)
Using the current master branch
go get github.com/consensys/gnark-crypto@masterHowever, using the @latest release, the result is correct.
The in-circuit
std/algebra/native/twistededwardsimplementation also fails whenScalarMulis called as an Identity witness, triggering an assertion failure.