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.

302 lines
9.4 KiB

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