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.

275 lines
8.4 KiB

  1. // implementation of https://eprint.iacr.org/2016/260.pdf
  2. package proof
  3. import (
  4. "fmt"
  5. "math/big"
  6. "github.com/arnaucube/go-snark/circuit"
  7. )
  8. // Groth16Setup is Groth16 system setup structure
  9. type Groth16Setup struct {
  10. Toxic struct {
  11. T *big.Int // trusted setup secret
  12. Kalpha *big.Int
  13. Kbeta *big.Int
  14. Kgamma *big.Int
  15. Kdelta *big.Int
  16. } `json:"-"`
  17. // public
  18. Pk struct { // Proving Key
  19. BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
  20. Z []*big.Int
  21. G1 struct {
  22. Alpha [3]*big.Int
  23. Beta [3]*big.Int
  24. Delta [3]*big.Int
  25. At [][3]*big.Int // {a(τ)} from 0 to m
  26. BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
  27. }
  28. G2 struct {
  29. Beta [3][2]*big.Int
  30. Gamma [3][2]*big.Int
  31. Delta [3][2]*big.Int
  32. BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
  33. }
  34. PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
  35. }
  36. Vk struct {
  37. IC [][3]*big.Int
  38. G1 struct {
  39. Alpha [3]*big.Int
  40. }
  41. G2 struct {
  42. Beta [3][2]*big.Int
  43. Gamma [3][2]*big.Int
  44. Delta [3][2]*big.Int
  45. }
  46. }
  47. }
  48. // Groth16Proof is Groth16 proof structure
  49. type Groth16Proof struct {
  50. PiA [3]*big.Int
  51. PiB [3][2]*big.Int
  52. PiC [3]*big.Int
  53. }
  54. // Z is ...
  55. func (setup *Groth16Setup) Z() []*big.Int {
  56. return setup.Pk.Z
  57. }
  58. // Init setups the trusted setup from a compiled circuit
  59. func (setup *Groth16Setup) Init(cir *circuit.Circuit, alphas, betas, gammas [][]*big.Int) error {
  60. var err error
  61. setup.Toxic.T, err = Utils.FqR.Rand()
  62. if err != nil {
  63. return err
  64. }
  65. setup.Toxic.Kalpha, err = Utils.FqR.Rand()
  66. if err != nil {
  67. return err
  68. }
  69. setup.Toxic.Kbeta, err = Utils.FqR.Rand()
  70. if err != nil {
  71. return err
  72. }
  73. setup.Toxic.Kgamma, err = Utils.FqR.Rand()
  74. if err != nil {
  75. return err
  76. }
  77. setup.Toxic.Kdelta, err = Utils.FqR.Rand()
  78. if err != nil {
  79. return err
  80. }
  81. zpol := []*big.Int{big.NewInt(int64(1))}
  82. for i := 1; i < len(alphas)-1; i++ {
  83. zpol = Utils.PF.Mul(
  84. zpol,
  85. []*big.Int{
  86. Utils.FqR.Neg(
  87. big.NewInt(int64(i))),
  88. big.NewInt(int64(1)),
  89. })
  90. }
  91. setup.Pk.Z = zpol
  92. zt := Utils.PF.Eval(zpol, setup.Toxic.T)
  93. invDelta := Utils.FqR.Inverse(setup.Toxic.Kdelta)
  94. ztinvDelta := Utils.FqR.Mul(invDelta, zt)
  95. // encrypt t values with curve generators
  96. // powers of tau divided by delta
  97. var ptd [][3]*big.Int
  98. ini := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, ztinvDelta)
  99. ptd = append(ptd, ini)
  100. tEncr := setup.Toxic.T
  101. for i := 1; i < len(zpol); i++ {
  102. ptd = append(ptd, Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, Utils.FqR.Mul(tEncr, ztinvDelta)))
  103. tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T)
  104. }
  105. // powers of τ encrypted in G1 curve, divided by δ
  106. // (G1 * τ) / δ
  107. setup.Pk.PowersTauDelta = ptd
  108. setup.Pk.G1.Alpha = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kalpha)
  109. setup.Pk.G1.Beta = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kbeta)
  110. setup.Pk.G1.Delta = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kdelta)
  111. setup.Pk.G2.Beta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kbeta)
  112. setup.Pk.G2.Delta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kdelta)
  113. setup.Vk.G1.Alpha = Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, setup.Toxic.Kalpha)
  114. setup.Vk.G2.Beta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kbeta)
  115. setup.Vk.G2.Gamma = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kgamma)
  116. setup.Vk.G2.Delta = Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, setup.Toxic.Kdelta)
  117. for i := 0; i < len(cir.Signals); i++ {
  118. // Pk.G1.At: {a(τ)} from 0 to m
  119. at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
  120. a := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, at)
  121. setup.Pk.G1.At = append(setup.Pk.G1.At, a)
  122. bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
  123. g1bt := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, bt)
  124. g2bt := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, bt)
  125. // G1.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G1
  126. setup.Pk.G1.BACGamma = append(setup.Pk.G1.BACGamma, g1bt)
  127. // G2.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G2
  128. setup.Pk.G2.BACGamma = append(setup.Pk.G2.BACGamma, g2bt)
  129. }
  130. zero3 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
  131. for i := 0; i < cir.NPublic+1; i++ {
  132. setup.Pk.BACDelta = append(setup.Pk.BACDelta, zero3)
  133. }
  134. for i := cir.NPublic + 1; i < cir.NVars; i++ {
  135. // TODO calculate all at, bt, ct outside, to avoid repeating calculations
  136. at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
  137. bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
  138. ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
  139. c := Utils.FqR.Mul(
  140. invDelta,
  141. Utils.FqR.Add(
  142. Utils.FqR.Add(
  143. Utils.FqR.Mul(at, setup.Toxic.Kbeta),
  144. Utils.FqR.Mul(bt, setup.Toxic.Kalpha),
  145. ),
  146. ct,
  147. ),
  148. )
  149. g1c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, c)
  150. // Pk.BACDelta: {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
  151. setup.Pk.BACDelta = append(setup.Pk.BACDelta, g1c)
  152. }
  153. for i := 0; i <= cir.NPublic; i++ {
  154. at := Utils.PF.Eval(alphas[i], setup.Toxic.T)
  155. bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
  156. ct := Utils.PF.Eval(gammas[i], setup.Toxic.T)
  157. ic := Utils.FqR.Mul(
  158. Utils.FqR.Inverse(setup.Toxic.Kgamma),
  159. Utils.FqR.Add(
  160. Utils.FqR.Add(
  161. Utils.FqR.Mul(at, setup.Toxic.Kbeta),
  162. Utils.FqR.Mul(bt, setup.Toxic.Kalpha),
  163. ),
  164. ct,
  165. ),
  166. )
  167. g1ic := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, ic)
  168. // used in verifier
  169. setup.Vk.IC = append(setup.Vk.IC, g1ic)
  170. }
  171. return nil
  172. }
  173. // Generate generates Pinocchio proof
  174. func (setup Groth16Setup) Generate(cir *circuit.Circuit, w []*big.Int, px []*big.Int) (Proof, error) {
  175. proof := &Groth16Proof{}
  176. proof.PiA = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
  177. proof.PiB = Utils.Bn.Fq6.Zero()
  178. proof.PiC = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
  179. r, err := Utils.FqR.Rand()
  180. if err != nil {
  181. return &Groth16Proof{}, err
  182. }
  183. s, err := Utils.FqR.Rand()
  184. if err != nil {
  185. return &Groth16Proof{}, err
  186. }
  187. // piBG1 will hold all the same than proof.PiB but in G1 curve
  188. piBG1 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
  189. for i := 0; i < cir.NVars; i++ {
  190. proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(setup.Pk.G1.At[i], w[i]))
  191. piBG1 = Utils.Bn.G1.Add(piBG1, Utils.Bn.G1.MulScalar(setup.Pk.G1.BACGamma[i], w[i]))
  192. proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(setup.Pk.G2.BACGamma[i], w[i]))
  193. }
  194. for i := cir.NPublic + 1; i < cir.NVars; i++ {
  195. proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.BACDelta[i], w[i]))
  196. }
  197. // piA = (Σ from 0 to m (pk.A * w[i])) + pk.Alpha1 + r * δ
  198. proof.PiA = Utils.Bn.G1.Add(proof.PiA, setup.Pk.G1.Alpha)
  199. deltaR := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, r)
  200. proof.PiA = Utils.Bn.G1.Add(proof.PiA, deltaR)
  201. // piBG1 = (Σ from 0 to m (pk.B1 * w[i])) + pk.g1.Beta + s * δ
  202. // piB = piB2 = (Σ from 0 to m (pk.B2 * w[i])) + pk.g2.Beta + s * δ
  203. piBG1 = Utils.Bn.G1.Add(piBG1, setup.Pk.G1.Beta)
  204. proof.PiB = Utils.Bn.G2.Add(proof.PiB, setup.Pk.G2.Beta)
  205. deltaSG1 := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, s)
  206. piBG1 = Utils.Bn.G1.Add(piBG1, deltaSG1)
  207. deltaSG2 := Utils.Bn.G2.MulScalar(setup.Pk.G2.Delta, s)
  208. proof.PiB = Utils.Bn.G2.Add(proof.PiB, deltaSG2)
  209. hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
  210. // piC = (Σ from l+1 to m (w[i] * (pk.g1.Beta + pk.g1.Alpha + pk.C)) + h(tau)) / δ) + piA*s + r*piB - r*s*δ
  211. for i := 0; i < len(hx); i++ {
  212. proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.PowersTauDelta[i], hx[i]))
  213. }
  214. proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(proof.PiA, s))
  215. proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(piBG1, r))
  216. negRS := Utils.FqR.Neg(Utils.FqR.Mul(r, s))
  217. proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, negRS))
  218. return proof, nil
  219. }
  220. // Verify verifies over the BN128 the Pairings of the Proof
  221. func (setup Groth16Setup) Verify(proof Proof, publicSignals []*big.Int) (bool, error) {
  222. pproof, ok := proof.(*Groth16Proof)
  223. if !ok {
  224. return false, fmt.Errorf("bad proof type")
  225. }
  226. icPubl := setup.Vk.IC[0]
  227. for i := 0; i < len(publicSignals); i++ {
  228. icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
  229. }
  230. if !Utils.Bn.Fq12.Equal(
  231. Utils.Bn.Pairing(pproof.PiA, pproof.PiB),
  232. Utils.Bn.Fq12.Mul(
  233. Utils.Bn.Pairing(setup.Vk.G1.Alpha, setup.Vk.G2.Beta),
  234. Utils.Bn.Fq12.Mul(
  235. Utils.Bn.Pairing(icPubl, setup.Vk.G2.Gamma),
  236. Utils.Bn.Pairing(pproof.PiC, setup.Vk.G2.Delta),
  237. ),
  238. )) {
  239. return false, nil
  240. }
  241. return true, nil
  242. }