mirror of
https://github.com/0xPARC/plonkathon.git
synced 2026-01-08 21:28:02 -05:00
add more notes to README
This commit is contained in:
23
README.md
23
README.md
@@ -2,13 +2,29 @@
|
||||
**PlonKathon** is part of the program for [MIT IAP 2023] [Modern Zero Knowledge Cryptography](https://zkiap.com/). Over the course of this weekend, we will get into the weeds of the PlonK protocol through a series of exercises and extensions. This repository contains a simple python implementation of PlonK adapted from [py_plonk](https://github.com/ethereum/research/tree/master/py_plonk), and targeted to be close to compatible with the implementation at https://zkrepl.dev.
|
||||
|
||||
### Exercises
|
||||
#### Prover
|
||||
|
||||
Each step of the exercise is accompanied by tests in `test.py` to check your progress.
|
||||
|
||||
#### Step 1: Implement setup.py
|
||||
|
||||
Implement `Setup.commit` and `Setup.verification_key`.
|
||||
|
||||
#### Step 2: Implement prover.py
|
||||
|
||||
1. Implement Round 1 of the PlonK prover
|
||||
2. Implement Round 2 of the PlonK prover
|
||||
3. Implement Round 3 of the PlonK prover
|
||||
4. Implement Round 4 of the PlonK prover
|
||||
5. Implement Round 5 of the PlonK prover
|
||||
|
||||
#### Step 3: Implement verifier.py
|
||||
|
||||
Implement `VerificationKey.verify_proof_unoptimized` and `VerificationKey.verify_proof`. See the comments for the differences.
|
||||
|
||||
#### Step 4: Pass all the tests!
|
||||
|
||||
Pass a number of miscellaneous tests that test your implementation end-to-end.
|
||||
|
||||
### Extensions
|
||||
1. Add support for custom gates.
|
||||
[TurboPlonK](https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf) introduced support for custom constraints, beyond the addition and multiplication gates supported here. Try to generalise this implementation to allow circuit writers to define custom constraints.
|
||||
@@ -26,6 +42,11 @@ To get started, you'll need to have a Python version >= 3.8 and [`poetry`](https
|
||||
Then, run `poetry install` in the root of the repository. This will install all the dependencies in a virtualenv.
|
||||
|
||||
Then, to see the proof system in action, run `poetry run python test.py` from the root of the repository. This will take you through the workflow of setup, proof generation, and verification for several example programs.
|
||||
|
||||
The `main` branch contains code stubbed out with comments to guide you through the tests. The `hardcore` branch removes the comments for the more adventurous amongst you. The `reference` branch contains a completed implementation.
|
||||
|
||||
For linting and types, the repo also provides `poetry run black .` and `poetry run mypy .`
|
||||
|
||||
### Compiler
|
||||
#### Program
|
||||
We specify our program logic in a high-level language involving constraints and variable assignments. Here is a program that lets you prove that you know two small numbers that multiply to a given number (in our example we'll use 91) without revealing what those numbers are:
|
||||
|
||||
10
prover.py
10
prover.py
@@ -114,7 +114,7 @@ class Prover:
|
||||
+ self.pk.QC
|
||||
== Polynomial([Scalar(0)] * group_order, Basis.LAGRANGE)
|
||||
)
|
||||
|
||||
|
||||
# Return a_1, b_1, c_1
|
||||
return Message1(a_1, b_1, c_1)
|
||||
|
||||
@@ -124,7 +124,7 @@ class Prover:
|
||||
|
||||
# Using A, B, C, values, and pk.S1, pk.S2, pk.S3, compute
|
||||
# Z_values for permutation grand product polynomial Z
|
||||
#
|
||||
#
|
||||
# Note the convenience function:
|
||||
# self.rlc(val1, val2) = val_1 + self.beta * val_2 + gamma
|
||||
|
||||
@@ -190,13 +190,13 @@ class Prover:
|
||||
# equations are true at all roots of unity {1, w ... w^(n-1)}:
|
||||
# 1. All gates are correct:
|
||||
# A * QL + B * QR + A * B * QM + C * QO + PI + QC = 0
|
||||
#
|
||||
#
|
||||
# 2. The permutation accumulator is valid:
|
||||
# Z(wx) = Z(x) * (rlc of A, X, 1) * (rlc of B, 2X, 1) *
|
||||
# (rlc of C, 3X, 1) / (rlc of A, S1, 1) /
|
||||
# (rlc of B, S2, 1) / (rlc of C, S3, 1)
|
||||
# rlc = random linear combination: term_1 + beta * term2 + gamma * term3
|
||||
#
|
||||
#
|
||||
# 3. The permutation accumulator equals 1 at the start point
|
||||
# (Z - 1) * L0 = 0
|
||||
# L0 = Lagrange polynomial, equal at all roots of unity except 1
|
||||
@@ -227,7 +227,7 @@ class Prover:
|
||||
|
||||
def round_4(self) -> Message4:
|
||||
# Compute evaluations to be used in constructing the linearization polynomial.
|
||||
|
||||
|
||||
# Compute a_eval = A(zeta)
|
||||
# Compute b_eval = B(zeta)
|
||||
# Compute c_eval = C(zeta)
|
||||
|
||||
20
test.py
20
test.py
@@ -10,18 +10,30 @@ import json
|
||||
from test.mini_poseidon import rc, mds, poseidon_hash
|
||||
from utils import *
|
||||
|
||||
|
||||
def setup_test():
|
||||
print("===setup_test===")
|
||||
|
||||
setup = Setup.from_file("test/powersOfTau28_hez_final_11.ptau")
|
||||
dummy_values = Polynomial(list(map(Scalar, [1, 2, 3, 4, 5, 6, 7, 8])), Basis.LAGRANGE)
|
||||
dummy_values = Polynomial(
|
||||
list(map(Scalar, [1, 2, 3, 4, 5, 6, 7, 8])), Basis.LAGRANGE
|
||||
)
|
||||
program = Program(["c <== a * b"], 8)
|
||||
commitment = setup.commit(dummy_values)
|
||||
assert commitment == G1Point((16120260411117808045030798560855586501988622612038310041007562782458075125622, 3125847109934958347271782137825877642397632921923926105820408033549219695465))
|
||||
assert commitment == G1Point(
|
||||
(
|
||||
16120260411117808045030798560855586501988622612038310041007562782458075125622,
|
||||
3125847109934958347271782137825877642397632921923926105820408033549219695465,
|
||||
)
|
||||
)
|
||||
vk = setup.verification_key(program.common_preprocessed_input())
|
||||
assert vk.w == 19540430494807482326159819597004422086093766032135589407132600596362845576832
|
||||
assert (
|
||||
vk.w
|
||||
== 19540430494807482326159819597004422086093766032135589407132600596362845576832
|
||||
)
|
||||
print("Successfully created dummy commitment and verification key")
|
||||
|
||||
|
||||
def basic_test():
|
||||
print("===basic_test===")
|
||||
|
||||
@@ -121,7 +133,6 @@ def prover_test_dummy_verifier(setup):
|
||||
print("Prover test with dummy verifier success")
|
||||
|
||||
|
||||
|
||||
def prover_test(setup):
|
||||
print("===prover_test===")
|
||||
|
||||
@@ -257,7 +268,6 @@ if __name__ == "__main__":
|
||||
# Step 2: Pass prover test using verifier we provide (DO NOT READ TEST VERIFIER CODE)
|
||||
prover_test_dummy_verifier(setup)
|
||||
|
||||
|
||||
# Step 3: Pass verifier test using your own verifier
|
||||
with open("test/proof.pickle", "rb") as f:
|
||||
proof = pickle.load(f)
|
||||
|
||||
@@ -67,7 +67,7 @@ class VerificationKey:
|
||||
#
|
||||
# so at this point we can take a random linear combination of the two
|
||||
# checks, and verify it with only one pairing.
|
||||
|
||||
|
||||
return False
|
||||
|
||||
# Basic, easier-to-understand version of what's going on
|
||||
@@ -82,12 +82,12 @@ class VerificationKey:
|
||||
|
||||
# Recover the commitment to the linearization polynomial R,
|
||||
# exactly the same as what was created by the prover
|
||||
|
||||
|
||||
# Verify that R(z) = 0 and the prover-provided evaluations
|
||||
# A(z), B(z), C(z), S1(z), S2(z) are all correct
|
||||
|
||||
# Verify that the provided value of Z(zeta*w) is correct
|
||||
|
||||
|
||||
return False
|
||||
|
||||
# Compute challenges (should be same as those computed by prover)
|
||||
|
||||
Reference in New Issue
Block a user