nova-simplified.sage 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/env sage
  2. """
  3. Implements the simplified Nova scheme introduced in [1] Section 5.1
  4. [1] Nova: Recursive Zero-Knowledge Arguments from Folding Schemes
  5. https://eprint.iacr.org/2021/370.pdf
  6. [2] Nova: The ZK Bug of the Year (by Wilson Nguyen)
  7. https://www.youtube.com/watch?v=SOAQCL1NaYY
  8. """
  9. q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
  10. K = GF(q)
  11. hash_table = {}
  12. def hash(key):
  13. if key in hash_table:
  14. return hash_table[key]
  15. c = K.random_element()
  16. while c > 2**250 - 1:
  17. c = K.random_element()
  18. hash_table[key] = c
  19. return c
  20. def fold(U, u):
  21. return U + (u,)
  22. z0 = 5
  23. F = lambda z, ω: 5*z
  24. i = 0
  25. ω0 = ()
  26. z1 = F(z0, ω0)
  27. u1 = hash((1, z0, z1, ()))
  28. U1 = ()
  29. # ZK proof
  30. assert u1 == hash((1, z0, z1, ()))
  31. assert z1 == F(z0, ω0)
  32. i = 1
  33. ω1 = ()
  34. U2 = fold(U1, u1)
  35. z2 = F(z1, ω1)
  36. u2 = hash((i+1, z0, z2, U2))
  37. assert u1 == hash((i, z0, z1, U1))
  38. assert U2 == fold(U1, u1)
  39. assert z2 == F(z1, ω1)
  40. assert u2 == hash((i+1, z0, z2, U2))
  41. i = 2
  42. ω2 = ()
  43. U3 = fold(U2, u2)
  44. z3 = F(z2, ω2)
  45. u3 = hash((i+1, z0, z3, U3))
  46. assert u2 == hash((i, z0, z2, U2))
  47. assert U3 == fold(U2, u2)
  48. assert z3 == F(z2, ω2)
  49. assert u3 == hash((i+1, z0, z3, U3))
  50. # By folding proofs, we simultaneously verify all the asserts
  51. # when verifying U3 with u3.
  52. # Although there is no connection between u2 in i=1, and u2 in i=2,
  53. # by including the satisfying accumulator U2, and proving U3 = fold(U2, u2),
  54. # we guarantee the recursive nature of the circuit.
  55. # We've now made a proof of what 5^4 is
  56. assert z0 == 5
  57. assert z1 == 5*5
  58. assert z2 == 5*5*5
  59. assert z3 == 5^(i+2)