diff --git a/README.md b/README.md index e5c8ed6b7..d08143210 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # lambdaworks + > From the heights of these towers of fields, forty centuries of mathematics look down on us. This library provides efficient implementation of cryptographic primitives used to build proving systems. Along with it, many backends for proving systems are shipped, and compatibility with different frontends is supported. @@ -32,6 +33,7 @@ So, we decided to build our library, focusing on performance, with clear documen - [Groth 16](https://github.com/lambdaclass/lambdaworks/tree/main/provers/groth16) ### Crypto + - [Elliptic curves](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve) - [Multiscalar multiplication](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/msm) - [Hashes](https://github.com/lambdaclass/lambdaworks/tree/main/crypto/src/hash) @@ -41,12 +43,15 @@ Most of math and crypto crates supports no-std without allocation with `no-defau Both Math and Crypto support wasm with target `wasm32-unknown-unknown`. To see an example of how to use this to deploy a verifier in a browser, check the Cairo Prover wasm-pack verifier. ## Examples - mini apps + - [Merkle Tree CLI](https://github.com/lambdaclass/lambdaworks/tree/main/examples/merkle-tree-cli) - [Proving Miden](https://github.com/lambdaclass/lambdaworks/tree/main/examples/prove-miden) - [Shamir's secret sharing](https://github.com/lambdaclass/lambdaworks/tree/main/examples/shamir_secret_sharing) - [BabySNARK](https://github.com/lambdaclass/lambdaworks/tree/main/examples/baby-snark) +- [Pinocchio](https://github.com/lambdaclass/lambdaworks/tree/main/examples/pinocchio) ## Exercises and Challenges + - [lambdaworks exercises and challenges](https://github.com/lambdaclass/lambdaworks_exercises/tree/main) - [Roadmap for Sparkling Water Bootcamp](https://github.com/lambdaclass/sparkling_water_bootcamp/blob/main/README.md) @@ -85,9 +90,9 @@ List of symbols: | **Elliptic Curves** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | BLS12-377 | 🏗️ | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | -| BN-254 | 🏗️ | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | -| Pallas | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | -| Vesta | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | +| BN-254 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Pallas | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | +| Vesta | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | | Bandersnatch | 🏗️ | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | | **STARKs** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** | | STARK Prover | :heavy_check_mark: | :x: | :x: | :x: | :x: | @@ -158,11 +163,22 @@ To serve the documentation locally, first install both [mdbook](https://rust-lan make docs ``` -## 📚 References +## 📚 References and acknowledgements -The following links, repos and projects have been important in the development of this library and we want to thank and acknowledge them. +The following links, repos, companies and projects have been important in the development of this library and we want to thank and acknowledge them. - [Starkware](https://starkware.co/) +- [Polygon](https://polygon.technology/) +- [Mina](https://minaprotocol.com/) +- [zcash](https://z.cash/) +- [Matter Labs](https://matter-labs.io/) +- [o1Labs](https://www.o1labs.org/) +- [zkSync](https://zksync.io/) +- [Aleo](https://aleo.org/) +- [Risc0](https://github.com/risc0/risc0) +- [Aztec](https://github.com/AztecProtocol) +- [Ingonyama](https://www.ingonyama.com/) +- [Neptune](https://github.com/Neptune-Crypto) - [Winterfell](https://github.com/facebook/winterfell) - [Anatomy of a Stark](https://aszepieniec.github.io/stark-anatomy/overview) - [Giza](https://github.com/maxgillett/giza) @@ -170,14 +186,11 @@ The following links, repos and projects have been important in the development o - [Sandstorm](https://github.com/andrewmilson/sandstorm) - [STARK-101](https://starkware.co/stark-101/) - [starknet-rs](https://github.com/xJonathanLEI/starknet-rs/) -- [Risc0](https://github.com/risc0/risc0) -- [Neptune](https://github.com/Neptune-Crypto) - [Summary on FRI low degree test](https://eprint.iacr.org/2022/1216) - [STARKs paper](https://eprint.iacr.org/2018/046) - [DEEP FRI](https://eprint.iacr.org/2019/336) - [BrainSTARK](https://aszepieniec.github.io/stark-brainfuck/) - [Plonky2](https://github.com/mir-protocol/plonky2) -- [Aztec](https://github.com/AztecProtocol) - [Arkworks](https://github.com/arkworks-rs) - [Thank goodness it's FRIday](https://vitalik.ca/general/2017/11/22/starks_part_2.html) - [Diving DEEP FRI](https://blog.lambdaclass.com/diving-deep-fri/) @@ -190,3 +203,4 @@ The following links, repos and projects have been important in the development o - [CAIRO whitepaper](https://eprint.iacr.org/2021/1063.pdf) - [Gnark](https://github.com/Consensys/gnark) - [Constantine](https://github.com/mratsim/constantine) +- [Plonky3](https://github.com/Plonky3/Plonky3) \ No newline at end of file diff --git a/bootcamp/README.md b/bootcamp/README.md index 58e65e272..0f49e9469 100644 --- a/bootcamp/README.md +++ b/bootcamp/README.md @@ -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) @@ -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 diff --git a/crypto/README.md b/crypto/README.md index 4e367d6a7..8633f5dde 100644 --- a/crypto/README.md +++ b/crypto/README.md @@ -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` diff --git a/docs/src/plonk/SUMMARY.md b/docs/src/plonk/SUMMARY.md index f1a17e1da..150298155 100644 --- a/docs/src/plonk/SUMMARY.md +++ b/docs/src/plonk/SUMMARY.md @@ -3,5 +3,4 @@ - [Recap](./recap.md) - [Protocol](./protocol.md) - [Implementation](./implementation.md) -- [Circuit API](./constraint_system.md) - +- [Circuit API](./constraint_system.md) \ No newline at end of file diff --git a/docs/src/plonk/constraint_system.md b/docs/src/plonk/constraint_system.md index e82ecec4e..9d961a615 100644 --- a/docs/src/plonk/constraint_system.md +++ b/docs/src/plonk/constraint_system.md @@ -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 @@ -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. \ No newline at end of file diff --git a/docs/src/plonk/implementation.md b/docs/src/plonk/implementation.md index c8ee21c8a..a06aa61e3 100644 --- a/docs/src/plonk/implementation.md +++ b/docs/src/plonk/implementation.md @@ -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 @@ -90,16 +93,21 @@ pub struct Witness { pub c: Vec>, } ``` + 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 { pub qm_1: G1Point, @@ -113,6 +121,7 @@ pub struct VerificationKey { 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 @@ -133,6 +142,7 @@ where phantom: PhantomData, } ``` + 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. @@ -149,7 +159,9 @@ let proof = prover.prove( &verifying_key, ); ``` + The output is an instance of the struct `Proof`. + ```rust pub struct Proof> { // Round 1. @@ -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$. @@ -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 @@ -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) \ No newline at end of file diff --git a/docs/src/plonk/plonk.md b/docs/src/plonk/plonk.md index f80b28b76..4bf083370 100644 --- a/docs/src/plonk/plonk.md +++ b/docs/src/plonk/plonk.md @@ -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) \ No newline at end of file diff --git a/docs/src/plonk/protocol.md b/docs/src/plonk/protocol.md index 3674a24f0..49e788e76 100644 --- a/docs/src/plonk/protocol.md +++ b/docs/src/plonk/protocol.md @@ -13,9 +13,9 @@ In the implementation section we'll explain the inner workings of the Kate-Zaver For the moment we only need the following about it: It consists of a finite group $\mathbb{G}$ and the following algorithms: -- **Commit($f$)**: This algorithm takes a polynomial $f$ and produces an element of the group $\mathbb{G}$. It is called the commitment of $f$ and is denoted by $[f]_1$. It is homomorphic in the sense that $[f + g]_1 = [f]_1 + [g]_1$. The former sum being addition of polynomials. The latter is addition in the group $\mathbb{G}$. +- **Commit($f$)**: This algorithm takes a polynomial $f$ and produces an element of the group $\mathbb{G}$. It is called the commitment of $f$ and is denoted by $\left[f\right]_1$. It is homomorphic in the sense that $\left[f + g\right]_1 = \left[f\right]_1 + \left[g\right]_1$. The former sum being addition of polynomials. The latter is addition in the group $\mathbb{G}$. - **Open($f$, $\zeta$ )**: It takes a polynomial $f$ and a field element $\zeta$ and produces an element $\pi$ of the group $\mathbb{G}$. This element is called an opening proof for $f(\zeta)$. It is the proof that $f$ evaluated at $\zeta$ gives $f(\zeta)$. -- **Verify($[f]_1$, $\pi$, $\zeta$, $y$)**: It takes group elements $[f]_1$ and $\pi$, and also field elements $\zeta$ and $y$. With overwhelming probability it outputs _Accept_ if $f(z)=y$ and _Reject_ otherwise. +- **Verify($\left[f\right]_1$, $\pi$, $\zeta$, $y$)**: It takes group elements $\left[f\right]_1$ and $\pi$, and also field elements $\zeta$ and $y$. With overwhelming probability it outputs _Accept_ if $f(z)=y$ and _Reject_ otherwise. ### Blindings @@ -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 @@ -39,11 +39,11 @@ This is an optimization in PLONK to reduce the number of checks of the verifier. One of the main checks in PLONK boils down to check that $p(\zeta) = z_H(\zeta) t(\zeta)$, with $p$ some polynomial that looks like $p = a q_L + b q_R + ab q_M + \cdots$, and so on. In particular the verifier needs to get the value $p(\zeta)$ from somewhere. -For the sake of simplicity, in this section assume $p$ is exactly $a q_L + bq_R$. Secret to the prover here are only $a, b$. The polynomials $q_L$ and $q_R$ are known also to the verifier. The verifier will already have the commitments $[a]_1, [b]_1, [q_L]_1$ and $[q_R]_1$. So the prover could send just $a( \zeta )$, $b( \zeta )$ along with their opening proofs and let the verifier compute by himself $q_L(\zeta)$ and $q_R(\zeta)$. Then with all these values the verifier could compute $p(\zeta) = a(\zeta) q_L (\zeta) + b(\zeta) q_R (\zeta)$. And also use his commitments to validate the opening proofs of $a(\zeta)$ and $b(\zeta)$. +For the sake of simplicity, in this section assume $p$ is exactly $a q_L + bq_R$. Secret to the prover here are only $a, b$. The polynomials $q_L$ and $q_R$ are known also to the verifier. The verifier will already have the commitments $\left[a\right]_1, \left[b\right]_1, \left[q_L\right]_1$ and $\left[q_R\right]_1$. So the prover could send just $a( \zeta )$, $b( \zeta )$ along with their opening proofs and let the verifier compute by himself $q_L(\zeta)$ and $q_R(\zeta)$. Then with all these values the verifier could compute $p(\zeta) = a(\zeta) q_L (\zeta) + b(\zeta) q_R (\zeta)$. And also use his commitments to validate the opening proofs of $a(\zeta)$ and $b(\zeta)$. -This has the problem that computing $q_L (\zeta)$ and $q_R (\zeta)$ is expensive. The prover can instead save the verifier this by sending also $q_L (\zeta), q_R (\zeta)$ along with opening proofs. Since the verifier will have the commitments $[q_L]_1$ and $[q_R]_1$ beforehand, he can check that the prover is not cheating and cheaply be convinced that the claimed values are actually $q_L(\zeta)$ and $q_R(\zeta)$. This is much better. It involves the check of four opening proofs and the computation of $p(\zeta)$ off the values received from the prover. But it can be further improved as follows. +This has the problem that computing $q_L (\zeta)$ and $q_R (\zeta)$ is expensive. The prover can instead save the verifier this by sending also $q_L (\zeta), q_R (\zeta)$ along with opening proofs. Since the verifier will have the commitments $\left[q_L\right]_1$ and $\left[q_R\right]_1$ beforehand, he can check that the prover is not cheating and cheaply be convinced that the claimed values are actually $q_L(\zeta)$ and $q_R(\zeta)$. This is much better. It involves the check of four opening proofs and the computation of $p(\zeta)$ off the values received from the prover. But it can be further improved as follows. -As before, the prover sends $a(\zeta), b(\zeta)$ along with their opening proofs. She constructs the polynomial $f = a(\zeta)q_L + b(\zeta)q_R$. She sends the value $f(\zeta)$ along with an opening proof of it. Notice that the value of $f(\zeta)$ is exactly $p(\zeta)$. The verifier can compute by himself $[f]_1$ as $a(\zeta)[q_L]_1 + b(\zeta)[q_R]_1$. The verifier has everything to check all three openings and get convinced that the claimed value $f(\zeta)$ is true. And this value is actually $p(\zeta)$. So this means no more work for the verifier. And the whole thing got reduced to three openings. +As before, the prover sends $a(\zeta), b(\zeta)$ along with their opening proofs. She constructs the polynomial $f = a(\zeta)q_L + b(\zeta)q_R$. She sends the value $f(\zeta)$ along with an opening proof of it. Notice that the value of $f(\zeta)$ is exactly $p(\zeta)$. The verifier can compute by himself $\left[f\right]_1$ as $a(\zeta)\left[q_L\right]_1 + b(\zeta)\left[q_R\right]_1$. The verifier has everything to check all three openings and get convinced that the claimed value $f(\zeta)$ is true. And this value is actually $p(\zeta)$. So this means no more work for the verifier. And the whole thing got reduced to three openings. This is called the linearization trick. The polynomial $f$ is called the _linearization_ of $p$. @@ -51,7 +51,7 @@ This is called the linearization trick. The polynomial $f$ is called the _linear ## Setup There's a one time setup phase to compute some values common to any execution and proof of the particular circuit. Precisely, the following commitments are computed and published. -$$[ 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$$ +$$\left[q_L\right]_1 , \left[q_R\right]_1 , \left[q_M\right]_1 , \left[q_O\right]_1 , \left[q_C\right]_1 , \left[S_{ \sigma 1 }\right]_1 , \left[S_{ \sigma 2 }\right]_1 , \left[S_{ \sigma 3 }\right]_1$$ ## Proving algorithm @@ -64,7 +64,7 @@ The prover computes the trace matrix $T$ as described in the first sections. Tha ### Round 1 Add to the transcript the following: -$$[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$$ +$$\left[ S_{\sigma 1 } \right]_1, \left[ S_ { \sigma 2 } \right]_1, \left[ S { \sigma 3 } \right]_1, \left[ q_L \right]_1, \left[ q_R \right]_1, \left[ q_M \right]_1, \left[ q_O \right]_1, \left[ q_C \right]_1$$ Compute polynomials $a',b',c'$ as the interpolation polynomials of the columns of $T$ at the domain $H$. Sample random $b_1, b_2, b_3, b_4, b_5, b_6$ @@ -76,7 +76,7 @@ $b := (b_3 X + b_4 )Z_H + b'$ $c := (b_5 X + b_6 )Z_H + c'$ -Compute $[a]_1, [b]_1, [c]_1$ and add them to the transcript. +Compute $\left[a\right]_1, \left[b\right]_1, \left[c\right]_1$ and add them to the transcript. ### Round 2 @@ -85,14 +85,14 @@ Sample $\beta, \gamma$ from the transcript. Let $z_0 = 1$ and define recursively for $0\leq k < N$. $$ -z_{k+1} = z_k \frac{(a_k + \beta\omega^k + \gamma)(b_k + \beta\omega^k k_1 + \gamma)(c_k + \beta\omega^k k_2 + \gamma)}{(a_k + \beta S_{\sigma1} (\omega^k ) + \gamma)(b_k + \beta S_{\sigma2} (\omega^k) + \gamma)(c_k + \beta S_{\sigma3} (\omega^k) + \gamma)} +z_{k + 1} = z_k \frac{(a_k + \beta \omega^k + \gamma) (b_k + \beta \omega^k k_1 + \gamma)(c_k + \beta \omega^k k_2 + \gamma)}{(a_k + \beta S_{ \sigma 1} (\omega^k ) + \gamma) (b_k + \beta S_{ \sigma 2} (\omega^k) + \gamma)(c_k + \beta S_{ \sigma 3} (\omega^k) + \gamma)} $$ Compute the polynomial $z'$ as the interpolation polynomial at the domain $H$ of the values $(z_0, \dots, z_{ N - 1 })$. -Sample random values $b_7, b_8, b_9$ and let $z = (b_7X^2 + b_8X + b_9 )Z_H + z'$. +Sample random values $b_7, b_8, b_9$ and let $z = (b_7 X^2 + b_8 X + b_9 )Z_H + z'$. -Compute $[z]_1$ and add it to the transcript. +Compute $\left[z\right]_1$ and add it to the transcript. ### Round 3 @@ -105,7 +105,7 @@ Let $$ \begin{aligned} p_1 &= aq_L + bq_R + abq_M + cq_O + q_C + pi \\ -p_2 &= (a + \beta X + \gamma)(b + \beta k_1 X + \gamma)(c + \beta k_2 X + \gamma)z - (a + \beta S_{\sigma1} + \gamma)(b + \beta S_{\sigma2} + \gamma)(c + \beta S_{\sigma3} + \gamma)z(\omega X)\\ +p_2 &= (a + \beta X + \gamma)(b + \beta k_1 X + \gamma)(c + \beta k_2 X + \gamma)z - (a + \beta S_{ \sigma 1} + \gamma)(b + \beta S_{ \sigma 2} + \gamma)(c + \beta S_{ \sigma 3} + \gamma)z(\omega X)\\ p_3 &= (z - 1)L_1 \end{aligned} $$ @@ -122,13 +122,13 @@ t_{hi} &= t_{hi}' - b_{11} \end{aligned} $$ -Compute $[t_{lo} ]_1, [t_{mid} ]_1,[t_{hi} ]_1$ and add them to the transcript. +Compute $\left[t_{lo}\right]_1, \left[t_{mid}\right]_1,\left[t_{hi}\right]_1$ and add them to the transcript. ### Round 4 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 @@ -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} $$ @@ -149,14 +149,14 @@ Define $$ \begin{aligned} p_{nc} &= p_{nc1} + \alpha p_{nc2} + \alpha^2 p_{nc3} \\ -t_{\text{partial}} &= t_{lo} + \zeta^{N+2}t_{mid} + \zeta^{2(N+2)}t_{hi} +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$. @@ -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$$ +$$\left[a\right]_1, \left[b\right]_1 , \left[c\right]_1, \left[z\right]_1, \left[t_{lo}\right]_1, \left[t_{mid}\right]_1, \left[t_{hi}\right]_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$$ +$$\left[ S_{ \sigma 1 } \right]_1, \left[ S_{ \sigma 2 } \right]_1, \left[ S_{ \sigma 3 }\right]_1, \left[ q_L \right]_1, \left[ q_R \right]_1, \left[ q_M \right]_1, \left[ q_O \right]_1, \left[ q_C \right]_1$$ ### Extraction of values and commitments @@ -180,13 +180,13 @@ $$[S_{\sigma1}]_1, [S_{\sigma2}]_1, [S_{\sigma3}]_1, [q_L]_1, [q_R]_1, [q_M]_1, Firstly, the verifier needs to compute all the challenges. For that, he follows these steps: -- Add $[a]_1, [b]_1, [c]_1$ to the transcript. +- Add $\left[a\right]_1, \left[b\right]_1, \left[c\right]_1$ to the transcript. - Sample two challenges $\beta, \gamma$. -- Add $[z]_1$ to the transcript. +- Add $\left[z\right]_1$ to the transcript. - Sample a challenge $\alpha$. -- Add $[t_{lo}]_1, [t_{mid}]_1, [t_{hi}]_1$ to the transcript. +- Add $\left[t_{lo}\right]_1, \left[t_{mid}\right]_1, \left[t_{hi}\right]_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 )$ @@ -197,31 +197,31 @@ 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}$$ With respect to $t(\zeta)$, this is actually already $\bar{t}$. -#### Compute $[t_{\mathrm{partial}} ]_1$ and $[p_{nc} ]_1$ +#### Compute $\left[t_{\mathrm{partial}} \right]_1$ and $\left[p_{nc} \right]_1$ He computes these off the commitments in the proof as follows -$$[t_{\mathrm{partial}}]_1 = [t_{lo}]_1 + \zeta^{ N + 2 }[t_{mid}]_1 + \zeta^{ 2 (N + 2) }[t_{hi}]_1$$ +$$\left[t_{\mathrm{partial}}\right]_1 = \left[t_{lo}\right]_1 + \zeta^{ N + 2 }\left[t_{mid}\right]_1 + \zeta^{ 2 (N + 2) }\left[t_{hi}\right]_1$$ -For $[p_{nc}]_1$, first compute +For $\left[p_{nc}\right]_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_{nc3} ]_1 &= L_1(\zeta)[z]_1 +\left[\hat p_{nc1} \right]_1 &= \bar a\left[q_L\right]_1 + \bar b\left[q_R\right]_1 + (\bar a\bar b)\left[q_M\right]_1 + \bar c\left[q_O\right]_1 + \left[q_C\right]_1 \\ +\left[\hat p_{nc2} \right]_1 &= (\bar a + \beta\zeta + \gamma)(\bar b + \beta k_1 \zeta + \gamma)(\bar c + \beta k_2 \zeta + \gamma)\left[z\right]_1 - (\bar a + \beta \bar s_{\sigma 1} + \gamma)(\bar b + \beta \bar s_{\sigma 2} + \gamma)\beta \bar z_\omega \left[S_{\sigma 3}\right]_1 \\ +\left[\hat p_{nc3} \right]_1 &= L_1(\zeta)\left[z\right]_1 \end{aligned} $$ -Then $[p_{nc} ]_1 = [p_{nc1} ]_1 + [p_{nc2} ]_1 + [p_{nc3} ]_1$. +Then $\left[p_{nc} \right]_1 = \left[p_{nc1} \right]_1 + \left[p_{nc2} \right]_1 + \left[p_{nc3} \right]_1$. -#### Compute claimed value $f_{\text{batch} } (\zeta)$ and $[f_{{batch} }]_1$ +#### Compute claimed value $f_{\text{batch} } (\zeta)$ and $\left[f_{{batch} }\right]_1$ Compute $f_{\text{batch}} (\zeta)$ as @@ -231,16 +231,15 @@ 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$$ +$$\left[f_{\mathrm{batch} }\right]_1 = \left[t_{\mathrm{partial}}\right]_1 + \upsilon \left[p_{nc}\right]_1 + \upsilon^2 \left[a\right]_1 + \upsilon^3 \left[b\right]_1 + \upsilon^4 \left[c\right]_1 + \upsilon^5 \left[S_{\sigma 1}\right]_1 + \upsilon^6 \left[S_{\sigma 2}\right]_1$$ ### Proof check Now the verifier has all the necessary values to proceed with the checks. - Check that $p(\zeta)$ equals $(\zeta^N - 1)t(\zeta)$. -- Verify the opening of $f_{\text{batch}}$ at $\zeta$. That is, check that $\mathrm{Verify}([f_{\mathrm{batch} } ]_1, \pi_{\mathrm{batch}}, \zeta, f_{\mathrm{batch} } (\zeta))$ outputs _Accept_. -- 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_. +- Verify the opening of $f_{\text{batch}}$ at $\zeta$. That is, check that $\mathrm{Verify}(\left[f_{\mathrm{batch} } \right]_1, \pi_{\mathrm{batch}}, \zeta, f_{\mathrm{batch} } (\zeta))$ outputs _Accept_. +- Verify the opening of $z$ at $\zeta\omega$. That is, check the validity of the proof $\pi_{single}$ using the commitment $\left[z\right]_1$ and the value $\bar z_\omega$. +That is, check that $\mathrm{Verify}(\left[z\right]_1, \pi_{\mathrm{single}}, \zeta \omega, \bar z_\omega)$ outputs _Accept_. +If all checks pass, he outputs _Accept_. Otherwise outputs _Reject_. \ No newline at end of file diff --git a/docs/src/plonk/recap.md b/docs/src/plonk/recap.md index 7a67618c5..c3e0ef0ce 100644 --- a/docs/src/plonk/recap.md +++ b/docs/src/plonk/recap.md @@ -173,7 +173,7 @@ PLONK has the flexibility to construct more sophisticated gates as combinations | $Q_L$ | $Q_R$ | $Q_M$ | $Q_O$ | $Q_C$ | | ----- | ----- | ----- | ----- | ----- | -| 1 | 1 | 1 | -1 | 1 | +| 0 | 1 | 1 | -1 | 1 | and also the $V$ matrix @@ -189,7 +189,7 @@ The trace matrix for this representation is just And we check that it satisfies the equation -$$ 2 \times 1 + 3 \times 1 + 2 \times 3 \times 1 + 8 \times (-1) + (-1) = 0$$ +$$ 2 \times 0 + 3 \times 1 + 2 \times 3 \times 1 + 8 \times (-1) + (-1) = 0$$ Of course, we can't always squash an entire program into a single gate. @@ -256,7 +256,7 @@ In the previous section we showed how the arithmetization process works in PLONK Polynomials enter now to squash most of these equations. We will traduce the set of all equations in conditions (a) and (b) to just a few equations on polynomials. -Let $\omega$ be a primitive $N$-th root of unity and let $H = {\omega^i: 0\leq i < N}$. Let $a, b, c, q_L, q_R, q_M, q_O, q_C, pi$ be the polynomials of degree at most $N$ that interpolate the columns $A, B, C, Q_L, Q_R, Q_M, Q_O, Q_C, PI$ at the domain $H$. This means for example that $a(\omega^i) = A_i$ for all $i$. And similarly for all the other columns. +Let $\omega$ be a primitive $N$-th root of unity and let $H = {\omega^i: 0 \leq i < N}$. Let $a, b, c, q_L, q_R, q_M, q_O, q_C, pi$ be the polynomials of degree at most $N$ that interpolate the columns $A, B, C, Q_L, Q_R, Q_M, Q_O, Q_C, PI$ at the domain $H$. This means for example that $a(\omega^i) = A_i$ for all $i$. And similarly for all the other columns. With this, condition (a) of the claim is equivalent to $$a(x) q_L(x) + b(x) q_R(x) + a(x) b(x) q_M(x) + c(x) q_O(x) + q_c(x) + pi(x) = 0$$ for all $x$ in $H$.This is just by definition of the polynomials. But in polynomials land this is also equivalent to (a) there exists a polynomial $t$ such that $$a q_L + b q_R + a b q_M + c q_O + q_c + pi = z_H t$$, where $z_H$ is the polynomial $X^N -1$. @@ -308,12 +308,12 @@ Polynomials come to rescue here. What we can do instead is consider the followin Putting this altogether, if for some random element $\gamma$ we have $(a_0 + \gamma)(a_1 + \gamma) = (b_0 + \gamma)(b_1 + \gamma)$, then the sets $A$ and $B$ are equal. Of course this also holds for sets with more than two elements. Let's write that down. -_Fact:_ Let $A=\{a_0, \dots, a_{k-1}\}$ and $B=\{b_0, \dots, b_{k-1}\}$ be sets of field elements. If for some random $\gamma$ the following equality holds -$$\prod_{i=0}^{k-1}(a_i + \gamma) = \prod_{i=0}^{k-1}(b_i + \gamma),$$ +_Fact:_ Let $A=\{a_0, \dots, a_{k - 1}\}$ and $B=\{b_0, \dots, b_{k - 1}\}$ be sets of field elements. If for some random $\gamma$ the following equality holds +$$\prod_{i = 0}^{ k - 1}(a_i + \gamma) = \prod_{i = 0}^{ k - 1 }(b_i + \gamma),$$ then with overwhelming probability $A$ is equal to $B$. And here comes the trick that reduces this check to polynomial equations. Let -$H$ be a domain of the form $\{1, \omega, \dots, \omega^{k-1}\}$ for some primitive $k$-th root of unity $\omega$. Let $f$ and $g$ be respectively the polynomials that interpolate the following values at $H$. +$H$ be a domain of the form $\{1, \omega, \dots, \omega^{k - 1}\}$ for some primitive $k$-th root of unity $\omega$. Let $f$ and $g$ be respectively the polynomials that interpolate the following values at $H$. $$(a_0 + \gamma, \dots, a_{k-1} + \gamma),$$ $$(b_0 + \gamma, \dots, b_{k-1} + \gamma),$$ @@ -444,5 +444,4 @@ $$ This last step is not obvious. You can check the paper to see the proof. Anyway, this is the equation you'll recognize below in the description of the protocol. -Randomness is a delicate matter and an important part of the protocol is where it comes from, who chooses it and when they choose it. Check out the protocol to see how it works. - +Randomness is a delicate matter and an important part of the protocol is where it comes from, who chooses it and when they choose it. Check out the protocol to see how it works. \ No newline at end of file diff --git a/docs/src/starks/protocol_overview.md b/docs/src/starks/protocol_overview.md index 321329cbd..deea73965 100644 --- a/docs/src/starks/protocol_overview.md +++ b/docs/src/starks/protocol_overview.md @@ -159,5 +159,4 @@ The verifier must check that $H$ was constructed according to the protocol rules ## Round 4: Run batch open protocol -In this round, the prover and verifier engage in the batch open protocol of the polynomial commitment scheme described above to validate all the evaluations at $z$ from the previous round. - +In this round, the prover and verifier engage in the batch open protocol of the polynomial commitment scheme described above to validate all the evaluations at $z$ from the previous round. \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index 44075b9ce..3d97f746d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,6 +8,8 @@ Below is a list of all lambdaworks examples in the folder: - [Shamir Secret Sharing](https://github.com/lambdaclass/lambdaworks/tree/main/examples/shamir_secret_sharing): implements example of [Shamir's secret sharing](https://en.wikipedia.org/wiki/Shamir%27s_secret_sharing). Shows use of polynomials and finite fields in lambdaworks. - [Merkle tree CLI](https://github.com/lambdaclass/lambdaworks/tree/main/examples/merkle-tree-cli): generate inclusion proofs for an element inside a Merkle tree and verify them using a CLI. - [Proving Miden using lambdaworks STARK Platinum prover](https://github.com/lambdaclass/lambdaworks/tree/main/examples/prove-miden): Executes a Miden vm Fibonacci program, gets the execution trace and generates a proof (and verifies it) using STARK Platinum. +- [BabySNARK](https://github.com/lambdaclass/lambdaworks/tree/main/examples/baby-snark): a simple SNARK to start learning the basics of elliptic curve-based proof systems. +- [Pinocchio](https://github.com/lambdaclass/lambdaworks/tree/main/examples/pinocchio): the first practical SNARK. A good starting point to start learning about zero-knowledge proofs. You can also check [lambdaworks exercises](https://github.com/lambdaclass/lambdaworks/tree/main/exercises) to learn more. diff --git a/math/src/elliptic_curve/README.md b/math/src/elliptic_curve/README.md index dce09afff..88fb63718 100644 --- a/math/src/elliptic_curve/README.md +++ b/math/src/elliptic_curve/README.md @@ -12,6 +12,8 @@ Each of the curve models can have one or more coordinate systems, such as homoge The following curves are currently supported: - [BLS12-377](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/bls12_377), a pairing-friendly elliptic curve (pairing implementation pending). - [BLS12-381](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/bls12_381), a pairing-friendly elliptic curve. +- [BN-254](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/bn_254), a pairing-friendly elliptic curve. Used on Ethereum. +- [Grumpkin](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/grumpkin), an elliptic curve that forms a two-cycle with BN-254. This means that the base field for Grumpkin (where the coordinates $x,y$ live) is the scalar field of BN-254 (the field with order equal to the order of the group of the elliptic curve), and the scalar field for Grumpkin is the base field of BN-254. - [Pallas](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/pallas), useful for recursive SNARKs when used with Vesta. - [Vesta](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve/short_weierstrass/curves/vesta), useful for recursive SNARKs when used with Pallas. - [Starknet's curve](https://github.com/lambdaclass/lambdaworks/blob/main/math/src/elliptic_curve/short_weierstrass/curves/stark_curve.rs) @@ -131,4 +133,11 @@ fn commit(&self, p: &Polynomial>) -> Self::Commitment { Pairings are an important calculation for BLS signatures and the KZG polynomial commitment scheme. These are functions mapping elements from groups of order $r$ belonging to an elliptic curve to the set of $r$-th roots of unity, $e: G_1 \times G_2 \rightarrow G_t$. They satisfy two properties: 1. Bilinearity 2. Non-degeneracy -Not all elliptic curves have efficiently computable pairings. If the curve is pairing-friendly, we can implement the trait `IsPairing`. Examples of pairing-friendly curves are BLS12-381, BLS12-377, BN254. Curves such as Pallas, Vesta, secp256k1 are not pairing-friendly. +Not all elliptic curves have efficiently computable pairings. If the curve is pairing-friendly, we can implement the trait `IsPairing`. Examples of pairing-friendly curves are BLS12-381, BLS12-377, BN254. Curves such as Pallas, Vesta, secp256k1 are not pairing-friendly. For an explanation of pairings, see our [blogpost](https://blog.lambdaclass.com/how-we-implemented-the-bn254-ate-pairing-in-lambdaworks/). + +The pairing function takes pairs of points $(a , b)$, where $a \in G_1$ (formed by coordinates $x,y$ taking values on the base field ${F_p}$) and $b \in G_2$ (formed by coordinates $x,y$ taking values in $F_{ p^2 }$, a quadratic extension of the base field) and outputs an element in the $r$-th roots of unity of $F_{ p^k }$. To use the pairing, provide a slice of pairs and call the function `compute_batch`. For example, +```rust +let p = BN254Curve::generator(); +let q = BN254TwistCurve::generator(); +let pairing_result = BN254AtePairing::compute_batch(&[(&p, &q)]).unwrap(); +```