diff --git a/src/kzg.rs b/src/kzg.rs index 32da9d3ddfc7f9acc4f4f36a203633f39658aced..0f5fe3b0df2b8d71467be3af498a449a88d58ac5 100644 --- a/src/kzg.rs +++ b/src/kzg.rs @@ -3,6 +3,40 @@ //! > references: //! > - [Kate et al., 2010](https://link.springer.com/chapter/10.1007/978-3-642-17373-8_11) //! > - [Boneh et al., 2020](https://eprint.iacr.org/2020/081) +//! +//! # The protocol +//! Here, we assume that the input data has been encoded with a _Reed-Solomon_ encoding, as can be +//! done with the [crate::fec] module. +//! +//! Conveniently, each one of the $n$ encoded shards is a linear combination of the $k$ source +//! shards. More precisely, it is the evaluation of the input data seen as a polynomial on some +//! evalution point. +//! +//! We would like to prove that this evaluation has been done correctly and not corrupted. More +//! formally, we want to prove that a shard $s$ is the evaluation of a polynomial $P$, the input +//! data, on some evaluation point $\alpha$. +//! +//! KZG+ will unfold as follows: +//! - the prover: evaluates $P$ on a secret point $\tau$ and generates a commitment $c$ +//! - the prover: computes the quotient between $A(X) = P(X) - P(\alpha)$ and $B(X) = X - \alpha$. +//! Because $A(X)$ has $\alpha$ as a root by definition, $A(X)$ is divisible by $B(X)$ and the +//! result $Q(X) = \frac{A(X)}{B(X)}$ makes sense. A proof $\pi$ is then crafted by evaluting the +//! polynomial $Q(X)$ on $\tau$ +//! - the prover: attaches the commit $c$ and the proof $\pi$ to the shard $s$ and shares this +//! block onto the network +//! - the verifier: verifies the validity of the commit $c$, the proof $\pi$ and the shard $s$ with +//! a _pairing_ operator defined on an appropriate elliptic curve +//! +//! ## Some details +//! - each shard $s$ is associated to a unique evaluation point $\alpha$ +//! - because $k$ is a fixed code parameter and the data can be of arbitrary size, the bytes are +//! arranged in an $m \times k$ matrix of finite field elements. Then, instead of computing $m$ +//! proofs per shard, KZG+ will _aggregate_ the $m$ polynomials, one per row in the data, into a +//! single polynomial $P$. This is done by computing a random linear combination of the $m$ input +//! polynomials +//! +//! # Example +//! see the KZG example. use ark_ec::{pairing::Pairing, AffineRepr}; use ark_ff::PrimeField; use ark_poly::DenseUVPolynomial; @@ -18,6 +52,10 @@ use crate::fec::Shard; pub use crate::zk::ark_commit as commit; +/// representation of a block of proven data. +/// +/// this is a wrapper around a [`fec::Shard`] with some additional cryptographic +/// information that allows to prove the integrity of said shard. #[derive(Debug, Clone, Default, PartialEq, CanonicalDeserialize, CanonicalSerialize)] pub struct Block<E: Pairing> { pub shard: Shard<E::ScalarField>, @@ -25,14 +63,7 @@ pub struct Block<E: Pairing> { proof: kzg10::Proof<E>, } -/// this function splits the data (bytes) into k shards and generates n shards with a proof for each. -/// First, generate m polynomials with k coefficients (meaning degree is k-1) -/// Then, for each shard (n): -/// evaluate the m polynomials in one point (alpha) -/// compute a hash of the concatenated evaluations -/// compute Q(X) = sum_{i=0}^{m-1}{r^i * P_i(X)} -/// prove this polynomial with KZG10 -/// store in the n Block the proof, the m commits and the m P_i evaluations +/// proves $n$ encoded shards by computing one proof for each of them and attaching the commitment pub fn prove<E, P>( commits: Vec<kzg10::Commitment<E>>, polynomials: Vec<P>, @@ -124,6 +155,7 @@ where } /// for a given Block, verify that the data has been correctly generated +/// /// First, transform data bytes into m polynomial evaluation /// compute the hash of the concatenation of these evaluations /// compute y as a combination of the shards: y = sum(r^i * Shard_i) for i=[0..m[ diff --git a/src/semi_avid.rs b/src/semi_avid.rs index b21a9e731fba3d7431a5c78ef2be77416b72e375..fa844ed7487443ae3689e901f9abd2626b697896 100644 --- a/src/semi_avid.rs +++ b/src/semi_avid.rs @@ -25,6 +25,8 @@ //! > using generic types as it's commonly done in Arkworks, it should be possible to specify them //! > once and Rust will take care of _carrying_ the types in the rest of the code. Also, `DP<F>` //! > will likely be its own generic type, usually written `P` in this code base. +//! > +//! > see the Semi-AVID example for a fully-typed code. //! //! - first, let's import some types... //! ```