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.

107 lines
2.9 KiB

  1. package groth16
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/big"
  6. "strings"
  7. "testing"
  8. "time"
  9. "github.com/arnaucube/go-snark-study/circuitcompiler"
  10. "github.com/arnaucube/go-snark-study/r1csqap"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestGroth16MinimalFlow(t *testing.T) {
  14. fmt.Println("testing Groth16 minimal flow")
  15. // circuit function
  16. // y = x^3 + x + 5
  17. code := `
  18. func main(private s0, public s1):
  19. s2 = s0 * s0
  20. s3 = s2 * s0
  21. s4 = s3 + s0
  22. s5 = s4 + 5
  23. equals(s1, s5)
  24. out = 1 * 1
  25. `
  26. fmt.Print("\ncode of the circuit:")
  27. // parse the code
  28. parser := circuitcompiler.NewParser(strings.NewReader(code))
  29. circuit, err := parser.Parse()
  30. assert.Nil(t, err)
  31. b3 := big.NewInt(int64(3))
  32. privateInputs := []*big.Int{b3}
  33. b35 := big.NewInt(int64(35))
  34. publicSignals := []*big.Int{b35}
  35. // wittness
  36. w, err := circuit.CalculateWitness(privateInputs, publicSignals)
  37. assert.Nil(t, err)
  38. // code to R1CS
  39. fmt.Println("\ngenerating R1CS from code")
  40. a, b, c := circuit.GenerateR1CS()
  41. fmt.Println("\nR1CS:")
  42. fmt.Println("a:", a)
  43. fmt.Println("b:", b)
  44. fmt.Println("c:", c)
  45. // R1CS to QAP
  46. // TODO zxQAP is not used and is an old impl, TODO remove
  47. alphas, betas, gammas, _ := Utils.PF.R1CSToQAP(a, b, c)
  48. fmt.Println("qap")
  49. assert.Equal(t, 8, len(alphas))
  50. assert.Equal(t, 8, len(alphas))
  51. assert.Equal(t, 8, len(alphas))
  52. assert.True(t, !bytes.Equal(alphas[1][1].Bytes(), big.NewInt(int64(0)).Bytes()))
  53. ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
  54. assert.Equal(t, 7, len(ax))
  55. assert.Equal(t, 7, len(bx))
  56. assert.Equal(t, 7, len(cx))
  57. assert.Equal(t, 13, len(px))
  58. // ---
  59. // from here is the GROTH16
  60. // ---
  61. // calculate trusted setup
  62. fmt.Println("groth")
  63. setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas)
  64. assert.Nil(t, err)
  65. fmt.Println("\nt:", setup.Toxic.T)
  66. hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z)
  67. div, rem := Utils.PF.Div(px, setup.Pk.Z)
  68. assert.Equal(t, hx, div)
  69. assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(6))
  70. // hx==px/zx so px==hx*zx
  71. assert.Equal(t, px, Utils.PF.Mul(hx, setup.Pk.Z))
  72. // check length of polynomials H(x) and Z(x)
  73. assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
  74. proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
  75. assert.Nil(t, err)
  76. // fmt.Println("\n proofs:")
  77. // fmt.Println(proof)
  78. // fmt.Println("public signals:", proof.PublicSignals)
  79. fmt.Println("\nsignals:", circuit.Signals)
  80. fmt.Println("witness:", w)
  81. b35Verif := big.NewInt(int64(35))
  82. publicSignalsVerif := []*big.Int{b35Verif}
  83. before := time.Now()
  84. assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
  85. fmt.Println("verify proof time elapsed:", time.Since(before))
  86. // check that with another public input the verification returns false
  87. bOtherWrongPublic := big.NewInt(int64(34))
  88. wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
  89. assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
  90. }