From 997fb4cce821a48ac40d0fff3fb9321122b07ef9 Mon Sep 17 00:00:00 2001 From: Nalin Bhardwaj Date: Sat, 28 Jan 2023 09:24:10 -0500 Subject: [PATCH] add more notes to README --- README.md | 23 ++++++++++++++++++++++- prover.py | 10 +++++----- test.py | 20 +++++++++++++++----- verifier.py | 6 +++--- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bc066f8..c0d2075 100644 --- a/README.md +++ b/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: diff --git a/prover.py b/prover.py index b86ca45..1354cdd 100644 --- a/prover.py +++ b/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) diff --git a/test.py b/test.py index bdc9597..206d20b 100644 --- a/test.py +++ b/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) diff --git a/verifier.py b/verifier.py index 6648791..ddc5bd9 100644 --- a/verifier.py +++ b/verifier.py @@ -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)