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.

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