Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: hello-world namespace support for ADVZ VID scheme #389

Merged
merged 56 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
9ca622e
restore simple bytes-to-field from https://github.com/EspressoSystems…
ggutoski Oct 19, 2023
8f0d7f5
rename vid/mod.rs -> vid.rs
ggutoski Oct 23, 2023
f25b9e1
new assoc type VidScheme::Payload instead of Vec<u8>
ggutoski Oct 24, 2023
20ac68f
tidy: move boilerplate to the bottom
ggutoski Oct 24, 2023
a1070c9
new Namespacer trait skeleton
ggutoski Oct 25, 2023
ddccddb
wip: untested impl for namespace_verify
ggutoski Oct 25, 2023
f146fd2
port prove_namespace test to advz/namespaces.rs
ggutoski Oct 25, 2023
af98cb6
wip: untested implementation of data_proof
ggutoski Oct 26, 2023
75011f6
fix: use ifft instead of fft, debugging code for posterity
ggutoski Oct 27, 2023
efc81c5
remove debugging code
ggutoski Oct 27, 2023
2e65705
fix bug in modulus_byte_len, should refactor later
ggutoski Oct 27, 2023
b8f1505
test for data_proof
ggutoski Oct 27, 2023
29187f5
impl data_verify, fix bug fft -> ifft
ggutoski Oct 30, 2023
2cc8acb
refactor polynomial construction
ggutoski Oct 30, 2023
26bb9ec
refactor computation of block hash from polynomial commitments
ggutoski Oct 30, 2023
2453404
delete superfluous modulus_byte_len
ggutoski Oct 30, 2023
c753718
tidy index conversion utils
ggutoski Oct 30, 2023
08a536e
tidy
ggutoski Oct 30, 2023
7d36361
fix test build (my vscode settings has std feature enabled by default…
ggutoski Oct 31, 2023
293ed1a
update changelog (is this always worthwhile?)
ggutoski Oct 31, 2023
96e8f87
remove broken rustdoc links
ggutoski Oct 31, 2023
4dd89f4
add timer data to VID disperse, remove it temmporarily from KZG to re…
ggutoski Nov 1, 2023
58feac5
remove namespace_verify, add chunk_prove, chunk_verify
ggutoski Nov 2, 2023
daabb28
wip: stubs
ggutoski Nov 2, 2023
cc5e3c6
new chunk_proof_2 use Range instead of start, len
ggutoski Nov 3, 2023
7054ea4
wip ugly debugging for index gymnastics, forbid 0-length data
ggutoski Nov 3, 2023
76998f7
tighten checks in chunk_xxx2()
ggutoski Nov 3, 2023
373602b
tidy test
ggutoski Nov 3, 2023
59376a6
wip data_xxx2 methods, untested
ggutoski Nov 4, 2023
9bc5d33
test pass for data_verify2 (yay)
ggutoski Nov 5, 2023
0ea565c
remove old [data|chunk]_[proof|verify] methods
ggutoski Nov 5, 2023
054ae18
remove unneeded Payload struct
ggutoski Nov 5, 2023
6c1f161
replace Namespacer with 2 impls for PayloadProver
ggutoski Nov 5, 2023
4089612
rename files: namespace.rs -> payload_prover.rs
ggutoski Nov 5, 2023
0ae66d1
refactor common arg-checking code
ggutoski Nov 6, 2023
7b31498
clean up TODOs
ggutoski Nov 6, 2023
6ab15f3
fix bench
ggutoski Nov 6, 2023
5b19e06
tidy
ggutoski Nov 6, 2023
cd6e341
coeffs_iter -> evals_iter as per https://github.com/EspressoSystems/j…
ggutoski Nov 6, 2023
8f2240b
address https://github.com/EspressoSystems/jellyfish/pull/389#discuss…
ggutoski Nov 6, 2023
ff764b4
add commit arg to verify_share()
ggutoski Nov 6, 2023
89c9fea
add issue comment for https://github.com/EspressoSystems/jellyfish/pu…
ggutoski Nov 6, 2023
93e396e
clippy and fmt
ggutoski Nov 6, 2023
254c2e5
clarify rustdoc
ggutoski Nov 6, 2023
beeaea9
fix bench
ggutoski Nov 6, 2023
39d16e8
move bytes_to_field, etc from conversion.rs to new bytes_to_field.rs
ggutoski Nov 6, 2023
4b3a806
replace compile_time_checks with new elem_byte_capacity owned by advz
ggutoski Nov 6, 2023
7dcb84f
fmt and doctest
ggutoski Nov 6, 2023
a067833
timer tidy as per https://github.com/EspressoSystems/jellyfish/pull/3…
ggutoski Nov 6, 2023
b7e1480
fix rustdoc
ggutoski Nov 6, 2023
68453c6
fmt
ggutoski Nov 6, 2023
613a097
Merge branch 'main' into gg/vid-namespace
ggutoski Nov 6, 2023
f399a4f
new Statement type to simplify args for payload_verify as per https:/…
ggutoski Nov 7, 2023
4805bfb
fmt
ggutoski Nov 7, 2023
d51f76e
Merge branch 'main' into gg/vid-namespace
ggutoski Nov 7, 2023
eb8fde4
rename proof types, tidy, comment
ggutoski Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions primitives/src/vid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@ use serde::{Deserialize, Serialize};
/// VID: Verifiable Information Dispersal
pub trait VidScheme {
/// Payload commitment.
type Commit: Clone + Debug + Eq + PartialEq + Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253
type Commit: Clone + Debug + Eq + PartialEq + Hash + Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253

/// Share-specific data sent to a storage node.
type Share: Clone + Debug + Eq + Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253
type Share: Clone + Debug + Eq + PartialEq + Hash + Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253

/// Common data sent to all storage nodes.
type Common: CanonicalSerialize + CanonicalDeserialize + Clone + Eq + PartialEq + Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253
type Common: CanonicalSerialize
+ CanonicalDeserialize
+ Clone
+ Debug
+ Eq
+ PartialEq
+ Hash
+ Sync; // TODO https://github.com/EspressoSystems/jellyfish/issues/253

/// Compute a payload commitment
fn commit_only<B>(&self, payload: B) -> VidResult<Self::Commit>
Expand Down
188 changes: 101 additions & 87 deletions primitives/src/vid/advz/payload_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
//! Implementations of [`PayloadProver`] for `Advz`.
//!
//! Two implementations:
jbearer marked this conversation as resolved.
Show resolved Hide resolved
//! 1. `PROOF = `[`Proof`]: KZG batch proof for the data. Useful for small
//! sub-slices of `payload` such as an individual transaction within a block.
//! Not snark-friendly because it requires a pairing.
//! 2. `PROOF = `[`CommitRecovery`]: Rebuild the KZG commitment. Useful for
//! larger sub-slices of `payload` such as a complete namespace.
//! Snark-friendly because it does not require a pairing.
//! 1. `PROOF = `[`SmallRangeProof`]: Useful for small sub-slices of `payload`
//! such as an individual transaction within a block. Not snark-friendly
//! because it requires a pairing. Consists of metadata required to verify a
//! KZG batch proof.
//! 2. `PROOF = `[`LargeRangeProof`]: Useful for large sub-slices of `payload`
//! such as a complete namespace. Snark-friendly because it does not require
//! a pairing. Consists of metadata required to rebuild a KZG commitment.

use ark_poly::EvaluationDomain;

Expand All @@ -23,11 +24,37 @@ use super::{
};
use crate::{
alloc::string::ToString,
vid::{payload_prover::PayloadProver, vid, VidError, VidScheme},
vid::{
payload_prover::{PayloadProver, Statement},
vid, VidError, VidScheme,
},
};
use ark_std::{format, ops::Range};

impl<P, T, H, V> PayloadProver<Proof<P::Proof>> for GenericAdvz<P, T, H, V>
/// A proof intended for use on small payload subslices.
///
/// KZG batch proofs and accompanying metadata.
///
/// TODO use batch proof instead of `Vec<P>` <https://github.com/EspressoSystems/jellyfish/issues/387>
pub struct SmallRangeProof<P> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proof types should at least derive Clone, Debug, and serde traits

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely true. I'm going to merge now anyway because (i) this PR is already too big, (ii) don't want to initiate another round of approval, (iii) there will certainly be back-and-forth over issues like this as we integrate into the sequencer.

proofs: Vec<P>,
prefix_bytes: Vec<u8>,
suffix_bytes: Vec<u8>,
chunk_range: Range<usize>,
}

/// A proof intended for use on large payload subslices.
///
/// Metadata needed to recover a KZG commitment.
pub struct LargeRangeProof<F> {
prefix_elems: Vec<F>,
suffix_elems: Vec<F>,
prefix_bytes: Vec<u8>,
suffix_bytes: Vec<u8>,
chunk_range: Range<usize>,
}

impl<P, T, H, V> PayloadProver<SmallRangeProof<P::Proof>> for GenericAdvz<P, T, H, V>
where
// TODO ugly trait bounds https://github.com/EspressoSystems/jellyfish/issues/253
P: UnivariatePCS<Point = <P as PolynomialCommitmentScheme>::Evaluation>,
Expand All @@ -40,7 +67,11 @@ where
V::MembershipProof: Sync + Debug,
V::Index: From<u64>,
{
fn payload_proof<B>(&self, payload: B, range: Range<usize>) -> VidResult<Proof<P::Proof>>
fn payload_proof<B>(
&self,
payload: B,
range: Range<usize>,
) -> VidResult<SmallRangeProof<P::Proof>>
where
B: AsRef<[u8]>,
{
Expand Down Expand Up @@ -75,26 +106,20 @@ where

let (proofs, _evals) = P::multi_open(&self.ck, &polynomial, &points).map_err(vid)?;

Ok(Proof {
Ok(SmallRangeProof {
proofs,
prefix_bytes: payload[range_elem_byte.start..range.start].to_vec(),
suffix_bytes: payload[range.end..range_elem_byte.end].to_vec(),
chunk_range: range,
})
}

fn payload_verify<B>(
fn payload_verify(
&self,
chunk: B,
commit: &Self::Commit,
common: &Self::Common,
proof: &Proof<P::Proof>,
) -> VidResult<Result<(), ()>>
where
B: AsRef<[u8]>,
{
let chunk = chunk.as_ref();
check_chunk_proof_consistency(chunk, proof.chunk_range.len())?;
stmt: Statement<Self>,
proof: &SmallRangeProof<P::Proof>,
) -> VidResult<Result<(), ()>> {
Self::check_stmt_proof_consistency(&stmt, &proof.chunk_range)?;

// index conversion
let range_elem = self.range_byte_to_elem(&proof.chunk_range);
Expand All @@ -103,14 +128,14 @@ where
let offset_elem = range_elem.start - self.index_byte_to_elem(start_namespace_byte);

check_range_poly(&range_poly)?;
Self::check_common_commit_consistency(common, commit)?;
Self::check_common_commit_consistency(stmt.common, stmt.commit)?;

// prepare list of data elems
let data_elems: Vec<_> = bytes_to_field::<_, P::Evaluation>(
proof
.prefix_bytes
.iter()
.chain(chunk)
.chain(stmt.payload_subslice)
.chain(proof.suffix_bytes.iter()),
)
.collect();
Expand All @@ -135,7 +160,7 @@ where
)));
}
assert_eq!(data_elems.len(), points.len()); // sanity
let poly_commit = &common.poly_commits[range_poly.start];
let poly_commit = &stmt.common.poly_commits[range_poly.start];
for (point, (elem, pf)) in points
.iter()
.zip(data_elems.iter().zip(proof.proofs.iter()))
Expand All @@ -148,17 +173,7 @@ where
}
}

/// KZG batch proofs and accompanying metadata.
///
/// TODO use batch proof instead of `Vec<P>` <https://github.com/EspressoSystems/jellyfish/issues/387>
pub struct Proof<P> {
proofs: Vec<P>,
prefix_bytes: Vec<u8>,
suffix_bytes: Vec<u8>,
chunk_range: Range<usize>,
}

impl<P, T, H, V> PayloadProver<CommitRecovery<P::Evaluation>> for GenericAdvz<P, T, H, V>
impl<P, T, H, V> PayloadProver<LargeRangeProof<P::Evaluation>> for GenericAdvz<P, T, H, V>
where
// TODO ugly trait bounds https://github.com/EspressoSystems/jellyfish/issues/253
P: UnivariatePCS<Point = <P as PolynomialCommitmentScheme>::Evaluation>,
Expand All @@ -175,7 +190,7 @@ where
&self,
payload: B,
range: Range<usize>,
) -> VidResult<CommitRecovery<P::Evaluation>>
) -> VidResult<LargeRangeProof<P::Evaluation>>
where
B: AsRef<[u8]>,
{
Expand All @@ -198,7 +213,7 @@ where
let prefix: Vec<_> = elems_iter.by_ref().take(offset_elem).collect();
let suffix: Vec<_> = elems_iter.skip(range_elem.len()).collect();

Ok(CommitRecovery {
Ok(LargeRangeProof {
prefix_elems: prefix,
suffix_elems: suffix,
prefix_bytes: payload[range_elem_byte.start..range.start].to_vec(),
Expand All @@ -207,24 +222,18 @@ where
})
}

fn payload_verify<B>(
fn payload_verify(
&self,
chunk: B,
commit: &Self::Commit,
common: &Self::Common,
proof: &CommitRecovery<P::Evaluation>,
) -> VidResult<Result<(), ()>>
where
B: AsRef<[u8]>,
{
let chunk = chunk.as_ref();
check_chunk_proof_consistency(chunk, proof.chunk_range.len())?;
stmt: Statement<Self>,
proof: &LargeRangeProof<P::Evaluation>,
) -> VidResult<Result<(), ()>> {
Self::check_stmt_proof_consistency(&stmt, &proof.chunk_range)?;

// index conversion
let range_poly = self.range_byte_to_poly(&proof.chunk_range);

check_range_poly(&range_poly)?;
Self::check_common_commit_consistency(common, commit)?;
Self::check_common_commit_consistency(stmt.common, stmt.commit)?;

// rebuild the poly commit, check against `common`
let poly_commit = {
Expand All @@ -237,30 +246,21 @@ where
proof
.prefix_bytes
.iter()
.chain(chunk)
.chain(stmt.payload_subslice)
.chain(proof.suffix_bytes.iter()),
))
.chain(proof.suffix_elems.iter().cloned()),
);
P::commit(&self.ck, &poly).map_err(vid)?
};
if poly_commit != common.poly_commits[range_poly.start] {
if poly_commit != stmt.common.poly_commits[range_poly.start] {
return Ok(Err(()));
}

Ok(Ok(()))
}
}

/// Metadata needed to recover a KZG commitment.
pub struct CommitRecovery<F> {
prefix_elems: Vec<F>,
suffix_elems: Vec<F>,
prefix_bytes: Vec<u8>,
suffix_bytes: Vec<u8>,
chunk_range: Range<usize>,
}

impl<P, T, H, V> GenericAdvz<P, T, H, V>
where
// TODO ugly trait bounds https://github.com/EspressoSystems/jellyfish/issues/253
Expand Down Expand Up @@ -311,6 +311,32 @@ where
}
Ok(())
}

fn check_stmt_proof_consistency(
stmt: &Statement<Self>,
proof_range: &Range<usize>,
) -> VidResult<()> {
if stmt.range.is_empty() {
return Err(VidError::Argument(format!(
"empty range ({},{})",
stmt.range.start, stmt.range.end
)));
}
if stmt.payload_subslice.len() != stmt.range.len() {
return Err(VidError::Argument(format!(
"payload_subslice length {} inconsistent with range length {}",
stmt.payload_subslice.len(),
stmt.range.len()
)));
}
if stmt.range != *proof_range {
return Err(VidError::Argument(format!(
"statement range ({},{}) differs from proof range ({},{})",
stmt.range.start, stmt.range.end, proof_range.start, proof_range.end,
)));
}
Ok(())
}
}

fn range_coarsen(range: &Range<usize>, denominator: usize) -> Range<usize> {
Expand Down Expand Up @@ -366,27 +392,12 @@ fn check_range_poly(range_poly: &Range<usize>) -> VidResult<()> {
Ok(())
}

fn check_chunk_proof_consistency(chunk: &[u8], proof_chunk_len: usize) -> VidResult<()> {
if chunk.is_empty() {
return Err(VidError::Argument("empty chunk".to_string()));
}

if chunk.len() != proof_chunk_len {
return Err(VidError::Argument(format!(
"chunk length {} inconsistent with proof length {}",
chunk.len(),
proof_chunk_len
)));
}
Ok(())
}

#[cfg(test)]
mod tests {
use crate::vid::{
advz::{
bytes_to_field::elem_byte_capacity,
payload_prover::{CommitRecovery, Proof},
payload_prover::{LargeRangeProof, SmallRangeProof, Statement},
tests::*,
*,
},
Expand Down Expand Up @@ -478,21 +489,24 @@ mod tests {
};
println!("poly {} {} case: {:?}", poly, cases.1, range);

let data_proof: Proof<_> = advz.payload_proof(&payload, range.clone()).unwrap();
advz.payload_verify(&payload[range.clone()], &d.commit, &d.common, &data_proof)
let stmt = Statement {
payload_subslice: &payload[range.clone()],
range: range.clone(),
commit: &d.commit,
common: &d.common,
};

let small_range_proof: SmallRangeProof<_> =
advz.payload_proof(&payload, range.clone()).unwrap();
advz.payload_verify(stmt.clone(), &small_range_proof)
.unwrap()
.unwrap();

let chunk_proof: CommitRecovery<_> =
let large_range_proof: LargeRangeProof<_> =
advz.payload_proof(&payload, range.clone()).unwrap();
advz.payload_verify(
&payload[range.clone()],
&d.commit,
&d.common,
&chunk_proof,
)
.unwrap()
.unwrap();
advz.payload_verify(stmt, &large_range_proof)
.unwrap()
.unwrap();
}
}
}
Expand Down
Loading
Loading