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

fix: check eval_proof for all evaluations #657

Merged
merged 10 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
50 changes: 31 additions & 19 deletions vid/src/advz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ where
// TODO further aggregate into a single KZG proof.
aggregate_proofs: Vec<KzgProof<E>>,

evals_proof: KzgEvalsMerkleTreeProof<E, H>,
eval_proofs: Vec<KzgEvalsMerkleTreeProof<E, H>>,
ggutoski marked this conversation as resolved.
Show resolved Hide resolved
}

/// The [`VidScheme::Common`] type for [`Advz`].
Expand Down Expand Up @@ -527,25 +527,33 @@ where
common.poly_commits.len()
)));
}
if share.eval_proofs.len() != multiplicity {
return Err(VidError::Argument(format!(
"number of eval_proofs {} differs from common multiplicity {}",
share.eval_proofs.len(),
multiplicity,
)));
}

Self::is_consistent(commit, common)?;

if share.index >= self.num_storage_nodes {
return Ok(Err(())); // not an arg error
}

// verify eval proof
// TODO: check all indices that represents the shares
if KzgEvalsMerkleTree::<E, H>::verify(
common.all_evals_digest,
&KzgEvalsMerkleTreeIndex::<E, H>::from(share.index as u64),
&share.evals_proof,
)
.map_err(vid)?
.is_err()
{
return Ok(Err(()));
// verify eval proofs
for i in 0..self.multiplicity {
if KzgEvalsMerkleTree::<E, H>::verify(
common.all_evals_digest,
&KzgEvalsMerkleTreeIndex::<E, H>::from(share.index + i),
&share.eval_proofs[i as usize],
)
.map_err(vid)?
.is_err()
{
return Ok(Err(()));
}
}

let pseudorandom_scalar = Self::pseudorandom_scalar(common, commit)?;

// Compute aggregate polynomial [commitment|evaluation]
Expand Down Expand Up @@ -899,7 +907,7 @@ where
/// Each share contains (for multiplicity m):
/// 1. (m * num_poly) evaluations.
/// 2. a collection of m KZG proofs. TODO KZG aggregation https://github.com/EspressoSystems/jellyfish/issues/356
/// 3. a merkle tree membership proof.
/// 3. m merkle tree membership proofs.
fn assemble_shares(
&self,
all_storage_node_evals: Vec<Vec<<E as Pairing>::ScalarField>>,
Expand All @@ -915,20 +923,24 @@ where
let mut shares = Vec::with_capacity(self.num_storage_nodes as usize);
let mut evals = Vec::with_capacity(num_of_polys * self.multiplicity as usize);
let mut proofs = Vec::with_capacity(self.multiplicity as usize);
let mut eval_proofs = Vec::with_capacity(self.multiplicity as usize);
let mut index = 0;
for i in 0..code_word_size {
ggutoski marked this conversation as resolved.
Show resolved Hide resolved
evals.extend(all_storage_node_evals[i].iter());
proofs.push(aggregate_proofs[i].clone());
eval_proofs.push(
all_evals_commit
.lookup(KzgEvalsMerkleTreeIndex::<E, H>::from(i as u64))
.expect_ok()
.map_err(vid)?
.1,
);
if (i + 1) % self.multiplicity as usize == 0 {
shares.push(Share {
index,
evals: mem::take(&mut evals),
aggregate_proofs: mem::take(&mut proofs),
evals_proof: all_evals_commit // TODO: check MT lookup for each index
.lookup(KzgEvalsMerkleTreeIndex::<E, H>::from(index as u64))
.expect_ok()
.map_err(vid)?
.1,
eval_proofs: mem::take(&mut eval_proofs),
});
index += 1;
}
Expand Down
69 changes: 63 additions & 6 deletions vid/src/advz/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use ark_std::{
rand::{CryptoRng, RngCore},
vec,
};
use jf_pcs::{checked_fft_size, prelude::UnivariateUniversalParams};
use jf_pcs::{
checked_fft_size,
prelude::{Commitment, UnivariateUniversalParams},
};
use jf_utils::field_byte_len;
use sha2::Sha256;

Expand Down Expand Up @@ -104,7 +107,7 @@ fn sad_path_verify_share_corrupt_share() {
// (without also causing a deserialization failure).
// So we use another share's proof instead.
let share_bad_evals_proof = Share {
evals_proof: shares[(i + 1) % shares.len()].evals_proof.clone(),
eval_proofs: shares[(i + 1) % shares.len()].eval_proofs.clone(),
..share.clone()
};
advz.verify_share(&share_bad_evals_proof, &common, &commit)
Expand Down Expand Up @@ -240,6 +243,24 @@ fn sad_path_recover_payload_corrupt_shares() {
}
}

#[test]
ggutoski marked this conversation as resolved.
Show resolved Hide resolved
fn verify_share_with_multiplicity() {
let advz_params = AdvzParams {
recovery_threshold: 16,
num_storage_nodes: 20,
multiplicity: 4,
payload_len: 4000,
};
let (mut advz, payload) = advz_init_with(advz_params);

let disperse = advz.disperse(payload).unwrap();
let (shares, common, commit) = (disperse.shares, disperse.common, disperse.commit);

for share in shares {
assert!(advz.verify_share(&share, &common, &commit).is_ok())
}
}

#[test]
fn verify_share_with_different_multiplicity() {
// leader_multiplicity < everyone else's multiplicity
Expand Down Expand Up @@ -298,17 +319,53 @@ fn verify_share_with_different_multiplicity_helper<E, H>(
}
}

struct AdvzParams {
recovery_threshold: u32,
num_storage_nodes: u32,
multiplicity: u32,
payload_len: usize,
}

/// Routine initialization tasks.
///
/// Returns the following tuple:
/// 1. An initialized [`Advz`] instance.
/// 2. A `Vec<u8>` filled with random bytes.
pub(super) fn advz_init() -> (Advz<Bls12_381, Sha256>, Vec<u8>) {
let (recovery_threshold, num_storage_nodes) = (4, 6);
let advz_params = AdvzParams {
recovery_threshold: 16,
num_storage_nodes: 20,
multiplicity: 1,
payload_len: 4000,
};
advz_init_with(advz_params)
}

fn advz_init_with(advz_params: AdvzParams) -> (Advz<Bls12_381, Sha256>, Vec<u8>) {
let mut rng = jf_utils::test_rng();
let srs = init_srs(recovery_threshold as usize, &mut rng);
let advz = Advz::new(num_storage_nodes, recovery_threshold, srs).unwrap();
let bytes_random = init_random_payload(4000, &mut rng);
let poly_len = advz_params.recovery_threshold * advz_params.multiplicity;
let srs = init_srs(poly_len as usize, &mut rng);
assert_ne!(
advz_params.multiplicity, 0,
"multiplicity should not be zero"
);
let advz = if advz_params.multiplicity > 1 {
Advz::with_multiplicity(
advz_params.num_storage_nodes,
advz_params.recovery_threshold,
advz_params.multiplicity,
srs,
)
.unwrap()
} else {
Advz::new(
advz_params.num_storage_nodes,
advz_params.recovery_threshold,
srs,
)
.unwrap()
};
let bytes_random = init_random_payload(advz_params.payload_len, &mut rng);
(advz, bytes_random)
}

Expand Down
Loading