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.

160 lines
4.0 KiB

  1. package snark
  2. import (
  3. "fmt"
  4. "math/big"
  5. "strings"
  6. "testing"
  7. "github.com/arnaucube/go-snark/bn128"
  8. "github.com/arnaucube/go-snark/circuitcompiler"
  9. "github.com/arnaucube/go-snark/fields"
  10. "github.com/arnaucube/go-snark/r1csqap"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestZkFromFlatCircuitCode(t *testing.T) {
  14. bn, err := bn128.NewBn128()
  15. assert.Nil(t, err)
  16. // new Finite Field
  17. fqR := fields.NewFq(bn.R)
  18. // new Polynomial Field
  19. pf := r1csqap.NewPolynomialField(fqR)
  20. // compile circuit and get the R1CS
  21. flatCode := `
  22. func test(x):
  23. aux = x*x
  24. y = aux*x
  25. z = x + y
  26. out = z + 5
  27. `
  28. fmt.Print("\nflat code of the circuit:")
  29. fmt.Println(flatCode)
  30. // parse the code
  31. parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
  32. circuit, err := parser.Parse()
  33. assert.Nil(t, err)
  34. fmt.Println("\ncircuit data:", circuit)
  35. b3 := big.NewInt(int64(3))
  36. inputs := []*big.Int{b3}
  37. // wittness
  38. w := circuit.CalculateWitness(inputs)
  39. fmt.Println("\nwitness", w)
  40. // flat code to R1CS
  41. fmt.Println("\ngenerating R1CS from flat code")
  42. a, b, c := circuit.GenerateR1CS()
  43. fmt.Println("\nR1CS:")
  44. fmt.Println("a:", a)
  45. fmt.Println("b:", b)
  46. fmt.Println("c:", c)
  47. alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c)
  48. ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
  49. hx := pf.DivisorPolinomial(px, zx)
  50. // hx==px/zx so px==hx*zx
  51. assert.Equal(t, px, pf.Mul(hx, zx))
  52. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  53. abc := pf.Sub(pf.Mul(ax, bx), cx)
  54. assert.Equal(t, abc, px)
  55. hz := pf.Mul(hx, zx)
  56. assert.Equal(t, abc, hz)
  57. div, rem := pf.Div(px, zx)
  58. assert.Equal(t, hx, div)
  59. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  60. // calculate trusted setup
  61. setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), *circuit, alphas, betas, gammas, zx)
  62. assert.Nil(t, err)
  63. fmt.Println("\nt:", setup.Toxic.T)
  64. // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
  65. proof, err := GenerateProofs(bn, fqR, *circuit, setup, hx, w)
  66. assert.Nil(t, err)
  67. assert.True(t, VerifyProof(bn, *circuit, setup, proof))
  68. }
  69. func TestZkFromHardcodedR1CS(t *testing.T) {
  70. bn, err := bn128.NewBn128()
  71. assert.Nil(t, err)
  72. // new Finite Field
  73. fqR := fields.NewFq(bn.R)
  74. // new Polynomial Field
  75. pf := r1csqap.NewPolynomialField(fqR)
  76. b0 := big.NewInt(int64(0))
  77. b1 := big.NewInt(int64(1))
  78. b3 := big.NewInt(int64(3))
  79. b5 := big.NewInt(int64(5))
  80. b9 := big.NewInt(int64(9))
  81. b27 := big.NewInt(int64(27))
  82. b30 := big.NewInt(int64(30))
  83. b35 := big.NewInt(int64(35))
  84. a := [][]*big.Int{
  85. []*big.Int{b0, b1, b0, b0, b0, b0},
  86. []*big.Int{b0, b0, b0, b1, b0, b0},
  87. []*big.Int{b0, b1, b0, b0, b1, b0},
  88. []*big.Int{b5, b0, b0, b0, b0, b1},
  89. }
  90. b := [][]*big.Int{
  91. []*big.Int{b0, b1, b0, b0, b0, b0},
  92. []*big.Int{b0, b1, b0, b0, b0, b0},
  93. []*big.Int{b1, b0, b0, b0, b0, b0},
  94. []*big.Int{b1, b0, b0, b0, b0, b0},
  95. }
  96. c := [][]*big.Int{
  97. []*big.Int{b0, b0, b0, b1, b0, b0},
  98. []*big.Int{b0, b0, b0, b0, b1, b0},
  99. []*big.Int{b0, b0, b0, b0, b0, b1},
  100. []*big.Int{b0, b0, b1, b0, b0, b0},
  101. }
  102. alphas, betas, gammas, zx := pf.R1CSToQAP(a, b, c)
  103. // wittness = 1, 3, 35, 9, 27, 30
  104. w := []*big.Int{b1, b3, b35, b9, b27, b30}
  105. circuit := circuitcompiler.Circuit{
  106. NVars: 6,
  107. NPublic: 0,
  108. NSignals: len(w),
  109. }
  110. ax, bx, cx, px := pf.CombinePolynomials(w, alphas, betas, gammas)
  111. hx := pf.DivisorPolinomial(px, zx)
  112. // hx==px/zx so px==hx*zx
  113. assert.Equal(t, px, pf.Mul(hx, zx))
  114. // p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
  115. abc := pf.Sub(pf.Mul(ax, bx), cx)
  116. assert.Equal(t, abc, px)
  117. hz := pf.Mul(hx, zx)
  118. assert.Equal(t, abc, hz)
  119. div, rem := pf.Div(px, zx)
  120. assert.Equal(t, hx, div)
  121. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
  122. // calculate trusted setup
  123. setup, err := GenerateTrustedSetup(bn, fqR, pf, len(w), circuit, alphas, betas, gammas, zx)
  124. assert.Nil(t, err)
  125. fmt.Println("t", setup.Toxic.T)
  126. // piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
  127. proof, err := GenerateProofs(bn, fqR, circuit, setup, hx, w)
  128. assert.Nil(t, err)
  129. assert.True(t, VerifyProof(bn, circuit, setup, proof))
  130. }