Skip to content

Commit

Permalink
Mastic clean up (#1187)
Browse files Browse the repository at this point in the history
* mastic: Remove `verify_key` from tests that don't use it

Some tests in the `mastic` module generate verification keys that aren't
actually used by the test. Incidentally, the same tests were
generating keys of the wrong length.

* mastic: De-duplicate agg share length computation

Add a function that computes the length of the aggregate share in field
elements as a function of the aggregation parameter.

* vidpf: Improve `VidpfPublicShare::encoded_len()`

Avoid iterating over the weights to compute the length of the encoded
public share; just take the length of the first weight and multiply by
the number of correction words.

This computation assumes the length of each weight is equal to the
weight parameter at ever level of the VIDPF tree. This certainly is
true, but add a test to validate this assumption anyway.

* vidpf: Move `eval_prefix_tree_with_siblings()` to `impl<W: VidpfValue>`

This method is currently implemented for `Vidpf<VidpfWeight<F>>`, but it
applies to the more general `Vidpf<W>`.

* vdaf: Remove `domain_separation_tag()` from `Vdaf` trait

This method is used in Prio3 and Poplar1 for domain separation with the
version of the document that specifies them. This version control is not
applicable to future VDAFs defined by future documents.

Remove the method from the trait and add it to implementations of
`Prio3` and `Poplar1`.

* vidpf: Rename `weight_parameter` to `weight_len`

The associated type `ValueParameter` is likely always going to be a
`usize` that expresses the length. In the future we might consider
hardcoding this change in the API.
  • Loading branch information
cjpatton authored Jan 16, 2025
1 parent 48bf7c6 commit ed949d7
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 139 deletions.
12 changes: 0 additions & 12 deletions src/vdaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,18 +197,6 @@ pub trait Vdaf: Clone + Debug {
/// The number of Aggregators. The Client generates as many input shares as there are
/// Aggregators.
fn num_aggregators(&self) -> usize;

/// Generate the domain separation tag for this VDAF. The output is used for domain separation
/// by the XOF.
fn domain_separation_tag(&self, usage: u16) -> [u8; 8] {
// Prefix is 8 bytes and defined by the spec. Copy these values in
let mut dst = [0; 8];
dst[0] = VERSION;
dst[1] = 0; // algorithm class
dst[2..6].clone_from_slice(self.algorithm_id().to_be_bytes().as_slice());
dst[6..8].clone_from_slice(usage.to_be_bytes().as_slice());
dst
}
}

/// The Client's role in the execution of a VDAF.
Expand Down
53 changes: 12 additions & 41 deletions src/vdaf/mastic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ where
bits,
})
}

fn agg_share_len(&self, agg_param: &MasticAggregationParam) -> usize {
// The aggregate share consists of the counter and truncated weight for each candidate prefix.
(1 + self.szk.typ.output_len()) * agg_param.level_and_prefixes.prefixes().len()
}
}

/// Mastic aggregation parameter.
Expand Down Expand Up @@ -158,7 +163,7 @@ where
mastic: &Mastic<T, P, SEED_SIZE>,
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
VidpfPublicShare::decode_with_param(&(mastic.bits, mastic.vidpf.weight_parameter), bytes)
VidpfPublicShare::decode_with_param(&(mastic.bits, mastic.vidpf.weight_len), bytes)
}
}

Expand Down Expand Up @@ -252,8 +257,7 @@ where
(mastic, agg_param): &(&Mastic<T, P, SEED_SIZE>, &MasticAggregationParam),
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
let len = (1 + mastic.szk.typ.output_len()) * agg_param.level_and_prefixes.prefixes().len();
decode_fieldvec(len, bytes).map(AggregateShare)
decode_fieldvec(mastic.agg_share_len(agg_param), bytes).map(AggregateShare)
}
}

Expand All @@ -268,8 +272,7 @@ where
(mastic, agg_param): &(&Mastic<T, P, SEED_SIZE>, &MasticAggregationParam),
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
let len = (1 + mastic.szk.typ.output_len()) * agg_param.level_and_prefixes.prefixes().len();
decode_fieldvec(len, bytes).map(OutputShare)
decode_fieldvec(mastic.agg_share_len(agg_param), bytes).map(OutputShare)
}
}

Expand Down Expand Up @@ -425,10 +428,10 @@ impl<'a, T: Type, P: Xof<SEED_SIZE>, const SEED_SIZE: usize>
for MasticPrepareState<T::Field, SEED_SIZE>
{
fn decode_with_param(
(mastic, agg_param): &(&Mastic<T, P, SEED_SIZE>, &MasticAggregationParam),
decoder @ (mastic, agg_param): &(&Mastic<T, P, SEED_SIZE>, &MasticAggregationParam),
bytes: &mut Cursor<&[u8]>,
) -> Result<Self, CodecError> {
let output_shares = MasticOutputShare::decode_with_param(&(*mastic, *agg_param), bytes)?;
let output_shares = MasticOutputShare::decode_with_param(decoder, bytes)?;
let szk_query_state = (mastic.szk.typ.joint_rand_len() > 0
&& agg_param.require_weight_check)
.then(|| Seed::decode(bytes))
Expand Down Expand Up @@ -774,14 +777,7 @@ where
output_shares: M,
) -> Result<MasticAggregateShare<T::Field>, VdafError> {
let mut agg_share =
MasticAggregateShare::<T::Field>::from(vec![
T::Field::zero();
(1 + self.szk.typ.output_len())
* agg_param
.level_and_prefixes
.prefixes()
.len()
]);
MasticAggregateShare::from(vec![T::Field::zero(); self.agg_share_len(agg_param)]);
for output_share in output_shares.into_iter() {
agg_share.accumulate(&output_share)?;
}
Expand All @@ -803,10 +799,7 @@ where
let num_prefixes = agg_param.level_and_prefixes.prefixes().len();

let AggregateShare(agg) = agg_shares.into_iter().try_fold(
AggregateShare(vec![
T::Field::zero();
num_prefixes * (1 + self.szk.typ.output_len())
]),
AggregateShare(vec![T::Field::zero(); self.agg_share_len(agg_param)]),
|mut agg, agg_share| {
agg.merge(&agg_share)?;
Result::<_, VdafError>::Ok(agg)
Expand Down Expand Up @@ -866,8 +859,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sum_typ, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let inputs = [
Expand Down Expand Up @@ -947,8 +938,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sum_typ, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand Down Expand Up @@ -1000,8 +989,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sum_typ, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand All @@ -1023,8 +1010,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, count, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let inputs = [
Expand Down Expand Up @@ -1102,8 +1087,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, count, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);
let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);

Expand All @@ -1122,8 +1105,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, count, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand All @@ -1144,8 +1125,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sumvec, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let inputs = [
Expand Down Expand Up @@ -1234,8 +1213,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sumvec, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand Down Expand Up @@ -1265,8 +1242,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sumvec, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand Down Expand Up @@ -1298,8 +1273,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sumvec, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand All @@ -1323,8 +1296,6 @@ mod tests {
let mastic = Mastic::<_, XofTurboShake128, 32>::new(algorithm_id, sumvec, 32).unwrap();

let mut nonce = [0u8; 16];
let mut verify_key = [0u8; 16];
thread_rng().fill(&mut verify_key[..]);
thread_rng().fill(&mut nonce[..]);

let first_input = VidpfInput::from_bytes(&[15u8, 0u8, 1u8, 4u8][..]);
Expand Down
14 changes: 13 additions & 1 deletion src/vdaf/poplar1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
prng::Prng,
vdaf::{
xof::{Seed, Xof, XofTurboShake128},
Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError,
Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError, VERSION,
},
};
use rand_core::RngCore;
Expand Down Expand Up @@ -862,6 +862,18 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Vdaf for Poplar1<P, SEED_SIZE> {
}

impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> {
/// Generate the domain separation tag for this VDAF. The output is used for domain separation
/// by the XOF.
fn domain_separation_tag(&self, usage: u16) -> [u8; 8] {
// Prefix is 8 bytes and defined by the spec. Copy these values in
let mut dst = [0; 8];
dst[0] = VERSION;
dst[1] = 0; // algorithm class
dst[2..6].clone_from_slice(self.algorithm_id().to_be_bytes().as_slice());
dst[6..8].clone_from_slice(usage.to_be_bytes().as_slice());
dst
}

fn shard_with_random(
&self,
ctx: &[u8],
Expand Down
14 changes: 13 additions & 1 deletion src/vdaf/prio3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ use crate::prng::Prng;
use crate::vdaf::xof::{IntoFieldVec, Seed, Xof};
use crate::vdaf::{
Aggregatable, AggregateShare, Aggregator, Client, Collector, OutputShare, PrepareTransition,
Share, ShareDecodingParameter, Vdaf, VdafError,
Share, ShareDecodingParameter, Vdaf, VdafError, VERSION,
};
#[cfg(feature = "experimental")]
use fixed::traits::Fixed;
Expand Down Expand Up @@ -548,6 +548,18 @@ where
.into_field_vec(self.typ.query_rand_len() * self.num_proofs())
}

/// Generate the domain separation tag for this VDAF. The output is used for domain separation
/// by the XOF.
fn domain_separation_tag(&self, usage: u16) -> [u8; 8] {
// Prefix is 8 bytes and defined by the spec. Copy these values in
let mut dst = [0; 8];
dst[0] = VERSION;
dst[1] = 0; // algorithm class
dst[2..6].clone_from_slice(self.algorithm_id().to_be_bytes().as_slice());
dst[6..8].clone_from_slice(usage.to_be_bytes().as_slice());
dst
}

fn random_size(&self) -> usize {
if self.typ.joint_rand_len() == 0 {
// One seed per helper (share, proof) pair, plus one seed for proving randomness
Expand Down
Loading

0 comments on commit ed949d7

Please sign in to comment.