From 8c81f5041ec12016abb602f0432651cf183f0088 Mon Sep 17 00:00:00 2001 From: druiz0992 Date: Sun, 3 May 2020 03:02:49 +0200 Subject: [PATCH] G1 Functionality to precomput G1 tables --- prover/gextra.go | 218 ++++++++++++++++++++++++++++++++++++++++++ prover/gextra_test.go | 96 +++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 prover/gextra.go create mode 100644 prover/gextra_test.go diff --git a/prover/gextra.go b/prover/gextra.go new file mode 100644 index 0000000..84a751d --- /dev/null +++ b/prover/gextra.go @@ -0,0 +1,218 @@ +package prover + +import ( + "math/big" + bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" + cryptoConstants "github.com/iden3/go-iden3-crypto/constants" + //"fmt" +) + +type TableG1 struct{ + data []*bn256.G1 +} + +func (t TableG1) GetData() []*bn256.G1 { + return t.data +} + + +// Compute table of gsize elements as :: +// Table[0] = Inf +// Table[1] = a[0] +// Table[2] = a[1] +// Table[3] = a[0]+a[1] +// ..... +// Table[(1<= 0; i-- { + // TODO. bn256 doesn't export double operation. We will need to fork repo and export it + Q = new(bn256.G1).Add(Q,Q) + b := getBit(k_ext,i) + if b != 0 { + // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient. + Q.Add(Q, t.data[b]) + } + } + return Q +} + +// Multiply scalar by precomputed table of G1 elements without intermediate doubling +func MulTableNoDoubleG1(t []TableG1, k []*big.Int, gsize int) *bn256.G1 { + // We need at least gsize elements. If not enough, fill with 0 + min_nelems := len(t) * gsize + k_ext := make([]*big.Int, 0) + k_ext = append(k_ext, k...) + for i := len(k); i < min_nelems; i++ { + k_ext = append(k_ext,new(big.Int).SetUint64(0)) + } + // Init Adders + nbitsQ := cryptoConstants.Q.BitLen() + Q := make([]*bn256.G1,nbitsQ) + + for i:=0; i< nbitsQ; i++ { + Q[i] = new(bn256.G1).ScalarBaseMult(big.NewInt(0)) + } + + // Perform bitwise addition + for j:=0; j < len(t); j++ { + msb := getMsb(k_ext[j*gsize:(j+1)*gsize]) + + for i := msb-1; i >= 0; i-- { + b := getBit(k_ext[j*gsize:(j+1)*gsize],i) + if b != 0 { + // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient. + Q[i].Add(Q[i], t[j].data[b]) + } + } + } + + // Consolidate Addition + R := new(bn256.G1).Set(Q[nbitsQ-1]) + for i:=nbitsQ-1; i>0; i-- { + // TODO. bn256 doesn't export double operation. We will need to fork repo and export it + R = new(bn256.G1).Add(R,R) + R.Add(R,Q[i-1]) + } + return R +} + +// Compute tables within function. This solution should still be faster than std multiplication +// for gsize = 7 +func ScalarMult(a []*bn256.G1, k []*big.Int, gsize int) *bn256.G1 { + ntables := int((len(a) + gsize - 1) / gsize) + table := TableG1{} + Q:= new(bn256.G1).ScalarBaseMult(new(big.Int)) + + for i:=0; i= 0; i-- { + b := getBit(k_ext[j*gsize:(j+1)*gsize],i) + if b != 0 { + // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient. + Q[i].Add(Q[i], table.data[b]) + } + } + } + table.NewTableG1( a[(ntables-1)*gsize:], gsize) + msb := getMsb(k_ext[(ntables-1)*gsize:]) + + for i := msb-1; i >= 0; i-- { + b := getBit(k_ext[(ntables-1)*gsize:],i) + if b != 0 { + // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient. + Q[i].Add(Q[i], table.data[b]) + } + } + + // Consolidate Addition + R := new(bn256.G1).Set(Q[nbitsQ-1]) + for i:=nbitsQ-1; i>0; i-- { + // TODO. bn256 doesn't export double operation. We will need to fork repo and export it + R = new(bn256.G1).Add(R,R) + R.Add(R,Q[i-1]) + } + return R +} + +// Return most significant bit position in a group of Big Integers +func getMsb(k []*big.Int) int{ + msb := 0 + + for _, el := range(k){ + tmp_msb := el.BitLen() + if tmp_msb > msb { + msb = tmp_msb + } + } + return msb +} + +// Return ith bit in group of Big Integers +func getBit(k []*big.Int, i int) uint { + table_idx := uint(0) + + for idx, el := range(k){ + b := el.Bit(i) + table_idx += (b << idx) + } + return table_idx +} diff --git a/prover/gextra_test.go b/prover/gextra_test.go new file mode 100644 index 0000000..22f6747 --- /dev/null +++ b/prover/gextra_test.go @@ -0,0 +1,96 @@ +package prover + +import ( + "crypto/rand" + "math/big" + "testing" + bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" + "time" + "bytes" + "fmt" +) + +const ( + N = 5000 +) + +func randomBigIntArray(n int) []*big.Int{ + var p []*big.Int + for i := 0; i < n; i++ { + pi := randBI() + p = append(p, pi) + } + + return p +} + +func randomG1Array(n int) []*bn256.G1 { + arrayG1 := make([]*bn256.G1, n) + + for i:=0; i