diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b10e619 --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module kzgceremony + +go 1.19 + +require ( + github.com/ethereum/go-ethereum v1.10.26 + github.com/frankban/quicktest v1.14.4 +) + +require ( + github.com/google/go-cmp v0.5.9 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..dcdad52 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= +github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/powersoftau.go b/powersoftau.go new file mode 100644 index 0000000..301718d --- /dev/null +++ b/powersoftau.go @@ -0,0 +1,79 @@ +package kzgceremony + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/crypto/bls12381" +) + +type Contribution struct { + SRS *SRS +} + +type SRS struct { + G1s []*bls12381.PointG1 + G2s []*bls12381.PointG2 +} + +type toxicWaste struct { + tau *big.Int + TauG2 *bls12381.PointG2 +} + +// newEmptySRS creates an empty SRS +func newEmptySRS(nG1, nG2 int) *SRS { + g1s := make([]*bls12381.PointG1, nG1) + g2s := make([]*bls12381.PointG2, nG2) + g1 := bls12381.NewG1() + g2 := bls12381.NewG2() + // one_G1 := g1.One() + // one_G2 := g2.One() + for i := 0; i < nG1; i++ { + g1s[i] = g1.One() + // g1.MulScalar(g1s[i], one_G1, big.NewInt(int64(i))) + } + for i := 0; i < nG2; i++ { + g2s[i] = g2.One() + // g2.MulScalar(g2s[i], one_G2, big.NewInt(int64(i))) + } + return &SRS{g1s, g2s} +} + +func tau(randomness []byte) *toxicWaste { + g2 := bls12381.NewG2() + tau := new(big.Int).Mod( + new(big.Int).SetBytes(randomness), + g2.Q()) + TauG2 := g2.New() + g2.MulScalar(TauG2, g2.One(), tau) + + return &toxicWaste{tau, TauG2} +} + +func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS { + srs := newEmptySRS(len(prevSRS.G1s), len(prevSRS.G2s)) + g1 := bls12381.NewG1() + g2 := bls12381.NewG2() + Q := g1.Q() // Q = |G1| == |G2| + + for i := 0; i < len(prevSRS.G1s); i++ { + tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q) + g1.MulScalar(srs.G1s[i], prevSRS.G1s[i], tau_i) + } + for i := 0; i < len(prevSRS.G2s); i++ { + tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q) + g2.MulScalar(srs.G2s[i], prevSRS.G2s[i], tau_i) + } + + return srs +} + +// Contribute +func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) { + // set tau from randomness + tw := tau(randomness) + + newSRS := computeContribution(tw, prevSRS) + + return Contribution{SRS: newSRS}, nil +} diff --git a/powersoftau_test.go b/powersoftau_test.go new file mode 100644 index 0000000..47ec836 --- /dev/null +++ b/powersoftau_test.go @@ -0,0 +1,19 @@ +package kzgceremony + +import ( + "testing" + + qt "github.com/frankban/quicktest" +) + +func TestContribute(t *testing.T) { + c := qt.New(t) + + srs_0 := newEmptySRS(10, 10) + + contr_1, err := Contribute(srs_0, []byte("1111111111111111111111111111111111111111111111111111111111111111")) + c.Assert(err, qt.IsNil) + + _, err = Contribute(contr_1.SRS, []byte("2222222222222222222222222222222222222222222222222222222222222222")) + c.Assert(err, qt.IsNil) +}