You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.0 KiB

  1. package prover
  2. import (
  3. "math/big"
  4. bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
  5. cryptoConstants "github.com/iden3/go-iden3-crypto/constants"
  6. )
  7. type TableG1 struct{
  8. data []*bn256.G1
  9. }
  10. func (t TableG1) GetData() []*bn256.G1 {
  11. return t.data
  12. }
  13. // Compute table of gsize elements as ::
  14. // Table[0] = Inf
  15. // Table[1] = a[0]
  16. // Table[2] = a[1]
  17. // Table[3] = a[0]+a[1]
  18. // .....
  19. // Table[(1<<gsize)-1] = a[0]+a[1]+...+a[gsize-1]
  20. func (t *TableG1) NewTableG1(a []*bn256.G1, gsize int){
  21. // EC table
  22. table := make([]*bn256.G1, 0)
  23. // We need at least gsize elements. If not enough, fill with 0
  24. a_ext := make([]*bn256.G1, 0)
  25. a_ext = append(a_ext, a...)
  26. for i:=len(a); i<gsize; i++ {
  27. a_ext = append(a_ext,new(bn256.G1).ScalarBaseMult(big.NewInt(0)))
  28. }
  29. elG1 := new(bn256.G1).ScalarBaseMult(big.NewInt(0))
  30. table = append(table,elG1)
  31. last_pow2 := 1
  32. nelems := 0
  33. for i :=1; i< 1<<gsize; i++ {
  34. elG1 := new(bn256.G1)
  35. // if power of 2
  36. if i & (i-1) == 0{
  37. last_pow2 = i
  38. elG1.Set(a_ext[nelems])
  39. nelems++
  40. } else {
  41. elG1.Add(table[last_pow2], table[i-last_pow2])
  42. // TODO bn256 doesn't export MakeAffine function. We need to fork repo
  43. //table[i].MakeAffine()
  44. }
  45. table = append(table, elG1)
  46. }
  47. t.data = table
  48. }
  49. // Multiply scalar by precomputed table of G1 elements
  50. func (t *TableG1) MulTableG1(k []*big.Int, gsize int) *bn256.G1 {
  51. // We need at least gsize elements. If not enough, fill with 0
  52. k_ext := make([]*big.Int, 0)
  53. k_ext = append(k_ext, k...)
  54. for i:=len(k); i < gsize; i++ {
  55. k_ext = append(k_ext,new(big.Int).SetUint64(0))
  56. }
  57. Q := new(bn256.G1).ScalarBaseMult(big.NewInt(0))
  58. msb := getMsb(k_ext)
  59. for i := msb-1; i >= 0; i-- {
  60. // TODO. bn256 doesn't export double operation. We will need to fork repo and export it
  61. Q = new(bn256.G1).Add(Q,Q)
  62. b := getBit(k_ext,i)
  63. if b != 0 {
  64. // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
  65. Q.Add(Q, t.data[b])
  66. }
  67. }
  68. return Q
  69. }
  70. // Multiply scalar by precomputed table of G1 elements without intermediate doubling
  71. func MulTableNoDoubleG1(t []TableG1, k []*big.Int, gsize int) *bn256.G1 {
  72. // We need at least gsize elements. If not enough, fill with 0
  73. min_nelems := len(t) * gsize
  74. k_ext := make([]*big.Int, 0)
  75. k_ext = append(k_ext, k...)
  76. for i := len(k); i < min_nelems; i++ {
  77. k_ext = append(k_ext,new(big.Int).SetUint64(0))
  78. }
  79. // Init Adders
  80. nbitsQ := cryptoConstants.Q.BitLen()
  81. Q := make([]*bn256.G1,nbitsQ)
  82. for i:=0; i< nbitsQ; i++ {
  83. Q[i] = new(bn256.G1).ScalarBaseMult(big.NewInt(0))
  84. }
  85. // Perform bitwise addition
  86. for j:=0; j < len(t); j++ {
  87. msb := getMsb(k_ext[j*gsize:(j+1)*gsize])
  88. for i := msb-1; i >= 0; i-- {
  89. b := getBit(k_ext[j*gsize:(j+1)*gsize],i)
  90. if b != 0 {
  91. // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
  92. Q[i].Add(Q[i], t[j].data[b])
  93. }
  94. }
  95. }
  96. // Consolidate Addition
  97. R := new(bn256.G1).Set(Q[nbitsQ-1])
  98. for i:=nbitsQ-1; i>0; i-- {
  99. // TODO. bn256 doesn't export double operation. We will need to fork repo and export it
  100. R = new(bn256.G1).Add(R,R)
  101. R.Add(R,Q[i-1])
  102. }
  103. return R
  104. }
  105. // Compute tables within function. This solution should still be faster than std multiplication
  106. // for gsize = 7
  107. func ScalarMult(a []*bn256.G1, k []*big.Int, gsize int) *bn256.G1 {
  108. ntables := int((len(a) + gsize - 1) / gsize)
  109. table := TableG1{}
  110. Q:= new(bn256.G1).ScalarBaseMult(new(big.Int))
  111. for i:=0; i<ntables-1; i++ {
  112. table.NewTableG1( a[i*gsize:(i+1)*gsize], gsize)
  113. Q.Add(Q,table.MulTableG1(k[i*gsize:(i+1)*gsize], gsize))
  114. }
  115. table.NewTableG1( a[(ntables-1)*gsize:], gsize)
  116. Q.Add(Q,table.MulTableG1(k[(ntables-1)*gsize:], gsize))
  117. return Q
  118. }
  119. // Multiply scalar by precomputed table of G1 elements without intermediate doubling
  120. func ScalarMultNoDoubleG1(a []*bn256.G1, k []*big.Int, gsize int) *bn256.G1 {
  121. ntables := int((len(a) + gsize - 1) / gsize)
  122. table := TableG1{}
  123. // We need at least gsize elements. If not enough, fill with 0
  124. min_nelems := ntables * gsize
  125. k_ext := make([]*big.Int, 0)
  126. k_ext = append(k_ext, k...)
  127. for i := len(k); i < min_nelems; i++ {
  128. k_ext = append(k_ext,new(big.Int).SetUint64(0))
  129. }
  130. // Init Adders
  131. nbitsQ := cryptoConstants.Q.BitLen()
  132. Q := make([]*bn256.G1,nbitsQ)
  133. for i:=0; i< nbitsQ; i++ {
  134. Q[i] = new(bn256.G1).ScalarBaseMult(big.NewInt(0))
  135. }
  136. // Perform bitwise addition
  137. for j:=0; j < ntables-1; j++ {
  138. table.NewTableG1( a[j*gsize:(j+1)*gsize], gsize)
  139. msb := getMsb(k_ext[j*gsize:(j+1)*gsize])
  140. for i := msb-1; i >= 0; i-- {
  141. b := getBit(k_ext[j*gsize:(j+1)*gsize],i)
  142. if b != 0 {
  143. // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
  144. Q[i].Add(Q[i], table.data[b])
  145. }
  146. }
  147. }
  148. table.NewTableG1( a[(ntables-1)*gsize:], gsize)
  149. msb := getMsb(k_ext[(ntables-1)*gsize:])
  150. for i := msb-1; i >= 0; i-- {
  151. b := getBit(k_ext[(ntables-1)*gsize:],i)
  152. if b != 0 {
  153. // TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
  154. Q[i].Add(Q[i], table.data[b])
  155. }
  156. }
  157. // Consolidate Addition
  158. R := new(bn256.G1).Set(Q[nbitsQ-1])
  159. for i:=nbitsQ-1; i>0; i-- {
  160. // TODO. bn256 doesn't export double operation. We will need to fork repo and export it
  161. R = new(bn256.G1).Add(R,R)
  162. R.Add(R,Q[i-1])
  163. }
  164. return R
  165. }
  166. // Return most significant bit position in a group of Big Integers
  167. func getMsb(k []*big.Int) int{
  168. msb := 0
  169. for _, el := range(k){
  170. tmp_msb := el.BitLen()
  171. if tmp_msb > msb {
  172. msb = tmp_msb
  173. }
  174. }
  175. return msb
  176. }
  177. // Return ith bit in group of Big Integers
  178. func getBit(k []*big.Int, i int) uint {
  179. table_idx := uint(0)
  180. for idx, el := range(k){
  181. b := el.Bit(i)
  182. table_idx += (b << idx)
  183. }
  184. return table_idx
  185. }