From 5def044f444d9b8faa06b7ed1e3cfd446b352c4c Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 12 Sep 2023 19:59:11 -0300 Subject: [PATCH 01/21] hacky Group and Element abstraction Signed-off-by: Ignacio Hagopian --- common/rand.go | 14 ++ group/g1.go | 55 ++++++ group/group.go | 68 ++++++++ samescalarargument/samescalarargument.go | 145 ++++++++-------- samescalarargument/samescalarargument_test.go | 164 ++++++++++-------- transcript/transcript.go | 22 +++ 6 files changed, 327 insertions(+), 141 deletions(-) create mode 100644 group/g1.go create mode 100644 group/group.go diff --git a/common/rand.go b/common/rand.go index e006146..cf2ff1e 100644 --- a/common/rand.go +++ b/common/rand.go @@ -46,6 +46,20 @@ func (r *Rand) GetFr() (fr.Element, error) { } } +// TODO: this function is temporary. It returns a big.Int +// from some random 128 bytes. It should be better defined +// regarding the underlying group order. +func (r *Rand) GetBigInt128() (big.Int, error) { + var byts [128]byte + if _, err := r.rand.Read(byts[:]); err != nil { + return big.Int{}, fmt.Errorf("get randomness: %s", err) + + } + var scalar big.Int + scalar.SetBytes(byts[:]) + return scalar, nil +} + func (r *Rand) GetFrs(n int) ([]fr.Element, error) { var err error ret := make([]fr.Element, n) diff --git a/group/g1.go b/group/g1.go new file mode 100644 index 0000000..23787f7 --- /dev/null +++ b/group/g1.go @@ -0,0 +1,55 @@ +package group + +import ( + "math/big" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" +) + +type GroupG1 struct { +} + +func (g *GroupG1) CreateElement() Element { + return &G1Element{} +} + +// G1Element implements Elemen backed by a G1 element. +type G1Element struct { + inner bls12381.G1Jac +} + +func FromG1Jac(g1Jac bls12381.G1Jac) Element { + return &G1Element{ + inner: g1Jac, + } +} + +func (z *G1Element) ScalarMultiplication(e Element, scalar *big.Int) Element { + ee := e.(*G1Element).inner + z.inner.ScalarMultiplication(&ee, scalar) + return z +} + +func (z *G1Element) Set(e Element) Element { + ee := e.(*G1Element).inner + z.inner.Set(&ee) + return z +} + +func (z *G1Element) AddAssign(e Element) Element { + ee := e.(*G1Element).inner + z.inner.AddAssign(&ee) + return z +} + +func (z *G1Element) Equal(e Element) bool { + ee := e.(*G1Element).inner + return z.inner.Equal(&ee) +} + +func (z *G1Element) Bytes() []byte { + var aff bls12381.G1Affine + aff.FromJacobian(&z.inner) + res := aff.Bytes() + return res[:] +} diff --git a/group/group.go b/group/group.go new file mode 100644 index 0000000..b8699da --- /dev/null +++ b/group/group.go @@ -0,0 +1,68 @@ +package group + +import "math/big" + +type Group interface { + CreateElement() Element +} + +type Element interface { + ScalarMultiplication(e Element, scalar *big.Int) Element + Set(e Element) Element + AddAssign(e Element) Element + Equal(e Element) bool + Bytes() []byte +} + +type GroupCommitment struct { + g Group + + T_1 Element + T_2 Element +} + +func NewGroupCommitment( + group Group, + crsG Element, + crsH Element, + T Element, + r *big.Int, +) GroupCommitment { + T_1, T_2, tmp := group.CreateElement(), group.CreateElement(), group.CreateElement() + T_1.ScalarMultiplication(crsG, r) + T_2.Set(T).AddAssign(tmp.ScalarMultiplication(crsH, r)) + + return GroupCommitment{ + g: group, + T_1: T_1, + T_2: T_2, + } +} + +func (gc *GroupCommitment) Add(cm GroupCommitment) GroupCommitment { + ret := GroupCommitment{ + g: gc.g, + T_1: gc.g.CreateElement(), + T_2: gc.g.CreateElement(), + } + ret.T_1.Set(gc.T_1).AddAssign(cm.T_1) + ret.T_2.Set(gc.T_2).AddAssign(cm.T_2) + + return ret +} + +func (gc *GroupCommitment) Mul(scalar *big.Int) GroupCommitment { + ret := GroupCommitment{ + g: gc.g, + T_1: gc.g.CreateElement(), + T_2: gc.g.CreateElement(), + } + ret.T_1.ScalarMultiplication(gc.T_1, scalar) + ret.T_2.ScalarMultiplication(gc.T_2, scalar) + + return ret +} + +func (t GroupCommitment) Eq(cm GroupCommitment) bool { + return t.T_1.Equal(cm.T_1) && t.T_2.Equal(cm.T_2) +} diff --git a/samescalarargument/samescalarargument.go b/samescalarargument/samescalarargument.go index 9eeb48c..d181cec 100644 --- a/samescalarargument/samescalarargument.go +++ b/samescalarargument/samescalarargument.go @@ -5,10 +5,8 @@ import ( "io" "math/big" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/groupcommitment" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" ) @@ -18,55 +16,58 @@ var ( ) type CRS struct { - Gt bls12381.G1Jac - Gu bls12381.G1Jac - H bls12381.G1Jac + Gt group.Element + Gu group.Element + H group.Element } type Proof struct { - A groupcommitment.GroupCommitment - B groupcommitment.GroupCommitment - Z_k fr.Element - Z_t fr.Element - Z_u fr.Element + A group.GroupCommitment + B group.GroupCommitment + Z_k big.Int + Z_t big.Int + Z_u big.Int } func Prove( + g group.Group, + crs CRS, - R bls12381.G1Jac, - S bls12381.G1Jac, - T groupcommitment.GroupCommitment, - U groupcommitment.GroupCommitment, - k fr.Element, - r_t fr.Element, - r_u fr.Element, + R group.Element, + S group.Element, + T group.GroupCommitment, + U group.GroupCommitment, + k big.Int, + r_t big.Int, + r_u big.Int, transcript *transcript.Transcript, rand *common.Rand, ) (Proof, error) { - r_a, err := rand.GetFr() + // TODO: 128 bytes random big.Int is arbitrary. It should be better defined, + // regarding the underlying group order. Should be fine for an experiment. + r_a, err := rand.GetBigInt128() if err != nil { return Proof{}, fmt.Errorf("get r_a: %s", err) } - r_b, err := rand.GetFr() + r_b, err := rand.GetBigInt128() if err != nil { return Proof{}, fmt.Errorf("get r_b: %s", err) } - r_k, err := rand.GetFr() + r_k, err := rand.GetBigInt128() if err != nil { return Proof{}, fmt.Errorf("get r_k: %s", err) } - var bi_r_k big.Int - r_k.BigInt(&bi_r_k) + var bi_r_k = r_k // TODO: unnecessary, just to keep the the same names as the original code. - var tmp bls12381.G1Jac - A := groupcommitment.New(crs.Gt, crs.H, *tmp.ScalarMultiplication(&R, &bi_r_k), r_a) - B := groupcommitment.New(crs.Gu, crs.H, *tmp.ScalarMultiplication(&S, &bi_r_k), r_b) + tmp := g.CreateElement() + A := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &bi_r_k), &r_a) + B := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &bi_r_k), &r_b) - transcript.AppendPoints(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, A.T_1, A.T_2, B.T_1, B.T_2) + transcript.AppendGroupElements(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, A.T_1, A.T_2, B.T_1, B.T_2) - alpha := transcript.GetAndAppendChallenge(labelAlpha) + alpha := transcript.GetAndAppendChallengeBigInt(labelAlpha) - var z_k, z_t, z_u fr.Element + var z_k, z_t, z_u big.Int z_k.Add(&r_k, z_k.Mul(&k, &alpha)) z_t.Add(&r_a, z_t.Mul(&r_t, &alpha)) z_u.Add(&r_b, z_u.Mul(&r_u, &alpha)) @@ -81,60 +82,62 @@ func Prove( } func Verify( + g group.Group, + proof Proof, crs CRS, - R bls12381.G1Jac, - S bls12381.G1Jac, - T groupcommitment.GroupCommitment, - U groupcommitment.GroupCommitment, + R group.Element, + S group.Element, + T group.GroupCommitment, + U group.GroupCommitment, transcript *transcript.Transcript, ) bool { - transcript.AppendPoints(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, proof.A.T_1, proof.A.T_2, proof.B.T_1, proof.B.T_2) - alpha := transcript.GetAndAppendChallenge(labelAlpha) + transcript.AppendGroupElements(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, proof.A.T_1, proof.A.T_2, proof.B.T_1, proof.B.T_2) + alpha := transcript.GetAndAppendChallengeBigInt(labelAlpha) - var tmp bls12381.G1Jac - expected_1 := groupcommitment.New(crs.Gt, crs.H, *tmp.ScalarMultiplication(&R, common.FrToBigInt(&proof.Z_k)), proof.Z_t) - expected_2 := groupcommitment.New(crs.Gu, crs.H, *tmp.ScalarMultiplication(&S, common.FrToBigInt(&proof.Z_k)), proof.Z_u) + tmp := g.CreateElement() + expected_1 := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &proof.Z_k), &proof.Z_t) + expected_2 := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &proof.Z_k), &proof.Z_u) - return proof.A.Add(T.Mul(alpha)).Eq(&expected_1) && proof.B.Add(U.Mul(alpha)).Eq(&expected_2) + return proof.A.Add(T.Mul(&alpha)).Eq(expected_1) && proof.B.Add(U.Mul(&alpha)).Eq(expected_2) } func (p *Proof) FromReader(r io.Reader) error { - if err := p.A.FromReader(r); err != nil { - return fmt.Errorf("read A: %s", err) - } - if err := p.B.FromReader(r); err != nil { - return fmt.Errorf("read B: %s", err) - } - d := bls12381.NewDecoder(r) - if err := d.Decode(&p.Z_k); err != nil { - return fmt.Errorf("read Z_k: %s", err) - } - if err := d.Decode(&p.Z_t); err != nil { - return fmt.Errorf("read Z_t: %s", err) - } - if err := d.Decode(&p.Z_u); err != nil { - return fmt.Errorf("read Z_u: %s", err) - } + // if err := p.A.FromReader(r); err != nil { + // return fmt.Errorf("read A: %s", err) + // } + // if err := p.B.FromReader(r); err != nil { + // return fmt.Errorf("read B: %s", err) + // } + // d := bls12381.NewDecoder(r) + // if err := d.Decode(&p.Z_k); err != nil { + // return fmt.Errorf("read Z_k: %s", err) + // } + // if err := d.Decode(&p.Z_t); err != nil { + // return fmt.Errorf("read Z_t: %s", err) + // } + // if err := d.Decode(&p.Z_u); err != nil { + // return fmt.Errorf("read Z_u: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - if err := p.A.Serialize(w); err != nil { - return fmt.Errorf("write A: %s", err) - } - if err := p.B.Serialize(w); err != nil { - return fmt.Errorf("write B: %s", err) - } - e := bls12381.NewEncoder(w) - if err := e.Encode(&p.Z_k); err != nil { - return fmt.Errorf("write Z_k: %s", err) - } - if err := e.Encode(&p.Z_t); err != nil { - return fmt.Errorf("write Z_t: %s", err) - } - if err := e.Encode(&p.Z_u); err != nil { - return fmt.Errorf("write Z_u: %s", err) - } + // if err := p.A.Serialize(w); err != nil { + // return fmt.Errorf("write A: %s", err) + // } + // if err := p.B.Serialize(w); err != nil { + // return fmt.Errorf("write B: %s", err) + // } + // e := bls12381.NewEncoder(w) + // if err := e.Encode(&p.Z_k); err != nil { + // return fmt.Errorf("write Z_k: %s", err) + // } + // if err := e.Encode(&p.Z_t); err != nil { + // return fmt.Errorf("write Z_t: %s", err) + // } + // if err := e.Encode(&p.Z_u); err != nil { + // return fmt.Errorf("write Z_u: %s", err) + // } return nil } diff --git a/samescalarargument/samescalarargument_test.go b/samescalarargument/samescalarargument_test.go index e762c34..d5b6435 100644 --- a/samescalarargument/samescalarargument_test.go +++ b/samescalarargument/samescalarargument_test.go @@ -1,12 +1,10 @@ package samescalarargument import ( - "bytes" "testing" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/groupcommitment" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" "github.com/stretchr/testify/require" ) @@ -17,71 +15,97 @@ func TestProveVerify(t *testing.T) { rand, err := common.NewRand(0) require.NoError(t, err) - transcriptProver := transcript.New([]byte("same_scalar")) - - var crs CRS - crs.Gt, err = rand.GetG1Jac() - require.NoError(t, err) - crs.Gu, err = rand.GetG1Jac() - require.NoError(t, err) - crs.H, err = rand.GetG1Jac() - require.NoError(t, err) - - R, err := rand.GetG1Jac() - require.NoError(t, err) - S, err := rand.GetG1Jac() - require.NoError(t, err) - - k, err := rand.GetFr() - require.NoError(t, err) - r_t, err := rand.GetFr() - require.NoError(t, err) - r_u, err := rand.GetFr() - require.NoError(t, err) - - var tmp bls12381.G1Jac - T := groupcommitment.New(crs.Gt, crs.H, *tmp.ScalarMultiplication(&R, common.FrToBigInt(&k)), r_t) - U := groupcommitment.New(crs.Gu, crs.H, *tmp.ScalarMultiplication(&S, common.FrToBigInt(&k)), r_u) - - proof, err := Prove( - crs, - R, - S, - T, - U, - k, - r_t, - r_u, - transcriptProver, - rand, - ) - require.NoError(t, err) - - t.Run("completeness", func(t *testing.T) { - transcriptVerifier := transcript.New([]byte("same_scalar")) - require.True(t, Verify( - proof, - crs, - R, - S, - T, - U, - transcriptVerifier, - )) - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() - - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) - - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) - - require.Equal(t, expected, buf2.Bytes()) - - }) + configs := []struct { + name string + + group group.Group + genRandomGroupElement func() (group.Element, error) + }{ + { + name: "G1 Jacobian", + group: &group.GroupG1{}, + genRandomGroupElement: func() (group.Element, error) { + randG1Jac, err := rand.GetG1Jac() + if err != nil { + return nil, err + } + return group.FromG1Jac(randG1Jac), nil + }, + }, + } + + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + transcriptProver := transcript.New([]byte("same_scalar")) + + var crs CRS + crs.Gt, err = config.genRandomGroupElement() + require.NoError(t, err) + crs.Gu, err = config.genRandomGroupElement() + require.NoError(t, err) + crs.H, err = config.genRandomGroupElement() + require.NoError(t, err) + + R, err := config.genRandomGroupElement() + require.NoError(t, err) + S, err := config.genRandomGroupElement() + require.NoError(t, err) + + k, err := rand.GetBigInt128() + require.NoError(t, err) + r_t, err := rand.GetBigInt128() + require.NoError(t, err) + r_u, err := rand.GetBigInt128() + require.NoError(t, err) + + tmp := config.group.CreateElement() + T := group.NewGroupCommitment(config.group, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &k), &r_t) + U := group.NewGroupCommitment(config.group, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &k), &r_u) + + proof, err := Prove( + config.group, + crs, + R, + S, + T, + U, + k, + r_t, + r_u, + transcriptProver, + rand, + ) + require.NoError(t, err) + + t.Run("completeness", func(t *testing.T) { + transcriptVerifier := transcript.New([]byte("same_scalar")) + require.True(t, Verify( + config.group, + proof, + crs, + R, + S, + T, + U, + transcriptVerifier, + )) + }) + }) + } + + // TEMP: disabled for a while... + // t.Run("encode/decode", func(t *testing.T) { + // buf := bytes.NewBuffer(nil) + // require.NoError(t, proof.Serialize(buf)) + // expected := buf.Bytes() + + // var proof2 Proof + // require.NoError(t, proof2.FromReader(buf)) + + // buf2 := bytes.NewBuffer(nil) + // require.NoError(t, proof2.Serialize(buf2)) + + // require.Equal(t, expected, buf2.Bytes()) + + // }) } diff --git a/transcript/transcript.go b/transcript/transcript.go index 38707a0..fc1ecc9 100644 --- a/transcript/transcript.go +++ b/transcript/transcript.go @@ -2,9 +2,11 @@ package transcript import ( "bytes" + "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/jsign/curdleproofs/group" transcript "github.com/jsign/merlin" ) @@ -29,6 +31,17 @@ func (t *Transcript) AppendPoints(label []byte, points ...bls12381.G1Jac) { } } +// TEMP: experimental. +func (t *Transcript) AppendGroupElements(label []byte, points ...group.Element) { + for _, point := range points { + var bytes bytes.Buffer + affineBytes := point.Bytes() + bytes.Write(affineBytes[:]) + t.appendMessage(label, bytes.Bytes()) + + } +} + func (t *Transcript) AppendPointsAffine(label []byte, points ...bls12381.G1Affine) { for _, point := range points { var bytes bytes.Buffer @@ -57,6 +70,15 @@ func (t *Transcript) GetAndAppendChallenge(label []byte) fr.Element { } } +// TEMP: experimental. +func (t *Transcript) GetAndAppendChallengeBigInt(label []byte) big.Int { + var dest [128]byte + t.inner.ChallengeBytes(label, dest[:]) + var challenge big.Int + challenge.SetBytes(dest[:]) + return challenge +} + func (t *Transcript) GetAndAppendChallenges(label []byte, count int) []fr.Element { challenges := make([]fr.Element, count) for i := 0; i < count; i++ { From 6352d93195d67c2430243d71e08bca20b2a38ea4 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 12 Sep 2023 20:04:26 -0300 Subject: [PATCH 02/21] add gt group impl skeleton Signed-off-by: Ignacio Hagopian --- group/gt.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 group/gt.go diff --git a/group/gt.go b/group/gt.go new file mode 100644 index 0000000..3def9ef --- /dev/null +++ b/group/gt.go @@ -0,0 +1,39 @@ +package group + +import ( + "math/big" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" +) + +type GroupGt struct { +} + +func (g *GroupGt) CreateElement() Element { + return &GtElement{} +} + +// GtElement implements Elemen backed by a Gt element. +type GtElement struct { + inner bls12381.GT +} + +func (z *GtElement) ScalarMultiplication(e Element, scalar *big.Int) Element { + panic("TODO") +} + +func (z *GtElement) Set(e Element) Element { + panic("TODO") +} + +func (z *GtElement) AddAssign(e Element) Element { + panic("TODO") +} + +func (z *GtElement) Equal(e Element) bool { + panic("TODO") +} + +func (z *GtElement) Bytes() []byte { + panic("TODO") +} From 45e69f7538b9551d345b8c8d6b6bd6c1debed1c5 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 12 Sep 2023 20:10:21 -0300 Subject: [PATCH 03/21] add gt backend Signed-off-by: Ignacio Hagopian --- common/rand.go | 10 ++++++++ group/gt.go | 24 +++++++++++++++---- samescalarargument/samescalarargument_test.go | 13 +++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/common/rand.go b/common/rand.go index cf2ff1e..72db4a5 100644 --- a/common/rand.go +++ b/common/rand.go @@ -125,3 +125,13 @@ func (r *Rand) GeneratePermutation(n int) ([]uint32, error) { return permutation, nil } + +// Experimental +func (r *Rand) GetGt() (bls12381.GT, error) { + var randElem bls12381.GT + if _, err := randElem.SetRandom(); err != nil { + return bls12381.GT{}, fmt.Errorf("get random GT: %s", err) + } + + return randElem, nil +} diff --git a/group/gt.go b/group/gt.go index 3def9ef..122b2bb 100644 --- a/group/gt.go +++ b/group/gt.go @@ -18,22 +18,36 @@ type GtElement struct { inner bls12381.GT } +func FromGt(gt bls12381.GT) Element { + return &GtElement{ + inner: gt, + } +} + func (z *GtElement) ScalarMultiplication(e Element, scalar *big.Int) Element { - panic("TODO") + ee := e.(*GtElement).inner + z.inner.Exp(ee, scalar) + return z } func (z *GtElement) Set(e Element) Element { - panic("TODO") + ee := e.(*GtElement).inner + z.inner.Set(&ee) + return z } func (z *GtElement) AddAssign(e Element) Element { - panic("TODO") + ee := e.(*GtElement).inner + z.inner.Mul(&z.inner, &ee) + return z } func (z *GtElement) Equal(e Element) bool { - panic("TODO") + ee := e.(*GtElement).inner + return z.inner.Equal(&ee) } func (z *GtElement) Bytes() []byte { - panic("TODO") + res := z.inner.Bytes() + return res[:] } diff --git a/samescalarargument/samescalarargument_test.go b/samescalarargument/samescalarargument_test.go index d5b6435..8e0713d 100644 --- a/samescalarargument/samescalarargument_test.go +++ b/samescalarargument/samescalarargument_test.go @@ -22,7 +22,7 @@ func TestProveVerify(t *testing.T) { genRandomGroupElement func() (group.Element, error) }{ { - name: "G1 Jacobian", + name: "G1", group: &group.GroupG1{}, genRandomGroupElement: func() (group.Element, error) { randG1Jac, err := rand.GetG1Jac() @@ -32,6 +32,17 @@ func TestProveVerify(t *testing.T) { return group.FromG1Jac(randG1Jac), nil }, }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func() (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, } for _, config := range configs { From 0965c1e570e10654fe1f6e4ecbf42ea99e105f94 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 12 Sep 2023 20:11:57 -0300 Subject: [PATCH 04/21] naive time measurement Signed-off-by: Ignacio Hagopian --- samescalarargument/samescalarargument_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/samescalarargument/samescalarargument_test.go b/samescalarargument/samescalarargument_test.go index 8e0713d..f6ef915 100644 --- a/samescalarargument/samescalarargument_test.go +++ b/samescalarargument/samescalarargument_test.go @@ -1,7 +1,9 @@ package samescalarargument import ( + "fmt" "testing" + "time" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/group" @@ -73,6 +75,7 @@ func TestProveVerify(t *testing.T) { T := group.NewGroupCommitment(config.group, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &k), &r_t) U := group.NewGroupCommitment(config.group, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &k), &r_u) + now := time.Now() proof, err := Prove( config.group, crs, @@ -87,9 +90,11 @@ func TestProveVerify(t *testing.T) { rand, ) require.NoError(t, err) + fmt.Printf("Prove: %s\n", time.Since(now)) t.Run("completeness", func(t *testing.T) { transcriptVerifier := transcript.New([]byte("same_scalar")) + now := time.Now() require.True(t, Verify( config.group, proof, @@ -100,6 +105,7 @@ func TestProveVerify(t *testing.T) { U, transcriptVerifier, )) + fmt.Printf("Verify: %s\n", time.Since(now)) }) }) } From a16d27e99574204d917722821f6c1b19ac43725b Mon Sep 17 00:00:00 2001 From: Antonio Sanso Date: Thu, 21 Sep 2023 12:36:43 +0200 Subject: [PATCH 05/21] be sure to sample only element in G_T --- common/rand.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/rand.go b/common/rand.go index 72db4a5..e8030a1 100644 --- a/common/rand.go +++ b/common/rand.go @@ -133,5 +133,5 @@ func (r *Rand) GetGt() (bls12381.GT, error) { return bls12381.GT{}, fmt.Errorf("get random GT: %s", err) } - return randElem, nil + return bls12381.FinalExponentiation(&randElem), nil } From 760c571b85f6df3f79e35ec2bf0fd3c74cfc5665 Mon Sep 17 00:00:00 2001 From: Antonio Sanso Date: Thu, 21 Sep 2023 13:35:27 +0200 Subject: [PATCH 06/21] adding ExpGLV --- common/rand.go | 17 +++++++---------- group/gt.go | 2 +- samescalarargument/samescalarargument.go | 12 ++++++++---- samescalarargument/samescalarargument_test.go | 6 +++--- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/common/rand.go b/common/rand.go index e8030a1..6ba3013 100644 --- a/common/rand.go +++ b/common/rand.go @@ -46,18 +46,15 @@ func (r *Rand) GetFr() (fr.Element, error) { } } -// TODO: this function is temporary. It returns a big.Int -// from some random 128 bytes. It should be better defined -// regarding the underlying group order. -func (r *Rand) GetBigInt128() (big.Int, error) { - var byts [128]byte - if _, err := r.rand.Read(byts[:]); err != nil { - return big.Int{}, fmt.Errorf("get randomness: %s", err) - +func (r *Rand) GetFrBigInt() (big.Int, error) { + var randElem fr.Element + if _, err := randElem.SetRandom(); err != nil { + return big.Int{}, fmt.Errorf("get random GT: %s", err) } var scalar big.Int - scalar.SetBytes(byts[:]) - return scalar, nil + randElem.BigInt(&scalar) + + return *randElem.BigInt(&scalar), nil } func (r *Rand) GetFrs(n int) ([]fr.Element, error) { diff --git a/group/gt.go b/group/gt.go index 122b2bb..cd161af 100644 --- a/group/gt.go +++ b/group/gt.go @@ -26,7 +26,7 @@ func FromGt(gt bls12381.GT) Element { func (z *GtElement) ScalarMultiplication(e Element, scalar *big.Int) Element { ee := e.(*GtElement).inner - z.inner.Exp(ee, scalar) + z.inner.ExpGLV(ee, scalar) return z } diff --git a/samescalarargument/samescalarargument.go b/samescalarargument/samescalarargument.go index d181cec..8dee817 100644 --- a/samescalarargument/samescalarargument.go +++ b/samescalarargument/samescalarargument.go @@ -5,6 +5,7 @@ import ( "io" "math/big" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" @@ -45,15 +46,15 @@ func Prove( ) (Proof, error) { // TODO: 128 bytes random big.Int is arbitrary. It should be better defined, // regarding the underlying group order. Should be fine for an experiment. - r_a, err := rand.GetBigInt128() + r_a, err := rand.GetFrBigInt() if err != nil { return Proof{}, fmt.Errorf("get r_a: %s", err) } - r_b, err := rand.GetBigInt128() + r_b, err := rand.GetFrBigInt() if err != nil { return Proof{}, fmt.Errorf("get r_b: %s", err) } - r_k, err := rand.GetBigInt128() + r_k, err := rand.GetFrBigInt() if err != nil { return Proof{}, fmt.Errorf("get r_k: %s", err) } @@ -69,8 +70,11 @@ func Prove( var z_k, z_t, z_u big.Int z_k.Add(&r_k, z_k.Mul(&k, &alpha)) + z_k.Mod(&z_k, fr.Modulus()) z_t.Add(&r_a, z_t.Mul(&r_t, &alpha)) + z_t.Mod(&z_t, fr.Modulus()) z_u.Add(&r_b, z_u.Mul(&r_u, &alpha)) + z_u.Mod(&z_u, fr.Modulus()) return Proof{ A: A, @@ -94,7 +98,7 @@ func Verify( ) bool { transcript.AppendGroupElements(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, proof.A.T_1, proof.A.T_2, proof.B.T_1, proof.B.T_2) alpha := transcript.GetAndAppendChallengeBigInt(labelAlpha) - + alpha.Mod(&alpha, fr.Modulus()) tmp := g.CreateElement() expected_1 := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &proof.Z_k), &proof.Z_t) expected_2 := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &proof.Z_k), &proof.Z_u) diff --git a/samescalarargument/samescalarargument_test.go b/samescalarargument/samescalarargument_test.go index f6ef915..f1d3b30 100644 --- a/samescalarargument/samescalarargument_test.go +++ b/samescalarargument/samescalarargument_test.go @@ -64,11 +64,11 @@ func TestProveVerify(t *testing.T) { S, err := config.genRandomGroupElement() require.NoError(t, err) - k, err := rand.GetBigInt128() + k, err := rand.GetFrBigInt() require.NoError(t, err) - r_t, err := rand.GetBigInt128() + r_t, err := rand.GetFrBigInt() require.NoError(t, err) - r_u, err := rand.GetBigInt128() + r_u, err := rand.GetFrBigInt() require.NoError(t, err) tmp := config.group.CreateElement() From fa40fb8dbb27e4229965a0f4536d3a293bf95937 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 21 Sep 2023 15:29:52 -0300 Subject: [PATCH 07/21] group: add constraint that order is r Signed-off-by: Ignacio Hagopian --- common/rand.go | 11 ------ group/g1.go | 7 +++- group/group.go | 10 +++-- group/gt.go | 7 +++- samescalarargument/samescalarargument.go | 39 ++++++++----------- samescalarargument/samescalarargument_test.go | 10 ++--- transcript/transcript.go | 10 ----- 7 files changed, 38 insertions(+), 56 deletions(-) diff --git a/common/rand.go b/common/rand.go index 6ba3013..5cbaf89 100644 --- a/common/rand.go +++ b/common/rand.go @@ -46,17 +46,6 @@ func (r *Rand) GetFr() (fr.Element, error) { } } -func (r *Rand) GetFrBigInt() (big.Int, error) { - var randElem fr.Element - if _, err := randElem.SetRandom(); err != nil { - return big.Int{}, fmt.Errorf("get random GT: %s", err) - } - var scalar big.Int - randElem.BigInt(&scalar) - - return *randElem.BigInt(&scalar), nil -} - func (r *Rand) GetFrs(n int) ([]fr.Element, error) { var err error ret := make([]fr.Element, n) diff --git a/group/g1.go b/group/g1.go index 23787f7..e0e9d15 100644 --- a/group/g1.go +++ b/group/g1.go @@ -4,6 +4,7 @@ import ( "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" ) type GroupG1 struct { @@ -24,9 +25,11 @@ func FromG1Jac(g1Jac bls12381.G1Jac) Element { } } -func (z *G1Element) ScalarMultiplication(e Element, scalar *big.Int) Element { +func (z *G1Element) ScalarMultiplication(e Element, scalar fr.Element) Element { ee := e.(*G1Element).inner - z.inner.ScalarMultiplication(&ee, scalar) + var bi big.Int + scalar.BigInt(&bi) + z.inner.ScalarMultiplication(&ee, &bi) return z } diff --git a/group/group.go b/group/group.go index b8699da..aa093ce 100644 --- a/group/group.go +++ b/group/group.go @@ -1,13 +1,15 @@ package group -import "math/big" +import ( + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) type Group interface { CreateElement() Element } type Element interface { - ScalarMultiplication(e Element, scalar *big.Int) Element + ScalarMultiplication(e Element, scalar fr.Element) Element Set(e Element) Element AddAssign(e Element) Element Equal(e Element) bool @@ -26,7 +28,7 @@ func NewGroupCommitment( crsG Element, crsH Element, T Element, - r *big.Int, + r fr.Element, ) GroupCommitment { T_1, T_2, tmp := group.CreateElement(), group.CreateElement(), group.CreateElement() T_1.ScalarMultiplication(crsG, r) @@ -51,7 +53,7 @@ func (gc *GroupCommitment) Add(cm GroupCommitment) GroupCommitment { return ret } -func (gc *GroupCommitment) Mul(scalar *big.Int) GroupCommitment { +func (gc *GroupCommitment) Mul(scalar fr.Element) GroupCommitment { ret := GroupCommitment{ g: gc.g, T_1: gc.g.CreateElement(), diff --git a/group/gt.go b/group/gt.go index cd161af..dedd9d5 100644 --- a/group/gt.go +++ b/group/gt.go @@ -4,6 +4,7 @@ import ( "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" ) type GroupGt struct { @@ -24,9 +25,11 @@ func FromGt(gt bls12381.GT) Element { } } -func (z *GtElement) ScalarMultiplication(e Element, scalar *big.Int) Element { +func (z *GtElement) ScalarMultiplication(e Element, scalar fr.Element) Element { ee := e.(*GtElement).inner - z.inner.ExpGLV(ee, scalar) + var bi big.Int + scalar.BigInt(&bi) + z.inner.ExpGLV(ee, &bi) return z } diff --git a/samescalarargument/samescalarargument.go b/samescalarargument/samescalarargument.go index 8dee817..c2a0a6d 100644 --- a/samescalarargument/samescalarargument.go +++ b/samescalarargument/samescalarargument.go @@ -3,7 +3,6 @@ package samescalarargument import ( "fmt" "io" - "math/big" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" @@ -25,9 +24,9 @@ type CRS struct { type Proof struct { A group.GroupCommitment B group.GroupCommitment - Z_k big.Int - Z_t big.Int - Z_u big.Int + Z_k fr.Element + Z_t fr.Element + Z_u fr.Element } func Prove( @@ -38,43 +37,40 @@ func Prove( S group.Element, T group.GroupCommitment, U group.GroupCommitment, - k big.Int, - r_t big.Int, - r_u big.Int, + k fr.Element, + r_t fr.Element, + r_u fr.Element, transcript *transcript.Transcript, rand *common.Rand, ) (Proof, error) { // TODO: 128 bytes random big.Int is arbitrary. It should be better defined, // regarding the underlying group order. Should be fine for an experiment. - r_a, err := rand.GetFrBigInt() + r_a, err := rand.GetFr() if err != nil { return Proof{}, fmt.Errorf("get r_a: %s", err) } - r_b, err := rand.GetFrBigInt() + r_b, err := rand.GetFr() if err != nil { return Proof{}, fmt.Errorf("get r_b: %s", err) } - r_k, err := rand.GetFrBigInt() + r_k, err := rand.GetFr() if err != nil { return Proof{}, fmt.Errorf("get r_k: %s", err) } var bi_r_k = r_k // TODO: unnecessary, just to keep the the same names as the original code. tmp := g.CreateElement() - A := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &bi_r_k), &r_a) - B := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &bi_r_k), &r_b) + A := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, bi_r_k), r_a) + B := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, bi_r_k), r_b) transcript.AppendGroupElements(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, A.T_1, A.T_2, B.T_1, B.T_2) - alpha := transcript.GetAndAppendChallengeBigInt(labelAlpha) + alpha := transcript.GetAndAppendChallenge(labelAlpha) - var z_k, z_t, z_u big.Int + var z_k, z_t, z_u fr.Element z_k.Add(&r_k, z_k.Mul(&k, &alpha)) - z_k.Mod(&z_k, fr.Modulus()) z_t.Add(&r_a, z_t.Mul(&r_t, &alpha)) - z_t.Mod(&z_t, fr.Modulus()) z_u.Add(&r_b, z_u.Mul(&r_u, &alpha)) - z_u.Mod(&z_u, fr.Modulus()) return Proof{ A: A, @@ -97,13 +93,12 @@ func Verify( transcript *transcript.Transcript, ) bool { transcript.AppendGroupElements(labelPoints, R, S, T.T_1, T.T_2, U.T_1, U.T_2, proof.A.T_1, proof.A.T_2, proof.B.T_1, proof.B.T_2) - alpha := transcript.GetAndAppendChallengeBigInt(labelAlpha) - alpha.Mod(&alpha, fr.Modulus()) + alpha := transcript.GetAndAppendChallenge(labelAlpha) tmp := g.CreateElement() - expected_1 := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &proof.Z_k), &proof.Z_t) - expected_2 := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &proof.Z_k), &proof.Z_u) + expected_1 := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp.ScalarMultiplication(R, proof.Z_k), proof.Z_t) + expected_2 := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp.ScalarMultiplication(S, proof.Z_k), proof.Z_u) - return proof.A.Add(T.Mul(&alpha)).Eq(expected_1) && proof.B.Add(U.Mul(&alpha)).Eq(expected_2) + return proof.A.Add(T.Mul(alpha)).Eq(expected_1) && proof.B.Add(U.Mul(alpha)).Eq(expected_2) } func (p *Proof) FromReader(r io.Reader) error { diff --git a/samescalarargument/samescalarargument_test.go b/samescalarargument/samescalarargument_test.go index f1d3b30..c6be2ac 100644 --- a/samescalarargument/samescalarargument_test.go +++ b/samescalarargument/samescalarargument_test.go @@ -64,16 +64,16 @@ func TestProveVerify(t *testing.T) { S, err := config.genRandomGroupElement() require.NoError(t, err) - k, err := rand.GetFrBigInt() + k, err := rand.GetFr() require.NoError(t, err) - r_t, err := rand.GetFrBigInt() + r_t, err := rand.GetFr() require.NoError(t, err) - r_u, err := rand.GetFrBigInt() + r_u, err := rand.GetFr() require.NoError(t, err) tmp := config.group.CreateElement() - T := group.NewGroupCommitment(config.group, crs.Gt, crs.H, tmp.ScalarMultiplication(R, &k), &r_t) - U := group.NewGroupCommitment(config.group, crs.Gu, crs.H, tmp.ScalarMultiplication(S, &k), &r_u) + T := group.NewGroupCommitment(config.group, crs.Gt, crs.H, tmp.ScalarMultiplication(R, k), r_t) + U := group.NewGroupCommitment(config.group, crs.Gu, crs.H, tmp.ScalarMultiplication(S, k), r_u) now := time.Now() proof, err := Prove( diff --git a/transcript/transcript.go b/transcript/transcript.go index fc1ecc9..121a14f 100644 --- a/transcript/transcript.go +++ b/transcript/transcript.go @@ -2,7 +2,6 @@ package transcript import ( "bytes" - "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" @@ -70,15 +69,6 @@ func (t *Transcript) GetAndAppendChallenge(label []byte) fr.Element { } } -// TEMP: experimental. -func (t *Transcript) GetAndAppendChallengeBigInt(label []byte) big.Int { - var dest [128]byte - t.inner.ChallengeBytes(label, dest[:]) - var challenge big.Int - challenge.SetBytes(dest[:]) - return challenge -} - func (t *Transcript) GetAndAppendChallenges(label []byte, count int) []fr.Element { challenges := make([]fr.Element, count) for i := 0; i < count; i++ { From 1ae4f670130130682a6190fcd9c52a81d213abc8 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 21 Sep 2023 23:15:43 -0300 Subject: [PATCH 08/21] generalize innerproductargument for g1 Signed-off-by: Ignacio Hagopian --- group/g1.go | 22 ++ group/group.go | 75 +++++ group/gt.go | 101 +++---- innerproductargument/innerproductargument.go | 283 +++++++++--------- .../innerproductargument_test.go | 177 +++++++---- 5 files changed, 399 insertions(+), 259 deletions(-) diff --git a/group/g1.go b/group/g1.go index e0e9d15..07a4f2a 100644 --- a/group/g1.go +++ b/group/g1.go @@ -1,10 +1,12 @@ package group import ( + "fmt" "math/big" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/jsign/curdleproofs/common" ) type GroupG1 struct { @@ -45,6 +47,26 @@ func (z *G1Element) AddAssign(e Element) Element { return z } +func (z *G1Element) Add(a, b Element) Element { + aa := a.(*G1Element).inner + bb := b.(*G1Element).inner + z.inner.Set(&aa) + z.inner.AddAssign(&bb) + return z +} + +func (z *G1Element) MultiExp(base []Element, scalars []fr.Element) (Element, error) { + jacs := make([]bls12381.G1Jac, len(base)) + for i := 0; i < len(base); i++ { + jacs[i] = base[i].(*G1Element).inner + } + affs := bls12381.BatchJacobianToAffineG1(jacs) + if _, err := z.inner.MultiExp(affs, scalars, common.MultiExpConf); err != nil { + return nil, fmt.Errorf("g1 multiexp: %s", err) + } + return z, nil +} + func (z *G1Element) Equal(e Element) bool { ee := e.(*G1Element).inner return z.inner.Equal(&ee) diff --git a/group/group.go b/group/group.go index aa093ce..12ee56a 100644 --- a/group/group.go +++ b/group/group.go @@ -1,7 +1,10 @@ package group import ( + "fmt" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/jsign/curdleproofs/common" ) type Group interface { @@ -11,9 +14,11 @@ type Group interface { type Element interface { ScalarMultiplication(e Element, scalar fr.Element) Element Set(e Element) Element + Add(a, b Element) Element AddAssign(e Element) Element Equal(e Element) bool Bytes() []byte + MultiExp([]Element, []fr.Element) (Element, error) } type GroupCommitment struct { @@ -68,3 +73,73 @@ func (gc *GroupCommitment) Mul(scalar fr.Element) GroupCommitment { func (t GroupCommitment) Eq(cm GroupCommitment) bool { return t.T_1.Equal(cm.T_1) && t.T_2.Equal(cm.T_2) } + +type MsmAccumulator struct { + g Group + A_c Element + baseScalarMap []msmCoeff +} + +type msmCoeff struct { + basis Element + scalar fr.Element +} + +func NewMsmAccumulator(g Group) *MsmAccumulator { + return &MsmAccumulator{ + g: g, + A_c: g.CreateElement(), + baseScalarMap: nil, + } +} + +func (ma *MsmAccumulator) AccumulateCheck( + C Element, + scalar []fr.Element, + basis []Element, + rand *common.Rand) error { + if len(basis) != len(scalar) { + return fmt.Errorf("x and v must have the same length") + } + + alpha, err := rand.GetFr() + if err != nil { + return fmt.Errorf("get random scalar: %s", err) + } + + var tmp fr.Element +outer: + for i := 0; i < len(basis); i++ { + tmp.Mul(&alpha, &scalar[i]) + + for j := range ma.baseScalarMap { + if ma.baseScalarMap[j].basis.Equal(basis[i]) { + var scalar fr.Element + scalar.Add(&ma.baseScalarMap[j].scalar, &tmp) + ma.baseScalarMap[j].scalar = scalar + continue outer + } + } + ma.baseScalarMap = append(ma.baseScalarMap, msmCoeff{basis: basis[i], scalar: tmp}) + } + ma.A_c.AddAssign(C.ScalarMultiplication(C, alpha)) + + return nil +} + +func (ma *MsmAccumulator) Verify() (bool, error) { + x := make([]fr.Element, 0, len(ma.baseScalarMap)) + v := make([]Element, 0, len(ma.baseScalarMap)) + + for _, coeff := range ma.baseScalarMap { + v = append(v, coeff.basis) + x = append(x, coeff.scalar) + } + + msmRes := ma.g.CreateElement() + if _, err := msmRes.MultiExp(v, x); err != nil { + return false, fmt.Errorf("computing msm: %s", err) + } + + return msmRes.Equal(ma.A_c), nil +} diff --git a/group/gt.go b/group/gt.go index dedd9d5..9699791 100644 --- a/group/gt.go +++ b/group/gt.go @@ -1,56 +1,49 @@ package group -import ( - "math/big" - - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" -) - -type GroupGt struct { -} - -func (g *GroupGt) CreateElement() Element { - return &GtElement{} -} - -// GtElement implements Elemen backed by a Gt element. -type GtElement struct { - inner bls12381.GT -} - -func FromGt(gt bls12381.GT) Element { - return &GtElement{ - inner: gt, - } -} - -func (z *GtElement) ScalarMultiplication(e Element, scalar fr.Element) Element { - ee := e.(*GtElement).inner - var bi big.Int - scalar.BigInt(&bi) - z.inner.ExpGLV(ee, &bi) - return z -} - -func (z *GtElement) Set(e Element) Element { - ee := e.(*GtElement).inner - z.inner.Set(&ee) - return z -} - -func (z *GtElement) AddAssign(e Element) Element { - ee := e.(*GtElement).inner - z.inner.Mul(&z.inner, &ee) - return z -} - -func (z *GtElement) Equal(e Element) bool { - ee := e.(*GtElement).inner - return z.inner.Equal(&ee) -} - -func (z *GtElement) Bytes() []byte { - res := z.inner.Bytes() - return res[:] -} +// type GroupGt struct { +// } + +// func (g *GroupGt) CreateElement() Element { +// return &GtElement{} +// } + +// // GtElement implements Elemen backed by a Gt element. +// type GtElement struct { +// inner bls12381.GT +// } + +// func FromGt(gt bls12381.GT) Element { +// return &GtElement{ +// inner: gt, +// } +// } + +// func (z *GtElement) ScalarMultiplication(e Element, scalar fr.Element) Element { +// ee := e.(*GtElement).inner +// var bi big.Int +// scalar.BigInt(&bi) +// z.inner.ExpGLV(ee, &bi) +// return z +// } + +// func (z *GtElement) Set(e Element) Element { +// ee := e.(*GtElement).inner +// z.inner.Set(&ee) +// return z +// } + +// func (z *GtElement) AddAssign(e Element) Element { +// ee := e.(*GtElement).inner +// z.inner.Mul(&z.inner, &ee) +// return z +// } + +// func (z *GtElement) Equal(e Element) bool { +// ee := e.(*GtElement).inner +// return z.inner.Equal(&ee) +// } + +// func (z *GtElement) Bytes() []byte { +// res := z.inner.Bytes() +// return res[:] +// } diff --git a/innerproductargument/innerproductargument.go b/innerproductargument/innerproductargument.go index cdb2a65..f3a820b 100644 --- a/innerproductargument/innerproductargument.go +++ b/innerproductargument/innerproductargument.go @@ -5,10 +5,9 @@ import ( "io" "math/bits" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" ) @@ -21,28 +20,30 @@ var ( ) type CRS struct { - Gs []bls12381.G1Affine - Gs_prime []bls12381.G1Affine - H bls12381.G1Jac + Gs []group.Element + Gs_prime []group.Element + H group.Element } type Proof struct { - B_c bls12381.G1Jac - B_d bls12381.G1Jac + B_c group.Element + B_d group.Element - L_Cs []bls12381.G1Jac - R_Cs []bls12381.G1Jac - L_Ds []bls12381.G1Jac - R_Ds []bls12381.G1Jac + L_Cs []group.Element + R_Cs []group.Element + L_Ds []group.Element + R_Ds []group.Element c0 fr.Element d0 fr.Element } func Prove( + g group.Group, + crs CRS, - C bls12381.G1Jac, - D bls12381.G1Jac, + C group.Element, + D group.Element, z fr.Element, cs []fr.Element, ds []fr.Element, @@ -62,18 +63,18 @@ func Prove( return Proof{}, fmt.Errorf("generate IPA blinders: %s", err) } - var B_c bls12381.G1Jac - if _, err := B_c.MultiExp(crs.Gs, rs_c, common.MultiExpConf); err != nil { + B_c := g.CreateElement() + if _, err := B_c.MultiExp(crs.Gs, rs_c); err != nil { return Proof{}, fmt.Errorf("multiexp B_c: %s", err) } - var B_d bls12381.G1Jac - if _, err := B_d.MultiExp(crs.Gs_prime, rs_d, common.MultiExpConf); err != nil { + B_d := g.CreateElement() + if _, err := B_d.MultiExp(crs.Gs_prime, rs_d); err != nil { return Proof{}, fmt.Errorf("multiexp B_d: %s", err) } - transcript.AppendPoints(labelStep1, C, D) + transcript.AppendGroupElements(labelStep1, C, D) transcript.AppendScalars(labelStep1, z) - transcript.AppendPoints(labelStep1, B_c, B_d) + transcript.AppendGroupElements(labelStep1, B_c, B_d) alpha := transcript.GetAndAppendChallenge(labelAlpha) beta := transcript.GetAndAppendChallenge(labelBeta) @@ -87,15 +88,15 @@ func Prove( ds[i].Add(&rs_d[i], &tmp) } - var H bls12381.G1Jac - H.ScalarMultiplication(&crs.H, common.FrToBigInt(&beta)) + H := g.CreateElement() + H.ScalarMultiplication(crs.H, beta) // Step 2. m := bits.Len(n) - 1 - L_Cs := make([]bls12381.G1Jac, 0, m) - R_Cs := make([]bls12381.G1Jac, 0, m) - L_Ds := make([]bls12381.G1Jac, 0, m) - R_Ds := make([]bls12381.G1Jac, 0, m) + L_Cs := make([]group.Element, 0, m) + R_Cs := make([]group.Element, 0, m) + L_Ds := make([]group.Element, 0, m) + R_Ds := make([]group.Element, 0, m) for len(cs) > 1 { n /= 2 @@ -105,37 +106,37 @@ func Prove( G_L, G_R := common.SplitAt(crs.Gs, n) G_prime_L, G_prime_R := common.SplitAt(crs.Gs_prime, n) - var L_C, L_C_L, L_C_R bls12381.G1Jac - if _, err := L_C_L.MultiExp(G_R, c_L, common.MultiExpConf); err != nil { + L_C, L_C_L, L_C_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := L_C_L.MultiExp(G_R, c_L); err != nil { return Proof{}, fmt.Errorf("ipa L_C_1 multiexp: %s", err) } ipaCLDR, err := common.IPA(c_L, d_R) if err != nil { return Proof{}, fmt.Errorf("ipa L_C_2 multiexp: %s", err) } - L_C_R.ScalarMultiplication(&H, common.FrToBigInt(&ipaCLDR)) - L_C.Set(&L_C_L) - L_C.AddAssign(&L_C_R) + L_C_R.ScalarMultiplication(H, ipaCLDR) + L_C.Set(L_C_L) + L_C.AddAssign(L_C_R) - var L_D bls12381.G1Jac - if _, err := L_D.MultiExp(G_prime_L, d_R, common.MultiExpConf); err != nil { + L_D := g.CreateElement() + if _, err := L_D.MultiExp(G_prime_L, d_R); err != nil { return Proof{}, fmt.Errorf("ipa L_D multiexp: %s", err) } - var R_C, R_C_L, R_C_R bls12381.G1Jac - if _, err := R_C_L.MultiExp(G_L, c_R, common.MultiExpConf); err != nil { + R_C, R_C_L, R_C_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := R_C_L.MultiExp(G_L, c_R); err != nil { return Proof{}, fmt.Errorf("ipa R_C_1 multiexp: %s", err) } ipaCRDL, err := common.IPA(c_R, d_L) if err != nil { return Proof{}, fmt.Errorf("ipa R_C_2 multiexp: %s", err) } - R_C_R.ScalarMultiplication(&H, common.FrToBigInt(&ipaCRDL)) - R_C.Set(&R_C_L) - R_C.AddAssign(&R_C_R) + R_C_R.ScalarMultiplication(H, ipaCRDL) + R_C.Set(R_C_L) + R_C.AddAssign(R_C_R) - var R_D bls12381.G1Jac - if _, err := R_D.MultiExp(G_prime_R, d_L, common.MultiExpConf); err != nil { + R_D := g.CreateElement() + if _, err := R_D.MultiExp(G_prime_R, d_L); err != nil { return Proof{}, fmt.Errorf("ipa R_D multiexp: %s", err) } @@ -144,7 +145,7 @@ func Prove( R_Cs = append(R_Cs, R_C) R_Ds = append(R_Ds, R_D) - transcript.AppendPoints(labelLoop, L_C, L_D, R_C, R_D) + transcript.AppendGroupElements(labelLoop, L_C, L_D, R_C, R_D) gamma := transcript.GetAndAppendChallenge(labelGamma) if gamma.IsZero() { return Proof{}, fmt.Errorf("ipa gamma challenge is zero") @@ -157,12 +158,12 @@ func Prove( c_L[i].Add(&c_L[i], tmps.Mul(&gamma_inv, &c_R[i])) d_L[i].Add(&d_L[i], tmps.Mul(&gamma, &d_R[i])) - var tmpp bls12381.G1Affine - tmpp.ScalarMultiplication(&G_R[i], common.FrToBigInt(&gamma)) - G_L[i].Add(&G_L[i], &tmpp) + tmpp := g.CreateElement() + tmpp.ScalarMultiplication(G_R[i], gamma) + G_L[i].Add(G_L[i], tmpp) - tmpp.ScalarMultiplication(&G_prime_R[i], common.FrToBigInt(&gamma_inv)) - G_prime_L[i].Add(&G_prime_L[i], &tmpp) + tmpp.ScalarMultiplication(G_prime_R[i], gamma_inv) + G_prime_L[i].Add(G_prime_L[i], tmpp) } cs = c_L @@ -188,20 +189,22 @@ func Prove( } func Verify( + g group.Group, + proof Proof, crs CRS, - C bls12381.G1Jac, - D bls12381.G1Jac, + C group.Element, + D group.Element, z fr.Element, us []fr.Element, transcript *transcript.Transcript, - msmAccumulator *msmaccumulator.MsmAccumulator, + msmAccumulator *group.MsmAccumulator, rand *common.Rand, ) (bool, error) { // Step 1. - transcript.AppendPoints(labelStep1, C, D) + transcript.AppendGroupElements(labelStep1, C, D) transcript.AppendScalars(labelStep1, z) - transcript.AppendPoints(labelStep1, proof.B_c, proof.B_d) + transcript.AppendGroupElements(labelStep1, proof.B_c, proof.B_d) alpha := transcript.GetAndAppendChallenge(labelAlpha) beta := transcript.GetAndAppendChallenge(labelBeta) @@ -214,7 +217,7 @@ func Verify( gamma := make([]fr.Element, 0, m) for i := 0; i < m; i++ { - transcript.AppendPoints(labelLoop, proof.L_Cs[i], proof.L_Ds[i], proof.R_Cs[i], proof.R_Ds[i]) + transcript.AppendGroupElements(labelLoop, proof.L_Cs[i], proof.L_Ds[i], proof.R_Cs[i], proof.R_Ds[i]) gamma = append(gamma, transcript.GetAndAppendChallenge(labelGamma)) } gamma_inv := fr.BatchInvert(gamma) @@ -234,31 +237,33 @@ func Verify( } // Accummulate check 1 - var AC1, AC1_L, AC1_M_1, AC1_M_2, AC1_M_3, AC1_R bls12381.G1Jac - if _, err := AC1_L.MultiExp(bls12381.BatchJacobianToAffineG1(proof.L_Cs), gamma, common.MultiExpConf); err != nil { + AC1, AC1_L, AC1_M_1, AC1_M_2, AC1_M_3, AC1_R := g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := AC1_L.MultiExp(proof.L_Cs, gamma); err != nil { return false, fmt.Errorf("ipa AC1_L multiexp: %s", err) } - AC1_M_1.Set(&proof.B_c) - AC1_M_2.ScalarMultiplication(&C, common.FrToBigInt(&alpha)) + AC1_M_1.Set(proof.B_c) + AC1_M_2.ScalarMultiplication(C, alpha) var alphasquaredtimesz fr.Element alphasquaredtimesz.Mul(&alpha, &alpha) alphasquaredtimesz.Mul(&alphasquaredtimesz, &z) - var betaH bls12381.G1Jac - betaH.ScalarMultiplication(&crs.H, common.FrToBigInt(&beta)) - AC1_M_3.ScalarMultiplication(&betaH, common.FrToBigInt(&alphasquaredtimesz)) - if _, err := AC1_R.MultiExp(bls12381.BatchJacobianToAffineG1(proof.R_Cs), gamma_inv, common.MultiExpConf); err != nil { + betaH := g.CreateElement() + betaH.ScalarMultiplication(crs.H, beta) + AC1_M_3.ScalarMultiplication(betaH, alphasquaredtimesz) + if _, err := AC1_R.MultiExp(proof.R_Cs, gamma_inv); err != nil { return false, fmt.Errorf("ipa AC1_R multiexp: %s", err) } - AC1.Set(&AC1_L) - AC1.AddAssign(&AC1_M_1) - AC1.AddAssign(&AC1_M_2) - AC1.AddAssign(&AC1_M_3) - AC1.AddAssign(&AC1_R) - GplusH := make([]bls12381.G1Affine, len(crs.Gs)+1) - copy(GplusH, crs.Gs) - var HAffine bls12381.G1Affine - HAffine.FromJacobian(&crs.H) - GplusH[len(crs.Gs)].Set(&HAffine) + AC1.Set(AC1_L) + AC1.AddAssign(AC1_M_1) + AC1.AddAssign(AC1_M_2) + AC1.AddAssign(AC1_M_3) + AC1.AddAssign(AC1_R) + GplusH := make([]group.Element, len(crs.Gs)+1) + for i := range crs.Gs { + GplusH[i] = g.CreateElement() + GplusH[i].Set(crs.Gs[i]) + } + GplusH[len(crs.Gs)] = g.CreateElement() + GplusH[len(crs.Gs)].Set(crs.H) for i := range s { s[i].Mul(&s[i], &proof.c0) } @@ -271,19 +276,19 @@ func Verify( } // Accummulate check 2 - var AC2, AC2_L, AC2_M_1, AC2_M_2, AC2_R bls12381.G1Jac - if _, err := AC2_L.MultiExp(bls12381.BatchJacobianToAffineG1(proof.L_Ds), gamma, common.MultiExpConf); err != nil { + AC2, AC2_L, AC2_M_1, AC2_M_2, AC2_R := g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := AC2_L.MultiExp(proof.L_Ds, gamma); err != nil { return false, fmt.Errorf("multiexp: %s", err) } - AC2_M_1.Set(&proof.B_d) - AC2_M_2.ScalarMultiplication(&D, common.FrToBigInt(&alpha)) - if _, err := AC2_R.MultiExp(bls12381.BatchJacobianToAffineG1(proof.R_Ds), gamma_inv, common.MultiExpConf); err != nil { + AC2_M_1.Set(proof.B_d) + AC2_M_2.ScalarMultiplication(D, alpha) + if _, err := AC2_R.MultiExp(proof.R_Ds, gamma_inv); err != nil { return false, fmt.Errorf("multiexp: %s", err) } - AC2.Set(&AC2_L) - AC2.AddAssign(&AC2_M_1) - AC2.AddAssign(&AC2_M_2) - AC2.AddAssign(&AC2_R) + AC2.Set(AC2_L) + AC2.AddAssign(AC2_M_1) + AC2.AddAssign(AC2_M_2) + AC2.AddAssign(AC2_R) scalars = s_prime for i := range s_prime { scalars[i].Mul(&scalars[i], &us[i]) @@ -391,70 +396,70 @@ func generateIPABlinders(rand *common.Rand, cs []fr.Element, ds []fr.Element) ([ } func (p *Proof) FromReader(r io.Reader) error { - var tmp bls12381.G1Affine - d := bls12381.NewDecoder(r) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decode B_c: %s", err) - } - p.B_c.FromAffine(&tmp) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decode B_d: %s", err) - } - p.B_d.FromAffine(&tmp) - - if err := common.DecodeAffineSliceToJac(d, &p.L_Cs); err != nil { - return fmt.Errorf("decode L_Cs: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.R_Cs); err != nil { - return fmt.Errorf("decode R_Cs: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.L_Ds); err != nil { - return fmt.Errorf("decode L_Ds: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.R_Ds); err != nil { - return fmt.Errorf("decode R_Ds: %s", err) - } - if err := d.Decode(&p.c0); err != nil { - return fmt.Errorf("decode c0: %s", err) - } - if err := d.Decode(&p.d0); err != nil { - return fmt.Errorf("decode d0: %s", err) - } + // var tmp bls12381.G1Affine + // d := bls12381.NewDecoder(r) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decode B_c: %s", err) + // } + // p.B_c.FromAffine(&tmp) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decode B_d: %s", err) + // } + // p.B_d.FromAffine(&tmp) + + // if err := common.DecodeAffineSliceToJac(d, &p.L_Cs); err != nil { + // return fmt.Errorf("decode L_Cs: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.R_Cs); err != nil { + // return fmt.Errorf("decode R_Cs: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.L_Ds); err != nil { + // return fmt.Errorf("decode L_Ds: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.R_Ds); err != nil { + // return fmt.Errorf("decode R_Ds: %s", err) + // } + // if err := d.Decode(&p.c0); err != nil { + // return fmt.Errorf("decode c0: %s", err) + // } + // if err := d.Decode(&p.d0); err != nil { + // return fmt.Errorf("decode d0: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - b_cd := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.B_c, p.B_d}) - e := bls12381.NewEncoder(w) - if err := e.Encode(&b_cd[0]); err != nil { - return fmt.Errorf("encode B_c: %s", err) - } - if err := e.Encode(&b_cd[1]); err != nil { - return fmt.Errorf("encode B_d: %s", err) - } - affL_Cs := bls12381.BatchJacobianToAffineG1(p.L_Cs) - if err := e.Encode(affL_Cs); err != nil { - return fmt.Errorf("encode L_Cs: %s", err) - } - affR_Cs := bls12381.BatchJacobianToAffineG1(p.R_Cs) - if err := e.Encode(affR_Cs); err != nil { - return fmt.Errorf("encode R_Cs: %s", err) - } - affL_Ds := bls12381.BatchJacobianToAffineG1(p.L_Ds) - if err := e.Encode(affL_Ds); err != nil { - return fmt.Errorf("encode L_Ds: %s", err) - } - affR_Ds := bls12381.BatchJacobianToAffineG1(p.R_Ds) - if err := e.Encode(affR_Ds); err != nil { - return fmt.Errorf("encode R_Ds: %s", err) - } - if err := e.Encode(&p.c0); err != nil { - return fmt.Errorf("encode c0: %s", err) - } - if err := e.Encode(&p.d0); err != nil { - return fmt.Errorf("encode d0: %s", err) - } + // b_cd := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.B_c, p.B_d}) + // e := bls12381.NewEncoder(w) + // if err := e.Encode(&b_cd[0]); err != nil { + // return fmt.Errorf("encode B_c: %s", err) + // } + // if err := e.Encode(&b_cd[1]); err != nil { + // return fmt.Errorf("encode B_d: %s", err) + // } + // affL_Cs := bls12381.BatchJacobianToAffineG1(p.L_Cs) + // if err := e.Encode(affL_Cs); err != nil { + // return fmt.Errorf("encode L_Cs: %s", err) + // } + // affR_Cs := bls12381.BatchJacobianToAffineG1(p.R_Cs) + // if err := e.Encode(affR_Cs); err != nil { + // return fmt.Errorf("encode R_Cs: %s", err) + // } + // affL_Ds := bls12381.BatchJacobianToAffineG1(p.L_Ds) + // if err := e.Encode(affL_Ds); err != nil { + // return fmt.Errorf("encode L_Ds: %s", err) + // } + // affR_Ds := bls12381.BatchJacobianToAffineG1(p.R_Ds) + // if err := e.Encode(affR_Ds); err != nil { + // return fmt.Errorf("encode R_Ds: %s", err) + // } + // if err := e.Encode(&p.c0); err != nil { + // return fmt.Errorf("encode c0: %s", err) + // } + // if err := e.Encode(&p.d0); err != nil { + // return fmt.Errorf("encode d0: %s", err) + // } return nil } diff --git a/innerproductargument/innerproductargument_test.go b/innerproductargument/innerproductargument_test.go index 7b6ddfd..eb3cb24 100644 --- a/innerproductargument/innerproductargument_test.go +++ b/innerproductargument/innerproductargument_test.go @@ -1,98 +1,143 @@ package innerproductargument import ( - "bytes" "testing" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" "github.com/stretchr/testify/require" ) +type testConfig struct { + name string + group group.Group + genRandomGroupElement func(*common.Rand) (group.Element, error) +} + func TestInnerProductArgument(t *testing.T) { t.Parallel() n := 128 - var proof Proof - { - transcript := transcript.New([]byte("IPA")) - crs, B, C, z, bs, cs, _ := setup(t, n) - rand, err := common.NewRand(42) - require.NoError(t, err) - proof, err = Prove( - crs, - B, - C, - z, - bs, - cs, - transcript, - rand, - ) - require.NoError(t, err) + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + // { + // name: "Gt", + // group: &group.GroupGt{}, + // genRandomGroupElement: func() (group.Element, error) { + // randGt, err := rand.GetGt() + // if err != nil { + // return nil, err + // } + // return group.FromGt(randGt), nil + // }, + // }, + } + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + + var proof Proof + { + transcript := transcript.New([]byte("IPA")) + crs, B, C, z, bs, cs, _ := setup(t, config, n) + + rand, err := common.NewRand(42) + require.NoError(t, err) + proof, err = Prove( + config.group, + crs, + B, + C, + z, + bs, + cs, + transcript, + rand, + ) + require.NoError(t, err) + } + + t.Run("completeness", func(t *testing.T) { + transcript := transcript.New([]byte("IPA")) + msmAccumulator := group.NewMsmAccumulator(config.group) + crs, B, C, z, _, _, us := setup(t, config, n) + + rand, err := common.NewRand(43) + require.NoError(t, err) + + ok, err := Verify( + config.group, + proof, + crs, + B, + C, + z, + us, + transcript, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) + + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.True(t, ok) + }) + }) } - t.Run("completeness", func(t *testing.T) { - transcript := transcript.New([]byte("IPA")) - msmAccumulator := msmaccumulator.New() - crs, B, C, z, _, _, us := setup(t, n) - - rand, err := common.NewRand(43) - require.NoError(t, err) - - ok, err := Verify( - proof, - crs, - B, - C, - z, - us, - transcript, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.True(t, ok) - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() + // t.Run("encode/decode", func(t *testing.T) { + // buf := bytes.NewBuffer(nil) + // require.NoError(t, proof.Serialize(buf)) + // expected := buf.Bytes() - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) + // var proof2 Proof + // require.NoError(t, proof2.FromReader(buf)) - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) + // buf2 := bytes.NewBuffer(nil) + // require.NoError(t, proof2.Serialize(buf2)) - require.Equal(t, expected, buf2.Bytes()) - }) + // require.Equal(t, expected, buf2.Bytes()) + // }) } -func setup(t *testing.T, n int) (CRS, bls12381.G1Jac, bls12381.G1Jac, fr.Element, []fr.Element, []fr.Element, []fr.Element) { +func setup(t *testing.T, config testConfig, n int) (CRS, group.Element, group.Element, fr.Element, []fr.Element, []fr.Element, []fr.Element) { rand, err := common.NewRand(0) require.NoError(t, err) - crsGs, err := rand.GetG1Affines(n) - require.NoError(t, err) + crsGs := make([]group.Element, n) + for i := range crsGs { + crsGs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } // There is actually a relationship between crs_G_vec and crs_G_prime_vec because of the grandproduct optimization // We generate a `vec_u` which has the discrete logs of every crs_G_prime element with respect to crs_G us, err := rand.GetFrs(n) require.NoError(t, err) - crsGs_prime := make([]bls12381.G1Affine, n) + crsGs_prime := make([]group.Element, n) + for i := range crsGs_prime { + crsGs_prime[i] = config.group.CreateElement() + } for i := 0; i < n; i++ { - crsGs_prime[i].ScalarMultiplication(&crsGs[i], common.FrToBigInt(&us[i])) + crsGs_prime[i].ScalarMultiplication(crsGs[i], us[i]) } - H, err := rand.GetG1Jac() + H, err := config.genRandomGroupElement(rand) require.NoError(t, err) crs := CRS{ Gs: crsGs, @@ -110,11 +155,11 @@ func setup(t *testing.T, n int) (CRS, bls12381.G1Jac, bls12381.G1Jac, fr.Element require.NoError(t, err) // Create commitments - var B bls12381.G1Jac - _, err = B.MultiExp(crs.Gs, bs, common.MultiExpConf) + B := config.group.CreateElement() + _, err = B.MultiExp(crs.Gs, bs) require.NoError(t, err) - var C bls12381.G1Jac - _, err = C.MultiExp(crs.Gs_prime, cs, common.MultiExpConf) + C := config.group.CreateElement() + _, err = C.MultiExp(crs.Gs_prime, cs) require.NoError(t, err) return crs, B, C, z, bs, cs, us From b8d7f5fd59fe59568d28a653c3b1722e2c94a600 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 21 Sep 2023 23:15:43 -0300 Subject: [PATCH 09/21] innerproductargument: add support for Gt Signed-off-by: Ignacio Hagopian --- group/gt.go | 118 +++++++++++------- .../innerproductargument_test.go | 22 ++-- 2 files changed, 82 insertions(+), 58 deletions(-) diff --git a/group/gt.go b/group/gt.go index 9699791..f476f6b 100644 --- a/group/gt.go +++ b/group/gt.go @@ -1,49 +1,73 @@ package group -// type GroupGt struct { -// } - -// func (g *GroupGt) CreateElement() Element { -// return &GtElement{} -// } - -// // GtElement implements Elemen backed by a Gt element. -// type GtElement struct { -// inner bls12381.GT -// } - -// func FromGt(gt bls12381.GT) Element { -// return &GtElement{ -// inner: gt, -// } -// } - -// func (z *GtElement) ScalarMultiplication(e Element, scalar fr.Element) Element { -// ee := e.(*GtElement).inner -// var bi big.Int -// scalar.BigInt(&bi) -// z.inner.ExpGLV(ee, &bi) -// return z -// } - -// func (z *GtElement) Set(e Element) Element { -// ee := e.(*GtElement).inner -// z.inner.Set(&ee) -// return z -// } - -// func (z *GtElement) AddAssign(e Element) Element { -// ee := e.(*GtElement).inner -// z.inner.Mul(&z.inner, &ee) -// return z -// } - -// func (z *GtElement) Equal(e Element) bool { -// ee := e.(*GtElement).inner -// return z.inner.Equal(&ee) -// } - -// func (z *GtElement) Bytes() []byte { -// res := z.inner.Bytes() -// return res[:] -// } +import ( + "math/big" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +type GroupGt struct { +} + +func (g *GroupGt) CreateElement() Element { + return &GtElement{} +} + +// GtElement implements Elemen backed by a Gt element. +type GtElement struct { + inner bls12381.GT +} + +func FromGt(gt bls12381.GT) Element { + return &GtElement{ + inner: gt, + } +} + +func (z *GtElement) ScalarMultiplication(e Element, scalar fr.Element) Element { + ee := e.(*GtElement).inner + var bi big.Int + scalar.BigInt(&bi) + z.inner.ExpGLV(ee, &bi) + return z +} + +func (z *GtElement) Set(e Element) Element { + ee := e.(*GtElement).inner + z.inner.Set(&ee) + return z +} + +func (z *GtElement) AddAssign(e Element) Element { + ee := e.(*GtElement).inner + z.inner.Mul(&z.inner, &ee) + return z +} + +func (z *GtElement) Add(a, b Element) Element { + z.Set(a) + z.AddAssign(b) + return z +} + +func (z *GtElement) MultiExp(basis []Element, scalars []fr.Element) (Element, error) { + // Maybe quite naive; but it works. Prob could use some Pippenger algorithm? + z.inner = bls12381.GT{} + for i := 0; i < len(basis); i++ { + var tmp GtElement + tmp.ScalarMultiplication(basis[i], scalars[i]) + z.AddAssign(&tmp) + } + return z, nil +} + +func (z *GtElement) Equal(e Element) bool { + ee := e.(*GtElement).inner + return z.inner.Equal(&ee) +} + +func (z *GtElement) Bytes() []byte { + res := z.inner.Bytes() + return res[:] +} diff --git a/innerproductargument/innerproductargument_test.go b/innerproductargument/innerproductargument_test.go index eb3cb24..b6550f6 100644 --- a/innerproductargument/innerproductargument_test.go +++ b/innerproductargument/innerproductargument_test.go @@ -36,17 +36,17 @@ func TestInnerProductArgument(t *testing.T) { return group.FromG1Jac(randG1Jac), nil }, }, - // { - // name: "Gt", - // group: &group.GroupGt{}, - // genRandomGroupElement: func() (group.Element, error) { - // randGt, err := rand.GetGt() - // if err != nil { - // return nil, err - // } - // return group.FromGt(randGt), nil - // }, - // }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, } for _, config := range configs { t.Run(config.name, func(t *testing.T) { From ec7fb7fde30ecda40f65e7cf975ff0a0909b000a Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Thu, 21 Sep 2023 23:15:44 -0300 Subject: [PATCH 10/21] innerproductargument: add group durations Signed-off-by: Ignacio Hagopian --- innerproductargument/innerproductargument_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/innerproductargument/innerproductargument_test.go b/innerproductargument/innerproductargument_test.go index b6550f6..e7f1b74 100644 --- a/innerproductargument/innerproductargument_test.go +++ b/innerproductargument/innerproductargument_test.go @@ -1,7 +1,9 @@ package innerproductargument import ( + "fmt" "testing" + "time" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" @@ -58,6 +60,7 @@ func TestInnerProductArgument(t *testing.T) { rand, err := common.NewRand(42) require.NoError(t, err) + start := time.Now() proof, err = Prove( config.group, crs, @@ -70,6 +73,7 @@ func TestInnerProductArgument(t *testing.T) { rand, ) require.NoError(t, err) + fmt.Printf("Prove for %s took %s\n", config.name, time.Since(start)) } t.Run("completeness", func(t *testing.T) { @@ -80,6 +84,7 @@ func TestInnerProductArgument(t *testing.T) { rand, err := common.NewRand(43) require.NoError(t, err) + startVerify := time.Now() ok, err := Verify( config.group, proof, @@ -95,9 +100,11 @@ func TestInnerProductArgument(t *testing.T) { require.NoError(t, err) require.True(t, ok) + startMsmAccumCheck := time.Now() ok, err = msmAccumulator.Verify() require.NoError(t, err) require.True(t, ok) + fmt.Printf("Verify for %s took %s (%s+%s)\n", config.name, time.Since(startVerify), startMsmAccumCheck.Sub(startVerify), time.Since(startMsmAccumCheck)) }) }) } From a86b74afab3342873d5188d84ed1e1943bdda348 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 13:56:06 -0300 Subject: [PATCH 11/21] tmp progress Signed-off-by: Ignacio Hagopian --- grandproductargument/grandproductargument.go | 158 ++++---- .../grandproductargument_test.go | 348 ++++++++++-------- group/g1.go | 14 + group/group.go | 46 ++- group/gt.go | 18 +- innerproductargument/innerproductargument.go | 7 + .../innerproductargument_test.go | 2 - 7 files changed, 353 insertions(+), 240 deletions(-) diff --git a/grandproductargument/grandproductargument.go b/grandproductargument/grandproductargument.go index 957cf27..3fb721f 100644 --- a/grandproductargument/grandproductargument.go +++ b/grandproductargument/grandproductargument.go @@ -5,11 +5,10 @@ import ( "io" "math/big" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/innerproductargument" - "github.com/jsign/curdleproofs/msmaccumulator" "github.com/jsign/curdleproofs/transcript" ) @@ -21,15 +20,15 @@ func init() { } type Proof struct { - C bls12381.G1Jac + C group.Element Rp fr.Element IPAProof innerproductargument.Proof } type CRS struct { - Gs []bls12381.G1Affine - Hs []bls12381.G1Affine - H bls12381.G1Jac + Gs []group.Element + Hs []group.Element + H group.Element } var ( @@ -40,8 +39,10 @@ var ( ) func Prove( + g group.Group, + crs CRS, - B bls12381.G1Jac, + B group.Element, result fr.Element, bs []fr.Element, r_bs []fr.Element, @@ -49,7 +50,7 @@ func Prove( rand *common.Rand, ) (Proof, error) { // Step 1. - transcript.AppendPoints(labelGprodStep1, B) + transcript.AppendGroupElements(labelGprodStep1, B) transcript.AppendScalars(labelGprodStep1, result) alpha := transcript.GetAndAppendChallenge(labelGrpodAlpha) @@ -63,14 +64,14 @@ func Prove( if err != nil { return Proof{}, fmt.Errorf("generate R_Cs: %s", err) } - var C, C_L, C_R bls12381.G1Jac - if _, err := C_L.MultiExp(crs.Gs, cs, common.MultiExpConf); err != nil { + C, C_L, C_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := C_L.MultiExp(crs.Gs, cs); err != nil { return Proof{}, fmt.Errorf("compute C_L: %s", err) } - if _, err := C_R.MultiExp(crs.Hs, r_cs, common.MultiExpConf); err != nil { + if _, err := C_R.MultiExp(crs.Hs, r_cs); err != nil { return Proof{}, fmt.Errorf("compute C_R: %s", err) } - C.Set(&C_L).AddAssign(&C_R) + C.Set(C_L).AddAssign(C_R) r_b_plus_alpha := make([]fr.Element, len(r_bs)) for i := range r_b_plus_alpha { @@ -81,7 +82,7 @@ func Prove( return Proof{}, fmt.Errorf("compute r_p: %s", err) } - transcript.AppendPoints(labelGprodStep2, C) + transcript.AppendGroupElements(labelGprodStep2, C) transcript.AppendScalars(labelGprodStep2, r_p) beta := transcript.GetAndAppendChallenge(labelGprodBeta) if beta.IsZero() { @@ -91,15 +92,17 @@ func Prove( var betaInv fr.Element betaInv.Inverse(&beta) - Gs_prime := make([]bls12381.G1Affine, len(crs.Gs)) + Gs_prime := make([]group.Element, len(crs.Gs)) tmpBetaInv := betaInv for i := range Gs_prime { - Gs_prime[i].ScalarMultiplication(&crs.Gs[i], common.FrToBigInt(&tmpBetaInv)) + Gs_prime[i] = g.CreateElement() + Gs_prime[i].ScalarMultiplication(crs.Gs[i], tmpBetaInv) tmpBetaInv.Mul(&tmpBetaInv, &betaInv) } - Hs_prime := make([]bls12381.G1Affine, len(crs.Hs)) + Hs_prime := make([]group.Element, len(crs.Hs)) for i := range Hs_prime { - Hs_prime[i].ScalarMultiplication(&crs.Hs[i], common.FrToBigInt(&tmpBetaInv)) + Hs_prime[i] = g.CreateElement() + Hs_prime[i].ScalarMultiplication(crs.Hs[i], tmpBetaInv) } bs_prime := make([]fr.Element, len(crs.Gs)) tmpBeta := beta @@ -128,20 +131,25 @@ func Prove( for i := range alphaBetaExpPlus1 { alphaBetaExpPlus1[i].Mul(&alpha, &betaExpLPlus1) } - var D, D_L, D_R bls12381.G1Jac - if _, err := D_L.MultiExp(Gs_prime, betaPowers, common.MultiExpConf); err != nil { + D, D_L, D_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := D_L.MultiExp(Gs_prime, betaPowers); err != nil { return Proof{}, fmt.Errorf("compute D_L: %s", err) } - if _, err := D_R.MultiExp(Hs_prime, alphaBetaExpPlus1, common.MultiExpConf); err != nil { + if _, err := D_R.MultiExp(Hs_prime, alphaBetaExpPlus1); err != nil { return Proof{}, fmt.Errorf("compute D_R: %s", err) } - D.Set(&B).SubAssign(&D_L).AddAssign(&D_R) + D.Set(B).SubAssign(D_L).AddAssign(D_R) // Step 4 - Gs := make([]bls12381.G1Affine, len(crs.Gs)+len(crs.Hs)) - copy(Gs, crs.Gs) - copy(Gs[len(crs.Gs):], crs.Hs) - + Gs := make([]group.Element, len(crs.Gs)+len(crs.Hs)) + for i := range crs.Gs { + Gs[i] = g.CreateElement() + Gs[i].Set(crs.Gs[i]) + } + for i := range crs.Hs { + Gs[len(crs.Gs)+i] = g.CreateElement() + Gs[len(crs.Gs)+i].Set(crs.Hs[i]) + } Gs_prime = append(Gs_prime, Hs_prime...) var z, z_L, z_R fr.Element @@ -161,18 +169,18 @@ func Prove( if !ipaC_D.Equal(&z) { return Proof{}, fmt.Errorf("IPA(C, D) != z") } - var msmG_cs bls12381.G1Jac - if _, err := msmG_cs.MultiExp(Gs, cs, common.MultiExpConf); err != nil { + msmG_cs := g.CreateElement() + if _, err := msmG_cs.MultiExp(Gs, cs); err != nil { return Proof{}, fmt.Errorf("compute msm(G, c): %s", err) } - if !msmG_cs.Equal(&C) { + if !msmG_cs.Equal(C) { return Proof{}, fmt.Errorf("msm(G, c) != C") } - var msmG_prime_ds bls12381.G1Jac - if _, err := msmG_prime_ds.MultiExp(Gs_prime, ds, common.MultiExpConf); err != nil { + msmG_prime_ds := g.CreateElement() + if _, err := msmG_prime_ds.MultiExp(Gs_prime, ds); err != nil { return Proof{}, fmt.Errorf("compute msm(G', d): %s", err) } - if !msmG_prime_ds.Equal(&D) { + if !msmG_prime_ds.Equal(D) { return Proof{}, fmt.Errorf("msm(G', d) != D") } @@ -183,6 +191,7 @@ func Prove( } ipaProof, err := innerproductargument.Prove( + g, crsIPA, C, D, @@ -204,24 +213,26 @@ func Prove( } func Verify( + g group.Group, + proof Proof, crs CRS, - Gsum bls12381.G1Affine, - Hsum bls12381.G1Affine, - B bls12381.G1Jac, + Gsum group.Element, + Hsum group.Element, + B group.Element, result fr.Element, numBlinders int, transcript *transcript.Transcript, - msmAccumulator *msmaccumulator.MsmAccumulator, + msmAccumulator *group.MsmAccumulator, rand *common.Rand, ) (bool, error) { // Step 1 - transcript.AppendPoints(labelGprodStep1, B) + transcript.AppendGroupElements(labelGprodStep1, B) transcript.AppendScalars(labelGprodStep1, result) alpha := transcript.GetAndAppendChallenge(labelGrpodAlpha) // Step 2 - transcript.AppendPoints(labelGprodStep2, proof.C) + transcript.AppendGroupElements(labelGprodStep2, proof.C) transcript.AppendScalars(labelGprodStep2, proof.Rp) beta := transcript.GetAndAppendChallenge(labelGprodBeta) if beta.IsZero() { @@ -240,15 +251,21 @@ func Verify( for i := len(crs.Gs); i < len(us); i++ { us[i] = betaInvPow } - var D, D_M, D_R bls12381.G1Affine - D_M.ScalarMultiplication(&Gsum, common.FrToBigInt(&betaInv)) - D_R.ScalarMultiplication(&Hsum, common.FrToBigInt(&alpha)) - D.FromJacobian(&B).Sub(&D, &D_M).Add(&D, &D_R) + D, D_M, D_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + D_M.ScalarMultiplication(Gsum, betaInv) + D_R.ScalarMultiplication(Hsum, alpha) + D.Set(B).Sub(D, D_M).Add(D, D_R) // Step 4 - Gs := make([]bls12381.G1Affine, len(crs.Gs)+len(crs.Hs)) - copy(Gs, crs.Gs) - copy(Gs[len(crs.Gs):], crs.Hs) + Gs := make([]group.Element, len(crs.Gs)+len(crs.Hs)) + for i := range crs.Gs { + Gs[i] = g.CreateElement() + Gs[i] = crs.Gs[i] + } + for i := range crs.Hs { + Gs[len(crs.Gs)+i] = g.CreateElement() + Gs[len(crs.Gs)+i] = crs.Hs[i] + } var z, z_L, z_M fr.Element var betaExpL, betaExpLPlusOne fr.Element @@ -265,9 +282,10 @@ func Verify( H: crs.H, } - var DAffine bls12381.G1Jac - DAffine.FromAffine(&D) // TODO(jsign): despite doesn't require inversion, see if we can avoid this. + DAffine := g.CreateElement() + DAffine.Set(D) ok, err := innerproductargument.Verify( + g, proof.IPAProof, ipaCRS, proof.C, @@ -286,33 +304,33 @@ func Verify( } func (p *Proof) FromReader(r io.Reader) error { - d := bls12381.NewDecoder(r) - var tmp bls12381.G1Affine - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decode C: %s", err) - } - p.C.FromAffine(&tmp) - if err := d.Decode(&p.Rp); err != nil { - return fmt.Errorf("decode Rp: %s", err) - } - if err := p.IPAProof.FromReader(r); err != nil { - return fmt.Errorf("decode IPAProof: %s", err) - } + // d := bls12381.NewDecoder(r) + // var tmp bls12381.G1Affine + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decode C: %s", err) + // } + // p.C.FromAffine(&tmp) + // if err := d.Decode(&p.Rp); err != nil { + // return fmt.Errorf("decode Rp: %s", err) + // } + // if err := p.IPAProof.FromReader(r); err != nil { + // return fmt.Errorf("decode IPAProof: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - var cAffine bls12381.G1Affine - cAffine.FromJacobian(&p.C) - e := bls12381.NewEncoder(w) - if err := e.Encode(&cAffine); err != nil { - return fmt.Errorf("encode C: %s", err) - } - if err := e.Encode(&p.Rp); err != nil { - return fmt.Errorf("encode Rp: %s", err) - } - if err := p.IPAProof.Serialize(w); err != nil { - return fmt.Errorf("encode IPAProof: %s", err) - } + // var cAffine bls12381.G1Affine + // cAffine.FromJacobian(&p.C) + // e := bls12381.NewEncoder(w) + // if err := e.Encode(&cAffine); err != nil { + // return fmt.Errorf("encode C: %s", err) + // } + // if err := e.Encode(&p.Rp); err != nil { + // return fmt.Errorf("encode Rp: %s", err) + // } + // if err := p.IPAProof.Serialize(w); err != nil { + // return fmt.Errorf("encode IPAProof: %s", err) + // } return nil } diff --git a/grandproductargument/grandproductargument_test.go b/grandproductargument/grandproductargument_test.go index e5d9da7..8a14377 100644 --- a/grandproductargument/grandproductargument_test.go +++ b/grandproductargument/grandproductargument_test.go @@ -1,178 +1,230 @@ package grandproductargument import ( - "bytes" "testing" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" "github.com/stretchr/testify/require" ) +type testConfig struct { + name string + group group.Group + genRandomGroupElement func(*common.Rand) (group.Element, error) +} + func TestCompletenessAndSoundess(t *testing.T) { t.Parallel() n := 128 + configs := []testConfig{ + // { + // name: "G1", + // group: &group.GroupG1{}, + // genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + // randG1Aff, err := rand.GetG1Affine() + // if err != nil { + // return nil, err + // } + // var randG1Jac bls12381.G1Jac + // randG1Jac.FromAffine(&randG1Aff) + // return group.FromG1Jac(randG1Jac), nil + // }, + // }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } + rand, err := common.NewRand(0) require.NoError(t, err) - var proof Proof - { - transcriptProver := transcript.New([]byte("gprod")) - - crsGs, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - crsHs, err := rand.GetG1Affines(common.N_BLINDERS) - require.NoError(t, err) - crsH, err := rand.GetG1Jac() - require.NoError(t, err) - crs := CRS{ - Gs: crsGs, - Hs: crsHs, - H: crsH, - } - - bs, err := rand.GetFrs(n - common.N_BLINDERS) - require.NoError(t, err) - r_bs, err := rand.GetFrs(common.N_BLINDERS) - require.NoError(t, err) - - result := fr.One() - for _, b := range bs { - result.Mul(&result, &b) - } - - var B, B_L, B_R bls12381.G1Jac - _, err = B_L.MultiExp(crsGs, bs, common.MultiExpConf) - require.NoError(t, err) - _, err = B_R.MultiExp(crsHs, r_bs, common.MultiExpConf) - require.NoError(t, err) - B.AddAssign(&B_L).AddAssign(&B_R) - - proof, err = Prove( - crs, - B, - result, - bs, - r_bs, - transcriptProver, - rand, - ) - require.NoError(t, err) + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + + var proof Proof + { + transcriptProver := transcript.New([]byte("gprod")) + + crsGs := make([]group.Element, n-common.N_BLINDERS) + for i := range crsGs { + crsGs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsHs := make([]group.Element, common.N_BLINDERS) + for i := range crsHs { + crsHs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsH, err := config.genRandomGroupElement(rand) + require.NoError(t, err) + crs := CRS{ + Gs: crsGs, + Hs: crsHs, + H: crsH, + } + + bs, err := rand.GetFrs(n - common.N_BLINDERS) + require.NoError(t, err) + r_bs, err := rand.GetFrs(common.N_BLINDERS) + require.NoError(t, err) + + result := fr.One() + for _, b := range bs { + result.Mul(&result, &b) + } + + B, B_L, B_R := config.group.CreateElement(), config.group.CreateElement(), config.group.CreateElement() + _, err = B_L.MultiExp(crsGs, bs) + require.NoError(t, err) + _, err = B_R.MultiExp(crsHs, r_bs) + require.NoError(t, err) + B.AddAssign(B_L).AddAssign(B_R) + + proof, err = Prove( + config.group, + crs, + B, + result, + bs, + r_bs, + transcriptProver, + rand, + ) + require.NoError(t, err) + } + + t.Run("completeness", func(t *testing.T) { + crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, config, n) + ok, err := Verify( + config.group, + proof, + crs, + Gsum, + Hsum, + B, + result, + common.N_BLINDERS, + transcriptVerifier, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) + + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.True(t, ok) + }) + + t.Run("soundness - wrong result", func(t *testing.T) { + crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, config, n) + one := fr.One() + var resultPlusOne fr.Element + resultPlusOne.Add(&result, &one) + ok, err := Verify( + config.group, + proof, + crs, + Gsum, + Hsum, + B, + resultPlusOne, // This is the reason why the verifier should not accept the proof. + common.N_BLINDERS, + transcriptVerifier, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) // This is OK, because the ultimate check is in the MSM accumulator below. + + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.False(t, ok) // Note we expect this to be false. + }) + + t.Run("soundness - wrong commitment to Bs", func(t *testing.T) { + crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, config, n) + randScalar, err := rand.GetFr() + require.NoError(t, err) + + B.ScalarMultiplication(B, randScalar) // This is the reason why the verifier should not accept the proof. + ok, err := Verify( + config.group, + proof, + crs, + Gsum, + Hsum, + B, + result, + common.N_BLINDERS, + transcriptVerifier, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) // This is OK, because the ultimate check is in the MSM accumulator below. + + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.False(t, ok) // Note we expect this to be false. + }) + + // t.Run("encode/decode", func(t *testing.T) { + // buf := bytes.NewBuffer(nil) + // require.NoError(t, proof.Serialize(buf)) + // expected := buf.Bytes() + + // var proof2 Proof + // require.NoError(t, proof2.FromReader(buf)) + + // buf2 := bytes.NewBuffer(nil) + // require.NoError(t, proof2.Serialize(buf2)) + + // require.Equal(t, expected, buf2.Bytes()) + // }) + }) } - - t.Run("completeness", func(t *testing.T) { - crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, n) - ok, err := Verify( - proof, - crs, - Gsum, - Hsum, - B, - result, - common.N_BLINDERS, - transcriptVerifier, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.True(t, ok) - }) - - t.Run("soundness - wrong result", func(t *testing.T) { - crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, n) - one := fr.One() - var resultPlusOne fr.Element - resultPlusOne.Add(&result, &one) - ok, err := Verify( - proof, - crs, - Gsum, - Hsum, - B, - resultPlusOne, // This is the reason why the verifier should not accept the proof. - common.N_BLINDERS, - transcriptVerifier, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) // This is OK, because the ultimate check is in the MSM accumulator below. - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.False(t, ok) // Note we expect this to be false. - }) - - t.Run("soundness - wrong commitment to Bs", func(t *testing.T) { - crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, n) - randScalar, err := rand.GetFr() - require.NoError(t, err) - - B.ScalarMultiplication(&B, common.FrToBigInt(&randScalar)) // This is the reason why the verifier should not accept the proof. - ok, err := Verify( - proof, - crs, - Gsum, - Hsum, - B, - result, - common.N_BLINDERS, - transcriptVerifier, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) // This is OK, because the ultimate check is in the MSM accumulator below. - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.False(t, ok) // Note we expect this to be false. - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() - - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) - - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) - - require.Equal(t, expected, buf2.Bytes()) - }) } // TOOD(jsign): replicat in other tests. -func genVerifierParameters(t *testing.T, n int) (CRS, bls12381.G1Affine, bls12381.G1Affine, bls12381.G1Jac, fr.Element, *transcript.Transcript, *msmaccumulator.MsmAccumulator) { +func genVerifierParameters(t *testing.T, config testConfig, n int) (CRS, group.Element, group.Element, group.Element, fr.Element, *transcript.Transcript, *group.MsmAccumulator) { rand, err := common.NewRand(0) require.NoError(t, err) transcriptVerifier := transcript.New([]byte("gprod")) - msmAccumulator := msmaccumulator.New() + msmAccumulator := group.NewMsmAccumulator(config.group) - crsGs, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - crsHs, err := rand.GetG1Affines(common.N_BLINDERS) - require.NoError(t, err) - crsH, err := rand.GetG1Jac() + crsGs := make([]group.Element, n-common.N_BLINDERS) + for i := range crsGs { + crsGs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsHs := make([]group.Element, common.N_BLINDERS) + for i := range crsHs { + crsHs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsH, err := config.genRandomGroupElement(rand) require.NoError(t, err) - var Gsum bls12381.G1Affine + Gsum := config.group.CreateElement() for _, g := range crsGs { - Gsum.Add(&Gsum, &g) + Gsum.Add(Gsum, g) } - var Hsum bls12381.G1Affine + Hsum := config.group.CreateElement() for _, h := range crsHs { - Hsum.Add(&Hsum, &h) + Hsum.Add(Hsum, h) } crs := CRS{ Gs: crsGs, @@ -189,12 +241,12 @@ func genVerifierParameters(t *testing.T, n int) (CRS, bls12381.G1Affine, bls1238 result.Mul(&result, &b) } - var B, B_L, B_R bls12381.G1Jac - _, err = B_L.MultiExp(crsGs, bs, common.MultiExpConf) + B, B_L, B_R := config.group.CreateElement(), config.group.CreateElement(), config.group.CreateElement() + _, err = B_L.MultiExp(crsGs, bs) require.NoError(t, err) - _, err = B_R.MultiExp(crsHs, r_bs, common.MultiExpConf) + _, err = B_R.MultiExp(crsHs, r_bs) require.NoError(t, err) - B.AddAssign(&B_L).AddAssign(&B_R) + B.AddAssign(B_L).AddAssign(B_R) return crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator } diff --git a/group/g1.go b/group/g1.go index 07a4f2a..ae1bc18 100644 --- a/group/g1.go +++ b/group/g1.go @@ -47,6 +47,12 @@ func (z *G1Element) AddAssign(e Element) Element { return z } +func (z *G1Element) SubAssign(e Element) Element { + ee := e.(*G1Element).inner + z.inner.SubAssign(&ee) + return z +} + func (z *G1Element) Add(a, b Element) Element { aa := a.(*G1Element).inner bb := b.(*G1Element).inner @@ -55,6 +61,14 @@ func (z *G1Element) Add(a, b Element) Element { return z } +func (z *G1Element) Sub(a, b Element) Element { + aa := a.(*G1Element).inner + bb := b.(*G1Element).inner + z.inner.Set(&aa) + z.inner.SubAssign(&bb) + return z +} + func (z *G1Element) MultiExp(base []Element, scalars []fr.Element) (Element, error) { jacs := make([]bls12381.G1Jac, len(base)) for i := 0; i < len(base); i++ { diff --git a/group/group.go b/group/group.go index 12ee56a..3d90ecb 100644 --- a/group/group.go +++ b/group/group.go @@ -16,6 +16,8 @@ type Element interface { Set(e Element) Element Add(a, b Element) Element AddAssign(e Element) Element + Sub(a, b Element) Element + SubAssign(e Element) Element Equal(e Element) bool Bytes() []byte MultiExp([]Element, []fr.Element) (Element, error) @@ -102,27 +104,35 @@ func (ma *MsmAccumulator) AccumulateCheck( return fmt.Errorf("x and v must have the same length") } - alpha, err := rand.GetFr() - if err != nil { - return fmt.Errorf("get random scalar: %s", err) - } + // alpha, err := rand.GetFr() + // if err != nil { + // return fmt.Errorf("get random scalar: %s", err) + // } + var alpha fr.Element + alpha.SetOne() - var tmp fr.Element -outer: + // var tmp fr.Element + // outer: for i := 0; i < len(basis); i++ { - tmp.Mul(&alpha, &scalar[i]) - - for j := range ma.baseScalarMap { - if ma.baseScalarMap[j].basis.Equal(basis[i]) { - var scalar fr.Element - scalar.Add(&ma.baseScalarMap[j].scalar, &tmp) - ma.baseScalarMap[j].scalar = scalar - continue outer - } - } - ma.baseScalarMap = append(ma.baseScalarMap, msmCoeff{basis: basis[i], scalar: tmp}) + // tmp.Mul(&alpha, &scalar[i]) + + // for j := range ma.baseScalarMap { + // if ma.baseScalarMap[j].basis.Equal(basis[i]) { + // var scalar fr.Element + // scalar.Add(&ma.baseScalarMap[j].scalar, &tmp) + // ma.baseScalarMap[j].scalar = scalar + // continue outer + // } + // } + + var basisCoeff msmCoeff + basisCoeff.basis = ma.g.CreateElement() + basisCoeff.basis.Set(basis[i]) + basisCoeff.scalar = scalar[i] + ma.baseScalarMap = append(ma.baseScalarMap, basisCoeff) } - ma.A_c.AddAssign(C.ScalarMultiplication(C, alpha)) + // ma.A_c.AddAssign(C.ScalarMultiplication(C, alpha)) + ma.A_c.AddAssign(C) return nil } diff --git a/group/gt.go b/group/gt.go index f476f6b..f33b439 100644 --- a/group/gt.go +++ b/group/gt.go @@ -11,7 +11,9 @@ type GroupGt struct { } func (g *GroupGt) CreateElement() Element { - return &GtElement{} + res := &GtElement{} + res.inner.SetOne() + return res } // GtElement implements Elemen backed by a Gt element. @@ -45,15 +47,27 @@ func (z *GtElement) AddAssign(e Element) Element { return z } +func (z *GtElement) SubAssign(e Element) Element { + ee := e.(*GtElement).inner + z.inner.Div(&z.inner, &ee) + return z +} + func (z *GtElement) Add(a, b Element) Element { z.Set(a) z.AddAssign(b) return z } +func (z *GtElement) Sub(a, b Element) Element { + z.Set(a) + z.SubAssign(b) + return z +} + func (z *GtElement) MultiExp(basis []Element, scalars []fr.Element) (Element, error) { // Maybe quite naive; but it works. Prob could use some Pippenger algorithm? - z.inner = bls12381.GT{} + z.inner.SetOne() for i := 0; i < len(basis); i++ { var tmp GtElement tmp.ScalarMultiplication(basis[i], scalars[i]) diff --git a/innerproductargument/innerproductargument.go b/innerproductargument/innerproductargument.go index f3a820b..5ca449c 100644 --- a/innerproductargument/innerproductargument.go +++ b/innerproductargument/innerproductargument.go @@ -271,6 +271,13 @@ func Verify( beta.Mul(&beta, &proof.c0) scalars := append(s, beta) + AAAA := g.CreateElement() + if _, err := AAAA.MultiExp(GplusH, scalars); err != nil { + panic(err) + } + if !AAAA.Equal(AC1) { + panic("nope") + } if err := msmAccumulator.AccumulateCheck(AC1, scalars, GplusH, rand); err != nil { return false, fmt.Errorf("accumulate check 1: %s", err) } diff --git a/innerproductargument/innerproductargument_test.go b/innerproductargument/innerproductargument_test.go index e7f1b74..80aeefb 100644 --- a/innerproductargument/innerproductargument_test.go +++ b/innerproductargument/innerproductargument_test.go @@ -140,8 +140,6 @@ func setup(t *testing.T, config testConfig, n int) (CRS, group.Element, group.El crsGs_prime := make([]group.Element, n) for i := range crsGs_prime { crsGs_prime[i] = config.group.CreateElement() - } - for i := 0; i < n; i++ { crsGs_prime[i].ScalarMultiplication(crsGs[i], us[i]) } H, err := config.genRandomGroupElement(rand) From 1acab36056c39ddab932359de0f7d4f03932e0fb Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 16:03:27 -0300 Subject: [PATCH 12/21] samemultiscalarargument: use generic group backend Signed-off-by: Ignacio Hagopian --- common/rand.go | 11 +- group/gt.go | 6 +- .../samemultiscalarargument.go | 312 +++++++++--------- .../samemultiscalarargument_test.go | 200 +++++++---- 4 files changed, 299 insertions(+), 230 deletions(-) diff --git a/common/rand.go b/common/rand.go index 5cbaf89..d6f6197 100644 --- a/common/rand.go +++ b/common/rand.go @@ -114,8 +114,17 @@ func (r *Rand) GeneratePermutation(n int) ([]uint32, error) { // Experimental func (r *Rand) GetGt() (bls12381.GT, error) { + var byts [48 * 12]byte + for i := 0; i < 6; i++ { + a, err := r.GetG1Affine() + if err != nil { + return bls12381.GT{}, nil + } + abytes := a.RawBytes() + copy(byts[i*(48*2):], abytes[:]) + } var randElem bls12381.GT - if _, err := randElem.SetRandom(); err != nil { + if err := randElem.SetBytes(byts[:]); err != nil { return bls12381.GT{}, fmt.Errorf("get random GT: %s", err) } diff --git a/group/gt.go b/group/gt.go index f476f6b..c79556a 100644 --- a/group/gt.go +++ b/group/gt.go @@ -11,7 +11,9 @@ type GroupGt struct { } func (g *GroupGt) CreateElement() Element { - return &GtElement{} + res := &GtElement{} + res.inner.SetOne() + return res } // GtElement implements Elemen backed by a Gt element. @@ -53,7 +55,7 @@ func (z *GtElement) Add(a, b Element) Element { func (z *GtElement) MultiExp(basis []Element, scalars []fr.Element) (Element, error) { // Maybe quite naive; but it works. Prob could use some Pippenger algorithm? - z.inner = bls12381.GT{} + z.inner.SetOne() for i := 0; i < len(basis); i++ { var tmp GtElement tmp.ScalarMultiplication(basis[i], scalars[i]) diff --git a/samemultiscalarargument/samemultiscalarargument.go b/samemultiscalarargument/samemultiscalarargument.go index d3127eb..06a8459 100644 --- a/samemultiscalarargument/samemultiscalarargument.go +++ b/samemultiscalarargument/samemultiscalarargument.go @@ -5,10 +5,9 @@ import ( "io" "math/bits" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" ) @@ -20,27 +19,29 @@ var ( ) type Proof struct { - B_a bls12381.G1Jac - B_t bls12381.G1Jac - B_u bls12381.G1Jac + B_a group.Element + B_t group.Element + B_u group.Element - L_A []bls12381.G1Jac - L_T []bls12381.G1Jac - L_U []bls12381.G1Jac - R_A []bls12381.G1Jac - R_T []bls12381.G1Jac - R_U []bls12381.G1Jac + L_A []group.Element + L_T []group.Element + L_U []group.Element + R_A []group.Element + R_T []group.Element + R_U []group.Element x fr.Element } func Prove( - G []bls12381.G1Affine, - A bls12381.G1Jac, - Z_t bls12381.G1Jac, - Z_u bls12381.G1Jac, - T []bls12381.G1Affine, - U []bls12381.G1Affine, + g group.Group, + + G []group.Element, + A group.Element, + Z_t group.Element, + Z_u group.Element, + T []group.Element, + U []group.Element, x []fr.Element, transcript *transcript.Transcript, rand *common.Rand, @@ -48,33 +49,33 @@ func Prove( n := uint(len(x)) m := bits.Len(n) - 1 - L_Ts := make([]bls12381.G1Jac, 0, m) - R_Ts := make([]bls12381.G1Jac, 0, m) - L_Us := make([]bls12381.G1Jac, 0, m) - R_Us := make([]bls12381.G1Jac, 0, m) - L_As := make([]bls12381.G1Jac, 0, m) - R_As := make([]bls12381.G1Jac, 0, m) + L_Ts := make([]group.Element, 0, m) + R_Ts := make([]group.Element, 0, m) + L_Us := make([]group.Element, 0, m) + R_Us := make([]group.Element, 0, m) + L_As := make([]group.Element, 0, m) + R_As := make([]group.Element, 0, m) r, err := rand.GetFrs(int(n)) if err != nil { return Proof{}, fmt.Errorf("generating blinders: %s", err) } - var B_a, B_t, B_u bls12381.G1Jac - if _, err := B_a.MultiExp(G, r, common.MultiExpConf); err != nil { + B_a, B_t, B_u := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := B_a.MultiExp(G, r); err != nil { return Proof{}, fmt.Errorf("computing B_a: %s", err) } - if _, err := B_t.MultiExp(T, r, common.MultiExpConf); err != nil { + if _, err := B_t.MultiExp(T, r); err != nil { return Proof{}, fmt.Errorf("computing B_t: %s", err) } - if _, err := B_u.MultiExp(U, r, common.MultiExpConf); err != nil { + if _, err := B_u.MultiExp(U, r); err != nil { return Proof{}, fmt.Errorf("computing B_u: %s", err) } - transcript.AppendPoints(labelStep1, A, Z_t, Z_u) - transcript.AppendPointsAffine(labelStep1, T...) - transcript.AppendPointsAffine(labelStep1, U...) - transcript.AppendPoints(labelStep1, B_a, B_t, B_u) + transcript.AppendGroupElements(labelStep1, A, Z_t, Z_u) + transcript.AppendGroupElements(labelStep1, T...) + transcript.AppendGroupElements(labelStep1, U...) + transcript.AppendGroupElements(labelStep1, B_a, B_t, B_u) alpha := transcript.GetAndAppendChallenge(labelAlpha) var tmp fr.Element @@ -90,23 +91,23 @@ func Prove( U_L, U_R := common.SplitAt(U, n) G_L, G_R := common.SplitAt(G, n) - var L_A, L_T, L_U, R_A, R_T, R_U bls12381.G1Jac - if _, err := L_A.MultiExp(G_R, x_L, common.MultiExpConf); err != nil { + L_A, L_T, L_U, R_A, R_T, R_U := g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := L_A.MultiExp(G_R, x_L); err != nil { return Proof{}, fmt.Errorf("computing L_A: %s", err) } - if _, err := L_T.MultiExp(T_R, x_L, common.MultiExpConf); err != nil { + if _, err := L_T.MultiExp(T_R, x_L); err != nil { return Proof{}, fmt.Errorf("computing L_T: %s", err) } - if _, err := L_U.MultiExp(U_R, x_L, common.MultiExpConf); err != nil { + if _, err := L_U.MultiExp(U_R, x_L); err != nil { return Proof{}, fmt.Errorf("computing L_U: %s", err) } - if _, err := R_A.MultiExp(G_L, x_R, common.MultiExpConf); err != nil { + if _, err := R_A.MultiExp(G_L, x_R); err != nil { return Proof{}, fmt.Errorf("computing R_A: %s", err) } - if _, err := R_T.MultiExp(T_L, x_R, common.MultiExpConf); err != nil { + if _, err := R_T.MultiExp(T_L, x_R); err != nil { return Proof{}, fmt.Errorf("computing R_T: %s", err) } - if _, err := R_U.MultiExp(U_L, x_R, common.MultiExpConf); err != nil { + if _, err := R_U.MultiExp(U_L, x_R); err != nil { return Proof{}, fmt.Errorf("computing R_U: %s", err) } @@ -117,7 +118,7 @@ func Prove( R_Ts = append(R_Ts, R_T) R_Us = append(R_Us, R_U) - transcript.AppendPoints(labelLoop, L_A, L_T, L_U, R_A, R_T, R_U) + transcript.AppendGroupElements(labelLoop, L_A, L_T, L_U, R_A, R_T, R_U) gamma := transcript.GetAndAppendChallenge(labelGamma) if gamma.IsZero() { return Proof{}, fmt.Errorf("gamma is zero") @@ -127,11 +128,11 @@ func Prove( // Fold vectors and basis for i := 0; i < int(n); i++ { - gammaBigInt := common.FrToBigInt(&gamma) + tmp := g.CreateElement() x_L[i].Add(&x_L[i], (&fr.Element{}).Mul(&gamma_inv, &x_R[i])) - T_L[i].Add(&T_L[i], (&bls12381.G1Affine{}).ScalarMultiplication(&T_R[i], gammaBigInt)) - U_L[i].Add(&U_L[i], (&bls12381.G1Affine{}).ScalarMultiplication(&U_R[i], gammaBigInt)) - G_L[i].Add(&G_L[i], (&bls12381.G1Affine{}).ScalarMultiplication(&G_R[i], gammaBigInt)) + T_L[i].Add(T_L[i], tmp.ScalarMultiplication(T_R[i], gamma)) + U_L[i].Add(U_L[i], tmp.ScalarMultiplication(U_R[i], gamma)) + G_L[i].Add(G_L[i], tmp.ScalarMultiplication(G_R[i], gamma)) } x = x_L T = T_L @@ -157,23 +158,25 @@ func Prove( } func Verify( + g group.Group, + proof Proof, - G []bls12381.G1Affine, - A bls12381.G1Jac, - Z_t bls12381.G1Jac, - Z_u bls12381.G1Jac, - T []bls12381.G1Affine, - U []bls12381.G1Affine, + G []group.Element, + A group.Element, + Z_t group.Element, + Z_u group.Element, + T []group.Element, + U []group.Element, transcript *transcript.Transcript, - msmacc *msmaccumulator.MsmAccumulator, + msmacc *group.MsmAccumulator, rand *common.Rand, ) (bool, error) { n := len(T) - transcript.AppendPoints(labelStep1, A, Z_t, Z_u) - transcript.AppendPointsAffine(labelStep1, T...) - transcript.AppendPointsAffine(labelStep1, U...) - transcript.AppendPoints(labelStep1, proof.B_a, proof.B_t, proof.B_u) + transcript.AppendGroupElements(labelStep1, A, Z_t, Z_u) + transcript.AppendGroupElements(labelStep1, T...) + transcript.AppendGroupElements(labelStep1, U...) + transcript.AppendGroupElements(labelStep1, proof.B_a, proof.B_t, proof.B_u) alpha := transcript.GetAndAppendChallenge(labelAlpha) gamma, gamma_inv, s, err := unfoldedScalars(&proof, n, transcript) @@ -186,48 +189,49 @@ func Verify( xtimess[i].Mul(&proof.x, &s[i]) } - var A_a, Z_t_a, Z_u_a bls12381.G1Jac - A_a.Set(&proof.B_a).AddAssign((&bls12381.G1Jac{}).ScalarMultiplication(&A, common.FrToBigInt(&alpha))) - Z_t_a.Set(&proof.B_t).AddAssign((&bls12381.G1Jac{}).ScalarMultiplication(&Z_t, common.FrToBigInt(&alpha))) - Z_u_a.Set(&proof.B_u).AddAssign((&bls12381.G1Jac{}).ScalarMultiplication(&Z_u, common.FrToBigInt(&alpha))) + A_a, Z_t_a, Z_u_a := g.CreateElement(), g.CreateElement(), g.CreateElement() + tmp := g.CreateElement() + A_a.Set(proof.B_a).AddAssign(tmp.ScalarMultiplication(A, alpha)) + Z_t_a.Set(proof.B_t).AddAssign(tmp.ScalarMultiplication(Z_t, alpha)) + Z_u_a.Set(proof.B_u).AddAssign(tmp.ScalarMultiplication(Z_u, alpha)) - var l, p, r bls12381.G1Jac - L_A_Affine := bls12381.BatchJacobianToAffineG1(proof.L_A) - if _, err := l.MultiExp(L_A_Affine, gamma, common.MultiExpConf); err != nil { + l, p, r := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := l.MultiExp(proof.L_A, gamma); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - R_A_Affine := bls12381.BatchJacobianToAffineG1(proof.R_A) - if _, err := r.MultiExp(R_A_Affine, gamma_inv, common.MultiExpConf); err != nil { + if _, err := r.MultiExp(proof.R_A, gamma_inv); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - p.Set(&A_a).AddAssign(&l).AddAssign(&r) - var p_affine bls12381.G1Affine - p_affine.FromJacobian(&p) + p.Set(A_a).AddAssign(l).AddAssign(r) + + tmpCheck := g.CreateElement() + if _, err := tmpCheck.MultiExp(G, xtimess); err != nil { + panic(err) + } + if !tmpCheck.Equal(p) { + panic("wrong") + } if err := msmacc.AccumulateCheck(p, xtimess, G, rand); err != nil { return false, fmt.Errorf("accumulating msm 1: %s", err) } - L_T_Affine := bls12381.BatchJacobianToAffineG1(proof.L_T) - if _, err := l.MultiExp(L_T_Affine, gamma, common.MultiExpConf); err != nil { + if _, err := l.MultiExp(proof.L_T, gamma); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - R_T_Affine := bls12381.BatchJacobianToAffineG1(proof.R_T) - if _, err := r.MultiExp(R_T_Affine, gamma_inv, common.MultiExpConf); err != nil { + if _, err := r.MultiExp(proof.R_T, gamma_inv); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - p.Set(&Z_t_a).AddAssign(&l).AddAssign(&r) + p.Set(Z_t_a).AddAssign(l).AddAssign(r) if err := msmacc.AccumulateCheck(p, xtimess, T, rand); err != nil { return false, fmt.Errorf("accumulating msm 1: %s", err) } - L_U_Affine := bls12381.BatchJacobianToAffineG1(proof.L_U) - if _, err := l.MultiExp(L_U_Affine, gamma, common.MultiExpConf); err != nil { + if _, err := l.MultiExp(proof.L_U, gamma); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - R_U_Affine := bls12381.BatchJacobianToAffineG1(proof.R_U) - if _, err := r.MultiExp(R_U_Affine, gamma_inv, common.MultiExpConf); err != nil { + if _, err := r.MultiExp(proof.R_U, gamma_inv); err != nil { return false, fmt.Errorf("computing point_lhs msm: %s", err) } - p.Set(&Z_u_a).AddAssign(&l).AddAssign(&r) + p.Set(Z_u_a).AddAssign(l).AddAssign(r) if err := msmacc.AccumulateCheck(p, xtimess, U, rand); err != nil { return false, fmt.Errorf("accumulating msm 1: %s", err) } @@ -252,7 +256,7 @@ func unfoldedScalars( challenges := make([]fr.Element, 0, lg_n) for i := range proof.L_A { - transcript.AppendPoints( + transcript.AppendGroupElements( labelLoop, proof.L_A[i], proof.L_T[i], @@ -280,86 +284,86 @@ func unfoldedScalars( } func (p *Proof) FromReader(r io.Reader) error { - d := bls12381.NewDecoder(r) - var tmp bls12381.G1Affine - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding B_a: %s", err) - } - p.B_a.FromAffine(&tmp) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding B_t: %s", err) - } - p.B_t.FromAffine(&tmp) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding B_u: %s", err) - } - p.B_u.FromAffine(&tmp) - - if err := common.DecodeAffineSliceToJac(d, &p.L_A); err != nil { - return fmt.Errorf("decoding L_A: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.L_T); err != nil { - return fmt.Errorf("decoding L_T: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.L_U); err != nil { - return fmt.Errorf("decoding L_U: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.R_A); err != nil { - return fmt.Errorf("decoding R_A: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.R_T); err != nil { - return fmt.Errorf("decoding R_T: %s", err) - } - if err := common.DecodeAffineSliceToJac(d, &p.R_U); err != nil { - return fmt.Errorf("decoding R_U: %s", err) - } - if err := d.Decode(&p.x); err != nil { - return fmt.Errorf("decoding x: %s", err) - } + // d := bls12381.NewDecoder(r) + // var tmp bls12381.G1Affine + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding B_a: %s", err) + // } + // p.B_a.FromAffine(&tmp) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding B_t: %s", err) + // } + // p.B_t.FromAffine(&tmp) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding B_u: %s", err) + // } + // p.B_u.FromAffine(&tmp) + + // if err := common.DecodeAffineSliceToJac(d, &p.L_A); err != nil { + // return fmt.Errorf("decoding L_A: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.L_T); err != nil { + // return fmt.Errorf("decoding L_T: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.L_U); err != nil { + // return fmt.Errorf("decoding L_U: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.R_A); err != nil { + // return fmt.Errorf("decoding R_A: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.R_T); err != nil { + // return fmt.Errorf("decoding R_T: %s", err) + // } + // if err := common.DecodeAffineSliceToJac(d, &p.R_U); err != nil { + // return fmt.Errorf("decoding R_U: %s", err) + // } + // if err := d.Decode(&p.x); err != nil { + // return fmt.Errorf("decoding x: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - aff_bs := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.B_a, p.B_t, p.B_u}) - e := bls12381.NewEncoder(w) - if err := e.Encode(&aff_bs[0]); err != nil { - return fmt.Errorf("encoding B_a: %s", err) - } - if err := e.Encode(&aff_bs[1]); err != nil { - return fmt.Errorf("encoding B_t: %s", err) - } - if err := e.Encode(&aff_bs[2]); err != nil { - return fmt.Errorf("encoding B_u: %s", err) - } - affL_A := bls12381.BatchJacobianToAffineG1(p.L_A) - if err := e.Encode(affL_A); err != nil { - return fmt.Errorf("encoding L_A: %s", err) - } - affL_T := bls12381.BatchJacobianToAffineG1(p.L_T) - if err := e.Encode(affL_T); err != nil { - return fmt.Errorf("encoding L_T: %s", err) - } - affL_U := bls12381.BatchJacobianToAffineG1(p.L_U) - if err := e.Encode(affL_U); err != nil { - return fmt.Errorf("encoding L_U: %s", err) - } - affR_A := bls12381.BatchJacobianToAffineG1(p.R_A) - if err := e.Encode(affR_A); err != nil { - return fmt.Errorf("encoding R_A: %s", err) - } - affR_T := bls12381.BatchJacobianToAffineG1(p.R_T) - if err := e.Encode(affR_T); err != nil { - return fmt.Errorf("encoding R_T: %s", err) - } - affR_U := bls12381.BatchJacobianToAffineG1(p.R_U) - if err := e.Encode(affR_U); err != nil { - return fmt.Errorf("encoding R_U: %s", err) - } - if err := e.Encode(&p.x); err != nil { - return fmt.Errorf("encoding x: %s", err) - } + // aff_bs := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.B_a, p.B_t, p.B_u}) + // e := bls12381.NewEncoder(w) + // if err := e.Encode(&aff_bs[0]); err != nil { + // return fmt.Errorf("encoding B_a: %s", err) + // } + // if err := e.Encode(&aff_bs[1]); err != nil { + // return fmt.Errorf("encoding B_t: %s", err) + // } + // if err := e.Encode(&aff_bs[2]); err != nil { + // return fmt.Errorf("encoding B_u: %s", err) + // } + // affL_A := bls12381.BatchJacobianToAffineG1(p.L_A) + // if err := e.Encode(affL_A); err != nil { + // return fmt.Errorf("encoding L_A: %s", err) + // } + // affL_T := bls12381.BatchJacobianToAffineG1(p.L_T) + // if err := e.Encode(affL_T); err != nil { + // return fmt.Errorf("encoding L_T: %s", err) + // } + // affL_U := bls12381.BatchJacobianToAffineG1(p.L_U) + // if err := e.Encode(affL_U); err != nil { + // return fmt.Errorf("encoding L_U: %s", err) + // } + // affR_A := bls12381.BatchJacobianToAffineG1(p.R_A) + // if err := e.Encode(affR_A); err != nil { + // return fmt.Errorf("encoding R_A: %s", err) + // } + // affR_T := bls12381.BatchJacobianToAffineG1(p.R_T) + // if err := e.Encode(affR_T); err != nil { + // return fmt.Errorf("encoding R_T: %s", err) + // } + // affR_U := bls12381.BatchJacobianToAffineG1(p.R_U) + // if err := e.Encode(affR_U); err != nil { + // return fmt.Errorf("encoding R_U: %s", err) + // } + // if err := e.Encode(&p.x); err != nil { + // return fmt.Errorf("encoding x: %s", err) + // } return nil } diff --git a/samemultiscalarargument/samemultiscalarargument_test.go b/samemultiscalarargument/samemultiscalarargument_test.go index f21c807..14d522c 100644 --- a/samemultiscalarargument/samemultiscalarargument_test.go +++ b/samemultiscalarargument/samemultiscalarargument_test.go @@ -1,103 +1,157 @@ package samemultiscalarargument import ( - "bytes" + "fmt" "testing" + "time" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" "github.com/stretchr/testify/require" ) +type testConfig struct { + name string + group group.Group + genRandomGroupElement func(*common.Rand) (group.Element, error) +} + func TestSameMultiscalarArgument(t *testing.T) { t.Parallel() n := 128 - transcriptProver := transcript.New([]byte("same_msm")) - rand, err := common.NewRand(42) - require.NoError(t, err) - - crs_Gs, A, Z_t, Z_u, Ts, Us, xs := setup(t, n) - - proof, err := Prove( - crs_Gs, - A, - Z_t, - Z_u, - Ts, - Us, - xs, - transcriptProver, - rand, - ) - require.NoError(t, err) - - t.Run("completeness", func(t *testing.T) { - transcriptVerifier := transcript.New([]byte("same_msm")) - rand, err := common.NewRand(43) - require.NoError(t, err) - - crs_Gs, A, Z_t, Z_u, Ts, Us, _ := setup(t, n) - msmAccumulator := msmaccumulator.New() - - ok, err := Verify( - proof, - crs_Gs, - A, - Z_t, - Z_u, - Ts, - Us, - transcriptVerifier, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.True(t, ok) - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() - - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) - - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) - - require.Equal(t, expected, buf2.Bytes()) - }) + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + + transcriptProver := transcript.New([]byte("same_msm")) + rand, err := common.NewRand(42) + require.NoError(t, err) + + crs_Gs, A, Z_t, Z_u, Ts, Us, xs := setup(t, config, n) + + start := time.Now() + proof, err := Prove( + config.group, + crs_Gs, + A, + Z_t, + Z_u, + Ts, + Us, + xs, + transcriptProver, + rand, + ) + require.NoError(t, err) + fmt.Printf("Prove %s took %s\n", config.name, time.Since(start)) + + t.Run("completeness", func(t *testing.T) { + transcriptVerifier := transcript.New([]byte("same_msm")) + rand, err := common.NewRand(43) + require.NoError(t, err) + + start := time.Now() + crs_Gs, A, Z_t, Z_u, Ts, Us, _ := setup(t, config, n) + msmAccumulator := group.NewMsmAccumulator(config.group) + + ok, err := Verify( + config.group, + proof, + crs_Gs, + A, + Z_t, + Z_u, + Ts, + Us, + transcriptVerifier, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) + + startMsmVerif := time.Now() + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.True(t, ok) + fmt.Printf("Verify %s took %s (%s+%s)\n", config.name, time.Since(start), startMsmVerif.Sub(start), time.Since(startMsmVerif)) + }) + }) + } + + // t.Run("encode/decode", func(t *testing.T) { + // buf := bytes.NewBuffer(nil) + // require.NoError(t, proof.Serialize(buf)) + // expected := buf.Bytes() + + // var proof2 Proof + // require.NoError(t, proof2.FromReader(buf)) + + // buf2 := bytes.NewBuffer(nil) + // require.NoError(t, proof2.Serialize(buf2)) + + // require.Equal(t, expected, buf2.Bytes()) + // }) } -func setup(t *testing.T, n int) ([]bls12381.G1Affine, bls12381.G1Jac, bls12381.G1Jac, bls12381.G1Jac, []bls12381.G1Affine, []bls12381.G1Affine, []fr.Element) { +func setup(t *testing.T, config testConfig, n int) ([]group.Element, group.Element, group.Element, group.Element, []group.Element, []group.Element, []fr.Element) { rand, err := common.NewRand(0) require.NoError(t, err) - crs_Gs, err := rand.GetG1Affines(n) - require.NoError(t, err) - Ts, err := rand.GetG1Affines(n) - require.NoError(t, err) - Us, err := rand.GetG1Affines(n) - require.NoError(t, err) + crs_Gs := make([]group.Element, n) + for i := range crs_Gs { + crs_Gs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + Ts := make([]group.Element, n) + for i := range Ts { + Ts[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + Us := make([]group.Element, n) + for i := range Us { + Us[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } xs, err := rand.GetFrs(n) require.NoError(t, err) - var A, Z_t, Z_u bls12381.G1Jac - _, err = A.MultiExp(crs_Gs, xs, common.MultiExpConf) + A, Z_t, Z_u := config.group.CreateElement(), config.group.CreateElement(), config.group.CreateElement() + _, err = A.MultiExp(crs_Gs, xs) require.NoError(t, err) - _, err = Z_t.MultiExp(Ts, xs, common.MultiExpConf) + _, err = Z_t.MultiExp(Ts, xs) require.NoError(t, err) - _, err = Z_u.MultiExp(Us, xs, common.MultiExpConf) + _, err = Z_u.MultiExp(Us, xs) require.NoError(t, err) return crs_Gs, A, Z_t, Z_u, Ts, Us, xs From b66501f25169b0b24bedb6cc1e0bd8508853e68e Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 16:07:53 -0300 Subject: [PATCH 13/21] remove debug code Signed-off-by: Ignacio Hagopian --- .../grandproductargument_test.go | 27 ++++++++++--------- innerproductargument/innerproductargument.go | 7 ----- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/grandproductargument/grandproductargument_test.go b/grandproductargument/grandproductargument_test.go index 8a14377..9f1dedb 100644 --- a/grandproductargument/grandproductargument_test.go +++ b/grandproductargument/grandproductargument_test.go @@ -3,6 +3,7 @@ package grandproductargument import ( "testing" + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/group" @@ -21,19 +22,19 @@ func TestCompletenessAndSoundess(t *testing.T) { n := 128 configs := []testConfig{ - // { - // name: "G1", - // group: &group.GroupG1{}, - // genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { - // randG1Aff, err := rand.GetG1Affine() - // if err != nil { - // return nil, err - // } - // var randG1Jac bls12381.G1Jac - // randG1Jac.FromAffine(&randG1Aff) - // return group.FromG1Jac(randG1Jac), nil - // }, - // }, + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, { name: "Gt", group: &group.GroupGt{}, diff --git a/innerproductargument/innerproductargument.go b/innerproductargument/innerproductargument.go index 5ca449c..f3a820b 100644 --- a/innerproductargument/innerproductargument.go +++ b/innerproductargument/innerproductargument.go @@ -271,13 +271,6 @@ func Verify( beta.Mul(&beta, &proof.c0) scalars := append(s, beta) - AAAA := g.CreateElement() - if _, err := AAAA.MultiExp(GplusH, scalars); err != nil { - panic(err) - } - if !AAAA.Equal(AC1) { - panic("nope") - } if err := msmAccumulator.AccumulateCheck(AC1, scalars, GplusH, rand); err != nil { return false, fmt.Errorf("accumulate check 1: %s", err) } From 220deaa15f5a886713937c25461e5e92d20c2da0 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 16:09:57 -0300 Subject: [PATCH 14/21] grandproductargument: fixes Signed-off-by: Ignacio Hagopian --- grandproductargument/grandproductargument_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/grandproductargument/grandproductargument_test.go b/grandproductargument/grandproductargument_test.go index 9f1dedb..6221c46 100644 --- a/grandproductargument/grandproductargument_test.go +++ b/grandproductargument/grandproductargument_test.go @@ -1,7 +1,9 @@ package grandproductargument import ( + "fmt" "testing" + "time" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" @@ -48,11 +50,10 @@ func TestCompletenessAndSoundess(t *testing.T) { }, } - rand, err := common.NewRand(0) - require.NoError(t, err) - for _, config := range configs { t.Run(config.name, func(t *testing.T) { + rand, err := common.NewRand(0) + require.NoError(t, err) var proof Proof { @@ -93,6 +94,7 @@ func TestCompletenessAndSoundess(t *testing.T) { require.NoError(t, err) B.AddAssign(B_L).AddAssign(B_R) + start := time.Now() proof, err = Prove( config.group, crs, @@ -104,10 +106,12 @@ func TestCompletenessAndSoundess(t *testing.T) { rand, ) require.NoError(t, err) + fmt.Printf("Prove %s took %s\n", config.name, time.Since(start)) } t.Run("completeness", func(t *testing.T) { crs, Gsum, Hsum, B, result, transcriptVerifier, msmAccumulator := genVerifierParameters(t, config, n) + start := time.Now() ok, err := Verify( config.group, proof, @@ -124,9 +128,11 @@ func TestCompletenessAndSoundess(t *testing.T) { require.NoError(t, err) require.True(t, ok) + startMsmVerif := time.Now() ok, err = msmAccumulator.Verify() require.NoError(t, err) require.True(t, ok) + fmt.Printf("Verify %s took %s (%s+%s)\n", config.name, time.Since(start), startMsmVerif.Sub(start), time.Since(startMsmVerif)) }) t.Run("soundness - wrong result", func(t *testing.T) { From 207067c17621fae62a5a78637a53111e93430248 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 16:20:06 -0300 Subject: [PATCH 15/21] samepermutationargument: migrate to generic backend Signed-off-by: Ignacio Hagopian --- .../samepermutationargument.go | 91 ++++---- .../samepermutationargument_test.go | 208 +++++++++++------- 2 files changed, 177 insertions(+), 122 deletions(-) diff --git a/samepermutationargument/samepermutationargument.go b/samepermutationargument/samepermutationargument.go index ef95f56..440142d 100644 --- a/samepermutationargument/samepermutationargument.go +++ b/samepermutationargument/samepermutationargument.go @@ -4,11 +4,10 @@ import ( "fmt" "io" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/grandproductargument" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" ) @@ -19,20 +18,22 @@ var ( ) type CRS struct { - Gs []bls12381.G1Affine - Hs []bls12381.G1Affine - H bls12381.G1Jac + Gs []group.Element + Hs []group.Element + H group.Element } type Proof struct { - B bls12381.G1Jac + B group.Element gpaProof grandproductargument.Proof } func Prove( + g group.Group, + crs CRS, - A bls12381.G1Jac, - M bls12381.G1Jac, + A group.Element, + M group.Element, as []fr.Element, permutation []uint32, rs_a []fr.Element, @@ -41,7 +42,7 @@ func Prove( rand *common.Rand, ) (Proof, error) { // Step 1 - transcript.AppendPoints(labelStep1, A, M) + transcript.AppendGroupElements(labelStep1, A, M) transcript.AppendScalars(labelStep1, as...) alpha := transcript.GetAndAppendChallenge(labelAlpha) beta := transcript.GetAndAppendChallenge(labelBeta) @@ -63,14 +64,14 @@ func Prove( for i := range betas { betas[i] = beta } - var msmBetasGs bls12381.G1Jac - if _, err := msmBetasGs.MultiExp(crs.Gs, betas, common.MultiExpConf); err != nil { + msmBetasGs := g.CreateElement() + if _, err := msmBetasGs.MultiExp(crs.Gs, betas); err != nil { return Proof{}, fmt.Errorf("failed to compute msm(Bs, Gs): %s", err) } - var alphaM bls12381.G1Jac - alphaM.ScalarMultiplication(&M, common.FrToBigInt(&alpha)) - var B bls12381.G1Jac - B.Set(&A).AddAssign(&alphaM).AddAssign(&msmBetasGs) + alphaM := g.CreateElement() + alphaM.ScalarMultiplication(M, alpha) + B := g.CreateElement() + B.Set(A).AddAssign(alphaM).AddAssign(msmBetasGs) rs_b := make([]fr.Element, len(rs_a)) for i := range rs_b { @@ -78,6 +79,7 @@ func Prove( } gpaproof, err := grandproductargument.Prove( + g, grandproductargument.CRS{ Gs: crs.Gs, Hs: crs.Hs, @@ -101,22 +103,24 @@ func Prove( } func Verify( + g group.Group, + proof Proof, crs CRS, - Gsum bls12381.G1Affine, - Hsum bls12381.G1Affine, - A bls12381.G1Jac, - M bls12381.G1Jac, + Gsum group.Element, + Hsum group.Element, + A group.Element, + M group.Element, as []fr.Element, numBlinders int, transcript *transcript.Transcript, - msmAccumulator *msmaccumulator.MsmAccumulator, + msmAccumulator *group.MsmAccumulator, rand *common.Rand, ) (bool, error) { // Step 1 // TODO(jsign): double check FS since doesn't seem to match paper. - transcript.AppendPoints(labelStep1, A, M) + transcript.AppendGroupElements(labelStep1, A, M) transcript.AppendScalars(labelStep1, as...) alpha := transcript.GetAndAppendChallenge(labelAlpha) beta := transcript.GetAndAppendChallenge(labelBeta) @@ -133,15 +137,16 @@ func Verify( for i := range betas { betas[i] = beta } - var C bls12381.G1Jac - var alphaM bls12381.G1Jac - alphaM.ScalarMultiplication(&M, common.FrToBigInt(&alpha)) - C.Set(&proof.B).SubAssign(&A).SubAssign(&alphaM) + C := g.CreateElement() + alphaM := g.CreateElement() + alphaM.ScalarMultiplication(M, alpha) + C.Set(proof.B).SubAssign(A).SubAssign(alphaM) if err := msmAccumulator.AccumulateCheck(C, betas, crs.Gs, rand); err != nil { return false, fmt.Errorf("failed to accumulate check: %s", err) } ok, err := grandproductargument.Verify( + g, proof.gpaProof, grandproductargument.CRS{ Gs: crs.Gs, @@ -164,29 +169,29 @@ func Verify( } func (p *Proof) FromReader(r io.Reader) error { - var tmp bls12381.G1Affine - d := bls12381.NewDecoder(r) + // var tmp bls12381.G1Affine + // d := bls12381.NewDecoder(r) - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("failed to decode B: %s", err) - } - p.B.FromAffine(&tmp) + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("failed to decode B: %s", err) + // } + // p.B.FromAffine(&tmp) - if err := p.gpaProof.FromReader(r); err != nil { - return fmt.Errorf("failed to decode GPA proof: %s", err) - } + // if err := p.gpaProof.FromReader(r); err != nil { + // return fmt.Errorf("failed to decode GPA proof: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - e := bls12381.NewEncoder(w) - var bAffine bls12381.G1Affine - bAffine.FromJacobian(&p.B) - if err := e.Encode(&bAffine); err != nil { - return fmt.Errorf("failed to encode B: %s", err) - } - if err := p.gpaProof.Serialize(w); err != nil { - return fmt.Errorf("failed to encode GPA proof: %s", err) - } + // e := bls12381.NewEncoder(w) + // var bAffine bls12381.G1Affine + // bAffine.FromJacobian(&p.B) + // if err := e.Encode(&bAffine); err != nil { + // return fmt.Errorf("failed to encode B: %s", err) + // } + // if err := p.gpaProof.Serialize(w); err != nil { + // return fmt.Errorf("failed to encode GPA proof: %s", err) + // } return nil } diff --git a/samepermutationargument/samepermutationargument_test.go b/samepermutationargument/samepermutationargument_test.go index 6e52f42..1cc40ae 100644 --- a/samepermutationargument/samepermutationargument_test.go +++ b/samepermutationargument/samepermutationargument_test.go @@ -1,101 +1,151 @@ package samepermutationargument import ( - "bytes" + "fmt" "testing" + "time" mrand "math/rand" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/transcript" "github.com/stretchr/testify/require" ) +type testConfig struct { + name string + group group.Group + genRandomGroupElement func(*common.Rand) (group.Element, error) +} + func TestSamePermutationArgument(t *testing.T) { t.Parallel() n := 128 + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + + rand, err := common.NewRand(0) + require.NoError(t, err) + + crs, A, M, as, perm, rs_a, rs_m := setup(t, config, n) + start := time.Now() + transcriptProver := transcript.New([]byte("sameperm")) + proof, err := Prove( + config.group, + crs, + A, + M, + as, + perm, + rs_a, + rs_m, + transcriptProver, + rand, + ) + require.NoError(t, err) + fmt.Printf("Prove %s took %s\n", config.name, time.Since(start)) + + t.Run("completeness", func(t *testing.T) { + crs, A, M, as, _, _, _ := setup(t, config, n) + transcriptVerifier := transcript.New([]byte("sameperm")) + msmAccumulator := group.NewMsmAccumulator(config.group) + + Gsum := config.group.CreateElement() + for _, g := range crs.Gs { + Gsum.Add(Gsum, g) + } + Hsum := config.group.CreateElement() + for _, h := range crs.Hs { + Hsum.Add(Hsum, h) + } + + start := time.Now() + ok, err := Verify( + config.group, + proof, + crs, + Gsum, + Hsum, + A, + M, + as, + common.N_BLINDERS, + transcriptVerifier, + msmAccumulator, + rand, + ) + require.NoError(t, err) + require.True(t, ok) + + startMsmVerif := time.Now() + ok, err = msmAccumulator.Verify() + require.NoError(t, err) + require.True(t, ok) + fmt.Printf("Verify %s took %s (%s+%s)\n", config.name, time.Since(start), startMsmVerif.Sub(start), time.Since(startMsmVerif)) + }) + }) + } - rand, err := common.NewRand(0) - require.NoError(t, err) - - crs, A, M, as, perm, rs_a, rs_m := setup(t, n) - transcriptProver := transcript.New([]byte("sameperm")) - proof, err := Prove( - crs, - A, - M, - as, - perm, - rs_a, - rs_m, - transcriptProver, - rand, - ) - require.NoError(t, err) - - t.Run("completeness", func(t *testing.T) { - crs, A, M, as, _, _, _ := setup(t, n) - transcriptVerifier := transcript.New([]byte("sameperm")) - msmAccumulator := msmaccumulator.New() - - var Gsum bls12381.G1Affine - for _, g := range crs.Gs { - Gsum.Add(&Gsum, &g) - } - var Hsum bls12381.G1Affine - for _, h := range crs.Hs { - Hsum.Add(&Hsum, &h) - } - - ok, err := Verify( - proof, - crs, - Gsum, - Hsum, - A, - M, - as, - common.N_BLINDERS, - transcriptVerifier, - msmAccumulator, - rand, - ) - require.NoError(t, err) - require.True(t, ok) - - ok, err = msmAccumulator.Verify() - require.NoError(t, err) - require.True(t, ok) - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() + // t.Run("encode/decode", func(t *testing.T) { + // buf := bytes.NewBuffer(nil) + // require.NoError(t, proof.Serialize(buf)) + // expected := buf.Bytes() - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) + // var proof2 Proof + // require.NoError(t, proof2.FromReader(buf)) - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) + // buf2 := bytes.NewBuffer(nil) + // require.NoError(t, proof2.Serialize(buf2)) - require.Equal(t, expected, buf2.Bytes()) - }) + // require.Equal(t, expected, buf2.Bytes()) + // }) } -func setup(t *testing.T, n int) (CRS, bls12381.G1Jac, bls12381.G1Jac, []fr.Element, []uint32, []fr.Element, []fr.Element) { +func setup(t *testing.T, config testConfig, n int) (CRS, group.Element, group.Element, []fr.Element, []uint32, []fr.Element, []fr.Element) { rand, err := common.NewRand(0) require.NoError(t, err) - crsGs, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - crsHs, err := rand.GetG1Affines(common.N_BLINDERS) - require.NoError(t, err) - crsH, err := rand.GetG1Jac() + crsGs := make([]group.Element, n-common.N_BLINDERS) + for i := range crsGs { + crsGs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsHs := make([]group.Element, common.N_BLINDERS) + for i := range crsHs { + crsHs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + crsH, err := config.genRandomGroupElement(rand) require.NoError(t, err) crs := CRS{ Gs: crsGs, @@ -123,19 +173,19 @@ func setup(t *testing.T, n int) (CRS, bls12381.G1Jac, bls12381.G1Jac, []fr.Eleme require.NoError(t, err) permAs := common.Permute(as, perm) - var A, A_L, A_R bls12381.G1Jac - _, err = A_L.MultiExp(crsGs, permAs, common.MultiExpConf) + A, A_L, A_R := config.group.CreateElement(), config.group.CreateElement(), config.group.CreateElement() + _, err = A_L.MultiExp(crsGs, permAs) require.NoError(t, err) - _, err = A_R.MultiExp(crsHs, rs_a, common.MultiExpConf) + _, err = A_R.MultiExp(crsHs, rs_a) require.NoError(t, err) - A.Set(&A_L).AddAssign(&A_R) + A.Set(A_L).AddAssign(A_R) - var M, M_L, M_R bls12381.G1Jac - _, err = M_L.MultiExp(crsGs, permFrs, common.MultiExpConf) + M, M_L, M_R := config.group.CreateElement(), config.group.CreateElement(), config.group.CreateElement() + _, err = M_L.MultiExp(crsGs, permFrs) require.NoError(t, err) - _, err = M_R.MultiExp(crsHs, rs_m, common.MultiExpConf) + _, err = M_R.MultiExp(crsHs, rs_m) require.NoError(t, err) - M.Set(&M_L).AddAssign(&M_R) + M.Set(M_L).AddAssign(M_R) return crs, A, M, as, perm, rs_a, rs_m } From 829c17940a7b0af64c49ddec264bb05dd1721a2c Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 20:47:08 -0300 Subject: [PATCH 16/21] curdleproofs: make progress in generic backend Signed-off-by: Ignacio Hagopian --- common/util.go | 46 ----- crs.go | 50 +++-- curdleproof.go | 328 ++++++++++++++++++------------- curdleproof_test.go | 470 ++++++++++++++++++++++++-------------------- utils/utils.go | 57 ++++++ whisk/whisk.go | 184 ++++++++--------- whisk/whisk_test.go | 110 +++++------ 7 files changed, 682 insertions(+), 563 deletions(-) create mode 100644 utils/utils.go diff --git a/common/util.go b/common/util.go index bc2eb77..558ff6c 100644 --- a/common/util.go +++ b/common/util.go @@ -2,7 +2,6 @@ package common import ( "errors" - "fmt" "math/big" "runtime" @@ -42,51 +41,6 @@ func Permute[T any](vs []T, perm []uint32) []T { return ret } -func ShufflePermuteCommit( - crsGs []bls12381.G1Affine, - crsHs []bls12381.G1Affine, - Rs []bls12381.G1Affine, - Ss []bls12381.G1Affine, - perm []uint32, - k fr.Element, - rand *Rand, -) ([]bls12381.G1Affine, []bls12381.G1Affine, bls12381.G1Jac, []fr.Element, error) { - biK := FrToBigInt(&k) - Ts := make([]bls12381.G1Affine, len(Rs)) - for i := range Ts { - Ts[i].ScalarMultiplication(&Rs[i], biK) - } - - Us := make([]bls12381.G1Affine, len(Ss)) - for i := range Us { - Us[i].ScalarMultiplication(&Ss[i], biK) - } - - Ts = Permute(Ts, perm) - Us = Permute(Us, perm) - - rangeFrs := make([]fr.Element, len(crsGs)) - for i := range perm { - rangeFrs[i] = fr.NewElement(uint64(i)) - } - - permRangeFrs := Permute(rangeFrs, perm) - var M, M2 bls12381.G1Jac - if _, err := M.MultiExp(crsGs, permRangeFrs, MultiExpConf); err != nil { - return nil, nil, bls12381.G1Jac{}, nil, fmt.Errorf("calculating M_1: %s", err) - } - rs_m, err := rand.GetFrs(N_BLINDERS) - if err != nil { - return nil, nil, bls12381.G1Jac{}, nil, fmt.Errorf("getting rs_m: %s", err) - } - if _, err := M2.MultiExp(crsHs, rs_m, MultiExpConf); err != nil { - return nil, nil, bls12381.G1Jac{}, nil, fmt.Errorf("calculating M_2: %s", err) - } - M.AddAssign(&M2) - - return Ts, Us, M, rs_m, nil -} - func DecodeAffineSliceToJac(d *bls12381.Decoder, out *[]bls12381.G1Jac) error { var affs []bls12381.G1Affine if err := d.Decode(&affs); err != nil { diff --git a/crs.go b/crs.go index 06bbdf4..aafee1b 100644 --- a/crs.go +++ b/crs.go @@ -3,48 +3,62 @@ package curdleproof import ( "fmt" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/jsign/curdleproofs/common" + "github.com/jsign/curdleproofs/group" ) type CRS struct { - Gs []bls12381.G1Affine - Hs []bls12381.G1Affine - H bls12381.G1Jac - Gt bls12381.G1Jac - Gu bls12381.G1Jac - Gsum bls12381.G1Affine - Hsum bls12381.G1Affine + Gs []group.Element + Hs []group.Element + H group.Element + Gt group.Element + Gu group.Element + Gsum group.Element + Hsum group.Element } -func GenerateCRS(size int, rand *common.Rand) (CRS, error) { - gs, err := rand.GetG1Affines(size) +// TODO: Clean up API if generic backend is used. +func GenerateCRS(size int, g group.Group, genRandGroupElement func() (group.Element, error)) (CRS, error) { + var err error + gs := make([]group.Element, size) + for i := range gs { + gs[i], err = genRandGroupElement() + if err != nil { + return CRS{}, fmt.Errorf("gen gs: %s", err) + } + } if err != nil { return CRS{}, fmt.Errorf("gen gs: %s", err) } - hs, err := rand.GetG1Affines(common.N_BLINDERS) + hs := make([]group.Element, common.N_BLINDERS) + for i := range hs { + hs[i], err = genRandGroupElement() + if err != nil { + return CRS{}, fmt.Errorf("gen hs: %s", err) + } + } if err != nil { return CRS{}, fmt.Errorf("gen hs: %s", err) } - h, err := rand.GetG1Jac() + h, err := genRandGroupElement() if err != nil { return CRS{}, fmt.Errorf("gen h: %s", err) } - gt, err := rand.GetG1Jac() + gt, err := genRandGroupElement() if err != nil { return CRS{}, fmt.Errorf("gen gt: %s", err) } - gu, err := rand.GetG1Jac() + gu, err := genRandGroupElement() if err != nil { return CRS{}, fmt.Errorf("gen gu: %s", err) } - var gsum bls12381.G1Affine + gsum := g.CreateElement() for _, g := range gs { - gsum.Add(&gsum, &g) + gsum.Add(gsum, g) } - var hsum bls12381.G1Affine + hsum := g.CreateElement() for _, h := range hs { - hsum.Add(&hsum, &h) + hsum.Add(hsum, h) } return CRS{ diff --git a/curdleproof.go b/curdleproof.go index 9493558..5d01dc8 100644 --- a/curdleproof.go +++ b/curdleproof.go @@ -7,8 +7,7 @@ import ( bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" - "github.com/jsign/curdleproofs/groupcommitment" - "github.com/jsign/curdleproofs/msmaccumulator" + "github.com/jsign/curdleproofs/group" "github.com/jsign/curdleproofs/samemultiscalarargument" "github.com/jsign/curdleproofs/samepermutationargument" "github.com/jsign/curdleproofs/samescalarargument" @@ -25,23 +24,25 @@ var ( ) type Proof struct { - A bls12381.G1Jac - T groupcommitment.GroupCommitment - U groupcommitment.GroupCommitment - R bls12381.G1Jac - S bls12381.G1Jac + A group.Element + T group.GroupCommitment + U group.GroupCommitment + R group.Element + S group.Element proofSamePermutation samepermutationargument.Proof proofSameScalar samescalarargument.Proof proofSameMultiscalar samemultiscalarargument.Proof } func Prove( + g group.Group, + crs CRS, - Rs []bls12381.G1Affine, - Ss []bls12381.G1Affine, - Ts []bls12381.G1Affine, - Us []bls12381.G1Affine, - M bls12381.G1Jac, + Rs []group.Element, + Ss []group.Element, + Ts []group.Element, + Us []group.Element, + M group.Element, perm []uint32, k fr.Element, rs_m []fr.Element, @@ -50,11 +51,11 @@ func Prove( transcript := transcript.New(labelTranscript) // Step 1 - transcript.AppendPointsAffine(labelStep1, Rs...) - transcript.AppendPointsAffine(labelStep1, Ss...) - transcript.AppendPointsAffine(labelStep1, Ts...) - transcript.AppendPointsAffine(labelStep1, Us...) - transcript.AppendPoints(labelStep1, M) + transcript.AppendGroupElements(labelStep1, Rs...) + transcript.AppendGroupElements(labelStep1, Ss...) + transcript.AppendGroupElements(labelStep1, Ts...) + transcript.AppendGroupElements(labelStep1, Us...) + transcript.AppendGroupElements(labelStep1, M) as := transcript.GetAndAppendChallenges(labelVecA, len(Rs)) // Step 2 @@ -69,16 +70,17 @@ func Prove( perm_as := common.Permute(as, perm) - var A, A_L, A_R bls12381.G1Jac - if _, err := A_L.MultiExp(crs.Gs, perm_as, common.MultiExpConf); err != nil { + A, A_L, A_R := g.CreateElement(), g.CreateElement(), g.CreateElement() + if _, err := A_L.MultiExp(crs.Gs, perm_as); err != nil { return Proof{}, fmt.Errorf("computing A_L: %s", err) } - if _, err := A_R.MultiExp(crs.Hs, rs_a_prime, common.MultiExpConf); err != nil { + if _, err := A_R.MultiExp(crs.Hs, rs_a_prime); err != nil { return Proof{}, fmt.Errorf("computing A_R: %s", err) } - A.Set(&A_L).AddAssign(&A_R) + A.Set(A_L).AddAssign(A_R) proofSamePerm, err := samepermutationargument.Prove( + g, samepermutationargument.CRS{ Gs: crs.Gs, Hs: crs.Hs, @@ -106,23 +108,24 @@ func Prove( if err != nil { return Proof{}, fmt.Errorf("getting random r_u: %s", err) } - var R bls12381.G1Jac - if _, err := R.MultiExp(Rs, as, common.MultiExpConf); err != nil { + R := g.CreateElement() + if _, err := R.MultiExp(Rs, as); err != nil { return Proof{}, fmt.Errorf("computing R: %s", err) } - var S bls12381.G1Jac - if _, err := S.MultiExp(Ss, as, common.MultiExpConf); err != nil { + S := g.CreateElement() + if _, err := S.MultiExp(Ss, as); err != nil { return Proof{}, fmt.Errorf("computing S: %s", err) } - var tmp bls12381.G1Jac - tmp.ScalarMultiplication(&R, common.FrToBigInt(&k)) - T := groupcommitment.New(crs.Gt, crs.H, tmp, r_t) - tmp.ScalarMultiplication(&S, common.FrToBigInt(&k)) - U := groupcommitment.New(crs.Gu, crs.H, tmp, r_u) + tmp := g.CreateElement() + tmp.ScalarMultiplication(R, k) + T := group.NewGroupCommitment(g, crs.Gt, crs.H, tmp, r_t) + tmp.ScalarMultiplication(S, k) + U := group.NewGroupCommitment(g, crs.Gu, crs.H, tmp, r_u) // TODO(jsign): enforce assumption in callees about mutation of parameters. proofSameScalar, err := samescalarargument.Prove( + g, samescalarargument.CRS{ Gt: crs.Gt, Gu: crs.Gu, @@ -143,26 +146,46 @@ func Prove( } // Step 4 - A_prime := A - A_prime.AddAssign(&T.T_1) - A_prime.AddAssign(&U.T_1) - - G := make([]bls12381.G1Affine, 0, len(crs.Gs)+(common.N_BLINDERS-2)+1+1) - G = append(G, crs.Gs...) - G = append(G, crs.Hs[:common.N_BLINDERS-2]...) - gxaffine := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{crs.Gt, crs.Gu}) - G = append(G, gxaffine...) - - T_prime := make([]bls12381.G1Affine, 0, len(Ts)+2+1+1) - T_prime = append(T_prime, Ts...) - var crsHAffine bls12381.G1Affine - crsHAffine.FromJacobian(&crs.H) - T_prime = append(T_prime, zeroPoint, zeroPoint, crsHAffine, zeroPoint) - - U_prime := make([]bls12381.G1Affine, 0, len(Us)+2+1+1) - U_prime = append(U_prime, Us...) - U_prime = append(U_prime, zeroPoint, zeroPoint, zeroPoint) - U_prime = append(U_prime, crsHAffine) + A_prime := g.CreateElement() + A_prime.Set(A) + A_prime.AddAssign(T.T_1) + A_prime.AddAssign(U.T_1) + + G := make([]group.Element, len(crs.Gs)+(common.N_BLINDERS-2)+1+1) + for i := range crs.Gs { + G[i] = g.CreateElement() + G[i].Set(crs.Gs[i]) + } + for i := 0; i < len(crs.Hs)-2; i++ { + G[i+len(crs.Gs)] = g.CreateElement() + G[i+len(crs.Gs)].Set(crs.Hs[i]) + } + G[len(G)-2] = g.CreateElement() + G[len(G)-2].Set(crs.Gt) + G[len(G)-1] = g.CreateElement() + G[len(G)-1].Set(crs.Gu) + + T_prime := make([]group.Element, len(Ts)+2+1+1) + for i := range Ts { + T_prime[i] = g.CreateElement() + T_prime[i].Set(Ts[i]) + } + T_prime[len(T_prime)-4] = g.CreateElement() + T_prime[len(T_prime)-3] = g.CreateElement() + T_prime[len(T_prime)-2] = g.CreateElement() + T_prime[len(T_prime)-2].Set(crs.H) + T_prime[len(T_prime)-1] = g.CreateElement() + + U_prime := make([]group.Element, len(Us)+2+1+1) + for i := range Us { + U_prime[i] = g.CreateElement() + U_prime[i].Set(Us[i]) + } + U_prime[len(U_prime)-4] = g.CreateElement() + U_prime[len(U_prime)-3] = g.CreateElement() + U_prime[len(U_prime)-2] = g.CreateElement() + U_prime[len(U_prime)-1] = g.CreateElement() + U_prime[len(U_prime)-1].Set(crs.H) x := make([]fr.Element, 0, len(perm_as)+len(rs_a)+1+1) x = append(x, perm_as...) @@ -170,6 +193,7 @@ func Prove( x = append(x, r_t, r_u) proofSameMultiscalar, err := samemultiscalarargument.Prove( + g, G, A_prime, T.T_2, @@ -197,33 +221,36 @@ func Prove( } func Verify( + g group.Group, + proof Proof, crs CRS, - Rs []bls12381.G1Affine, - Ss []bls12381.G1Affine, - Ts []bls12381.G1Affine, - Us []bls12381.G1Affine, - M bls12381.G1Jac, + Rs []group.Element, + Ss []group.Element, + Ts []group.Element, + Us []group.Element, + M group.Element, rand *common.Rand, ) (bool, error) { transcript := transcript.New(labelTranscript) - msmAccumulator := msmaccumulator.New() + msmAccumulator := group.NewMsmAccumulator(g) // Make sure that randomizer was not the zero element (and wiped out the ciphertexts) - if Ts[0].IsInfinity() { + if Ts[0].Equal(g.CreateElement()) { return false, fmt.Errorf("randomizer is zero") } // Step 1 - transcript.AppendPointsAffine(labelStep1, Rs...) - transcript.AppendPointsAffine(labelStep1, Ss...) - transcript.AppendPointsAffine(labelStep1, Ts...) - transcript.AppendPointsAffine(labelStep1, Us...) - transcript.AppendPoints(labelStep1, M) + transcript.AppendGroupElements(labelStep1, Rs...) + transcript.AppendGroupElements(labelStep1, Ss...) + transcript.AppendGroupElements(labelStep1, Ts...) + transcript.AppendGroupElements(labelStep1, Us...) + transcript.AppendGroupElements(labelStep1, M) as := transcript.GetAndAppendChallenges(labelVecA, len(Rs)) // Step 2 ok, err := samepermutationargument.Verify( + g, proof.proofSamePermutation, samepermutationargument.CRS{ Gs: crs.Gs, @@ -249,6 +276,7 @@ func Verify( // Step 3 if ok := samescalarargument.Verify( + g, proof.proofSameScalar, samescalarargument.CRS{ Gt: crs.Gt, @@ -265,26 +293,48 @@ func Verify( } // Step 4 - Aprime := proof.A - Aprime.AddAssign(&proof.T.T_1).AddAssign(&proof.U.T_1) - - Gs := make([]bls12381.G1Affine, 0, len(crs.Gs)+(common.N_BLINDERS-2)+1+1) - Gs = append(Gs, crs.Gs...) - Gs = append(Gs, crs.Hs[:common.N_BLINDERS-2]...) - gaffs := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{crs.Gt, crs.Gu}) - Gs = append(Gs, gaffs...) - - Tsprime := make([]bls12381.G1Affine, 0, len(Ts)+2+1+1) - Tsprime = append(Tsprime, Ts...) - var HAff bls12381.G1Affine - HAff.FromJacobian(&crs.H) - Tsprime = append(Tsprime, zeroPoint, zeroPoint, HAff, zeroPoint) - - Usprime := make([]bls12381.G1Affine, 0, len(Us)+2+1+1) - Usprime = append(Usprime, Us...) - Usprime = append(Usprime, zeroPoint, zeroPoint, zeroPoint, HAff) + Aprime := g.CreateElement() + Aprime.Set(proof.A) + Aprime.AddAssign(proof.T.T_1).AddAssign(proof.U.T_1) + + Gs := make([]group.Element, len(crs.Gs)+(common.N_BLINDERS-2)+1+1) + for i := range crs.Gs { + Gs[i] = g.CreateElement() + Gs[i].Set(crs.Gs[i]) + } + for i := 0; i < len(crs.Hs)-2; i++ { + Gs[i+len(crs.Gs)] = g.CreateElement() + Gs[i+len(crs.Gs)].Set(crs.Hs[i]) + } + Gs[len(Gs)-2] = g.CreateElement() + Gs[len(Gs)-2].Set(crs.Gt) + Gs[len(Gs)-1] = g.CreateElement() + Gs[len(Gs)-1].Set(crs.Gu) + + Tsprime := make([]group.Element, len(Ts)+2+1+1) + for i := range Ts { + Tsprime[i] = g.CreateElement() + Tsprime[i].Set(Ts[i]) + } + Tsprime[len(Tsprime)-4] = g.CreateElement() + Tsprime[len(Tsprime)-3] = g.CreateElement() + Tsprime[len(Tsprime)-2] = g.CreateElement() + Tsprime[len(Tsprime)-2] = crs.H + Tsprime[len(Tsprime)-1] = g.CreateElement() + + Usprime := make([]group.Element, len(Us)+2+1+1) + for i := range Us { + Usprime[i] = g.CreateElement() + Usprime[i].Set(Us[i]) + } + Usprime[len(Usprime)-4] = g.CreateElement() + Usprime[len(Usprime)-3] = g.CreateElement() + Usprime[len(Usprime)-2] = g.CreateElement() + Usprime[len(Usprime)-1] = g.CreateElement() + Usprime[len(Usprime)-1] = crs.H ok, err = samemultiscalarargument.Verify( + g, proof.proofSameMultiscalar, Gs, Aprime, @@ -318,70 +368,70 @@ func Verify( } func (p *Proof) FromReader(r io.Reader) error { - var tmp bls12381.G1Affine - d := bls12381.NewDecoder(r) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding A: %s", err) - } - p.A.FromAffine(&tmp) - - if err := p.T.FromReader(r); err != nil { - return fmt.Errorf("decoding T: %s", err) - } - if err := p.U.FromReader(r); err != nil { - return fmt.Errorf("decoding U: %s", err) - } - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding R: %s", err) - } - p.R.FromAffine(&tmp) - - if err := d.Decode(&tmp); err != nil { - return fmt.Errorf("decoding S: %s", err) - } - p.S.FromAffine(&tmp) - - if err := p.proofSamePermutation.FromReader(r); err != nil { - return fmt.Errorf("decoding proofSamePermutation: %s", err) - } - if err := p.proofSameScalar.FromReader(r); err != nil { - return fmt.Errorf("decoding proofSameScalar: %s", err) - } - if err := p.proofSameMultiscalar.FromReader(r); err != nil { - return fmt.Errorf("decoding proofSameMultiscalar: %s", err) - } + // var tmp bls12381.G1Affine + // d := bls12381.NewDecoder(r) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding A: %s", err) + // } + // p.A.FromAffine(&tmp) + + // if err := p.T.FromReader(r); err != nil { + // return fmt.Errorf("decoding T: %s", err) + // } + // if err := p.U.FromReader(r); err != nil { + // return fmt.Errorf("decoding U: %s", err) + // } + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding R: %s", err) + // } + // p.R.FromAffine(&tmp) + + // if err := d.Decode(&tmp); err != nil { + // return fmt.Errorf("decoding S: %s", err) + // } + // p.S.FromAffine(&tmp) + + // if err := p.proofSamePermutation.FromReader(r); err != nil { + // return fmt.Errorf("decoding proofSamePermutation: %s", err) + // } + // if err := p.proofSameScalar.FromReader(r); err != nil { + // return fmt.Errorf("decoding proofSameScalar: %s", err) + // } + // if err := p.proofSameMultiscalar.FromReader(r); err != nil { + // return fmt.Errorf("decoding proofSameMultiscalar: %s", err) + // } return nil } func (p *Proof) Serialize(w io.Writer) error { - e := bls12381.NewEncoder(w) - ars := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.A, p.R, p.S}) - if err := e.Encode(&ars[0]); err != nil { - panic(fmt.Errorf("encoding A: %s", err)) - } - if err := p.T.Serialize(w); err != nil { - return fmt.Errorf("encoding T: %s", err) - } - if err := p.U.Serialize(w); err != nil { - return fmt.Errorf("encoding U: %s", err) - } - if err := e.Encode(&ars[1]); err != nil { - return fmt.Errorf("encoding R: %s", err) - } - if err := e.Encode(&ars[2]); err != nil { - return fmt.Errorf("encoding S: %s", err) - } - if err := p.proofSamePermutation.Serialize(w); err != nil { - return fmt.Errorf("encoding proofSamePermutation: %s", err) - } - if err := p.proofSameScalar.Serialize(w); err != nil { - return fmt.Errorf("encoding proofSameScalar: %s", err) - } - if err := p.proofSameMultiscalar.Serialize(w); err != nil { - return fmt.Errorf("encoding proofSameMultiscalar: %s", err) - } + // e := bls12381.NewEncoder(w) + // ars := bls12381.BatchJacobianToAffineG1([]bls12381.G1Jac{p.A, p.R, p.S}) + // if err := e.Encode(&ars[0]); err != nil { + // panic(fmt.Errorf("encoding A: %s", err)) + // } + // if err := p.T.Serialize(w); err != nil { + // return fmt.Errorf("encoding T: %s", err) + // } + // if err := p.U.Serialize(w); err != nil { + // return fmt.Errorf("encoding U: %s", err) + // } + // if err := e.Encode(&ars[1]); err != nil { + // return fmt.Errorf("encoding R: %s", err) + // } + // if err := e.Encode(&ars[2]); err != nil { + // return fmt.Errorf("encoding S: %s", err) + // } + // if err := p.proofSamePermutation.Serialize(w); err != nil { + // return fmt.Errorf("encoding proofSamePermutation: %s", err) + // } + // if err := p.proofSameScalar.Serialize(w); err != nil { + // return fmt.Errorf("encoding proofSameScalar: %s", err) + // } + // if err := p.proofSameMultiscalar.Serialize(w); err != nil { + // return fmt.Errorf("encoding proofSameMultiscalar: %s", err) + // } return nil } diff --git a/curdleproof_test.go b/curdleproof_test.go index bda64bb..dde55a3 100644 --- a/curdleproof_test.go +++ b/curdleproof_test.go @@ -1,8 +1,6 @@ package curdleproof import ( - "bytes" - "fmt" "testing" mrand "math/rand" @@ -10,211 +8,58 @@ import ( bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" + "github.com/jsign/curdleproofs/group" + "github.com/jsign/curdleproofs/utils" "github.com/stretchr/testify/require" ) -func TestCompleteness(t *testing.T) { - t.Parallel() - - n := 64 - - // Prove. - rand, err := common.NewRand(42) - require.NoError(t, err) - - crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(t, n) - proof, err := Prove( - crs, - Rs, - Ss, - Ts, - Us, - M, - perm, - k, - rs_m, - rand, - ) - require.NoError(t, err) - - // Verify. - rand, err = common.NewRand(43) - require.NoError(t, err) - ok, err := Verify(proof, crs, Rs, Ss, Ts, Us, M, rand) - require.NoError(t, err) - require.True(t, ok) +type testConfig struct { + name string + group group.Group + genRandomGroupElement func(*common.Rand) (group.Element, error) } -func TestSoundness(t *testing.T) { +func TestCompleteness(t *testing.T) { t.Parallel() - n := 128 - - rand, err := common.NewRand(0) - require.NoError(t, err) - - crs, err := GenerateCRS(n-common.N_BLINDERS, rand) - require.NoError(t, err) - - perm := make([]uint32, n-common.N_BLINDERS) - for i := range perm { - perm[i] = uint32(i) - } - srand := mrand.New(mrand.NewSource(42)) - srand.Shuffle(len(perm), func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) - - k, err := rand.GetFr() - require.NoError(t, err) - - Rs, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - Ss, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - - Ts, Us, M, rs_m, err := common.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) - require.NoError(t, err) - - // Prove. - rand, err = common.NewRand(0) - require.NoError(t, err) - proof, err := Prove( - crs, - Rs, - Ss, - Ts, - Us, - M, - perm, - k, - rs_m, - rand, - ) - require.NoError(t, err) - - anotherPerm := make([]uint32, n-common.N_BLINDERS) - for i := range anotherPerm { - anotherPerm[i] = uint32(i) - } - srand.Shuffle(len(anotherPerm), func(i, j int) { anotherPerm[i], anotherPerm[j] = anotherPerm[j], anotherPerm[i] }) - - t.Run("flips Ss and Rs", func(t *testing.T) { - ok, err := Verify(proof, crs, Ss, Rs, Ts, Us, M, rand) - require.NoError(t, err) - require.False(t, ok) - }) - - t.Run("apply a different permutation than the one proved", func(t *testing.T) { - ok, err := Verify( - proof, - crs, - Rs, - Ss, - common.Permute(Ts, anotherPerm), - common.Permute(Us, anotherPerm), - M, - rand, - ) - require.NoError(t, err) - require.False(t, ok) - }) - - t.Run("provide wrong perm commitment", func(t *testing.T) { - biK := common.FrToBigInt(&k) - var touchedM bls12381.G1Jac - touchedM.ScalarMultiplication(&M, biK) - ok, err := Verify( - proof, - crs, - Rs, - Ss, - Ts, - Us, - touchedM, - rand, - ) - require.NoError(t, err) - require.False(t, ok) - - }) - - t.Run("instance outputs use a different randomizer", func(t *testing.T) { - anotherK, err := rand.GetFr() - require.NoError(t, err) - biAnotherK := common.FrToBigInt(&anotherK) - - anotherTs := make([]bls12381.G1Affine, len(Rs)) - for i := range Ts { - anotherTs[i].ScalarMultiplication(&Ts[i], biAnotherK) - } - - anotherUs := make([]bls12381.G1Affine, len(Us)) - for i := range Us { - anotherUs[i].ScalarMultiplication(&Us[i], biAnotherK) - } - ok, err := Verify( - proof, - crs, - Rs, - Ss, - anotherTs, - anotherUs, - M, - rand, - ) - require.NoError(t, err) - require.False(t, ok) - - }) - - t.Run("encode/decode", func(t *testing.T) { - buf := bytes.NewBuffer(nil) - require.NoError(t, proof.Serialize(buf)) - expected := buf.Bytes() - - var proof2 Proof - require.NoError(t, proof2.FromReader(buf)) - - buf2 := bytes.NewBuffer(nil) - require.NoError(t, proof2.Serialize(buf2)) - - require.Equal(t, expected, buf2.Bytes()) - }) -} + n := 64 -func BenchmarkProver(b *testing.B) { - rand, err := common.NewRand(42) - require.NoError(b, err) - - for _, n := range []int{64, 128, 256, 512} { - b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { - crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = Prove( - crs, - Rs, - Ss, - Ts, - Us, - M, - perm, - k, - rs_m, - rand, - ) - } - }) + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, } -} -func BenchmarkVerifier(b *testing.B) { - rand, err := common.NewRand(42) - require.NoError(b, err) + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + // Prove. + rand, err := common.NewRand(42) + require.NoError(t, err) - for _, n := range []int{64, 128, 256, 512} { - b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { - crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) + crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(t, config, n) proof, err := Prove( + config.group, crs, Rs, Ss, @@ -226,30 +71,223 @@ func BenchmarkVerifier(b *testing.B) { rs_m, rand, ) - require.NoError(b, err) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = Verify(proof, crs, Rs, Ss, Ts, Us, M, rand) - } + require.NoError(t, err) + + // Verify. + rand, err = common.NewRand(43) + require.NoError(t, err) + ok, err := Verify(config.group, proof, crs, Rs, Ss, Ts, Us, M, rand) + require.NoError(t, err) + require.True(t, ok) }) } } -func setup(t testing.TB, n int) ( +// func TestSoundness(t *testing.T) { +// t.Parallel() + +// n := 128 + +// rand, err := common.NewRand(0) +// require.NoError(t, err) + +// crs, err := GenerateCRS(n-common.N_BLINDERS, rand) +// require.NoError(t, err) + +// perm := make([]uint32, n-common.N_BLINDERS) +// for i := range perm { +// perm[i] = uint32(i) +// } +// srand := mrand.New(mrand.NewSource(42)) +// srand.Shuffle(len(perm), func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) + +// k, err := rand.GetFr() +// require.NoError(t, err) + +// Rs, err := rand.GetG1Affines(n - common.N_BLINDERS) +// require.NoError(t, err) +// Ss, err := rand.GetG1Affines(n - common.N_BLINDERS) +// require.NoError(t, err) + +// Ts, Us, M, rs_m, err := common.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) +// require.NoError(t, err) + +// // Prove. +// rand, err = common.NewRand(0) +// require.NoError(t, err) +// proof, err := Prove( +// crs, +// Rs, +// Ss, +// Ts, +// Us, +// M, +// perm, +// k, +// rs_m, +// rand, +// ) +// require.NoError(t, err) + +// anotherPerm := make([]uint32, n-common.N_BLINDERS) +// for i := range anotherPerm { +// anotherPerm[i] = uint32(i) +// } +// srand.Shuffle(len(anotherPerm), func(i, j int) { anotherPerm[i], anotherPerm[j] = anotherPerm[j], anotherPerm[i] }) + +// t.Run("flips Ss and Rs", func(t *testing.T) { +// ok, err := Verify(proof, crs, Ss, Rs, Ts, Us, M, rand) +// require.NoError(t, err) +// require.False(t, ok) +// }) + +// t.Run("apply a different permutation than the one proved", func(t *testing.T) { +// ok, err := Verify( +// proof, +// crs, +// Rs, +// Ss, +// common.Permute(Ts, anotherPerm), +// common.Permute(Us, anotherPerm), +// M, +// rand, +// ) +// require.NoError(t, err) +// require.False(t, ok) +// }) + +// t.Run("provide wrong perm commitment", func(t *testing.T) { +// biK := common.FrToBigInt(&k) +// var touchedM bls12381.G1Jac +// touchedM.ScalarMultiplication(&M, biK) +// ok, err := Verify( +// proof, +// crs, +// Rs, +// Ss, +// Ts, +// Us, +// touchedM, +// rand, +// ) +// require.NoError(t, err) +// require.False(t, ok) + +// }) + +// t.Run("instance outputs use a different randomizer", func(t *testing.T) { +// anotherK, err := rand.GetFr() +// require.NoError(t, err) +// biAnotherK := common.FrToBigInt(&anotherK) + +// anotherTs := make([]bls12381.G1Affine, len(Rs)) +// for i := range Ts { +// anotherTs[i].ScalarMultiplication(&Ts[i], biAnotherK) +// } + +// anotherUs := make([]bls12381.G1Affine, len(Us)) +// for i := range Us { +// anotherUs[i].ScalarMultiplication(&Us[i], biAnotherK) +// } +// ok, err := Verify( +// proof, +// crs, +// Rs, +// Ss, +// anotherTs, +// anotherUs, +// M, +// rand, +// ) +// require.NoError(t, err) +// require.False(t, ok) + +// }) + +// t.Run("encode/decode", func(t *testing.T) { +// buf := bytes.NewBuffer(nil) +// require.NoError(t, proof.Serialize(buf)) +// expected := buf.Bytes() + +// var proof2 Proof +// require.NoError(t, proof2.FromReader(buf)) + +// buf2 := bytes.NewBuffer(nil) +// require.NoError(t, proof2.Serialize(buf2)) + +// require.Equal(t, expected, buf2.Bytes()) +// }) +// } + +// func BenchmarkProver(b *testing.B) { +// rand, err := common.NewRand(42) +// require.NoError(b, err) + +// for _, n := range []int{64, 128, 256, 512} { +// b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { +// crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) +// b.ResetTimer() +// for i := 0; i < b.N; i++ { +// _, _ = Prove( +// crs, +// Rs, +// Ss, +// Ts, +// Us, +// M, +// perm, +// k, +// rs_m, +// rand, +// ) +// } +// }) +// } +// } + +// func BenchmarkVerifier(b *testing.B) { +// rand, err := common.NewRand(42) +// require.NoError(b, err) + +// for _, n := range []int{64, 128, 256, 512} { +// b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { +// crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) +// proof, err := Prove( +// crs, +// Rs, +// Ss, +// Ts, +// Us, +// M, +// perm, +// k, +// rs_m, +// rand, +// ) +// require.NoError(b, err) + +// b.ResetTimer() +// for i := 0; i < b.N; i++ { +// _, _ = Verify(proof, crs, Rs, Ss, Ts, Us, M, rand) +// } +// }) +// } +// } + +func setup(t testing.TB, config testConfig, n int) ( CRS, - []bls12381.G1Affine, - []bls12381.G1Affine, - []bls12381.G1Affine, - []bls12381.G1Affine, - bls12381.G1Jac, + []group.Element, + []group.Element, + []group.Element, + []group.Element, + group.Element, []uint32, fr.Element, []fr.Element) { rand, err := common.NewRand(0) require.NoError(t, err) - crs, err := GenerateCRS(n-common.N_BLINDERS, rand) + crs, err := GenerateCRS(n-common.N_BLINDERS, config.group, func() (group.Element, error) { return config.genRandomGroupElement(rand) }) require.NoError(t, err) perm := make([]uint32, n-common.N_BLINDERS) @@ -262,12 +300,18 @@ func setup(t testing.TB, n int) ( k, err := rand.GetFr() require.NoError(t, err) - Rs, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) - Ss, err := rand.GetG1Affines(n - common.N_BLINDERS) - require.NoError(t, err) + Rs := make([]group.Element, n-common.N_BLINDERS) + for i := range Rs { + Rs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + Ss := make([]group.Element, n-common.N_BLINDERS) + for i := range Ss { + Ss[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } - Ts, Us, M, rs_m, err := common.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) + Ts, Us, M, rs_m, err := utils.ShufflePermuteCommit(config.group, crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) require.NoError(t, err) return crs, Rs, Ss, Ts, Us, M, perm, k, rs_m diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..f8f29f0 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,57 @@ +package utils + +import ( + "fmt" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/jsign/curdleproofs/common" + "github.com/jsign/curdleproofs/group" +) + +// TODO: moved from commons to avoid import cycle. try looking for a better separation. +func ShufflePermuteCommit( + g group.Group, + crsGs []group.Element, + crsHs []group.Element, + Rs []group.Element, + Ss []group.Element, + perm []uint32, + k fr.Element, + rand *common.Rand, +) ([]group.Element, []group.Element, group.Element, []fr.Element, error) { + Ts := make([]group.Element, len(Rs)) + for i := range Ts { + Ts[i] = g.CreateElement() + Ts[i].ScalarMultiplication(Rs[i], k) + } + + Us := make([]group.Element, len(Ss)) + for i := range Us { + Us[i] = g.CreateElement() + Us[i].ScalarMultiplication(Ss[i], k) + } + + Ts = common.Permute(Ts, perm) + Us = common.Permute(Us, perm) + + rangeFrs := make([]fr.Element, len(crsGs)) + for i := range perm { + rangeFrs[i] = fr.NewElement(uint64(i)) + } + + permRangeFrs := common.Permute(rangeFrs, perm) + M, M2 := g.CreateElement(), g.CreateElement() + if _, err := M.MultiExp(crsGs, permRangeFrs); err != nil { + return nil, nil, nil, nil, fmt.Errorf("calculating M_1: %s", err) + } + rs_m, err := rand.GetFrs(common.N_BLINDERS) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("getting rs_m: %s", err) + } + if _, err := M2.MultiExp(crsHs, rs_m); err != nil { + return nil, nil, nil, nil, fmt.Errorf("calculating M_2: %s", err) + } + M.AddAssign(M2) + + return Ts, Us, M, rs_m, nil +} diff --git a/whisk/whisk.go b/whisk/whisk.go index 752777a..bdfd6c8 100644 --- a/whisk/whisk.go +++ b/whisk/whisk.go @@ -1,12 +1,10 @@ package whisk import ( - "bytes" "fmt" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - curdleproof "github.com/jsign/curdleproofs" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/transcript" ) @@ -18,99 +16,101 @@ var ( ) func IsValidWhiskShuffleProof(crs CRS, preST, postST []WhiskTracker, proof WhiskShuffleProofBytes, rand *common.Rand) (bool, error) { - if len(preST) != len(postST) { - return false, fmt.Errorf("pre and post shuffle trackers must be the same length") - } - - var whiskProof WhiskShuffleProof - if err := whiskProof.FromReader(bytes.NewReader(proof[:])); err != nil { - return false, fmt.Errorf("decoding proof: %s", err) - } - - var err error - Rs := make([]bls12381.G1Affine, len(preST)) - Ss := make([]bls12381.G1Affine, len(preST)) - Ts := make([]bls12381.G1Affine, len(postST)) - Us := make([]bls12381.G1Affine, len(postST)) - for i := 0; i < len(preST); i++ { - Rs[i], Ss[i], err = preST[i].getPoints() - if err != nil { - return false, fmt.Errorf("getting pre shuffle points: %s", err) - } - Ts[i], Us[i], err = postST[i].getPoints() - if err != nil { - return false, fmt.Errorf("getting post shuffle points: %s", err) - } - } - - ok, err := curdleproof.Verify( - whiskProof.Proof, - crs, - Rs, - Ss, - Ts, - Us, - whiskProof.M, - rand, - ) - if err != nil { - return false, fmt.Errorf("verifying proof: %s", err) - } - - return ok, nil + // if len(preST) != len(postST) { + // return false, fmt.Errorf("pre and post shuffle trackers must be the same length") + // } + + // var whiskProof WhiskShuffleProof + // if err := whiskProof.FromReader(bytes.NewReader(proof[:])); err != nil { + // return false, fmt.Errorf("decoding proof: %s", err) + // } + + // var err error + // Rs := make([]bls12381.G1Affine, len(preST)) + // Ss := make([]bls12381.G1Affine, len(preST)) + // Ts := make([]bls12381.G1Affine, len(postST)) + // Us := make([]bls12381.G1Affine, len(postST)) + // for i := 0; i < len(preST); i++ { + // Rs[i], Ss[i], err = preST[i].getPoints() + // if err != nil { + // return false, fmt.Errorf("getting pre shuffle points: %s", err) + // } + // Ts[i], Us[i], err = postST[i].getPoints() + // if err != nil { + // return false, fmt.Errorf("getting post shuffle points: %s", err) + // } + // } + + // ok, err := curdleproof.Verify( + // whiskProof.Proof, + // crs, + // Rs, + // Ss, + // Ts, + // Us, + // whiskProof.M, + // rand, + // ) + // if err != nil { + // return false, fmt.Errorf("verifying proof: %s", err) + // } + + // return ok, nil + return false, nil } func GenerateWhiskShuffleProof(crs CRS, preTrackers []WhiskTracker, rand *common.Rand) ([]WhiskTracker, WhiskShuffleProofBytes, error) { - permutation, err := rand.GeneratePermutation(ELL) - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating permutation: %s", err) - } - k, err := rand.GetFr() - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating k: %s", err) - } - - Rs := make([]bls12381.G1Affine, len(preTrackers)) - Ss := make([]bls12381.G1Affine, len(preTrackers)) - for i := 0; i < len(preTrackers); i++ { - Rs[i], Ss[i], err = preTrackers[i].getPoints() - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("getting points: %s", err) - } - } - - Ts, Us, M, rs_m, err := common.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, permutation, k, rand) - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("shuffling and permuting: %s", err) - } - - proof, err := curdleproof.Prove( - crs, - Rs, - Ss, - Ts, - Us, - M, - permutation, - k, - rs_m, - rand) - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating proof: %s", err) - } - - whiskProof := WhiskShuffleProof{M: M, Proof: proof} - proofBytes, err := whiskProof.Serialize() - if err != nil { - return nil, WhiskShuffleProofBytes{}, fmt.Errorf("serializing proof: %s", err) - } - - postTrackers := make([]WhiskTracker, len(preTrackers)) - for i := 0; i < len(preTrackers); i++ { - postTrackers[i] = NewWhiskTracker(Ts[i], Us[i]) - } - - return postTrackers, proofBytes, nil + // permutation, err := rand.GeneratePermutation(ELL) + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating permutation: %s", err) + // } + // k, err := rand.GetFr() + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating k: %s", err) + // } + + // Rs := make([]bls12381.G1Affine, len(preTrackers)) + // Ss := make([]bls12381.G1Affine, len(preTrackers)) + // for i := 0; i < len(preTrackers); i++ { + // Rs[i], Ss[i], err = preTrackers[i].getPoints() + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("getting points: %s", err) + // } + // } + + // Ts, Us, M, rs_m, err := utils.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, permutation, k, rand) + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("shuffling and permuting: %s", err) + // } + + // proof, err := curdleproof.Prove( + // crs, + // Rs, + // Ss, + // Ts, + // Us, + // M, + // permutation, + // k, + // rs_m, + // rand) + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("generating proof: %s", err) + // } + + // whiskProof := WhiskShuffleProof{M: M, Proof: proof} + // proofBytes, err := whiskProof.Serialize() + // if err != nil { + // return nil, WhiskShuffleProofBytes{}, fmt.Errorf("serializing proof: %s", err) + // } + + // postTrackers := make([]WhiskTracker, len(preTrackers)) + // for i := 0; i < len(preTrackers); i++ { + // postTrackers[i] = NewWhiskTracker(Ts[i], Us[i]) + // } + + // return postTrackers, proofBytes, nil + return nil, WhiskShuffleProofBytes{}, nil } func IsValidWhiskTrackerProof(tracker WhiskTracker, kComm G1PointBytes, trackerProofBytes TrackerProofBytes) (bool, error) { diff --git a/whisk/whisk_test.go b/whisk/whisk_test.go index fe08080..7b171bd 100644 --- a/whisk/whisk_test.go +++ b/whisk/whisk_test.go @@ -33,61 +33,61 @@ func TestWhiskTrackerProof(t *testing.T) { // be an array of length equal TRACKER_PROOF_SIZE. } -func TestWhiskShuffleProof(t *testing.T) { - rand, err := common.NewRand(0) - require.NoError(t, err) - - crs, err := curdleproof.GenerateCRS(ELL, rand) - require.NoError(t, err) - - shuffledTrackers := generateShuffleTrackers(t, rand) - - postTrackers, proofBytes, err := GenerateWhiskShuffleProof(crs, shuffledTrackers, rand) - require.NoError(t, err) - - ok, err := IsValidWhiskShuffleProof(crs, shuffledTrackers, postTrackers, proofBytes, rand) - require.NoError(t, err) - require.True(t, ok) - - // Assert correct WHISK_SHUFFLE_PROOF_SIZE - // Note: this part of the reference test isn't implemented since - // in this implementation the serialized proof is forced to - // be an array of length equal WHISK_SHUFFLE_PROOF_SIZE. -} - -func TestWhiskFullLifecycle(t *testing.T) { - rand, err := common.NewRand(0) - require.NoError(t, err) - crs, err := curdleproof.GenerateCRS(ELL, rand) - require.NoError(t, err) - - // Initial tracker in state - shuffledTrackers := generateShuffleTrackers(t, rand) - - proposerIndex := uint64(15400) - proposerInitialK := fr.NewElement(proposerIndex) - - // Initial dummy values, r = 1 - state := State{ - proposerTracker: computeTracker(proposerInitialK, fr.One()), - proposerKCommitment: getKComm(proposerInitialK), - shuffledTrackers: shuffledTrackers, - } - - // k must be kept - proposerK, err := rand.GetFr() - require.NoError(t, err) - - // On first proposal, validator creates tracker for registering - block0 := produceBlock(t, crs, &state, proposerK, proposerIndex) - // Block is valid - processBlock(t, crs, &state, block0) - - // On second proposal, validator opens previously submited tracker - block1 := produceBlock(t, crs, &state, proposerK, proposerIndex) - // Block is valid - processBlock(t, crs, &state, block1) -} +// func TestWhiskShuffleProof(t *testing.T) { +// rand, err := common.NewRand(0) +// require.NoError(t, err) + +// crs, err := curdleproof.GenerateCRS(ELL, rand) +// require.NoError(t, err) + +// shuffledTrackers := generateShuffleTrackers(t, rand) + +// postTrackers, proofBytes, err := GenerateWhiskShuffleProof(crs, shuffledTrackers, rand) +// require.NoError(t, err) + +// ok, err := IsValidWhiskShuffleProof(crs, shuffledTrackers, postTrackers, proofBytes, rand) +// require.NoError(t, err) +// require.True(t, ok) + +// // Assert correct WHISK_SHUFFLE_PROOF_SIZE +// // Note: this part of the reference test isn't implemented since +// // in this implementation the serialized proof is forced to +// // be an array of length equal WHISK_SHUFFLE_PROOF_SIZE. +// } + +// func TestWhiskFullLifecycle(t *testing.T) { +// rand, err := common.NewRand(0) +// require.NoError(t, err) +// crs, err := curdleproof.GenerateCRS(ELL, rand) +// require.NoError(t, err) + +// // Initial tracker in state +// shuffledTrackers := generateShuffleTrackers(t, rand) + +// proposerIndex := uint64(15400) +// proposerInitialK := fr.NewElement(proposerIndex) + +// // Initial dummy values, r = 1 +// state := State{ +// proposerTracker: computeTracker(proposerInitialK, fr.One()), +// proposerKCommitment: getKComm(proposerInitialK), +// shuffledTrackers: shuffledTrackers, +// } + +// // k must be kept +// proposerK, err := rand.GetFr() +// require.NoError(t, err) + +// // On first proposal, validator creates tracker for registering +// block0 := produceBlock(t, crs, &state, proposerK, proposerIndex) +// // Block is valid +// processBlock(t, crs, &state, block0) + +// // On second proposal, validator opens previously submited tracker +// block1 := produceBlock(t, crs, &state, proposerK, proposerIndex) +// // Block is valid +// processBlock(t, crs, &state, block1) +// } func generateTracker(t *testing.T, rand *common.Rand, k fr.Element) WhiskTracker { r, err := rand.GetFr() From 61fc0c45b14e75eafe1390fb655ac81680b3d2af Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sat, 23 Sep 2023 20:52:40 -0300 Subject: [PATCH 17/21] bench: support abstract group Signed-off-by: Ignacio Hagopian --- curdleproof_test.go | 173 ++++++++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 53 deletions(-) diff --git a/curdleproof_test.go b/curdleproof_test.go index dde55a3..ccb9078 100644 --- a/curdleproof_test.go +++ b/curdleproof_test.go @@ -1,6 +1,7 @@ package curdleproof import ( + "fmt" "testing" mrand "math/rand" @@ -219,60 +220,126 @@ func TestCompleteness(t *testing.T) { // }) // } -// func BenchmarkProver(b *testing.B) { -// rand, err := common.NewRand(42) -// require.NoError(b, err) - -// for _, n := range []int{64, 128, 256, 512} { -// b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { -// crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) -// b.ResetTimer() -// for i := 0; i < b.N; i++ { -// _, _ = Prove( -// crs, -// Rs, -// Ss, -// Ts, -// Us, -// M, -// perm, -// k, -// rs_m, -// rand, -// ) -// } -// }) -// } -// } +func BenchmarkProver(b *testing.B) { + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } -// func BenchmarkVerifier(b *testing.B) { -// rand, err := common.NewRand(42) -// require.NoError(b, err) - -// for _, n := range []int{64, 128, 256, 512} { -// b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { -// crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, n) -// proof, err := Prove( -// crs, -// Rs, -// Ss, -// Ts, -// Us, -// M, -// perm, -// k, -// rs_m, -// rand, -// ) -// require.NoError(b, err) - -// b.ResetTimer() -// for i := 0; i < b.N; i++ { -// _, _ = Verify(proof, crs, Rs, Ss, Ts, Us, M, rand) -// } -// }) -// } -// } + for _, config := range configs { + b.Run(config.name, func(b *testing.B) { + rand, err := common.NewRand(42) + require.NoError(b, err) + + for _, n := range []int{64, 128, 256, 512} { + b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { + crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, config, n) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = Prove( + config.group, + crs, + Rs, + Ss, + Ts, + Us, + M, + perm, + k, + rs_m, + rand, + ) + } + }) + } + }) + } +} + +func BenchmarkVerifier(b *testing.B) { + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } + + for _, config := range configs { + b.Run(config.name, func(b *testing.B) { + + rand, err := common.NewRand(42) + require.NoError(b, err) + + for _, n := range []int{64, 128, 256, 512} { + b.Run(fmt.Sprintf("shuffled elements=%d", n-common.N_BLINDERS), func(b *testing.B) { + crs, Rs, Ss, Ts, Us, M, perm, k, rs_m := setup(b, config, n) + proof, err := Prove( + config.group, + crs, + Rs, + Ss, + Ts, + Us, + M, + perm, + k, + rs_m, + rand, + ) + require.NoError(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = Verify(config.group, proof, crs, Rs, Ss, Ts, Us, M, rand) + } + }) + } + }) + } +} func setup(t testing.TB, config testConfig, n int) ( CRS, From 9f96dcd356dcf74c79cba0693dade0af4e0b028c Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sun, 24 Sep 2023 08:11:51 -0300 Subject: [PATCH 18/21] curdleproofs: migrate soundess tests to generic gorup Signed-off-by: Ignacio Hagopian --- curdleproof_test.go | 314 +++++++++++++++++++++++++------------------- 1 file changed, 179 insertions(+), 135 deletions(-) diff --git a/curdleproof_test.go b/curdleproof_test.go index ccb9078..f978460 100644 --- a/curdleproof_test.go +++ b/curdleproof_test.go @@ -1,6 +1,7 @@ package curdleproof import ( + "bytes" "fmt" "testing" @@ -84,141 +85,184 @@ func TestCompleteness(t *testing.T) { } } -// func TestSoundness(t *testing.T) { -// t.Parallel() - -// n := 128 - -// rand, err := common.NewRand(0) -// require.NoError(t, err) - -// crs, err := GenerateCRS(n-common.N_BLINDERS, rand) -// require.NoError(t, err) - -// perm := make([]uint32, n-common.N_BLINDERS) -// for i := range perm { -// perm[i] = uint32(i) -// } -// srand := mrand.New(mrand.NewSource(42)) -// srand.Shuffle(len(perm), func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) - -// k, err := rand.GetFr() -// require.NoError(t, err) - -// Rs, err := rand.GetG1Affines(n - common.N_BLINDERS) -// require.NoError(t, err) -// Ss, err := rand.GetG1Affines(n - common.N_BLINDERS) -// require.NoError(t, err) - -// Ts, Us, M, rs_m, err := common.ShufflePermuteCommit(crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) -// require.NoError(t, err) - -// // Prove. -// rand, err = common.NewRand(0) -// require.NoError(t, err) -// proof, err := Prove( -// crs, -// Rs, -// Ss, -// Ts, -// Us, -// M, -// perm, -// k, -// rs_m, -// rand, -// ) -// require.NoError(t, err) - -// anotherPerm := make([]uint32, n-common.N_BLINDERS) -// for i := range anotherPerm { -// anotherPerm[i] = uint32(i) -// } -// srand.Shuffle(len(anotherPerm), func(i, j int) { anotherPerm[i], anotherPerm[j] = anotherPerm[j], anotherPerm[i] }) - -// t.Run("flips Ss and Rs", func(t *testing.T) { -// ok, err := Verify(proof, crs, Ss, Rs, Ts, Us, M, rand) -// require.NoError(t, err) -// require.False(t, ok) -// }) - -// t.Run("apply a different permutation than the one proved", func(t *testing.T) { -// ok, err := Verify( -// proof, -// crs, -// Rs, -// Ss, -// common.Permute(Ts, anotherPerm), -// common.Permute(Us, anotherPerm), -// M, -// rand, -// ) -// require.NoError(t, err) -// require.False(t, ok) -// }) - -// t.Run("provide wrong perm commitment", func(t *testing.T) { -// biK := common.FrToBigInt(&k) -// var touchedM bls12381.G1Jac -// touchedM.ScalarMultiplication(&M, biK) -// ok, err := Verify( -// proof, -// crs, -// Rs, -// Ss, -// Ts, -// Us, -// touchedM, -// rand, -// ) -// require.NoError(t, err) -// require.False(t, ok) - -// }) - -// t.Run("instance outputs use a different randomizer", func(t *testing.T) { -// anotherK, err := rand.GetFr() -// require.NoError(t, err) -// biAnotherK := common.FrToBigInt(&anotherK) - -// anotherTs := make([]bls12381.G1Affine, len(Rs)) -// for i := range Ts { -// anotherTs[i].ScalarMultiplication(&Ts[i], biAnotherK) -// } - -// anotherUs := make([]bls12381.G1Affine, len(Us)) -// for i := range Us { -// anotherUs[i].ScalarMultiplication(&Us[i], biAnotherK) -// } -// ok, err := Verify( -// proof, -// crs, -// Rs, -// Ss, -// anotherTs, -// anotherUs, -// M, -// rand, -// ) -// require.NoError(t, err) -// require.False(t, ok) - -// }) - -// t.Run("encode/decode", func(t *testing.T) { -// buf := bytes.NewBuffer(nil) -// require.NoError(t, proof.Serialize(buf)) -// expected := buf.Bytes() - -// var proof2 Proof -// require.NoError(t, proof2.FromReader(buf)) - -// buf2 := bytes.NewBuffer(nil) -// require.NoError(t, proof2.Serialize(buf2)) - -// require.Equal(t, expected, buf2.Bytes()) -// }) -// } +func TestSoundness(t *testing.T) { + t.Parallel() + + n := 128 + + configs := []testConfig{ + { + name: "G1", + group: &group.GroupG1{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randG1Aff, err := rand.GetG1Affine() + if err != nil { + return nil, err + } + var randG1Jac bls12381.G1Jac + randG1Jac.FromAffine(&randG1Aff) + return group.FromG1Jac(randG1Jac), nil + }, + }, + { + name: "Gt", + group: &group.GroupGt{}, + genRandomGroupElement: func(rand *common.Rand) (group.Element, error) { + randGt, err := rand.GetGt() + if err != nil { + return nil, err + } + return group.FromGt(randGt), nil + }, + }, + } + + for _, config := range configs { + t.Run(config.name, func(t *testing.T) { + + rand, err := common.NewRand(0) + require.NoError(t, err) + + crs, err := GenerateCRS(n-common.N_BLINDERS, config.group, func() (group.Element, error) { return config.genRandomGroupElement(rand) }) + require.NoError(t, err) + + perm := make([]uint32, n-common.N_BLINDERS) + for i := range perm { + perm[i] = uint32(i) + } + srand := mrand.New(mrand.NewSource(42)) + srand.Shuffle(len(perm), func(i, j int) { perm[i], perm[j] = perm[j], perm[i] }) + + k, err := rand.GetFr() + require.NoError(t, err) + + Rs := make([]group.Element, n-common.N_BLINDERS) + for i := range Rs { + Rs[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + + Ss := make([]group.Element, n-common.N_BLINDERS) + for i := range Ss { + Ss[i], err = config.genRandomGroupElement(rand) + require.NoError(t, err) + } + + Ts, Us, M, rs_m, err := utils.ShufflePermuteCommit(config.group, crs.Gs, crs.Hs, Rs, Ss, perm, k, rand) + require.NoError(t, err) + + // Prove. + rand, err = common.NewRand(0) + require.NoError(t, err) + proof, err := Prove( + config.group, + crs, + Rs, + Ss, + Ts, + Us, + M, + perm, + k, + rs_m, + rand, + ) + require.NoError(t, err) + + anotherPerm := make([]uint32, n-common.N_BLINDERS) + for i := range anotherPerm { + anotherPerm[i] = uint32(i) + } + srand.Shuffle(len(anotherPerm), func(i, j int) { anotherPerm[i], anotherPerm[j] = anotherPerm[j], anotherPerm[i] }) + + t.Run("flips Ss and Rs", func(t *testing.T) { + ok, err := Verify(config.group, proof, crs, Ss, Rs, Ts, Us, M, rand) + require.NoError(t, err) + require.False(t, ok) + }) + + t.Run("apply a different permutation than the one proved", func(t *testing.T) { + ok, err := Verify( + config.group, + proof, + crs, + Rs, + Ss, + common.Permute(Ts, anotherPerm), + common.Permute(Us, anotherPerm), + M, + rand, + ) + require.NoError(t, err) + require.False(t, ok) + }) + + t.Run("provide wrong perm commitment", func(t *testing.T) { + touchedM := config.group.CreateElement() + touchedM.ScalarMultiplication(M, k) + ok, err := Verify( + config.group, + proof, + crs, + Rs, + Ss, + Ts, + Us, + touchedM, + rand, + ) + require.NoError(t, err) + require.False(t, ok) + + }) + + t.Run("instance outputs use a different randomizer", func(t *testing.T) { + anotherK, err := rand.GetFr() + require.NoError(t, err) + + anotherTs := make([]group.Element, len(Rs)) + for i := range Ts { + anotherTs[i] = config.group.CreateElement() + anotherTs[i].ScalarMultiplication(Ts[i], anotherK) + } + + anotherUs := make([]group.Element, len(Us)) + for i := range Us { + anotherUs[i] = config.group.CreateElement() + anotherUs[i].ScalarMultiplication(Us[i], anotherK) + } + ok, err := Verify( + config.group, + proof, + crs, + Rs, + Ss, + anotherTs, + anotherUs, + M, + rand, + ) + require.NoError(t, err) + require.False(t, ok) + + }) + + t.Run("encode/decode", func(t *testing.T) { + buf := bytes.NewBuffer(nil) + require.NoError(t, proof.Serialize(buf)) + expected := buf.Bytes() + + var proof2 Proof + require.NoError(t, proof2.FromReader(buf)) + + buf2 := bytes.NewBuffer(nil) + require.NoError(t, proof2.Serialize(buf2)) + + require.Equal(t, expected, buf2.Bytes()) + }) + }) + } +} func BenchmarkProver(b *testing.B) { configs := []testConfig{ From 61e1bbac3a38755bf5ee38031b88babb7556a10b Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sun, 24 Sep 2023 08:54:57 -0300 Subject: [PATCH 19/21] mod: add my patch for faster equality check Signed-off-by: Ignacio Hagopian --- go.mod | 10 +++++++--- go.sum | 25 ++++++++++++++++--------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 5a6040b..0aa1430 100644 --- a/go.mod +++ b/go.mod @@ -6,16 +6,20 @@ require ( github.com/consensys/gnark-crypto v0.11.0 github.com/jsign/merlin v0.0.0-20230603163309-c45ec8d8b2ce github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa + golang.org/x/crypto v0.10.0 ) require ( - github.com/bits-and-blooms/bitset v1.5.0 // indirect + github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + golang.org/x/sys v0.9.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/consensys/gnark-crypto => github.com/jsign/gnark-crypto v0.0.0-20230924115253-255461e78d73 diff --git a/go.sum b/go.sum index 26abc70..b8a67df 100644 --- a/go.sum +++ b/go.sum @@ -1,28 +1,35 @@ -github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8= -github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.11.0 h1:QqzHQlwEqlQr5jfWblGDkwlKHpT+4QodYqqExkAtyks= -github.com/consensys/gnark-crypto v0.11.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/jsign/gnark-crypto v0.0.0-20230924115253-255461e78d73 h1:VxFSHzAurx/fdNu6mkHNuJbdZyX7KpdDQhkD5VfrwDA= +github.com/jsign/gnark-crypto v0.0.0-20230924115253-255461e78d73/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/jsign/merlin v0.0.0-20230603163309-c45ec8d8b2ce h1:E4CZLSM8rth+vB4mf3d7tcvsfof5WxyTE3JL+0uWL8s= github.com/jsign/merlin v0.0.0-20230603163309-c45ec8d8b2ce/go.mod h1:D3j3jW+JJdLHJahHvx0chVOk+PfPVQFZhDOkcQnh3g8= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= From 685d7227c5580114518782bc39c20733f1bf356c Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sun, 24 Sep 2023 09:30:34 -0300 Subject: [PATCH 20/21] cleanups Signed-off-by: Ignacio Hagopian --- group/group.go | 34 +++++++++---------- .../samemultiscalarargument.go | 7 ---- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/group/group.go b/group/group.go index 3d90ecb..3fc3052 100644 --- a/group/group.go +++ b/group/group.go @@ -104,26 +104,25 @@ func (ma *MsmAccumulator) AccumulateCheck( return fmt.Errorf("x and v must have the same length") } - // alpha, err := rand.GetFr() - // if err != nil { - // return fmt.Errorf("get random scalar: %s", err) - // } - var alpha fr.Element + alpha, err := rand.GetFr() + if err != nil { + return fmt.Errorf("get random scalar: %s", err) + } alpha.SetOne() - // var tmp fr.Element - // outer: + var tmp fr.Element +outer: for i := 0; i < len(basis); i++ { - // tmp.Mul(&alpha, &scalar[i]) + tmp.Mul(&alpha, &scalar[i]) - // for j := range ma.baseScalarMap { - // if ma.baseScalarMap[j].basis.Equal(basis[i]) { - // var scalar fr.Element - // scalar.Add(&ma.baseScalarMap[j].scalar, &tmp) - // ma.baseScalarMap[j].scalar = scalar - // continue outer - // } - // } + for j := range ma.baseScalarMap { + if ma.baseScalarMap[j].basis.Equal(basis[i]) { + var scalar fr.Element + scalar.Add(&ma.baseScalarMap[j].scalar, &tmp) + ma.baseScalarMap[j].scalar = scalar + continue outer + } + } var basisCoeff msmCoeff basisCoeff.basis = ma.g.CreateElement() @@ -131,8 +130,7 @@ func (ma *MsmAccumulator) AccumulateCheck( basisCoeff.scalar = scalar[i] ma.baseScalarMap = append(ma.baseScalarMap, basisCoeff) } - // ma.A_c.AddAssign(C.ScalarMultiplication(C, alpha)) - ma.A_c.AddAssign(C) + ma.A_c.AddAssign(C.ScalarMultiplication(C, alpha)) return nil } diff --git a/samemultiscalarargument/samemultiscalarargument.go b/samemultiscalarargument/samemultiscalarargument.go index 06a8459..b902ccf 100644 --- a/samemultiscalarargument/samemultiscalarargument.go +++ b/samemultiscalarargument/samemultiscalarargument.go @@ -204,13 +204,6 @@ func Verify( } p.Set(A_a).AddAssign(l).AddAssign(r) - tmpCheck := g.CreateElement() - if _, err := tmpCheck.MultiExp(G, xtimess); err != nil { - panic(err) - } - if !tmpCheck.Equal(p) { - panic("wrong") - } if err := msmacc.AccumulateCheck(p, xtimess, G, rand); err != nil { return false, fmt.Errorf("accumulating msm 1: %s", err) } From 502ef8f8c7493ded77d6f4722c21cfa60dd79276 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Mon, 25 Sep 2023 19:48:43 -0300 Subject: [PATCH 21/21] make the linter happy Signed-off-by: Ignacio Hagopian --- curdleproof.go | 5 +- whisk/whisk_test.go | 179 ++++++++++++++++++++++---------------------- 2 files changed, 91 insertions(+), 93 deletions(-) diff --git a/curdleproof.go b/curdleproof.go index 5d01dc8..4f9bbbc 100644 --- a/curdleproof.go +++ b/curdleproof.go @@ -4,7 +4,6 @@ import ( "fmt" "io" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/jsign/curdleproofs/common" "github.com/jsign/curdleproofs/group" @@ -19,8 +18,8 @@ var ( labelStep1 = []byte("curdleproofs_step1") labelVecA = []byte("curdleproofs_vec_a") - zeroPoint = bls12381.G1Affine{} - zeroFr = fr.Element{} + // zeroPoint = bls12381.G1Affine{} + zeroFr = fr.Element{} ) type Proof struct { diff --git a/whisk/whisk_test.go b/whisk/whisk_test.go index 7b171bd..d95715c 100644 --- a/whisk/whisk_test.go +++ b/whisk/whisk_test.go @@ -5,7 +5,6 @@ import ( bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - curdleproof "github.com/jsign/curdleproofs" "github.com/jsign/curdleproofs/common" "github.com/stretchr/testify/require" ) @@ -108,102 +107,102 @@ func getKComm(k fr.Element) G1PointBytes { return res.ScalarMultiplication(&g1Gen, common.FrToBigInt(&k)).Bytes() } -func generateShuffleTrackers(t *testing.T, rand *common.Rand) []WhiskTracker { - wts := make([]WhiskTracker, ELL) - for i := 0; i < ELL; i++ { - k, err := rand.GetFr() - require.NoError(t, err) - wts[i] = generateTracker(t, rand, k) - } - return wts -} +// func generateShuffleTrackers(t *testing.T, rand *common.Rand) []WhiskTracker { +// wts := make([]WhiskTracker, ELL) +// for i := 0; i < ELL; i++ { +// k, err := rand.GetFr() +// require.NoError(t, err) +// wts[i] = generateTracker(t, rand, k) +// } +// return wts +// } -// Construct the CRS -type Block struct { - whiskOpeningProof TrackerProofBytes - whiskPostShuffleTrackers []WhiskTracker - whiskShuffleProof WhiskShuffleProofBytes - whiskRegistrationProof TrackerProofBytes - whiskTracker WhiskTracker - whiskKCommitment G1PointBytes -} +// // Construct the CRS +// type Block struct { +// whiskOpeningProof TrackerProofBytes +// whiskPostShuffleTrackers []WhiskTracker +// whiskShuffleProof WhiskShuffleProofBytes +// whiskRegistrationProof TrackerProofBytes +// whiskTracker WhiskTracker +// whiskKCommitment G1PointBytes +// } -type State struct { - proposerTracker WhiskTracker - proposerKCommitment G1PointBytes - shuffledTrackers []WhiskTracker -} +// type State struct { +// proposerTracker WhiskTracker +// proposerKCommitment G1PointBytes +// shuffledTrackers []WhiskTracker +// } -func processBlock(t *testing.T, crs curdleproof.CRS, state *State, block *Block) { - rand, err := common.NewRand(0) - require.NoError(t, err) +// func processBlock(t *testing.T, crs curdleproof.CRS, state *State, block *Block) { +// rand, err := common.NewRand(0) +// require.NoError(t, err) - // process_whisk_opening_proof - ok, err := IsValidWhiskTrackerProof(state.proposerTracker, state.proposerKCommitment, block.whiskOpeningProof) - require.NoError(t, err) - require.True(t, ok) +// // process_whisk_opening_proof +// ok, err := IsValidWhiskTrackerProof(state.proposerTracker, state.proposerKCommitment, block.whiskOpeningProof) +// require.NoError(t, err) +// require.True(t, ok) - // whisk_process_shuffled_trackers - ok, err = IsValidWhiskShuffleProof(crs, state.shuffledTrackers, block.whiskPostShuffleTrackers, block.whiskShuffleProof, rand) - require.NoError(t, err) - require.True(t, ok) +// // whisk_process_shuffled_trackers +// ok, err = IsValidWhiskShuffleProof(crs, state.shuffledTrackers, block.whiskPostShuffleTrackers, block.whiskShuffleProof, rand) +// require.NoError(t, err) +// require.True(t, ok) - // whisk_process_tracker_registration - g1GenBytes := g1Gen.Bytes() - if state.proposerTracker.rG == g1GenBytes { - // First proposal - ok, err := IsValidWhiskTrackerProof(block.whiskTracker, block.whiskKCommitment, block.whiskRegistrationProof) - require.NoError(t, err) - require.True(t, ok) - state.proposerTracker = block.whiskTracker - state.proposerKCommitment = block.whiskKCommitment - } - // `else` -> Next proposals, registration data not used -} +// // whisk_process_tracker_registration +// g1GenBytes := g1Gen.Bytes() +// if state.proposerTracker.rG == g1GenBytes { +// // First proposal +// ok, err := IsValidWhiskTrackerProof(block.whiskTracker, block.whiskKCommitment, block.whiskRegistrationProof) +// require.NoError(t, err) +// require.True(t, ok) +// state.proposerTracker = block.whiskTracker +// state.proposerKCommitment = block.whiskKCommitment +// } +// // `else` -> Next proposals, registration data not used +// } -func produceBlock(t *testing.T, crs curdleproof.CRS, state *State, proposerK fr.Element, proposerIndex uint64) *Block { - rand, err := common.NewRand(0) - require.NoError(t, err) +// func produceBlock(t *testing.T, crs curdleproof.CRS, state *State, proposerK fr.Element, proposerIndex uint64) *Block { +// rand, err := common.NewRand(0) +// require.NoError(t, err) - whiskPostShuffleTrackers, whiskShuffleProof, err := GenerateWhiskShuffleProof(crs, state.shuffledTrackers, rand) - require.NoError(t, err) +// whiskPostShuffleTrackers, whiskShuffleProof, err := GenerateWhiskShuffleProof(crs, state.shuffledTrackers, rand) +// require.NoError(t, err) - g1GenBytes := g1Gen.Bytes() - isFirstProposal := state.proposerTracker.rG == g1GenBytes - - var whiskTracker WhiskTracker - var whiskRegistrationProof TrackerProofBytes - var whiskKCommitment G1PointBytes - if isFirstProposal { - // First proposal, validator creates tracker for registering - whiskTracker = generateTracker(t, rand, proposerK) - whiskKCommitment = getKComm(proposerK) - whiskRegistrationProof, err = GenerateWhiskTrackerProof(whiskTracker, proposerK, rand) - require.NoError(t, err) - } else { - // And subsequent proposals leave registration fields empty - whiskTracker = computeTracker(fr.One(), fr.One()) - whiskKCommitment = getKComm(fr.One()) - } - - var kPrevProposal fr.Element - if isFirstProposal { - // On first proposal the k is computed deterministically and known to all - kPrevProposal = fr.NewElement(proposerIndex) - } else { - // Subsequent proposals use same k for registered tracker - kPrevProposal = proposerK - } - - whiskOpeningProof, err := GenerateWhiskTrackerProof(state.proposerTracker, kPrevProposal, rand) - require.NoError(t, err) +// g1GenBytes := g1Gen.Bytes() +// isFirstProposal := state.proposerTracker.rG == g1GenBytes + +// var whiskTracker WhiskTracker +// var whiskRegistrationProof TrackerProofBytes +// var whiskKCommitment G1PointBytes +// if isFirstProposal { +// // First proposal, validator creates tracker for registering +// whiskTracker = generateTracker(t, rand, proposerK) +// whiskKCommitment = getKComm(proposerK) +// whiskRegistrationProof, err = GenerateWhiskTrackerProof(whiskTracker, proposerK, rand) +// require.NoError(t, err) +// } else { +// // And subsequent proposals leave registration fields empty +// whiskTracker = computeTracker(fr.One(), fr.One()) +// whiskKCommitment = getKComm(fr.One()) +// } - return &Block{ - whiskOpeningProof, - whiskPostShuffleTrackers, - whiskShuffleProof, - whiskRegistrationProof, - whiskTracker, - whiskKCommitment, - } -} +// var kPrevProposal fr.Element +// if isFirstProposal { +// // On first proposal the k is computed deterministically and known to all +// kPrevProposal = fr.NewElement(proposerIndex) +// } else { +// // Subsequent proposals use same k for registered tracker +// kPrevProposal = proposerK +// } + +// whiskOpeningProof, err := GenerateWhiskTrackerProof(state.proposerTracker, kPrevProposal, rand) +// require.NoError(t, err) + +// return &Block{ +// whiskOpeningProof, +// whiskPostShuffleTrackers, +// whiskShuffleProof, +// whiskRegistrationProof, +// whiskTracker, +// whiskKCommitment, +// } +// }