Skip to content

Commit

Permalink
Merge pull request #129 from ConsenSys/fix/reduce_constraints_eddsa
Browse files Browse the repository at this point in the history
Fix/reduce constraints eddsa
  • Loading branch information
gbotrel authored Aug 30, 2021
2 parents 75a43bd + 7950acb commit 1875817
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 67 deletions.
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

0 comments on commit 1875817

Please sign in to comment.