| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- #!/usr/bin/env sage
- """
- Implements the simplified Nova scheme introduced in [1] Section 5.1
- [1] Nova: Recursive Zero-Knowledge Arguments from Folding Schemes
- https://eprint.iacr.org/2021/370.pdf
- [2] Nova: The ZK Bug of the Year (by Wilson Nguyen)
- https://www.youtube.com/watch?v=SOAQCL1NaYY
- """
- q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
- K = GF(q)
- hash_table = {}
- def hash(key):
- if key in hash_table:
- return hash_table[key]
- c = K.random_element()
- while c > 2**250 - 1:
- c = K.random_element()
- hash_table[key] = c
- return c
- def fold(U, u):
- return U + (u,)
- z0 = 5
- F = lambda z, ω: 5*z
- i = 0
- ω0 = ()
- z1 = F(z0, ω0)
- u1 = hash((1, z0, z1, ()))
- U1 = ()
- # ZK proof
- assert u1 == hash((1, z0, z1, ()))
- assert z1 == F(z0, ω0)
- i = 1
- ω1 = ()
- U2 = fold(U1, u1)
- z2 = F(z1, ω1)
- u2 = hash((i+1, z0, z2, U2))
- assert u1 == hash((i, z0, z1, U1))
- assert U2 == fold(U1, u1)
- assert z2 == F(z1, ω1)
- assert u2 == hash((i+1, z0, z2, U2))
- i = 2
- ω2 = ()
- U3 = fold(U2, u2)
- z3 = F(z2, ω2)
- u3 = hash((i+1, z0, z3, U3))
- assert u2 == hash((i, z0, z2, U2))
- assert U3 == fold(U2, u2)
- assert z3 == F(z2, ω2)
- assert u3 == hash((i+1, z0, z3, U3))
- # By folding proofs, we simultaneously verify all the asserts
- # when verifying U3 with u3.
- # Although there is no connection between u2 in i=1, and u2 in i=2,
- # by including the satisfying accumulator U2, and proving U3 = fold(U2, u2),
- # we guarantee the recursive nature of the circuit.
- # We've now made a proof of what 5^4 is
- assert z0 == 5
- assert z1 == 5*5
- assert z2 == 5*5*5
- assert z3 == 5^(i+2)
|