Skip to content

Commit

Permalink
fix errors
Browse files Browse the repository at this point in the history
  • Loading branch information
diegokingston committed Aug 23, 2024
1 parent 00e1ee5 commit 7e3fe70
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 36 deletions.
3 changes: 3 additions & 0 deletions bootcamp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Public repository for exercises, challenges and all the needs of the Sparkling W
This first week will be focused on the development of one of the building blocks of Cryptography: Finite Fields.

### Recommended material:

- [An introduction to mathematical cryptography](https://books.google.com.ar/books/about/An_Introduction_to_Mathematical_Cryptogr.html?id=BHuTQgAACAAJ&source=kp_book_description&redir_esc=y) - Chapter 1.
- [Finite Fields](https://www.youtube.com/watch?v=MAhmV_omOwA&list=PLFX2cij7c2PynTNWDBzmzaD6ij170ILbQ&index=8)
- [Constructing finite fields](https://www.youtube.com/watch?v=JPiXFn9WA5Y&list=PLFX2cij7c2PynTNWDBzmzaD6ij170ILbQ&index=6)
Expand All @@ -15,12 +16,14 @@ This first week will be focused on the development of one of the building blocks
- [Mersenne primes](https://eprint.iacr.org/2023/824.pdf)

### Challenges:

- [Implement Montgomery backend for 32 bit fields](https://github.com/lambdaclass/lambdaworks/issues/538).
- [Implement efficient Mersenne prime backend](https://github.com/lambdaclass/lambdaworks/issues/540).
- [Implement efficient backend for pseudo-Mersenne primes](https://github.com/lambdaclass/lambdaworks/issues/393).
- Compare specific field implementations with ordinary Montgomery arithmetic.

### Cryptography content:

- [Serious Cryptography](https://books.google.com.ar/books/about/Serious_Cryptography.html?id=1D-QEAAAQBAJ&source=kp_book_description&redir_esc=y), Chapters 9 & 10.

### Exercises
Expand Down
1 change: 0 additions & 1 deletion crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[Latest Version]: https://img.shields.io/crates/v/lambdaworks-crypto.svg
[crates.io]: https://crates.io/crates/lambdaworks-crypto


## Usage

Add this to your `Cargo.toml`
Expand Down
3 changes: 1 addition & 2 deletions docs/src/plonk/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
- [Recap](./recap.md)
- [Protocol](./protocol.md)
- [Implementation](./implementation.md)
- [Circuit API](./constraint_system.md)

- [Circuit API](./constraint_system.md)
4 changes: 2 additions & 2 deletions docs/src/plonk/constraint_system.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Circuit API

In this section, we'll discuss how to build your own constraint system to prove the execution of a particular program.

## Simple Example
Expand Down Expand Up @@ -99,5 +100,4 @@ fn main() {
}
```

You can keep composing these functions in order to create more complex systems.

You can keep composing these functions in order to create more complex systems.
26 changes: 21 additions & 5 deletions docs/src/plonk/implementation.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Implementation

In this section we discuss the implementation details of the PLONK algorithm. We use the notation and terminology of the [protocol](./protocol.md) and [recap](./recap.md) sections.

At the moment our API supports the backend of PLONK. That is, all the setup, prove and verify algorithms. We temporarily rely on external sources for the definition of a circuit and the creation of the $Q$ and $V$ matrices, as well as the execution of it to obtain the trace matrix $T$. We mainly use gnark temporarily for that purpose.
At the moment our API supports the backend of PLONK, that is, all the setup, prove and verify algorithms. We temporarily rely on external sources for the definition of a circuit and the creation of the $Q$ and $V$ matrices, as well as the execution of it to obtain the trace matrix $T$. We mainly use gnark temporarily for that purpose.

To generate proofs and validate them, we need to feed the algorithms with precomputed values of the $Q$, $V$ and $T$ matrices, and the primitive root of unity $\omega$.

So to generate proofs and validate them, we need to feed the algorithms with precomputed values of the $Q$, $V$ and $T$ matrices, and the primitive root of unity $\omega$.
Let's see our API on a test circuit that provides all these values. The program in this case is the one that takes an input $x$, a private input $e$ and computes $y = xe + 5$. As in the toy example of the recap, the output of the program is added to the public inputs and the circuit actually asserts that the output is the claimed value. So more precisely, the prover will generate a proof for the statement `ASSERT(x*e+5==y)`, where both $x,y$ are public inputs.

Let us see our API on a test circuit that provides all these values. The program in this case is the one that takes an input $x$, a private input $e$ and computes $y = xe +5$. As in the toy example of the recap, the output of the program is added to the public inputs and the circuit actually asserts that the output is the claimed value. So more precisely, the prover will generate a proof for the statement `ASSERT(x*e+5==y)`, where both $x,y$ are public inputs.
# Usage

Here is the happy path.

```rust
Expand Down Expand Up @@ -90,16 +93,21 @@ pub struct Witness<F: IsField> {
pub c: Vec<FieldElement<F>>,
}
```

Next the commitment scheme KZG (Kate-Zaverucha-Goldberg) is instantiated.

```rust
let srs = test_srs(common_preprocessed_input.n);
let kzg = KZG::new(srs);
```
The `setup` function performs the setup phase. It only needs the common preprocessed input and the commitment scheme.

```rust
let verifying_key = setup(&common_preprocessed_input, &kzg);
```
It outputs an instance of the struct `VerificationKey`.

It outputs an instance of the struct `VerificationKey`:

```rust
pub struct VerificationKey<G1Point> {
pub qm_1: G1Point,
Expand All @@ -113,6 +121,7 @@ pub struct VerificationKey<G1Point> {
pub s3_1: G1Point,
}
```

It stores the commitments of the eight polynomials of the common preprocessed input. The suffix `_1` means it is a commitment. It comes from the notation $[f]_1$, where $f$ is a polynomial.

Then a prover is instantiated
Expand All @@ -133,6 +142,7 @@ where
phantom: PhantomData<F>,
}
```

It stores an instance of a commitment scheme and a random field element generator needed for blinding polynomials.

Then the public input is defined. As we mentioned in the recap, the public input contains the output of the program.
Expand All @@ -149,7 +159,9 @@ let proof = prover.prove(
&verifying_key,
);
```

The output is an instance of the struct `Proof`.

```rust
pub struct Proof<F: IsField, CS: IsCommitmentScheme<F>> {
// Round 1.
Expand Down Expand Up @@ -222,6 +234,7 @@ assert!(verifier.verify(
```

## Padding

All the matrices $Q, V, T, PI$ are padded with dummy rows so that their length is a power of two. To be able to interpolate their columns, we need a primitive root of unity $\omega$ of that order. Given the particular field used in our implementation, that means that the maximum possible size for a circuit is $2^{32}$.

The entries of the dummy rows are filled in with zeroes in the $Q$, $V$ and $PI$ matrices. The $T$ matrix needs to be consistent with the $V$ matrix. Therefore it is filled with the value of the variable with index $0$.
Expand All @@ -233,6 +246,7 @@ Some other rows in the $V$ matrix have also dummy values. These are the rows cor
The implementation pretty much follows the rounds as are described in the [protocol](./protocol.md) section. There are a few details that are worth mentioning.

## Commitment Scheme

The commitment scheme we use is the [Kate-Zaverucha-Goldberg](https://www.iacr.org/archive/asiacrypt2010/6477178/6477178.pdf) scheme with the `BLS 12 381` curve and the ate pairing. It can be found in the `commitments` module of the `lambdaworks_crypto` package.

The order $r$ of the cyclic subgroup is
Expand Down Expand Up @@ -271,12 +285,14 @@ The internal state of the hasher at the end of this exercise is `message_4 || Ha
The underlying hasher function we use is `h=sha3`.

### Field elements

The result of every challenge is a $256$-bit string, which is interpreted as an integer in big-endian order. A field element is constructed out of it by taking modulo the field order. The prime field used in this implementation has a $255$-bit order. Therefore some field elements are more probable to occur than others because they have more representatives as 256-bit integers.

### Strong Fiat-Shamir

The first messages added to the transcript are all commitments of the polynomials of the common preprocessed input and the values of the public inputs. This prevents a known vulnerability called "weak Fiat-Shamir".
Check out the following resources to learn more about it.

- [What can go wrong (zkdocs)](https://www.zkdocs.com/docs/zkdocs/protocol-primitives/fiat-shamir/#what-can-go-wrong)
- [How not to Prove Yourself: Pitfalls of the Fiat-Shamir Heuristic and Applications to Helios](https://eprint.iacr.org/2016/771.pdf)
- [Weak Fiat-Shamir Attacks on Modern Proof Systems](https://eprint.iacr.org/2023/691)
- [Weak Fiat-Shamir Attacks on Modern Proof Systems](https://eprint.iacr.org/2023/691)
3 changes: 1 addition & 2 deletions docs/src/plonk/plonk.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ We have written this document with the aim of making it accessible to both novic

- [Recap](./recap.md)
- [Protocol](./protocol.md)
- [Implementation](./implementation.md)

- [Implementation](./implementation.md)
27 changes: 13 additions & 14 deletions docs/src/plonk/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ As you will see in the protocol, the prover reveals the value taken by a bunch o

Let's take for example the polynomial $a$ the prover constructs. This is the interpolation of the first column of the trace matrix $T$ at the domain $H$.
This matrix has all of the left operands of all the gates. The prover wishes to keep them secret.
Say the trace matrix $T$ has $N$ rows. And so $H$ is $\{1, \omega,\omega^2, \dots, \omega^{N-1}\}$. The invariant that the prover cannot violate is that $a_{\text{blinded}}(\omega^i)$ must take the value $T_{0, i}$, for all $i$. This is what the interpolation polynomial $a$ satisfies. And is the unique such polynomial of degree at most $N-1$ with such property. But for higher degrees, there are many such polynomials.
Say the trace matrix $T$ has $N$ rows. $H$ is $\{1, \omega,\omega^2, \dots, \omega^{N - 1}\}$. The invariant that the prover cannot violate is that $a_{\text{blinded}}(\omega^i)$ must take the value $T_{0, i}$, for all $i$. This is what the interpolation polynomial $a$ satisfies. And is the unique such polynomial of degree at most $N - 1$ with such property. But for higher degrees, there are many such polynomials.

The _blinding_ process takes $a$ and a desired degree $M\geq N$, and produces a new polynomial $a_{\text{blinded}}$ of degree exactly $M$. This new polynomial satisfies that $a_{\text{blinded}}(\omega^i) = a(\omega^i)$ for all $i$. But outside $H$ differs from $a$.

This may seem hard but it's actually very simple. Let $z_H$ be the polynomial $z_H = X^N - 1$. If $M = N + k$, with $k \geq 0$, then sample random values $b_0, \dots, b_k$ and define
$$a_{\text{blinded}} := (b_0 + b_1 X + \cdots + b_k X^k )z_H + a$$

The reason why this does the job is that $z_H(\omega^i)=0$ for all $i$. Therefore the added term vanishes at $H$ and leaves the values of $a$ at $H$ unchanged.
The reason why this does the job is that $z_H(\omega^i) = 0$ for all $i$. Therefore the added term vanishes at $H$ and leaves the values of $a$ at $H$ unchanged.

### Linearization trick

Expand Down Expand Up @@ -128,7 +128,7 @@ Compute $[t_{lo} ]_1, [t_{mid} ]_1,[t_{hi} ]_1$ and add them to the transcript.

Sample $\zeta$ from the transcript.

Compute $\bar a = a(\zeta), \bar b = b(\zeta), \bar c = c(\zeta), \bar s_{\sigma1} = S_{\sigma1}(\zeta), \bar s_{\sigma2} = S_{\sigma2}(\zeta), \bar z_\omega = z(\zeta\omega)$ and add them to the transcript.
Compute $\bar a = a(\zeta), \bar b = b(\zeta), \bar c = c(\zeta), \bar s_{\sigma 1} = S_{\sigma 1}(\zeta), \bar s_{\sigma 2} = S_{\sigma 2}(\zeta), \bar z_\omega = z(\zeta\omega)$ and add them to the transcript.

### Round 5

Expand All @@ -139,7 +139,7 @@ Let
$$
\begin{aligned}
\hat p_{nc1} &= \bar aq_L + \bar bq_R + \bar a\bar bq_M + \bar cq_O + q_C \\
\hat p_{nc2} &=(\bar a + \beta\zeta + \gamma)(\bar b + \beta k_1\zeta + \gamma)(\bar c + \beta k_2\zeta + \gamma)z - (\bar a + \beta \bar s_{\sigma1} + \gamma)(\bar b + \beta \bar s_{\sigma2} + \gamma)\beta \bar z_\omega S_{\sigma3} \\
\hat p_{nc2} &=(\bar a + \beta\zeta + \gamma)(\bar b + \beta k_1\zeta + \gamma)(\bar c + \beta k_2 \zeta + \gamma)z - (\bar a + \beta \bar s_{\sigma 1} + \gamma)(\bar b + \beta \bar s_{\sigma 2} + \gamma)\beta \bar z_\omega S_{\sigma 3} \\
\hat p_{nc3} &= L_1(\zeta) z
\end{aligned}
$$
Expand All @@ -153,10 +153,10 @@ t_{\text{partial}} &= t_{lo} + \zeta^{N+2}t_{mid} + \zeta^{2(N+2)}t_{hi}
\end{aligned}
$$

The subscript $nc$ stands for "non constant", as is the part of the linearization of $p$ that has non constant factors. The subscript "partial" indicates that it is a partial evaluation of $t$ at $\zeta$. Partial meaning that only some power of $X$ ar replaced by the powers of $\zeta$. So in particular $t_{\text{partial}}(\zeta) = t(\zeta)$.
The subscript $nc$ stands for "non-constant", as is the part of the linearization of $p$ that has non-constant factors. The subscript "partial" indicates that it is a partial evaluation of $t$ at $\zeta$. Partial meaning that only some power of $X$ ar replaced by the powers of $\zeta$. So in particular $t_{\text{partial}}(\zeta) = t(\zeta)$.

Let $\pi_{\text{batch}}$ be the opening proof at $\zeta$ of the polynomial $f_{\text{batch}}$ defined as
$$t_{\text{partial}} +\upsilon p_{nc} + \upsilon^2 a + \upsilon^3 b + \upsilon^4 c + \upsilon^5 S_{\sigma1} + \upsilon^6 S_{\sigma2}$$
$$t_{\text{partial}} +\upsilon p_{nc} + \upsilon^2 a + \upsilon^3 b + \upsilon^4 c + \upsilon^5 S_{\sigma 1} + \upsilon^6 S_{\sigma 2}$$

Let $\pi_{\text{single}}$ be the opening proof at $\zeta\omega$ of the polynomial $z$.

Expand All @@ -165,14 +165,14 @@ Compute $\bar p_{nc} := p_{nc}(\zeta)$ and $\bar t = t(\zeta)$.
### Proof

The proof is:
$$[a]_1, [b]_1 , [c]_1, [z]_1, [t_{lo} ]_1, [t_{mid} ]_1, [t_{hi} ]_1, \bar{a}, \bar{b}, \bar{c}, \bar{s_{\sigma1}}, \bar{s_{\sigma2}}, \bar{z_\omega}, \pi_{\mathrm{batch}}, \pi_{\mathrm{single}}, \bar p_{nc}, \bar t$$
$$[a]_1, [b]_1 , [c]_1, [z]_1, [t_{lo} ]_1, [t_{mid} ]_1, [t_{hi} ]_1, \bar{a}, \bar{b}, \bar{c}, \bar{s_{\sigma 1}}, \bar{s_{\sigma 2}}, \bar{z_\omega}, \pi_{\mathrm{batch}}, \pi_{\mathrm{single}}, \bar p_{nc}, \bar t$$

## Verification algorithm

### Transcript initialization

The first step is to initialize the transcript in the same way the prover did, adding to it the following elements.
$$[S_{\sigma1}]_1, [S_{\sigma2}]_1, [S_{\sigma3}]_1, [q_L]_1, [q_R]_1, [q_M]_1, [q_O]_1, [q_C]_1$$
$$[S_{\sigma 1}]_1, [S_{\sigma 2}]_1, [S_{\sigma 3}]_1, [q_L]_1, [q_R]_1, [q_M]_1, [q_O]_1, [q_C]_1$$

### Extraction of values and commitments

Expand All @@ -186,7 +186,7 @@ Firstly, the verifier needs to compute all the challenges. For that, he follows
- Sample a challenge $\alpha$.
- Add $[t_{lo}]_1, [t_{mid}]_1, [t_{hi}]_1$ to the transcript.
- Sample a challenge $\zeta$.
- Add $\bar a, \bar b, \bar c, \bar s_{\sigma1}, \bar s_{\sigma2}, \bar z_\omega$ to the transcript.
- Add $\bar a, \bar b, \bar c, \bar s_{\sigma 1}, \bar s_{\sigma 2}, \bar z_\omega$ to the transcript.
- Sample a challenge $\upsilon$.

#### Compute $p.i ( \zeta )$
Expand All @@ -197,7 +197,7 @@ where $n$ is the number of public inputs and $L_i$ is the Lagrange basis at the

#### Compute claimed values of $p( \zeta )$ and $t( \zeta )$

He computes $\bar p_{c} := pi(\zeta) + \alpha \bar z_\omega (\bar c + \gamma) (\bar a + \beta \bar s_{\sigma1} + \gamma) (\bar b + \beta \bar s_{\sigma2} + \gamma) - \alpha^2 L_1(\zeta)$
He computes $\bar p_{c} := pi(\zeta) + \alpha \bar z_\omega (\bar c + \gamma) (\bar a + \beta \bar s_{\sigma 1} + \gamma) (\bar b + \beta \bar s_{\sigma 2} + \gamma) - \alpha^2 L_1(\zeta)$

This is the _constant_ part of the linearization of $p$. So adding it to what the prover claims to be $\bar p_{nc}$, he obtains
$$p(\zeta) = \bar p_{c} + \bar p_{nc}$$
Expand All @@ -214,7 +214,7 @@ For $[p_{nc}]_1$, first compute
$$
\begin{aligned}
[\hat p_{nc1} ]_1 &= \bar a[q_L]_1 + \bar b[q_R]_1 + (\bar a\bar b)[q_M]_1 + \bar c[q_O]_1 + [q_C]_1 \\
[\hat p_{nc2} ]_1 &= (\bar a + \beta\zeta + \gamma)(\bar b + \beta k_1 \zeta + \gamma)(\bar c + \beta k_2 \zeta + \gamma)[z]_1 - (\bar a + \beta \bar s_{\sigma1} + \gamma)(\bar b + \beta \bar s_{\sigma2} + \gamma)\beta \bar z_\omega [S_{\sigma3}]_1 \\
[\hat p_{nc2} ]_1 &= (\bar a + \beta\zeta + \gamma)(\bar b + \beta k_1 \zeta + \gamma)(\bar c + \beta k_2 \zeta + \gamma)[z]_1 - (\bar a + \beta \bar s_{\sigma 1} + \gamma)(\bar b + \beta \bar s_{\sigma 2} + \gamma)\beta \bar z_\omega [S_{\sigma 3}]_1 \\
[\hat p_{nc3} ]_1 &= L_1(\zeta)[z]_1
\end{aligned}
$$
Expand All @@ -231,7 +231,7 @@ f_{\mathrm{batch}} (\zeta) =
$$

Also, the commitment of the polynomial $f_{\text{batch}}$ is
$$[f_{\mathrm{batch} }]_1 = [t_{\mathrm{partial}}]_1 + \upsilon [p_{nc}]_1 + \upsilon^2 [a]_1 + \upsilon^3 [b]_1 + \upsilon^4 [c]_1 + \upsilon^5 [S_{\sigma1}]_1 + \upsilon^6 [S_{\sigma2}]_1$$
$$[f_{\mathrm{batch} }]_1 = [t_{\mathrm{partial}}]_1 + \upsilon [p_{nc}]_1 + \upsilon^2 [a]_1 + \upsilon^3 [b]_1 + \upsilon^4 [c]_1 + \upsilon^5 [S_{\sigma 1}]_1 + \upsilon^6 [S_{\sigma 2}]_1$$

### Proof check

Expand All @@ -242,5 +242,4 @@ Now the verifier has all the necessary values to proceed with the checks.
- Verify the opening of $z$ at $\zeta\omega$. That is, check the validity of the proof $\pi_{single}$ using the commitment $[z]_1$ and the value $\bar z_\omega$.
That is, check that $\mathrm{Verify}([z]_1, \pi_{\mathrm{single}}, \zeta \omega, \bar z_\omega)$ outputs _Accept_.

If all checks pass, he outputs _Accept_. Otherwise outputs _Reject_.

If all checks pass, he outputs _Accept_. Otherwise outputs _Reject_.
Loading

0 comments on commit 7e3fe70

Please sign in to comment.