Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/reduce constraints eddsa #129

Merged
merged 5 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions examples/rollup/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,7 @@ func (o *Operator) updateState(t Transfer, numTransfer int) error {
o.witnesses.Transfers[numTransfer].Amount.Assign(t.amount)
o.witnesses.Transfers[numTransfer].Signature.R.X.Assign(t.signature.R.X)
o.witnesses.Transfers[numTransfer].Signature.R.Y.Assign(t.signature.R.Y)
o.witnesses.Transfers[numTransfer].Signature.S1.Assign(t.signature.S[:16])
o.witnesses.Transfers[numTransfer].Signature.S2.Assign(t.signature.S[16:])
o.witnesses.Transfers[numTransfer].Signature.S.Assign(t.signature.S[:])

// verifying the signature. The msg is the hash (o.h) of the transfer
// nonce || amount || senderpubKey(x&y) || receiverPubkey(x&y)
Expand Down
68 changes: 27 additions & 41 deletions std/signature/eddsa/eddsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ limitations under the License.
package eddsa

import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/algebra/twistededwards"
"github.com/consensys/gnark/std/hash/mimc"
Expand All @@ -32,12 +31,13 @@ type PublicKey struct {

// Signature stores a signature (to be used in gnark circuit)
// An EdDSA signature is a tuple (R,S) where R is a point on the twisted Edwards curve
// and S a scalar. S can be greater than r, the size of the zk snark field, and must
// not be reduced modulo r. Therefore it is split in S1 and S2, such that if r is n-bits long,
// S = 2^(n/2)*S1 + S2. In other words, S is written S1S2 in basis 2^(n/2).
// and S a scalar. Since the base field of the twisted Edwards is Fr, the number of points
// N on the Edwards is < r+1+2sqrt(r)+2 (since the curve has 2 points of multiplicity 2).
// The subgroup l used in eddsa is <1/2N, so the reduction
// mod l ensures S < r, therefore there is no risk of overflow.
type Signature struct {
R twistededwards.Point
S1, S2 frontend.Variable
R twistededwards.Point
S frontend.Variable
}

// Verify verifies an eddsa signature
Expand All @@ -61,48 +61,34 @@ func Verify(cs *frontend.ConstraintSystem, sig Signature, msg frontend.Variable,
//hramConstant := hash.Sum(data...)
hramConstant := hash.Sum()

// lhs = cofactor*SB
cofactorConstant := cs.Constant(pubKey.Curve.Cofactor)
// lhs = [S]G
cofactor := pubKey.Curve.Cofactor.Uint64()
lhs := twistededwards.Point{}

var basis frontend.Variable
switch pubKey.Curve.ID {
case ecc.BN254:
basis = cs.Constant("340282366920938463463374607431768211456") // 2**128
case ecc.BLS12_381:
basis = cs.Constant("340282366920938463463374607431768211456")
case ecc.BLS12_377:
basis = cs.Constant("340282366920938463463374607431768211456")
case ecc.BW6_761:
basis = cs.Constant("6277101735386680763835789423207666416102355444464034512896") // 2**192
case ecc.BLS24_315:
basis = cs.Constant("340282366920938463463374607431768211456")
default:
panic("curve is not supported")
}

// [cofactor*(2^basis*S1 + S2)]G
lhs.ScalarMulFixedBase(cs, pubKey.Curve.BaseX, pubKey.Curve.BaseY, sig.S1, pubKey.Curve).
ScalarMulNonFixedBase(cs, &lhs, basis, pubKey.Curve)

tmp := twistededwards.Point{}
tmp.ScalarMulFixedBase(cs, pubKey.Curve.BaseX, pubKey.Curve.BaseY, sig.S2, pubKey.Curve)

lhs.AddGeneric(cs, &lhs, &tmp, pubKey.Curve)

lhs.ScalarMulNonFixedBase(cs, &lhs, cofactorConstant, pubKey.Curve)

lhs.ScalarMulFixedBase(cs, pubKey.Curve.BaseX, pubKey.Curve.BaseY, sig.S, pubKey.Curve)
lhs.MustBeOnCurve(cs, pubKey.Curve)

//rhs = cofactor*(R+H(R,A,M)*A)
// rhs = R+[H(R,A,M)]*A
rhs := twistededwards.Point{}
rhs.ScalarMulNonFixedBase(cs, &pubKey.A, hramConstant, pubKey.Curve).
AddGeneric(cs, &rhs, &sig.R, pubKey.Curve).
ScalarMulNonFixedBase(cs, &rhs, cofactorConstant, pubKey.Curve)
AddGeneric(cs, &rhs, &sig.R, pubKey.Curve)
rhs.MustBeOnCurve(cs, pubKey.Curve)

cs.AssertIsEqual(lhs.X, rhs.X)
cs.AssertIsEqual(lhs.Y, rhs.Y)
// lhs-rhs
rhs.Neg(cs, &rhs).AddGeneric(cs, &lhs, &rhs, pubKey.Curve)

// [cofactor](lhs-rhs)
switch cofactor {
case 4:
rhs.Double(cs, &rhs, pubKey.Curve).
Double(cs, &rhs, pubKey.Curve)
case 8:
rhs.Double(cs, &rhs, pubKey.Curve).
Double(cs, &rhs, pubKey.Curve).Double(cs, &rhs, pubKey.Curve)
}

//rhs.MustBeOnCurve(cs, pubKey.Curve)
cs.AssertIsEqual(rhs.X, 0)
cs.AssertIsEqual(rhs.Y, 1)

return nil
}
46 changes: 22 additions & 24 deletions std/signature/eddsa/eddsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ type eddsaCircuit struct {
Message frontend.Variable `gnark:",public"`
}

func parseSignature(id ecc.ID, buf []byte) ([]byte, []byte, []byte, []byte) {
//func parseSignature(id ecc.ID, buf []byte) ([]byte, []byte, []byte) {
func parseSignature(id ecc.ID, buf []byte) ([]byte, []byte, []byte) {

var pointbn254 edwardsbn254.PointAffine
var pointbls12381 edwardsbls12381.PointAffine
Expand All @@ -58,35 +59,30 @@ func parseSignature(id ecc.ID, buf []byte) ([]byte, []byte, []byte, []byte) {
case ecc.BN254:
pointbn254.SetBytes(buf[:32])
a, b := parsePoint(id, buf)
s1 := buf[32:48] // r is 256 bits, so s = 2^128*s1 + s2
s2 := buf[48:]
return a[:], b[:], s1, s2
s := buf[32:]
return a[:], b[:], s
case ecc.BLS12_381:
pointbls12381.SetBytes(buf[:32])
a, b := parsePoint(id, buf)
s1 := buf[32:48]
s2 := buf[48:]
return a[:], b[:], s1, s2
s := buf[32:]
return a[:], b[:], s
case ecc.BLS12_377:
pointbls12377.SetBytes(buf[:32])
a, b := parsePoint(id, buf)
s1 := buf[32:48]
s2 := buf[48:]
return a[:], b[:], s1, s2
s := buf[32:]
return a[:], b[:], s
case ecc.BW6_761:
pointbw6761.SetBytes(buf[:48]) // r is 384 bits, so s = 2^192*s1 + s2
pointbw6761.SetBytes(buf[:48])
a, b := parsePoint(id, buf)
s1 := buf[48:72]
s2 := buf[72:]
return a[:], b[:], s1, s2
s := buf[48:]
return a[:], b[:], s
case ecc.BLS24_315:
pointbls24315.SetBytes(buf[:32])
a, b := parsePoint(id, buf)
s1 := buf[32:48]
s2 := buf[48:]
return a[:], b[:], s1, s2
s := buf[32:]
return a[:], b[:], s
default:
return buf, buf, buf, buf
return buf, buf, buf
}
}

Expand Down Expand Up @@ -214,11 +210,13 @@ func TestEddsa(t *testing.T) {
witness.PublicKey.A.X.Assign(pubkeyAx)
witness.PublicKey.A.Y.Assign(pubkeyAy)

sigRx, sigRy, sigS1, sigS2 := parseSignature(id, signature)
// sigRx, sigRy, sigS1, sigS2 := parseSignature(id, signature)
sigRx, sigRy, sigS := parseSignature(id, signature)
witness.Signature.R.X.Assign(sigRx)
witness.Signature.R.Y.Assign(sigRy)
witness.Signature.S1.Assign(sigS1)
witness.Signature.S2.Assign(sigS2)
// witness.Signature.S1.Assign(sigS1)
// witness.Signature.S2.Assign(sigS2)
witness.Signature.S.Assign(sigS)

assert.SolvingSucceeded(r1cs, &witness)
}
Expand All @@ -232,11 +230,11 @@ func TestEddsa(t *testing.T) {
witness.PublicKey.A.X.Assign(pubkeyAx)
witness.PublicKey.A.Y.Assign(pubkeyAy)

sigRx, sigRy, sigS1, sigS2 := parseSignature(id, signature)
// sigRx, sigRy, sigS1, sigS2 := parseSignature(id, signature)
sigRx, sigRy, sigS := parseSignature(id, signature)
witness.Signature.R.X.Assign(sigRx)
witness.Signature.R.Y.Assign(sigRy)
witness.Signature.S1.Assign(sigS1)
witness.Signature.S2.Assign(sigS2)
witness.Signature.S.Assign(sigS)

assert.SolvingFailed(r1cs, &witness)
}
Expand Down