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

More Mastic clean up #1200

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 0 additions & 2 deletions src/flp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ use std::convert::TryFrom;
use std::fmt::Debug;

pub mod gadgets;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
pub mod szk;
pub mod types;

/// Errors propagated by methods in this module.
Expand Down
12 changes: 6 additions & 6 deletions src/prng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<F: FieldElement> Prng<F, SeedStreamTurboShake128> {
pub(crate) fn new() -> Result<Self, PrngError> {
let seed = Seed::generate()?;
Ok(Prng::from_seed_stream(XofTurboShake128::seed_stream(
&seed,
seed.as_ref(),
&[],
&[],
)))
Expand Down Expand Up @@ -234,14 +234,14 @@ mod tests {
.unwrap();
let expected = Field64::from(4857131209231097247);

let seed_stream = XofTurboShake128::seed_stream(&seed, &[], &[]);
let seed_stream = XofTurboShake128::seed_stream(seed.as_ref(), &[], &[]);
let mut prng = Prng::<Field64, _>::from_seed_stream(seed_stream);
let actual = prng.nth(13882).unwrap();
assert_eq!(actual, expected);

#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
{
let mut seed_stream = XofTurboShake128::seed_stream(&seed, &[], &[]);
let mut seed_stream = XofTurboShake128::seed_stream(seed.as_ref(), &[], &[]);
let mut actual = <Field64 as FieldElement>::zero();
for _ in 0..=13882 {
actual = <Field64 as crate::idpf::IdpfValue>::generate(&mut seed_stream, &());
Expand All @@ -257,11 +257,11 @@ mod tests {
let seed = Seed::generate().unwrap();

let mut prng: Prng<Field64, SeedStreamTurboShake128> =
Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, &[], &[]));
Prng::from_seed_stream(XofTurboShake128::seed_stream(seed.as_ref(), &[], &[]));

// Construct a `Prng` with a longer-than-usual buffer.
let mut prng_weird_buffer_size: Prng<Field64, SeedStreamTurboShake128> =
Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, &[], &[]));
Prng::from_seed_stream(XofTurboShake128::seed_stream(seed.as_ref(), &[], &[]));
let mut extra = [0; 7];
prng_weird_buffer_size.seed_stream.fill_bytes(&mut extra);
prng_weird_buffer_size.buffer.extend_from_slice(&extra);
Expand All @@ -278,7 +278,7 @@ mod tests {
fn into_different_field() {
let seed = Seed::generate().unwrap();
let want: Prng<Field64, SeedStreamTurboShake128> =
Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, &[], &[]));
Prng::from_seed_stream(XofTurboShake128::seed_stream(seed.as_ref(), &[], &[]));
let want_buffer = want.buffer.clone();

let got: Prng<Field128, _> = want.into_new_field();
Expand Down
4 changes: 2 additions & 2 deletions src/vdaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
#[cfg(feature = "experimental")]
use crate::dp::DifferentialPrivacyStrategy;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::flp::szk::SzkError;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::idpf::IdpfError;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::vdaf::mastic::szk::SzkError;
#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))]
use crate::vidpf::VidpfError;
use crate::{
codec::{CodecError, Decode, Encode, ParameterizedDecode},
Expand Down
78 changes: 40 additions & 38 deletions src/vdaf/mastic.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
// SPDX-License-Identifier: MPL-2.0

//! Implementation of Mastic as specified in [[draft-mouris-cfrg-mastic-01]].
//! Implementation of Mastic as specified in [[draft-mouris-cfrg-mastic-04]].
//!
//! [draft-mouris-cfrg-mastic-01]: https://www.ietf.org/archive/id/draft-mouris-cfrg-mastic-01.html
//! [draft-mouris-cfrg-mastic-04]: https://www.ietf.org/archive/id/draft-mouris-cfrg-mastic-04.html

use crate::{
bt::BinaryTree,
codec::{CodecError, Decode, Encode, ParameterizedDecode},
field::{decode_fieldvec, FieldElement, FieldElementWithInteger},
flp::{
szk::{Szk, SzkJointShare, SzkProofShare, SzkQueryShare, SzkQueryState},
Type,
},
flp::Type,
vdaf::{
poplar1::{Poplar1, Poplar1AggregationParam},
xof::{Seed, Xof},
Expand All @@ -24,6 +21,9 @@ use crate::{
},
};

use szk::{Szk, SzkJointShare, SzkProofShare, SzkQueryShare, SzkQueryState};

use rand::prelude::*;
use std::io::{Cursor, Read};
use std::ops::BitAnd;
use std::slice::from_ref;
Expand All @@ -32,7 +32,10 @@ use subtle::{Choice, ConstantTimeEq};

use super::xof::XofTurboShake128;

const NONCE_SIZE: usize = 16;
pub(crate) mod szk;

pub(crate) const SEED_SIZE: usize = 32;
pub(crate) const NONCE_SIZE: usize = 16;

pub(crate) const USAGE_PROVE_RAND: u8 = 0;
pub(crate) const USAGE_PROOF_SHARE: u8 = 1;
Expand Down Expand Up @@ -60,8 +63,6 @@ pub struct Mastic<T: Type> {
id: [u8; 4],
pub(crate) szk: Szk<T>,
pub(crate) vidpf: Vidpf<VidpfWeight<T::Field>>,
/// The length of the private attribute associated with any input.
pub(crate) bits: usize,
}

impl<T: Type> Mastic<T> {
Expand All @@ -73,7 +74,6 @@ impl<T: Type> Mastic<T> {
id: algorithm_id.to_le_bytes(),
szk,
vidpf,
bits,
})
}

Expand Down Expand Up @@ -140,7 +140,7 @@ impl<T: Type> ParameterizedDecode<Mastic<T>> for MasticPublicShare<VidpfWeight<T
mastic: &Mastic<T>,
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
VidpfPublicShare::decode_with_param(&(mastic.bits, mastic.vidpf.weight_len), bytes)
VidpfPublicShare::decode_with_param(&mastic.vidpf, bytes)
}
}

Expand Down Expand Up @@ -260,12 +260,12 @@ impl<T: Type> Mastic<T> {
&self,
ctx: &[u8],
(alpha, weight): &(VidpfInput, T::Measurement),
nonce: &[u8; 16],
nonce: &[u8; NONCE_SIZE],
vidpf_keys: [VidpfKey; 2],
szk_random: [Seed<32>; 2],
joint_random_opt: Option<Seed<32>>,
szk_random: [Seed<SEED_SIZE>; 2],
joint_random_opt: Option<Seed<SEED_SIZE>>,
) -> Result<(<Self as Vdaf>::PublicShare, Vec<<Self as Vdaf>::InputShare>), VdafError> {
if alpha.len() != self.bits {
if alpha.len() != usize::from(self.vidpf.bits) {
return Err(VdafError::Vidpf(VidpfError::InvalidInputLength));
}

Expand Down Expand Up @@ -344,9 +344,9 @@ impl<T: Type> Client<16> for Mastic<T> {

/// Mastic preparation state.
///
/// State held by an aggregator waiting for a message during Mastic preparation. Includes intermediate
/// state for [`Szk`] verification, the output shares currently being validated, and
/// parameters of Mastic used for encoding.
/// State held by an aggregator waiting for a message during Mastic preparation. Includes
/// intermediate state for the evaluation check, the range check (if applicable) verification, and
/// the output shares currently being validated.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MasticPrepareState<F: FieldElement> {
/// The counter and truncated weight for each candidate prefix.
Expand All @@ -368,7 +368,7 @@ impl<F: FieldElement> Encode for MasticPrepareState<F> {
fn encoded_len(&self) -> Option<usize> {
Some(
self.output_shares.as_ref().len() * F::ENCODED_SIZE
+ self.szk_query_state.as_ref().map_or(0, |_| 32),
+ self.szk_query_state.as_ref().map_or(0, |_| SEED_SIZE),
)
}
}
Expand Down Expand Up @@ -405,15 +405,15 @@ impl<'a, T: Type> ParameterizedDecode<(&'a Mastic<T>, &'a MasticAggregationParam
#[derive(Clone, Debug, PartialEq)]
pub struct MasticPrepareShare<F: FieldElement> {
/// [`Vidpf`] evaluation proof, which guarantees one-hotness and payload consistency.
eval_proof: [u8; VIDPF_PROOF_SIZE],
vidpf_eval_proof: [u8; VIDPF_PROOF_SIZE],

/// If [`Szk`]` verification of the root weight is needed, a verification message.
szk_query_share_opt: Option<SzkQueryShare<F>>,
}

impl<F: FieldElement> Encode for MasticPrepareShare<F> {
fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
bytes.extend_from_slice(&self.eval_proof);
bytes.extend_from_slice(&self.vidpf_eval_proof);
match &self.szk_query_share_opt {
Some(query_share) => query_share.encode(bytes),
None => Ok(()),
Expand All @@ -436,8 +436,8 @@ impl<F: FieldElement> ParameterizedDecode<MasticPrepareState<F>> for MasticPrepa
prep_state: &MasticPrepareState<F>,
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
let mut eval_proof = [0; VIDPF_PROOF_SIZE];
bytes.read_exact(&mut eval_proof[..])?;
let mut vidpf_eval_proof = [0; VIDPF_PROOF_SIZE];
bytes.read_exact(&mut vidpf_eval_proof[..])?;
let requires_joint_rand = prep_state.szk_query_state.is_some();
let szk_query_share_opt = prep_state
.verifier_len
Expand All @@ -446,7 +446,7 @@ impl<F: FieldElement> ParameterizedDecode<MasticPrepareState<F>> for MasticPrepa
})
.transpose()?;
Ok(Self {
eval_proof,
vidpf_eval_proof,
szk_query_share_opt,
})
}
Expand All @@ -470,7 +470,7 @@ impl<F: FieldElement> ParameterizedDecode<MasticPrepareState<F>> for MasticPrepa
}
}

impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
impl<T: Type> Aggregator<SEED_SIZE, NONCE_SIZE> for Mastic<T> {
type PrepareState = MasticPrepareState<T::Field>;
type PrepareShare = MasticPrepareShare<T::Field>;
type PrepareMessage = MasticPrepareMessage;
Expand All @@ -487,15 +487,15 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
// Unpack this agg param and the last one in the list
let cur_poplar_agg_param = &cur.level_and_prefixes;
let prev_poplar_agg_param = from_ref(&prev.last().as_ref().unwrap().level_and_prefixes);
Poplar1::<XofTurboShake128, 32>::is_agg_param_valid(
Poplar1::<XofTurboShake128, SEED_SIZE>::is_agg_param_valid(
cur_poplar_agg_param,
prev_poplar_agg_param,
)
}

fn prepare_init(
&self,
verify_key: &[u8; 32],
verify_key: &[u8; SEED_SIZE],
ctx: &[u8],
agg_id: usize,
agg_param: &MasticAggregationParam,
Expand Down Expand Up @@ -583,13 +583,15 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
c.get_encoded().unwrap()
};

let eval_proof = {
let mut eval_proof_xof =
XofTurboShake128::init(verify_key, &[&dst_usage(USAGE_EVAL_PROOF), &self.id, ctx]);
eval_proof_xof.update(&onehot_check);
eval_proof_xof.update(&counter_check);
eval_proof_xof.update(&payload_check);
eval_proof_xof.into_seed().0
let vidpf_eval_proof = {
let mut vidpf_eval_proof = [0; VIDPF_PROOF_SIZE];
XofTurboShake128::seed_stream(
verify_key,
&[&dst_usage(USAGE_EVAL_PROOF), &self.id, ctx],
&[&onehot_check, &counter_check, &payload_check],
)
.fill(&mut vidpf_eval_proof);
vidpf_eval_proof
};

let mut truncated_out_shares =
Expand Down Expand Up @@ -626,7 +628,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
verifier_len: Some(verifier_len),
},
MasticPrepareShare {
eval_proof,
vidpf_eval_proof,
szk_query_share_opt: Some(szk_query_share),
},
)
Expand All @@ -638,7 +640,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
verifier_len: None,
},
MasticPrepareShare {
eval_proof,
vidpf_eval_proof,
szk_query_share_opt: None,
},
)
Expand All @@ -663,7 +665,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
"Received more than two prepare shares".to_string(),
));
};
if leader_share.eval_proof != helper_share.eval_proof {
if leader_share.vidpf_eval_proof != helper_share.vidpf_eval_proof {
return Err(VdafError::Uncategorized(
"Vidpf proof verification failed".to_string(),
));
Expand All @@ -688,7 +690,7 @@ impl<T: Type> Aggregator<32, NONCE_SIZE> for Mastic<T> {
_ctx: &[u8],
state: MasticPrepareState<T::Field>,
input: MasticPrepareMessage,
) -> Result<PrepareTransition<Self, 32, NONCE_SIZE>, VdafError> {
) -> Result<PrepareTransition<Self, SEED_SIZE, NONCE_SIZE>, VdafError> {
let MasticPrepareState {
output_shares,
szk_query_state,
Expand Down
Loading
Loading