diff options
Diffstat (limited to '')
56 files changed, 3990 insertions, 2596 deletions
diff --git a/third_party/rust/prio/src/codec.rs b/third_party/rust/prio/src/codec.rs index 71f4f8ce5f..98e6299abd 100644 --- a/third_party/rust/prio/src/codec.rs +++ b/third_party/rust/prio/src/codec.rs @@ -20,6 +20,7 @@ use std::{ /// An error that occurred during decoding. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum CodecError { /// An I/O error. #[error("I/O error")] @@ -33,6 +34,10 @@ pub enum CodecError { #[error("length prefix of encoded vector overflows buffer: {0}")] LengthPrefixTooBig(usize), + /// The byte length of a vector exceeded the range of its length prefix. + #[error("vector length exceeded range of length prefix")] + LengthPrefixOverflow, + /// Custom errors from [`Decode`] implementations. #[error("other error: {0}")] Other(#[source] Box<dyn Error + 'static + Send + Sync>), @@ -97,10 +102,10 @@ impl<D: Decode + ?Sized, T> ParameterizedDecode<T> for D { /// Describes how to encode objects into a byte sequence. pub trait Encode { /// Append the encoded form of this object to the end of `bytes`, growing the vector as needed. - fn encode(&self, bytes: &mut Vec<u8>); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError>; /// Convenience method to encode a value into a new `Vec<u8>`. - fn get_encoded(&self) -> Vec<u8> { + fn get_encoded(&self) -> Result<Vec<u8>, CodecError> { self.get_encoded_with_param(&()) } @@ -116,17 +121,21 @@ pub trait ParameterizedEncode<P> { /// Append the encoded form of this object to the end of `bytes`, growing the vector as needed. /// `encoding_parameter` provides details of the wire encoding, used to control how the value /// is encoded. - fn encode_with_param(&self, encoding_parameter: &P, bytes: &mut Vec<u8>); + fn encode_with_param( + &self, + encoding_parameter: &P, + bytes: &mut Vec<u8>, + ) -> Result<(), CodecError>; /// Convenience method to encode a value into a new `Vec<u8>`. - fn get_encoded_with_param(&self, encoding_parameter: &P) -> Vec<u8> { + fn get_encoded_with_param(&self, encoding_parameter: &P) -> Result<Vec<u8>, CodecError> { let mut ret = if let Some(length) = self.encoded_len_with_param(encoding_parameter) { Vec::with_capacity(length) } else { Vec::new() }; - self.encode_with_param(encoding_parameter, &mut ret); - ret + self.encode_with_param(encoding_parameter, &mut ret)?; + Ok(ret) } /// Returns an optional hint indicating how many bytes will be required to encode this value, or @@ -139,7 +148,11 @@ pub trait ParameterizedEncode<P> { /// Provide a blanket implementation so that any [`Encode`] can be used as a /// `ParameterizedEncode<T>` for any `T`. impl<E: Encode + ?Sized, T> ParameterizedEncode<T> for E { - fn encode_with_param(&self, _encoding_parameter: &T, bytes: &mut Vec<u8>) { + fn encode_with_param( + &self, + _encoding_parameter: &T, + bytes: &mut Vec<u8>, + ) -> Result<(), CodecError> { self.encode(bytes) } @@ -155,7 +168,9 @@ impl Decode for () { } impl Encode for () { - fn encode(&self, _bytes: &mut Vec<u8>) {} + fn encode(&self, _bytes: &mut Vec<u8>) -> Result<(), CodecError> { + Ok(()) + } fn encoded_len(&self) -> Option<usize> { Some(0) @@ -171,8 +186,9 @@ impl Decode for u8 { } impl Encode for u8 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.push(*self); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -187,8 +203,9 @@ impl Decode for u16 { } impl Encode for u16 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.extend_from_slice(&u16::to_be_bytes(*self)); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -208,9 +225,10 @@ impl Decode for U24 { } impl Encode for U24 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { // Encode lower three bytes of the u32 as u24 bytes.extend_from_slice(&u32::to_be_bytes(self.0)[1..]); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -225,8 +243,9 @@ impl Decode for u32 { } impl Encode for u32 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.extend_from_slice(&u32::to_be_bytes(*self)); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -241,8 +260,9 @@ impl Decode for u64 { } impl Encode for u64 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.extend_from_slice(&u64::to_be_bytes(*self)); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -257,18 +277,19 @@ pub fn encode_u8_items<P, E: ParameterizedEncode<P>>( bytes: &mut Vec<u8>, encoding_parameter: &P, items: &[E], -) { +) -> Result<(), CodecError> { // Reserve space to later write length let len_offset = bytes.len(); bytes.push(0); for item in items { - item.encode_with_param(encoding_parameter, bytes); + item.encode_with_param(encoding_parameter, bytes)?; } - let len = bytes.len() - len_offset - 1; - assert!(len <= usize::from(u8::MAX)); - bytes[len_offset] = len as u8; + let len = + u8::try_from(bytes.len() - len_offset - 1).map_err(|_| CodecError::LengthPrefixOverflow)?; + bytes[len_offset] = len; + Ok(()) } /// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of @@ -292,20 +313,19 @@ pub fn encode_u16_items<P, E: ParameterizedEncode<P>>( bytes: &mut Vec<u8>, encoding_parameter: &P, items: &[E], -) { +) -> Result<(), CodecError> { // Reserve space to later write length let len_offset = bytes.len(); - 0u16.encode(bytes); + 0u16.encode(bytes)?; for item in items { - item.encode_with_param(encoding_parameter, bytes); + item.encode_with_param(encoding_parameter, bytes)?; } - let len = bytes.len() - len_offset - 2; - assert!(len <= usize::from(u16::MAX)); - for (offset, byte) in u16::to_be_bytes(len as u16).iter().enumerate() { - bytes[len_offset + offset] = *byte; - } + let len = u16::try_from(bytes.len() - len_offset - 2) + .map_err(|_| CodecError::LengthPrefixOverflow)?; + bytes[len_offset..len_offset + 2].copy_from_slice(&len.to_be_bytes()); + Ok(()) } /// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of @@ -330,20 +350,22 @@ pub fn encode_u24_items<P, E: ParameterizedEncode<P>>( bytes: &mut Vec<u8>, encoding_parameter: &P, items: &[E], -) { +) -> Result<(), CodecError> { // Reserve space to later write length let len_offset = bytes.len(); - U24(0).encode(bytes); + U24(0).encode(bytes)?; for item in items { - item.encode_with_param(encoding_parameter, bytes); + item.encode_with_param(encoding_parameter, bytes)?; } - let len = bytes.len() - len_offset - 3; - assert!(len <= 0xffffff); - for (offset, byte) in u32::to_be_bytes(len as u32)[1..].iter().enumerate() { - bytes[len_offset + offset] = *byte; + let len = u32::try_from(bytes.len() - len_offset - 3) + .map_err(|_| CodecError::LengthPrefixOverflow)?; + if len > 0xffffff { + return Err(CodecError::LengthPrefixOverflow); } + bytes[len_offset..len_offset + 3].copy_from_slice(&len.to_be_bytes()[1..]); + Ok(()) } /// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of @@ -368,20 +390,19 @@ pub fn encode_u32_items<P, E: ParameterizedEncode<P>>( bytes: &mut Vec<u8>, encoding_parameter: &P, items: &[E], -) { +) -> Result<(), CodecError> { // Reserve space to later write length let len_offset = bytes.len(); - 0u32.encode(bytes); + 0u32.encode(bytes)?; for item in items { - item.encode_with_param(encoding_parameter, bytes); + item.encode_with_param(encoding_parameter, bytes)?; } - let len = bytes.len() - len_offset - 4; - let len: u32 = len.try_into().expect("Length too large"); - for (offset, byte) in len.to_be_bytes().iter().enumerate() { - bytes[len_offset + offset] = *byte; - } + let len = u32::try_from(bytes.len() - len_offset - 4) + .map_err(|_| CodecError::LengthPrefixOverflow)?; + bytes[len_offset..len_offset + 4].copy_from_slice(&len.to_be_bytes()); + Ok(()) } /// Decode `bytes` into a vector of `D` values, treating `bytes` as a [variable-length vector][1] of @@ -432,6 +453,7 @@ fn decode_items<P, D: ParameterizedDecode<P>>( #[cfg(test)] mod tests { + use std::io::ErrorKind; use super::*; use assert_matches::assert_matches; @@ -439,7 +461,7 @@ mod tests { #[test] fn encode_nothing() { let mut bytes = vec![]; - ().encode(&mut bytes); + ().encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 0); } @@ -448,7 +470,7 @@ mod tests { let value = 100u8; let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 1); let decoded = u8::decode(&mut Cursor::new(&bytes)).unwrap(); @@ -460,7 +482,7 @@ mod tests { let value = 1000u16; let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 2); // Check endianness of encoding assert_eq!(bytes, vec![3, 232]); @@ -474,7 +496,7 @@ mod tests { let value = U24(1_000_000u32); let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 3); // Check endianness of encoding assert_eq!(bytes, vec![15, 66, 64]); @@ -488,7 +510,7 @@ mod tests { let value = 134_217_728u32; let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 4); // Check endianness of encoding assert_eq!(bytes, vec![8, 0, 0, 0]); @@ -502,7 +524,7 @@ mod tests { let value = 137_438_953_472u64; let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), 8); // Check endianness of encoding assert_eq!(bytes, vec![0, 0, 0, 32, 0, 0, 0, 0]); @@ -521,12 +543,12 @@ mod tests { } impl Encode for TestMessage { - fn encode(&self, bytes: &mut Vec<u8>) { - self.field_u8.encode(bytes); - self.field_u16.encode(bytes); - self.field_u24.encode(bytes); - self.field_u32.encode(bytes); - self.field_u64.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.field_u8.encode(bytes)?; + self.field_u16.encode(bytes)?; + self.field_u24.encode(bytes)?; + self.field_u32.encode(bytes)?; + self.field_u64.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -584,7 +606,7 @@ mod tests { }; let mut bytes = vec![]; - value.encode(&mut bytes); + value.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), TestMessage::encoded_length()); assert_eq!(value.encoded_len().unwrap(), TestMessage::encoded_length()); @@ -622,7 +644,7 @@ mod tests { fn roundtrip_variable_length_u8() { let values = messages_vec(); let mut bytes = vec![]; - encode_u8_items(&mut bytes, &(), &values); + encode_u8_items(&mut bytes, &(), &values).unwrap(); assert_eq!( bytes.len(), @@ -640,7 +662,7 @@ mod tests { fn roundtrip_variable_length_u16() { let values = messages_vec(); let mut bytes = vec![]; - encode_u16_items(&mut bytes, &(), &values); + encode_u16_items(&mut bytes, &(), &values).unwrap(); assert_eq!( bytes.len(), @@ -661,7 +683,7 @@ mod tests { fn roundtrip_variable_length_u24() { let values = messages_vec(); let mut bytes = vec![]; - encode_u24_items(&mut bytes, &(), &values); + encode_u24_items(&mut bytes, &(), &values).unwrap(); assert_eq!( bytes.len(), @@ -682,7 +704,7 @@ mod tests { fn roundtrip_variable_length_u32() { let values = messages_vec(); let mut bytes = Vec::new(); - encode_u32_items(&mut bytes, &(), &values); + encode_u32_items(&mut bytes, &(), &values).unwrap(); assert_eq!(bytes.len(), 4 + 3 * TestMessage::encoded_length()); @@ -697,6 +719,21 @@ mod tests { } #[test] + fn decode_too_short() { + let values = messages_vec(); + let mut bytes = Vec::new(); + encode_u32_items(&mut bytes, &(), &values).unwrap(); + + let error = + decode_u32_items::<_, TestMessage>(&(), &mut Cursor::new(&bytes[..3])).unwrap_err(); + assert_matches!(error, CodecError::Io(e) => assert_eq!(e.kind(), ErrorKind::UnexpectedEof)); + + let error = + decode_u32_items::<_, TestMessage>(&(), &mut Cursor::new(&bytes[..4])).unwrap_err(); + assert_matches!(error, CodecError::LengthPrefixTooBig(_)); + } + + #[test] fn decode_items_overflow() { let encoded = vec![1u8]; @@ -724,11 +761,56 @@ mod tests { #[test] fn length_hint_correctness() { - assert_eq!(().encoded_len().unwrap(), ().get_encoded().len()); - assert_eq!(0u8.encoded_len().unwrap(), 0u8.get_encoded().len()); - assert_eq!(0u16.encoded_len().unwrap(), 0u16.get_encoded().len()); - assert_eq!(U24(0).encoded_len().unwrap(), U24(0).get_encoded().len()); - assert_eq!(0u32.encoded_len().unwrap(), 0u32.get_encoded().len()); - assert_eq!(0u64.encoded_len().unwrap(), 0u64.get_encoded().len()); + assert_eq!(().encoded_len().unwrap(), ().get_encoded().unwrap().len()); + assert_eq!(0u8.encoded_len().unwrap(), 0u8.get_encoded().unwrap().len()); + assert_eq!( + 0u16.encoded_len().unwrap(), + 0u16.get_encoded().unwrap().len() + ); + assert_eq!( + U24(0).encoded_len().unwrap(), + U24(0).get_encoded().unwrap().len() + ); + assert_eq!( + 0u32.encoded_len().unwrap(), + 0u32.get_encoded().unwrap().len() + ); + assert_eq!( + 0u64.encoded_len().unwrap(), + 0u64.get_encoded().unwrap().len() + ); + } + + #[test] + fn get_decoded_leftover() { + let encoded_good = [1, 2, 3, 4]; + assert_matches!(u32::get_decoded(&encoded_good).unwrap(), 0x01020304u32); + + let encoded_bad = [1, 2, 3, 4, 5]; + let error = u32::get_decoded(&encoded_bad).unwrap_err(); + assert_matches!(error, CodecError::BytesLeftOver(1)); + } + + #[test] + fn encoded_len_backwards_compatibility() { + struct MyMessage; + + impl Encode for MyMessage { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + bytes.extend_from_slice(b"Hello, world"); + Ok(()) + } + } + + assert_eq!(MyMessage.encoded_len(), None); + + assert_eq!(MyMessage.get_encoded().unwrap(), b"Hello, world"); + } + + #[test] + fn encode_length_prefix_overflow() { + let mut bytes = Vec::new(); + let error = encode_u8_items(&mut bytes, &(), &[1u8; u8::MAX as usize + 1]).unwrap_err(); + assert_matches!(error, CodecError::LengthPrefixOverflow); } } diff --git a/third_party/rust/prio/src/dp.rs b/third_party/rust/prio/src/dp.rs index 506676dbb9..6ed4f2afdf 100644 --- a/third_party/rust/prio/src/dp.rs +++ b/third_party/rust/prio/src/dp.rs @@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize}; /// Errors propagated by methods in this module. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum DpError { /// Tried to use an invalid float as privacy parameter. #[error( diff --git a/third_party/rust/prio/src/dp/distributions.rs b/third_party/rust/prio/src/dp/distributions.rs index ba0270df9c..5fc42f96ec 100644 --- a/third_party/rust/prio/src/dp/distributions.rs +++ b/third_party/rust/prio/src/dp/distributions.rs @@ -292,7 +292,7 @@ mod tests { use super::*; use crate::dp::Rational; - use crate::vdaf::xof::SeedStreamSha3; + use crate::vdaf::xof::SeedStreamTurboShake128; use num_bigint::{BigUint, Sign, ToBigInt, ToBigUint}; use num_traits::{One, Signed, ToPrimitive}; @@ -306,15 +306,15 @@ mod tests { DiscreteGaussian::new(Ratio::<BigUint>::from_integer(BigUint::from(5u8))).unwrap(); // check samples are consistent - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples: Vec<i8> = (0..10) .map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap()) .collect(); let samples1: Vec<i8> = (0..10) .map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap()) .collect(); - assert_eq!(samples, vec![-3, -11, -3, 5, 1, 5, 2, 2, 1, 18]); - assert_eq!(samples1, vec![4, -4, -5, -2, 0, -5, -3, 1, 1, -2]); + assert_eq!(samples, vec![0, -3, -2, 3, 2, -1, -5, 4, -7, -5]); + assert_eq!(samples1, vec![2, 7, -8, -3, 1, -3, -3, 6, -3, -1]); } #[test] @@ -325,7 +325,7 @@ mod tests { // sample from a manually created distribution let sampler1 = DiscreteGaussian::new(Ratio::<BigUint>::from_integer(BigUint::from(4u8))).unwrap(); - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples1: Vec<i8> = (0..10) .map(|_| i8::try_from(sampler1.sample(&mut rng)).unwrap()) .collect(); @@ -337,7 +337,7 @@ mod tests { let sampler2 = zcdp .create_distribution(Ratio::<BigUint>::from_integer(1u8.into())) .unwrap(); - let mut rng2 = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng2 = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples2: Vec<i8> = (0..10) .map(|_| i8::try_from(sampler2.sample(&mut rng2)).unwrap()) .collect(); @@ -485,7 +485,7 @@ mod tests { .unwrap(); // collect that number of samples - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples: Vec<BigInt> = (1..n_samples) .map(|_| { sample_discrete_gaussian(&Ratio::<BigUint>::from_integer(sigma.clone()), &mut rng) @@ -519,7 +519,7 @@ mod tests { #[test] fn empirical_test_gauss() { [100, 2000, 20000].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_discrete_gaussian( &Ratio::<BigUint>::from_integer((*p).to_biguint().unwrap()), @@ -541,7 +541,7 @@ mod tests { #[test] fn empirical_test_bernoulli_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { if sample_bernoulli( &Ratio::<BigUint>::new(BigUint::one(), (*p).into()), @@ -565,7 +565,7 @@ mod tests { #[test] fn empirical_test_geometric_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_geometric_exp( &Ratio::<BigUint>::new(BigUint::one(), (*p).into()), @@ -588,7 +588,7 @@ mod tests { #[test] fn empirical_test_laplace_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_discrete_laplace( &Ratio::<BigUint>::new(BigUint::one(), (*p).into()), diff --git a/third_party/rust/prio/src/fft.rs b/third_party/rust/prio/src/fft.rs index cac59a89ea..612013eb45 100644 --- a/third_party/rust/prio/src/fft.rs +++ b/third_party/rust/prio/src/fft.rs @@ -10,6 +10,7 @@ use std::convert::TryFrom; /// An error returned by an FFT operation. #[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[non_exhaustive] pub enum FftError { /// The output is too small. #[error("output slice is smaller than specified size")] diff --git a/third_party/rust/prio/src/field.rs b/third_party/rust/prio/src/field.rs index fb931de2d3..e6cd5c105d 100644 --- a/third_party/rust/prio/src/field.rs +++ b/third_party/rust/prio/src/field.rs @@ -7,7 +7,6 @@ //! [`FftFriendlyFieldElement`], and have an associated element called the "generator" that //! generates a multiplicative subgroup of order `2^n` for some `n`. -#[cfg(feature = "crypto-dependencies")] use crate::prng::{Prng, PrngError}; use crate::{ codec::{CodecError, Decode, Encode}, @@ -25,8 +24,8 @@ use std::{ io::{Cursor, Read}, marker::PhantomData, ops::{ - Add, AddAssign, BitAnd, ControlFlow, Div, DivAssign, Mul, MulAssign, Neg, Shl, Shr, Sub, - SubAssign, + Add, AddAssign, BitAnd, ControlFlow, Div, DivAssign, Mul, MulAssign, Neg, Range, Shl, Shr, + Sub, SubAssign, }, }; use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq}; @@ -39,6 +38,7 @@ pub use field255::Field255; /// Possible errors from finite field operations. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum FieldError { /// Input sizes do not match. #[error("input sizes do not match")] @@ -46,19 +46,24 @@ pub enum FieldError { /// Returned when decoding a [`FieldElement`] from a too-short byte string. #[error("short read from bytes")] ShortRead, - /// Returned when decoding a [`FieldElement`] from a byte string that encodes an integer greater - /// than or equal to the field modulus. - #[error("read from byte slice exceeds modulus")] + /// Returned when converting an integer to a [`FieldElement`] if the integer is greater than or + /// equal to the field modulus. + #[error("input value exceeds modulus")] ModulusOverflow, /// Error while performing I/O. #[error("I/O error")] Io(#[from] std::io::Error), /// Error encoding or decoding a field. #[error("Codec error")] - Codec(#[from] CodecError), + #[deprecated] + Codec(CodecError), /// Error converting to [`FieldElementWithInteger::Integer`]. #[error("Integer TryFrom error")] IntegerTryFrom, + /// Returned when encoding an integer to "bitvector representation", or decoding from the same, + /// if the number of bits is larger than the bit length of the field's modulus. + #[error("bit vector length exceeds modulus bit length")] + BitVectorTooLong, } /// Objects with this trait represent an element of `GF(p)` for some prime `p`. @@ -100,8 +105,8 @@ pub trait FieldElement: fn inv(&self) -> Self; /// Interprets the next [`Self::ENCODED_SIZE`] bytes from the input slice as an element of the - /// field. The `m` most significant bits are cleared, where `m` is equal to the length of - /// [`Self::Integer`] in bits minus the length of the modulus in bits. + /// field. Any of the most significant bits beyond the bit length of the modulus will be + /// cleared, in order to minimize the amount of rejection sampling needed. /// /// # Errors /// @@ -110,9 +115,9 @@ pub trait FieldElement: /// /// # Warnings /// - /// This function should only be used within [`prng::Prng`] to convert a random byte string into - /// a field element. Use [`Self::decode`] to deserialize field elements. Use - /// [`field::rand`] or [`prng::Prng`] to randomly generate field elements. + /// This function should only be used internally to convert a random byte string into + /// a field element. Use [`Decode::decode`] to deserialize field elements. Use + /// [`random_vector`] to randomly generate field elements. #[doc(hidden)] fn try_from_random(bytes: &[u8]) -> Result<Self, FieldError>; @@ -129,9 +134,10 @@ pub trait FieldElement: /// Ideally we would implement `From<&[F: FieldElement]> for Vec<u8>` or the corresponding /// `Into`, but the orphan rule and the stdlib's blanket implementations of `Into` make this /// impossible. + #[deprecated] fn slice_into_byte_vec(values: &[Self]) -> Vec<u8> { let mut vec = Vec::with_capacity(values.len() * Self::ENCODED_SIZE); - encode_fieldvec(values, &mut vec); + encode_fieldvec(values, &mut vec).unwrap(); vec } @@ -149,18 +155,49 @@ pub trait FieldElement: /// Ideally we would implement `From<&[u8]> for Vec<F: FieldElement>` or the corresponding /// `Into`, but the orphan rule and the stdlib's blanket implementations of `Into` make this /// impossible. + #[deprecated] fn byte_slice_into_vec(bytes: &[u8]) -> Result<Vec<Self>, FieldError> { if bytes.len() % Self::ENCODED_SIZE != 0 { return Err(FieldError::ShortRead); } let mut vec = Vec::with_capacity(bytes.len() / Self::ENCODED_SIZE); for chunk in bytes.chunks_exact(Self::ENCODED_SIZE) { - vec.push(Self::get_decoded(chunk)?); + #[allow(deprecated)] + vec.push(Self::get_decoded(chunk).map_err(FieldError::Codec)?); } Ok(vec) } } +/// An integer type that accompanies a finite field. Integers and field elements may be converted +/// back and forth via the natural map between residue classes modulo 'p' and integers between 0 +/// and p - 1. +pub trait Integer: + Debug + + Eq + + Ord + + BitAnd<Output = Self> + + Div<Output = Self> + + Shl<usize, Output = Self> + + Shr<usize, Output = Self> + + Add<Output = Self> + + Sub<Output = Self> + + TryFrom<usize, Error = Self::TryFromUsizeError> + + TryInto<u64, Error = Self::TryIntoU64Error> +{ + /// The error returned if converting `usize` to this integer type fails. + type TryFromUsizeError: std::error::Error; + + /// The error returned if converting this integer type to a `u64` fails. + type TryIntoU64Error: std::error::Error; + + /// Returns zero. + fn zero() -> Self; + + /// Returns one. + fn one() -> Self; +} + /// Extension trait for field elements that can be converted back and forth to an integer type. /// /// The `Integer` associated type is an integer (primitive or otherwise) that supports various @@ -168,104 +205,95 @@ pub trait FieldElement: /// integer type. This trait also defines methods on field elements, `pow` and `modulus`, that make /// use of the associated integer type. pub trait FieldElementWithInteger: FieldElement + From<Self::Integer> { - /// The error returned if converting `usize` to an `Integer` fails. - type IntegerTryFromError: std::error::Error; - - /// The error returned if converting an `Integer` to a `u64` fails. - type TryIntoU64Error: std::error::Error; - /// The integer representation of a field element. - type Integer: Copy - + Debug - + Eq - + Ord - + BitAnd<Output = Self::Integer> - + Div<Output = Self::Integer> - + Shl<usize, Output = Self::Integer> - + Shr<usize, Output = Self::Integer> - + Add<Output = Self::Integer> - + Sub<Output = Self::Integer> - + From<Self> - + TryFrom<usize, Error = Self::IntegerTryFromError> - + TryInto<u64, Error = Self::TryIntoU64Error>; + type Integer: Integer + From<Self> + Copy; /// Modular exponentation, i.e., `self^exp (mod p)`. fn pow(&self, exp: Self::Integer) -> Self; /// Returns the prime modulus `p`. fn modulus() -> Self::Integer; -} - -/// Methods common to all `FieldElementWithInteger` implementations that are private to the crate. -pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger { - /// Encode `input` as bitvector of elements of `Self`. Output is written into the `output` slice. - /// If `output.len()` is smaller than the number of bits required to respresent `input`, - /// an error is returned. - /// - /// # Arguments + /// Encode the integer `input` as a sequence of bits in two's complement representation, least + /// significant bit first, and then map each bit to a field element. /// - /// * `input` - The field element to encode - /// * `output` - The slice to write the encoded bits into. Least signicant bit comes first - fn fill_with_bitvector_representation( - input: &Self::Integer, - output: &mut [Self], - ) -> Result<(), FieldError> { - // Create a mutable copy of `input`. In each iteration of the following loop we take the - // least significant bit, and shift input to the right by one bit. - let mut i = *input; - - let one = Self::Integer::from(Self::one()); - for bit in output.iter_mut() { - let w = Self::from(i & one); - *bit = w; - i = i >> 1; + /// Returns an error if `input` cannot be represented with `bits` many bits, or if `bits` + /// is larger than the bit width of the field's modulus. + fn encode_as_bitvector( + input: Self::Integer, + bits: usize, + ) -> Result<BitvectorRepresentationIter<Self>, FieldError> { + // Check if `bits` is too large for this field. + if !Self::valid_integer_bitlength(bits) { + return Err(FieldError::BitVectorTooLong); } - // If `i` is still not zero, this means that it cannot be encoded by `bits` bits. - if i != Self::Integer::from(Self::zero()) { + // Check if the input value can be represented in the requested number of bits by shifting + // it. The above check on `bits` ensures this shift won't panic due to the shift width + // being too large. + if input >> bits != Self::Integer::zero() { return Err(FieldError::InputSizeMismatch); } - Ok(()) + Ok(BitvectorRepresentationIter { + inner: 0..bits, + input, + }) } - /// Encode `input` as `bits`-bit vector of elements of `Self` if it's small enough - /// to be represented with that many bits. - /// - /// # Arguments + /// Inverts the encoding done by [`Self::encode_as_bitvector`], and returns a single field + /// element. /// - /// * `input` - The field element to encode - /// * `bits` - The number of bits to use for the encoding - fn encode_into_bitvector_representation( - input: &Self::Integer, - bits: usize, - ) -> Result<Vec<Self>, FieldError> { - let mut result = vec![Self::zero(); bits]; - Self::fill_with_bitvector_representation(input, &mut result)?; - Ok(result) - } - - /// Decode the bitvector-represented value `input` into a simple representation as a single - /// field element. + /// This performs an inner product between the input vector of field elements and successive + /// powers of two (starting with 2^0 = 1). If the input came from [`Self::encode_as_bitvector`], + /// then the result will be equal to the originally encoded integer, projected into the field. /// - /// # Errors + /// Note that this decoding operation is linear, so it can be applied to secret shares of an + /// encoded integer, and if the results are summed up, it will be equal to the encoded integer. /// - /// This function errors if `2^input.len() - 1` does not fit into the field `Self`. - fn decode_from_bitvector_representation(input: &[Self]) -> Result<Self, FieldError> { - let fi_one = Self::Integer::from(Self::one()); - + /// Returns an error if the length of the input is larger than the bit width of the field's + /// modulus. + fn decode_bitvector(input: &[Self]) -> Result<Self, FieldError> { if !Self::valid_integer_bitlength(input.len()) { - return Err(FieldError::ModulusOverflow); + return Err(FieldError::BitVectorTooLong); } let mut decoded = Self::zero(); - for (l, bit) in input.iter().enumerate() { - let w = fi_one << l; - decoded += Self::from(w) * *bit; + let one = Self::one(); + let two = one + one; + let mut power_of_two = one; + for value in input.iter() { + decoded += *value * power_of_two; + power_of_two *= two; } Ok(decoded) } +} + +/// This iterator returns a sequence of field elements that are equal to zero or one, representing +/// some integer in two's complement form. See [`FieldElementWithInteger::encode_as_bitvector`]. +// Note that this is implemented with a separate struct, instead of using the map combinator, +// because return_position_impl_trait_in_trait is not yet stable. +#[derive(Debug, Clone)] +pub struct BitvectorRepresentationIter<F: FieldElementWithInteger> { + inner: Range<usize>, + input: F::Integer, +} + +impl<F> Iterator for BitvectorRepresentationIter<F> +where + F: FieldElementWithInteger, +{ + type Item = F; + + #[inline] + fn next(&mut self) -> Option<Self::Item> { + let bit_offset = self.inner.next()?; + Some(F::from((self.input >> bit_offset) & F::Integer::one())) + } +} +/// Methods common to all `FieldElementWithInteger` implementations that are private to the crate. +pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger { /// Interpret `i` as [`Self::Integer`] if it's representable in that type and smaller than the /// field modulus. fn valid_integer_try_from<N>(i: N) -> Result<Self::Integer, FieldError> @@ -285,7 +313,7 @@ pub(crate) trait FieldElementWithIntegerExt: FieldElementWithInteger { if bits >= 8 * Self::ENCODED_SIZE { return false; } - if Self::modulus() >> bits != Self::Integer::from(Self::zero()) { + if Self::modulus() >> bits != Self::Integer::zero() { return true; } false @@ -382,7 +410,7 @@ macro_rules! make_field { /// /// As an invariant, this integer representing the field element in the Montgomery domain /// must be less than the field modulus, `p`. - #[derive(Clone, Copy, PartialOrd, Ord, Default)] + #[derive(Clone, Copy, Default)] pub struct $elem(u128); impl $elem { @@ -640,9 +668,10 @@ macro_rules! make_field { } impl Encode for $elem { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { let slice = <[u8; $elem::ENCODED_SIZE]>::from(*self); bytes.extend_from_slice(&slice); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -683,8 +712,6 @@ macro_rules! make_field { impl FieldElementWithInteger for $elem { type Integer = $int; - type IntegerTryFromError = <Self::Integer as TryFrom<usize>>::Error; - type TryIntoU64Error = <Self::Integer as TryInto<u64>>::Error; fn pow(&self, exp: Self::Integer) -> Self { // FieldParameters::pow() relies on mul(), and will always return a value less @@ -717,6 +744,45 @@ macro_rules! make_field { }; } +impl Integer for u32 { + type TryFromUsizeError = <Self as TryFrom<usize>>::Error; + type TryIntoU64Error = <Self as TryInto<u64>>::Error; + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } +} + +impl Integer for u64 { + type TryFromUsizeError = <Self as TryFrom<usize>>::Error; + type TryIntoU64Error = <Self as TryInto<u64>>::Error; + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } +} + +impl Integer for u128 { + type TryFromUsizeError = <Self as TryFrom<usize>>::Error; + type TryIntoU64Error = <Self as TryInto<u64>>::Error; + + fn zero() -> Self { + 0 + } + + fn one() -> Self { + 1 + } +} + make_field!( /// Same as Field32, but encoded in little endian for compatibility with Prio v2. FieldPrio2, @@ -761,7 +827,7 @@ pub(crate) fn merge_vector<F: FieldElement>( } /// Outputs an additive secret sharing of the input. -#[cfg(all(feature = "crypto-dependencies", test))] +#[cfg(test)] pub(crate) fn split_vector<F: FieldElement>( inp: &[F], num_shares: usize, @@ -785,18 +851,20 @@ pub(crate) fn split_vector<F: FieldElement>( } /// Generate a vector of uniformly distributed random field elements. -#[cfg(feature = "crypto-dependencies")] -#[cfg_attr(docsrs, doc(cfg(feature = "crypto-dependencies")))] pub fn random_vector<F: FieldElement>(len: usize) -> Result<Vec<F>, PrngError> { Ok(Prng::new()?.take(len).collect()) } /// `encode_fieldvec` serializes a type that is equivalent to a vector of field elements. #[inline(always)] -pub(crate) fn encode_fieldvec<F: FieldElement, T: AsRef<[F]>>(val: T, bytes: &mut Vec<u8>) { +pub(crate) fn encode_fieldvec<F: FieldElement, T: AsRef<[F]>>( + val: T, + bytes: &mut Vec<u8>, +) -> Result<(), CodecError> { for elem in val.as_ref() { - elem.encode(bytes); + elem.encode(bytes)?; } + Ok(()) } /// `decode_fieldvec` deserializes some number of field elements from a cursor, and advances the @@ -822,16 +890,14 @@ pub(crate) fn decode_fieldvec<F: FieldElement>( #[cfg(test)] pub(crate) mod test_utils { - use super::{FieldElement, FieldElementWithInteger}; + use super::{FieldElement, FieldElementWithInteger, Integer}; use crate::{codec::CodecError, field::FieldError, prng::Prng}; use assert_matches::assert_matches; use std::{ collections::hash_map::DefaultHasher, - convert::{TryFrom, TryInto}, - fmt::Debug, + convert::TryFrom, hash::{Hash, Hasher}, io::Cursor, - ops::{Add, BitAnd, Div, Shl, Shr, Sub}, }; /// A test-only copy of `FieldElementWithInteger`. @@ -842,42 +908,30 @@ pub(crate) mod test_utils { /// requires the `Integer` associated type satisfy `Clone`, not `Copy`, so that it may be used /// with arbitrary precision integer implementations. pub(crate) trait TestFieldElementWithInteger: - FieldElement + From<Self::Integer> + FieldElement + From<Self::TestInteger> { type IntegerTryFromError: std::error::Error; type TryIntoU64Error: std::error::Error; - type Integer: Clone - + Debug - + Eq - + Ord - + BitAnd<Output = Self::Integer> - + Div<Output = Self::Integer> - + Shl<usize, Output = Self::Integer> - + Shr<usize, Output = Self::Integer> - + Add<Output = Self::Integer> - + Sub<Output = Self::Integer> - + From<Self> - + TryFrom<usize, Error = Self::IntegerTryFromError> - + TryInto<u64, Error = Self::TryIntoU64Error>; - - fn pow(&self, exp: Self::Integer) -> Self; - - fn modulus() -> Self::Integer; + type TestInteger: Integer + From<Self> + Clone; + + fn pow(&self, exp: Self::TestInteger) -> Self; + + fn modulus() -> Self::TestInteger; } impl<F> TestFieldElementWithInteger for F where F: FieldElementWithInteger, { - type IntegerTryFromError = <F as FieldElementWithInteger>::IntegerTryFromError; - type TryIntoU64Error = <F as FieldElementWithInteger>::TryIntoU64Error; - type Integer = <F as FieldElementWithInteger>::Integer; + type IntegerTryFromError = <F::Integer as Integer>::TryFromUsizeError; + type TryIntoU64Error = <F::Integer as Integer>::TryIntoU64Error; + type TestInteger = F::Integer; - fn pow(&self, exp: Self::Integer) -> Self { + fn pow(&self, exp: Self::TestInteger) -> Self { <F as FieldElementWithInteger>::pow(self, exp) } - fn modulus() -> Self::Integer { + fn modulus() -> Self::TestInteger { <F as FieldElementWithInteger>::modulus() } } @@ -885,11 +939,11 @@ pub(crate) mod test_utils { pub(crate) fn field_element_test_common<F: TestFieldElementWithInteger>() { let mut prng: Prng<F, _> = Prng::new().unwrap(); let int_modulus = F::modulus(); - let int_one = F::Integer::try_from(1).unwrap(); + let int_one = F::TestInteger::try_from(1).unwrap(); let zero = F::zero(); let one = F::one(); - let two = F::from(F::Integer::try_from(2).unwrap()); - let four = F::from(F::Integer::try_from(4).unwrap()); + let two = F::from(F::TestInteger::try_from(2).unwrap()); + let four = F::from(F::TestInteger::try_from(4).unwrap()); // add assert_eq!(F::from(int_modulus.clone() - int_one.clone()) + one, zero); @@ -943,10 +997,22 @@ pub(crate) mod test_utils { assert_eq!(a, c); // integer conversion - assert_eq!(F::Integer::from(zero), F::Integer::try_from(0).unwrap()); - assert_eq!(F::Integer::from(one), F::Integer::try_from(1).unwrap()); - assert_eq!(F::Integer::from(two), F::Integer::try_from(2).unwrap()); - assert_eq!(F::Integer::from(four), F::Integer::try_from(4).unwrap()); + assert_eq!( + F::TestInteger::from(zero), + F::TestInteger::try_from(0).unwrap() + ); + assert_eq!( + F::TestInteger::from(one), + F::TestInteger::try_from(1).unwrap() + ); + assert_eq!( + F::TestInteger::from(two), + F::TestInteger::try_from(2).unwrap() + ); + assert_eq!( + F::TestInteger::from(four), + F::TestInteger::try_from(4).unwrap() + ); // serialization let test_inputs = vec![ @@ -957,7 +1023,7 @@ pub(crate) mod test_utils { ]; for want in test_inputs.iter() { let mut bytes = vec![]; - want.encode(&mut bytes); + want.encode(&mut bytes).unwrap(); assert_eq!(bytes.len(), F::ENCODED_SIZE); assert_eq!(want.encoded_len().unwrap(), F::ENCODED_SIZE); @@ -966,9 +1032,12 @@ pub(crate) mod test_utils { assert_eq!(got, *want); } - let serialized_vec = F::slice_into_byte_vec(&test_inputs); - let deserialized = F::byte_slice_into_vec(&serialized_vec).unwrap(); - assert_eq!(deserialized, test_inputs); + #[allow(deprecated)] + { + let serialized_vec = F::slice_into_byte_vec(&test_inputs); + let deserialized = F::byte_slice_into_vec(&serialized_vec).unwrap(); + assert_eq!(deserialized, test_inputs); + } let test_input = prng.get(); let json = serde_json::to_string(&test_input).unwrap(); @@ -981,13 +1050,16 @@ pub(crate) mod test_utils { element.as_u64().unwrap(); } - let err = F::byte_slice_into_vec(&[0]).unwrap_err(); - assert_matches!(err, FieldError::ShortRead); + #[allow(deprecated)] + { + let err = F::byte_slice_into_vec(&[0]).unwrap_err(); + assert_matches!(err, FieldError::ShortRead); - let err = F::byte_slice_into_vec(&vec![0xffu8; F::ENCODED_SIZE]).unwrap_err(); - assert_matches!(err, FieldError::Codec(CodecError::Other(err)) => { - assert_matches!(err.downcast_ref::<FieldError>(), Some(FieldError::ModulusOverflow)); - }); + let err = F::byte_slice_into_vec(&vec![0xffu8; F::ENCODED_SIZE]).unwrap_err(); + assert_matches!(err, FieldError::Codec(CodecError::Other(err)) => { + assert_matches!(err.downcast_ref::<FieldError>(), Some(FieldError::ModulusOverflow)); + }); + } let insufficient = vec![0u8; F::ENCODED_SIZE - 1]; let err = F::try_from(insufficient.as_ref()).unwrap_err(); @@ -1004,7 +1076,7 @@ pub(crate) mod test_utils { // various products that should be equal have the same hash. Three is chosen as a generator // here because it happens to generate fairly large subgroups of (Z/pZ)* for all four // primes. - let three = F::from(F::Integer::try_from(3).unwrap()); + let three = F::from(F::TestInteger::try_from(3).unwrap()); let mut powers_of_three = Vec::with_capacity(500); let mut power = one; for _ in 0..500 { @@ -1169,22 +1241,19 @@ mod tests { fn test_encode_into_bitvector() { let zero = Field128::zero(); let one = Field128::one(); - let zero_enc = Field128::encode_into_bitvector_representation(&0, 4).unwrap(); - let one_enc = Field128::encode_into_bitvector_representation(&1, 4).unwrap(); - let fifteen_enc = Field128::encode_into_bitvector_representation(&15, 4).unwrap(); + let zero_enc = Field128::encode_as_bitvector(0, 4) + .unwrap() + .collect::<Vec<_>>(); + let one_enc = Field128::encode_as_bitvector(1, 4) + .unwrap() + .collect::<Vec<_>>(); + let fifteen_enc = Field128::encode_as_bitvector(15, 4) + .unwrap() + .collect::<Vec<_>>(); assert_eq!(zero_enc, [zero; 4]); assert_eq!(one_enc, [one, zero, zero, zero]); assert_eq!(fifteen_enc, [one; 4]); - Field128::encode_into_bitvector_representation(&16, 4).unwrap_err(); - } - - #[test] - fn test_fill_bitvector() { - let zero = Field128::zero(); - let one = Field128::one(); - let mut output: Vec<Field128> = vec![zero; 6]; - Field128::fill_with_bitvector_representation(&9, &mut output[1..5]).unwrap(); - assert_eq!(output, [zero, one, zero, zero, one, zero]); - Field128::fill_with_bitvector_representation(&16, &mut output[1..5]).unwrap_err(); + Field128::encode_as_bitvector(16, 4).unwrap_err(); + Field128::encode_as_bitvector(0, 129).unwrap_err(); } } diff --git a/third_party/rust/prio/src/field/field255.rs b/third_party/rust/prio/src/field/field255.rs index fd06a6334a..15a53f8b09 100644 --- a/third_party/rust/prio/src/field/field255.rs +++ b/third_party/rust/prio/src/field/field255.rs @@ -271,8 +271,9 @@ impl<'de> Deserialize<'de> for Field255 { } impl Encode for Field255 { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.extend_from_slice(&<[u8; Self::ENCODED_SIZE]>::from(*self)); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -341,7 +342,7 @@ mod tests { codec::Encode, field::{ test_utils::{field_element_test_common, TestFieldElementWithInteger}, - FieldElement, FieldError, + FieldElement, FieldError, Integer, }, }; use assert_matches::assert_matches; @@ -375,16 +376,30 @@ mod tests { } } + impl Integer for BigUint { + type TryFromUsizeError = <Self as TryFrom<usize>>::Error; + + type TryIntoU64Error = <Self as TryInto<u64>>::Error; + + fn zero() -> Self { + Self::new(Vec::new()) + } + + fn one() -> Self { + Self::new(Vec::from([1])) + } + } + impl TestFieldElementWithInteger for Field255 { - type Integer = BigUint; - type IntegerTryFromError = <Self::Integer as TryFrom<usize>>::Error; - type TryIntoU64Error = <Self::Integer as TryInto<u64>>::Error; + type TestInteger = BigUint; + type IntegerTryFromError = <Self::TestInteger as TryFrom<usize>>::Error; + type TryIntoU64Error = <Self::TestInteger as TryInto<u64>>::Error; - fn pow(&self, _exp: Self::Integer) -> Self { + fn pow(&self, _exp: Self::TestInteger) -> Self { unimplemented!("Field255::pow() is not implemented because it's not needed yet") } - fn modulus() -> Self::Integer { + fn modulus() -> Self::TestInteger { MODULUS.clone() } } @@ -415,7 +430,7 @@ mod tests { #[test] fn encode_endianness() { let mut one_encoded = Vec::new(); - Field255::one().encode(&mut one_encoded); + Field255::one().encode(&mut one_encoded).unwrap(); assert_eq!( one_encoded, [ diff --git a/third_party/rust/prio/src/flp.rs b/third_party/rust/prio/src/flp.rs index 1912ebab14..5fd956155a 100644 --- a/third_party/rust/prio/src/flp.rs +++ b/third_party/rust/prio/src/flp.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 //! Implementation of the generic Fully Linear Proof (FLP) system specified in -//! [[draft-irtf-cfrg-vdaf-07]]. This is the main building block of [`Prio3`](crate::vdaf::prio3). +//! [[draft-irtf-cfrg-vdaf-08]]. This is the main building block of [`Prio3`](crate::vdaf::prio3). //! //! The FLP is derived for any implementation of the [`Type`] trait. Such an implementation //! specifies a validity circuit that defines the set of valid measurements, as well as the finite @@ -24,7 +24,7 @@ //! //! // The prover chooses a measurement. //! let count = Count::new(); -//! let input: Vec<Field64> = count.encode_measurement(&0).unwrap(); +//! let input: Vec<Field64> = count.encode_measurement(&false).unwrap(); //! //! // The prover and verifier agree on "joint randomness" used to generate and //! // check the proof. The application needs to ensure that the prover @@ -44,7 +44,7 @@ //! assert!(count.decide(&verifier).unwrap()); //! ``` //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[cfg(feature = "experimental")] use crate::dp::DifferentialPrivacyStrategy; @@ -61,6 +61,7 @@ pub mod types; /// Errors propagated by methods in this module. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum FlpError { /// Calling [`Type::prove`] returned an error. #[error("prove error: {0}")] @@ -110,20 +111,12 @@ pub enum FlpError { /// An error happened during noising. #[error("differential privacy error: {0}")] DifferentialPrivacy(#[from] crate::dp::DpError), - - /// Unit test error. - #[cfg(test)] - #[error("test failed: {0}")] - Test(String), } /// A type. Implementations of this trait specify how a particular kind of measurement is encoded /// as a vector of field elements and how validity of the encoded measurement is determined. /// Validity is determined via an arithmetic circuit evaluated over the encoded measurement. pub trait Type: Sized + Eq + Clone + Debug { - /// The Prio3 VDAF identifier corresponding to this type. - const ID: u32; - /// The type of raw measurement to be encoded. type Measurement: Clone + Debug; @@ -178,7 +171,7 @@ pub trait Type: Sized + Eq + Clone + Debug { /// use prio::field::{random_vector, FieldElement, Field64}; /// /// let count = Count::new(); - /// let input: Vec<Field64> = count.encode_measurement(&1).unwrap(); + /// let input: Vec<Field64> = count.encode_measurement(&true).unwrap(); /// let joint_rand = random_vector(count.joint_rand_len()).unwrap(); /// let v = count.valid(&mut count.gadget(), &input, &joint_rand, 1).unwrap(); /// assert_eq!(v, Field64::zero()); @@ -552,6 +545,7 @@ pub trait Type: Sized + Eq + Clone + Debug { /// A type which supports adding noise to aggregate shares for Server Differential Privacy. #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub trait TypeWithNoise<S>: Type where S: DifferentialPrivacyStrategy, @@ -754,6 +748,227 @@ pub(crate) fn gadget_poly_len(gadget_degree: usize, wire_poly_len: usize) -> usi gadget_degree * (wire_poly_len - 1) + 1 } +/// Utilities for testing FLPs. +#[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub mod test_utils { + use super::*; + use crate::field::{random_vector, FieldElement, FieldElementWithInteger}; + + /// Various tests for an FLP. + #[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] + pub struct FlpTest<'a, T: Type> { + /// The FLP. + pub flp: &'a T, + + /// Optional test name. + pub name: Option<&'a str>, + + /// The input to use for the tests. + pub input: &'a [T::Field], + + /// If set, the expected result of truncating the input. + pub expected_output: Option<&'a [T::Field]>, + + /// Whether the input is expected to be valid. + pub expect_valid: bool, + } + + impl<T: Type> FlpTest<'_, T> { + /// Construct a test and run it. Expect the input to be valid and compare the truncated + /// output to the provided value. + pub fn expect_valid<const SHARES: usize>( + flp: &T, + input: &[T::Field], + expected_output: &[T::Field], + ) { + FlpTest { + flp, + name: None, + input, + expected_output: Some(expected_output), + expect_valid: true, + } + .run::<SHARES>() + } + + /// Construct a test and run it. Expect the input to be invalid. + pub fn expect_invalid<const SHARES: usize>(flp: &T, input: &[T::Field]) { + FlpTest { + flp, + name: None, + input, + expect_valid: false, + expected_output: None, + } + .run::<SHARES>() + } + + /// Construct a test and run it. Expect the input to be valid. + pub fn expect_valid_no_output<const SHARES: usize>(flp: &T, input: &[T::Field]) { + FlpTest { + flp, + name: None, + input, + expect_valid: true, + expected_output: None, + } + .run::<SHARES>() + } + + /// Run the tests. + pub fn run<const SHARES: usize>(&self) { + let name = self.name.unwrap_or("unnamed test"); + + assert_eq!( + self.input.len(), + self.flp.input_len(), + "{name}: unexpected input length" + ); + + let mut gadgets = self.flp.gadget(); + let joint_rand = random_vector(self.flp.joint_rand_len()).unwrap(); + let prove_rand = random_vector(self.flp.prove_rand_len()).unwrap(); + let query_rand = random_vector(self.flp.query_rand_len()).unwrap(); + assert_eq!( + self.flp.query_rand_len(), + gadgets.len(), + "{name}: unexpected number of gadgets" + ); + assert_eq!( + self.flp.joint_rand_len(), + joint_rand.len(), + "{name}: unexpected joint rand length" + ); + assert_eq!( + self.flp.prove_rand_len(), + prove_rand.len(), + "{name}: unexpected prove rand length", + ); + assert_eq!( + self.flp.query_rand_len(), + query_rand.len(), + "{name}: unexpected query rand length", + ); + + // Run the validity circuit. + let v = self + .flp + .valid(&mut gadgets, self.input, &joint_rand, 1) + .unwrap(); + assert_eq!( + v == T::Field::zero(), + self.expect_valid, + "{name}: unexpected output of valid() returned {v}", + ); + + // Generate the proof. + let proof = self + .flp + .prove(self.input, &prove_rand, &joint_rand) + .unwrap(); + assert_eq!( + proof.len(), + self.flp.proof_len(), + "{name}: unexpected proof length" + ); + + // Query the proof. + let verifier = self + .flp + .query(self.input, &proof, &query_rand, &joint_rand, 1) + .unwrap(); + assert_eq!( + verifier.len(), + self.flp.verifier_len(), + "{name}: unexpected verifier length" + ); + + // Decide if the input is valid. + let res = self.flp.decide(&verifier).unwrap(); + assert_eq!(res, self.expect_valid, "{name}: unexpected decision"); + + // Run distributed FLP. + let input_shares = split_vector::<_, SHARES>(self.input); + let proof_shares = split_vector::<_, SHARES>(&proof); + let verifier: Vec<T::Field> = (0..SHARES) + .map(|i| { + self.flp + .query( + &input_shares[i], + &proof_shares[i], + &query_rand, + &joint_rand, + SHARES, + ) + .unwrap() + }) + .reduce(|mut left, right| { + for (x, y) in left.iter_mut().zip(right.iter()) { + *x += *y; + } + left + }) + .unwrap(); + + let res = self.flp.decide(&verifier).unwrap(); + assert_eq!( + res, self.expect_valid, + "{name}: unexpected distributed decision" + ); + + // Try verifying various proof mutants. + for i in 0..std::cmp::min(proof.len(), 10) { + let mut mutated_proof = proof.clone(); + mutated_proof[i] *= T::Field::from( + <T::Field as FieldElementWithInteger>::Integer::try_from(23).unwrap(), + ); + let verifier = self + .flp + .query(self.input, &mutated_proof, &query_rand, &joint_rand, 1) + .unwrap(); + assert!( + !self.flp.decide(&verifier).unwrap(), + "{name}: proof mutant {} deemed valid", + i + ); + } + + // Try truncating the input. + if let Some(ref expected_output) = self.expected_output { + let output = self.flp.truncate(self.input.to_vec()).unwrap(); + + assert_eq!( + output.len(), + self.flp.output_len(), + "{name}: unexpected output length of truncate()" + ); + + assert_eq!( + &output, expected_output, + "{name}: unexpected output of truncate()" + ); + } + } + } + + fn split_vector<F: FieldElement, const SHARES: usize>(inp: &[F]) -> [Vec<F>; SHARES] { + let mut outp = Vec::with_capacity(SHARES); + outp.push(inp.to_vec()); + + for _ in 1..SHARES { + let share: Vec<F> = + random_vector(inp.len()).expect("failed to generate a random vector"); + for (x, y) in outp[0].iter_mut().zip(&share) { + *x -= *y; + } + outp.push(share); + } + + outp.try_into().unwrap() + } +} + #[cfg(test)] mod tests { use super::*; @@ -825,7 +1040,6 @@ mod tests { } impl<F: FftFriendlyFieldElement> Type for TestType<F> { - const ID: u32 = 0xFFFF0000; type Measurement = F::Integer; type AggregateResult = F::Integer; type Field = F; @@ -960,7 +1174,6 @@ mod tests { } impl<F: FftFriendlyFieldElement> Type for Issue254Type<F> { - const ID: u32 = 0xFFFF0000; type Measurement = F::Integer; type AggregateResult = F::Integer; type Field = F; diff --git a/third_party/rust/prio/src/flp/types.rs b/third_party/rust/prio/src/flp/types.rs index 18c290355c..bca88a36cd 100644 --- a/third_party/rust/prio/src/flp/types.rs +++ b/third_party/rust/prio/src/flp/types.rs @@ -9,6 +9,7 @@ use crate::polynomial::poly_range_check; use std::convert::TryInto; use std::fmt::{self, Debug}; use std::marker::PhantomData; +use subtle::Choice; /// The counter data type. Each measurement is `0` or `1` and the aggregate result is the sum of the measurements (i.e., the total number of `1s`). #[derive(Clone, PartialEq, Eq)] pub struct Count<F> { @@ -37,18 +38,16 @@ impl<F: FftFriendlyFieldElement> Default for Count<F> { } impl<F: FftFriendlyFieldElement> Type for Count<F> { - const ID: u32 = 0x00000000; - type Measurement = F::Integer; + type Measurement = bool; type AggregateResult = F::Integer; type Field = F; - fn encode_measurement(&self, value: &F::Integer) -> Result<Vec<F>, FlpError> { - let max = F::valid_integer_try_from(1)?; - if *value > max { - return Err(FlpError::Encode("Count value must be 0 or 1".to_string())); - } - - Ok(vec![F::from(*value)]) + fn encode_measurement(&self, value: &bool) -> Result<Vec<F>, FlpError> { + Ok(vec![F::conditional_select( + &F::zero(), + &F::one(), + Choice::from(u8::from(*value)), + )]) } fn decode_result(&self, data: &[F], _num_measurements: usize) -> Result<F::Integer, FlpError> { @@ -140,13 +139,12 @@ impl<F: FftFriendlyFieldElement> Sum<F> { } impl<F: FftFriendlyFieldElement> Type for Sum<F> { - const ID: u32 = 0x00000001; type Measurement = F::Integer; type AggregateResult = F::Integer; type Field = F; fn encode_measurement(&self, summand: &F::Integer) -> Result<Vec<F>, FlpError> { - let v = F::encode_into_bitvector_representation(summand, self.bits)?; + let v = F::encode_as_bitvector(*summand, self.bits)?.collect(); Ok(v) } @@ -174,7 +172,7 @@ impl<F: FftFriendlyFieldElement> Type for Sum<F> { fn truncate(&self, input: Vec<F>) -> Result<Vec<F>, FlpError> { self.truncate_call_check(&input)?; - let res = F::decode_from_bitvector_representation(&input)?; + let res = F::decode_bitvector(&input)?; Ok(vec![res]) } @@ -239,13 +237,12 @@ impl<F: FftFriendlyFieldElement> Average<F> { } impl<F: FftFriendlyFieldElement> Type for Average<F> { - const ID: u32 = 0xFFFF0000; type Measurement = F::Integer; type AggregateResult = f64; type Field = F; fn encode_measurement(&self, summand: &F::Integer) -> Result<Vec<F>, FlpError> { - let v = F::encode_into_bitvector_representation(summand, self.bits)?; + let v = F::encode_as_bitvector(*summand, self.bits)?.collect(); Ok(v) } @@ -279,7 +276,7 @@ impl<F: FftFriendlyFieldElement> Type for Average<F> { fn truncate(&self, input: Vec<F>) -> Result<Vec<F>, FlpError> { self.truncate_call_check(&input)?; - let res = F::decode_from_bitvector_representation(&input)?; + let res = F::decode_bitvector(&input)?; Ok(vec![res]) } @@ -380,7 +377,6 @@ where F: FftFriendlyFieldElement, S: ParallelSumGadget<F, Mul<F>> + Eq + 'static, { - const ID: u32 = 0x00000003; type Measurement = usize; type AggregateResult = Vec<F::Integer>; type Field = F; @@ -574,7 +570,6 @@ where F: FftFriendlyFieldElement, S: ParallelSumGadget<F, Mul<F>> + Eq + 'static, { - const ID: u32 = 0x00000002; type Measurement = Vec<F::Integer>; type AggregateResult = Vec<F::Integer>; type Field = F; @@ -588,18 +583,15 @@ where ))); } - let mut flattened = vec![F::zero(); self.flattened_len]; - for (summand, chunk) in measurement - .iter() - .zip(flattened.chunks_exact_mut(self.bits)) - { + let mut flattened = Vec::with_capacity(self.flattened_len); + for summand in measurement.iter() { if summand > &self.max { return Err(FlpError::Encode(format!( "summand exceeds maximum of 2^{}-1", self.bits ))); } - F::fill_with_bitvector_representation(summand, chunk)?; + flattened.extend(F::encode_as_bitvector(*summand, self.bits)?); } Ok(flattened) @@ -642,7 +634,7 @@ where self.truncate_call_check(&input)?; let mut unflattened = Vec::with_capacity(self.len); for chunk in input.chunks(self.bits) { - unflattened.push(F::decode_from_bitvector_representation(chunk)?); + unflattened.push(F::decode_bitvector(chunk)?); } Ok(unflattened) } @@ -783,7 +775,7 @@ mod tests { use crate::flp::gadgets::ParallelSum; #[cfg(feature = "multithreaded")] use crate::flp::gadgets::ParallelSumMultithreaded; - use crate::flp::types::test_utils::{flp_validity_test, ValidityTestCase}; + use crate::flp::test_utils::FlpTest; use std::cmp; #[test] @@ -797,7 +789,7 @@ mod tests { count .decode_result( &count - .truncate(count.encode_measurement(&1).unwrap()) + .truncate(count.encode_measurement(&true).unwrap()) .unwrap(), 1 ) @@ -806,39 +798,11 @@ mod tests { ); // Test FLP on valid input. - flp_validity_test( - &count, - &count.encode_measurement(&1).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![one]), - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &count, - &count.encode_measurement(&0).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![zero]), - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_valid::<3>(&count, &count.encode_measurement(&true).unwrap(), &[one]); + FlpTest::expect_valid::<3>(&count, &count.encode_measurement(&false).unwrap(), &[zero]); // Test FLP on invalid input. - flp_validity_test( - &count, - &[TestField::from(1337)], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_invalid::<3>(&count, &[TestField::from(1337)]); // Try running the validity circuit on an input that's too short. count.valid(&mut count.gadget(), &[], &[], 1).unwrap_err(); @@ -865,72 +829,22 @@ mod tests { ); // Test FLP on valid input. - flp_validity_test( + FlpTest::expect_valid::<3>( &sum, &sum.encode_measurement(&1337).unwrap(), - &ValidityTestCase { - expect_valid: true, - expected_output: Some(vec![TestField::from(1337)]), - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &Sum::new(0).unwrap(), - &[], - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![zero]), - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &Sum::new(2).unwrap(), - &[one, zero], - &ValidityTestCase { - expect_valid: true, - expected_output: Some(vec![one]), - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( + &[TestField::from(1337)], + ); + FlpTest::expect_valid::<3>(&Sum::new(0).unwrap(), &[], &[zero]); + FlpTest::expect_valid::<3>(&Sum::new(2).unwrap(), &[one, zero], &[one]); + FlpTest::expect_valid::<3>( &Sum::new(9).unwrap(), &[one, zero, one, one, zero, one, one, one, zero], - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![TestField::from(237)]), - num_shares: 3, - }, - ) - .unwrap(); + &[TestField::from(237)], + ); // Test FLP on invalid input. - flp_validity_test( - &Sum::new(3).unwrap(), - &[one, nine, zero], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &Sum::new(5).unwrap(), - &[zero, zero, zero, zero, nine], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_invalid::<3>(&Sum::new(3).unwrap(), &[one, nine, zero]); + FlpTest::expect_invalid::<3>(&Sum::new(5).unwrap(), &[zero, zero, zero, zero, nine]); } #[test] @@ -1000,83 +914,29 @@ mod tests { ); // Test valid inputs. - flp_validity_test( + FlpTest::expect_valid::<3>( &hist, &hist.encode_measurement(&0).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![one, zero, zero]), - num_shares: 3, - }, - ) - .unwrap(); + &[one, zero, zero], + ); - flp_validity_test( + FlpTest::expect_valid::<3>( &hist, &hist.encode_measurement(&1).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![zero, one, zero]), - num_shares: 3, - }, - ) - .unwrap(); + &[zero, one, zero], + ); - flp_validity_test( + FlpTest::expect_valid::<3>( &hist, &hist.encode_measurement(&2).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![zero, zero, one]), - num_shares: 3, - }, - ) - .unwrap(); + &[zero, zero, one], + ); // Test invalid inputs. - flp_validity_test( - &hist, - &[zero, zero, nine], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &hist, - &[zero, one, one], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &hist, - &[one, one, one], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); - - flp_validity_test( - &hist, - &[zero, zero, zero], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_invalid::<3>(&hist, &[zero, zero, nine]); + FlpTest::expect_invalid::<3>(&hist, &[zero, one, one]); + FlpTest::expect_invalid::<3>(&hist, &[one, one, one]); + FlpTest::expect_invalid::<3>(&hist, &[zero, zero, zero]); } #[test] @@ -1104,72 +964,38 @@ mod tests { for len in 1..10 { let chunk_length = cmp::max((len as f64).sqrt() as usize, 1); let sum_vec = f(1, len, chunk_length).unwrap(); - flp_validity_test( + FlpTest::expect_valid_no_output::<3>( &sum_vec, &sum_vec.encode_measurement(&vec![1; len]).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![one; len]), - num_shares: 3, - }, - ) - .unwrap(); + ); } let len = 100; let sum_vec = f(1, len, 10).unwrap(); - flp_validity_test( + FlpTest::expect_valid::<3>( &sum_vec, &sum_vec.encode_measurement(&vec![1; len]).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![one; len]), - num_shares: 3, - }, - ) - .unwrap(); + &vec![one; len], + ); let len = 23; let sum_vec = f(4, len, 4).unwrap(); - flp_validity_test( + FlpTest::expect_valid::<3>( &sum_vec, &sum_vec.encode_measurement(&vec![9; len]).unwrap(), - &ValidityTestCase::<TestField> { - expect_valid: true, - expected_output: Some(vec![nine; len]), - num_shares: 3, - }, - ) - .unwrap(); + &vec![nine; len], + ); // Test on invalid inputs. for len in 1..10 { let chunk_length = cmp::max((len as f64).sqrt() as usize, 1); let sum_vec = f(1, len, chunk_length).unwrap(); - flp_validity_test( - &sum_vec, - &vec![nine; len], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_invalid::<3>(&sum_vec, &vec![nine; len]); } let len = 23; let sum_vec = f(2, len, 4).unwrap(); - flp_validity_test( - &sum_vec, - &vec![nine; 2 * len], - &ValidityTestCase::<TestField> { - expect_valid: false, - expected_output: None, - num_shares: 3, - }, - ) - .unwrap(); + FlpTest::expect_invalid::<3>(&sum_vec, &vec![nine; 2 * len]); // Round trip let want = vec![1; len]; @@ -1232,184 +1058,6 @@ mod tests { } } -#[cfg(test)] -mod test_utils { - use super::*; - use crate::field::{random_vector, split_vector, FieldElement}; - - pub(crate) struct ValidityTestCase<F> { - pub(crate) expect_valid: bool, - pub(crate) expected_output: Option<Vec<F>>, - // Number of shares to split input and proofs into in `flp_test`. - pub(crate) num_shares: usize, - } - - pub(crate) fn flp_validity_test<T: Type>( - typ: &T, - input: &[T::Field], - t: &ValidityTestCase<T::Field>, - ) -> Result<(), FlpError> { - let mut gadgets = typ.gadget(); - - if input.len() != typ.input_len() { - return Err(FlpError::Test(format!( - "unexpected input length: got {}; want {}", - input.len(), - typ.input_len() - ))); - } - - if typ.query_rand_len() != gadgets.len() { - return Err(FlpError::Test(format!( - "query rand length: got {}; want {}", - typ.query_rand_len(), - gadgets.len() - ))); - } - - let joint_rand = random_vector(typ.joint_rand_len()).unwrap(); - let prove_rand = random_vector(typ.prove_rand_len()).unwrap(); - let query_rand = random_vector(typ.query_rand_len()).unwrap(); - - // Run the validity circuit. - let v = typ.valid(&mut gadgets, input, &joint_rand, 1)?; - if v != T::Field::zero() && t.expect_valid { - return Err(FlpError::Test(format!( - "expected valid input: valid() returned {v}" - ))); - } - if v == T::Field::zero() && !t.expect_valid { - return Err(FlpError::Test(format!( - "expected invalid input: valid() returned {v}" - ))); - } - - // Generate the proof. - let proof = typ.prove(input, &prove_rand, &joint_rand)?; - if proof.len() != typ.proof_len() { - return Err(FlpError::Test(format!( - "unexpected proof length: got {}; want {}", - proof.len(), - typ.proof_len() - ))); - } - - // Query the proof. - let verifier = typ.query(input, &proof, &query_rand, &joint_rand, 1)?; - if verifier.len() != typ.verifier_len() { - return Err(FlpError::Test(format!( - "unexpected verifier length: got {}; want {}", - verifier.len(), - typ.verifier_len() - ))); - } - - // Decide if the input is valid. - let res = typ.decide(&verifier)?; - if res != t.expect_valid { - return Err(FlpError::Test(format!( - "decision is {}; want {}", - res, t.expect_valid, - ))); - } - - // Run distributed FLP. - let input_shares: Vec<Vec<T::Field>> = split_vector(input, t.num_shares) - .unwrap() - .into_iter() - .collect(); - - let proof_shares: Vec<Vec<T::Field>> = split_vector(&proof, t.num_shares) - .unwrap() - .into_iter() - .collect(); - - let verifier: Vec<T::Field> = (0..t.num_shares) - .map(|i| { - typ.query( - &input_shares[i], - &proof_shares[i], - &query_rand, - &joint_rand, - t.num_shares, - ) - .unwrap() - }) - .reduce(|mut left, right| { - for (x, y) in left.iter_mut().zip(right.iter()) { - *x += *y; - } - left - }) - .unwrap(); - - let res = typ.decide(&verifier)?; - if res != t.expect_valid { - return Err(FlpError::Test(format!( - "distributed decision is {}; want {}", - res, t.expect_valid, - ))); - } - - // Try verifying various proof mutants. - for i in 0..proof.len() { - let mut mutated_proof = proof.clone(); - mutated_proof[i] += T::Field::one(); - let verifier = typ.query(input, &mutated_proof, &query_rand, &joint_rand, 1)?; - if typ.decide(&verifier)? { - return Err(FlpError::Test(format!( - "decision for proof mutant {} is {}; want {}", - i, true, false, - ))); - } - } - - // Try verifying a proof that is too short. - let mut mutated_proof = proof.clone(); - mutated_proof.truncate(gadgets[0].arity() - 1); - if typ - .query(input, &mutated_proof, &query_rand, &joint_rand, 1) - .is_ok() - { - return Err(FlpError::Test( - "query on short proof succeeded; want failure".to_string(), - )); - } - - // Try verifying a proof that is too long. - let mut mutated_proof = proof; - mutated_proof.extend_from_slice(&[T::Field::one(); 17]); - if typ - .query(input, &mutated_proof, &query_rand, &joint_rand, 1) - .is_ok() - { - return Err(FlpError::Test( - "query on long proof succeeded; want failure".to_string(), - )); - } - - if let Some(ref want) = t.expected_output { - let got = typ.truncate(input.to_vec())?; - - if got.len() != typ.output_len() { - return Err(FlpError::Test(format!( - "unexpected output length: got {}; want {}", - got.len(), - typ.output_len() - ))); - } - - if &got != want { - return Err(FlpError::Test(format!( - "unexpected output: got {got:?}; want {want:?}" - ))); - } - } - - Ok(()) - } -} - #[cfg(feature = "experimental")] #[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub mod fixedpoint_l2; diff --git a/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs b/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs index b5aa2fd116..8766c035b8 100644 --- a/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs +++ b/third_party/rust/prio/src/flp/types/fixedpoint_l2.rs @@ -172,15 +172,17 @@ pub mod compatible_float; use crate::dp::{distributions::ZCdpDiscreteGaussian, DifferentialPrivacyStrategy, DpError}; -use crate::field::{Field128, FieldElement, FieldElementWithInteger, FieldElementWithIntegerExt}; +use crate::field::{ + Field128, FieldElement, FieldElementWithInteger, FieldElementWithIntegerExt, Integer, +}; use crate::flp::gadgets::{Mul, ParallelSumGadget, PolyEval}; use crate::flp::types::fixedpoint_l2::compatible_float::CompatibleFloat; use crate::flp::types::parallel_sum_range_checks; use crate::flp::{FlpError, Gadget, Type, TypeWithNoise}; -use crate::vdaf::xof::SeedStreamSha3; +use crate::vdaf::xof::SeedStreamTurboShake128; use fixed::traits::Fixed; use num_bigint::{BigInt, BigUint, TryFromBigIntError}; -use num_integer::Integer; +use num_integer::Integer as _; use num_rational::Ratio; use rand::{distributions::Distribution, Rng}; use rand_core::SeedableRng; @@ -250,7 +252,7 @@ where /// fixed point vector with `entries` entries. pub fn new(entries: usize) -> Result<Self, FlpError> { // (0) initialize constants - let fi_one = u128::from(Field128::one()); + let fi_one = <Field128 as FieldElementWithInteger>::Integer::one(); // (I) Check that the fixed type is compatible. // @@ -400,7 +402,6 @@ where SPoly: ParallelSumGadget<Field128, PolyEval<Field128>> + Eq + Clone + 'static, SMul: ParallelSumGadget<Field128, Mul<Field128>> + Eq + Clone + 'static, { - const ID: u32 = 0xFFFF0000; type Measurement = Vec<T>; type AggregateResult = Vec<f64>; type Field = Field128; @@ -419,12 +420,9 @@ where // Encode the integer entries bitwise, and write them into the `encoded` // vector. let mut encoded: Vec<Field128> = - vec![Field128::zero(); self.bits_per_entry * self.entries + self.bits_for_norm]; - for (l, entry) in integer_entries.clone().enumerate() { - Field128::fill_with_bitvector_representation( - &entry, - &mut encoded[l * self.bits_per_entry..(l + 1) * self.bits_per_entry], - )?; + Vec::with_capacity(self.bits_per_entry * self.entries + self.bits_for_norm); + for entry in integer_entries.clone() { + encoded.extend(Field128::encode_as_bitvector(entry, self.bits_per_entry)?); } // (II) Vector norm. @@ -434,10 +432,7 @@ where let norm_int = u128::from(norm); // Write the norm into the `entries` vector. - Field128::fill_with_bitvector_representation( - &norm_int, - &mut encoded[self.range_norm_begin..self.range_norm_end], - )?; + encoded.extend(Field128::encode_as_bitvector(norm_int, self.bits_for_norm)?); Ok(encoded) } @@ -535,7 +530,7 @@ where // decode the bit-encoded entries into elements in the range [0,2^n): let decoded_entries: Result<Vec<_>, _> = input[0..self.entries * self.bits_per_entry] .chunks(self.bits_per_entry) - .map(Field128::decode_from_bitvector_representation) + .map(Field128::decode_bitvector) .collect(); // run parallel sum gadget on the decoded entries @@ -544,7 +539,7 @@ where // Chunks which are too short need to be extended with a share of the // encoded zero value, that is: 1/num_shares * (2^(n-1)) - let fi_one = u128::from(Field128::one()); + let fi_one = <Field128 as FieldElementWithInteger>::Integer::one(); let zero_enc = Field128::from(fi_one << (self.bits_per_entry - 1)); let zero_enc_share = zero_enc * num_shares_inverse; @@ -567,7 +562,7 @@ where // The submitted norm is also decoded from its bit-encoding, and // compared with the computed norm. let submitted_norm_enc = &input[self.range_norm_begin..self.range_norm_end]; - let submitted_norm = Field128::decode_from_bitvector_representation(submitted_norm_enc)?; + let submitted_norm = Field128::decode_bitvector(submitted_norm_enc)?; let norm_check = computed_norm - submitted_norm; @@ -586,7 +581,7 @@ where let start = i_entry * self.bits_per_entry; let end = (i_entry + 1) * self.bits_per_entry; - let decoded = Field128::decode_from_bitvector_representation(&input[start..end])?; + let decoded = Field128::decode_bitvector(&input[start..end])?; decoded_vector.push(decoded); } Ok(decoded_vector) @@ -644,7 +639,11 @@ where agg_result: &mut [Self::Field], _num_measurements: usize, ) -> Result<(), FlpError> { - self.add_noise(dp_strategy, agg_result, &mut SeedStreamSha3::from_entropy()) + self.add_noise( + dp_strategy, + agg_result, + &mut SeedStreamTurboShake128::from_entropy(), + ) } } @@ -686,8 +685,8 @@ mod tests { use crate::dp::{Rational, ZCdpBudget}; use crate::field::{random_vector, Field128, FieldElement}; use crate::flp::gadgets::ParallelSum; - use crate::flp::types::test_utils::{flp_validity_test, ValidityTestCase}; - use crate::vdaf::xof::SeedStreamSha3; + use crate::flp::test_utils::FlpTest; + use crate::vdaf::xof::SeedStreamTurboShake128; use fixed::types::extra::{U127, U14, U63}; use fixed::{FixedI128, FixedI16, FixedI64}; use fixed_macro::fixed; @@ -768,15 +767,23 @@ mod tests { let strategy = ZCdpDiscreteGaussian::from_budget(ZCdpBudget::new( Rational::from_unsigned(100u8, 3u8).unwrap(), )); - vsum.add_noise(&strategy, &mut v, &mut SeedStreamSha3::from_seed([0u8; 16])) - .unwrap(); + vsum.add_noise( + &strategy, + &mut v, + &mut SeedStreamTurboShake128::from_seed([0u8; 16]), + ) + .unwrap(); assert_eq!( vsum.decode_result(&v, 1).unwrap(), match n { // sensitivity depends on encoding so the noise differs - 16 => vec![0.150604248046875, 0.139373779296875, -0.03759765625], - 32 => vec![0.3051439793780446, 0.1226568529382348, 0.08595499861985445], - 64 => vec![0.2896077990915178, 0.16115188007715098, 0.0788390114728425], + 16 => vec![0.288970947265625, 0.168853759765625, 0.085662841796875], + 32 => vec![0.257810294162482, 0.10634658299386501, 0.10149003705009818], + 64 => vec![ + 0.37697368351762867, + -0.02388947667663828, + 0.19813152630930916 + ], _ => panic!("unsupported bitsize"), } ); @@ -785,52 +792,46 @@ mod tests { let mut input: Vec<Field128> = vsum.encode_measurement(&fp_vec).unwrap(); assert_eq!(input[0], Field128::zero()); input[0] = one; // it was zero - flp_validity_test( - &vsum, - &input, - &ValidityTestCase::<Field128> { - expect_valid: false, - expected_output: Some(vec![ - Field128::from(enc_vec[0] + 1), // = enc(0.25) + 2^0 - Field128::from(enc_vec[1]), - Field128::from(enc_vec[2]), - ]), - num_shares: 3, - }, - ) - .unwrap(); + FlpTest { + name: None, + flp: &vsum, + input: &input, + expected_output: Some(&[ + Field128::from(enc_vec[0] + 1), // = enc(0.25) + 2^0 + Field128::from(enc_vec[1]), + Field128::from(enc_vec[2]), + ]), + expect_valid: false, + } + .run::<3>(); // encoding contains entries that are not zero or one let mut input2: Vec<Field128> = vsum.encode_measurement(&fp_vec).unwrap(); input2[0] = one + one; - flp_validity_test( - &vsum, - &input2, - &ValidityTestCase::<Field128> { - expect_valid: false, - expected_output: Some(vec![ - Field128::from(enc_vec[0] + 2), // = enc(0.25) + 2*2^0 - Field128::from(enc_vec[1]), - Field128::from(enc_vec[2]), - ]), - num_shares: 3, - }, - ) - .unwrap(); + FlpTest { + name: None, + flp: &vsum, + input: &input2, + expected_output: Some(&[ + Field128::from(enc_vec[0] + 2), // = enc(0.25) + 2*2^0 + Field128::from(enc_vec[1]), + Field128::from(enc_vec[2]), + ]), + expect_valid: false, + } + .run::<3>(); // norm is too big // 2^n - 1, the field element encoded by the all-1 vector let one_enc = Field128::from(((2_u128) << (n - 1)) - 1); - flp_validity_test( - &vsum, - &vec![one; 3 * n + 2 * n - 2], // all vector entries and the norm are all-1-vectors - &ValidityTestCase::<Field128> { - expect_valid: false, - expected_output: Some(vec![one_enc; 3]), - num_shares: 3, - }, - ) - .unwrap(); + FlpTest { + name: None, + flp: &vsum, + input: &vec![one; 3 * n + 2 * n - 2], // all vector entries and the norm are all-1-vectors + expected_output: Some(&[one_enc; 3]), + expect_valid: false, + } + .run::<3>(); // invalid submission length, should be 3n + (2*n - 2) for a // 3-element n-bit vector. 3*n bits for 3 entries, (2*n-2) for norm. diff --git a/third_party/rust/prio/src/idpf.rs b/third_party/rust/prio/src/idpf.rs index 2bb73f2159..b3da128fa0 100644 --- a/third_party/rust/prio/src/idpf.rs +++ b/third_party/rust/prio/src/idpf.rs @@ -1,7 +1,7 @@ //! This module implements the incremental distributed point function (IDPF) described in -//! [[draft-irtf-cfrg-vdaf-07]]. +//! [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ use crate::{ codec::{CodecError, Decode, Encode, ParameterizedDecode}, @@ -24,12 +24,14 @@ use std::{ collections::{HashMap, VecDeque}, fmt::Debug, io::{Cursor, Read}, + iter::zip, ops::{Add, AddAssign, ControlFlow, Index, Sub}, }; use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTimeEq}; /// IDPF-related errors. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum IdpfError { /// Error from incompatible shares at different levels. #[error("tried to merge shares from incompatible levels")] @@ -107,6 +109,11 @@ impl IdpfInput { index: self.index[..=level].to_owned().into(), } } + + /// Return the bit at the specified level if the level is in bounds. + pub fn get(&self, level: usize) -> Option<bool> { + self.index.get(level).as_deref().copied() + } } impl From<BitVec<usize, Lsb0>> for IdpfInput { @@ -146,7 +153,7 @@ pub trait IdpfValue: + Sub<Output = Self> + ConditionallyNegatable + Encode - + Decode + + ParameterizedDecode<Self::ValueParameter> + Sized { /// Any run-time parameters needed to produce a value. @@ -239,11 +246,13 @@ fn extend(seed: &[u8; 16], xof_fixed_key: &XofFixedKeyAes128Key) -> ([[u8; 16]; seed_stream.fill_bytes(&mut seeds[0]); seed_stream.fill_bytes(&mut seeds[1]); - let mut byte = [0u8]; - seed_stream.fill_bytes(&mut byte); - let control_bits = [(byte[0] & 1).into(), ((byte[0] >> 1) & 1).into()]; + // "Steal" the control bits from the seeds. + let control_bits_0 = seeds[0].as_ref()[0] & 1; + let control_bits_1 = seeds[1].as_ref()[0] & 1; + seeds[0].as_mut()[0] &= 0xfe; + seeds[1].as_mut()[0] &= 0xfe; - (seeds, control_bits) + (seeds, [control_bits_0.into(), control_bits_1.into()]) } fn convert<V>( @@ -670,7 +679,7 @@ where VI: Encode, VL: Encode, { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { // Control bits need to be written within each byte in LSB-to-MSB order, and assigned into // bytes in big-endian order. Thus, the first four levels will have their control bits // encoded in the last byte, and the last levels will have their control bits encoded in the @@ -691,11 +700,11 @@ where bytes.append(&mut packed_control); for correction_words in self.inner_correction_words.iter() { - Seed(correction_words.seed).encode(bytes); - correction_words.value.encode(bytes); + Seed(correction_words.seed).encode(bytes)?; + correction_words.value.encode(bytes)?; } - Seed(self.leaf_correction_word.seed).encode(bytes); - self.leaf_correction_word.value.encode(bytes); + Seed(self.leaf_correction_word.seed).encode(bytes)?; + self.leaf_correction_word.value.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -785,7 +794,7 @@ where impl<V> Eq for IdpfCorrectionWord<V> where V: ConstantTimeEq {} -fn xor_seeds(left: &[u8; 16], right: &[u8; 16]) -> [u8; 16] { +pub(crate) fn xor_seeds(left: &[u8; 16], right: &[u8; 16]) -> [u8; 16] { let mut seed = [0u8; 16]; for (a, (b, c)) in left.iter().zip(right.iter().zip(seed.iter_mut())) { *c = a ^ b; @@ -819,7 +828,7 @@ fn control_bit_to_seed_mask(control: Choice) -> [u8; 16] { /// Take two seeds and a control bit, and return the first seed if the control bit is zero, or the /// XOR of the two seeds if the control bit is one. This does not branch on the control bit. -fn conditional_xor_seeds( +pub(crate) fn conditional_xor_seeds( normal_input: &[u8; 16], switched_input: &[u8; 16], control: Choice, @@ -832,13 +841,18 @@ fn conditional_xor_seeds( /// Returns one of two seeds, depending on the value of a selector bit. Does not branch on the /// selector input or make selector-dependent memory accesses. -fn conditional_select_seed(select: Choice, seeds: &[[u8; 16]; 2]) -> [u8; 16] { +pub(crate) fn conditional_select_seed(select: Choice, seeds: &[[u8; 16]; 2]) -> [u8; 16] { or_seeds( &and_seeds(&control_bit_to_seed_mask(!select), &seeds[0]), &and_seeds(&control_bit_to_seed_mask(select), &seeds[1]), ) } +/// Interchange the contents of seeds if the choice is 1, otherwise seeds remain unchanged. +pub(crate) fn conditional_swap_seed(lhs: &mut [u8; 16], rhs: &mut [u8; 16], choice: Choice) { + zip(lhs, rhs).for_each(|(a, b)| u8::conditional_swap(a, b, choice)); +} + /// An interface that provides memoization of IDPF computations. /// /// Each instance of a type implementing `IdpfCache` should only be used with one IDPF key and @@ -947,11 +961,91 @@ impl IdpfCache for RingBufferCache { } } +/// Utilities for testing IDPFs. +#[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub mod test_utils { + use super::*; + + use rand::prelude::*; + use zipf::ZipfDistribution; + + /// Generate a set of IDPF inputs with the given bit length `bits`. They are sampled according + /// to the Zipf distribution with parameters `zipf_support` and `zipf_exponent`. Return the + /// measurements, along with the prefixes traversed during the heavy hitters computation for + /// the given threshold. + /// + /// The prefix tree consists of a sequence of candidate prefixes for each level. For a given level, + /// the candidate prefixes are computed from the hit counts of the prefixes at the previous level: + /// For any prefix `p` whose hit count is at least the desired threshold, add `p || 0` and `p || 1` + /// to the list. + pub fn generate_zipf_distributed_batch( + rng: &mut impl Rng, + bits: usize, + threshold: usize, + measurement_count: usize, + zipf_support: usize, + zipf_exponent: f64, + ) -> (Vec<IdpfInput>, Vec<Vec<IdpfInput>>) { + // Generate random inputs. + let mut inputs = Vec::with_capacity(zipf_support); + for _ in 0..zipf_support { + let bools: Vec<bool> = (0..bits).map(|_| rng.gen()).collect(); + inputs.push(IdpfInput::from_bools(&bools)); + } + + // Sample a number of inputs according to the Zipf distribution. + let mut samples = Vec::with_capacity(measurement_count); + let zipf = ZipfDistribution::new(zipf_support, zipf_exponent).unwrap(); + for _ in 0..measurement_count { + samples.push(inputs[zipf.sample(rng) - 1].clone()); + } + + // Compute the prefix tree for the desired threshold. + let mut prefix_tree = Vec::with_capacity(bits); + prefix_tree.push(vec![ + IdpfInput::from_bools(&[false]), + IdpfInput::from_bools(&[true]), + ]); + + for level in 0..bits - 1 { + // Compute the hit count of each prefix from the previous level. + let mut hit_counts = vec![0; prefix_tree[level].len()]; + for (hit_count, prefix) in hit_counts.iter_mut().zip(prefix_tree[level].iter()) { + for sample in samples.iter() { + let mut is_prefix = true; + for j in 0..prefix.len() { + if prefix[j] != sample[j] { + is_prefix = false; + break; + } + } + if is_prefix { + *hit_count += 1; + } + } + } + + // Compute the next set of candidate prefixes. + let mut next_prefixes = Vec::with_capacity(prefix_tree.last().unwrap().len()); + for (hit_count, prefix) in hit_counts.iter().zip(prefix_tree[level].iter()) { + if *hit_count >= threshold { + next_prefixes.push(prefix.clone_with_suffix(&[false])); + next_prefixes.push(prefix.clone_with_suffix(&[true])); + } + } + prefix_tree.push(next_prefixes); + } + + (samples, prefix_tree) + } +} + #[cfg(test)] mod tests { use std::{ collections::HashMap, - convert::{TryFrom, TryInto}, + convert::TryInto, io::Cursor, ops::{Add, AddAssign, Sub}, str::FromStr, @@ -1568,16 +1662,16 @@ mod tests { seed: [0xab; 16], control_bits: [Choice::from(1), Choice::from(0)], value: Poplar1IdpfValue::new([ - Field64::try_from(83261u64).unwrap(), - Field64::try_from(125159u64).unwrap(), + Field64::from(83261u64), + Field64::from(125159u64), ]), }, IdpfCorrectionWord{ seed: [0xcd;16], control_bits: [Choice::from(0), Choice::from(1)], value: Poplar1IdpfValue::new([ - Field64::try_from(17614120u64).unwrap(), - Field64::try_from(20674u64).unwrap(), + Field64::from(17614120u64), + Field64::from(20674u64), ]), }, ]), @@ -1605,7 +1699,7 @@ mod tests { "f0debc9a78563412f0debc9a78563412f0debc9a78563412f0debc9a78563412", // field element correction word, continued )) .unwrap(); - let encoded = public_share.get_encoded(); + let encoded = public_share.get_encoded().unwrap(); let decoded = IdpfPublicShare::get_decoded_with_param(&3, &message).unwrap(); assert_eq!(public_share, decoded); assert_eq!(message, encoded); @@ -1692,7 +1786,7 @@ mod tests { "0000000000000000000000000000000000000000000000000000000000000000", )) .unwrap(); - let encoded = public_share.get_encoded(); + let encoded = public_share.get_encoded().unwrap(); let decoded = IdpfPublicShare::get_decoded_with_param(&9, &message).unwrap(); assert_eq!(public_share, decoded); assert_eq!(message, encoded); @@ -1761,7 +1855,7 @@ mod tests { 0, ); - assert_eq!(public_share.get_encoded(), serialized_public_share); + assert_eq!(public_share.get_encoded().unwrap(), serialized_public_share); assert_eq!( IdpfPublicShare::get_decoded_with_param(&idpf_bits, &serialized_public_share) .unwrap(), @@ -1821,7 +1915,7 @@ mod tests { /// Load a test vector for Idpf key generation. fn load_idpfpoplar_test_vector() -> IdpfTestVector { let test_vec: serde_json::Value = - serde_json::from_str(include_str!("vdaf/test_vec/07/IdpfPoplar_0.json")).unwrap(); + serde_json::from_str(include_str!("vdaf/test_vec/08/IdpfPoplar_0.json")).unwrap(); let test_vec_obj = test_vec.as_object().unwrap(); let bits = test_vec_obj @@ -1939,7 +2033,7 @@ mod tests { public_share, expected_public_share, "public share did not match\n{public_share:#x?}\n{expected_public_share:#x?}" ); - let encoded_public_share = public_share.get_encoded(); + let encoded_public_share = public_share.get_encoded().unwrap(); assert_eq!(encoded_public_share, test_vector.public_share); } @@ -1988,7 +2082,9 @@ mod tests { } impl Encode for MyUnit { - fn encode(&self, _: &mut Vec<u8>) {} + fn encode(&self, _: &mut Vec<u8>) -> Result<(), CodecError> { + Ok(()) + } } impl Decode for MyUnit { @@ -2066,8 +2162,8 @@ mod tests { } impl Encode for MyVector { - fn encode(&self, bytes: &mut Vec<u8>) { - encode_u32_items(bytes, &(), &self.0); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + encode_u32_items(bytes, &(), &self.0) } } diff --git a/third_party/rust/prio/src/lib.rs b/third_party/rust/prio/src/lib.rs index c9d4e22c49..630e118646 100644 --- a/third_party/rust/prio/src/lib.rs +++ b/third_party/rust/prio/src/lib.rs @@ -17,6 +17,7 @@ pub mod benchmarked; pub mod codec; #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub mod dp; mod fft; pub mod field; @@ -32,3 +33,9 @@ mod polynomial; mod prng; pub mod topology; pub mod vdaf; +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) +)] +pub mod vidpf; diff --git a/third_party/rust/prio/src/polynomial.rs b/third_party/rust/prio/src/polynomial.rs index 89d8a91404..272266f538 100644 --- a/third_party/rust/prio/src/polynomial.rs +++ b/third_party/rust/prio/src/polynomial.rs @@ -3,7 +3,7 @@ //! Functions for polynomial interpolation and evaluation -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] use crate::fft::{discrete_fourier_transform, discrete_fourier_transform_inv_finish}; use crate::field::FftFriendlyFieldElement; @@ -204,7 +204,7 @@ pub fn poly_mul<F: FftFriendlyFieldElement>(p: &[F], q: &[F]) -> Vec<F> { out } -#[cfg(feature = "prio2")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[inline] pub fn poly_interpret_eval<F: FftFriendlyFieldElement>( points: &[F], diff --git a/third_party/rust/prio/src/prng.rs b/third_party/rust/prio/src/prng.rs index cb7d3a54c8..2c3f5b6640 100644 --- a/third_party/rust/prio/src/prng.rs +++ b/third_party/rust/prio/src/prng.rs @@ -6,10 +6,9 @@ //! NOTE: The public API for this module is a work in progress. use crate::field::{FieldElement, FieldElementExt}; -#[cfg(feature = "crypto-dependencies")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] use crate::vdaf::xof::SeedStreamAes128; -#[cfg(feature = "crypto-dependencies")] -use getrandom::getrandom; +use crate::vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128}; use rand_core::RngCore; use std::marker::PhantomData; @@ -19,6 +18,7 @@ const BUFFER_SIZE_IN_ELEMENTS: usize = 32; /// Errors propagated by methods in this module. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum PrngError { /// Failure when calling getrandom(). #[error("getrandom: {0}")] @@ -35,7 +35,7 @@ pub(crate) struct Prng<F, S> { buffer_index: usize, } -#[cfg(feature = "crypto-dependencies")] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] impl<F: FieldElement> Prng<F, SeedStreamAes128> { /// Create a [`Prng`] from a seed for Prio 2. The first 16 bytes of the seed and the last 16 /// bytes of the seed are used, respectively, for the key and initialization vector for AES128 @@ -44,12 +44,17 @@ impl<F: FieldElement> Prng<F, SeedStreamAes128> { let seed_stream = SeedStreamAes128::new(&seed[..16], &seed[16..]); Self::from_seed_stream(seed_stream) } +} +impl<F: FieldElement> Prng<F, SeedStreamTurboShake128> { /// Create a [`Prng`] from a randomly generated seed. pub(crate) fn new() -> Result<Self, PrngError> { - let mut seed = [0; 32]; - getrandom(&mut seed)?; - Ok(Self::from_prio2_seed(&seed)) + let seed = Seed::generate()?; + Ok(Prng::from_seed_stream(XofTurboShake128::seed_stream( + &seed, + &[], + &[], + ))) } } @@ -125,18 +130,20 @@ where #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "experimental")] + use crate::field::{encode_fieldvec, Field128, FieldPrio2}; use crate::{ codec::Decode, - field::{Field64, FieldPrio2}, - vdaf::xof::{Seed, SeedStreamSha3, Xof, XofShake128}, + field::Field64, + vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128}, }; - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] use base64::{engine::Engine, prelude::BASE64_STANDARD}; - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] use sha2::{Digest, Sha256}; - use std::convert::TryInto; #[test] + #[cfg(feature = "experimental")] fn secret_sharing_interop() { let seed = [ 0xcd, 0x85, 0x5b, 0xd4, 0x86, 0x48, 0xa4, 0xce, 0x52, 0x5c, 0x36, 0xee, 0x5a, 0x71, @@ -158,21 +165,22 @@ mod tests { } /// takes a seed and hash as base64 encoded strings - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn random_data_interop(seed_base64: &str, hash_base64: &str, len: usize) { let seed = BASE64_STANDARD.decode(seed_base64).unwrap(); let random_data = extract_share_from_seed::<FieldPrio2>(len, &seed); - let random_bytes = FieldPrio2::slice_into_byte_vec(&random_data); + let mut random_bytes = Vec::new(); + encode_fieldvec(&random_data, &mut random_bytes).unwrap(); - let mut hasher = Sha256::new(); + let mut hasher = <Sha256 as Digest>::new(); hasher.update(&random_bytes); let digest = hasher.finalize(); assert_eq!(BASE64_STANDARD.encode(digest), hash_base64); } #[test] - #[cfg(feature = "prio2")] + #[cfg(feature = "experimental")] fn test_hash_interop() { random_data_interop( "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", @@ -206,6 +214,7 @@ mod tests { ); } + #[cfg(feature = "experimental")] fn extract_share_from_seed<F: FieldElement>(length: usize, seed: &[u8]) -> Vec<F> { assert_eq!(seed.len(), 32); Prng::from_prio2_seed(seed.try_into().unwrap()) @@ -218,22 +227,22 @@ mod tests { // These constants were found in a brute-force search, and they test that the XOF performs // rejection sampling correctly when the raw output exceeds the prime modulus. let seed = Seed::get_decoded(&[ - 0x29, 0xb2, 0x98, 0x64, 0xb4, 0xaa, 0x4e, 0x07, 0x2a, 0x44, 0x49, 0x24, 0xf6, 0x74, - 0x0a, 0x3d, + 0xd5, 0x3f, 0xff, 0x5d, 0x88, 0x8c, 0x60, 0x4e, 0x9f, 0x24, 0x16, 0xe1, 0xa2, 0x0a, + 0x62, 0x34, ]) .unwrap(); - let expected = Field64::from(2035552711764301796); + let expected = Field64::from(3401316594827516850); - let seed_stream = XofShake128::seed_stream(&seed, b"", b""); + let seed_stream = XofTurboShake128::seed_stream(&seed, b"", b""); let mut prng = Prng::<Field64, _>::from_seed_stream(seed_stream); - let actual = prng.nth(33236).unwrap(); + let actual = prng.nth(662).unwrap(); assert_eq!(actual, expected); #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] { - let mut seed_stream = XofShake128::seed_stream(&seed, b"", b""); + let mut seed_stream = XofTurboShake128::seed_stream(&seed, b"", b""); let mut actual = <Field64 as FieldElement>::zero(); - for _ in 0..=33236 { + for _ in 0..=662 { actual = <Field64 as crate::idpf::IdpfValue>::generate(&mut seed_stream, &()); } assert_eq!(actual, expected); @@ -246,12 +255,12 @@ mod tests { fn left_over_buffer_back_fill() { let seed = Seed::generate().unwrap(); - let mut prng: Prng<Field64, SeedStreamSha3> = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let mut prng: Prng<Field64, SeedStreamTurboShake128> = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); // Construct a `Prng` with a longer-than-usual buffer. - let mut prng_weird_buffer_size: Prng<Field64, SeedStreamSha3> = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let mut prng_weird_buffer_size: Prng<Field64, SeedStreamTurboShake128> = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); let mut extra = [0; 7]; prng_weird_buffer_size.seed_stream.fill_bytes(&mut extra); prng_weird_buffer_size.buffer.extend_from_slice(&extra); @@ -265,13 +274,13 @@ mod tests { #[cfg(feature = "experimental")] #[test] - fn into_new_field() { + fn into_different_field() { let seed = Seed::generate().unwrap(); - let want: Prng<Field64, SeedStreamSha3> = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let want: Prng<Field64, SeedStreamTurboShake128> = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); let want_buffer = want.buffer.clone(); - let got: Prng<FieldPrio2, _> = want.into_new_field(); + let got: Prng<Field128, _> = want.into_new_field(); assert_eq!(got.buffer_index, 0); assert_eq!(got.buffer, want_buffer); } diff --git a/third_party/rust/prio/src/topology/ping_pong.rs b/third_party/rust/prio/src/topology/ping_pong.rs index c55d4f638d..646f181865 100644 --- a/third_party/rust/prio/src/topology/ping_pong.rs +++ b/third_party/rust/prio/src/topology/ping_pong.rs @@ -4,7 +4,7 @@ //! two aggregators, designated "Leader" and "Helper". This topology is required for implementing //! the [Distributed Aggregation Protocol][DAP]. //! -//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 //! [DAP]: https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap use crate::{ @@ -15,6 +15,7 @@ use std::fmt::Debug; /// Errors emitted by this module. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum PingPongError { /// Error running prepare_init #[error("vdaf.prepare_init: {0}")] @@ -28,12 +29,12 @@ pub enum PingPongError { #[error("vdaf.prepare_next {0}")] VdafPrepareNext(VdafError), - /// Error decoding a prepare share - #[error("decode prep share {0}")] + /// Error encoding or decoding a prepare share + #[error("encode/decode prep share {0}")] CodecPrepShare(CodecError), - /// Error decoding a prepare message - #[error("decode prep message {0}")] + /// Error encoding or decoding a prepare message + #[error("encode/decode prep message {0}")] CodecPrepMessage(CodecError), /// Host is in an unexpected state @@ -63,7 +64,7 @@ pub enum PingPongError { /// variants are opaque byte buffers. This is because the ping-pong routines take responsibility for /// decoding preparation shares and messages, which usually requires having the preparation state. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, PartialEq, Eq)] pub enum PingPongMessage { /// Corresponds to MessageType.initialize. @@ -108,27 +109,28 @@ impl Debug for PingPongMessage { } impl Encode for PingPongMessage { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { // The encoding includes an implicit discriminator byte, called MessageType in the VDAF // spec. match self { Self::Initialize { prep_share } => { - 0u8.encode(bytes); - encode_u32_items(bytes, &(), prep_share); + 0u8.encode(bytes)?; + encode_u32_items(bytes, &(), prep_share)?; } Self::Continue { prep_msg, prep_share, } => { - 1u8.encode(bytes); - encode_u32_items(bytes, &(), prep_msg); - encode_u32_items(bytes, &(), prep_share); + 1u8.encode(bytes)?; + encode_u32_items(bytes, &(), prep_msg)?; + encode_u32_items(bytes, &(), prep_share)?; } Self::Finish { prep_msg } => { - 2u8.encode(bytes); - encode_u32_items(bytes, &(), prep_msg); + 2u8.encode(bytes)?; + encode_u32_items(bytes, &(), prep_msg)?; } } + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -182,7 +184,7 @@ impl Decode for PingPongMessage { /// preprocessed prepare message. Their encoding is much smaller than the `(State, Message)` tuple, /// which can always be recomputed with [`Self::evaluate`]. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, Debug, Eq)] pub struct PingPongTransition< const VERIFY_KEY_SIZE: usize, @@ -212,26 +214,31 @@ impl< ), PingPongError, > { - let prep_msg = self.current_prepare_message.get_encoded(); + let prep_msg = self + .current_prepare_message + .get_encoded() + .map_err(PingPongError::CodecPrepMessage)?; vdaf.prepare_next( self.previous_prepare_state.clone(), self.current_prepare_message.clone(), ) - .map(|transition| match transition { - PrepareTransition::Continue(prep_state, prep_share) => ( + .map_err(PingPongError::VdafPrepareNext) + .and_then(|transition| match transition { + PrepareTransition::Continue(prep_state, prep_share) => Ok(( PingPongState::Continued(prep_state), PingPongMessage::Continue { prep_msg, - prep_share: prep_share.get_encoded(), + prep_share: prep_share + .get_encoded() + .map_err(PingPongError::CodecPrepShare)?, }, - ), - PrepareTransition::Finish(output_share) => ( + )), + PrepareTransition::Finish(output_share) => Ok(( PingPongState::Finished(output_share), PingPongMessage::Finish { prep_msg }, - ), + )), }) - .map_err(PingPongError::VdafPrepareNext) } } @@ -253,9 +260,9 @@ where A: Aggregator<VERIFY_KEY_SIZE, NONCE_SIZE>, A::PrepareState: Encode, { - fn encode(&self, bytes: &mut Vec<u8>) { - self.previous_prepare_state.encode(bytes); - self.current_prepare_message.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.previous_prepare_state.encode(bytes)?; + self.current_prepare_message.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -293,7 +300,7 @@ where /// code, and the `Rejected` state is represented as `std::result::Result::Err`, so this enum does /// not include those variants. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, Debug, PartialEq, Eq)] pub enum PingPongState< const VERIFY_KEY_SIZE: usize, @@ -331,7 +338,7 @@ pub enum PingPongContinuedValue< /// Extension trait on [`crate::vdaf::Aggregator`] which adds the [VDAF Ping-Pong Topology][VDAF]. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Aggregator<VERIFY_KEY_SIZE, NONCE_SIZE> { @@ -351,7 +358,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize /// leader along with the next [`PingPongMessage`] received from the helper as input to /// [`Self::leader_continued`] to advance to the next round. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 fn leader_initialized( &self, verify_key: &[u8; VERIFY_KEY_SIZE], @@ -362,7 +369,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize ) -> Result<(Self::State, PingPongMessage), PingPongError>; /// Initialize helper state using the helper's input share and the leader's first prepare share. - /// Corresponds to `ping_pong_helper_init` in the forthcoming `draft-irtf-cfrg-vdaf-07`. + /// Corresponds to `ping_pong_helper_init` in [VDAF]. /// /// If successful, the returned [`PingPongTransition`] should be evaluated, yielding a /// [`PingPongMessage`], which should be transmitted to the leader, and a [`PingPongState`]. @@ -378,6 +385,8 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize /// # Errors /// /// `inbound` must be `PingPongMessage::Initialize` or the function will fail. + /// + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 fn helper_initialized( &self, verify_key: &[u8; VERIFY_KEY_SIZE], @@ -415,15 +424,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize /// /// `inbound` must not be `PingPongMessage::Initialize` or the function will fail. /// - /// # Notes - /// - /// The specification of this function in [VDAF] takes the aggregation parameter. This version - /// does not, because [`crate::vdaf::Aggregator::prepare_preprocess`] does not take the - /// aggregation parameter. This may change in the future if/when [#670][issue] is addressed. - /// - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 - /// [issue]: https://github.com/divviup/libprio-rs/issues/670 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 fn leader_continued( &self, leader_state: Self::State, @@ -458,15 +459,7 @@ pub trait PingPongTopology<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize /// /// `inbound` must not be `PingPongMessage::Initialize` or the function will fail. /// - /// # Notes - /// - /// The specification of this function in [VDAF] takes the aggregation parameter. This version - /// does not, because [`crate::vdaf::Aggregator::prepare_preprocess`] does not take the - /// aggregation parameter. This may change in the future if/when [#670][issue] is addressed. - /// - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 - /// [issue]: https://github.com/divviup/libprio-rs/issues/670 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 fn helper_continued( &self, helper_state: Self::State, @@ -513,15 +506,17 @@ where public_share, input_share, ) - .map(|(prep_state, prep_share)| { - ( + .map_err(PingPongError::VdafPrepareInit) + .and_then(|(prep_state, prep_share)| { + Ok(( PingPongState::Continued(prep_state), PingPongMessage::Initialize { - prep_share: prep_share.get_encoded(), + prep_share: prep_share + .get_encoded() + .map_err(PingPongError::CodecPrepShare)?, }, - ) + )) }) - .map_err(PingPongError::VdafPrepareInit) } fn helper_initialized( @@ -652,18 +647,14 @@ where (PrepareTransition::Finish(output_share), None) => { Ok(PingPongContinuedValue::FinishedNoMessage { output_share }) } - (PrepareTransition::Continue(_, _), None) => { - return Err(PingPongError::PeerMessageMismatch { - found: inbound.variant(), - expected: "continue", - }) - } - (PrepareTransition::Finish(_), Some(_)) => { - return Err(PingPongError::PeerMessageMismatch { - found: inbound.variant(), - expected: "finish", - }) - } + (PrepareTransition::Continue(_, _), None) => Err(PingPongError::PeerMessageMismatch { + found: inbound.variant(), + expected: "continue", + }), + (PrepareTransition::Finish(_), Some(_)) => Err(PingPongError::PeerMessageMismatch { + found: inbound.variant(), + expected: "finish", + }), } } } @@ -914,7 +905,7 @@ mod tests { for (message, expected_hex) in messages { let mut encoded_val = Vec::new(); - message.encode(&mut encoded_val); + message.encode(&mut encoded_val).unwrap(); let got_hex = hex::encode(&encoded_val); assert_eq!( &got_hex, expected_hex, @@ -942,7 +933,7 @@ mod tests { current_prepare_message: (), }; - let encoded = transition.get_encoded(); + let encoded = transition.get_encoded().unwrap(); let hex_encoded = hex::encode(&encoded); assert_eq!( diff --git a/third_party/rust/prio/src/vdaf.rs b/third_party/rust/prio/src/vdaf.rs index 1a6c5f0315..e5f4e14c5a 100644 --- a/third_party/rust/prio/src/vdaf.rs +++ b/third_party/rust/prio/src/vdaf.rs @@ -1,14 +1,16 @@ // SPDX-License-Identifier: MPL-2.0 //! Verifiable Distributed Aggregation Functions (VDAFs) as described in -//! [[draft-irtf-cfrg-vdaf-07]]. +//! [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[cfg(feature = "experimental")] use crate::dp::DifferentialPrivacyStrategy; #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] use crate::idpf::IdpfError; +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +use crate::vidpf::VidpfError; use crate::{ codec::{CodecError, Decode, Encode, ParameterizedDecode}, field::{encode_fieldvec, merge_vector, FieldElement, FieldError}, @@ -17,15 +19,16 @@ use crate::{ vdaf::xof::Seed, }; use serde::{Deserialize, Serialize}; -use std::{fmt::Debug, io::Cursor}; +use std::{error::Error, fmt::Debug, io::Cursor}; use subtle::{Choice, ConstantTimeEq}; /// A component of the domain-separation tag, used to bind the VDAF operations to the document /// version. This will be revised with each draft with breaking changes. -pub(crate) const VERSION: u8 = 7; +pub(crate) const VERSION: u8 = 8; /// Errors emitted by this module. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum VdafError { /// An error occurred. #[error("vdaf error: {0}")] @@ -55,6 +58,15 @@ pub enum VdafError { #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[error("idpf error: {0}")] Idpf(#[from] IdpfError), + + /// VIDPF error. + #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] + #[error("vidpf error: {0}")] + Vidpf(#[from] VidpfError), + + /// Errors from other VDAFs. + #[error(transparent)] + Other(Box<dyn Error + 'static + Send + Sync>), } /// An additive share of a vector of field elements. @@ -67,18 +79,6 @@ pub enum Share<F, const SEED_SIZE: usize> { Helper(Seed<SEED_SIZE>), } -impl<F: Clone, const SEED_SIZE: usize> Share<F, SEED_SIZE> { - /// Truncate the Leader's share to the given length. If this is the Helper's share, then this - /// method clones the input without modifying it. - #[cfg(feature = "prio2")] - pub(crate) fn truncated(&self, len: usize) -> Self { - match self { - Self::Leader(ref data) => Self::Leader(data[..len].to_vec()), - Self::Helper(ref seed) => Self::Helper(seed.clone()), - } - } -} - impl<F: ConstantTimeEq, const SEED_SIZE: usize> PartialEq for Share<F, SEED_SIZE> { fn eq(&self, other: &Self) -> bool { self.ct_eq(other).into() @@ -130,16 +130,15 @@ impl<F: FieldElement, const SEED_SIZE: usize> ParameterizedDecode<ShareDecodingP } impl<F: FieldElement, const SEED_SIZE: usize> Encode for Share<F, SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { match self { Share::Leader(share_data) => { for x in share_data { - x.encode(bytes); + x.encode(bytes)?; } + Ok(()) } - Share::Helper(share_seed) => { - share_seed.encode(bytes); - } + Share::Helper(share_seed) => share_seed.encode(bytes), } } @@ -158,9 +157,6 @@ impl<F: FieldElement, const SEED_SIZE: usize> Encode for Share<F, SEED_SIZE> { /// and [`Collector`], which define the roles of the various parties involved in the execution of /// the VDAF. pub trait Vdaf: Clone + Debug { - /// Algorithm identifier for this VDAF. - const ID: u32; - /// The type of Client measurement to be aggregated. type Measurement: Clone + Debug; @@ -188,17 +184,20 @@ pub trait Vdaf: Clone + Debug { + for<'a> ParameterizedDecode<(&'a Self, &'a Self::AggregationParam)> + Encode; + /// Return the VDAF's algorithm ID. + fn algorithm_id(&self) -> u32; + /// 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(usage: u16) -> [u8; 8] { + fn domain_separation_tag(&self, usage: u16) -> [u8; 8] { let mut dst = [0_u8; 8]; dst[0] = VERSION; dst[1] = 0; // algorithm class - dst[2..6].copy_from_slice(&(Self::ID).to_be_bytes()); + dst[2..6].copy_from_slice(&(self.algorithm_id()).to_be_bytes()); dst[6..8].copy_from_slice(&usage.to_be_bytes()); dst } @@ -211,7 +210,7 @@ pub trait Client<const NONCE_SIZE: usize>: Vdaf { /// /// Implements `Vdaf::shard` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.1 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.1 fn shard( &self, measurement: &Self::Measurement, @@ -247,7 +246,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda /// /// Implements `Vdaf.prep_init` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_init( &self, verify_key: &[u8; VERIFY_KEY_SIZE], @@ -262,29 +261,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda /// /// Implements `Vdaf.prep_shares_to_prep` from [VDAF]. /// - /// # Notes - /// - /// [`Self::prepare_shares_to_prepare_message`] is preferable since its name better matches the - /// specification. - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 - #[deprecated( - since = "0.15.0", - note = "Use Vdaf::prepare_shares_to_prepare_message instead" - )] - fn prepare_preprocess<M: IntoIterator<Item = Self::PrepareShare>>( - &self, - agg_param: &Self::AggregationParam, - inputs: M, - ) -> Result<Self::PrepareMessage, VdafError> { - self.prepare_shares_to_prepare_message(agg_param, inputs) - } - - /// Preprocess a round of preparation shares into a single input to [`Self::prepare_next`]. - /// - /// Implements `Vdaf.prep_shares_to_prep` from [VDAF]. - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_shares_to_prepare_message<M: IntoIterator<Item = Self::PrepareShare>>( &self, agg_param: &Self::AggregationParam, @@ -301,31 +278,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda /// /// Implements `Vdaf.prep_next` from [VDAF]. /// - /// # Notes - /// - /// [`Self::prepare_next`] is preferable since its name better matches the specification. - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 - #[deprecated(since = "0.15.0", note = "Use Vdaf::prepare_next")] - fn prepare_step( - &self, - state: Self::PrepareState, - input: Self::PrepareMessage, - ) -> Result<PrepareTransition<Self, VERIFY_KEY_SIZE, NONCE_SIZE>, VdafError> { - self.prepare_next(state, input) - } - - /// Compute the next state transition from the current state and the previous round of input - /// messages. If this returns [`PrepareTransition::Continue`], then the returned - /// [`Self::PrepareShare`] should be combined with the other Aggregators' `PrepareShare`s from - /// this round and passed into another call to this method. This continues until this method - /// returns [`PrepareTransition::Finish`], at which point the returned output share may be - /// aggregated. If the method returns an error, the aggregator should consider its input share - /// invalid and not attempt to process it any further. - /// - /// Implements `Vdaf.prep_next` from [VDAF]. - /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_next( &self, state: Self::PrepareState, @@ -342,6 +295,7 @@ pub trait Aggregator<const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize>: Vda /// Aggregator that implements differential privacy with Aggregator-side noise addition. #[cfg(feature = "experimental")] +#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))] pub trait AggregatorWithNoise< const VERIFY_KEY_SIZE: usize, const NONCE_SIZE: usize, @@ -428,7 +382,7 @@ impl<F> From<Vec<F>> for OutputShare<F> { } impl<F: FieldElement> Encode for OutputShare<F> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { encode_fieldvec(&self.0, bytes) } @@ -451,6 +405,12 @@ impl<F> Debug for OutputShare<F> { pub struct AggregateShare<F>(Vec<F>); +impl<F> From<Vec<F>> for AggregateShare<F> { + fn from(other: Vec<F>) -> Self { + Self(other) + } +} + impl<F: ConstantTimeEq> PartialEq for AggregateShare<F> { fn eq(&self, other: &Self) -> bool { self.ct_eq(other).into() @@ -498,7 +458,7 @@ impl<F: FieldElement> AggregateShare<F> { } impl<F: FieldElement> Encode for AggregateShare<F> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { encode_fieldvec(&self.0, bytes) } @@ -507,151 +467,190 @@ impl<F: FieldElement> Encode for AggregateShare<F> { } } -#[cfg(test)] -pub(crate) fn run_vdaf<V, M, const SEED_SIZE: usize>( - vdaf: &V, - agg_param: &V::AggregationParam, - measurements: M, -) -> Result<V::AggregateResult, VdafError> -where - V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector, - M: IntoIterator<Item = V::Measurement>, -{ +/// Utilities for testing VDAFs. +#[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub mod test_utils { + use super::{Aggregatable, Aggregator, Client, Collector, PrepareTransition, VdafError}; + use crate::codec::{Encode, ParameterizedDecode}; use rand::prelude::*; - let mut rng = thread_rng(); - let mut verify_key = [0; SEED_SIZE]; - rng.fill(&mut verify_key[..]); - - let mut agg_shares: Vec<Option<V::AggregateShare>> = vec![None; vdaf.num_aggregators()]; - let mut num_measurements: usize = 0; - for measurement in measurements.into_iter() { - num_measurements += 1; - let nonce = rng.gen(); - let (public_share, input_shares) = vdaf.shard(&measurement, &nonce)?; - let out_shares = run_vdaf_prepare( - vdaf, - &verify_key, - agg_param, - &nonce, - public_share, - input_shares, - )?; - for (out_share, agg_share) in out_shares.into_iter().zip(agg_shares.iter_mut()) { - // Check serialization of output shares - let encoded_out_share = out_share.get_encoded(); - let round_trip_out_share = - V::OutputShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_out_share) - .unwrap(); - assert_eq!(round_trip_out_share.get_encoded(), encoded_out_share); - let this_agg_share = V::AggregateShare::from(out_share); - if let Some(ref mut inner) = agg_share { - inner.merge(&this_agg_share)?; - } else { - *agg_share = Some(this_agg_share); - } + /// Execute the VDAF end-to-end and return the aggregate result. + pub fn run_vdaf<V, M, const SEED_SIZE: usize>( + vdaf: &V, + agg_param: &V::AggregationParam, + measurements: M, + ) -> Result<V::AggregateResult, VdafError> + where + V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector, + M: IntoIterator<Item = V::Measurement>, + { + let mut sharded_measurements = Vec::new(); + for measurement in measurements.into_iter() { + let nonce = random(); + let (public_share, input_shares) = vdaf.shard(&measurement, &nonce)?; + + sharded_measurements.push((public_share, nonce, input_shares)); } - } - for agg_share in agg_shares.iter() { - // Check serialization of aggregate shares - let encoded_agg_share = agg_share.as_ref().unwrap().get_encoded(); - let round_trip_agg_share = - V::AggregateShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_agg_share) - .unwrap(); - assert_eq!(round_trip_agg_share.get_encoded(), encoded_agg_share); - } + run_vdaf_sharded(vdaf, agg_param, sharded_measurements) + } + + /// Execute the VDAF on sharded measurements and return the aggregate result. + pub fn run_vdaf_sharded<V, M, I, const SEED_SIZE: usize>( + vdaf: &V, + agg_param: &V::AggregationParam, + sharded_measurements: M, + ) -> Result<V::AggregateResult, VdafError> + where + V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector, + M: IntoIterator<Item = (V::PublicShare, [u8; 16], I)>, + I: IntoIterator<Item = V::InputShare>, + { + let mut rng = thread_rng(); + let mut verify_key = [0; SEED_SIZE]; + rng.fill(&mut verify_key[..]); + + let mut agg_shares: Vec<Option<V::AggregateShare>> = vec![None; vdaf.num_aggregators()]; + let mut num_measurements: usize = 0; + for (public_share, nonce, input_shares) in sharded_measurements.into_iter() { + num_measurements += 1; + let out_shares = run_vdaf_prepare( + vdaf, + &verify_key, + agg_param, + &nonce, + public_share, + input_shares, + )?; + for (out_share, agg_share) in out_shares.into_iter().zip(agg_shares.iter_mut()) { + // Check serialization of output shares + let encoded_out_share = out_share.get_encoded().unwrap(); + let round_trip_out_share = + V::OutputShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_out_share) + .unwrap(); + assert_eq!( + round_trip_out_share.get_encoded().unwrap(), + encoded_out_share + ); - let res = vdaf.unshard( - agg_param, - agg_shares.into_iter().map(|option| option.unwrap()), - num_measurements, - )?; - Ok(res) -} + let this_agg_share = V::AggregateShare::from(out_share); + if let Some(ref mut inner) = agg_share { + inner.merge(&this_agg_share)?; + } else { + *agg_share = Some(this_agg_share); + } + } + } -#[cfg(test)] -pub(crate) fn run_vdaf_prepare<V, M, const SEED_SIZE: usize>( - vdaf: &V, - verify_key: &[u8; SEED_SIZE], - agg_param: &V::AggregationParam, - nonce: &[u8; 16], - public_share: V::PublicShare, - input_shares: M, -) -> Result<Vec<V::OutputShare>, VdafError> -where - V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector, - M: IntoIterator<Item = V::InputShare>, -{ - let input_shares = input_shares - .into_iter() - .map(|input_share| input_share.get_encoded()); - - let mut states = Vec::new(); - let mut outbound = Vec::new(); - for (agg_id, input_share) in input_shares.enumerate() { - let (state, msg) = vdaf.prepare_init( - verify_key, - agg_id, + for agg_share in agg_shares.iter() { + // Check serialization of aggregate shares + let encoded_agg_share = agg_share.as_ref().unwrap().get_encoded().unwrap(); + let round_trip_agg_share = + V::AggregateShare::get_decoded_with_param(&(vdaf, agg_param), &encoded_agg_share) + .unwrap(); + assert_eq!( + round_trip_agg_share.get_encoded().unwrap(), + encoded_agg_share + ); + } + + let res = vdaf.unshard( agg_param, - nonce, - &public_share, - &V::InputShare::get_decoded_with_param(&(vdaf, agg_id), &input_share) - .expect("failed to decode input share"), + agg_shares.into_iter().map(|option| option.unwrap()), + num_measurements, )?; - states.push(state); - outbound.push(msg.get_encoded()); - } + Ok(res) + } + + /// Execute VDAF preparation for a single report and return the recovered output shares. + pub fn run_vdaf_prepare<V, M, const SEED_SIZE: usize>( + vdaf: &V, + verify_key: &[u8; SEED_SIZE], + agg_param: &V::AggregationParam, + nonce: &[u8; 16], + public_share: V::PublicShare, + input_shares: M, + ) -> Result<Vec<V::OutputShare>, VdafError> + where + V: Client<16> + Aggregator<SEED_SIZE, 16> + Collector, + M: IntoIterator<Item = V::InputShare>, + { + let public_share = + V::PublicShare::get_decoded_with_param(vdaf, &public_share.get_encoded().unwrap()) + .unwrap(); + let input_shares = input_shares + .into_iter() + .map(|input_share| input_share.get_encoded().unwrap()); - let mut inbound = vdaf - .prepare_shares_to_prepare_message( - agg_param, - outbound.iter().map(|encoded| { - V::PrepareShare::get_decoded_with_param(&states[0], encoded) - .expect("failed to decode prep share") - }), - )? - .get_encoded(); - - let mut out_shares = Vec::new(); - loop { + let mut states = Vec::new(); let mut outbound = Vec::new(); - for state in states.iter_mut() { - match vdaf.prepare_next( - state.clone(), - V::PrepareMessage::get_decoded_with_param(state, &inbound) - .expect("failed to decode prep message"), - )? { - PrepareTransition::Continue(new_state, msg) => { - outbound.push(msg.get_encoded()); - *state = new_state - } - PrepareTransition::Finish(out_share) => { - out_shares.push(out_share); + for (agg_id, input_share) in input_shares.enumerate() { + let (state, msg) = vdaf.prepare_init( + verify_key, + agg_id, + agg_param, + nonce, + &public_share, + &V::InputShare::get_decoded_with_param(&(vdaf, agg_id), &input_share) + .expect("failed to decode input share"), + )?; + states.push(state); + outbound.push(msg.get_encoded().unwrap()); + } + + let mut inbound = vdaf + .prepare_shares_to_prepare_message( + agg_param, + outbound.iter().map(|encoded| { + V::PrepareShare::get_decoded_with_param(&states[0], encoded) + .expect("failed to decode prep share") + }), + )? + .get_encoded() + .unwrap(); + + let mut out_shares = Vec::new(); + loop { + let mut outbound = Vec::new(); + for state in states.iter_mut() { + match vdaf.prepare_next( + state.clone(), + V::PrepareMessage::get_decoded_with_param(state, &inbound) + .expect("failed to decode prep message"), + )? { + PrepareTransition::Continue(new_state, msg) => { + outbound.push(msg.get_encoded().unwrap()); + *state = new_state + } + PrepareTransition::Finish(out_share) => { + out_shares.push(out_share); + } } } - } - if outbound.len() == vdaf.num_aggregators() { - // Another round is required before output shares are computed. - inbound = vdaf - .prepare_shares_to_prepare_message( - agg_param, - outbound.iter().map(|encoded| { - V::PrepareShare::get_decoded_with_param(&states[0], encoded) - .expect("failed to decode prep share") - }), - )? - .get_encoded(); - } else if outbound.is_empty() { - // Each Aggregator recovered an output share. - break; - } else { - panic!("Aggregators did not finish the prepare phase at the same time"); + if outbound.len() == vdaf.num_aggregators() { + // Another round is required before output shares are computed. + inbound = vdaf + .prepare_shares_to_prepare_message( + agg_param, + outbound.iter().map(|encoded| { + V::PrepareShare::get_decoded_with_param(&states[0], encoded) + .expect("failed to decode prep share") + }), + )? + .get_encoded() + .unwrap(); + } else if outbound.is_empty() { + // Each Aggregator recovered an output share. + break; + } else { + panic!("Aggregators did not finish the prepare phase at the same time"); + } } - } - Ok(out_shares) + Ok(out_shares) + } } #[cfg(test)] @@ -663,20 +662,17 @@ where for<'a> T: ParameterizedDecode<(&'a V, &'a V::AggregationParam)>, { // Generate an arbitrary vector of field elements. - let g = F::one() + F::one(); - let vec: Vec<F> = itertools::iterate(F::one(), |&v| g * v) - .take(length) - .collect(); + let vec: Vec<F> = crate::field::random_vector(length).unwrap(); // Serialize the field element vector into a vector of bytes. let mut bytes = Vec::with_capacity(vec.len() * F::ENCODED_SIZE); - encode_fieldvec(&vec, &mut bytes); + encode_fieldvec(&vec, &mut bytes).unwrap(); // Deserialize the type of interest from those bytes. let value = T::get_decoded_with_param(&(vdaf, agg_param), &bytes).unwrap(); // Round-trip the value back to a vector of bytes. - let encoded = value.get_encoded(); + let encoded = value.get_encoded().unwrap(); assert_eq!(encoded, bytes); } @@ -741,6 +737,7 @@ mod tests { } #[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] pub mod dummy; #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[cfg_attr( @@ -748,10 +745,14 @@ pub mod dummy; doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) )] pub mod poplar1; -#[cfg(feature = "prio2")] -#[cfg_attr(docsrs, doc(cfg(feature = "prio2")))] +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) +)] pub mod prio2; pub mod prio3; -#[cfg(test)] -mod prio3_test; +#[cfg(any(test, feature = "test-util"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub mod prio3_test; pub mod xof; diff --git a/third_party/rust/prio/src/vdaf/dummy.rs b/third_party/rust/prio/src/vdaf/dummy.rs index 507e7916bb..2bb0f96b8a 100644 --- a/third_party/rust/prio/src/vdaf/dummy.rs +++ b/third_party/rust/prio/src/vdaf/dummy.rs @@ -12,6 +12,9 @@ use crate::{ use rand::random; use std::{fmt::Debug, io::Cursor, sync::Arc}; +/// The Dummy VDAF does summation modulus 256 so we can predict aggregation results. +const MODULUS: u64 = u8::MAX as u64 + 1; + type ArcPrepInitFn = Arc<dyn Fn(&AggregationParam) -> Result<(), VdafError> + 'static + Send + Sync>; type ArcPrepStepFn = Arc< @@ -49,7 +52,9 @@ impl Vdaf { move |state| -> Result<PrepareTransition<Self, 0, 16>, VdafError> { let new_round = state.current_round + 1; if new_round == rounds { - Ok(PrepareTransition::Finish(OutputShare(state.input_share))) + Ok(PrepareTransition::Finish(OutputShare(u64::from( + state.input_share, + )))) } else { Ok(PrepareTransition::Continue( PrepareState { @@ -76,7 +81,7 @@ impl Vdaf { self } - /// Provide an alternate implementation of [`vdaf::Aggregator::prepare_step`]. + /// Provide an alternate implementation of [`vdaf::Aggregator::prepare_next`]. pub fn with_prep_step_fn< F: Fn(&PrepareState) -> Result<PrepareTransition<Self, 0, 16>, VdafError>, >( @@ -98,16 +103,18 @@ impl Default for Vdaf { } impl vdaf::Vdaf for Vdaf { - const ID: u32 = 0xFFFF0000; - type Measurement = u8; - type AggregateResult = u8; + type AggregateResult = u64; type AggregationParam = AggregationParam; type PublicShare = (); type InputShare = InputShare; type OutputShare = OutputShare; type AggregateShare = AggregateShare; + fn algorithm_id(&self) -> u32 { + 0xFFFF0000 + } + fn num_aggregators(&self) -> usize { 2 } @@ -155,7 +162,7 @@ impl vdaf::Aggregator<0, 16> for Vdaf { fn aggregate<M: IntoIterator<Item = Self::OutputShare>>( &self, - _: &Self::AggregationParam, + _aggregation_param: &Self::AggregationParam, output_shares: M, ) -> Result<Self::AggregateShare, VdafError> { let mut aggregate_share = AggregateShare(0); @@ -184,12 +191,28 @@ impl vdaf::Client<16> for Vdaf { } } +impl vdaf::Collector for Vdaf { + fn unshard<M: IntoIterator<Item = Self::AggregateShare>>( + &self, + aggregation_param: &Self::AggregationParam, + agg_shares: M, + _num_measurements: usize, + ) -> Result<Self::AggregateResult, VdafError> { + Ok(agg_shares + .into_iter() + .fold(0, |acc, share| (acc + share.0) % MODULUS) + // Sum in the aggregation parameter so that collections over the same measurements with + // varying parameters will yield predictable but distinct results. + + u64::from(aggregation_param.0)) + } +} + /// A dummy input share. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] pub struct InputShare(pub u8); impl Encode for InputShare { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { self.0.encode(bytes) } @@ -209,7 +232,7 @@ impl Decode for InputShare { pub struct AggregationParam(pub u8); impl Encode for AggregationParam { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { self.0.encode(bytes) } @@ -226,17 +249,17 @@ impl Decode for AggregationParam { /// Dummy output share. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct OutputShare(pub u8); +pub struct OutputShare(pub u64); impl Decode for OutputShare { fn decode(bytes: &mut Cursor<&[u8]>) -> Result<Self, CodecError> { - Ok(Self(u8::decode(bytes)?)) + Ok(Self(u64::decode(bytes)?)) } } impl Encode for OutputShare { - fn encode(&self, bytes: &mut Vec<u8>) { - self.0.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.0.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -252,9 +275,9 @@ pub struct PrepareState { } impl Encode for PrepareState { - fn encode(&self, bytes: &mut Vec<u8>) { - self.input_share.encode(bytes); - self.current_round.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.input_share.encode(bytes)?; + self.current_round.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -282,31 +305,30 @@ impl Aggregatable for AggregateShare { type OutputShare = OutputShare; fn merge(&mut self, other: &Self) -> Result<(), VdafError> { - self.0 += other.0; + self.0 = (self.0 + other.0) % MODULUS; Ok(()) } fn accumulate(&mut self, out_share: &Self::OutputShare) -> Result<(), VdafError> { - self.0 += u64::from(out_share.0); + self.0 = (self.0 + out_share.0) % MODULUS; Ok(()) } } impl From<OutputShare> for AggregateShare { fn from(out_share: OutputShare) -> Self { - Self(u64::from(out_share.0)) + Self(out_share.0) } } impl Decode for AggregateShare { fn decode(bytes: &mut Cursor<&[u8]>) -> Result<Self, CodecError> { - let val = u64::decode(bytes)?; - Ok(Self(val)) + Ok(Self(u64::decode(bytes)?)) } } impl Encode for AggregateShare { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { self.0.encode(bytes) } @@ -314,3 +336,86 @@ impl Encode for AggregateShare { self.0.encoded_len() } } + +/// Returns the aggregate result that the dummy VDAF would compute over the provided measurements, +/// for the provided aggregation parameter. +pub fn expected_aggregate_result<M>(aggregation_parameter: u8, measurements: M) -> u64 +where + M: IntoIterator<Item = u8>, +{ + (measurements.into_iter().map(u64::from).sum::<u64>()) % MODULUS + + u64::from(aggregation_parameter) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::vdaf::{test_utils::run_vdaf_sharded, Client}; + use rand::prelude::*; + + fn run_test(rounds: u32, aggregation_parameter: u8) { + let vdaf = Vdaf::new(rounds); + let mut verify_key = [0; 0]; + thread_rng().fill(&mut verify_key[..]); + let measurements = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; + + let mut sharded_measurements = Vec::new(); + for measurement in measurements { + let nonce = thread_rng().gen(); + let (public_share, input_shares) = vdaf.shard(&measurement, &nonce).unwrap(); + + sharded_measurements.push((public_share, nonce, input_shares)); + } + + let result = run_vdaf_sharded( + &vdaf, + &AggregationParam(aggregation_parameter), + sharded_measurements.clone(), + ) + .unwrap(); + assert_eq!( + result, + expected_aggregate_result(aggregation_parameter, measurements) + ); + } + + #[test] + fn single_round_agg_param_10() { + run_test(1, 10) + } + + #[test] + fn single_round_agg_param_20() { + run_test(1, 20) + } + + #[test] + fn single_round_agg_param_32() { + run_test(1, 32) + } + + #[test] + fn single_round_agg_param_u8_max() { + run_test(1, u8::MAX) + } + + #[test] + fn two_round_agg_param_10() { + run_test(2, 10) + } + + #[test] + fn two_round_agg_param_20() { + run_test(2, 20) + } + + #[test] + fn two_round_agg_param_32() { + run_test(2, 32) + } + + #[test] + fn two_round_agg_param_u8_max() { + run_test(2, u8::MAX) + } +} diff --git a/third_party/rust/prio/src/vdaf/poplar1.rs b/third_party/rust/prio/src/vdaf/poplar1.rs index e8591f2049..514ed39069 100644 --- a/third_party/rust/prio/src/vdaf/poplar1.rs +++ b/third_party/rust/prio/src/vdaf/poplar1.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-07]]. +//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ use crate::{ codec::{CodecError, Decode, Encode, ParameterizedDecode}, @@ -10,7 +10,7 @@ use crate::{ idpf::{Idpf, IdpfInput, IdpfOutputShare, IdpfPublicShare, IdpfValue, RingBufferCache}, prng::Prng, vdaf::{ - xof::{Seed, Xof, XofShake128}, + xof::{Seed, Xof, XofTurboShake128}, Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError, }, }; @@ -34,9 +34,9 @@ const DST_VERIFY_RANDOMNESS: u16 = 4; impl<P, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { /// Create an instance of [`Poplar1`]. The caller provides the bit length of each - /// measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]). + /// measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]). /// - /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ + /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ pub fn new(bits: usize) -> Self { Self { bits, @@ -45,12 +45,12 @@ impl<P, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { } } -impl Poplar1<XofShake128, 16> { - /// Create an instance of [`Poplar1`] using [`XofShake128`]. The caller provides the bit length of - /// each measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]). +impl Poplar1<XofTurboShake128, 16> { + /// Create an instance of [`Poplar1`] using [`XofTurboShake128`]. The caller provides the bit length of + /// each measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]). /// - /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ - pub fn new_shake128(bits: usize) -> Self { + /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ + pub fn new_turboshake128(bits: usize) -> Self { Poplar1::new(bits) } } @@ -65,6 +65,7 @@ pub struct Poplar1<P, const SEED_SIZE: usize> { impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { /// Construct a `Prng` with the given seed and info-string suffix. fn init_prng<I, B, F>( + &self, seed: &[u8; SEED_SIZE], usage: u16, binder_chunks: I, @@ -75,7 +76,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { P: Xof<SEED_SIZE>, F: FieldElement, { - let mut xof = P::init(seed, &Self::domain_separation_tag(usage)); + let mut xof = P::init(seed, &self.domain_separation_tag(usage)); for binder_chunk in binder_chunks.into_iter() { xof.update(binder_chunk.as_ref()); } @@ -156,15 +157,15 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Poplar1InputShare<SEED_SIZE> { } impl<const SEED_SIZE: usize> Encode for Poplar1InputShare<SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { - self.idpf_key.encode(bytes); - self.corr_seed.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.idpf_key.encode(bytes)?; + self.corr_seed.encode(bytes)?; for corr in self.corr_inner.iter() { - corr[0].encode(bytes); - corr[1].encode(bytes); + corr[0].encode(bytes)?; + corr[1].encode(bytes)?; } - self.corr_leaf[0].encode(bytes); - self.corr_leaf[1].encode(bytes); + self.corr_leaf[0].encode(bytes)?; + self.corr_leaf[1].encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -219,7 +220,7 @@ impl ConstantTimeEq for Poplar1PrepareState { } impl Encode for Poplar1PrepareState { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { self.0.encode(bytes) } @@ -268,15 +269,15 @@ impl ConstantTimeEq for PrepareStateVariant { } impl Encode for PrepareStateVariant { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { match self { PrepareStateVariant::Inner(prep_state) => { - 0u8.encode(bytes); - prep_state.encode(bytes); + 0u8.encode(bytes)?; + prep_state.encode(bytes) } PrepareStateVariant::Leaf(prep_state) => { - 1u8.encode(bytes); - prep_state.encode(bytes); + 1u8.encode(bytes)?; + prep_state.encode(bytes) } } } @@ -342,16 +343,17 @@ impl<F> Debug for PrepareState<F> { } impl<F: FieldElement> Encode for PrepareState<F> { - fn encode(&self, bytes: &mut Vec<u8>) { - self.sketch.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.sketch.encode(bytes)?; // `expect` safety: output_share's length is the same as the number of prefixes; the number // of prefixes is capped at 2^32-1. u32::try_from(self.output_share.len()) .expect("Couldn't convert output_share length to u32") - .encode(bytes); + .encode(bytes)?; for elem in &self.output_share { - elem.encode(bytes); + elem.encode(bytes)?; } + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -430,14 +432,14 @@ impl<F: ConstantTimeEq> ConstantTimeEq for SketchState<F> { } impl<F: FieldElement> Encode for SketchState<F> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { match self { SketchState::RoundOne { A_share, B_share, .. } => { - 0u8.encode(bytes); - A_share.encode(bytes); - B_share.encode(bytes); + 0u8.encode(bytes)?; + A_share.encode(bytes)?; + B_share.encode(bytes) } SketchState::RoundTwo => 1u8.encode(bytes), } @@ -519,19 +521,19 @@ enum PrepareMessageVariant { } impl Encode for Poplar1PrepareMessage { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { match self.0 { PrepareMessageVariant::SketchInner(vec) => { - vec[0].encode(bytes); - vec[1].encode(bytes); - vec[2].encode(bytes); + vec[0].encode(bytes)?; + vec[1].encode(bytes)?; + vec[2].encode(bytes) } PrepareMessageVariant::SketchLeaf(vec) => { - vec[0].encode(bytes); - vec[1].encode(bytes); - vec[2].encode(bytes); + vec[0].encode(bytes)?; + vec[1].encode(bytes)?; + vec[2].encode(bytes) } - PrepareMessageVariant::Done => (), + PrepareMessageVariant::Done => Ok(()), } } @@ -614,17 +616,19 @@ impl ConstantTimeEq for Poplar1FieldVec { } impl Encode for Poplar1FieldVec { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { match self { Self::Inner(ref data) => { for elem in data { - elem.encode(bytes); + elem.encode(bytes)?; } + Ok(()) } Self::Leaf(ref data) => { for elem in data { - elem.encode(bytes); + elem.encode(bytes)?; } + Ok(()) } } } @@ -769,11 +773,11 @@ impl Poplar1AggregationParam { } impl Encode for Poplar1AggregationParam { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { // Okay to unwrap because `try_from_prefixes()` checks this conversion succeeds. let prefix_count = u32::try_from(self.prefixes.len()).unwrap(); - self.level.encode(bytes); - prefix_count.encode(bytes); + self.level.encode(bytes)?; + prefix_count.encode(bytes)?; // The encoding of the prefixes is defined by treating the IDPF indices as integers, // shifting and ORing them together, and encoding the resulting arbitrary precision integer @@ -799,6 +803,7 @@ impl Encode for Poplar1AggregationParam { let mut packed = packed.into_vec(); packed.reverse(); bytes.append(&mut packed); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -839,7 +844,6 @@ impl Decode for Poplar1AggregationParam { } impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Vdaf for Poplar1<P, SEED_SIZE> { - const ID: u32 = 0x00001000; type Measurement = IdpfInput; type AggregateResult = Vec<u64>; type AggregationParam = Poplar1AggregationParam; @@ -848,6 +852,10 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Vdaf for Poplar1<P, SEED_SIZE> { type OutputShare = Poplar1FieldVec; type AggregateShare = Poplar1FieldVec; + fn algorithm_id(&self) -> u32 { + 0x00001000 + } + fn num_aggregators(&self) -> usize { 2 } @@ -870,7 +878,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { // Generate the authenticator for each inner level of the IDPF tree. let mut prng = - Self::init_prng::<_, _, Field64>(&poplar_random[2], DST_SHARD_RANDOMNESS, [&[]]); + self.init_prng::<_, _, Field64>(&poplar_random[2], DST_SHARD_RANDOMNESS, [nonce]); let auth_inner: Vec<Field64> = (0..self.bits - 1).map(|_| prng.get()).collect(); // Generate the authenticator for the last level of the IDPF tree (i.e., the leaves). @@ -900,12 +908,12 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { let corr_seed_0 = &poplar_random[0]; let corr_seed_1 = &poplar_random[1]; let mut prng = prng.into_new_field::<Field64>(); - let mut corr_prng_0 = Self::init_prng::<_, _, Field64>( + let mut corr_prng_0 = self.init_prng::<_, _, Field64>( corr_seed_0, DST_CORR_INNER, [[0].as_slice(), nonce.as_slice()], ); - let mut corr_prng_1 = Self::init_prng::<_, _, Field64>( + let mut corr_prng_1 = self.init_prng::<_, _, Field64>( corr_seed_1, DST_CORR_INNER, [[1].as_slice(), nonce.as_slice()], @@ -921,12 +929,12 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { // Generate the correlated randomness for the leaf nodes. let mut prng = prng.into_new_field::<Field255>(); - let mut corr_prng_0 = Self::init_prng::<_, _, Field255>( + let mut corr_prng_0 = self.init_prng::<_, _, Field255>( corr_seed_0, DST_CORR_LEAF, [[0].as_slice(), nonce.as_slice()], ); - let mut corr_prng_1 = Self::init_prng::<_, _, Field255>( + let mut corr_prng_1 = self.init_prng::<_, _, Field255>( corr_seed_1, DST_CORR_LEAF, [[1].as_slice(), nonce.as_slice()], @@ -952,6 +960,60 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Poplar1<P, SEED_SIZE> { ], )) } + + /// Evaluate the IDPF at the given prefixes and compute the Aggregator's share of the sketch. + #[allow(clippy::too_many_arguments)] + fn eval_and_sketch<F>( + &self, + verify_key: &[u8; SEED_SIZE], + agg_id: usize, + nonce: &[u8; 16], + agg_param: &Poplar1AggregationParam, + public_share: &Poplar1PublicShare, + idpf_key: &Seed<16>, + corr_prng: &mut Prng<F, P::SeedStream>, + ) -> Result<(Vec<F>, Vec<F>), VdafError> + where + P: Xof<SEED_SIZE>, + F: FieldElement, + Poplar1IdpfValue<F>: + From<IdpfOutputShare<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>>, + { + let mut verify_prng = self.init_prng( + verify_key, + DST_VERIFY_RANDOMNESS, + [nonce.as_slice(), agg_param.level.to_be_bytes().as_slice()], + ); + + let mut out_share = Vec::with_capacity(agg_param.prefixes.len()); + let mut sketch_share = vec![ + corr_prng.get(), // a_share + corr_prng.get(), // b_share + corr_prng.get(), // c_share + ]; + + let mut idpf_eval_cache = RingBufferCache::new(agg_param.prefixes.len()); + let idpf = Idpf::<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>::new((), ()); + for prefix in agg_param.prefixes.iter() { + let share = Poplar1IdpfValue::<F>::from(idpf.eval( + agg_id, + public_share, + idpf_key, + prefix, + nonce, + &mut idpf_eval_cache, + )?); + + let r = verify_prng.get(); + let checked_data_share = share.0[0] * r; + sketch_share[0] += checked_data_share; + sketch_share[1] += checked_data_share * r; + sketch_share[2] += share.0[1] * r; + out_share.push(share.0[0]); + } + + Ok((out_share, sketch_share)) + } } impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Client<16> for Poplar1<P, SEED_SIZE> { @@ -1000,7 +1062,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16> }; if usize::from(agg_param.level) < self.bits - 1 { - let mut corr_prng = Self::init_prng::<_, _, Field64>( + let mut corr_prng = self.init_prng::<_, _, Field64>( input_share.corr_seed.as_ref(), DST_CORR_INNER, [[agg_id as u8].as_slice(), nonce.as_slice()], @@ -1011,7 +1073,7 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16> corr_prng.get(); } - let (output_share, sketch_share) = eval_and_sketch::<P, Field64, SEED_SIZE>( + let (output_share, sketch_share) = self.eval_and_sketch::<Field64>( verify_key, agg_id, nonce, @@ -1033,13 +1095,13 @@ impl<P: Xof<SEED_SIZE>, const SEED_SIZE: usize> Aggregator<SEED_SIZE, 16> Poplar1FieldVec::Inner(sketch_share), )) } else { - let corr_prng = Self::init_prng::<_, _, Field255>( + let corr_prng = self.init_prng::<_, _, Field255>( input_share.corr_seed.as_ref(), DST_CORR_LEAF, [[agg_id as u8].as_slice(), nonce.as_slice()], ); - let (output_share, sketch_share) = eval_and_sketch::<P, Field255, SEED_SIZE>( + let (output_share, sketch_share) = self.eval_and_sketch::<Field255>( verify_key, agg_id, nonce, @@ -1257,59 +1319,6 @@ fn compute_next_corr_shares<F: FieldElement + From<u64>, S: RngCore>( (corr_0, corr_1) } -/// Evaluate the IDPF at the given prefixes and compute the Aggregator's share of the sketch. -fn eval_and_sketch<P, F, const SEED_SIZE: usize>( - verify_key: &[u8; SEED_SIZE], - agg_id: usize, - nonce: &[u8; 16], - agg_param: &Poplar1AggregationParam, - public_share: &Poplar1PublicShare, - idpf_key: &Seed<16>, - corr_prng: &mut Prng<F, P::SeedStream>, -) -> Result<(Vec<F>, Vec<F>), VdafError> -where - P: Xof<SEED_SIZE>, - F: FieldElement, - Poplar1IdpfValue<F>: - From<IdpfOutputShare<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>>, -{ - // TODO(cjpatton) spec: Consider not encoding the prefixes here. - let mut verify_prng = Poplar1::<P, SEED_SIZE>::init_prng( - verify_key, - DST_VERIFY_RANDOMNESS, - [nonce.as_slice(), agg_param.level.to_be_bytes().as_slice()], - ); - - let mut out_share = Vec::with_capacity(agg_param.prefixes.len()); - let mut sketch_share = vec![ - corr_prng.get(), // a_share - corr_prng.get(), // b_share - corr_prng.get(), // c_share - ]; - - let mut idpf_eval_cache = RingBufferCache::new(agg_param.prefixes.len()); - let idpf = Idpf::<Poplar1IdpfValue<Field64>, Poplar1IdpfValue<Field255>>::new((), ()); - for prefix in agg_param.prefixes.iter() { - let share = Poplar1IdpfValue::<F>::from(idpf.eval( - agg_id, - public_share, - idpf_key, - prefix, - nonce, - &mut idpf_eval_cache, - )?); - - let r = verify_prng.get(); - let checked_data_share = share.0[0] * r; - sketch_share[0] += checked_data_share; - sketch_share[1] += checked_data_share * r; - sketch_share[2] += share.0[1] * r; - out_share.push(share.0[0]); - } - - Ok((out_share, sketch_share)) -} - /// Compute the Aggregator's share of the sketch verifier. The shares should sum to zero. #[allow(non_snake_case)] fn finish_sketch<F: FieldElement>( @@ -1447,9 +1456,9 @@ impl<F> Encode for Poplar1IdpfValue<F> where F: FieldElement, { - fn encode(&self, bytes: &mut Vec<u8>) { - self.0[0].encode(bytes); - self.0[1].encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.0[0].encode(bytes)?; + self.0[1].encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -1491,7 +1500,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::vdaf::{equality_comparison_test, run_vdaf_prepare}; + use crate::vdaf::{equality_comparison_test, test_utils::run_vdaf_prepare}; use assert_matches::assert_matches; use rand::prelude::*; use serde::Deserialize; @@ -1628,7 +1637,7 @@ mod tests { #[test] fn shard_prepare() { let mut rng = thread_rng(); - let vdaf = Poplar1::new_shake128(64); + let vdaf = Poplar1::new_turboshake128(64); let verify_key = rng.gen(); let input = IdpfInput::from_bytes(b"12341324"); let nonce = rng.gen(); @@ -1672,7 +1681,7 @@ mod tests { fn heavy_hitters() { let mut rng = thread_rng(); let verify_key = rng.gen(); - let vdaf = Poplar1::new_shake128(8); + let vdaf = Poplar1::new_turboshake128(8); run_heavy_hitters( &vdaf, @@ -1699,7 +1708,7 @@ mod tests { corr_leaf: [Field255::one(), <Field255 as FieldElement>::zero()], }; assert_eq!( - input_share.get_encoded().len(), + input_share.get_encoded().unwrap().len(), input_share.encoded_len().unwrap() ); @@ -1710,7 +1719,7 @@ mod tests { Field64::one(), ])); assert_eq!( - prep_msg.get_encoded().len(), + prep_msg.get_encoded().unwrap().len(), prep_msg.encoded_len().unwrap() ); let prep_msg = Poplar1PrepareMessage(PrepareMessageVariant::SketchLeaf([ @@ -1719,24 +1728,24 @@ mod tests { Field255::one(), ])); assert_eq!( - prep_msg.get_encoded().len(), + prep_msg.get_encoded().unwrap().len(), prep_msg.encoded_len().unwrap() ); let prep_msg = Poplar1PrepareMessage(PrepareMessageVariant::Done); assert_eq!( - prep_msg.get_encoded().len(), + prep_msg.get_encoded().unwrap().len(), prep_msg.encoded_len().unwrap() ); // Field vector variants. let field_vec = Poplar1FieldVec::Inner(vec![Field64::one(); 23]); assert_eq!( - field_vec.get_encoded().len(), + field_vec.get_encoded().unwrap().len(), field_vec.encoded_len().unwrap() ); let field_vec = Poplar1FieldVec::Leaf(vec![Field255::one(); 23]); assert_eq!( - field_vec.get_encoded().len(), + field_vec.get_encoded().unwrap().len(), field_vec.encoded_len().unwrap() ); @@ -1747,7 +1756,7 @@ mod tests { ])) .unwrap(); assert_eq!( - agg_param.get_encoded().len(), + agg_param.get_encoded().unwrap().len(), agg_param.encoded_len().unwrap() ); let agg_param = Poplar1AggregationParam::try_from_prefixes(Vec::from([ @@ -1756,14 +1765,14 @@ mod tests { ])) .unwrap(); assert_eq!( - agg_param.get_encoded().len(), + agg_param.get_encoded().unwrap().len(), agg_param.encoded_len().unwrap() ); } #[test] fn round_trip_prepare_state() { - let vdaf = Poplar1::new_shake128(1); + let vdaf = Poplar1::new_turboshake128(1); for (agg_id, prep_state) in [ ( 0, @@ -1862,7 +1871,7 @@ mod tests { })), ), ] { - let encoded_prep_state = prep_state.get_encoded(); + let encoded_prep_state = prep_state.get_encoded().unwrap(); assert_eq!(prep_state.encoded_len(), Some(encoded_prep_state.len())); let decoded_prep_state = Poplar1PrepareState::get_decoded_with_param(&(&vdaf, agg_id), &encoded_prep_state) @@ -1947,7 +1956,7 @@ mod tests { ), ] { let agg_param = Poplar1AggregationParam::try_from_prefixes(prefixes).unwrap(); - let encoded = agg_param.get_encoded(); + let encoded = agg_param.get_encoded().unwrap(); assert_eq!(encoded, reference_encoding); let decoded = Poplar1AggregationParam::get_decoded(reference_encoding).unwrap(); assert_eq!(decoded, agg_param); @@ -2037,7 +2046,7 @@ mod tests { } // Shard measurement. - let poplar = Poplar1::new_shake128(test_vector.bits); + let poplar = Poplar1::new_turboshake128(test_vector.bits); let (public_share, input_shares) = poplar .shard_with_random(&measurement, &nonce, &idpf_random, &poplar_random) .unwrap(); @@ -2118,14 +2127,17 @@ mod tests { Poplar1PublicShare::get_decoded_with_param(&poplar, prep.public_share.as_ref()) .unwrap() ); - assert_eq!(&public_share.get_encoded(), prep.public_share.as_ref()); + assert_eq!( + &public_share.get_encoded().unwrap(), + prep.public_share.as_ref() + ); assert_eq!( input_shares[0], Poplar1InputShare::get_decoded_with_param(&(&poplar, 0), prep.input_shares[0].as_ref()) .unwrap() ); assert_eq!( - &input_shares[0].get_encoded(), + &input_shares[0].get_encoded().unwrap(), prep.input_shares[0].as_ref() ); assert_eq!( @@ -2134,7 +2146,7 @@ mod tests { .unwrap() ); assert_eq!( - &input_shares[1].get_encoded(), + &input_shares[1].get_encoded().unwrap(), prep.input_shares[1].as_ref() ); assert_eq!( @@ -2146,7 +2158,7 @@ mod tests { .unwrap() ); assert_eq!( - &init_prep_share_0.get_encoded(), + &init_prep_share_0.get_encoded().unwrap(), prep.prep_shares[0][0].as_ref() ); assert_eq!( @@ -2158,7 +2170,7 @@ mod tests { .unwrap() ); assert_eq!( - &init_prep_share_1.get_encoded(), + &init_prep_share_1.get_encoded().unwrap(), prep.prep_shares[0][1].as_ref() ); assert_eq!( @@ -2169,7 +2181,10 @@ mod tests { ) .unwrap() ); - assert_eq!(&r1_prep_msg.get_encoded(), prep.prep_messages[0].as_ref()); + assert_eq!( + &r1_prep_msg.get_encoded().unwrap(), + prep.prep_messages[0].as_ref() + ); assert_eq!( r1_prep_share_0, @@ -2180,7 +2195,7 @@ mod tests { .unwrap() ); assert_eq!( - &r1_prep_share_0.get_encoded(), + &r1_prep_share_0.get_encoded().unwrap(), prep.prep_shares[1][0].as_ref() ); assert_eq!( @@ -2192,7 +2207,7 @@ mod tests { .unwrap() ); assert_eq!( - &r1_prep_share_1.get_encoded(), + &r1_prep_share_1.get_encoded().unwrap(), prep.prep_shares[1][1].as_ref() ); assert_eq!( @@ -2203,7 +2218,10 @@ mod tests { ) .unwrap() ); - assert_eq!(&r2_prep_msg.get_encoded(), prep.prep_messages[1].as_ref()); + assert_eq!( + &r2_prep_msg.get_encoded().unwrap(), + prep.prep_messages[1].as_ref() + ); for (out_share, expected_out_share) in [ (out_share_0, &prep.out_shares[0]), (out_share_1, &prep.out_shares[1]), @@ -2212,13 +2230,13 @@ mod tests { Poplar1FieldVec::Inner(vec) => { assert_eq!(vec.len(), expected_out_share.len()); for (element, expected) in vec.iter().zip(expected_out_share.iter()) { - assert_eq!(&element.get_encoded(), expected.as_ref()); + assert_eq!(&element.get_encoded().unwrap(), expected.as_ref()); } } Poplar1FieldVec::Leaf(vec) => { assert_eq!(vec.len(), expected_out_share.len()); for (element, expected) in vec.iter().zip(expected_out_share.iter()) { - assert_eq!(&element.get_encoded(), expected.as_ref()); + assert_eq!(&element.get_encoded().unwrap(), expected.as_ref()); } } }; @@ -2233,7 +2251,7 @@ mod tests { ); assert_eq!( - &agg_share_0.get_encoded(), + &agg_share_0.get_encoded().unwrap(), test_vector.agg_shares[0].as_ref() ); assert_eq!( @@ -2245,7 +2263,7 @@ mod tests { .unwrap() ); assert_eq!( - &agg_share_1.get_encoded(), + &agg_share_1.get_encoded().unwrap(), test_vector.agg_shares[1].as_ref() ); assert_eq!(agg_result, test_vector.agg_result); @@ -2253,22 +2271,22 @@ mod tests { #[test] fn test_vec_poplar1_0() { - check_test_vec(include_str!("test_vec/07/Poplar1_0.json")); + check_test_vec(include_str!("test_vec/08/Poplar1_0.json")); } #[test] fn test_vec_poplar1_1() { - check_test_vec(include_str!("test_vec/07/Poplar1_1.json")); + check_test_vec(include_str!("test_vec/08/Poplar1_1.json")); } #[test] fn test_vec_poplar1_2() { - check_test_vec(include_str!("test_vec/07/Poplar1_2.json")); + check_test_vec(include_str!("test_vec/08/Poplar1_2.json")); } #[test] fn test_vec_poplar1_3() { - check_test_vec(include_str!("test_vec/07/Poplar1_3.json")); + check_test_vec(include_str!("test_vec/08/Poplar1_3.json")); } #[test] diff --git a/third_party/rust/prio/src/vdaf/prio2.rs b/third_party/rust/prio/src/vdaf/prio2.rs index 4669c47d00..ba725d90d7 100644 --- a/third_party/rust/prio/src/vdaf/prio2.rs +++ b/third_party/rust/prio/src/vdaf/prio2.rs @@ -88,8 +88,13 @@ impl Prio2 { ) .map_err(|e| VdafError::Uncategorized(e.to_string()))?; + let truncated_share = match input_share { + Share::Leader(data) => Share::Leader(data[..self.input_len].to_vec()), + Share::Helper(seed) => Share::Helper(seed.clone()), + }; + Ok(( - Prio2PrepareState(input_share.truncated(self.input_len)), + Prio2PrepareState(truncated_share), Prio2PrepareShare(verifier_share), )) } @@ -117,7 +122,6 @@ impl Prio2 { } impl Vdaf for Prio2 { - const ID: u32 = 0xFFFF0000; type Measurement = Vec<u32>; type AggregateResult = Vec<u32>; type AggregationParam = (); @@ -126,6 +130,10 @@ impl Vdaf for Prio2 { type OutputShare = OutputShare<FieldPrio2>; type AggregateShare = AggregateShare<FieldPrio2>; + fn algorithm_id(&self) -> u32 { + 0xFFFF0000 + } + fn num_aggregators(&self) -> usize { // Prio2 can easily be extended to support more than two Aggregators. 2 @@ -184,8 +192,8 @@ impl ConstantTimeEq for Prio2PrepareState { } impl Encode for Prio2PrepareState { - fn encode(&self, bytes: &mut Vec<u8>) { - self.0.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.0.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -213,10 +221,10 @@ impl<'a> ParameterizedDecode<(&'a Prio2, usize)> for Prio2PrepareState { pub struct Prio2PrepareShare(v2_server::VerificationMessage<FieldPrio2>); impl Encode for Prio2PrepareShare { - fn encode(&self, bytes: &mut Vec<u8>) { - self.0.f_r.encode(bytes); - self.0.g_r.encode(bytes); - self.0.h_r.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.0.f_r.encode(bytes)?; + self.0.g_r.encode(bytes)?; + self.0.h_r.encode(bytes) } fn encoded_len(&self) -> Option<usize> { @@ -388,7 +396,7 @@ mod tests { use super::*; use crate::vdaf::{ equality_comparison_test, fieldvec_roundtrip_test, prio2::test_vector::Priov2TestVector, - run_vdaf, + test_utils::run_vdaf, }; use assert_matches::assert_matches; use rand::prelude::*; @@ -434,7 +442,7 @@ mod tests { ) .unwrap(); - let encoded_prepare_state = prepare_state.get_encoded(); + let encoded_prepare_state = prepare_state.get_encoded().unwrap(); let decoded_prepare_state = Prio2PrepareState::get_decoded_with_param( &(&prio2, agg_id), &encoded_prepare_state, @@ -446,7 +454,7 @@ mod tests { encoded_prepare_state.len() ); - let encoded_prepare_share = prepare_share.get_encoded(); + let encoded_prepare_share = prepare_share.get_encoded().unwrap(); let decoded_prepare_share = Prio2PrepareShare::get_decoded_with_param(&prepare_state, &encoded_prepare_share) .expect("failed to decode prepare share"); diff --git a/third_party/rust/prio/src/vdaf/prio2/client.rs b/third_party/rust/prio/src/vdaf/prio2/client.rs index dbce39ee3f..9515601d8a 100644 --- a/third_party/rust/prio/src/vdaf/prio2/client.rs +++ b/third_party/rust/prio/src/vdaf/prio2/client.rs @@ -4,10 +4,14 @@ //! Primitives for the Prio2 client. use crate::{ - field::{FftFriendlyFieldElement, FieldError}, + codec::CodecError, + field::FftFriendlyFieldElement, polynomial::{poly_fft, PolyAuxMemory}, prng::{Prng, PrngError}, - vdaf::{xof::SeedStreamAes128, VdafError}, + vdaf::{ + xof::{Seed, SeedStreamAes128}, + VdafError, + }, }; use std::convert::TryFrom; @@ -32,9 +36,9 @@ pub enum SerializeError { /// Emitted by `unpack_proof[_mut]` if the serialized share+proof has the wrong length #[error("serialized input has wrong length")] UnpackInputSizeMismatch, - /// Finite field operation error. - #[error("finite field operation error")] - Field(#[from] FieldError), + /// Codec error. + #[error(transparent)] + Codec(#[from] CodecError), } #[derive(Debug)] @@ -63,7 +67,7 @@ impl<F: FftFriendlyFieldElement> ClientMemory<F> { } Ok(Self { - prng: Prng::new()?, + prng: Prng::from_prio2_seed(Seed::<32>::generate()?.as_ref()), points_f: vec![F::zero(); n], points_g: vec![F::zero(); n], evals_f: vec![F::zero(); 2 * n], diff --git a/third_party/rust/prio/src/vdaf/prio2/server.rs b/third_party/rust/prio/src/vdaf/prio2/server.rs index 11c161babf..9d2871c867 100644 --- a/third_party/rust/prio/src/vdaf/prio2/server.rs +++ b/third_party/rust/prio/src/vdaf/prio2/server.rs @@ -101,9 +101,13 @@ pub(crate) fn is_valid_share<F: FftFriendlyFieldElement>( #[cfg(test)] mod test_util { use crate::{ + codec::ParameterizedDecode, field::{merge_vector, FftFriendlyFieldElement}, prng::Prng, - vdaf::prio2::client::proof_length, + vdaf::{ + prio2::client::{proof_length, SerializeError}, + Share, ShareDecodingParameter, + }, }; use super::{generate_verification_message, is_valid_share, ServerError, VerificationMessage}; @@ -133,17 +137,17 @@ mod test_util { /// Deserialize fn deserialize_share(&self, share: &[u8]) -> Result<Vec<F>, ServerError> { let len = proof_length(self.dimension); - Ok(if self.is_first_server { - F::byte_slice_into_vec(share)? + let decoding_parameter = if self.is_first_server { + ShareDecodingParameter::Leader(len) } else { - if share.len() != 32 { - return Err(ServerError::ShareLength); - } - - Prng::from_prio2_seed(&share.try_into().unwrap()) - .take(len) - .collect() - }) + ShareDecodingParameter::Helper + }; + let decoded_share = Share::get_decoded_with_param(&decoding_parameter, share) + .map_err(SerializeError::from)?; + match decoded_share { + Share::Leader(vec) => Ok(vec), + Share::Helper(seed) => Ok(Prng::from_prio2_seed(&seed.0).take(len).collect()), + } } /// Generate verification message from an encrypted share @@ -194,14 +198,19 @@ mod test_util { mod tests { use super::*; use crate::{ - codec::Encode, + codec::{Encode, ParameterizedDecode}, field::{FieldElement, FieldPrio2}, prng::Prng, vdaf::{ - prio2::{client::unpack_proof_mut, server::test_util::Server, Prio2}, - Client, + prio2::{ + client::{proof_length, unpack_proof_mut}, + server::test_util::Server, + Prio2, + }, + Client, Share, ShareDecodingParameter, }, }; + use assert_matches::assert_matches; use rand::{random, Rng}; fn secret_share(share: &mut [FieldPrio2]) -> Vec<FieldPrio2> { @@ -286,10 +295,13 @@ mod tests { let vdaf = Prio2::new(dim).unwrap(); let (_, shares) = vdaf.shard(&data, &[0; 16]).unwrap(); - let share1_original = shares[0].get_encoded(); - let share2 = shares[1].get_encoded(); + let share1_original = shares[0].get_encoded().unwrap(); + let share2 = shares[1].get_encoded().unwrap(); - let mut share1_field = FieldPrio2::byte_slice_into_vec(&share1_original).unwrap(); + let mut share1_field: Vec<FieldPrio2> = assert_matches!( + Share::get_decoded_with_param(&ShareDecodingParameter::<32>::Leader(proof_length(dim)), &share1_original), + Ok(Share::Leader(vec)) => vec + ); let unpacked_share1 = unpack_proof_mut(&mut share1_field, dim).unwrap(); let one = FieldPrio2::from(1); @@ -304,7 +316,9 @@ mod tests { }; // reserialize altered share1 - let share1_modified = FieldPrio2::slice_into_byte_vec(&share1_field); + let share1_modified = Share::<FieldPrio2, 32>::Leader(share1_field) + .get_encoded() + .unwrap(); let mut prng = Prng::from_prio2_seed(&random()); let eval_at = vdaf.choose_eval_at(&mut prng); diff --git a/third_party/rust/prio/src/vdaf/prio2/test_vector.rs b/third_party/rust/prio/src/vdaf/prio2/test_vector.rs index ae2b8b0f9d..114b437b55 100644 --- a/third_party/rust/prio/src/vdaf/prio2/test_vector.rs +++ b/third_party/rust/prio/src/vdaf/prio2/test_vector.rs @@ -48,9 +48,16 @@ mod base64 { //! instead of an array of an array of integers when serializing to JSON. // // Thank you, Alice! https://users.rust-lang.org/t/serialize-a-vec-u8-to-json-as-base64/57781/2 - use crate::field::{FieldElement, FieldPrio2}; + use crate::{ + codec::ParameterizedDecode, + field::{encode_fieldvec, FieldElement, FieldPrio2}, + vdaf::{Share, ShareDecodingParameter}, + }; + use assert_matches::assert_matches; use base64::{engine::Engine, prelude::BASE64_STANDARD}; - use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; + use serde::{ + de::Error as _, ser::Error as _, Deserialize, Deserializer, Serialize, Serializer, + }; pub fn serialize_bytes<S: Serializer>(v: &[Vec<u8>], s: S) -> Result<S::Ok, S::Error> { let base64_vec = v @@ -63,21 +70,28 @@ mod base64 { pub fn deserialize_bytes<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<Vec<u8>>, D::Error> { <Vec<String>>::deserialize(d)? .iter() - .map(|s| BASE64_STANDARD.decode(s.as_bytes()).map_err(Error::custom)) + .map(|s| { + BASE64_STANDARD + .decode(s.as_bytes()) + .map_err(D::Error::custom) + }) .collect() } pub fn serialize_field<S: Serializer>(v: &[FieldPrio2], s: S) -> Result<S::Ok, S::Error> { - String::serialize( - &BASE64_STANDARD.encode(FieldPrio2::slice_into_byte_vec(v)), - s, - ) + let mut bytes = Vec::new(); + encode_fieldvec(v, &mut bytes).map_err(S::Error::custom)?; + String::serialize(&BASE64_STANDARD.encode(&bytes), s) } pub fn deserialize_field<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<FieldPrio2>, D::Error> { let bytes = BASE64_STANDARD .decode(String::deserialize(d)?.as_bytes()) - .map_err(Error::custom)?; - FieldPrio2::byte_slice_into_vec(&bytes).map_err(Error::custom) + .map_err(D::Error::custom)?; + let decoding_parameter = + ShareDecodingParameter::<32>::Leader(bytes.len() / FieldPrio2::ENCODED_SIZE); + let share = Share::<FieldPrio2, 32>::get_decoded_with_param(&decoding_parameter, &bytes) + .map_err(D::Error::custom)?; + assert_matches!(share, Share::Leader(vec) => Ok(vec)) } } diff --git a/third_party/rust/prio/src/vdaf/prio3.rs b/third_party/rust/prio/src/vdaf/prio3.rs index 4a7cdefb84..084f87f411 100644 --- a/third_party/rust/prio/src/vdaf/prio3.rs +++ b/third_party/rust/prio/src/vdaf/prio3.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-07]]. +//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-08]]. //! //! **WARNING:** This code has not undergone significant security analysis. Use at your own risk. //! @@ -9,7 +9,7 @@ //! 2019 [[BBCG+19]], that lead to substantial improvements in terms of run time and communication //! cost. The security of the construction was analyzed in [[DPRS23]]. //! -//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-07]] into +//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-08]] into //! a VDAF. The base type, [`Prio3`], supports a wide variety of aggregation functions, some of //! which are instantiated here: //! @@ -20,14 +20,14 @@ //! //! Additional types can be constructed from [`Prio3`] as needed. //! -//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-07]]. +//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-08]]. //! //! [BBCG+19]: https://ia.cr/2019/188 //! [CGB17]: https://crypto.stanford.edu/prio/ //! [DPRS23]: https://ia.cr/2023/130 -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ -use super::xof::XofShake128; +use super::xof::XofTurboShake128; #[cfg(feature = "experimental")] use super::AggregatorWithNoise; use crate::codec::{CodecError, Decode, Encode, ParameterizedDecode}; @@ -72,19 +72,19 @@ const DST_JOINT_RAND_SEED: u16 = 6; const DST_JOINT_RAND_PART: u16 = 7; /// The count type. Each measurement is an integer in `[0,2)` and the aggregate result is the sum. -pub type Prio3Count = Prio3<Count<Field64>, XofShake128, 16>; +pub type Prio3Count = Prio3<Count<Field64>, XofTurboShake128, 16>; impl Prio3Count { /// Construct an instance of Prio3Count with the given number of aggregators. pub fn new_count(num_aggregators: u8) -> Result<Self, VdafError> { - Prio3::new(num_aggregators, Count::new()) + Prio3::new(num_aggregators, 1, 0x00000000, Count::new()) } } /// The count-vector type. Each measurement is a vector of integers in `[0,2^bits)` and the /// aggregate is the element-wise sum. pub type Prio3SumVec = - Prio3<SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>, XofShake128, 16>; + Prio3<SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>, XofTurboShake128, 16>; impl Prio3SumVec { /// Construct an instance of Prio3SumVec with the given number of aggregators. `bits` defines @@ -96,7 +96,12 @@ impl Prio3SumVec { len: usize, chunk_length: usize, ) -> Result<Self, VdafError> { - Prio3::new(num_aggregators, SumVec::new(bits, len, chunk_length)?) + Prio3::new( + num_aggregators, + 1, + 0x00000002, + SumVec::new(bits, len, chunk_length)?, + ) } } @@ -104,8 +109,11 @@ impl Prio3SumVec { /// time. Note that the improvement is only noticeable for very large input lengths. #[cfg(feature = "multithreaded")] #[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))] -pub type Prio3SumVecMultithreaded = - Prio3<SumVec<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, XofShake128, 16>; +pub type Prio3SumVecMultithreaded = Prio3< + SumVec<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, + XofTurboShake128, + 16, +>; #[cfg(feature = "multithreaded")] impl Prio3SumVecMultithreaded { @@ -118,13 +126,18 @@ impl Prio3SumVecMultithreaded { len: usize, chunk_length: usize, ) -> Result<Self, VdafError> { - Prio3::new(num_aggregators, SumVec::new(bits, len, chunk_length)?) + Prio3::new( + num_aggregators, + 1, + 0x00000002, + SumVec::new(bits, len, chunk_length)?, + ) } } /// The sum type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and the /// aggregate is the sum. -pub type Prio3Sum = Prio3<Sum<Field128>, XofShake128, 16>; +pub type Prio3Sum = Prio3<Sum<Field128>, XofTurboShake128, 16>; impl Prio3Sum { /// Construct an instance of Prio3Sum with the given number of aggregators and required bit @@ -136,7 +149,7 @@ impl Prio3Sum { ))); } - Prio3::new(num_aggregators, Sum::new(bits)?) + Prio3::new(num_aggregators, 1, 0x00000001, Sum::new(bits)?) } } @@ -160,7 +173,7 @@ pub type Prio3FixedPointBoundedL2VecSum<Fx> = Prio3< ParallelSum<Field128, PolyEval<Field128>>, ParallelSum<Field128, Mul<Field128>>, >, - XofShake128, + XofTurboShake128, 16, >; @@ -173,7 +186,12 @@ impl<Fx: Fixed + CompatibleFloat> Prio3FixedPointBoundedL2VecSum<Fx> { entries: usize, ) -> Result<Self, VdafError> { check_num_aggregators(num_aggregators)?; - Prio3::new(num_aggregators, FixedPointBoundedL2VecSum::new(entries)?) + Prio3::new( + num_aggregators, + 1, + 0xFFFF0000, + FixedPointBoundedL2VecSum::new(entries)?, + ) } } @@ -191,7 +209,7 @@ pub type Prio3FixedPointBoundedL2VecSumMultithreaded<Fx> = Prio3< ParallelSumMultithreaded<Field128, PolyEval<Field128>>, ParallelSumMultithreaded<Field128, Mul<Field128>>, >, - XofShake128, + XofTurboShake128, 16, >; @@ -204,14 +222,19 @@ impl<Fx: Fixed + CompatibleFloat> Prio3FixedPointBoundedL2VecSumMultithreaded<Fx entries: usize, ) -> Result<Self, VdafError> { check_num_aggregators(num_aggregators)?; - Prio3::new(num_aggregators, FixedPointBoundedL2VecSum::new(entries)?) + Prio3::new( + num_aggregators, + 1, + 0xFFFF0000, + FixedPointBoundedL2VecSum::new(entries)?, + ) } } /// The histogram type. Each measurement is an integer in `[0, length)` and the result is a /// histogram counting the number of occurrences of each measurement. pub type Prio3Histogram = - Prio3<Histogram<Field128, ParallelSum<Field128, Mul<Field128>>>, XofShake128, 16>; + Prio3<Histogram<Field128, ParallelSum<Field128, Mul<Field128>>>, XofTurboShake128, 16>; impl Prio3Histogram { /// Constructs an instance of Prio3Histogram with the given number of aggregators, @@ -221,7 +244,12 @@ impl Prio3Histogram { length: usize, chunk_length: usize, ) -> Result<Self, VdafError> { - Prio3::new(num_aggregators, Histogram::new(length, chunk_length)?) + Prio3::new( + num_aggregators, + 1, + 0x00000003, + Histogram::new(length, chunk_length)?, + ) } } @@ -229,8 +257,11 @@ impl Prio3Histogram { /// time. Note that this improvement is only noticeable for very large input lengths. #[cfg(feature = "multithreaded")] #[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))] -pub type Prio3HistogramMultithreaded = - Prio3<Histogram<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, XofShake128, 16>; +pub type Prio3HistogramMultithreaded = Prio3< + Histogram<Field128, ParallelSumMultithreaded<Field128, Mul<Field128>>>, + XofTurboShake128, + 16, +>; #[cfg(feature = "multithreaded")] impl Prio3HistogramMultithreaded { @@ -241,13 +272,18 @@ impl Prio3HistogramMultithreaded { length: usize, chunk_length: usize, ) -> Result<Self, VdafError> { - Prio3::new(num_aggregators, Histogram::new(length, chunk_length)?) + Prio3::new( + num_aggregators, + 1, + 0x00000003, + Histogram::new(length, chunk_length)?, + ) } } /// The average type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and /// the aggregate is the arithmetic average. -pub type Prio3Average = Prio3<Average<Field128>, XofShake128, 16>; +pub type Prio3Average = Prio3<Average<Field128>, XofTurboShake128, 16>; impl Prio3Average { /// Construct an instance of Prio3Average with the given number of aggregators and required bit @@ -263,6 +299,8 @@ impl Prio3Average { Ok(Prio3 { num_aggregators, + num_proofs: 1, + algorithm_id: 0xFFFF0000, typ: Average::new(bits)?, phantom: PhantomData, }) @@ -277,7 +315,7 @@ impl Prio3Average { /// - a [`Xof`] for deriving vectors of field elements from seeds. /// /// New instances can be defined by aliasing the base type. For example, [`Prio3Count`] is an alias -/// for `Prio3<Count<Field64>, XofShake128, 16>`. +/// for `Prio3<Count<Field64>, XofTurboShake128, 16>`. /// /// ``` /// use prio::vdaf::{ @@ -292,7 +330,7 @@ impl Prio3Average { /// let mut out_shares = vec![vec![]; num_shares.into()]; /// let mut rng = thread_rng(); /// let verify_key = rng.gen(); -/// let measurements = [0, 1, 1, 1, 0]; +/// let measurements = [false, true, true, true, false]; /// for measurement in measurements { /// // Shard /// let nonce = rng.gen::<[u8; 16]>(); @@ -316,7 +354,7 @@ impl Prio3Average { /// let prep_msg = vdaf.prepare_shares_to_prepare_message(&(), prep_shares).unwrap(); /// /// for (agg_id, state) in prep_states.into_iter().enumerate() { -/// let out_share = match vdaf.prepare_step(state, prep_msg.clone()).unwrap() { +/// let out_share = match vdaf.prepare_next(state, prep_msg.clone()).unwrap() { /// PrepareTransition::Finish(out_share) => out_share, /// _ => panic!("unexpected transition"), /// }; @@ -339,6 +377,8 @@ where P: Xof<SEED_SIZE>, { num_aggregators: u8, + num_proofs: u8, + algorithm_id: u32, typ: T, phantom: PhantomData<P>, } @@ -348,12 +388,25 @@ where T: Type, P: Xof<SEED_SIZE>, { - /// Construct an instance of this Prio3 VDAF with the given number of aggregators and the - /// underlying type. - pub fn new(num_aggregators: u8, typ: T) -> Result<Self, VdafError> { + /// Construct an instance of this Prio3 VDAF with the given number of aggregators, number of + /// proofs to generate and verify, the algorithm ID, and the underlying type. + pub fn new( + num_aggregators: u8, + num_proofs: u8, + algorithm_id: u32, + typ: T, + ) -> Result<Self, VdafError> { check_num_aggregators(num_aggregators)?; + if num_proofs == 0 { + return Err(VdafError::Uncategorized( + "num_proofs must be at least 1".to_string(), + )); + } + Ok(Self { num_aggregators, + num_proofs, + algorithm_id, typ, phantom: PhantomData, }) @@ -369,19 +422,72 @@ where self.typ.verifier_len() } + #[inline] + fn num_proofs(&self) -> usize { + self.num_proofs.into() + } + + fn derive_prove_rands(&self, prove_rand_seed: &Seed<SEED_SIZE>) -> Vec<T::Field> { + P::seed_stream( + prove_rand_seed, + &self.domain_separation_tag(DST_PROVE_RANDOMNESS), + &[self.num_proofs], + ) + .into_field_vec(self.typ.prove_rand_len() * self.num_proofs()) + } + fn derive_joint_rand_seed<'a>( - parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>, + &self, + joint_rand_parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>, ) -> Seed<SEED_SIZE> { let mut xof = P::init( &[0; SEED_SIZE], - &Self::domain_separation_tag(DST_JOINT_RAND_SEED), + &self.domain_separation_tag(DST_JOINT_RAND_SEED), ); - for part in parts { + for part in joint_rand_parts { xof.update(part.as_ref()); } xof.into_seed() } + fn derive_joint_rands<'a>( + &self, + joint_rand_parts: impl Iterator<Item = &'a Seed<SEED_SIZE>>, + ) -> (Seed<SEED_SIZE>, Vec<T::Field>) { + let joint_rand_seed = self.derive_joint_rand_seed(joint_rand_parts); + let joint_rands = P::seed_stream( + &joint_rand_seed, + &self.domain_separation_tag(DST_JOINT_RANDOMNESS), + &[self.num_proofs], + ) + .into_field_vec(self.typ.joint_rand_len() * self.num_proofs()); + + (joint_rand_seed, joint_rands) + } + + fn derive_helper_proofs_share( + &self, + proofs_share_seed: &Seed<SEED_SIZE>, + agg_id: u8, + ) -> Prng<T::Field, P::SeedStream> { + Prng::from_seed_stream(P::seed_stream( + proofs_share_seed, + &self.domain_separation_tag(DST_PROOF_SHARE), + &[self.num_proofs, agg_id], + )) + } + + fn derive_query_rands(&self, verify_key: &[u8; SEED_SIZE], nonce: &[u8; 16]) -> Vec<T::Field> { + let mut xof = P::init( + verify_key, + &self.domain_separation_tag(DST_QUERY_RANDOMNESS), + ); + xof.update(&[self.num_proofs]); + xof.update(nonce); + xof.into_seed_stream() + .into_field_vec(self.typ.query_rand_len() * self.num_proofs()) + } + fn random_size(&self) -> usize { if self.typ.joint_rand_len() == 0 { // Two seeds per helper for measurement and proof shares, plus one seed for proving @@ -438,42 +544,45 @@ where let proof_share_seed = random_seeds.next().unwrap().try_into().unwrap(); let measurement_share_prng: Prng<T::Field, _> = Prng::from_seed_stream(P::seed_stream( &Seed(measurement_share_seed), - &Self::domain_separation_tag(DST_MEASUREMENT_SHARE), + &self.domain_separation_tag(DST_MEASUREMENT_SHARE), &[agg_id], )); - let joint_rand_blind = - if let Some(helper_joint_rand_parts) = helper_joint_rand_parts.as_mut() { - let joint_rand_blind = random_seeds.next().unwrap().try_into().unwrap(); - let mut joint_rand_part_xof = P::init( - &joint_rand_blind, - &Self::domain_separation_tag(DST_JOINT_RAND_PART), - ); - joint_rand_part_xof.update(&[agg_id]); // Aggregator ID - joint_rand_part_xof.update(nonce); - - let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE); - for (x, y) in leader_measurement_share - .iter_mut() - .zip(measurement_share_prng) - { - *x -= y; - y.encode(&mut encoding_buffer); - joint_rand_part_xof.update(&encoding_buffer); - encoding_buffer.clear(); - } + let joint_rand_blind = if let Some(helper_joint_rand_parts) = + helper_joint_rand_parts.as_mut() + { + let joint_rand_blind = random_seeds.next().unwrap().try_into().unwrap(); + let mut joint_rand_part_xof = P::init( + &joint_rand_blind, + &self.domain_separation_tag(DST_JOINT_RAND_PART), + ); + joint_rand_part_xof.update(&[agg_id]); // Aggregator ID + joint_rand_part_xof.update(nonce); + + let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE); + for (x, y) in leader_measurement_share + .iter_mut() + .zip(measurement_share_prng) + { + *x -= y; + y.encode(&mut encoding_buffer).map_err(|_| { + VdafError::Uncategorized("failed to encode measurement share".to_string()) + })?; + joint_rand_part_xof.update(&encoding_buffer); + encoding_buffer.clear(); + } - helper_joint_rand_parts.push(joint_rand_part_xof.into_seed()); + helper_joint_rand_parts.push(joint_rand_part_xof.into_seed()); - Some(joint_rand_blind) - } else { - for (x, y) in leader_measurement_share - .iter_mut() - .zip(measurement_share_prng) - { - *x -= y; - } - None - }; + Some(joint_rand_blind) + } else { + for (x, y) in leader_measurement_share + .iter_mut() + .zip(measurement_share_prng) + { + *x -= y; + } + None + }; let helper = HelperShare::from_seeds(measurement_share_seed, proof_share_seed, joint_rand_blind); helper_shares.push(helper); @@ -483,71 +592,75 @@ where let public_share = Prio3PublicShare { joint_rand_parts: helper_joint_rand_parts .as_ref() - .map(|helper_joint_rand_parts| { - let leader_blind_bytes = random_seeds.next().unwrap().try_into().unwrap(); - let leader_blind = Seed::from_bytes(leader_blind_bytes); - - let mut joint_rand_part_xof = P::init( - leader_blind.as_ref(), - &Self::domain_separation_tag(DST_JOINT_RAND_PART), - ); - joint_rand_part_xof.update(&[0]); // Aggregator ID - joint_rand_part_xof.update(nonce); - let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE); - for x in leader_measurement_share.iter() { - x.encode(&mut encoding_buffer); - joint_rand_part_xof.update(&encoding_buffer); - encoding_buffer.clear(); - } - leader_blind_opt = Some(leader_blind); - - let leader_joint_rand_seed_part = joint_rand_part_xof.into_seed(); - - let mut vec = Vec::with_capacity(self.num_aggregators()); - vec.push(leader_joint_rand_seed_part); - vec.extend(helper_joint_rand_parts.iter().cloned()); - vec - }), + .map( + |helper_joint_rand_parts| -> Result<Vec<Seed<SEED_SIZE>>, VdafError> { + let leader_blind_bytes = random_seeds.next().unwrap().try_into().unwrap(); + let leader_blind = Seed::from_bytes(leader_blind_bytes); + + let mut joint_rand_part_xof = P::init( + leader_blind.as_ref(), + &self.domain_separation_tag(DST_JOINT_RAND_PART), + ); + joint_rand_part_xof.update(&[0]); // Aggregator ID + joint_rand_part_xof.update(nonce); + let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE); + for x in leader_measurement_share.iter() { + x.encode(&mut encoding_buffer).map_err(|_| { + VdafError::Uncategorized( + "failed to encode measurement share".to_string(), + ) + })?; + joint_rand_part_xof.update(&encoding_buffer); + encoding_buffer.clear(); + } + leader_blind_opt = Some(leader_blind); + + let leader_joint_rand_seed_part = joint_rand_part_xof.into_seed(); + + let mut vec = Vec::with_capacity(self.num_aggregators()); + vec.push(leader_joint_rand_seed_part); + vec.extend(helper_joint_rand_parts.iter().cloned()); + Ok(vec) + }, + ) + .transpose()?, }; // Compute the joint randomness. - let joint_rand: Vec<T::Field> = public_share + let joint_rands = public_share .joint_rand_parts .as_ref() - .map(|joint_rand_parts| { - let joint_rand_seed = Self::derive_joint_rand_seed(joint_rand_parts.iter()); - P::seed_stream( - &joint_rand_seed, - &Self::domain_separation_tag(DST_JOINT_RANDOMNESS), - &[], - ) - .into_field_vec(self.typ.joint_rand_len()) - }) + .map(|joint_rand_parts| self.derive_joint_rands(joint_rand_parts.iter()).1) .unwrap_or_default(); - // Run the proof-generation algorithm. - let prove_rand_seed = random_seeds.next().unwrap().try_into().unwrap(); - let prove_rand = P::seed_stream( - &Seed::from_bytes(prove_rand_seed), - &Self::domain_separation_tag(DST_PROVE_RANDOMNESS), - &[], - ) - .into_field_vec(self.typ.prove_rand_len()); - let mut leader_proof_share = - self.typ - .prove(&encoded_measurement, &prove_rand, &joint_rand)?; + // Generate the proofs. + let prove_rands = self.derive_prove_rands(&Seed::from_bytes( + random_seeds.next().unwrap().try_into().unwrap(), + )); + let mut leader_proofs_share = Vec::with_capacity(self.typ.proof_len() * self.num_proofs()); + for p in 0..self.num_proofs() { + let prove_rand = + &prove_rands[p * self.typ.prove_rand_len()..(p + 1) * self.typ.prove_rand_len()]; + let joint_rand = + &joint_rands[p * self.typ.joint_rand_len()..(p + 1) * self.typ.joint_rand_len()]; + + leader_proofs_share.append(&mut self.typ.prove( + &encoded_measurement, + prove_rand, + joint_rand, + )?); + } // Generate the proof shares and distribute the joint randomness seed hints. for (j, helper) in helper_shares.iter_mut().enumerate() { - let proof_share_prng: Prng<T::Field, _> = Prng::from_seed_stream(P::seed_stream( - &helper.proof_share, - &Self::domain_separation_tag(DST_PROOF_SHARE), - &[j as u8 + 1], - )); - for (x, y) in leader_proof_share - .iter_mut() - .zip(proof_share_prng) - .take(self.typ.proof_len()) + for (x, y) in + leader_proofs_share + .iter_mut() + .zip(self.derive_helper_proofs_share( + &helper.proofs_share, + u8::try_from(j).unwrap() + 1, + )) + .take(self.typ.proof_len() * self.num_proofs()) { *x -= y; } @@ -557,14 +670,14 @@ where let mut out = Vec::with_capacity(num_aggregators as usize); out.push(Prio3InputShare { measurement_share: Share::Leader(leader_measurement_share), - proof_share: Share::Leader(leader_proof_share), + proofs_share: Share::Leader(leader_proofs_share), joint_rand_blind: leader_blind_opt, }); for helper in helper_shares.into_iter() { out.push(Prio3InputShare { measurement_share: Share::Helper(helper.measurement_share), - proof_share: Share::Helper(helper.proof_share), + proofs_share: Share::Helper(helper.proofs_share), joint_rand_blind: helper.joint_rand_blind, }); } @@ -585,7 +698,6 @@ where T: Type, P: Xof<SEED_SIZE>, { - const ID: u32 = T::ID; type Measurement = T::Measurement; type AggregateResult = T::AggregateResult; type AggregationParam = (); @@ -594,6 +706,10 @@ where type OutputShare = OutputShare<T::Field>; type AggregateShare = AggregateShare<T::Field>; + fn algorithm_id(&self) -> u32 { + self.algorithm_id + } + fn num_aggregators(&self) -> usize { self.num_aggregators as usize } @@ -607,12 +723,13 @@ pub struct Prio3PublicShare<const SEED_SIZE: usize> { } impl<const SEED_SIZE: usize> Encode for Prio3PublicShare<SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { if let Some(joint_rand_parts) = self.joint_rand_parts.as_ref() { for part in joint_rand_parts.iter() { - part.encode(bytes); + part.encode(bytes)?; } } + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -675,7 +792,7 @@ pub struct Prio3InputShare<F, const SEED_SIZE: usize> { measurement_share: Share<F, SEED_SIZE>, /// The proof share. - proof_share: Share<F, SEED_SIZE>, + proofs_share: Share<F, SEED_SIZE>, /// Blinding seed used by the Aggregator to compute the joint randomness. This field is optional /// because not every [`Type`] requires joint randomness. @@ -697,28 +814,29 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3InputSha self.joint_rand_blind.as_ref(), other.joint_rand_blind.as_ref(), ) & self.measurement_share.ct_eq(&other.measurement_share) - & self.proof_share.ct_eq(&other.proof_share) + & self.proofs_share.ct_eq(&other.proofs_share) } } impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode for Prio3InputShare<F, SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { if matches!( - (&self.measurement_share, &self.proof_share), + (&self.measurement_share, &self.proofs_share), (Share::Leader(_), Share::Helper(_)) | (Share::Helper(_), Share::Leader(_)) ) { panic!("tried to encode input share with ambiguous encoding") } - self.measurement_share.encode(bytes); - self.proof_share.encode(bytes); + self.measurement_share.encode(bytes)?; + self.proofs_share.encode(bytes)?; if let Some(ref blind) = self.joint_rand_blind { - blind.encode(bytes); + blind.encode(bytes)?; } + Ok(()) } fn encoded_len(&self) -> Option<usize> { - let mut len = self.measurement_share.encoded_len()? + self.proof_share.encoded_len()?; + let mut len = self.measurement_share.encoded_len()? + self.proofs_share.encoded_len()?; if let Some(ref blind) = self.joint_rand_blind { len += blind.encoded_len()?; } @@ -742,7 +860,7 @@ where let (input_decoder, proof_decoder) = if agg_id == 0 { ( ShareDecodingParameter::Leader(prio3.typ.input_len()), - ShareDecodingParameter::Leader(prio3.typ.proof_len()), + ShareDecodingParameter::Leader(prio3.typ.proof_len() * prio3.num_proofs()), ) } else { ( @@ -752,7 +870,7 @@ where }; let measurement_share = Share::decode_with_param(&input_decoder, bytes)?; - let proof_share = Share::decode_with_param(&proof_decoder, bytes)?; + let proofs_share = Share::decode_with_param(&proof_decoder, bytes)?; let joint_rand_blind = if prio3.typ.joint_rand_len() > 0 { let blind = Seed::decode(bytes)?; Some(blind) @@ -762,7 +880,7 @@ where Ok(Prio3InputShare { measurement_share, - proof_share, + proofs_share, joint_rand_blind, }) } @@ -772,7 +890,7 @@ where /// Message broadcast by each [`Aggregator`] in each round of the Preparation phase. pub struct Prio3PrepareShare<F, const SEED_SIZE: usize> { /// A share of the FLP verifier message. (See [`Type`].) - verifier: Vec<F>, + verifiers: Vec<F>, /// A part of the joint randomness seed. joint_rand_part: Option<Seed<SEED_SIZE>>, @@ -792,25 +910,26 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareS option_ct_eq( self.joint_rand_part.as_ref(), other.joint_rand_part.as_ref(), - ) & self.verifier.ct_eq(&other.verifier) + ) & self.verifiers.ct_eq(&other.verifiers) } } impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode for Prio3PrepareShare<F, SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { - for x in &self.verifier { - x.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + for x in &self.verifiers { + x.encode(bytes)?; } if let Some(ref seed) = self.joint_rand_part { - seed.encode(bytes); + seed.encode(bytes)?; } + Ok(()) } fn encoded_len(&self) -> Option<usize> { // Each element of the verifier has the same size. - let mut len = F::ENCODED_SIZE * self.verifier.len(); + let mut len = F::ENCODED_SIZE * self.verifiers.len(); if let Some(ref seed) = self.joint_rand_part { len += seed.encoded_len()?; } @@ -825,9 +944,9 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> decoding_parameter: &Prio3PrepareState<F, SEED_SIZE>, bytes: &mut Cursor<&[u8]>, ) -> Result<Self, CodecError> { - let mut verifier = Vec::with_capacity(decoding_parameter.verifier_len); - for _ in 0..decoding_parameter.verifier_len { - verifier.push(F::decode(bytes)?); + let mut verifiers = Vec::with_capacity(decoding_parameter.verifiers_len); + for _ in 0..decoding_parameter.verifiers_len { + verifiers.push(F::decode(bytes)?); } let joint_rand_part = if decoding_parameter.joint_rand_seed.is_some() { @@ -837,7 +956,7 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> }; Ok(Prio3PrepareShare { - verifier, + verifiers, joint_rand_part, }) } @@ -869,10 +988,11 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareMessage<SEED_SIZE> { } impl<const SEED_SIZE: usize> Encode for Prio3PrepareMessage<SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { if let Some(ref seed) = self.joint_rand_seed { - seed.encode(bytes); + seed.encode(bytes)?; } + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -924,7 +1044,7 @@ pub struct Prio3PrepareState<F, const SEED_SIZE: usize> { measurement_share: Share<F, SEED_SIZE>, joint_rand_seed: Option<Seed<SEED_SIZE>>, agg_id: u8, - verifier_len: usize, + verifiers_len: usize, } impl<F: ConstantTimeEq, const SEED_SIZE: usize> PartialEq for Prio3PrepareState<F, SEED_SIZE> { @@ -939,7 +1059,7 @@ impl<F: ConstantTimeEq, const SEED_SIZE: usize> ConstantTimeEq for Prio3PrepareS fn ct_eq(&self, other: &Self) -> Choice { // We allow short-circuiting on the presence or absence of the joint_rand_seed, as well as // the aggregator ID & verifier length parameters. - if self.agg_id != other.agg_id || self.verifier_len != other.verifier_len { + if self.agg_id != other.agg_id || self.verifiers_len != other.verifiers_len { return Choice::from(0); } @@ -962,7 +1082,7 @@ impl<F, const SEED_SIZE: usize> Debug for Prio3PrepareState<F, SEED_SIZE> { }, ) .field("agg_id", &self.agg_id) - .field("verifier_len", &self.verifier_len) + .field("verifiers_len", &self.verifiers_len) .finish() } } @@ -971,11 +1091,12 @@ impl<F: FftFriendlyFieldElement, const SEED_SIZE: usize> Encode for Prio3PrepareState<F, SEED_SIZE> { /// Append the encoded form of this object to the end of `bytes`, growing the vector as needed. - fn encode(&self, bytes: &mut Vec<u8>) { - self.measurement_share.encode(bytes); + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + self.measurement_share.encode(bytes)?; if let Some(ref seed) = self.joint_rand_seed { - seed.encode(bytes); + seed.encode(bytes)?; } + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -1018,7 +1139,7 @@ where measurement_share, joint_rand_seed, agg_id, - verifier_len: prio3.typ.verifier_len(), + verifiers_len: prio3.typ.verifier_len() * prio3.num_proofs(), }) } } @@ -1051,14 +1172,6 @@ where VdafError, > { let agg_id = self.role_try_from(agg_id)?; - let mut query_rand_xof = P::init( - verify_key, - &Self::domain_separation_tag(DST_QUERY_RANDOMNESS), - ); - query_rand_xof.update(nonce); - let query_rand = query_rand_xof - .into_seed_stream() - .into_field_vec(self.typ.query_rand_len()); // Create a reference to the (expanded) measurement share. let expanded_measurement_share: Option<Vec<T::Field>> = match msg.measurement_share { @@ -1066,7 +1179,7 @@ where Share::Helper(ref seed) => Some( P::seed_stream( seed, - &Self::domain_separation_tag(DST_MEASUREMENT_SHARE), + &self.domain_separation_tag(DST_MEASUREMENT_SHARE), &[agg_id], ) .into_field_vec(self.typ.input_len()), @@ -1078,33 +1191,32 @@ where }; // Create a reference to the (expanded) proof share. - let expanded_proof_share: Option<Vec<T::Field>> = match msg.proof_share { + let expanded_proofs_share: Option<Vec<T::Field>> = match msg.proofs_share { Share::Leader(_) => None, - Share::Helper(ref seed) => Some( - P::seed_stream( - seed, - &Self::domain_separation_tag(DST_PROOF_SHARE), - &[agg_id], - ) - .into_field_vec(self.typ.proof_len()), + Share::Helper(ref proof_shares_seed) => Some( + self.derive_helper_proofs_share(proof_shares_seed, agg_id) + .take(self.typ.proof_len() * self.num_proofs()) + .collect(), ), }; - let proof_share = match msg.proof_share { + let proofs_share = match msg.proofs_share { Share::Leader(ref data) => data, - Share::Helper(_) => expanded_proof_share.as_ref().unwrap(), + Share::Helper(_) => expanded_proofs_share.as_ref().unwrap(), }; // Compute the joint randomness. - let (joint_rand_seed, joint_rand_part, joint_rand) = if self.typ.joint_rand_len() > 0 { + let (joint_rand_seed, joint_rand_part, joint_rands) = if self.typ.joint_rand_len() > 0 { let mut joint_rand_part_xof = P::init( msg.joint_rand_blind.as_ref().unwrap().as_ref(), - &Self::domain_separation_tag(DST_JOINT_RAND_PART), + &self.domain_separation_tag(DST_JOINT_RAND_PART), ); joint_rand_part_xof.update(&[agg_id]); joint_rand_part_xof.update(nonce); let mut encoding_buffer = Vec::with_capacity(T::Field::ENCODED_SIZE); for x in measurement_share { - x.encode(&mut encoding_buffer); + x.encode(&mut encoding_buffer).map_err(|_| { + VdafError::Uncategorized("failed to encode measurement share".to_string()) + })?; joint_rand_part_xof.update(&encoding_buffer); encoding_buffer.clear(); } @@ -1131,37 +1243,47 @@ where .skip(agg_id as usize + 1), ); - let joint_rand_seed = Self::derive_joint_rand_seed(corrected_joint_rand_parts); + let (joint_rand_seed, joint_rands) = + self.derive_joint_rands(corrected_joint_rand_parts); - let joint_rand = P::seed_stream( - &joint_rand_seed, - &Self::domain_separation_tag(DST_JOINT_RANDOMNESS), - &[], + ( + Some(joint_rand_seed), + Some(own_joint_rand_part), + joint_rands, ) - .into_field_vec(self.typ.joint_rand_len()); - (Some(joint_rand_seed), Some(own_joint_rand_part), joint_rand) } else { (None, None, Vec::new()) }; // Run the query-generation algorithm. - let verifier_share = self.typ.query( - measurement_share, - proof_share, - &query_rand, - &joint_rand, - self.num_aggregators as usize, - )?; + let query_rands = self.derive_query_rands(verify_key, nonce); + let mut verifiers_share = Vec::with_capacity(self.typ.verifier_len() * self.num_proofs()); + for p in 0..self.num_proofs() { + let query_rand = + &query_rands[p * self.typ.query_rand_len()..(p + 1) * self.typ.query_rand_len()]; + let joint_rand = + &joint_rands[p * self.typ.joint_rand_len()..(p + 1) * self.typ.joint_rand_len()]; + let proof_share = + &proofs_share[p * self.typ.proof_len()..(p + 1) * self.typ.proof_len()]; + + verifiers_share.append(&mut self.typ.query( + measurement_share, + proof_share, + query_rand, + joint_rand, + self.num_aggregators as usize, + )?); + } Ok(( Prio3PrepareState { measurement_share: msg.measurement_share.clone(), joint_rand_seed, agg_id, - verifier_len: verifier_share.len(), + verifiers_len: verifiers_share.len(), }, Prio3PrepareShare { - verifier: verifier_share, + verifiers: verifiers_share, joint_rand_part, }, )) @@ -1174,17 +1296,17 @@ where _: &Self::AggregationParam, inputs: M, ) -> Result<Prio3PrepareMessage<SEED_SIZE>, VdafError> { - let mut verifier = vec![T::Field::zero(); self.typ.verifier_len()]; + let mut verifiers = vec![T::Field::zero(); self.typ.verifier_len() * self.num_proofs()]; let mut joint_rand_parts = Vec::with_capacity(self.num_aggregators()); let mut count = 0; for share in inputs.into_iter() { count += 1; - if share.verifier.len() != verifier.len() { + if share.verifiers.len() != verifiers.len() { return Err(VdafError::Uncategorized(format!( "unexpected verifier share length: got {}; want {}", - share.verifier.len(), - verifier.len(), + share.verifiers.len(), + verifiers.len(), ))); } @@ -1193,7 +1315,7 @@ where joint_rand_parts.push(joint_rand_seed_part); } - for (x, y) in verifier.iter_mut().zip(share.verifier) { + for (x, y) in verifiers.iter_mut().zip(share.verifiers) { *x += y; } } @@ -1205,19 +1327,17 @@ where ))); } - // Check the proof verifier. - match self.typ.decide(&verifier) { - Ok(true) => (), - Ok(false) => { + // Check the proof verifiers. + for verifier in verifiers.chunks(self.typ.verifier_len()) { + if !self.typ.decide(verifier)? { return Err(VdafError::Uncategorized( "proof verifier check failed".into(), - )) + )); } - Err(err) => return Err(VdafError::from(err)), - }; + } let joint_rand_seed = if self.typ.joint_rand_len() > 0 { - Some(Self::derive_joint_rand_seed(joint_rand_parts.iter())) + Some(self.derive_joint_rand_seed(joint_rand_parts.iter())) } else { None }; @@ -1249,7 +1369,7 @@ where let measurement_share = match step.measurement_share { Share::Leader(data) => data, Share::Helper(seed) => { - let dst = Self::domain_separation_tag(DST_MEASUREMENT_SHARE); + let dst = self.domain_separation_tag(DST_MEASUREMENT_SHARE); P::seed_stream(&seed, &dst, &[step.agg_id]).into_field_vec(self.typ.input_len()) } }; @@ -1324,7 +1444,7 @@ where #[derive(Clone)] struct HelperShare<const SEED_SIZE: usize> { measurement_share: Seed<SEED_SIZE>, - proof_share: Seed<SEED_SIZE>, + proofs_share: Seed<SEED_SIZE>, joint_rand_blind: Option<Seed<SEED_SIZE>>, } @@ -1336,7 +1456,7 @@ impl<const SEED_SIZE: usize> HelperShare<SEED_SIZE> { ) -> Self { HelperShare { measurement_share: Seed::from_bytes(measurement_share), - proof_share: Seed::from_bytes(proof_share), + proofs_share: Seed::from_bytes(proof_share), joint_rand_blind: joint_rand_blind.map(Seed::from_bytes), } } @@ -1458,7 +1578,8 @@ mod tests { #[cfg(feature = "experimental")] use crate::flp::gadgets::ParallelSumGadget; use crate::vdaf::{ - equality_comparison_test, fieldvec_roundtrip_test, run_vdaf, run_vdaf_prepare, + equality_comparison_test, fieldvec_roundtrip_test, + test_utils::{run_vdaf, run_vdaf_prepare}, }; use assert_matches::assert_matches; #[cfg(feature = "experimental")] @@ -1474,24 +1595,27 @@ mod tests { fn test_prio3_count() { let prio3 = Prio3::new_count(2).unwrap(); - assert_eq!(run_vdaf(&prio3, &(), [1, 0, 0, 1, 1]).unwrap(), 3); + assert_eq!( + run_vdaf(&prio3, &(), [true, false, false, true, true]).unwrap(), + 3 + ); let mut nonce = [0; 16]; let mut verify_key = [0; 16]; thread_rng().fill(&mut verify_key[..]); thread_rng().fill(&mut nonce[..]); - let (public_share, input_shares) = prio3.shard(&0, &nonce).unwrap(); + let (public_share, input_shares) = prio3.shard(&false, &nonce).unwrap(); run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares).unwrap(); - let (public_share, input_shares) = prio3.shard(&1, &nonce).unwrap(); + let (public_share, input_shares) = prio3.shard(&true, &nonce).unwrap(); run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares).unwrap(); - test_serialization(&prio3, &1, &nonce).unwrap(); + test_serialization(&prio3, &true, &nonce).unwrap(); let prio3_extra_helper = Prio3::new_count(3).unwrap(); assert_eq!( - run_vdaf(&prio3_extra_helper, &(), [1, 0, 0, 1, 1]).unwrap(), + run_vdaf(&prio3_extra_helper, &(), [true, false, false, true, true]).unwrap(), 3, ); } @@ -1522,7 +1646,7 @@ mod tests { assert_matches!(result, Err(VdafError::Uncategorized(_))); let (public_share, mut input_shares) = prio3.shard(&1, &nonce).unwrap(); - assert_matches!(input_shares[0].proof_share, Share::Leader(ref mut data) => { + assert_matches!(input_shares[0].proofs_share, Share::Leader(ref mut data) => { data[0] += Field128::one(); }); let result = run_vdaf_prepare(&prio3, &verify_key, &(), &nonce, public_share, input_shares); @@ -1550,6 +1674,30 @@ mod tests { } #[test] + fn test_prio3_sum_vec_multiproof() { + let prio3 = Prio3::< + SumVec<Field128, ParallelSum<Field128, Mul<Field128>>>, + XofTurboShake128, + 16, + >::new(2, 2, 0xFFFF0000, SumVec::new(2, 20, 4).unwrap()) + .unwrap(); + + assert_eq!( + run_vdaf( + &prio3, + &(), + [ + vec![0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1], + vec![0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 1, 3, 0, 3, 0, 0, 0, 1, 0, 0], + vec![1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1], + ] + ) + .unwrap(), + vec![1, 3, 1, 0, 3, 1, 0, 1, 2, 2, 3, 3, 1, 5, 1, 2, 1, 3, 0, 2], + ); + } + + #[test] #[cfg(feature = "multithreaded")] fn test_prio3_sum_vec_multithreaded() { let prio3 = Prio3::new_sum_vec_multithreaded(2, 2, 20, 4).unwrap(); @@ -1598,7 +1746,7 @@ mod tests { fn test_fixed_vec<Fx, PE, M, const SIZE: usize>( fp_0: Fx, - prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofShake128, 16>, + prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofTurboShake128, 16>, ) where Fx: Fixed + CompatibleFloat + std::ops::Neg<Output = Fx>, PE: Eq + ParallelSumGadget<Field128, PolyEval<Field128>> + Clone + 'static, @@ -1690,7 +1838,7 @@ mod tests { fp_4_inv: Fx, fp_8_inv: Fx, fp_16_inv: Fx, - prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofShake128, 16>, + prio3: Prio3<FixedPointBoundedL2VecSum<Fx, PE, M>, XofTurboShake128, 16>, ) where Fx: Fixed + CompatibleFloat + std::ops::Neg<Output = Fx>, PE: Eq + ParallelSumGadget<Field128, PolyEval<Field128>> + Clone + 'static, @@ -1752,7 +1900,7 @@ mod tests { let (public_share, mut input_shares) = prio3 .shard(&vec![fp_4_inv, fp_8_inv, fp_16_inv], &nonce) .unwrap(); - assert_matches!(input_shares[0].proof_share, Share::Leader(ref mut data) => { + assert_matches!(input_shares[0].proofs_share, Share::Leader(ref mut data) => { data[0] += Field128::one(); }); let result = @@ -1823,7 +1971,7 @@ mod tests { } if let (Share::Helper(left), Share::Helper(right)) = - (&x.proof_share, &y.proof_share) + (&x.proofs_share, &y.proofs_share) { assert_ne!(left, right); } @@ -1847,7 +1995,7 @@ mod tests { thread_rng().fill(&mut verify_key[..]); let (public_share, input_shares) = prio3.shard(measurement, nonce)?; - let encoded_public_share = public_share.get_encoded(); + let encoded_public_share = public_share.get_encoded().unwrap(); let decoded_public_share = Prio3PublicShare::get_decoded_with_param(prio3, &encoded_public_share) .expect("failed to decode public share"); @@ -1858,7 +2006,7 @@ mod tests { ); for (agg_id, input_share) in input_shares.iter().enumerate() { - let encoded_input_share = input_share.get_encoded(); + let encoded_input_share = input_share.get_encoded().unwrap(); let decoded_input_share = Prio3InputShare::get_decoded_with_param(&(prio3, agg_id), &encoded_input_share) .expect("failed to decode input share"); @@ -1875,7 +2023,7 @@ mod tests { let (prepare_state, prepare_share) = prio3.prepare_init(&verify_key, agg_id, &(), nonce, &public_share, input_share)?; - let encoded_prepare_state = prepare_state.get_encoded(); + let encoded_prepare_state = prepare_state.get_encoded().unwrap(); let decoded_prepare_state = Prio3PrepareState::get_decoded_with_param(&(prio3, agg_id), &encoded_prepare_state) .expect("failed to decode prepare state"); @@ -1885,7 +2033,7 @@ mod tests { encoded_prepare_state.len() ); - let encoded_prepare_share = prepare_share.get_encoded(); + let encoded_prepare_share = prepare_share.get_encoded().unwrap(); let decoded_prepare_share = Prio3PrepareShare::get_decoded_with_param(&prepare_state, &encoded_prepare_share) .expect("failed to decode prepare share"); @@ -1903,7 +2051,7 @@ mod tests { .prepare_shares_to_prepare_message(&(), prepare_shares) .unwrap(); - let encoded_prepare_message = prepare_message.get_encoded(); + let encoded_prepare_message = prepare_message.get_encoded().unwrap(); let decoded_prepare_message = Prio3PrepareMessage::get_decoded_with_param( &last_prepare_state.unwrap(), &encoded_prepare_message, @@ -1967,31 +2115,31 @@ mod tests { // Default. Prio3InputShare { measurement_share: Share::Leader(Vec::from([0])), - proof_share: Share::Leader(Vec::from([1])), + proofs_share: Share::Leader(Vec::from([1])), joint_rand_blind: Some(Seed([2])), }, // Modified measurement share. Prio3InputShare { measurement_share: Share::Leader(Vec::from([100])), - proof_share: Share::Leader(Vec::from([1])), + proofs_share: Share::Leader(Vec::from([1])), joint_rand_blind: Some(Seed([2])), }, // Modified proof share. Prio3InputShare { measurement_share: Share::Leader(Vec::from([0])), - proof_share: Share::Leader(Vec::from([101])), + proofs_share: Share::Leader(Vec::from([101])), joint_rand_blind: Some(Seed([2])), }, // Modified joint_rand_blind. Prio3InputShare { measurement_share: Share::Leader(Vec::from([0])), - proof_share: Share::Leader(Vec::from([1])), + proofs_share: Share::Leader(Vec::from([1])), joint_rand_blind: Some(Seed([102])), }, // Missing joint_rand_blind. Prio3InputShare { measurement_share: Share::Leader(Vec::from([0])), - proof_share: Share::Leader(Vec::from([1])), + proofs_share: Share::Leader(Vec::from([1])), joint_rand_blind: None, }, ]) @@ -2002,22 +2150,22 @@ mod tests { equality_comparison_test(&[ // Default. Prio3PrepareShare { - verifier: Vec::from([0]), + verifiers: Vec::from([0]), joint_rand_part: Some(Seed([1])), }, // Modified verifier. Prio3PrepareShare { - verifier: Vec::from([100]), + verifiers: Vec::from([100]), joint_rand_part: Some(Seed([1])), }, // Modified joint_rand_part. Prio3PrepareShare { - verifier: Vec::from([0]), + verifiers: Vec::from([0]), joint_rand_part: Some(Seed([101])), }, // Missing joint_rand_part. Prio3PrepareShare { - verifier: Vec::from([0]), + verifiers: Vec::from([0]), joint_rand_part: None, }, ]) @@ -2049,42 +2197,42 @@ mod tests { measurement_share: Share::Leader(Vec::from([0])), joint_rand_seed: Some(Seed([1])), agg_id: 2, - verifier_len: 3, + verifiers_len: 3, }, // Modified measurement share. Prio3PrepareState { measurement_share: Share::Leader(Vec::from([100])), joint_rand_seed: Some(Seed([1])), agg_id: 2, - verifier_len: 3, + verifiers_len: 3, }, // Modified joint_rand_seed. Prio3PrepareState { measurement_share: Share::Leader(Vec::from([0])), joint_rand_seed: Some(Seed([101])), agg_id: 2, - verifier_len: 3, + verifiers_len: 3, }, // Missing joint_rand_seed. Prio3PrepareState { measurement_share: Share::Leader(Vec::from([0])), joint_rand_seed: None, agg_id: 2, - verifier_len: 3, + verifiers_len: 3, }, // Modified agg_id. Prio3PrepareState { measurement_share: Share::Leader(Vec::from([0])), joint_rand_seed: Some(Seed([1])), agg_id: 102, - verifier_len: 3, + verifiers_len: 3, }, // Modified verifier_len. Prio3PrepareState { measurement_share: Share::Leader(Vec::from([0])), joint_rand_seed: Some(Seed([1])), agg_id: 2, - verifier_len: 103, + verifiers_len: 103, }, ]) } diff --git a/third_party/rust/prio/src/vdaf/prio3_test.rs b/third_party/rust/prio/src/vdaf/prio3_test.rs index 372a2c8560..9a3dfd85f4 100644 --- a/third_party/rust/prio/src/vdaf/prio3_test.rs +++ b/third_party/rust/prio/src/vdaf/prio3_test.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Tools for evaluating Prio3 test vectors. + use crate::{ codec::{Encode, ParameterizedDecode}, flp::Type, @@ -58,19 +60,21 @@ macro_rules! err { // TODO Generalize this method to work with any VDAF. To do so we would need to add // `shard_with_random()` to traits. (There may be a less invasive alternative.) -fn check_prep_test_vec<M, T, P, const SEED_SIZE: usize>( +fn check_prep_test_vec<MS, MP, T, P, const SEED_SIZE: usize>( prio3: &Prio3<T, P, SEED_SIZE>, verify_key: &[u8; SEED_SIZE], test_num: usize, - t: &TPrio3Prep<M>, + t: &TPrio3Prep<MS>, ) -> Vec<OutputShare<T::Field>> where - T: Type<Measurement = M>, + MS: Clone, + MP: From<MS>, + T: Type<Measurement = MP>, P: Xof<SEED_SIZE>, { let nonce = <[u8; 16]>::try_from(t.nonce.clone()).unwrap(); let (public_share, input_shares) = prio3 - .shard_with_random(&t.measurement, &nonce, &t.rand) + .shard_with_random(&t.measurement.clone().into(), &nonce, &t.rand) .expect("failed to generate input shares"); assert_eq!( @@ -86,7 +90,7 @@ where "#{test_num}" ); assert_eq!( - input_shares[agg_id].get_encoded(), + input_shares[agg_id].get_encoded().unwrap(), want.as_ref(), "#{test_num}" ) @@ -110,14 +114,18 @@ where .unwrap_or_else(|e| err!(test_num, e, "decode test vector (prep share)")), "#{test_num}" ); - assert_eq!(prep_shares[i].get_encoded(), want.as_ref(), "#{test_num}"); + assert_eq!( + prep_shares[i].get_encoded().unwrap(), + want.as_ref(), + "#{test_num}" + ); } let inbound = prio3 .prepare_shares_to_prepare_message(&(), prep_shares) .unwrap_or_else(|e| err!(test_num, e, "prep preprocess")); assert_eq!(t.prep_messages.len(), 1); - assert_eq!(inbound.get_encoded(), t.prep_messages[0].as_ref()); + assert_eq!(inbound.get_encoded().unwrap(), t.prep_messages[0].as_ref()); let mut out_shares = Vec::new(); for state in states.iter_mut() { @@ -130,7 +138,11 @@ where } for (got, want) in out_shares.iter().zip(t.out_shares.iter()) { - let got: Vec<Vec<u8>> = got.as_ref().iter().map(|x| x.get_encoded()).collect(); + let got: Vec<Vec<u8>> = got + .as_ref() + .iter() + .map(|x| x.get_encoded().unwrap()) + .collect(); assert_eq!(got.len(), want.len()); for (got_elem, want_elem) in got.iter().zip(want.iter()) { assert_eq!(got_elem.as_slice(), want_elem.as_ref()); @@ -141,12 +153,14 @@ where } #[must_use] -fn check_aggregate_test_vec<M, T, P, const SEED_SIZE: usize>( +fn check_aggregate_test_vec<MS, MP, T, P, const SEED_SIZE: usize>( prio3: &Prio3<T, P, SEED_SIZE>, - t: &TPrio3<M>, + t: &TPrio3<MS>, ) -> T::AggregateResult where - T: Type<Measurement = M>, + MS: Clone, + MP: From<MS>, + T: Type<Measurement = MP>, P: Xof<SEED_SIZE>, { let verify_key = t.verify_key.as_ref().try_into().unwrap(); @@ -167,85 +181,113 @@ where .collect::<Vec<_>>(); for (got, want) in aggregate_shares.iter().zip(t.agg_shares.iter()) { - let got = got.get_encoded(); + let got = got.get_encoded().unwrap(); assert_eq!(got.as_slice(), want.as_ref()); } prio3.unshard(&(), aggregate_shares, 1).unwrap() } +/// Evaluate a Prio3 test vector. The instance of Prio3 is constructed from the `new_vdaf` callback, +/// which takes in the VDAF parameters encoded by the test vectors and the number of shares. +/// +/// This version allows customizing the deserialization of measurements, via an additional type +/// parameter. +#[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub fn check_test_vec_custom_de<MS, MP, A, T, P, const SEED_SIZE: usize>( + test_vec_json_str: &str, + new_vdaf: impl Fn(&HashMap<String, serde_json::Value>, u8) -> Prio3<T, P, SEED_SIZE>, +) where + MS: for<'de> Deserialize<'de> + Clone, + MP: From<MS>, + A: for<'de> Deserialize<'de> + Debug + Eq, + T: Type<Measurement = MP, AggregateResult = A>, + P: Xof<SEED_SIZE>, +{ + let t: TPrio3<MS> = serde_json::from_str(test_vec_json_str).unwrap(); + let vdaf = new_vdaf(&t.other_params, t.shares); + let agg_result = check_aggregate_test_vec(&vdaf, &t); + assert_eq!(agg_result, serde_json::from_value(t.agg_result).unwrap()); +} + +/// Evaluate a Prio3 test vector. The instance of Prio3 is constructed from the `new_vdaf` callback, +/// which takes in the VDAF parameters encoded by the test vectors and the number of shares. +#[cfg(feature = "test-util")] +#[cfg_attr(docsrs, doc(cfg(feature = "test-util")))] +pub fn check_test_vec<M, A, T, P, const SEED_SIZE: usize>( + test_vec_json_str: &str, + new_vdaf: impl Fn(&HashMap<String, serde_json::Value>, u8) -> Prio3<T, P, SEED_SIZE>, +) where + M: for<'de> Deserialize<'de> + Clone, + A: for<'de> Deserialize<'de> + Debug + Eq, + T: Type<Measurement = M, AggregateResult = A>, + P: Xof<SEED_SIZE>, +{ + check_test_vec_custom_de::<M, M, _, _, _, SEED_SIZE>(test_vec_json_str, new_vdaf) +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(transparent)] +struct Prio3CountMeasurement(u8); + +impl From<Prio3CountMeasurement> for bool { + fn from(value: Prio3CountMeasurement) -> Self { + value.0 != 0 + } +} + #[test] fn test_vec_prio3_count() { for test_vector_str in [ - include_str!("test_vec/07/Prio3Count_0.json"), - include_str!("test_vec/07/Prio3Count_1.json"), + include_str!("test_vec/08/Prio3Count_0.json"), + include_str!("test_vec/08/Prio3Count_1.json"), ] { - let t: TPrio3<u64> = serde_json::from_str(test_vector_str).unwrap(); - let prio3 = Prio3::new_count(t.shares).unwrap(); - - let aggregate_result = check_aggregate_test_vec(&prio3, &t); - assert_eq!(aggregate_result, t.agg_result.as_u64().unwrap()); + check_test_vec_custom_de::<Prio3CountMeasurement, _, _, _, _, 16>( + test_vector_str, + |_json_params, num_shares| Prio3::new_count(num_shares).unwrap(), + ); } } #[test] fn test_vec_prio3_sum() { for test_vector_str in [ - include_str!("test_vec/07/Prio3Sum_0.json"), - include_str!("test_vec/07/Prio3Sum_1.json"), + include_str!("test_vec/08/Prio3Sum_0.json"), + include_str!("test_vec/08/Prio3Sum_1.json"), ] { - let t: TPrio3<u128> = serde_json::from_str(test_vector_str).unwrap(); - let bits = t.other_params["bits"].as_u64().unwrap() as usize; - let prio3 = Prio3::new_sum(t.shares, bits).unwrap(); - - let aggregate_result = check_aggregate_test_vec(&prio3, &t); - assert_eq!(aggregate_result, t.agg_result.as_u64().unwrap() as u128); + check_test_vec(test_vector_str, |json_params, num_shares| { + let bits = json_params["bits"].as_u64().unwrap() as usize; + Prio3::new_sum(num_shares, bits).unwrap() + }); } } #[test] fn test_vec_prio3_sum_vec() { for test_vector_str in [ - include_str!("test_vec/07/Prio3SumVec_0.json"), - include_str!("test_vec/07/Prio3SumVec_1.json"), + include_str!("test_vec/08/Prio3SumVec_0.json"), + include_str!("test_vec/08/Prio3SumVec_1.json"), ] { - let t: TPrio3<Vec<u128>> = serde_json::from_str(test_vector_str).unwrap(); - let bits = t.other_params["bits"].as_u64().unwrap() as usize; - let length = t.other_params["length"].as_u64().unwrap() as usize; - let chunk_length = t.other_params["chunk_length"].as_u64().unwrap() as usize; - let prio3 = Prio3::new_sum_vec(t.shares, bits, length, chunk_length).unwrap(); - - let aggregate_result = check_aggregate_test_vec(&prio3, &t); - let expected_aggregate_result = t - .agg_result - .as_array() - .unwrap() - .iter() - .map(|val| val.as_u64().unwrap() as u128) - .collect::<Vec<u128>>(); - assert_eq!(aggregate_result, expected_aggregate_result); + check_test_vec(test_vector_str, |json_params, num_shares| { + let bits = json_params["bits"].as_u64().unwrap() as usize; + let length = json_params["length"].as_u64().unwrap() as usize; + let chunk_length = json_params["chunk_length"].as_u64().unwrap() as usize; + Prio3::new_sum_vec(num_shares, bits, length, chunk_length).unwrap() + }); } } #[test] fn test_vec_prio3_histogram() { for test_vector_str in [ - include_str!("test_vec/07/Prio3Histogram_0.json"), - include_str!("test_vec/07/Prio3Histogram_1.json"), + include_str!("test_vec/08/Prio3Histogram_0.json"), + include_str!("test_vec/08/Prio3Histogram_1.json"), ] { - let t: TPrio3<usize> = serde_json::from_str(test_vector_str).unwrap(); - let length = t.other_params["length"].as_u64().unwrap() as usize; - let chunk_length = t.other_params["chunk_length"].as_u64().unwrap() as usize; - let prio3 = Prio3::new_histogram(t.shares, length, chunk_length).unwrap(); - - let aggregate_result = check_aggregate_test_vec(&prio3, &t); - let expected_aggregate_result = t - .agg_result - .as_array() - .unwrap() - .iter() - .map(|val| val.as_u64().unwrap() as u128) - .collect::<Vec<u128>>(); - assert_eq!(aggregate_result, expected_aggregate_result); + check_test_vec(test_vector_str, |json_params, num_shares| { + let length = json_params["length"].as_u64().unwrap() as usize; + let chunk_length = json_params["chunk_length"].as_u64().unwrap() as usize; + Prio3::new_histogram(num_shares, length, chunk_length).unwrap() + }); } } diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json deleted file mode 100644 index 2ff7aa7ffd..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/IdpfPoplar_0.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "alpha": "0", - "beta_inner": [ - [ - "0", - "0" - ], - [ - "1", - "1" - ], - [ - "2", - "2" - ], - [ - "3", - "3" - ], - [ - "4", - "4" - ], - [ - "5", - "5" - ], - [ - "6", - "6" - ], - [ - "7", - "7" - ], - [ - "8", - "8" - ] - ], - "beta_leaf": [ - "9", - "9" - ], - "binder": "736f6d65206e6f6e6365", - "bits": 10, - "keys": [ - "000102030405060708090a0b0c0d0e0f", - "101112131415161718191a1b1c1d1e1f" - ], - "public_share": "921909356f44964d29c537aeeaeba92e573e4298c88dcc35bd3ae6acb4367236226b1af3151d5814f308f04e208fde2110c72523338563bc1c5fb47d22b5c34ae102e1e82fa250c7e23b95e985f91d7d91887fa7fb301ec20a06b1d4408d9a594754dcd86ec00c91f40f17c1ff52ed99fcd59965fe243a6cec7e672fefc5e3a29e653d5dcca8917e8af2c4f19d122c6dd30a3e2a80fb809383ced9d24fcd86516025174f5183fddfc6d74dde3b78834391c785defc8e4fbff92214df4c8322ee433a8eaeed7369419e0d6037a536e081df333aaab9e8e4d207d846961f015d96d57e3b59e24927773d6e0d66108955c1da134baab4eacd363c8e452b8c3845d5fb5c0ff6c27d7423a73d32742ccc3c750a17cd1f6026dd98a2cf6d2bff2dd339017b25af23d6db00ae8975e3f7e6aaef4af71f3e8cd14eb5c4373db9c3a76fc04659b761e650a97cb873df894064ecb2043a4317ef237ffe8f130eb5c2ca2a132c16f14943cd7e462568c8544b82e29329eb2a" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json deleted file mode 100644 index 79fadca3df..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_0.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "agg_param": [ - 0, - [ - 0, - 1 - ] - ], - "agg_result": [ - 0, - 1 - ], - "agg_shares": [ - "70f1cb8dc03c9eea88d270d6211a8667", - "910e34723ec361157a2d8f29dde57998" - ], - "bits": 4, - "prep": [ - { - "input_shares": [ - "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930", - "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c" - ], - "measurement": 13, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "70f1cb8dc03c9eea", - "88d270d6211a8667" - ], - [ - "910e34723ec36115", - "7a2d8f29dde57998" - ] - ], - "prep_messages": [ - "d4cd54eb29f676c2d10fab848e6e85ebd51804e3562cf23b", - "" - ], - "prep_shares": [ - [ - "bd68d28c9fff9a30f84122278759025501b83270bf27b41d", - "1765825e8af6db91d9cd885d07158396d460d17297043e1e" - ], - [ - "7c9659b7c681b4a4", - "8569a648387e4b5b" - ] - ], - "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json deleted file mode 100644 index a566fe8b4d..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_1.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "agg_param": [ - 1, - [ - 0, - 1, - 2, - 3 - ] - ], - "agg_result": [ - 0, - 0, - 0, - 1 - ], - "agg_shares": [ - "d83fbcbf13566502f5849058b8b089e568a4e8aab8565425f69a56f809fc4527", - "29c04340eba99afd0c7b6fa7464f761a995b175546a9abda0c65a907f503bad8" - ], - "bits": 4, - "prep": [ - { - "input_shares": [ - "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930", - "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c" - ], - "measurement": 13, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "d83fbcbf13566502", - "f5849058b8b089e5", - "68a4e8aab8565425", - "f69a56f809fc4527" - ], - [ - "29c04340eba99afd", - "0c7b6fa7464f761a", - "995b175546a9abda", - "0c65a907f503bad8" - ] - ], - "prep_messages": [ - "d45c0eabcc906acfb8239f3d0ef2b69a0f465979b04e355c", - "" - ], - "prep_shares": [ - [ - "5d1b91841835491251436306076eaaa674d4b95b84b2a084", - "77417d26b45b21bd68e03b3706840cf49c719f1d2b9c94d7" - ], - [ - "6e703a28b5960604", - "938fc5d74969f9fb" - ] - ], - "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json deleted file mode 100644 index 8141bc942e..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_2.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "agg_param": [ - 2, - [ - 0, - 2, - 4, - 6 - ] - ], - "agg_result": [ - 0, - 0, - 0, - 1 - ], - "agg_shares": [ - "7ea47022f22f6be9bce8e0ee2eb522bcbc2d246c17704beed7043426b646fe26", - "835b8fdd0cd0941645171f11d04add4345d2db93e78fb4112bfbcbd948b901d9" - ], - "bits": 4, - "prep": [ - { - "input_shares": [ - "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930", - "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c" - ], - "measurement": 13, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "7ea47022f22f6be9", - "bce8e0ee2eb522bc", - "bc2d246c17704bee", - "d7043426b646fe26" - ], - [ - "835b8fdd0cd09416", - "45171f11d04add43", - "45d2db93e78fb411", - "2bfbcbd948b901d9" - ] - ], - "prep_messages": [ - "6fb240ce8b8a2a8ce62112240f676105e0398515599f04b4", - "" - ], - "prep_shares": [ - [ - "ca0f02c7c61655263bf76d954b8abd16eb6e5ce2b26911b2", - "a5a23e07c573d565ac2aa48ec2dca3eef5ca2833a635f301" - ], - [ - "f5171a3cc9d49422", - "0ce8e5c3352b6bdd" - ] - ], - "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json b/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json deleted file mode 100644 index 1741ec0ebc..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Poplar1_3.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "agg_param": [ - 3, - [ - 1, - 3, - 5, - 7, - 9, - 13, - 15 - ] - ], - "agg_result": [ - 0, - 0, - 0, - 0, - 0, - 1, - 0 - ], - "agg_shares": [ - "ec2be80f01fd1ded599b1a18d6ef112c400f421cca2c080d4ccc5cdd09562b3e556c1aaabe9dd47e8bc25979394c7bb5c61fd1db34b8dfdcc3eff4a5304fb7706b5462025bb400e644f2e0752f38098702491691494a2b498176ef41c4e6a962f716473c53087a3e80db0b9acb50cb15081b5ea4b50c48093f67a8c75875422dfd64ab2fa71fa3f3b55ec708ba4086672aff514d0cffe6f1c07f117c22af9b2c67b2a0c7ec1366ce474721174edb8b9eb33faef5f9c9d0c956e4407a86473120cfa46e8c634c1bc66c63a2009911f82c8426a45013e637aaba0e471b03f0a67a", - "01d417f0fe02e212a664e5e72910eed3bff0bde335d3f7f2b333a322f6a9d4419893e55541622b81743da686c6b3844a39e02e24cb4720233c100b5acfb0480f82ab9dfda44bff19bb0d1f8ad0c7f678fdb6e96eb6b5d4b67e8910be3b19561df6e8b8c3acf785c17f24f46534af34eaf7e4a15b4af3b7f6c0985738a78abd52f09a54d058e05c0c4aa138f745bf7998d500aeb2f300190e3f80ee83dd506453874d5f3813ec9931b8b8dee8b12474614cc0510a06362f36a91bbf8579b8ce5f1e5b91739cb3e439939c5dff66ee07d37bd95bafec19c85545f1b8e4fc0f5905" - ], - "bits": 4, - "prep": [ - { - "input_shares": [ - "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f311e448ab125690bc3a084a34301982c6aa325ab3f268338c9f4db9bda518743ee75c6c8ef7655d2d167d5385213d3bd1be920fad83c1b35fd9239efb406370db4d0a8e97eb41413957e264ded24e074ca433b6b5d451d0f65ec1d4ac246a36da12ecb2a537a449aeeb9d70bd064e930", - "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3f96998a1415c9876c2887f2dcc52f090ec64bcaeb3165e98f47d261a0bed49a156c054b063cad6277a526505ac31807288abfb796b6cee614e5c41ab75c2b9912cc246c66c5e248a7cfc30ad92eefec7e67c2da39726d5b7277eb1449c779f834b0ab75f383f07bd2f3747cb7b98f617c" - ], - "measurement": 13, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "ec2be80f01fd1ded599b1a18d6ef112c400f421cca2c080d4ccc5cdd09562b3e", - "556c1aaabe9dd47e8bc25979394c7bb5c61fd1db34b8dfdcc3eff4a5304fb770", - "6b5462025bb400e644f2e0752f38098702491691494a2b498176ef41c4e6a962", - "f716473c53087a3e80db0b9acb50cb15081b5ea4b50c48093f67a8c75875422d", - "fd64ab2fa71fa3f3b55ec708ba4086672aff514d0cffe6f1c07f117c22af9b2c", - "67b2a0c7ec1366ce474721174edb8b9eb33faef5f9c9d0c956e4407a86473120", - "cfa46e8c634c1bc66c63a2009911f82c8426a45013e637aaba0e471b03f0a67a" - ], - [ - "01d417f0fe02e212a664e5e72910eed3bff0bde335d3f7f2b333a322f6a9d441", - "9893e55541622b81743da686c6b3844a39e02e24cb4720233c100b5acfb0480f", - "82ab9dfda44bff19bb0d1f8ad0c7f678fdb6e96eb6b5d4b67e8910be3b19561d", - "f6e8b8c3acf785c17f24f46534af34eaf7e4a15b4af3b7f6c0985738a78abd52", - "f09a54d058e05c0c4aa138f745bf7998d500aeb2f300190e3f80ee83dd506453", - "874d5f3813ec9931b8b8dee8b12474614cc0510a06362f36a91bbf8579b8ce5f", - "1e5b91739cb3e439939c5dff66ee07d37bd95bafec19c85545f1b8e4fc0f5905" - ] - ], - "prep_messages": [ - "4a2b97cf17e54b126a86c6791c50d6507ee8b74b3d9903bcf3881121bc6e0975c4efb2d8b8a132b8a6caa4eb39ac2bbb5bdc351604fa9e78d1a6f5a5f615bb0c8819f485d8b24a4e48da47d3b7458a9cfde1e85c66453319a3f6d43dc40a0135", - "" - ], - "prep_shares": [ - [ - "4e64e5ed76c69ef68d3e144918a719986e40ab82f34bd30298b0085a3265d16988b8f646731ef47cb2fb1598e4cb817747623f1cc70ee7843ce1a9d6e3cf5c456801c9a3ae0c7c7663349a3daaf8fb51d165085c751e5bdd4e800df9e1e0193e", - "fcc6b1e1a01ead1bdc47b23004a9bcb80fa80cc9494d30b95bd808c78909380b2937bc9145833e3bf4ce8e5355e0a943147af6f93cebb7f394c54bcf12465e470d182be229a6ced7e4a5ad950d4d8e4a2c7ce000f126d83b5476c744e229e776" - ], - [ - "003c39f76240f6f9bcc6065a247b4432a651d5d72a35aff45928eec28c8a9d07", - "edc3c6089dbf09064339f9a5db84bbcd59ae2a28d5ca500ba6d7113d73756278" - ] - ], - "public_share": "b2c16aa5676c3188a74dff403c179dfb28c515d5a9892f38e5eb7be1c96bfdb0ebf761e6500e206a4ce363d09ab0a1d9b225e51798fd599f9dcd204058958c2d625646e5662534ff6650a9af834a248d46304f6d7a3b845f46c71433c833a86846147e264aaee1eb3e0bb19e53cd521e92ab9991265b731bfdb508fb164cd9d48d2c43953e7144a8b97e395bdd8aa2db7a1088f3bf8d245e15172e88764bba8271f6a19f70dc47a279e899394ea8658958", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json deleted file mode 100644 index c27ad93435..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_0.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "agg_param": null, - "agg_result": 1, - "agg_shares": [ - "afead111dacc0c7e", - "53152eee2433f381" - ], - "prep": [ - { - "input_shares": [ - "afead111dacc0c7ec08c411babd6e2404df512ddfa0a81736b7607f4ccb3f39e414fdb4bc89a63569702c92aed6a6a96", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" - ], - "measurement": 1, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "afead111dacc0c7e" - ], - [ - "53152eee2433f381" - ] - ], - "prep_messages": [ - "" - ], - "prep_shares": [ - [ - "123f23c117b7ed6099be9e6a31a42a9caa60882a3b4aa50303f8b588c9efe60b", - "efc0dc3ee748129f2da661f47a625a57d64a5b62ab38647c34bb161c7576d721" - ] - ], - "public_share": "", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json deleted file mode 100644 index 148fe6df58..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Count_1.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "agg_param": null, - "agg_result": 1, - "agg_shares": [ - "c5647e016eea69f6", - "53152eee2433f381", - "eb8553106be2a287" - ], - "prep": [ - { - "input_shares": [ - "c5647e016eea69f6d10e90d05e2ad8b402b8580f394a719b371ae8f1a364b280d08ca7177946a1a0b9643e2469b0a2e9", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", - "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" - ], - "measurement": 1, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "c5647e016eea69f6" - ], - [ - "53152eee2433f381" - ], - [ - "eb8553106be2a287" - ] - ], - "prep_messages": [ - "" - ], - "prep_shares": [ - [ - "5c8d00fd24e449d375581d6adbeaf9cf4bdface6d368fd7b1562e5bf47b9fa68", - "efc0dc3ee748129f2da661f47a625a57d64a5b62ab38647c34bb161c7576d721", - "b7b122c4f1d2a38df764c623c266f02f7b5178c3d64735ec06037585d643f528" - ] - ], - "public_share": "", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 3, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json deleted file mode 100644 index 099f786669..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_0.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "agg_param": null, - "agg_result": [ - 0, - 0, - 1, - 0 - ], - "agg_shares": [ - "14be9c4ef7a6e12e963fdeac21cebdd4d36e13f4bc25306322e56303c62c90afd73f6b4aa9fdf33cb0afb55426d645ff8cd7e78cebf9d4f1087f6d4a033c8eae", - "ed4163b108591ed14dc02153de31422b2e91ec0b43dacf9cc11a9cfc39d36f502bc094b556020cc333504aabd929ba007528187314062b0edb8092b5fcc37151" - ], - "chunk_length": 2, - "length": 4, - "prep": [ - { - "input_shares": [ - "14be9c4ef7a6e12e963fdeac21cebdd4d36e13f4bc25306322e56303c62c90afd73f6b4aa9fdf33cb0afb55426d645ff8cd7e78cebf9d4f1087f6d4a033c8eaeec786d3b212d968c939de66318dbacafe73c1f5aa3e9078ba2f63ec5179e6b4694612c36f5d4d539d46dab1ac20e43963978d9dd36f19f31c83e58c903c2cd94215c68b15f5d6071e9e19fa973829dc71b536351b0db1072e77b7570e3e06c65fac248d21dd970f29640050e901d06775f05a897850cab5707ac25543ed6ce7061b9cd70c783e0483727236d0cbb05dafefd78ec4e6419efe93d6f82cdadbfd4e860661238040229f60205bbba983790303132333435363738393a3b3c3d3e3f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - ], - "measurement": 2, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "14be9c4ef7a6e12e963fdeac21cebdd4", - "d36e13f4bc25306322e56303c62c90af", - "d73f6b4aa9fdf33cb0afb55426d645ff", - "8cd7e78cebf9d4f1087f6d4a033c8eae" - ], - [ - "ed4163b108591ed14dc02153de31422b", - "2e91ec0b43dacf9cc11a9cfc39d36f50", - "2bc094b556020cc333504aabd929ba00", - "7528187314062b0edb8092b5fcc37151" - ] - ], - "prep_messages": [ - "7556ccbddbd14d509ee89124d31d1feb" - ], - "prep_shares": [ - [ - "806b1f8537500ce0b4b501b0ae5ed8f82679ba11ad995d6f605b000e32c41afb6d0070287fe7b99b8304d264cba1e3c6f4456e1c06f3b9d3d4947b2041c86b020d26c74d7663817e6a91960489806931b304fcd3755b43b96c806d2bbeb0166bbec7c61c35f886f3f539890522388f43", - "8194e07ac8aff31f2f4afe4f51a12707b692a56a1745315a1022b4eb257b2a8725c610416af7b0d1a296f409cdb3fbf4f4c0d488206d794254e4755fd124cdc9a67364ddc7865afe3554de5f52f1ac910f3f8e110cfbad4113861316dc73ec60de4f6c512adaa41de631eda8d6d8c189" - ] - ], - "public_share": "bec7c61c35f886f3f539890522388f43de4f6c512adaa41de631eda8d6d8c189", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json deleted file mode 100644 index 0b9a9b4d5d..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Histogram_1.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "agg_param": null, - "agg_result": [ - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "agg_shares": [ - "a6d2b4756e63a10bf5f650e258c73b0ccb20bace98e225dea29d625d527fdd4ded86beb9a0a0ac5c4216f5add7a297cece34b479a568a327f1e259839f813df97b34de254be5b9b9c8d9e56dbff50b7a6bf1e5967686755a1dc42e0ab170add8c88f8ca68f945e768a5007c775fd27cfecb4495e257a2f2f94ca48830aa16ec0decaeee645e295c5dc2ebe491aae1a7f17b2807fcb33ee08127db466067bf84ec613dac9c93adbe73dd262c1859b2865", - "ed4163b108591ed14dc02153de31422b2e91ec0b43dacf9cc11a9cfc39d36f502bc094b556020cc333504aabd929ba007528187314062b0edb8092b5fcc3715126e16ce274ad58caaa14d22608269a4c41a256d3c9e847c0a6ac1a4fbaf6309e9ccbe74a9442ca956d843d6bd5adf9797a84557597d9cc81ddfa281ae5048d686bdb289ec2f3c96cdfa79b6974e6d15aec047748636d4358226283e11a78e045f59db2dda566162a56c85936ac0f4696", - "6eebe7d888434023a1488dcac80682c8084e592524430a857f4701a673adb261eab8ac90085d47e06d99c0a64e33ae30bfa23313469131cafb9b13c763ba50b560eab4f73f6ded7b7011486b38e45939566cc395bf9042e5038fb6a6949821899ea48b0edc28d7f3cf2abbcdb454deb69cc6602c43ac034f563a8e62105a04d7b859e87af729a0cd2729a64c716b1326fe480838d15ece9eaf20c8b7de0c276b464e7358905e0eee4f654308ce549104" - ], - "chunk_length": 3, - "length": 11, - "prep": [ - { - "input_shares": [ - "a6d2b4756e63a10bf5f650e258c73b0ccb20bace98e225dea29d625d527fdd4ded86beb9a0a0ac5c4216f5add7a297cece34b479a568a327f1e259839f813df97b34de254be5b9b9c8d9e56dbff50b7a6bf1e5967686755a1dc42e0ab170add8c88f8ca68f945e768a5007c775fd27cfecb4495e257a2f2f94ca48830aa16ec0decaeee645e295c5dc2ebe491aae1a7f17b2807fcb33ee08127db466067bf84ec613dac9c93adbe73dd262c1859b2865508d344dda6c4339e650c401324c31481780ef7e7dcc07120ac004c05ab75ee5d22e2d0eb229dcdd3755fab49a1c2916e17c8ed2d975cfe76d576569bf05233c07f94417fccaf73d1cc33e17dae74650badffdd639a9b9f9e89de4b9fd13e258b90fbb2b3817b607dc14e6e5327746ca20d1f1918bce9714b135ffe01eb4e6aefab92b0462f7e676e26007e8c2e5a66e16f32f7c8457a6dfba39d9082f640006d560b4d64e86e2e2358c84e03b857c980f51b1a78b53f7cb44343ed184d8dc87ebf8698609eeefae5d8882224ebd28b9531015badea8ae9fe01c7495cafecdc4f13389ea4eb0bbce0a5ab85aa6fc06aabd96d28c84ecf039bfeb4c350049485f8a4c706a109164ff4c640edaedd0ad50820b1d1ed7ab08fc69c48b39aff1eebc02ef1ea40bd70784bfa50511c3dd64b107f4297842280c3cff8d94be202a0e2cb0090f3adb2189f445fcf291f452f162606162636465666768696a6b6c6d6e6f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", - "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" - ], - "measurement": 2, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "a6d2b4756e63a10bf5f650e258c73b0c", - "cb20bace98e225dea29d625d527fdd4d", - "ed86beb9a0a0ac5c4216f5add7a297ce", - "ce34b479a568a327f1e259839f813df9", - "7b34de254be5b9b9c8d9e56dbff50b7a", - "6bf1e5967686755a1dc42e0ab170add8", - "c88f8ca68f945e768a5007c775fd27cf", - "ecb4495e257a2f2f94ca48830aa16ec0", - "decaeee645e295c5dc2ebe491aae1a7f", - "17b2807fcb33ee08127db466067bf84e", - "c613dac9c93adbe73dd262c1859b2865" - ], - [ - "ed4163b108591ed14dc02153de31422b", - "2e91ec0b43dacf9cc11a9cfc39d36f50", - "2bc094b556020cc333504aabd929ba00", - "7528187314062b0edb8092b5fcc37151", - "26e16ce274ad58caaa14d22608269a4c", - "41a256d3c9e847c0a6ac1a4fbaf6309e", - "9ccbe74a9442ca956d843d6bd5adf979", - "7a84557597d9cc81ddfa281ae5048d68", - "6bdb289ec2f3c96cdfa79b6974e6d15a", - "ec047748636d4358226283e11a78e045", - "f59db2dda566162a56c85936ac0f4696" - ], - [ - "6eebe7d888434023a1488dcac80682c8", - "084e592524430a857f4701a673adb261", - "eab8ac90085d47e06d99c0a64e33ae30", - "bfa23313469131cafb9b13c763ba50b5", - "60eab4f73f6ded7b7011486b38e45939", - "566cc395bf9042e5038fb6a694982189", - "9ea48b0edc28d7f3cf2abbcdb454deb6", - "9cc6602c43ac034f563a8e62105a04d7", - "b859e87af729a0cd2729a64c716b1326", - "fe480838d15ece9eaf20c8b7de0c276b", - "464e7358905e0eee4f654308ce549104" - ] - ], - "prep_messages": [ - "4b7dc5c1b2a08aec5dcfc13de800559b" - ], - "prep_shares": [ - [ - "e80c098526d9321dd0801f97a648722016fa117f10cb2b062fc5fb1e55705894007f838333ef348c6306e141369bd88d123c66d2faeb132e330a73882c38765d425847bd86e5f784b3348ee4840c5df103b49f04c4dcca4667abb956187da58c91c946d9d5fdf496d95428f8a625dddfc8b7bb469397ebd4b177f902896febdaac39a8d9ec0aa1a24132036c2430929c", - "4f6d4137ddffd58b243b8f845a1684550b240ea3e91a68335f717b83056e9b45c5e62d7a24da54147fcb9260d023cb7f9c8d036f0100f5fea0ce22f49e3d7672bc83fd5c724f2684f3442e8c5291c41509151808d1da447cddc3fe11cf5cd8d7fe662cf035eff88b583f6b32499b332aa6dee37947ef482e15fcb3a7f04b20813162d162b9bf30eee4953b6fdabd10f1", - "ca85b543fc26f756ef4351e4fea0098a73787eeab8b613029af310882b7e87d28fc5502fd76bd704626d9f0f662e531feaf1fa912cc209de6541401d8508a4788d92e549f58241334cfa29abc1fb80a28ae61d7a4060d9582e3e20f182e4519ab1bb9547c545aafc21416e779856c80cf3690155119111aebf3800757989229e4966453f7aa269163b272848de80227f" - ] - ], - "public_share": "ac39a8d9ec0aa1a24132036c2430929c3162d162b9bf30eee4953b6fdabd10f14966453f7aa269163b272848de80227f", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" - } - ], - "shares": 3, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json deleted file mode 100644 index a7178fcfee..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_0.json +++ /dev/null @@ -1,194 +0,0 @@ -{ - "agg_param": null, - "agg_result": [ - 256, - 257, - 258, - 259, - 260, - 261, - 262, - 263, - 264, - 265 - ], - "agg_shares": [ - "cdeb52d4615d1c718ef21a6560939efcb5024c89ea9b0f0018302087c0e978b5b5c84c8c4f217b14584cc3939963f56a2718c17af81d1f85129347fc73b2548262e047a67c3e0583eeef7c4a98a5da4ccdb558491081a00a8de5a46b8c2f299bc69162a7411b3ecf2b47670db337083dc50b8fc6d5c5d21da52fc7f538166b0e4564edd8fbb75bc8c4fdd0c02be2b6d11bc4a159297b72e2c635a9250feb2445", - "3415ad2b9ea2e38e550de59a9f6c61034dfeb3761564f0ffcbcfdf783f16874a4e38b373b0de84eb8bb33c6c669c0a95dde83e8507e2e07ad16cb8038c4dab7da320b85983c1fa7cf50f83b5675a25b3394ba7b6ef7e5ff5561a5b9473d0d664416f9d58bee4c130b8b898f24cc8f7c243f570392a3a2de23ed0380ac7e994f1c49c12270448a4371f022f3fd41d492eef3c5ea6d6848d1d1dca56daf014dbba" - ], - "bits": 8, - "chunk_length": 9, - "length": 10, - "prep": [ - { - "input_shares": [ - "2451f59efba2edc493c9246ff1f0e0a7f8f6f22ee46e662c899e485d7ce288d6becdfee804a39618972fbaa595eeec25423e412cbe51d44a62747de627630302368ec3535a2545a2799e8a0b9a144c811158dda278865d834b34fbe77ad11dbb9fdcf0637c24e10d5ab36d03cdc5f6b95e400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938368d5621cff66585454ef124daa5f18efd7e791a4bcb11caf74b378e2c4feff3e5bad16e7c3fab987eb4d4a0c675bb4f4e70e1373fb00a5dd30a1118355c20e2e4c3700be3d3c1cf25d3e4a729836ba564aa074f99be0d23d4cc0dc9f263c986988e0d16a3d28c262d34f220b1ed127cddea3e2a1bd075c653d4b6f1c3d35e25d2804e7960250dea42dc4a52c9545bedc182ee8391b4c6849366af8e15f30bd06872e5ed651ef7db0b0c442886de32eeeeacc5f2dfe87f9375b4774153fc9e442105b5f8e452e80874c84131400d4d588a1a5d94bac9e68dbf917ef6405b0bc13fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b9d728fc0c96ff898ed46bd289abbec9917397552ebf6d1eb3f916f69ee9f80e9466512bff70af2d8f3a9ed599f24e33550a09304e1b4f51948e2d8cbf5a1bb14455b1786ae3af4670111bc3983293ad9ae029128efd86d0a05cb3f442b43f466cec5cc9c4989bf5a29eb5c2401bc8bba0d5b7487bc0bf010c968fe76e3a9924459dce6704528d56540081240ed0d2f301a8c9baca5c183b1b5c3a9c03dce5036926d06e1470c2e63d15fdc3a61056154fca9439c595098ff3794c7d7e62af5e3139b43e22a0f8864c254a069a083604762d77ea000177a7b908efe27f6e00db7ea25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311dcedf0ea031688b2cf8c5248f21be444f1c61b050a0ab7dca04992673afb737bd27526a72dda3b03dad4d3b0bb81f0887ee6f25ec4cf35d58ea5f085e97609cfb6a8e97d84fdf8755b8e81ff29614bf1b03bcd2b8d9ab06dc4d60785f83eb6ee4573859223214ecdad734d114e15e1971a8b82222910fd041a1123a4e792a9239f99252de3e3e8d5bb209e2c9bda506a79853c482546940364a8246392fb5e18e85847458445fe3a970b29db6d3d0e4a806cfec7c8538f24896d2d10669113f2b724161d2007ee75c0b651f4934046142b04b2015212997c609625bbeb81b9fa0249c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7c8b13bded6ba43ed8b92f6ba7879b39932468260c5768ca0909aae899ad1252c5dbcd741d971f179bc36e88a0a10981f73202cb25db324da405fdd5ca5331431afe362c5f933b3c1216c3e19140cd27f7c2ef67898887856a46a518a3afec78ee0d9dce778289a38d2df906932c40019afadab12fe7d0695316e5a3c1e38aa630a44bc8cc01a5a8cae060b7de435e54963b9354182d64e340ec9dc3e37f8b2bbaaab23608b86827991df4367839f443c160c1eb77f41159f69592c3eb37c21a521afcd34036a13a145e9cb1039704b8e523359ea5c3a50f705118ea7d8b1063eb85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce918a98514903c63a3476d6ebe68e2503e6bf255691fbd8a006e9c77f5a4ad9e3e8d21a56bc4f7bc90d61ebb31eaa4dce48eb9a8069a584ae35266a4bc4af970860d2e9a0df7b87e8fc8b597e73a85d8eeb91def6057d7a77e8f859ee9ee07ef2fb2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4d37d8c2a17e97468cf923a5388eb0d1de61358e9651a7e76b033d32d6c84e7ed5831a990b46e8228b6ef120643049645b82e100a7ed6ddd2ebfe2dcbd8b0e7ac1e5ee021d4279f164acc47875ade2c0acff5dbbf3a6eb0e8601632c926780be1660270420aa02c99fb39af1852b09904791e90cfa1f02aec0ab2de111524394819527819e52d495196ab3aff1e323dfec07af91e18b9a04e37552a23b13177bdcfc64ec7108e5e9b3679ccdf6b1e998e2bbcd5fbbbebf5ad8008e727cae6499cc06aa03809947e298683a4340f51d6eecad38d0a7a5437dd6e72bce6543b81fd3a438d71e232845cdb403f1011295f9aee5e33352b86e92343985884284c9646da13545f37b9d6da7d0cf902c19a5ca1f4f1818a2c2644807fcc54be35c29f96fb4fea5efdc88b270f1c5504bd8ba558834786020cc2f03ab5c56eaea38532b9faf6208f57d970b2e5ff92872713c9e0ad07b26e72dca6f9a9c02bad6c9db4d1d738f306292f14415d2856c2b073c5d8faf89e9713ceb375b6eefabc240bf6c6bf39cafb99993767dbaf5ee5f4b3f93e638e904fb55f443312c145b809fd203b5b3a16bd229b952e100bbfc0e49bbd05d54c3e5fa1a44fe55de16cfa52f3b169e0bfe95b1b8b6367f9309adfe3df079104fd720d46d772def3c0534d73615071fa22a79af875f796478d2f599dbb4c1ed303132333435363738393a3b3c3d3e3f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - ], - "measurement": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "9aa31b9c201fb42526a6b32120318aa9", - "e8551983a3deafaafe0f608295f8d291", - "3eed6ed96f607eb1be6e96868876fc78", - "65b295d3525f0ad74886c2fe7b3b1cd6", - "794a6d37d41457d6f04fd418888cf36e", - "483cc86d052be058d0a1e12384ba0d89", - "9c85cb376b5ebfeffb6c22af3bbd02bf", - "9c0385979cecf00983ba97fc12b2235a", - "c7cbf9f2533dc942eca94540b9a0e745", - "0f418bc80d2926f6ec11e3615a4e0c17" - ], - [ - "675ce463dfe04bdabd594cdedfce7556", - "1aaae67c5c215055e5ef9f7d6a072d6e", - "c5129126909f814e2591697977890387", - "9f4d6a2cada0f5289b793d0184c4e329", - "8cb592c82beba829f3af2be777730c91", - "bec33792fad41fa7135e1edc7b45f276", - "6b7a34c894a14010e892dd50c442fd40", - "6cfc7a6863130ff660456803ed4ddca5", - "4234060dacc236bdf755babf465f18ba", - "fbbe7437f2d6d909f7ed1c9ea5b1f3e8" - ] - ], - "prep_messages": [ - "db085315822777376b4d0f962d8f06d9" - ], - "prep_shares": [ - [ - "e6a4fe7264f95c384446bd51db14f78e7f4133afed0604aeb3b87125fc076c7447d795723adfe93d85f9fe2993c52420e45694fd2ec164a54a7267ee5efc8cb40b6659ac81f2e850786218bcec469ec4f7bb28e875d75ee98d54d566186c61c35448a50cb11e195d886622861a78bbb74325b7972e7b4c47f0e2e10a15d7a33c3daecb2dfc507b1b6676c1e9bfc52a4873f408a5788e7b77ce6943e67f3f457280544d93b81b08e427f699ba54adcbb0ffab83366d9b336846c0c989f0bc25bdd14683f1a85e844b9dbac26daae84cc8d57ef6b0c340798ac5ade63150e8d7a9673b64d798a97cf2715f399fd371e342c1ad50e28431f54180ef63ad7dd21f3e5d8d67159cacfd56f5d99c39d53047c8d7bf11ad83a2e3e569e1393b12d87d01701fa71b50b51e092ca6b797bb97890efb6327f1c4e488663dca5f00675c2af7368a9ab95b3c4e9e1a8dd5430d336833", - "1b5b018d9b06a3c79fb942ae24eb087131693625114418115cb3e54a45056eabd0f6e371501957e00796db78ea8f3388eb8345e938f5fbdd8b24c3a968276d7c457ff43ce93631942f823f5bb9c6d1335b8022e804072711cb8fa5fb3afb209e696c9cac47da44cdc3eb3874eb0d8c89692408b463df12bb2d6e8193d5829cce221e486a579b91cd10a0fb38fec7214a9008d574ba32615f6215aef827a2962a31df892814bd8b8f828d029f07f6acf490e7ecd3377f10b86ec2d5741ba37a3a9522b897e840e315a614a89d0bcf8296bdd45e330eaf3f34b3ce4e1dd41306eae92147fc6676eedff2cb239581f46750df341390e066dabb01ef6362694f923d5a65dbc5252a8da8702a979aca3e211af7124485c1c7dc68f6fb1bdfb9a4d0d993cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb" - ] - ], - "public_share": "368a9ab95b3c4e9e1a8dd5430d3368330a3dfc6f55bb428773ce15071cb720fb", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - }, - { - "input_shares": [ - "2551f59efba2edc493c9246ff1f0e0a7f8f6f22ee46e662c899e485d7ce288d6becdfee804a39618972fbaa595eeec25423e412cbe51d44a62747de627630302368ec3535a2545a2799e8a0b9a144c811158dda278865d834b34fbe77ad11dbb9fdcf0637c24e10d5ab36d03cdc5f6b95e400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938368d5621cff66585454ef124daa5f18efd7e791a4bcb11caf74b378e2c4feff3e5bad16e7c3fab987eb4d4a0c675bb4f4e70e1373fb00a5dd30a1118355c20e2e4c3700be3d3c1cf25d3e4a729836ba564aa074f99be0d23d4cc0dc9f263c986988e0d16a3d28c262d34f220b1ed127cedea3e2a1bd075c653d4b6f1c3d35e25c2804e7960250dea42dc4a52c9545bedc182ee8391b4c6849366af8e15f30bd06872e5ed651ef7db0b0c442886de32eeeeacc5f2dfe87f9375b4774153fc9e442105b5f8e452e80874c84131400d4d588a1a5d94bac9e68dbf917ef6405b0bc13fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b8d728fc0c96ff898ed46bd289abbec9917397552ebf6d1eb3f916f69ee9f80e9466512bff70af2d8f3a9ed599f24e33550a09304e1b4f51948e2d8cbf5a1bb14455b1786ae3af4670111bc3983293ad9ae029128efd86d0a05cb3f442b43f466cec5cc9c4989bf5a29eb5c2401bc8bba1d5b7487bc0bf010c968fe76e3a9924459dce6704528d56540081240ed0d2f300a8c9baca5c183b1b5c3a9c03dce5036926d06e1470c2e63d15fdc3a61056154fca9439c595098ff3794c7d7e62af5e3139b43e22a0f8864c254a069a083604762d77ea000177a7b908efe27f6e00db7ea25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311dcedf0ea031688b2cf8c5248f21be444f0c61b050a0ab7dca04992673afb737bd27526a72dda3b03dad4d3b0bb81f0887ee6f25ec4cf35d58ea5f085e97609cfb6a8e97d84fdf8755b8e81ff29614bf1b03bcd2b8d9ab06dc4d60785f83eb6ee4573859223214ecdad734d114e15e1971b8b82222910fd041a1123a4e792a9239e99252de3e3e8d5bb209e2c9bda506a78853c482546940364a8246392fb5e18e85847458445fe3a970b29db6d3d0e4a806cfec7c8538f24896d2d10669113f2b724161d2007ee75c0b651f4934046142b04b2015212997c609625bbeb81b9fa0249c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7b8b13bded6ba43ed8b92f6ba7879b39922468260c5768ca0909aae899ad1252c5dbcd741d971f179bc36e88a0a10981f73202cb25db324da405fdd5ca5331431afe362c5f933b3c1216c3e19140cd27f7c2ef67898887856a46a518a3afec78ee0d9dce778289a38d2df906932c40019bfadab12fe7d0695316e5a3c1e38aa630a44bc8cc01a5a8cae060b7de435e54963b9354182d64e340ec9dc3e37f8b2bb9aab23608b86827991df4367839f443c160c1eb77f41159f69592c3eb37c21a521afcd34036a13a145e9cb1039704b8e523359ea5c3a50f705118ea7d8b1063eb85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce918a98514903c63a3476d6ebe68e2503e6bf255691fbd8a006e9c77f5a4ad9e3e7d21a56bc4f7bc90d61ebb31eaa4dce48eb9a8069a584ae35266a4bc4af970860d2e9a0df7b87e8fc8b597e73a85d8eeb91def6057d7a77e8f859ee9ee07ef2fb2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4d42a21c0a30addfe4b4176740f9a418eca631cda9a8b94d20c7f9b834ed87751464dc5e5b446d920312003e4673b48c6c12b407af1ed90002507883f78d166f0b90bc14ed77d4aec6220cdd51948cdad29ab70513aadccd0e3c8c8108d3b0722602d9612aa6feb323a4ff3e8fe0e3d5701467491acdd3c71c34bc019047647779922216ccd61c47958461e3017adf446c4bd2ab7fbf70e41419679f6a9b3fa4c9aa5e9ef8469ace0d88bc35a3374f462573d2ba24b712359ef36e413006a9883bfa4fad43d89c7f1732725e3cad482d17a9499e1fb0f57d1ca93cafa7fd6d654a70cd7318bd7ace30e981217317105bcfe5e33352b86e92343985884284c9646d966beb8aca87d44e15dcce24aeb08312091cd98e6b52e2525409c58438f00131d33ce09fde0343f84db73369954f2d77a3a559189bc4dfd7e7c043b1364b36550595f624483c4eccccb1c4958a9284e43522dcc72ad9b01162d964605eab990dd1ddd25796f55991e1201f22526117662c0cad518f191effe5608b444b9e8973f5a11a8c154bc501bc47bb4fb5832d67f4c5ea5c221e64ff88ff5d5117aadac704a8b94beb036e87fc9a9462c355231b9bbe8a9122f12390073600f2d7f6262f1758eced79619900cad1910286c5bae553c6525c63c52ca97bf452957c5fc1a7d695dcb5ed0cf0004454c528d63960cd303132333435363738393a3b3c3d3e3f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - ], - "measurement": [ - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "9ba31b9c201fb42526a6b32120318aa9", - "e8551983a3deafaafe0f608295f8d291", - "3ded6ed96f607eb1be6e96868876fc78", - "63b295d3525f0ad74886c2fe7b3b1cd6", - "764a6d37d41457d6f04fd418888cf36e", - "443cc86d052be058d0a1e12384ba0d89", - "9785cb376b5ebfeffb6c22af3bbd02bf", - "960385979cecf00983ba97fc12b2235a", - "c0cbf9f2533dc942eca94540b9a0e745", - "07418bc80d2926f6ec11e3615a4e0c17" - ], - [ - "675ce463dfe04bdabd594cdedfce7556", - "1aaae67c5c215055e5ef9f7d6a072d6e", - "c5129126909f814e2591697977890387", - "9f4d6a2cada0f5289b793d0184c4e329", - "8cb592c82beba829f3af2be777730c91", - "bec33792fad41fa7135e1edc7b45f276", - "6b7a34c894a14010e892dd50c442fd40", - "6cfc7a6863130ff660456803ed4ddca5", - "4234060dacc236bdf755babf465f18ba", - "fbbe7437f2d6d909f7ed1c9ea5b1f3e8" - ] - ], - "prep_messages": [ - "fdecd6d197e824492dd550fcdd0aa3c7" - ], - "prep_shares": [ - [ - "e6a4fe7264f95c384446bd51db14f78eec654b5beb7d60677c0b8385ca51a5bf896c79a069b04f339fdcb675885a26f533ec0d6e805beef6d7683a8ecdfa46cb87fdbc532efa5b1041347ed94f54fbca15041d013729d5eb78dcb1a1c293e0035448a50cb11e195d886622861a78bbb7bccc68d521fac002ece757cc5d82afb3b0f9f8766a1714047b50417a8e7f63eacf222c675bdf1d3e8362806ef5f9c16c446a1e5e06ce539aa300bc68c837c9207c5dbc7d85f896fb1be725e461ceacd303716a2cd8005e370a8ac1062d966b5c1499813d0dc63d697c4fd44dcfe81b3cfc37952de43649650c52ca9f2044fd3dfc42cd08bf0659e6a7facee2468ad1b07903a933ec3cbd06a5f81461e434449c32ef6678f3c8fd250c0b3318e80235144a96f07af2169dfddb503b38a2039f80f6bdfbbec6b3ad1025a43a90249221d20e627a73e2ed92bf1920574f42775675", - "1b5b018d9b06a3c79fb942ae24eb0871aba638b677efec2418d7921020c44ff8d0f6e371501957e00796db78ea8f338813d41fd058418e6056a93bb2785cec1d457ff43ce93631942f823f5bb9c6d133fbfbf9d10fa7922dccd1e570b0246775696c9cac47da44cdc3eb3874eb0d8c89fcdfd722a57116825749c8972129304c221e486a579b91cd10a0fb38fec7214af0fe63f4a24e9e189e180a8aaed3b22931df892814bd8b8f828d029f07f6acf402eb7c22aea07b55e871ebdf6475ae509522b897e840e315a614a89d0bcf8296c0b0d5b745f277689643e3da46c09a1ce92147fc6676eedff2cb239581f46750fa1947870c81f9d565f51ed7e09d86dc5a65dbc5252a8da8702a979aca3e211ae9def20e5f2fa85d16e3ccb0a917510793cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb" - ] - ], - "public_share": "0e627a73e2ed92bf1920574f427756750a3dfc6f55bb428773ce15071cb720fb", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - }, - { - "input_shares": [ - "2551f59efba2edc493c9246ff1f0e0a7f9f6f22ee46e662c899e485d7ce288d6bfcdfee804a39618972fbaa595eeec25433e412cbe51d44a62747de627630302378ec3535a2545a2799e8a0b9a144c811258dda278865d834b34fbe77ad11dbba0dcf0637c24e10d5ab36d03cdc5f6b95f400a0a81608d96c25733c376376de3927c3570e8ab671358a1686d0c44ac938468d5621cff66585454ef124daa5f18f0d7e791a4bcb11caf74b378e2c4feff3f5bad16e7c3fab987eb4d4a0c675bb4f5e70e1373fb00a5dd30a1118355c20e2f4c3700be3d3c1cf25d3e4a729836ba574aa074f99be0d23d4cc0dc9f263c986a88e0d16a3d28c262d34f220b1ed127cedea3e2a1bd075c653d4b6f1c3d35e25d2804e7960250dea42dc4a52c9545bedd182ee8391b4c6849366af8e15f30bd07872e5ed651ef7db0b0c442886de32eefeacc5f2dfe87f9375b4774153fc9e443105b5f8e452e80874c84131400d4d589a1a5d94bac9e68dbf917ef6405b0bc14fa89daf46f84405aedb166ac93f6545256b1da6ac65e01d580bb26eef82c34b9d728fc0c96ff898ed46bd289abbec9927397552ebf6d1eb3f916f69ee9f80e9566512bff70af2d8f3a9ed599f24e33560a09304e1b4f51948e2d8cbf5a1bb14555b1786ae3af4670111bc3983293ad9be029128efd86d0a05cb3f442b43f466dec5cc9c4989bf5a29eb5c2401bc8bba1d5b7487bc0bf010c968fe76e3a9924469dce6704528d56540081240ed0d2f301a8c9baca5c183b1b5c3a9c03dce5036a26d06e1470c2e63d15fdc3a610561550ca9439c595098ff3794c7d7e62af5e3239b43e22a0f8864c254a069a083604772d77ea000177a7b908efe27f6e00db7fa25f573734af803044fb2dc333ed9ad589d7677e23614143fa6836d68ed311ddedf0ea031688b2cf8c5248f21be444f1c61b050a0ab7dca04992673afb737bd37526a72dda3b03dad4d3b0bb81f0887fe6f25ec4cf35d58ea5f085e97609cfb7a8e97d84fdf8755b8e81ff29614bf1b13bcd2b8d9ab06dc4d60785f83eb6ee4673859223214ecdad734d114e15e1971b8b82222910fd041a1123a4e792a9239f99252de3e3e8d5bb209e2c9bda506a79853c482546940364a8246392fb5e18e95847458445fe3a970b29db6d3d0e4a816cfec7c8538f24896d2d10669113f2b824161d2007ee75c0b651f4934046142c04b2015212997c609625bbeb81b9fa0349c167196557c08ae9ea2defcf7859eed4d35b2183c628cb82fe01255e558e7c8b13bded6ba43ed8b92f6ba7879b39932468260c5768ca0909aae899ad1252c6dbcd741d971f179bc36e88a0a10981f83202cb25db324da405fdd5ca5331431bfe362c5f933b3c1216c3e19140cd27f8c2ef67898887856a46a518a3afec78ef0d9dce778289a38d2df906932c40019bfadab12fe7d0695316e5a3c1e38aa631a44bc8cc01a5a8cae060b7de435e54973b9354182d64e340ec9dc3e37f8b2bbaaab23608b86827991df4367839f443c260c1eb77f41159f69592c3eb37c21a531afcd34036a13a145e9cb1039704b8e623359ea5c3a50f705118ea7d8b1063ec85bfcdc941e0235579e97856ee6f6bfe9c4d0d161b5662de26a2fbddc530ce928a98514903c63a3476d6ebe68e2503e7bf255691fbd8a006e9c77f5a4ad9e3e8d21a56bc4f7bc90d61ebb31eaa4dce49eb9a8069a584ae35266a4bc4af970861d2e9a0df7b87e8fc8b597e73a85d8eec91def6057d7a77e8f859ee9ee07ef2fc2260660e59ee16458eafbd7bab979ed9bf72c1c27cadc9011f563aeed9a4b2f09ce5455857bcf3acbe0e1cf15537594469c777a885ad24ac5a8c894a8257c5212fb46184ad7f280bc25600129b25bf941460fcdd2e45a0216f1f2fec84d4792a15f877d15c649991ef998621a50a04251257ed6ccd803fdbc83ce4b5c4d7e8ee4487848768384e0b3970ec899dfb423560e755c4716deb3e188ca780cc7a97e8fb80076e9c44c6b7575725253ae4605844c3748bf90c14f17ee80a42fea450c05eb1f251eb09855f2ab368047d68cd7f4b8898d0113d52117375eed77707e7abff8554dc7da30cca674ac587198c0f165a47a5db79e9cc1c7bda9cdc36b94f14141a307850062f4d7208b8c612691699e3e3c16c3fc2dc6604e0fcb27acd6b5d326d2663a3f819589176c70423bc4dc97f402ea5053f2aa068d42c371d327339bd8637472eb9be88e409688a53bff392a8891c96c7804998d761fcf34dbf8da8cb17567f75ab4be29ecb6c33c85bf572b645bb7b226e4b99ccc0d959e6d809ec45b70cefe5ada611ea14962c9788d3e15100872669baf3c07a424cc205db97c0e2f72880a40a48d3820f89a16c7ee9dbc44bea18d787e0b730093a7b1fe4f9fd3e50128c61f6d4179fde88b02629629bf9f56f15abe3860ad2c99eaee9eba2310ca898fee5103f7bcb11ec9f4154007cf7d2b51a173331576526665d9f90879a2122b2bdef3a2cff68e57b146ae6d99a4e247d0daa693ef0a07aadc1a4b25ce5e33352b86e92343985884284c9646d0f8ec766552f75092a8b613870386a8b77901f01cddd76b4761e74519b24b851a570b5de8ca954b2c7df0fb314b6fa550e8e49713a28358e399afb3b9199496b229bc55644ee8e4772f1e00dc53886ade4932acee5cfd079707bd1d204c58360f26434fb158b53c1c4a51b65703f123f8090fe42dc48dbd3469a7d4bf1958203adffe46dd39084b66c789517b4438ed9415946ca552d523fa6c71e3302c3552f140d62d41cf3580e5e8500674cbb7d9ddd849d1ddb1d48ef7fd92f363e5e5b6a95b0c67b37e7e5e6a4dec9d8d56e577562eecec955cb6f9925c81cc165634018ab142c519ddd54f358356cee2ba50840303132333435363738393a3b3c3d3e3f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - ], - "measurement": [ - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255, - 255 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "99a41b9c201fb42526a6b32120318aa9", - "e6561983a3deafaafe0f608295f8d291", - "3bee6ed96f607eb1be6e96868876fc78", - "61b395d3525f0ad74886c2fe7b3b1cd6", - "744b6d37d41457d6f04fd418888cf36e", - "423dc86d052be058d0a1e12384ba0d89", - "9586cb376b5ebfeffb6c22af3bbd02bf", - "940485979cecf00983ba97fc12b2235a", - "beccf9f2533dc942eca94540b9a0e745", - "05428bc80d2926f6ec11e3615a4e0c17" - ], - [ - "675ce463dfe04bdabd594cdedfce7556", - "1aaae67c5c215055e5ef9f7d6a072d6e", - "c5129126909f814e2591697977890387", - "9f4d6a2cada0f5289b793d0184c4e329", - "8cb592c82beba829f3af2be777730c91", - "bec33792fad41fa7135e1edc7b45f276", - "6b7a34c894a14010e892dd50c442fd40", - "6cfc7a6863130ff660456803ed4ddca5", - "4234060dacc236bdf755babf465f18ba", - "fbbe7437f2d6d909f7ed1c9ea5b1f3e8" - ] - ], - "prep_messages": [ - "190c0ef07d6f2cbd1bed12d71b5f118d" - ], - "prep_shares": [ - [ - "e6a4fe7264f95c384446bd51db14f78ef1ffdfc96013014baff7bd0684b8ff3360f6a2a23b1d7b71796b845eeb21e7d1682128dc8b87837803fec0e3bd6c548d5cc9c041a482cbfc38120743a2f1a0985053eaeccc339c56c2edf76451e22c9a1bca6ab2181850f44d904964d1f227a970e70b59328028ddafdb1649a8c4f1f7cbeb366e42f8603a7b627f7519f25617a33726ede06ab438714b4bd3cda025dc2bcab64974eb02b9e2a23bf0cab4e5ef1e87bb1a72767098c768a20e1090a712ed38c1e8803fd18181cc0069355b40f5f98ff3cbd2b31022df719d9c660e7d5bab239819730ad9165a38641379444093ba148996166ccf5e2826bddb7a7dc8eda4dd5928b12e1ea715538788804b5ce231dfc98ff45027ff8cb1f92007f2339621201a7dc483c83bb6df082105cb5f5d9eda1f847b3d43b4e16502062d5a4a158f651439d7666c683a6283d308c91b25", - "1b5b018d9b06a3c79fb942ae24eb08714d70b996c916bc83063fda0f9ec82780d0f6e371501957e00796db78ea8f338874640cdcd2ca1496ea55d62aa3709498457ff43ce93631942f823f5bb9c6d133b1f04db02cc745245af6a31e4dfe912a696c9cac47da44cdc3eb3874eb0d8c89cc603d2ceec1678996fe311424b56e65221e486a579b91cd10a0fb38fec7214a46c9ce7f890afed4efa31fb5ca8766ae31df892814bd8b8f828d029f07f6acf47620063e9fa98ab947b376e068b9be689522b897e840e315a614a89d0bcf8296332affc2e6b52204d1d7994260e415c6e92147fc6676eedff2cb239581f4675066213f3b302497abbf10c1729131a0125a65dbc5252a8da8702a979aca3e211afb99a0edb76c92f2bd5941c6071db19d93cece17c818d8fb1151f1ef1b32745f09c155f42259af588b424c1dafe8d0e90a3dfc6f55bb428773ce15071cb720fb" - ] - ], - "public_share": "8f651439d7666c683a6283d308c91b250a3dfc6f55bb428773ce15071cb720fb", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json deleted file mode 100644 index af95aac5a0..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3SumVec_1.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "agg_param": null, - "agg_result": [ - 45328, - 76286, - 26980 - ], - "agg_shares": [ - "598a4207618eab7bd108c110106e84cd9498b18b79cace4b383274cef0ab280eae74b07f9a7f087a89a4f51f3adb97ed", - "ea61abdf14b8477f6de1b47a18ac778ad0149cb235e666ccce92a9246a2858403e5903013ab179dcf6719d10fccdf589", - "cfc412198ab90c0589158a74d7e503a89b7cb3c1504fcae7dc3ae20ca52b7fb17a9b4c7f2bcf7da947e96ccfc9567288" - ], - "bits": 16, - "chunk_length": 7, - "length": 3, - "prep": [ - { - "input_shares": [ - "db3fe5357f56f6cfe9a0a34ed08e231765b423d5670741c151f7bc28cb15c4c8678df838b6ef52d74c5bb5e8c8c607b2674c024da705b558163e3127ae09f4a5c061dc6129d71755ec77b5d5a2fc088541fa612bf1273d94718e0d28b654ea9524148bf910a5c6d55b596e323d4f55ab62b0851e0985987ea39cf500bfd4d5faed37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0f5d8a2e157f9c1ef6eedcb845a19fffd3f9c6e705b035c95f3ebe51219a91c6ffff33c52b8fd7e90417636bb443c98c3e6933b1599c09151095fff99d7af43d327fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa239333c6d1e2bec2132a3e3cf5fd11f7e823fbf275071a71535740ac64de88b83ba002bd4490de5c7540e454331d46ebb825725b964ecfcc5c3bb076bf57fd819c0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b0fbc219f5524eec22dc91aa56ed87a71d2b6e6b857ee03a700fb5af5b23513fb73023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e7d7fdf14abf76c605d42e523a540f40e816db420d599cea502baa131d6b61b8aed86a09b9f7587e107c6fc9043d72644153b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b12007c81a9b3c72a84522014f4cdcb949bb9850b62b1c9c5d35f0fc3dbf4f637ae85d3082ffd15890041a455a5dd38efca02eb415afcd2c93a2b6ab46c88847f380affbc3a9af4745718044c9f23978026af66871e610e1beee21360fc5ae4f05dd32689328216db3c512fddacefb2713187f4f5069170db246ae0cb13b3b88f8c832d11ae6b26fe6f0f89b9a9056c28ac6160134ab1af4be606a2ca7d1256cfc223c823ae4921ba11aab9e4f8104885b2d17ac7826ad06b0fd0e54397e67179755b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf7beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa9249c7a0530623084f3a7c8bdddf0cf0123597127f9416dcad20f71bb98bf0078d9d20d4ae09c46fc1882cae650f48bebfcc443dfd7963c9944f0ce0a9bda91fe8b8f307fb3da48e573224324c35e867599262fa281ee6bc537928747dd4a1370440bda92e28eb5ba088481e476f19e2a03a7c7619eb79e2184afff7bb585319fa6a58dbfb8862f5d193ccfe0e4aeb58c1633d9e983861d4976615b11514160e5d77ed9a3e2179893c65d9de03813d27aec3485d96098764ee1e7779d47850e6b96ba064b4b913da8390416afb16719a38b725d5b27db351049bdb322cfc93a905a108d07e49764eb5f3f66fe8f3aec7580606162636465666768696a6b6c6d6e6f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", - "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" - ], - "measurement": [ - 10000, - 32000, - 9 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "7e6f6b02cb848e7e3c5840b05acfd699", - "dda1902ed398efc35ebb269aa58e0d5a", - "cd03902ade7fad281b8cfc5f1349ddf9" - ], - [ - "f9758e4a5c3d6d2a1b4b3c7e5d397d83", - "9bb1de90bc4c2244e630e3b6780dc86a", - "15735600bee57d499ed0890554ef5183" - ], - [ - "9b4106b3d83d0457705c83d147f7abe2", - "89299140701aeef79e13f6aee1632a3b", - "298919d5639ad48d0ea3799a98c7d082" - ] - ], - "prep_messages": [ - "429a80b8b2f73ce00d066d0c0e540cfb" - ], - "prep_shares": [ - [ - "574ce7d79da173f0652f7d1e699d5fe756c90210a093e0c893b2b7510374465c35014cdcef24d6044e63ece20db245a982c5a00f16227c6530ade1e5fd4e925f8505da8add8b97fa3216790b11b46ad76bec9b6b3f0c1e9b8284f81f0c83bb690033a6c4a8e962d34b51e27aeaa33a0d41e852a78af96c6dfba1d36364996df4eaaacc993e5633528fb0d106753112ecbfe7fec74ea75d2d1b16267ee1b3d6145e746f19d0840be93d38baa3a5c7d42c6a05311092b4fe05e38aa9e24fb9c99a5aa4bc485752d049703409ccb6656150eeb34048030f19b5353df1e23b376b1c4be2925034d8b7a847690ca7f0c4f338c30b461d9e8c1a1de094fea67efdc4d3da6e96a43cd51241f828f01028e5b0e9", - "21c1bcbdd38fa9e8d86272f8c66c2b16768d00a79945c6014bb55374174299e4e7967f80f8df630af6f5aac52647e36437d08d0aabfd406b0984557a1a69b28f3706033ed34cde0d6bfd39a81a0fca04117cd7ac37f06815b6dc1a356454d669b0e7871238066b280f7c09e0365214235dcd39dfdf6e46ad632d50101029ff490910f79b754d99088059cf1d5da8a791b1a51d8d96fe428bac8f547dc2e9632c4e00b3a6e95d36d03d83969de2989c120aa3c54040bc7f49f910df6c5e4003721a03a3f1d743c457d0cbadbc0bd25ca7f464f404a1f39f852872314ca44ea35a32c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e", - "89f25b6a8ecee226a56d10e9cff57402c3198e7629d8c4152d9319172f0df07727e57ad2e170a0a32cf748f9dc0fe45597d26743a7254aebceb106f0f172a5f2aecf563787471334096bb202a07696b7e0cf22d7dda51e1cf0fcc3d0d5d0a9f4c7ea8999a3f4edb4bd7d3ecb26f2137fe9d443f34248265c25a12290866130c9ccd2dd263bce8b78c14ddbc0c94ed85da0c401ac614c789711c0e2db27ad6ef59aabfdbb6bf174fff2358c4a8d6b7e6cd2a0d41883f3563506755a920aaa7695cf35ffecb0b195d01d1d86ee1a015df5de2f145b61ef3bc5fff1634d911a69540c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a" - ] - ], - "public_share": "da6e96a43cd51241f828f01028e5b0e96639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" - }, - { - "input_shares": [ - "db3fe5357f56f6cfe9a0a34ed08e231766b423d5670741c151f7bc28cb15c4c8688df838b6ef52d74c5bb5e8c8c607b2684c024da705b558163e3127ae09f4a5bf61dc6129d71755ec77b5d5a2fc088541fa612bf1273d94718e0d28b654ea9524148bf910a5c6d55b596e323d4f55ab63b0851e0985987ea39cf500bfd4d5faed37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0e5d8a2e157f9c1ef6eedcb845a19fffd4f9c6e705b035c95f3ebe51219a91c6ffff33c52b8fd7e90417636bb443c98c3d6933b1599c09151095fff99d7af43d337fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa249333c6d1e2bec2132a3e3cf5fd11f7e923fbf275071a71535740ac64de88b83ca002bd4490de5c7540e454331d46ebb925725b964ecfcc5c3bb076bf57fd819d0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b0fbc219f5524eec22dc91aa56ed87a71e2b6e6b857ee03a700fb5af5b23513fb63023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e7d7fdf14abf76c605d42e523a540f40e816db420d599cea502baa131d6b61b8add86a09b9f7587e107c6fc9043d72644053b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b12007c81a9b3c72a84522014f4cdcb949bb9850b62b1c9c5d35f0fc3dbf4f637af85d3082ffd15890041a455a5dd38efc902eb415afcd2c93a2b6ab46c88847f390affbc3a9af4745718044c9f23978027af66871e610e1beee21360fc5ae4f05ed32689328216db3c512fddacefb2713287f4f5069170db246ae0cb13b3b88f8d832d11ae6b26fe6f0f89b9a9056c28ad6160134ab1af4be606a2ca7d1256cfc223c823ae4921ba11aab9e4f8104885b3d17ac7826ad06b0fd0e54397e67179755b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf7beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa924d95673e4d904cc4215bfda1c9c0ca55fa38af6b696ef4f1a452d6870c1d82fa311cee716b00a11313a0ba7c4038e5e195b5e1d3502a44d9a9ab1636394821eaf157e6c77316f6e26b98ca81220752396890cce205581aead60bfcc3916a6c2d6d360c7e845e70c8c68e4acb5eb2877a9a7c7619eb79e2184afff7bb585319fa669b151040f5b15cab2d8c3a50379e9d9e8bf1ac6319bc32e489f64793f882d0e3e1906ac04d47eaec15c20c503d007d09d6a9b032d0f9a8b3d95447fcb1d4b7334b95d873a171f876dcc2a62a62af58e10802f88742027d3d27b9d72fea73dc84906d3dde03299dc3e033651406229da606162636465666768696a6b6c6d6e6f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", - "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" - ], - "measurement": [ - 19342, - 19615, - 3061 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "fc936b02cb848e7e3c5840b05acfd699", - "7c71902ed398efc35ebb269aa58e0d5a", - "b90f902ade7fad281b8cfc5f1349ddf9" - ], - [ - "f9758e4a5c3d6d2a1b4b3c7e5d397d83", - "9bb1de90bc4c2244e630e3b6780dc86a", - "15735600bee57d499ed0890554ef5183" - ], - [ - "9b4106b3d83d0457705c83d147f7abe2", - "89299140701aeef79e13f6aee1632a3b", - "298919d5639ad48d0ea3799a98c7d082" - ] - ], - "prep_messages": [ - "e129a25d4bb45ae8f5ff9d97d72f6d86" - ], - "prep_shares": [ - [ - "574ce7d79da173f0652f7d1e699d5fe7865e23ddbe20c3646ca1d41f8d0d123a831f3b90d5b917779d25ca7aafd5c903b4b996399d29d3af9fcb1c6549c36a639e45759c53b3bf6a1014fbdf7ea4d5d3726af036968d80aed52a7e48dc0a06ee66a6e34bf38ce1083cb56057cfbe98ae9138b635f2b64b60daf151ce214d33b99062b201463033142fc734e4c163fd8a5d2ea4503567c0a9739027883ab0b37ece24259b5ddcc88b3e272bbad93857a52a48abf5eb9fb135ccaf27fc0379f49f203cc0f5a4f14183ef3b935076893f0bc56dcd9b0ffbf8f711039bfd3fe894c0c007d8702db35ded99e2605fa3d9d4b70f6dfcdea9883c839e2a91aa358a38359e2d3cb20272a3ecb52e1edc17a48940", - "21c1bcbdd38fa9e8d86272f8c66c2b167ab67945b007b46536ece1073c4ac681e7967f80f8df630af6f5aac52647e36454b87d9c2d6aa2d4c2186b47a6bef8153706033ed34cde0d6bfd39a81a0fca04618cc495486eccfbcba29099fb101871b0e7871238066b280f7c09e0365214230a741f21625c730fae5e37a7a3cbe0c00910f79b754d99088059cf1d5da8a7911221c38f8a6f79877dd34cb4fd2990744e00b3a6e95d36d03d83969de2989c12e44eb18d466e8954631aa1dbe84e78111a03a3f1d743c457d0cbadbc0bd25ca7de998de032e28d1a8ca88d584ad7a64032c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e", - "89f25b6a8ecee226a56d10e9cff57402a204a4e83b6b78a5aa32317f68443eac27e57ad2e170a0a32cf748f9dc0fe45524ab48c23361b4b327d498fd702f23b6aecf563787471334096bb202a07696b7eb8d79193777673f93547e14b15adb2ac7ea8999a3f4edb4bd7d3ecb26f2137f5e2881b52fd4d3ec538b978ebba54312ccd2dd263bce8b78c14ddbc0c94ed85d38fdf5fb7ee2eeb21ef066fdde8a94f89aabfdbb6bf174fff2358c4a8d6b7e6cdb080672d15b2ae06d6ca64387b56c00cf35ffecb0b195d01d1d86ee1a015df53e771738ec1faca3fcdfe4f033977dd50c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a" - ] - ], - "public_share": "9e2d3cb20272a3ecb52e1edc17a489406639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" - }, - { - "input_shares": [ - "db3fe5357f56f6cfe9a0a34ed08e231766b423d5670741c151f7bc28cb15c4c8678df838b6ef52d74c5bb5e8c8c607b2674c024da705b558163e3127ae09f4a5c061dc6129d71755ec77b5d5a2fc088542fa612bf1273d94718e0d28b654ea9525148bf910a5c6d55b596e323d4f55ab62b0851e0985987ea39cf500bfd4d5faec37f519120b574aead76d706e149c54b6e790f7c35553f830f67553ff3f08db0f5d8a2e157f9c1ef6eedcb845a19fffd4f9c6e705b035c95f3ebe51219a91c6000034c52b8fd7e90417636bb443c98c3e6933b1599c09151095fff99d7af43d327fcf2afdc50144e5b8f5b1ff1f8cc8d442613dc76dd48100dd4637b38fc5fa249333c6d1e2bec2132a3e3cf5fd11f7e923fbf275071a71535740ac64de88b83ca002bd4490de5c7540e454331d46ebb925725b964ecfcc5c3bb076bf57fd819d0bd788b4495da456594503c8f5b618c4713e957a7589b151ead3a27ae80153b1fbc219f5524eec22dc91aa56ed87a71d2b6e6b857ee03a700fb5af5b23513fb63023c2764f74b40f00e44e2e7acd463e7f38c783a898015b51863659502645e6d7fdf14abf76c605d42e523a540f40e716db420d599cea502baa131d6b61b8add86a09b9f7587e107c6fc9043d72644153b54234146535e9ec25223d293f4a2a4481b5649a7625116aef735ecbbdd9e99076985e1c424e91c29ae231c01f2b11007c81a9b3c72a84522014f4cdcb949cb9850b62b1c9c5d35f0fc3dbf4f637af85d3082ffd15890041a455a5dd38efc902eb415afcd2c93a2b6ab46c88847f380affbc3a9af4745718044c9f23978027af66871e610e1beee21360fc5ae4f05ed32689328216db3c512fddacefb2713187f4f5069170db246ae0cb13b3b88f8d832d11ae6b26fe6f0f89b9a9056c28ac6160134ab1af4be606a2ca7d1256cfc323c823ae4921ba11aab9e4f8104885b3d17ac7826ad06b0fd0e54397e67179765b29c6d724f3e9d9a6934619ef0bfee72cdcf0031672bb6e55be53d3ef0fccf8beba7dea636eff7fdecee99f60a0bc5d5cb11e24683ca8085cf218a3607c3f5a051c33717f39834435c5c542f42bd9c9d9103173cb11436e2a626e228415924037ee4a4078f0d9a5bd0fef1dc9415740c4b32f51d199d912907a103c7e25928acadfb4dc1e8d32c34b4f0100bfe95feb850e0d7b359aae9a332913d1f8eca0d1cd93dee2f4b75076536037ca2b6bec5003ae89e03db9813d0dd2165bf50a836ca492f05750a3b5fff4d089fc54fdf225aa112d72ab021b0cef1b8d31c852133fae501406668db0cb4c3589934bde5ec218876b0dc4087b61d706234635d5d9065787a21ed895fb7c05902a554f879dae44d0905292815c5ae2338be1faa924c67468654e6880c69828616e9d011132b27aa457c6dcbd554ec4374ec882357626d6f323bfadc3b23ac6d390e40f8f2008e462458194a1f9d63e0b977f4be907f34aecb0a12ad13b95bfc858c412abab064106faf149e9b25cb557c12a54e6ae957097b8b11f174094d134cc213bf98da7c7619eb79e2184afff7bb585319fa67b935c839af760464b6f3d5402847d07d9cf6c2502ae55f33e08959b38de273b2911fa9ef530cc2cc1a1f3f8224ed7c8efe455f3ad1e462c1d089d4be054801a56ecdd4dca5bbc7191990a1c028d6d79934bf7aed757eccdd68512ebe9f919f087f6020e75fa8e281316ae3a0a50a7f5606162636465666768696a6b6c6d6e6f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", - "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" - ], - "measurement": [ - 15986, - 24671, - 23910 - ], - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "e0866b02cb848e7e3c5840b05acfd699", - "3c85902ed398efc35ebb269aa58e0d5a", - "2a61902ade7fad281b8cfc5f1349ddf9" - ], - [ - "f9758e4a5c3d6d2a1b4b3c7e5d397d83", - "9bb1de90bc4c2244e630e3b6780dc86a", - "15735600bee57d499ed0890554ef5183" - ], - [ - "9b4106b3d83d0457705c83d147f7abe2", - "89299140701aeef79e13f6aee1632a3b", - "298919d5639ad48d0ea3799a98c7d082" - ] - ], - "prep_messages": [ - "62b225fa36c2cbc5896a40b1360f0ce0" - ], - "prep_shares": [ - [ - "574ce7d79da173f0652f7d1e699d5fe74186663960507c6ac01fafa7046bc88a5c4146feb2861bcb9f3ad8bb294028812c631ce293cde53b6fc09c6bdbcb839ede24393da7141c26a1a594ccdab1fba7ed2b2e38faf952343a2871b854699ff9533b4f88f9bc7e935cc62e3dea6efff7e2d396d8276281db4e789dc30d3fe01c397b64d685e87e7dccae1b7636b1a1486293f29e5c3433ee211e1f66ec5a7a0f1d79ed261735f53fdb51cbd51c1a6b057bf2845e34bfa091f0f8fd7565242c8b247064dfac759c1c646d085bca6ad0845b9cc2093fd49d493ebf2d48a90b99815f0bd165f56453c6b27dff04d3a161d9fc0bc4177e423791d4064faccfbbd3218c6815a24e38fb752efc839e59043cbb", - "21c1bcbdd38fa9e8d86272f8c66c2b16ce028e4f460022aed5c3e47011081a9ce7967f80f8df630af6f5aac52647e36481e9f91e23071ea7d98af1e76a9dd5823706033ed34cde0d6bfd39a81a0fca048271f4696baf9fd2e8a37e7b5e1be75eb0e7871238066b280f7c09e036521423abafe75c716165e86a573bab2e46efda0910f79b754d99088059cf1d5da8a79146cedb83d4b00d96b9871a66d73147984e00b3a6e95d36d03d83969de2989c12e222e1015cad12a219308643f8e1c1511a03a3f1d743c457d0cbadbc0bd25ca7cb9908430d0604df4468ab54b36f81ef32c150fc25094cd2147739d1a1e03e8f6e636170867687f1c511dbb936fb521b6639ebc145f03b6d1751fcdf14c5108e", - "89f25b6a8ecee226a56d10e9cff5740294125c8939f32731654a11d38906f94a27e57ad2e170a0a32cf748f9dc0fe45503b71c971d945163a09158bc06295e77aecf563787471334096bb202a07696b7f7c98da9fca5e00ff5ce6eb4b9d52274c7ea8999a3f4edb4bd7d3ecb26f2137fbd6dc71ed450947219eef408d88af7dbccd2dd263bce8b78c14ddbc0c94ed85db3255ece317e82a0f3b4a873e9b72b949aabfdbb6bf174fff2358c4a8d6b7e6c545473085c7c9b5c2aa9d290b01670ffcf35ffecb0b195d01d1d86ee1a015df56465c0991dd00dfda6948958c3ff38510c03444dcb256fa982b24cf064dd6e4dffe71f8d5648cf336acd9485f9d70e24f2ad6b4aa14511e7b660c0866f73672a" - ] - ], - "public_share": "8c6815a24e38fb752efc839e59043cbb6639ebc145f03b6d1751fcdf14c5108ef2ad6b4aa14511e7b660c0866f73672a", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" - } - ], - "shares": 3, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json deleted file mode 100644 index 4dd3798668..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_0.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "agg_param": null, - "agg_result": 100, - "agg_shares": [ - "0467d4fd6a7ec85386c9f3ef0790dc10", - "61992b02958137ac5d360c10f86f23ef" - ], - "bits": 8, - "prep": [ - { - "input_shares": [ - "1ac8a54e6804d575f85957d45c728487722ad069fc1ed413da970ea56ae482d81057f898a367319a14f402d072c24bb71aa13cf4f9cdcd731e779aaa4a5d561ff40e41797cf2d43308849ff9080f846c2e78e2736a1d3cdaa68f3ec890d633cc13f5bf96466d3f02f93612bc827ff53357d52ae00dd234b9758f2cbb7aa9682d06041da1507aa12446de554a945924f445d3715279ef00f4c55ae987cec4bb9f1316efdc8737b7f924d046a6b8ef222b0dc1205ce9b464076fa80d2dfe37af4d836d597ade7d51e18e9c95d13158942d249efd0a1a226759e4bc1d46d3a41bdb227703fe0a7554cf4769935bc99cd1f35b274ecec240816af4915c7abe3e16b7be5ab5e105f9ae7b2e683191c9400cf99ab0c687e4929f87e6e64f712ca02f07a1b29fcebdbfde7655797f9c1b6b3114420d8a19736ae614116782278b7a71f9ef6928ad44ce588644886523d6fbe0b7bbb47248edbaa0b5ce33f74a07005e2a6842eb2c05778e170112f6e6a5f206d7830aa122e29069dcb4a4c064e63c29b3c6e2b22dfb5ab344ca0f1be8e8ce36d26435413de2dc4f53e158ebb8478b4a98de014a688db9470106fd7e73a65c2e656b5a627b5584ca0594ba10cc39c5612bcef576625c37c5249ad5c04e42c66d6a9653c4ec47e2bcd860870bef64f812974654f17f77c08eaa395803d33bdf31db17d76dbb9d2407d7c4f9efbce274542ff6aa0dcf188803eb586108317db430ad517ce7cb0f56d225c835161eb348949ebe253bedc338c6b939ce837561f01d7f0304963eab2a28b38c36bb169a4ee0637635818bd5e4798a8319152a2678b0aa7b837cb0f24df6148ae2c84b78db8892f4415f90f3804e7a29cdcd32a0a8625fd20aca47ee0ef12ebd6138b3534a1b42303132333435363738393a3b3c3d3e3f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" - ], - "measurement": 100, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "0467d4fd6a7ec85386c9f3ef0790dc10" - ], - [ - "61992b02958137ac5d360c10f86f23ef" - ] - ], - "prep_messages": [ - "0fd2bb14ac123437f6520fdc4a817934" - ], - "prep_shares": [ - [ - "61428b8d7e326827ac832bc4074ad61652efcfdb8d95b6f06b83dd9f5d55ce9f142d1a1fd437eb8c84581ad15dcd9a57417942e63a1a46e6b0ffc8b6d6300f7d", - "a0bd747281cd97d8377cd43bf8b529e9eb5e4b1153111bd6cd06aa3a5493a6da4470f696b9afff52ec10fc00040e4538470fdb8d3e05e188aba2b16e24c71b69" - ] - ], - "public_share": "417942e63a1a46e6b0ffc8b6d6300f7d470fdb8d3e05e188aba2b16e24c71b69", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" - } - ], - "shares": 2, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json b/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json deleted file mode 100644 index 8e7163ae2a..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/Prio3Sum_1.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "agg_param": null, - "agg_result": 100, - "agg_shares": [ - "b3916e4086c52aa0439356b05082885a", - "61992b02958137ac5d360c10f86f23ef", - "52d565bde4b89db326369d3fb70d54b6" - ], - "bits": 8, - "prep": [ - { - "input_shares": [ - "ec863a16981eee70b71dc7d396a85ba412dcb4e86769d6db0c60f668456f5d6fbb844d9503580fb7b662bbb2ed7d92002e6ab4a2d31a6f611cbb5c48ca6df69811d536f74a3ff61eb29bd9b9f1b64c35eddd5c4ac97376057883a317f2989b545a682775f948f28f80f366f36b4eb90f931bca79e229eae377102295d9c46da2e239f74f045084747039c0a955726b4258bc0d14da7474bea6cd136eb5e55e9531e6a68703003a64943a5650b16674c82d9c4b526a7ed3d69f8f13ae83609cf056f3fed8d6593fdad7b367d2d248413072651073ea91b8162d42af168698f0f0928c8238b2df218e26d004d2bdb5f9f20d0a43c0286d08cfc26971f282992f82ff14d51cee3e0f3fc7411869c2176cabc6b1a68e33ff5eb217490de9f0d85cb84e9115bb7e208a190d25bf9cc138485892802a50b790ba6f45804de487a3353e54b5471adb5ab612d9ee6416649e136456215503637e0daab367149bc5cdf02a2dabc2790f84cadec1510263fe6aa27df5df395b7a241777a8ed28da27276b48f599dd895a005746cfd1f3c874e6f52407f4c417934d7091685c0b38b1d76b398ad263ec73f4f811aed38febf67a19a001a2c7ab8071f986939713cccd146c7a049c5129783359fcf86410765028fbfbbe62c2474a6b75de0ba49c037e07946deae971207f4f74b8b1d6a7b225eb0b66ed1f3878bc14d9d7a38b2162247b7ed9ac3df6fd2a98a3e4bf2855c8fb13f39487481fe03f5b5cb5123d11aaef180ff8ae69709322459a01a72e9304295ae5721d6eac6dae140677d0dd60f192f0475bacfd131d4ff3393238caa00fe0847c3a43c97a31f84f58b3c7487c5c0a09e85b39ed4b69fcdfa071da15216fd5f1fad125328e40689acce1a6cb113c2a16f599606162636465666768696a6b6c6d6e6f", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", - "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" - ], - "measurement": 100, - "nonce": "000102030405060708090a0b0c0d0e0f", - "out_shares": [ - [ - "b3916e4086c52aa0439356b05082885a" - ], - [ - "61992b02958137ac5d360c10f86f23ef" - ], - [ - "52d565bde4b89db326369d3fb70d54b6" - ] - ], - "prep_messages": [ - "e385da3bc2246be76ff12a7093ecb45e" - ], - "prep_shares": [ - [ - "7b6a9ad01449ec86dc6736dced3ecd24b47ab2a3768908b10696d537f2b02c98cf3314686f94ac37c7d81b14fea51f784e037bbdd56b2ee8486757acad61db1e", - "40a478cd7376c1e9ea339ddcf96ab1a7eb5e4b1153111bd6cd06aa3a5493a6da4470f696b9afff52ec10fc00040e4538470fdb8d3e05e188aba2b16e24c71b69", - "46f1ec617740528f1c642c47185681331adc83aace0cc5ddd256cf295c93c64d207d424f5056a8d59748ba9e423c4cf5f560fb4c6505c9a773629e12f21ee230" - ] - ], - "public_share": "4e037bbdd56b2ee8486757acad61db1e470fdb8d3e05e188aba2b16e24c71b69f560fb4c6505c9a773629e12f21ee230", - "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" - } - ], - "shares": 3, - "verify_key": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json b/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json deleted file mode 100644 index ea76c50ff8..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/XofFixedKeyAes128.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "binder": "62696e64657220737472696e67", - "derived_seed": "9cb53deb2feda2f9a7f34fde29a833f4", - "dst": "646f6d61696e2073657061726174696f6e20746167", - "expanded_vec_field128": "9cb53deb2feda2f9a7f34fde29a833f44ade288b2f55f2cd257e5f40595b5069543b40b740dfcf8ab5c863924f4510716b625f633a2f7e55a50b24a5fec9155dec199170f9ebe46768e9d120f7e8f62840441ef53dd5d2ba2d3fd39032e2da99498f4abf815b09c667cef08f0882fa945ba3335d2c7407de1b1650a5f4fe52884caf3ef1f5802eabb8f238c4d9d419bed904dcf79b22da49f68fb547c287a9cd4a38d58017eb2031a6bf1b4defb8905c3b777e9287f62a7fb0f97e4d8a26c4e5b909958bc73a6f7512b5b845488d98a7fcedf711ada6972f4c06818d3c3e7a070a88af60dc0323b59f304935fbbbd3792e590c9b6bce7459deba3599c7f30fe64a638219dde4bde4b1a51df8d85c2f36604c44f5f188148e3ba1dca3fd8073240ee577ef322df19a13d9ffa486a6833f4eb2838a58746707b8bf531cc86098f43809276b5f02914b26cb75938ca16eafa73397920a2f5e607af30e62ff60b83e15699d4d0265affe185b307ed330941a41b2b628e44d9a19412f7d9513cacd7b1fd740b7708e3bc764a0cf2146bca7c94d1901c43f509d7dcc9dfec54476789284e53f3760610a0ac5fce205e9b9aa0355c29702a5c9395bf1de8c974c800e1037a6bf5e0bd2af7d96b7f000ff6ab93299966b6832c493b600f2595a3db99353d2f8889019cd3ec5a73fa457f5442ed5edf349e78c9cf0cbf4f65aea03754c381c3efc206b7f17447cc51ac68eceacab9d92b13b0bc700c99a26ce2b6c3271f7639aa72dc27bbd54984907abb10ef1047ef352d378ddae48bf381804c89aa1847f5027537cf6af1b30aa44cead6495e98ca5b3205d39beb49d2db6752a4e57158e8c83464002b0b4a9838bc381c1dbdc3e9a584554fb76671a15f907c0b395a5", - "length": 40, - "seed": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json b/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json deleted file mode 100644 index edafb1bd4d..0000000000 --- a/third_party/rust/prio/src/vdaf/test_vec/07/XofShake128.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "binder": "62696e64657220737472696e67", - "derived_seed": "87c4d0dd654bf8eec8805c68b5eb0182", - "dst": "646f6d61696e2073657061726174696f6e20746167", - "expanded_vec_field128": "87c4d0dd654bf8eec8805c68b5eb0182b1b8ede598cfb8d8b234038fd0492eb14268bbb2ac15a55d463c8227c2d4fae8607631d13157c4935c5d2d56e4b1e2bdfe0f80b286d82e631704acee29ab6f7acaa316d3623cc3371297604caf57bc2eafe72056143971345901b9fb9f95b6a7384c6a88143124ff693ce9e453675f87a6b6338a1e1c9f72d19e32b51f60a1d7469de1fbe25407cc338d896b34c5fc437d2551297027eeefca9aaccdb78d655a6c220cbc2d76cc4a64b04806ae893c952996abb91f6ec32b6de27fe51be59514352d31af4967c0a85c5823ff73be7f15b9c0769321e4b69cb931a4e88f9da1fde1c5df9d84a7eadb41cf25681fc64a84a1c4accded794c1e6fec1fb26a286712425bfc29521273dcfc76cbab9b3c3c2b840ab6a4f9fd73ea434fc1c22a91943ed38fef0136f0f18f680c191978ab77c750d577c3526a327564da05cfc7bb9ef52c140d9e63b1f39761648772eaa61e2efb15890aed8340e6854b428f16dff5654c8a0852d46e817b49bbe91db3c46620adbd009a0d7d40843c1b6b7786833d3c1ae097b4fa35815dbcfca78e00a34f15936ed6d0f5bf50fc25adbecd3adfa55ba6bc7052f0662595cf7a933dfcc3d0ad5d825ec3bc191586a1c36a037d1c9e73c24777825d6afe59774abdb2918c2147a0436b17bafd967e07c46c3d6240c771f4fd4f9b3fff38b294508b8af5a1b71385f90f407620b7aa636fd2b55435b3688fc26ad3c23b2ad48158c4c475c07eb58569a8d1a906452b82d582397c4c69f5e79d3082d03b4dd85b5277a8b44c933d52d168caae8c602376f5487670a172d138364cb975c569c9c2d79506746090ea8102907c91b66764fd8740ca7bd3acb59173df29b5fa7542e51bce67b97c9ee2", - "length": 40, - "seed": "000102030405060708090a0b0c0d0e0f" -} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json new file mode 100644 index 0000000000..68f3159234 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/IdpfPoplar_0.json @@ -0,0 +1,52 @@ +{ + "alpha": "0", + "beta_inner": [ + [ + "0", + "0" + ], + [ + "1", + "1" + ], + [ + "2", + "2" + ], + [ + "3", + "3" + ], + [ + "4", + "4" + ], + [ + "5", + "5" + ], + [ + "6", + "6" + ], + [ + "7", + "7" + ], + [ + "8", + "8" + ] + ], + "beta_leaf": [ + "9", + "9" + ], + "binder": "736f6d65206e6f6e6365", + "bits": 10, + "keys": [ + "000102030405060708090a0b0c0d0e0f", + "101112131415161718191a1b1c1d1e1f" + ], + "public_share": "18850fb4933f36be2d456c4e2477baf2c9a4a7204fb09ae3e3ff925ecfe07a297b07b1980635d1e1f512afbd6388c98f5bf076cc5fe746282e59b81e51bffd6699fac7ec2dab3e9dd2c60d896beb64131d73b8abd7b2f0b327e5d91b42c677468048180e55bd80946611101ff01cb82022f7aecbe1db443499a311b7b9ee114acc16ae30d73d77ab2995eef0d536c26753647394f24d0c7b6db95b0eda08056b919e862c373e9c7a1e17590e5d5f250e56249ad28f9c13a8b57dfd7dcd05d78d49640d0aa35173cb4a659ada59f57d0c408edf52cb16d8bfb5c5d56d0c28a1aa7d96054c848cfeb0eeb6576b7c8c5328dfe502bc5eef4f1c6f58abe9ad37b448995e2b584cdb5f3a94f056ca7b868ad8f593f07c73f88596398fb4f13c5a7393b8fb0d2c76076132f54484f5f18209f42e4fe98ba2b9b1d1d19c139dc4520ada547ddbb70baecf1bba61a7b3cbb4648a7235142e201a173038dac559940a55d29a68cc87298d722b6644fa445460ddb9938c64" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json new file mode 100644 index 0000000000..c4056a156a --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_0.json @@ -0,0 +1,56 @@ +{ + "agg_param": [ + 0, + [ + 0, + 1 + ] + ], + "agg_result": [ + 0, + 1 + ], + "agg_shares": [ + "42417a6b9fd228e050220f57293f7555", + "bfbe85945f2dd71fb2ddf0a8d5c08aaa" + ], + "bits": 4, + "prep": [ + { + "input_shares": [ + "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53", + "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721" + ], + "measurement": 13, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "42417a6b9fd228e0", + "50220f57293f7555" + ], + [ + "bfbe85945f2dd71f", + "b2ddf0a8d5c08aaa" + ] + ], + "prep_messages": [ + "f7c882b687b7bd461fb1f898356db5fa88833cdaa1e26a71", + "" + ], + "prep_shares": [ + [ + "029b574f4e07246cb5b90e90207a148abb7dfba2efb9a32a", + "f62d2b6738b099da6af7e90815f3a070cd054137b228c746" + ], + [ + "264531e72e56a380", + "dbbace18d0a95c7f" + ] + ], + "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json new file mode 100644 index 0000000000..ea8bbfea10 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_1.json @@ -0,0 +1,64 @@ +{ + "agg_param": [ + 1, + [ + 0, + 1, + 2, + 3 + ] + ], + "agg_result": [ + 0, + 0, + 0, + 1 + ], + "agg_shares": [ + "f4265a0ff9c4f0d1f068b522d608c1a38cde98228531a78ccb74919ef72f5051", + "0dd9a5f0053b0f2e11974add28f73e5c752167dd79ce5873378b6e6107d0afae" + ], + "bits": 4, + "prep": [ + { + "input_shares": [ + "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53", + "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721" + ], + "measurement": 13, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "f4265a0ff9c4f0d1", + "f068b522d608c1a3", + "8cde98228531a78c", + "cb74919ef72f5051" + ], + [ + "0dd9a5f0053b0f2e", + "11974add28f73e5c", + "752167dd79ce5873", + "378b6e6107d0afae" + ] + ], + "prep_messages": [ + "d2ca8d38065df3047d92ebacf9c366b83ad81d98fb17356a", + "" + ], + "prep_shares": [ + [ + "4c00ed0607d7702352c8786bb90f360edd89e3c8507274b1", + "87caa031fe8582e12bca724140b430aa5e4e3acfa9a5c0b8" + ], + [ + "1ed0621986d79f57", + "e32f9de6782860a8" + ] + ], + "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json new file mode 100644 index 0000000000..9b4fd0bc70 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_2.json @@ -0,0 +1,64 @@ +{ + "agg_param": [ + 2, + [ + 0, + 2, + 4, + 6 + ] + ], + "agg_result": [ + 0, + 0, + 0, + 1 + ], + "agg_shares": [ + "6bc200377c0ebf33de6ac488c1427b38bea3859050a09e19208319b3875c5099", + "963dffc882f140cc23953b773dbd84c7435c7a6fae5f61e6e27ce64c77a3af66" + ], + "bits": 4, + "prep": [ + { + "input_shares": [ + "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53", + "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721" + ], + "measurement": 13, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "6bc200377c0ebf33", + "de6ac488c1427b38", + "bea3859050a09e19", + "208319b3875c5099" + ], + [ + "963dffc882f140cc", + "23953b773dbd84c7", + "435c7a6fae5f61e6", + "e27ce64c77a3af66" + ] + ], + "prep_messages": [ + "453405bb632d670892ddc291c4d886ce098d206debd7e121", + "" + ], + "prep_shares": [ + [ + "bd7d6befff9982c88c631d4c593d754f4b817e23f0faf751", + "89b699cb6293e43f067aa5456b9b117fbf0ba249fadce9cf" + ], + [ + "c36085ecec965e1f", + "3e9f7a131269a1e0" + ] + ], + "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json new file mode 100644 index 0000000000..f280aedebc --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Poplar1_3.json @@ -0,0 +1,76 @@ +{ + "agg_param": [ + 3, + [ + 1, + 3, + 5, + 7, + 9, + 13, + 15 + ] + ], + "agg_result": [ + 0, + 0, + 0, + 0, + 0, + 1, + 0 + ], + "agg_shares": [ + "7e787b132dfe4dfcf9f8cab505a6133d30b7fd75f52a422d05ce25abe1b9cc5d3c4dce1f874d3e6bc4e9d9162ce3ae1e01da0581055c3d83de238e22b71bed1e8a69ed19cf9ccc49f2bb00c049d3153af4087218b63d6ae26ad30ca130641f50cb85fedfecf35fed0451625ebf2dac37281549b3cd8798fdd12d3eca3a68a17ec2c6f6086fca7b6dd59cd532e1b72bc95bedbfb4ce1dcc7cc873d989601e8a16ca1724e563a6c114b58e3bf58a65c621b00ebd22074223ec8e863c418a8ec83e0701d49174dab847df196325664790b6aba39c2d8ab74275b80ecc5d85c43c61", + "6f8784ecd201b2030607354afa59ecc2cf48028a0ad5bdd2fa31da541e463322b1b231e078b2c1943b1626e9d31c51e1fe25fa7efaa3c27c21dc71dd48e41261639612e6306333b60d44ff3fb62ceac50bf78de749c2951d952cf35ecf9be02f227a0120130ca012fbae9da140d253c8d7eab64c327867022ed2c135c5975e012b3909f7903584922a632acd1e48d436a412404b31e23383378c26769fe1756924e8db1a9c593eeb4a71c40a759a39de4ff142ddf8bddc137179c3be75713741e6fe2b6e8b2547b820e69cda99b86f49545c63d27548bd8a47f133a27a3bc31e" + ], + "bits": 4, + "prep": [ + { + "input_shares": [ + "000102030405060708090a0b0c0d0e0f202122232425262728292a2b2c2d2e2f53a9af607a9ba90a1d3f318b8c32b858b3d50db495dd0cea621fc5acb48f197bd4e873a62181a039dda958c94fddf92a8c77579c03c6dfc230f22f48f76c4f904d2b114e3c8289045ca768975bbede4b411e83158149e59dcbccf8746fd6c3e46d02f6c1d55b61707cf072837674ce53", + "101112131415161718191a1b1c1d1e1f303132333435363738393a3b3c3d3e3ff353dae51a27e776577e4452505c1be72ff784ff29b113a7d382ed46393d577cbd67fe52d4b6de1db2e204d4a6eaca3e7cee015d5fe92a830800f01375b8b9e799ac36fc76ae347a6478dad319ed9e59a21d8102ae380d8462c88d5b5bdf438b46dfec7042682ff4ac55fb9e516d1721" + ], + "measurement": 13, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "7e787b132dfe4dfcf9f8cab505a6133d30b7fd75f52a422d05ce25abe1b9cc5d", + "3c4dce1f874d3e6bc4e9d9162ce3ae1e01da0581055c3d83de238e22b71bed1e", + "8a69ed19cf9ccc49f2bb00c049d3153af4087218b63d6ae26ad30ca130641f50", + "cb85fedfecf35fed0451625ebf2dac37281549b3cd8798fdd12d3eca3a68a17e", + "c2c6f6086fca7b6dd59cd532e1b72bc95bedbfb4ce1dcc7cc873d989601e8a16", + "ca1724e563a6c114b58e3bf58a65c621b00ebd22074223ec8e863c418a8ec83e", + "0701d49174dab847df196325664790b6aba39c2d8ab74275b80ecc5d85c43c61" + ], + [ + "6f8784ecd201b2030607354afa59ecc2cf48028a0ad5bdd2fa31da541e463322", + "b1b231e078b2c1943b1626e9d31c51e1fe25fa7efaa3c27c21dc71dd48e41261", + "639612e6306333b60d44ff3fb62ceac50bf78de749c2951d952cf35ecf9be02f", + "227a0120130ca012fbae9da140d253c8d7eab64c327867022ed2c135c5975e01", + "2b3909f7903584922a632acd1e48d436a412404b31e23383378c26769fe17569", + "24e8db1a9c593eeb4a71c40a759a39de4ff142ddf8bddc137179c3be75713741", + "e6fe2b6e8b2547b820e69cda99b86f49545c63d27548bd8a47f133a27a3bc31e" + ] + ], + "prep_messages": [ + "d6ce08ae0327f913210f5e0701c594bf1baa15a33f6933f9b73787f73464db6a6a10f3c7e7e76a1844367d0091f16a7f090e7ed1fcc6f2a456e9e12daec41b18e08c45f8b9c5d20b02e8fecd25cb7fc05e98a6c79a1ee08da284161b3bd94d53", + "" + ], + "prep_shares": [ + [ + "b289bbdd941be53774dbb8177fd40ee4614c325d64ca211dee7268c34fd93c7855030fd22ac1db9e4760d9cd03a090b976b2b9a9bcef2e9f9affeb5cd6afe05423b5b3db766c04dc072864e1dd8b0d0fabf8b8add732c7eeff4ae5ba5fe0fc13", + "11454dd06e0b14dcac33a5ef81f085dbb95de345db9e11dcc9c41e34e58a9e72020de4f5bc268f79fcd5a3328d51dac5925bc42740d7c305bce9f5d0d7143b43bdd7911c4359ce2ffabf9aec473f72b1b39fed19c3eb189fa2393160dbf8503f" + ], + [ + "b4fe321bd55f5135b7ebfda820401ad7b7fba83b65e68b8ede4b0a566a9f5629", + "3901cde42aa0aeca48140257dfbfe528480457c49a19747121b4f5a99560a956" + ] + ], + "public_share": "dfe8ba3fa8bf0b8340a577388d7f4537bc2ed02a8b8c11e498d8ffdf6eae85c76f1c8c890ad535ba72d385b77962a0a8dbb59836381fbd9d80814b2b0d95948d11ee55bcd51bece3c27a76ad9aa132f4dfe46ee0783cdf650b6276ffda3830a7f61a859d311aa38580829ef9097c0a5032d798b8a28a17869323b84f36f0e6fe82ed6bc5bff3ae8cc4d32d25ff56e9af6da83c2943b41bb4a49555dcdc76033c31ec7098db3274261f3b50d3335fc1474e", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json new file mode 100644 index 0000000000..c0336fa679 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_0.json @@ -0,0 +1,39 @@ +{ + "agg_param": null, + "agg_result": 1, + "agg_shares": [ + "352c53cbc1f95eee", + "cdd3ac343d06a111" + ], + "prep": [ + { + "input_shares": [ + "352c53cbc1f95eee43253a8650e8ac18a5bd9c18b824886772947facdf1a413f1cf547cdb8c1ad4ed4c1294ccc856209", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + ], + "measurement": 1, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "352c53cbc1f95eee" + ], + [ + "cdd3ac343d06a111" + ] + ], + "prep_messages": [ + "" + ], + "prep_shares": [ + [ + "f6340e6030e5960b53ad59de202314363e6063ed75a89676e3b9635d397d650e", + "0bcbf19fce1a69f4b5de9ce10c9c671b9baa607f88bfa49de4367212193d9b3b" + ] + ], + "public_share": "", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json new file mode 100644 index 0000000000..6731f2a13b --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Count_1.json @@ -0,0 +1,45 @@ +{ + "agg_param": null, + "agg_result": 1, + "agg_shares": [ + "4eeea47bcff955f0", + "cdd3ac343d06a111", + "e83dae4ff1ff08fe" + ], + "prep": [ + { + "input_shares": [ + "4eeea47bcff955f08194b8660a6bb007a346b42952b2298158c165d94c1c40979e10b54ae7092a5a14b325df003a6f9d", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + ], + "measurement": 1, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "4eeea47bcff955f0" + ], + [ + "cdd3ac343d06a111" + ], + [ + "e83dae4ff1ff08fe" + ] + ], + "prep_messages": [ + "" + ], + "prep_shares": [ + [ + "817531f295522feac2551124114fdc827bfda7719fb1eb33b0b4e1c49761f62f", + "0bcbf19fce1a69f4b5de9ce10c9c671b9baa607f88bfa49de4367212193d9b3b", + "76bfdc6d999267219aa129cccf1e2459cf93ae20bf886d0d22fe0f5fcded28e6" + ] + ], + "public_share": "", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 3, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json new file mode 100644 index 0000000000..b39dc2838d --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_0.json @@ -0,0 +1,52 @@ +{ + "agg_param": null, + "agg_result": [ + 0, + 0, + 1, + 0 + ], + "agg_shares": [ + "ac3ba28d7f5649e6b3932251da118acf6740508adaf7837c87cd0574c48a00ea2ba59154eff2921c69cdeb23276510d3758486d91898690c4ba0fd3e6e149956", + "55c45d7280a9b619306cddae25ee75309abfaf7525087c835c32fa8b3b75ff15d75a6eab100d6de37a3214dcd89aef2c8c7b7926e76796f3985f02c191eb66a9" + ], + "chunk_length": 2, + "length": 4, + "prep": [ + { + "input_shares": [ + "ac3ba28d7f5649e6b3932251da118acf6740508adaf7837c87cd0574c48a00ea2ba59154eff2921c69cdeb23276510d3758486d91898690c4ba0fd3e6e149956aaa0fbc70889fae40bf0b8873db6f2c2c26ef6772e0dd8d091e12a1dbe4388bbc88819a887c53a4afa8e3e35b0c00100af9000ad245790e71c322e5c252e25a25514ccc4ebeb9b9f47a98223b2d04d44f94a2cb4791ff9a056eca2a0c74ab11f08d41d917cdaa2858d372c08339c414559066eb7be61cf2b5bb36c7c598a97b19802fead02586c39b001c18b5ff36e66d9ab75d6e9c6c0c0eaae66b1014ba2645047801054acea9f87404cc2749584db303132333435363738393a3b3c3d3e3f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + ], + "measurement": 2, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "ac3ba28d7f5649e6b3932251da118acf", + "6740508adaf7837c87cd0574c48a00ea", + "2ba59154eff2921c69cdeb23276510d3", + "758486d91898690c4ba0fd3e6e149956" + ], + [ + "55c45d7280a9b619306cddae25ee7530", + "9abfaf7525087c835c32fa8b3b75ff15", + "d75a6eab100d6de37a3214dcd89aef2c", + "8c7b7926e76796f3985f02c191eb66a9" + ] + ], + "prep_messages": [ + "1acd91a20b79e95050d47db9bf4b1ed5" + ], + "prep_shares": [ + [ + "aaf0cada92114681d890231d05395ea51dcf30c4fa042de2f21b10d3126976a4565c5032534c5af98418b0bf0647dddada1e47da1c608f0d03070d5baf530d1e52b4ace95d26bdc41c0bf64068880a5bcbf5ab84954e1087ff8721b600477c48bc82ef4255afbf48216c910cd76ca594", + "570f35256deeb97e0b6fdce2fac6a15a8d4d3367a586ac831119c6edeefb5ab1d4a2ad70c499a97f61b3eb86717264b1a941e67b26a189ff84bc81c89edafd3187e190bacd40bfa5813ccbd77338c7eedb90e273a045b29382cdddc5571e35de1da4a26362199818038b8624ba1ea4a9" + ] + ], + "public_share": "bc82ef4255afbf48216c910cd76ca5941da4a26362199818038b8624ba1ea4a9", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json new file mode 100644 index 0000000000..512b2aca98 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Histogram_1.json @@ -0,0 +1,89 @@ +{ + "agg_param": null, + "agg_result": [ + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "agg_shares": [ + "6ef23fd4b5f5502e5c215848c3703c1ac06dbc83cebd2ebb78b8549c64cf10b6a709f226d0e6aadbaac7c1512dce7f44e0715547855fae84e0a1f1fe7612423940c18ce556a3754c64b46de79038603b2ffae8c57346b7a9385f34f084d8f62d8e145aab9b0f1c038ed9f7b94d82a6cc7d32743c367987da80859005285a4b2f41e62177eead51b17bae964e100bd7408688c19870104fddb90ed31a0065a92f870079891c2ccc659a2a2cf3cb424cc3", + "55c45d7280a9b619306cddae25ee75309abfaf7525087c835c32fa8b3b75ff15d75a6eab100d6de37a3214dcd89aef2c8c7b7926e76796f3985f02c191eb66a970fd5de8e08724782338a0d5e77d181f61a976f8712fccdde127760cb8056d105e3d2f6c325607ab4a9a3ce791283b3af006fd1a4aa66fbfb30ade0e81c5d226e5c8ad6b7e4bdd02db51d98a13f5cf81d7797d2adb9c59afef3378108eec9ad02f4bddb5208b11cdd02e159b36eddd76", + "3e4962b9c960f8b75772ca0817a14db5a7d293060c3a55c10e15b1d75fbbef33849b9f2d1f0ce840be052ad2f996908e951231929338bb876afe0b40f701571d51411532c8d4653b5c13f242874987a5715ca0411a8a7c78c9785503c3219cc116ae76e8319adc51ef8bcb5e20551ef994c68ea87fe00866af6f91eb56e0e1a9db50301d9306d14b8dff8f26dcff583da5fdc03cb45257731ebdb4d471aebbff4cb4a9c0c24822cd5ca6be71fdcfd5c5" + ], + "chunk_length": 3, + "length": 11, + "prep": [ + { + "input_shares": [ + "6ef23fd4b5f5502e5c215848c3703c1ac06dbc83cebd2ebb78b8549c64cf10b6a709f226d0e6aadbaac7c1512dce7f44e0715547855fae84e0a1f1fe7612423940c18ce556a3754c64b46de79038603b2ffae8c57346b7a9385f34f084d8f62d8e145aab9b0f1c038ed9f7b94d82a6cc7d32743c367987da80859005285a4b2f41e62177eead51b17bae964e100bd7408688c19870104fddb90ed31a0065a92f870079891c2ccc659a2a2cf3cb424cc31d60b4e3908aa656e527d0a66eaeaaf493bde0a7a86be4ed3145a5596fab04256c95611675891b234a939c91215ec467aa9a516cd6a9a7b8d1a4ddb91e8dbfbcc8d9a45d8792f9d56a68061809b7ef4963736c20e3cb8ce6a95e1bd84c7ae51ccb14192b3101ac85a5a3a62415fb516df685b9313b53f39bc6a74062a55435f9c35f50ffd660a6d7e0e9365128bf6d87e52358afe563bc1bdce119291c611597889d36caf3247f61821eb596b089dddaf32359b12e74260a24d816335a2bf1aa93dbd84dd31773f2795ee931187525a570589f31e66a0e0d8a92370c3458fb00b2afb3e3d98f142cf9606d47d28a75caa8b4ee730e1ff3faf0aed3a154887dceaa6dfad49582d4a560b0d6599e0cbab2b36f20b8ca497f6540ca17f69595c695c2c6e0e00956acca22c71fab529936c47ad8de0e09f39d41a3b0469edcbfea242b20cd6a4748d4075ffb9a755b297902606162636465666768696a6b6c6d6e6f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + ], + "measurement": 2, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "6ef23fd4b5f5502e5c215848c3703c1a", + "c06dbc83cebd2ebb78b8549c64cf10b6", + "a709f226d0e6aadbaac7c1512dce7f44", + "e0715547855fae84e0a1f1fe76124239", + "40c18ce556a3754c64b46de79038603b", + "2ffae8c57346b7a9385f34f084d8f62d", + "8e145aab9b0f1c038ed9f7b94d82a6cc", + "7d32743c367987da80859005285a4b2f", + "41e62177eead51b17bae964e100bd740", + "8688c19870104fddb90ed31a0065a92f", + "870079891c2ccc659a2a2cf3cb424cc3" + ], + [ + "55c45d7280a9b619306cddae25ee7530", + "9abfaf7525087c835c32fa8b3b75ff15", + "d75a6eab100d6de37a3214dcd89aef2c", + "8c7b7926e76796f3985f02c191eb66a9", + "70fd5de8e08724782338a0d5e77d181f", + "61a976f8712fccdde127760cb8056d10", + "5e3d2f6c325607ab4a9a3ce791283b3a", + "f006fd1a4aa66fbfb30ade0e81c5d226", + "e5c8ad6b7e4bdd02db51d98a13f5cf81", + "d7797d2adb9c59afef3378108eec9ad0", + "2f4bddb5208b11cdd02e159b36eddd76" + ], + [ + "3e4962b9c960f8b75772ca0817a14db5", + "a7d293060c3a55c10e15b1d75fbbef33", + "849b9f2d1f0ce840be052ad2f996908e", + "951231929338bb876afe0b40f701571d", + "51411532c8d4653b5c13f242874987a5", + "715ca0411a8a7c78c9785503c3219cc1", + "16ae76e8319adc51ef8bcb5e20551ef9", + "94c68ea87fe00866af6f91eb56e0e1a9", + "db50301d9306d14b8dff8f26dcff583d", + "a5fdc03cb45257731ebdb4d471aebbff", + "4cb4a9c0c24822cd5ca6be71fdcfd5c5" + ] + ], + "prep_messages": [ + "1b2dc3cedc43f65731985f19081f490a" + ], + "prep_shares": [ + [ + "cd5978e237aafb0552d6f2614be379176c256bd1bb2d3fa71ec64fcf5e64b6baf5c530e6c828d5be1468539c16917e08f6cc5d754b81f6ea05ed0747377a2dbb5a731ed05a41704a11aea67a37c668810c7fbee6ef543f6a757ffa07f22a6fdc6c37173af38746dcd7ef1f2cb0f555d13b999f3ef6a282b6649c29878349c501711da5ad2a4ac3de6fccb15c803f918a", + "87cd13bcc0f7bb62542f40b8a480db80fca16e26264525b236a3664c792009277d9133d4ff0df494d18758677dbea683d9be082297301d1db87b6a345f74f07a3e268fd6e440eec02b3d4109b30d9c680c18d29df84586f30d30a2cf2419471d2b45845e9a4ba9f1c835ef577bcfa710e9d907592e678fa3a225e115cac914fde07e503edb901812725c6f25d7585fb2", + "add87361075e48973dfacce50f9caa67077de5a0a3d6e85b8b04772423132387fb2732f839d0de182c65e61553e08af6fa237248acc8e6cfad227ed43c8eed56bd3c1ae929a7c2bc1c5b47dfd2d57a56fd8f3a4f2187c7f94ae1dd203aa9e3bc20a53b7ada0b4f545e0c7a8370be163a582fb321c11446cb9f3b65dc2979f432236aba9b84dbe8182bce25a97ad12186" + ] + ], + "public_share": "711da5ad2a4ac3de6fccb15c803f918ae07e503edb901812725c6f25d7585fb2236aba9b84dbe8182bce25a97ad12186", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + } + ], + "shares": 3, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json new file mode 100644 index 0000000000..f18f47d506 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_0.json @@ -0,0 +1,194 @@ +{ + "agg_param": null, + "agg_result": [ + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265 + ], + "agg_shares": [ + "b43a2f79240602a73fafe498f4596524e2d16ccd2a68978aa0fc3b08cb757afa0e634bcf86a6f9f6066716d8d6ff6fc5d8323c1f04aa8b08948ef2e9e7a7a10e3be55e452c536f004da7d3502d93f9ef835b59067c8de2bec68afff55e15d4923cdab73e57ea28b90b70d15dc110dac2ab8c34f509842b025606222ee32ce920b14cc3ccabdfc4f1f743b9ef3ca0c2b5bd715085b0d76c95daeecfad16278bb6", + "4dc6d086dbf9fd58a4501b670ba69adb202f9332d59768754303c4f7348a8505f59db43079590609dd98e9272900903a2ccec3e0fb5574f74f710d1618585ef1ca1ba1bad3ac90ff96582cafd26c061083a5a6f983721d411d75000aa1ea2b6dcb2648c1a815d746d88f2ea23eef253d5d74cb0af67bd4fd8df9ddd11cd316df58b43c3354203b0eecbb4610c35f3d4a4d8faf7a4f28936a09113052e9d87449" + ], + "bits": 8, + "chunk_length": 9, + "length": 10, + "prep": [ + { + "input_shares": [ + "43118698b73a59751812aa20a73ae412766ef3c4c7559adaf4f08d6d73fbe01849ac4f0da41a26f10b1709d08f56da39953a74ee5cca941b880a5857b143cdeb7065b4b8f6b13b474040cd9e5307fd42850c79e49dc4808a8bf2d976223522179142c2cce38fce9218a371029ac88597283e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe8ecf9e42a156f1fd2b6c434eb62813c0929e78c86cf9bcfad5d54287598c986364fcb6fbbfa0db79dc0f4c1dbaebed54201c88b9e1f93a7fcabc0137d2b6c8ec6f423d7aeeced8f7dbd4c64e7ed595b6e5d76034a16c5686a8982397ef1e882232a95e11e7377d5b758015b716472c4dfaa9021bf2f861e18507f7f8435b55a4a3c8f7357e245596c08975169be3fdf4f2bc8600e680b9013f52b67000959ce3a588caaabdedb7d6201210902695051d808571846039dc672be3d2a7d2d25137baf47f5b71d1d907c9db4d3c20045cb32bdcf9c0094bce467da04ed90e885c9e0765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab89afabd89620aa6090d21ad7226d173f23cbdd31702582ca06b336d277c4f39903414ab2baddfa578bce3be8ba27d68651d720b8401a4ffc61c999f628cdc71c058767c63f23e8b933add17cd3e50ab8540c9ebf935b2912fa26d68e2cc9289e4f894b8d03a81b8d306cadabb209de35c980d4ceea42abc4a0581b6114c77e4cc66c01be07deb7bdb8db23df5d67398497b30ea78518ff759304b5269502f93848838ba2d3e1737aadbbcbd4cde25689fff7a738df9017a4f2986c8fe8b8ba6b6f87b4dd6ec84876ba076c31039cf59b695313060ca1dfdb288c8924ebcaddddf9d067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ec604930ab55e288606fdeb863afbeb9df6a009694c055c34d68e19c19ef3fa851363493cdf197c201958449e57e327b15eb5e25d2d347374a85e4685b432a15f4f768fa0b180f6db9f0af65cbbcb0c137a2e12cbb0aadf81e78244e2b8855634a9d0014005d9c9209381943f019df54769b4452a47ce0f223ae52a4d28d725d97e40b37b250499508838bc8a7ccb133f7a02fbfc91fa1c27685786808ae4a45e08cf841c79f3a61b58ae87005dd4e43920089fc2bc23b8c6ac3aaf2081a14edf30a0299f3094410689ec026a8bf8ba2b1c470583987c30d5d8ca6e7ea605d0c7661dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ef7eaaf35761f7640b807483793ed8ab3ae20672da387979a8171eb1425700e257a912e645a80739e5d494ba6d419dcd4fec13aa806fcfcc84480d7e0e676916aded6f1cf9d69f7e958dceae1edaa11b2569954b7689e647906cccbdcbc2897f139356d9c85168f08ed8990aefc891158a1b89d7c19d3c56ad2a91d3de46ada48ec6338d13efb16c4cb49acd981a044c335240ce7d1db84fde51058290cae528cc7dc5794daa652268d9e5d0fa639a8549c9fdcd3fd126f653f9b970d804fdd4f420e473a31410fe9a84fc43ae415d008ac86ca0881f737382196cd5b6dd4b8673cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4bd36baab91c2867bcec745bc5334ce8cda1a0d77f6bb5f1838c60904f8ba7aec00d2529e87c41702b774c6f11c632d35f477988847de39626fd7e83b07ca2de2d7dbd68d07617dc590e00684c79ff1d8ff484a31056b53b29cbe470c8bf99515d7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f29637308283d5577ee3ea54987f14e4b1b4a51a17f7426a1ea86b42db1410a05064dd773bb5dacdf49702f7cf3ee9695f82fe881ef34c52e8d46e1e415989a757ec94cdd07294a2290e19749606638ed7ab2138cb9f7769a75b169f02dded1bb93c70095ef01be80b96b0ec21588146c8a238abd2bc14a170c5a024fe683c809ff478def04de33f353111c054ff502e7fad8e768bde39cfe419373b0bd40f1ae943d61b6fb824ac689955567fb7526f05d4db0c32f0e7b76cadb917ce200edfda6065129e19fa38ba3855586913baee0bbbade97144bac9c4763c95278f90bcaaa42fbbbfac31fcba0b8291025dbfd1a3660a60cc97763672331ee7db22c0932f46dfc313e7bd60ee86b7e3b4c11b5daaf8cf3e35fcaa124ae0a05bd063ff4944364ee16326b6131422bf08803aa713c771377f5f47cc940f879b2a1763110c22867c7a704c970163b15f702757d87e6e24a4474865877352ecef45294ef3bb7ec9e45f8609da982a161f89a8a9c2a6cf56fc9e8a2d9396fccf4bdd7b8aaf370f4478cb45bd5773f2a5af3d6149b4e41e364cf87c771848716998b070fe95d1d74c9d77466eae8efe0d5a0435de53d50d562c611ed8a2145c752ea54b31101db21f2688fefac5a3df5fc8163f134e5bcfcfcb2106a642ae3e6bcbd15654f09546ccb8c48d84d3bc7d0a18900dba3d66cb02ec33303132333435363738393a3b3c3d3e3f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + ], + "measurement": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "3c1365280c0256e2bf8fa1dda6c8210c", + "4cf0ce9963cd8783355469ad43277e53", + "5ccbc3ef2ce2fdfc4422b2f29caa7aec", + "f565690aac38d90228da50a3a2e2355a", + "c1f6746cb91b25006fe29bc5b9dbfd4f", + "2f1e7357292ff6949783aafc745cf130", + "c39d92bfc7f862e84f259b7440b04896", + "932ebc51032cb90072570bba4b64f80a", + "966e96998e4aeca59e1693fabe8aeb91", + "9b25702c90f2ce3136faef39b2b783e7" + ], + [ + "c5ec9ad7f3fda91d24705e225937def3", + "b60f31669c32787caeab9652bcd881ac", + "a7343c10d31d02039fdd4d0d63558513", + "0f9a96f553c726fdbb25af5c5d1dcaa5", + "44098b9346e4daff741d643a462402b0", + "d7e18ca8d6d0096b4c7c55038ba30ecf", + "44626d4038079d1794da648bbf4fb769", + "75d143aefcd346ff71a8f445b49b07f5", + "7391696671b5135a45e96c054175146e", + "6fda8fd36f0d31cead0510c64d487c18" + ] + ], + "prep_messages": [ + "faa44093d924dc5a7a7964fd9c8ec82b" + ], + "prep_shares": [ + [ + "f9ab3aa30354eb87abdd838ca558b6cbf26345360ccb2dea7deffb9e075c54b422f03470466c54abee94d25dd57eff3a073bf64fcf5eb3d7334b815115b39e6b16ea9cd0bd90f550dd701f3bf288451f17d4c7a3adc44ef5ad49663dfa2e95250320cb7d3fa0323ddcddcdb0d628146f48f6b53badd73c5333fe30cefbca3badd9a688c628f9df7129d7283772dfa0cc630e06a2795703ee70e9a01f64d3a704df997b7b6de7335aedbab9b3a1932989f93e66bb51c72416fc7f1c54bdf6f15d04c07dd5c8c2d5abea0921c5047299cd82f633af0f04fbde479b82628f0e446e781cca6b0548eaa34d8d1e5279078afe906905aa91922bf69977a92b586541d02a80245334e5321901ea62181f121f7aaaaf89061b36b0f9eb5c9ca22ddb5d09bca32696a262178178745830d0c0dee8fcc9033f8f5c98e5f3eaa91fded998019c068644495dcc3fad1eb4b63821a23b", + "0854c55cfcab147838227c735aa7493430369af6251b129c24fca111dc13d34678b16bc625356621f29ea8e47b665ab509578cae546f46e04b013376fc8439d5cde2eb50a36d1303c487fd8456539db6e653b588217b6b273b7b3d79de062a76332662a738cb172c781306cffa8b46f9aceaaf6b663a749763c9db91c5ebb62dd0f94a3d036b82c41b49709fe6c3815e215adf1c2ae55fd9d90f8186c07c37af26d2e0803bbda031317b76cdbcc7b6817529c92ef23b00db2243ffd4767f7c8e9d39781324cef39ddf613e24e4a6351037d62b77ff946d119fb2da47fd757e16d34aa0c53bd7d6fb53472d84ca55f554638e2529702522faa8c177d51394a89bbd4cec850ee6ff565296aad4f2cd6b9f35ad7ff7b7b494b97248e3a894dce393259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7" + ] + ], + "public_share": "9c068644495dcc3fad1eb4b63821a23bf4ec2449a30929eb714d75d9db74f3a7", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + }, + { + "input_shares": [ + "44118698b73a59751812aa20a73ae412766ef3c4c7559adaf4f08d6d73fbe01849ac4f0da41a26f10b1709d08f56da39953a74ee5cca941b880a5857b143cdeb7065b4b8f6b13b474040cd9e5307fd42850c79e49dc4808a8bf2d976223522179142c2cce38fce9218a371029ac88597283e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe8ecf9e42a156f1fd2b6c434eb62813c0929e78c86cf9bcfad5d54287598c986364fcb6fbbfa0db79dc0f4c1dbaebed54201c88b9e1f93a7fcabc0137d2b6c8ec6f423d7aeeced8f7dbd4c64e7ed595b6e5d76034a16c5686a8982397ef1e882232a95e11e7377d5b758015b716472c4e0aa9021bf2f861e18507f7f8435b55a493c8f7357e245596c08975169be3fdf4f2bc8600e680b9013f52b67000959ce3a588caaabdedb7d6201210902695051d808571846039dc672be3d2a7d2d25137baf47f5b71d1d907c9db4d3c20045cb32bdcf9c0094bce467da04ed90e885c9e0765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab899fabd89620aa6090d21ad7226d173f23cbdd31702582ca06b336d277c4f39903414ab2baddfa578bce3be8ba27d68651d720b8401a4ffc61c999f628cdc71c058767c63f23e8b933add17cd3e50ab8540c9ebf935b2912fa26d68e2cc9289e4f894b8d03a81b8d306cadabb209de35c990d4ceea42abc4a0581b6114c77e4cc66c01be07deb7bdb8db23df5d67398497a30ea78518ff759304b5269502f93848838ba2d3e1737aadbbcbd4cde25689fff7a738df9017a4f2986c8fe8b8ba6b6f87b4dd6ec84876ba076c31039cf59b695313060ca1dfdb288c8924ebcaddddf9d067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ec604930ab55e288606fdeb863afbeb9de6a009694c055c34d68e19c19ef3fa851363493cdf197c201958449e57e327b15eb5e25d2d347374a85e4685b432a15f4f768fa0b180f6db9f0af65cbbcb0c137a2e12cbb0aadf81e78244e2b8855634a9d0014005d9c9209381943f019df54779b4452a47ce0f223ae52a4d28d725d96e40b37b250499508838bc8a7ccb133f6a02fbfc91fa1c27685786808ae4a45e08cf841c79f3a61b58ae87005dd4e43920089fc2bc23b8c6ac3aaf2081a14edf30a0299f3094410689ec026a8bf8ba2b1c470583987c30d5d8ca6e7ea605d0c7661dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ee7eaaf35761f7640b807483793ed8ab39e20672da387979a8171eb1425700e257a912e645a80739e5d494ba6d419dcd4fec13aa806fcfcc84480d7e0e676916aded6f1cf9d69f7e958dceae1edaa11b2569954b7689e647906cccbdcbc2897f139356d9c85168f08ed8990aefc891158b1b89d7c19d3c56ad2a91d3de46ada48ec6338d13efb16c4cb49acd981a044c335240ce7d1db84fde51058290cae528cb7dc5794daa652268d9e5d0fa639a8549c9fdcd3fd126f653f9b970d804fdd4f420e473a31410fe9a84fc43ae415d008ac86ca0881f737382196cd5b6dd4b8673cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4bd36baab91c2867bcec745bc5334ce8cda1a0d77f6bb5f1838c60904f8ba7aebf0d2529e87c41702b774c6f11c632d35f477988847de39626fd7e83b07ca2de2d7dbd68d07617dc590e00684c79ff1d8ff484a31056b53b29cbe470c8bf99515d7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f296373045c4b3272022ca8eba72c601043d08da35f439bc7d0100d6aeb7c2a7cb74a82c9abf8982362807bed855c50ebe0e571d2624f06387b4439e7580af40033dccb657fea66e721e9b2c20cdd3dba93c3261c4ec327a89ed4007b7393820f46a60ace5876392117b97b9a358a1286944bcf0e7cf4f471d46694dc37fc670aee1d4cd7fa002020f5c7ea0bc65d0ca4e42729107abeab7a2f7b86d9f663a73485f54c4870609a0789554bd2f623176f563b8d577965464bc1d7ecca70103d13c963f741f6981cb1d83a7eb09878d39d5ec7e007d390fd93c9dba87670e981d6e21069f72602526625fd88a5cafc400b01720fccc97763672331ee7db22c0932f46dfc351a6df904c48d8a976ce693f58706d7f16ffb3c0ea860cc818c14c42c925832c041c075fd291ba417723cb6e68e5deea5716298370a7c6aae23beb7276354591e9c084351aa1ddb79d9067319c93931e5018cc62705ac5dd58f1a8b7439bf4bcff7192ee243138bc26a9a2c42eb57859751a58f04f4f83b4b673254700571cdcb66a38b1187b425df9e234484fa168dd01ab675fb38b167ec06b6b7878311fcf2f20ca9aee115b9d683375ce1dc64f98d93136680c056af071501b2b50ea4b267cab3e117c157683ba9f7a10069efa0afab0ed9ec6444ddf16d5e834834fe2e0dbd0df92d6b6c19697673837bf51d697303132333435363738393a3b3c3d3e3f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + ], + "measurement": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "3d1365280c0256e2bf8fa1dda6c8210c", + "4cf0ce9963cd8783355469ad43277e53", + "5bcbc3ef2ce2fdfc4422b2f29caa7aec", + "f365690aac38d90228da50a3a2e2355a", + "bef6746cb91b25006fe29bc5b9dbfd4f", + "2b1e7357292ff6949783aafc745cf130", + "be9d92bfc7f862e84f259b7440b04896", + "8d2ebc51032cb90072570bba4b64f80a", + "8f6e96998e4aeca59e1693fabe8aeb91", + "9325702c90f2ce3136faef39b2b783e7" + ], + [ + "c5ec9ad7f3fda91d24705e225937def3", + "b60f31669c32787caeab9652bcd881ac", + "a7343c10d31d02039fdd4d0d63558513", + "0f9a96f553c726fdbb25af5c5d1dcaa5", + "44098b9346e4daff741d643a462402b0", + "d7e18ca8d6d0096b4c7c55038ba30ecf", + "44626d4038079d1794da648bbf4fb769", + "75d143aefcd346ff71a8f445b49b07f5", + "7391696671b5135a45e96c054175146e", + "6fda8fd36f0d31cead0510c64d487c18" + ] + ], + "prep_messages": [ + "22b05b9abf6f7798c91fb089ec73d79c" + ], + "prep_shares": [ + [ + "f9ab3aa30354eb87abdd838ca558b6cba06d3c978291ea82c4c856026ce4a3cb3dec40f98bf1cf3db33e3a736043891abbb4629ed714cfb72b9a70be2083cc84c41c02e448c46154ed923d78db089e67c7bbe0ef236ecd77f99c8d5e5272f4aa0320cb7d3fa0323ddcddcdb0d628146f3a94850ce63a023fa1ec776f6082d00e5fef53097f1b9a562fe9c3c4b1d9b03a87131642b49c990eb174e205bf6d68af4248001090e9ee0c2c52614d1778ac60eaf3003e3714c6ef5c99442ad527fb434fea0dce4d6fe6cd3de25237bf75d34a3b619efbec942fe7f466c96521a9672a1b8773d0a3c0009b8020cc9719ddae7aee79d2a751e4405c17493fb96c28b9dfd90c135f76582ed5f72b0867cf2276d0aee16e5c44d6ac86eff63369b58b79fd5f34e68b4406f78664224591044c64f776d62683c1ad354cfd588c2168df20c6374a2b13433b05ee12db5fdd45070eac", + "0854c55cfcab147838227c735aa74934a0198736b579cfe4f87a1ab05d6cecc278b16bc625356621f29ea8e47b665ab59a91a8a0b72799489818a54757992f45cde2eb50a36d1303c487fd8456539db688dec5f51c76fdade09bf05bb59d8f82332662a738cb172c781306cffa8b46f986b9544adb196632fd3464f73faa14d8d0f94a3d036b82c41b49709fe6c3815ee39a9e9f46241986e33eb72c43757e3d26d2e0803bbda031317b76cdbcc7b681efe9a68224da578206e4518bbd64e9b69d39781324cef39ddf613e24e4a6351009ef3a1ca5f6d5b556077ed9c6e12b98d34aa0c53bd7d6fb53472d84ca55f554bff591feeca2f8c458b72bc0dd4a9dc4bd4cec850ee6ff565296aad4f2cd6b9fe2ca244753a83522e0d4496a1c66cdb8259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7" + ] + ], + "public_share": "374a2b13433b05ee12db5fdd45070eacf4ec2449a30929eb714d75d9db74f3a7", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + }, + { + "input_shares": [ + "44118698b73a59751812aa20a73ae412776ef3c4c7559adaf4f08d6d73fbe0184aac4f0da41a26f10b1709d08f56da39963a74ee5cca941b880a5857b143cdeb7165b4b8f6b13b474040cd9e5307fd42860c79e49dc4808a8bf2d976223522179242c2cce38fce9218a371029ac88597293e246464233e9d7cf7048bbe3d18d369dfb8d462dddbe94e33f7ebc07bf0cbe9ecf9e42a156f1fd2b6c434eb62813c0a29e78c86cf9bcfad5d54287598c986374fcb6fbbfa0db79dc0f4c1dbaebed54301c88b9e1f93a7fcabc0137d2b6c8ec7f423d7aeeced8f7dbd4c64e7ed595b6f5d76034a16c5686a8982397ef1e882242a95e11e7377d5b758015b716472c4e0aa9021bf2f861e18507f7f8435b55a4a3c8f7357e245596c08975169be3fdf502bc8600e680b9013f52b67000959ce3b588caaabdedb7d6201210902695051d908571846039dc672be3d2a7d2d25137caf47f5b71d1d907c9db4d3c20045cb33bdcf9c0094bce467da04ed90e885c9e1765a41d98cc0cc454d1d97efe2255eed21c3b2297d9d0717f8d46d1a016ab89afabd89620aa6090d21ad7226d173f23dbdd31702582ca06b336d277c4f39903514ab2baddfa578bce3be8ba27d68651e720b8401a4ffc61c999f628cdc71c059767c63f23e8b933add17cd3e50ab8541c9ebf935b2912fa26d68e2cc9289e4f994b8d03a81b8d306cadabb209de35c990d4ceea42abc4a0581b6114c77e4cc67c01be07deb7bdb8db23df5d67398497b30ea78518ff759304b5269502f93848938ba2d3e1737aadbbcbd4cde25689f007b738df9017a4f2986c8fe8b8ba6b6f97b4dd6ec84876ba076c31039cf59b696313060ca1dfdb288c8924ebcaddddf9e067f2be6033af80313292c03996a39281c78299d8549d12cd8427104783575ed604930ab55e288606fdeb863afbeb9df6a009694c055c34d68e19c19ef3fa852363493cdf197c201958449e57e327b16eb5e25d2d347374a85e4685b432a15f5f768fa0b180f6db9f0af65cbbcb0c138a2e12cbb0aadf81e78244e2b8855634b9d0014005d9c9209381943f019df54779b4452a47ce0f223ae52a4d28d725d97e40b37b250499508838bc8a7ccb133f7a02fbfc91fa1c27685786808ae4a45e18cf841c79f3a61b58ae87005dd4e43930089fc2bc23b8c6ac3aaf2081a14edf40a0299f3094410689ec026a8bf8ba2b2c470583987c30d5d8ca6e7ea605d0c7761dba95beef2f4b94f5306317ecfa60010d6b18c2aebb994a4559fad9f3538ef7eaaf35761f7640b807483793ed8ab3ae20672da387979a8171eb1425700e258a912e645a80739e5d494ba6d419dcd50ec13aa806fcfcc84480d7e0e676916aeed6f1cf9d69f7e958dceae1edaa11b2669954b7689e647906cccbdcbc2897f149356d9c85168f08ed8990aefc891158b1b89d7c19d3c56ad2a91d3de46ada48fc6338d13efb16c4cb49acd981a044c345240ce7d1db84fde51058290cae528cc7dc5794daa652268d9e5d0fa639a854ac9fdcd3fd126f653f9b970d804fdd4f520e473a31410fe9a84fc43ae415d008bc86ca0881f737382196cd5b6dd4b8674cb515ef70c4624bea32c22a7b72c2f8e1c2fc693a4905215e10580aef647be4cd36baab91c2867bcec745bc5334ce8cea1a0d77f6bb5f1838c60904f8ba7aec00d2529e87c41702b774c6f11c632d360477988847de39626fd7e83b07ca2de2e7dbd68d07617dc590e00684c79ff1d90f484a31056b53b29cbe470c8bf99515e7ad2939120d3b9b9ebabfb29d0e7b77cc7bb5ab97fc44591ee036de0206b8331c99c75e8bcc50ac1cb75fec3fb640318010d3ddeaaf423d14d2d715e7cf81ee4d01ad0c0f09c66b2e0b396b93c2bc97b21a42cdafe748aa4b59c250e4639be7173f4cff260339d2797e402653a3bef19a0a17763395889c4269679f6bd0289a356eaf0f06b409d24d4c112ff8f60b9383669677635f20d8eeed5c38d9500e39dca878f578b4980f374ee556aa3458b551628ff9f110d11b7f2497195d9bf3c9557e6f3d11c05f52158aab8f6485cdecfa158e592453351f1866faed652e75b37562a4c696867a89ed8b55355c82c6b571918d3995cb6516f00742a7f0974f62ca846d1306422176a204627930693eaf08951f082629d0a5537aea1d8729693798896fb16830a7cc7b29737f29637303d4b2d335a15f1c48ed11d7948cae1b1efcb5af7c398f535e799f58a13109605cc3afae7e08683e40b1d015cfb8de1f5ca44d2eaa0fbfa549b4aa3933de82380b81ddd451d5e44a8f7f456355dfa125c002c8c5e7b2697e33dbd5cc1ac7ac8bbdfcb08ed49999a24a72685a31cdc25e0c9a27be6eb32af2d260f6d60427108a552cbe2a99ad070aec066c78bbf260e49e7ead7646ddd80d2fd067e7361e83e23aa3df8810cb4a44ee4b1205ecc8c548c064345134bb02e081a65ade1d3ec4523448d81153fa692e852e443120c8aba426dbc11bcef30ab6de561000c5be09b10524cedfab2395b99861a6f0c7e9c820dcc97763672331ee7db22c0932f46dfc3591f66851255b173a26f12c813e393a75c279385a4ef1668e0de195f818a9553d2a096f927333e1b445c8f212b665412b3f546fc56600ff4bc71f71f3c8aedc788a14e5e6f61343cc668e4d7e8d5b22314d9727e7e216f01d26d84168b8b8cad052eed93ec12355123dbbe497b1d0f6a92472c5181623dd46fe47e576cc7e804e23f58098d06504f11e23d87debccc25206b7ab2e8a54e197ecb27785fa834700ce9dab85af30a0cb4e385e6469db3e14a8545b97d72b9b4ffec701ab993457758873ec75af28a865542c437cf00bfc8092eebbb13b15cf9b481804696904c6ffae417be85dc3e8889fc8d2bf1cc7386303132333435363738393a3b3c3d3e3f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + ], + "measurement": [ + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "3b1465280c0256e2bf8fa1dda6c8210c", + "4af1ce9963cd8783355469ad43277e53", + "59ccc3ef2ce2fdfc4422b2f29caa7aec", + "f166690aac38d90228da50a3a2e2355a", + "bcf7746cb91b25006fe29bc5b9dbfd4f", + "291f7357292ff6949783aafc745cf130", + "bc9e92bfc7f862e84f259b7440b04896", + "8b2fbc51032cb90072570bba4b64f80a", + "8d6f96998e4aeca59e1693fabe8aeb91", + "9126702c90f2ce3136faef39b2b783e7" + ], + [ + "c5ec9ad7f3fda91d24705e225937def3", + "b60f31669c32787caeab9652bcd881ac", + "a7343c10d31d02039fdd4d0d63558513", + "0f9a96f553c726fdbb25af5c5d1dcaa5", + "44098b9346e4daff741d643a462402b0", + "d7e18ca8d6d0096b4c7c55038ba30ecf", + "44626d4038079d1794da648bbf4fb769", + "75d143aefcd346ff71a8f445b49b07f5", + "7391696671b5135a45e96c054175146e", + "6fda8fd36f0d31cead0510c64d487c18" + ] + ], + "prep_messages": [ + "4b28ca5fab189f5689d02be161fe25af" + ], + "prep_shares": [ + [ + "f9ab3aa30354eb87abdd838ca558b6cb4cd1280dfc7d2f12bcb14c5a38a5fa1e4225a50845bc43cc7276668331627f53e6d1debec49fc79a6e0a2382b73e01d1af45275c3e553e9f0df2dce1fb8adf9b7cc9862e001ad0d0059d27c68b40e998a4233df802cb98ef8c94504a86e9b0e423e0661acc82059937329f34832d079f0184e04d6aafecf62dee814f748123de797d05203e140ccc9be383de282e7d377e0e3400af264e528f66cc39c14f6b590939d50e82fe5df4fa1e0aa96c27af32a5540a1ab456284c050fdf4fc7190c71acfc9d952d03d4af955b8df3f10fc64b48f1399d22792b7b18e64c7c09d986b27c4874ee16fff4ecde9d89391d3ca98a14f95ce098c05629305bb26e0db0955be0bafa82ff2a6b48283de372c395862a636d4a9bfdd06a15405a71a1d56a5a30afa2bde6fc55d8a3386fe4bd3c08985014376e4adc53e094949d34b36f1e8b16", + "0854c55cfcab147838227c735aa7493459da23320d129aafa331318931d85cdd78b16bc625356621f29ea8e47b665ab5d29caacc5ba36200516852c360c0a2d9cde2eb50a36d1303c487fd8456539db613567966c72ef1b9f8b8f2e93aebdc1c332662a738cb172c781306cffa8b46f908c1bfd01acb45c5c06c9ecb16265a3fd0f94a3d036b82c41b49709fe6c3815e1af0509da314c9297ca795e4487c9cc326d2e0803bbda031317b76cdbcc7b6819dd6910f3002a99c7075366ab035710a9d39781324cef39ddf613e24e4a635108fbc5c1b9dada07dd81a620426914410d34aa0c53bd7d6fb53472d84ca55f554883acb353f6718ee88b8e595fe5b9373bd4cec850ee6ff565296aad4f2cd6b9f2bdf8fd9fae82be3d2039778cad3aa16259fa038f067fb28655b6e18edc9a032053e900a2e3d07f7ca52461922710f91f4ec2449a30929eb714d75d9db74f3a7" + ] + ], + "public_share": "14376e4adc53e094949d34b36f1e8b16f4ec2449a30929eb714d75d9db74f3a7", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json new file mode 100644 index 0000000000..21fcfa001b --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3SumVec_1.json @@ -0,0 +1,146 @@ +{ + "agg_param": null, + "agg_result": [ + 45328, + 76286, + 26980 + ], + "agg_shares": [ + "447fb76d69adab4dc1990d2289325675e67772e564baab6396c6b45c58a1c5febe9c72ab66aab2aab4b588ff774cb480", + "47e6ff190ecf95c1c1941e2b03db246104c982f459555c7d30035b353f18e8985d9e4661cd30031dc481a1afdc0df13b", + "864b49788883bef060d1d3b273f2842916e90b2641f0f71e0136f06d684652684a2e47f3cb244a386bc8d550aba55a43" + ], + "bits": 16, + "chunk_length": 7, + "length": 3, + "prep": [ + { + "input_shares": [ + "5d82bd1f81516122465f8a60a3209afef5a5c181fdfd80d20d280edb0ae8ccc4953eff5c0efe473d411cf4f3b2e3fd320c83c6b8f2c626a42d25f89594365561966e130ecf8a778e42ce7cca37b919eb9304560ba6a60a5e5b523f5ad397b378edff4b21af66fba2f59db74e46ffdfa077bcea50472d6e771640a71fa31dd96446a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6f3407a9f6f9d6cf9ccc3696c4d3226e89cf3207643a12d8c30332a8d364c97aaee81f4dc31ad62d49506e422e146492bd92a5cc933532fbfc1ee2e8e33116414358edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c523cf7ae624b8fe1c8ffc2229bbeecfc18e91c8683df7c579390d8b31ca87372cb5ebbe716d0edc0fe8f10c54835396a68cbacc670eee07dffa3203f8b202dc414ccb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee607eccea1987b4bf6ba603e29043ef636b1b327e57adf1b29b098d4eadfebb737a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55d6140ffda97a5018ee007adf5125f079bebdb6eba6c35d0504d8b7a9cbbf0bd9d57bd5b563fdc052a492a7dad4a3c782b69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900222674a726db2b1b155190cec29c6afefe3841924dd7b212437fb10bffc8a17cea09a97ec2dfafe897e8ad4c5418946525e0908ac8790580a47a17a8089e7b78498f2a54375778e387b0985293431e2103f51600211e6e9a3f388e53d2df072d486d4c4838d8d8601fad2bd86d51ad3a58aebc0d8f6bac048d77968b26826cf545b44f7513667ac696564df8113529415a6e467d3a9f6bda8630717be753a45b5d688bbc4b95712f3bec044eb26db66f23861bf870cfb30347361e81a451f7f17642f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1965964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfc12d1a6582b16b4bf804f6503665f275e5de6c60aac82324be975fedb2dd651c1173635fde95660cc844d347d10f8a24586a75597b1c39e828063364e13921665af885b721addc72a72d9a23bb6aa7aa3169804cf944d523d855c97a71d723b464e3976d1264bef3c266ff630ac23753eb79ad90eb5593ce456db34e977dbb19cfb58c52cbaf4826858368c3cbd8863abb5b2b95c36a447b8a4eef73e276d8bc61be6a420a12dd507bc72ef767bf49ddc9a7dcf61290b191ca4c1444e4863f1438e480a661f860c6868256aa7390e1a5033292afdcb6da8c464298c1cf5bc86bac0ad5ee5f72219e33a356a4cc3bdefd606162636465666768696a6b6c6d6e6f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + ], + "measurement": [ + 10000, + 32000, + 9 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "22c1e77978e4e319838804b62d66c7d1", + "4eecd0a1213e3921caece61ec83597ff", + "27112639228e3b8e913cd8ff27c4e62a" + ], + [ + "18a2aa085a9adc958c310ab9abf3b675", + "0243d6a6c871c929a8ab73bcbfb2a2dd", + "75df6c20efbaab098480e08f49afa5be" + ], + [ + "d8c36d7d2d813f50b845f19026a681b8", + "b24d59b71550fdb45567a5247817c622", + "6e0f6da6eeb61868ce4247708e8c7316" + ] + ], + "prep_messages": [ + "065f5893e9afb58b358f78e7ed2cc07c" + ], + "prep_shares": [ + [ + "fedaa3d68353f75a2db6a1e49b2397a2bed007840b0f6ccc5ff3d89835264b58afa1771f5d2a277b65bbc2190fcac717b4f07c6d7ac4c692ad519e8a33e6d22479dfdaa6e2d3eb787ff4c9cc9deb4638b69a422203daec5a3a9b28f4eaddda1eef0000c41066465d05570989f605ad679d3d6906a8eba159f5af3995de50bdd1068ba7c0556bbd0724ada90ce58efc5b7c24f02cbc919cdb90bd915098f1f7b4bbc85c69e091f780fd70df4abb883070d02d2e06f76874cd4496526ce4aad58adf2b97e7cfed76951b532ebde9a3518e407992b67cbc6f3ccef64065bc5c214973167fea3f7baea5bf44bc32b85e37fb1f12524e4f720b7d10547ea1b558c569220ea8f5008a9be1e061606e347c3c49", + "cb8307fb467bb023448e58c74d159bf4ed77785c059b1bfe3c5b36ab3bb46cc6051853dd2151e2cc480d5164567c8c41df857ef182519ceaf1c704a25e6c948712d4839078fa72b1e64e8531f3e54c090d01fcc6023c8dc28300ceb5fd722c80211848dd2c787bd764b2099de3139df3e7472bf3c98fc31f1d3e09b8deaada8bb19f2941d9f4660018a051ede752680aa6d05e91c0c2feb5199be821f7eba9e3abe594acb8e9611a81294b8ed708fa93caa4f00ab2df5a298a09a7d71924a9ea0b98b57a0d21fda8ff765c0394041a9a2fce409f56e24f387aba5eec7bb507d18f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449", + "39a1542e3531588156bb055416c7cd68c32c28a3ac4eed2bb0f0460d41e3634bc0746eb13013792fcc318698a96b1343b152abb747abd3245a70d95eaf31f330e9e844395897d8d5f475d4644149864ca15c31da48dce96e593075a17d4deff6ae67d137adc6f38ec943c596b6fec177e66c119988225c82ac239141c8448add3f9b5c6e59d9736159ede439854b0532d9253f45dd09cb6b800fab1308b1f265978eab94b6bf4105729f7da8eddcee387a2a1eac1c64418e342368a3478fa335500371d0434c5e6511da60302f9947e84a52c49e6dc731f79ca0543441bff7a4cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb" + ] + ], + "public_share": "220ea8f5008a9be1e061606e347c3c4989a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + }, + { + "input_shares": [ + "5d82bd1f81516122465f8a60a3209afef6a5c181fdfd80d20d280edb0ae8ccc4963eff5c0efe473d411cf4f3b2e3fd320d83c6b8f2c626a42d25f89594365561956e130ecf8a778e42ce7cca37b919eb9304560ba6a60a5e5b523f5ad397b378edff4b21af66fba2f59db74e46ffdfa078bcea50472d6e771640a71fa31dd96446a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6e3407a9f6f9d6cf9ccc3696c4d3226e8acf3207643a12d8c30332a8d364c97aaee81f4dc31ad62d49506e422e146492bc92a5cc933532fbfc1ee2e8e33116414458edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c524cf7ae624b8fe1c8ffc2229bbeecfc18f91c8683df7c579390d8b31ca87372cb6ebbe716d0edc0fe8f10c54835396a68dbacc670eee07dffa3203f8b202dc414dcb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee607eccea1987b4bf6ba603e29043ef637b1b327e57adf1b29b098d4eadfebb736a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55d6140ffda97a5018ee007adf5125f079bebdb6eba6c35d0504d8b7a9cbbf0bd9c57bd5b563fdc052a492a7dad4a3c782a69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900222674a726db2b1b155190cec29c6afefe3841924dd7b212437fb10bffc8a17cea19a97ec2dfafe897e8ad4c5418946525d0908ac8790580a47a17a8089e7b78499f2a54375778e387b0985293431e2104051600211e6e9a3f388e53d2df072d487d4c4838d8d8601fad2bd86d51ad3a58bebc0d8f6bac048d77968b26826cf545c44f7513667ac696564df8113529415a7e467d3a9f6bda8630717be753a45b5d688bbc4b95712f3bec044eb26db66f23961bf870cfb30347361e81a451f7f17642f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1965964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfaddd5e94884c05ad97bdc1b9878082a47662898f549754812b390a2bb02ba487c6791eb083959499d8c22ec4b79caf467542aa89e22d69fa2bea599ce1923cb05efda49baa01b0405db15d8cbfe774cf38d520cde78b817177df5ddfdd1b7c5b164c1955aadd97a8ee58a53940041a8feb79ad90eb5593ce456db34e977dbb19e3054823c514afc4e5ca9c5a7abdf60b2ad80e66199c131e1dad4436e5289a51acb7aff16412afc36a49d37a813224bbadcfa7c6ab7e817fab68ed0be42d24ca34df61c2d8a38df8d0fe92416f131481fcc5f12eee6f2e3fa7b8035d631770c4faa15307c8f847e907b1b0ce96f9fbc1606162636465666768696a6b6c6d6e6f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + ], + "measurement": [ + 19342, + 19615, + 3061 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "a0e5e77978e4e319838804b62d66c7d1", + "edbbd0a1213e3921caece61ec83597ff", + "131d2639228e3b8e913cd8ff27c4e62a" + ], + [ + "18a2aa085a9adc958c310ab9abf3b675", + "0243d6a6c871c929a8ab73bcbfb2a2dd", + "75df6c20efbaab098480e08f49afa5be" + ], + [ + "d8c36d7d2d813f50b845f19026a681b8", + "b24d59b71550fdb45567a5247817c622", + "6e0f6da6eeb61868ce4247708e8c7316" + ] + ], + "prep_messages": [ + "25034fec369564c831e89105a21ed2c7" + ], + "prep_shares": [ + [ + "fedaa3d68353f75a2db6a1e49b2397a29e8bb52fe68533a6e7518d7c431765b09d9fb09303205bd20b7bad45f8ee66e18d4ff77adffd7c0b1990ba9c1c18c0d83c70aab9194ab6e494736b7521bff256e44fb48a11052214545c4fc23b0424f8965526d4d9d8d65bb919f8e823db52d0cd97bbb67e45ed5ae83205b3c379c8b72f4220e4407e1f46c60ea678ed8d47742d82abe8cc8b00055cbeb2bf9c5cf03ee851b53b57812560f8c16902a3ca3e54d95174e928fcb415d903ba75e20b5c824ad2d32f70d2375df7fd78e3a9da48d881c81e5a3126d013776adc18fa8ffbfa1ad84cc857cabdf17c81c8f08d04e9dcf11e92808e461939e811b768e5fd98c3186d21176ab71c0fd31e38c5ce590cae", + "cb8307fb467bb023448e58c74d159bf447187a131bca6a8f66f613129c42c481051853dd2151e2cc480d5164567c8c4164b4ac35f70fe6b64517e65804ca767a12d4839078fa72b1e64e8531f3e54c09efe5a1f7aca60dd9e174711c82596e04211848dd2c787bd764b2099de3139df35aacfef634fc7a8fd7d4cb8f68a8c4eab19f2941d9f4660018a051ede752680abcbc6d60afb6984df051b2a1940016a2abe594acb8e9611a81294b8ed708fa932e03ad037523630eff76925e1a8076900b98b57a0d21fda8ff765c0394041a9ac56ec6717034855e757728c6617c78e28f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449", + "39a1542e3531588156bb055416c7cd6884463d0b107893ff1174455e3c438265c0746eb13013792fcc318698a96b1343f33bbecee2d08efabd7facd829d80dafe9e844395897d8d5f475d4644149864c3faef9fbd6b690a3750c76e3721c6667ae67d137adc6f38ec943c596b6fec17750073dadaecc860ca8ce32846d68208c3f9b5c6e59d9736159ede439854b05328ab3d8b398c8d0d7401a8718d9aad830978eab94b6bf4105729f7da8eddcee386ddf59f7d19da2437c7656a1f3d873c2500371d0434c5e6511da60302f9947e8c857cee7aa680bb0dd711dfda75fe0a0cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb" + ] + ], + "public_share": "186d21176ab71c0fd31e38c5ce590cae89a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + }, + { + "input_shares": [ + "5d82bd1f81516122465f8a60a3209afef6a5c181fdfd80d20d280edb0ae8ccc4953eff5c0efe473d411cf4f3b2e3fd320c83c6b8f2c626a42d25f89594365561966e130ecf8a778e42ce7cca37b919eb9404560ba6a60a5e5b523f5ad397b378eeff4b21af66fba2f59db74e46ffdfa077bcea50472d6e771640a71fa31dd96445a2d8ce308904ea0d94760e7f8721d1531754521de6b338a20bdc8eda1d1acb6f3407a9f6f9d6cf9ccc3696c4d3226e8acf3207643a12d8c30332a8d364c97aafe81f4dc31ad62d49506e422e146492bd92a5cc933532fbfc1ee2e8e33116414358edd4baf633cdd80856f8132124171d9a2d989d3a9cf5d1d2b27baf94a5c524cf7ae624b8fe1c8ffc2229bbeecfc18f91c8683df7c579390d8b31ca87372cb6ebbe716d0edc0fe8f10c54835396a68dbacc670eee07dffa3203f8b202dc414dcb317950b35d8f4da3f0bafe8f4b0d09b5103494ed9cf9075bfd19c47f8bdee707eccea1987b4bf6ba603e29043ef636b1b327e57adf1b29b098d4eadfebb736a5ea3558794f02b97f3611034adf002518d85e769210bb2ed2e4b4390433c55c6140ffda97a5018ee007adf5125f079aebdb6eba6c35d0504d8b7a9cbbf0bd9c57bd5b563fdc052a492a7dad4a3c782b69b711ac2969758cffc3d9089a34716517c45fbb164a6bd15a001d454dfd444becef4c4a7fdbc1aaf3b7e0983b900221674a726db2b1b155190cec29c6afefe4841924dd7b212437fb10bffc8a17cea19a97ec2dfafe897e8ad4c5418946525d0908ac8790580a47a17a8089e7b78498f2a54375778e387b0985293431e2104051600211e6e9a3f388e53d2df072d487d4c4838d8d8601fad2bd86d51ad3a58aebc0d8f6bac048d77968b26826cf545c44f7513667ac696564df8113529415a6e467d3a9f6bda8630717be753a45b5d788bbc4b95712f3bec044eb26db66f23961bf870cfb30347361e81a451f7f17652f6cbd902e92cc063b7cd4cdffbec78cb3f1957d650f89be7798894f6594ae1a65964b5968c67003b247c0e83d3cef1ba2feef4c5c59d42a3efa8309f0ec4e9497b1c5a7c6b72f341d4ce5950bd12be5b6b22f32eade71f969f4ee1c0a864741fb2b5b1ad278c5f2f27000e4237b71cc664a87c50a7088b36bab5ad5a5494d599407fda9df6c538ad53563c222d3242b635116f5246b9dd6b7aba1f5abda8fd607ba18a3155c6e6c877ba0965f4005c8f475e5116bd7f899ba48ad299e5007401e49b85abf0ad681cbad302393975d682f6fb5a0795702ada0cf559198efff5ed8a16b12d1e866545db67d13ea5b7e59557776d458f5872d20ab0a3f6c74d61345bb6cd1f2dec5ee4a8d1c96d22a7b3c8ef21c1284d0785a56143100639cbfc3289478e516bd187dc85011217df3d9cc14a8f70c84bbd98d3a48ee1708913c3bd3c479700f0d9a01bc20a88c2c74202d08300dd1b74ec473f59b9f837fa6643b9a7627923e328512a0d1eaaef78c6fdb44f2789df4d6fea8cd33877405fbb744d075db8e2ea1c6363e0cb892ee5f90eb79ad90eb5593ce456db34e977dbb19ceba123f684af758e4bf0d03e1c085d6d425f0fd60afacc5baab06737d4cad9c375e0928789836c34150e196aca25fe1f4092243bdf49bb57f5dab084241ba1557429036f1660bb41b101fe37f03fce0595620833807d9b175ca2db5cc2df167cc1df780e3a73ecbbfcb4950440fb6c0606162636465666768696a6b6c6d6e6f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + ], + "measurement": [ + 15986, + 24671, + 23910 + ], + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "84d8e77978e4e319838804b62d66c7d1", + "adcfd0a1213e3921caece61ec83597ff", + "846e2639228e3b8e913cd8ff27c4e62a" + ], + [ + "18a2aa085a9adc958c310ab9abf3b675", + "0243d6a6c871c929a8ab73bcbfb2a2dd", + "75df6c20efbaab098480e08f49afa5be" + ], + [ + "d8c36d7d2d813f50b845f19026a681b8", + "b24d59b71550fdb45567a5247817c622", + "6e0f6da6eeb61868ce4247708e8c7316" + ] + ], + "prep_messages": [ + "164bb9a531ed86890f679cfee8e40bd7" + ], + "prep_shares": [ + [ + "fedaa3d68353f75a2db6a1e49b2397a2d951596ce321ca830642b1c9a71f119b750393c6c754d535696c304ff488bcc6977ced640b7644d68067fa674f608e0a5751aaca2e39d7e4f47bec846689f311124c532053e2285de1dd28c7430d205d7bef7f1ff5f36d363f8ca7cf16b9d28d7fe79342273ee2629adb1396910910d4f1243c6e17898c5de5b4e50915995e0ec6b2c92fd59cf001c32018e569d540e26a5512100c73b1dfb9e76c4865fb4c8a98d2382c1bd1bbef9cb6f8fee190a7b2c18bb9c694e107ede1966ba61589e8a1ee07c034878188043745d1a13e9d328c35ab0af3a25ad52a2941d5c87ef54e798f310d45c2a44eb9b8b484c4cf2cb11289979db009d84867e096271383f95f17", + "cb8307fb467bb023448e58c74d159bf49f9b010f8d3342eccac47f456395810c051853dd2151e2cc480d5164567c8c41b406b0bc3e39acaada3e1565084d70c512d4839078fa72b1e64e8531f3e54c09965aa5eacbdfd1c87023b5c2c1751952211848dd2c787bd764b2099de3139df3696d74860c683106e0ba03981fd175ceb19f2941d9f4660018a051ede752680a2e4d31fc97379acf03c3454eb29d0433abe594acb8e9611a81294b8ed708fa932cd4dc5aeb67e4082571e2c1a9e2e9370b98b57a0d21fda8ff765c0394041a9abc294b2171b29cdda805a50345b159548f623f5f376d80e762ee64ef3db152a4eaa42964a69f705f15eb77df0cf6f81589a8eaa4f01fe1b5aa656a0919ae5449", + "39a1542e3531588156bb055416c7cd68bc76b21ba7b0f0ee6be53024718f5ae0c0746eb13013792fcc318698a96b13435bf89e78f7ee3fd7e39a1fdab2ea808be9e844395897d8d5f475d4644149864c3768148cc4a96a193de9ea7fad3ee418ae67d137adc6f38ec943c596b6fec177dc960939e2aa0560144c058bc34cabcb3f9b5c6e59d9736159ede439854b053235b3543dd1ff08e9184d44c28b2e98c8978eab94b6bf4105729f7da8eddcee388df030cba4cd2df0eccbf799ad07d72e500371d0434c5e6511da60302f9947e8a9a78a25434f4d85ce460e1dc1446ea7cd909fe76206570074fca8dd8cc511ed104a88289bd3cd4d9e34a6c9a50a03649a431dd8df92d78dd6c0d478dd93c0cb" + ] + ], + "public_share": "89979db009d84867e096271383f95f1789a8eaa4f01fe1b5aa656a0919ae54499a431dd8df92d78dd6c0d478dd93c0cb", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + } + ], + "shares": 3, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json new file mode 100644 index 0000000000..040e3f1741 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_0.json @@ -0,0 +1,40 @@ +{ + "agg_param": null, + "agg_result": 100, + "agg_shares": [ + "f3d18d266d89cb425fd64a19a436e8bc", + "722e72d9927634bd8429b5e65bc91743" + ], + "bits": 8, + "prep": [ + { + "input_shares": [ + "6dc25550077a71c59f7020e3d0e7ac8da5809fa59c2a1c7da50f49f348a2dd8f46ac57b16cf3a153fb3aa17f19b651354b6e5e2666029f55a6e0d76f25269781bb4f7cf5e79ddd703d07a49094e878e48a68b2a4b901bceeb954375740d2385821e421c0d14a2246d80a4ef53b99eb6dac3738491e6a337c124d1bbdc0e1c752ee2e3b77c8f83cf734b152c7c93caab48127d1fcae79f5dc47d4e8f62463408f5c82435087d2a244e8b54a508f8474307003ff6d76327921cfc1b68e893f1eb8cbaf513ed61bbae3d3580c34c2dfae2ceb8a1120842f5db85c78c2f4225452a6f2b618972d56f013db62e73b92a8ec83107719d35a27f5cdc493d73a772c9f5c7bc67f4280e90dc1eadbe043546a8b5975976a00739136f5f4ab37b8d845f32db1c97a831b3a9d2d3bbec621146d5a5f8788d7e7a1958b2a9382c1d9f538b91d9582bab31f496c9ddc517ae206533a8b18e0b3854587379a3120970b0246aa13758de413cee5f99794170de0bbd7479bdf968c1db98d53b30bea4417d54c9cdcc5f5e71bd7367ad95aacfb02693f25bca1a5fd67cfb3ef6406607ecef3bbe052cab782eacce5d25f6589325d20a1d6f2d9beb14c3c89cb18d0042a5376907c057203feffcd8a36b24ecabc6fe4e0133ec68a1313b669c1771b91ffb86c284646ea5ad270c492b5d5d7a24b27655c2a715af2e797823fa97f87df42184add6f1cc26e9762159d43e9548a6a89da738a8a36159369e3aa7d3b2c25c8cf95b788bfd6293b9e66a42d3bde7b00a5822eb4f97347c91f9882d54a6279c22501ce4f3fa5ebca8fcbfd7baff84e687cb8d77b48e8b4026560d873e2b8c0529d02f3d4f1e5764e498cc9d22a5d64b50fb38edc42491e5f1571244bc6269a7fbbe64406b4303132333435363738393a3b3c3d3e3f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" + ], + "measurement": 100, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "f3d18d266d89cb425fd64a19a436e8bc" + ], + [ + "722e72d9927634bd8429b5e65bc91743" + ] + ], + "prep_messages": [ + "aac7d7306c0cdbbd7e23ef394322d54a" + ], + "prep_shares": [ + [ + "5e6f31522c0cb9b5107ad0c560b6ef9a69553124df856a84affd0a814674ea325a2f1c7fc62f1838a8d7aa8d4263ac0d86243c1f5c53992219ddfef99b94f76d", + "a390ceadd3f3464ad3852f3a9f49106571003e04a8d922570934a5812d4a8c45c1cf374cea16117767d4f4ee963acd756d42402e0f2b584af325b34eaa1615ad" + ] + ], + "public_share": "86243c1f5c53992219ddfef99b94f76d6d42402e0f2b584af325b34eaa1615ad", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + } + ], + "shares": 2, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json new file mode 100644 index 0000000000..8baf391f08 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/Prio3Sum_1.json @@ -0,0 +1,46 @@ +{ + "agg_param": null, + "agg_result": 100, + "agg_shares": [ + "f91bcafa315d7cfa26564999203babdc", + "722e72d9927634bd8429b5e65bc91743", + "fbb5c32b3b2c4f481c80018083fb3ce0" + ], + "bits": 8, + "prep": [ + { + "input_shares": [ + "a48f16f9472cb825154a980720bd436b62db8329758026ed40deaa18e9bccea80cc0d2e40164379e7498b61a280fa86e7080b53acd1baf84604c5270ba2e161b069c2f1187bbead120b10d073d3326c5da5edeca2a2e0322253face85a769c92155d2859b86caac4f2b25d8779b2a99de3af195b2be8a4e5923d2a566833f86a683fdd68189962ea14ca940bcae99c612ca93caf3ec9bfa9ca2bdc0adeb80dba90992e4ea878bd39e321fe43f0cc073d9b5a8f9ff7f38b333e907e510a04499dc78059a620bc2d7201e3c7a4545cb5066add82690fd25269e66e1cf4334211b5578dc556c377753a501da19da81e839e6f3b7f56724ad9ee5e6dbc0a1cdcd3fc36601586eca9a50a620ed1c8941379369ae3a72b13c11c76cbd1f69d5d5acca56da4d8567007cbba3da384aa2d73e1bfba7ff77864c3b508d5a5b69b69a0bc6c092fc84d564e8f9726686e13f32239912a8a0bd92a8849d81f30560618db3bbd7f8b14a68e8a4bb2f61db7fa471573a4bee095db799ff19407b22fd77ecd55206e85f36dabec6323d8aaea77e328a07e3ccbcb3c893f6522fd0aa39f09b79dd9167cb9bccc326e2aaf51cc0e187c46766ccbe75321deb403d470795926b6879f0398a996aa5330734a5f3fed8b0e69e3a2c8a4efcd739fbedda27ae086f7144e655cdc89b07183818b56ce01dddf691d2a57f846c77d8601b203a2caf8a9bb3ec4f340d68702bf320df74e304d2db24de0dd26a6346ccc9a65c6c24e45a31636efb0919a87c8b14c08226807807acb467c29481b03e541c3ad3b2512b89c794687f4dae6b4c5f7fef5b5c348e61cca26629f015fc7babc7e0261b477843df830057f7c69248b4493b2e7a9f5503ba3eee569fc9911b35d0dd6111e8985a42273606162636465666768696a6b6c6d6e6f", + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f", + "303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + ], + "measurement": 100, + "nonce": "000102030405060708090a0b0c0d0e0f", + "out_shares": [ + [ + "f91bcafa315d7cfa26564999203babdc" + ], + [ + "722e72d9927634bd8429b5e65bc91743" + ], + [ + "fbb5c32b3b2c4f481c80018083fb3ce0" + ] + ], + "prep_messages": [ + "215cd3acf2c12d42b2897cb57fb420a6" + ], + "prep_shares": [ + [ + "8a17e1ae7baf0fcb35b9d89394f8f34e5e965d98db9ffbe0867029fbbdfd7195d7fda8b597d471f0046bd4508be2e2abbf23e0b165f191b5165f0350ae251442", + "6c98be496224df8772c21173ad6fa2b271003e04a8d922570934a5812d4a8c45c1cf374cea16117767d4f4ee963acd756d42402e0f2b584af325b34eaa1615ad", + "0c506007222c11ad1f8415f9bd9769fe526f9e6835c5e2ce8c44b01f27cc5060c4c159a86eb48e1571437659eb32b3e8800a1a73b5ae07e45e4cc67555122b2d" + ] + ], + "public_share": "bf23e0b165f191b5165f0350ae2514426d42402e0f2b584af325b34eaa1615ad800a1a73b5ae07e45e4cc67555122b2d", + "rand": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + } + ], + "shares": 3, + "verify_key": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json b/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json new file mode 100644 index 0000000000..6a34d6e32e --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/XofFixedKeyAes128.json @@ -0,0 +1,8 @@ +{ + "binder": "62696e64657220737472696e67", + "derived_seed": "3805276060157b7376b069305303669b", + "dst": "646f6d61696e2073657061726174696f6e20746167", + "expanded_vec_field128": "3805276060157b7376b069305303669b92beaaa4afa982314428494ba98f3595d49e76d1301b451d6fd79c9acbe9118717cfd0d4b9ef29806b4dce298a2d6aba17d7025e7964a2d7e24a263bd79d19edb11cd1db4bc07ce0ae1a9c6d1f59233e8d7065a66ce1b123ed773e4b370c9217c7032fc805f3a13f6fe2ef6f7961bf9d20fd22b8cd544cefe8e634d9245db7813ba43f630a123dfda73b6bbad8b11a916090a7d5ba8a4d20853f3f5c8222684050a53119e829313fa8de64f92553a44aa522fc90d9ec75f80547ec9637ce60e74afd51baa1d80b549444c5f0a6283ff494698ea6ffaea65964c4e0c2f9cf72a11310000261ddc85661f5068f505d34273295be9b8549b4c6278a80794929093a17cc017cf0b0e68e32e941708cfa58b9e598ac3d5d2ab4e9b33111c9c9fbc0a3682617d0ed1a0d15c9bfb9d5fd2889d1f56dd3a7f2e61ca59b0705d35f915349ffea0341816532bbdaa6dddba42bf27d1699d9e9ef580f3686ea42d687e54a87c3e6dab4f1ee5e1185faa6b809eb1a1e940692b3ba882684e8440b73e23088411000cf77ba69777b3bfa417050f0cef6cd0c9b6e7a47ab5c3da9a0e3de6ec323aed32f4cc3f51ac719e34f0bd9b0cc617e3034581a708f4a3bba587b4b4cb91529cfd47393893c3b5cd430d0456a245b0c45d4398fe423b67faa8682c764d92c514d7e34a89abc16353e71de7d49895527e632a6163d7362549a8e9ab12277460d30d7892e0a5993a4d3922738f07892764b0ceabf280779894ced52aa7fba94100c2ec0fa1973d2b11044e6844ddcdbd59f26e1b321d02c9189414cace4abece30878ca21d198f2e61b84e7cbebb6a0ad83e2abd5bf69d7f8eed193a8e141088a4b7d41fe23a939f678ba94a1d9c9c2", + "length": 40, + "seed": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json b/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json new file mode 100644 index 0000000000..1e48d1f648 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/08/XofTurboShake128.json @@ -0,0 +1,8 @@ +{ + "binder": "62696e64657220737472696e67", + "derived_seed": "8bac064e720bb1c413040a3f41990075", + "dst": "646f6d61696e2073657061726174696f6e20746167", + "expanded_vec_field128": "8bac064e720bb1c413040a3f419900750ce08494b0f4f2d95171dcf44255ef94606fd5e6ffe3735329f5550e34fe61f0d4704239c107e4beb6623e20cb2e2659662aef8409fcc162a01d2333fc8d8ee7bc31c394c88edeb5904d25bf851d30246d9bf4221a5aec6ff4cb2580dde88dfa726e21b35da18f5b1839a257482ab292615b094b092444013874fce11cbd293fc81fd9a00d1befca7b1aefa2324ad2c84a8d678b02973bd539021e18861647474211e99ccfff5e47483985b25257f83665f44ed3fbce4f5a2b20e5c54239653141f7d5132b255936d33327789e13b145362059f67bd8d5b240dfd1e525d6ac5c0bb6a5b4a0b7b7318a5e22fc91763d2eb9dbd5fd3a3665127ffa63ac5be71a0b67a5ce5ee158d902a4e3a4c580e734ee40682e471373b958853eddee1de30dda6e6f4a3e3a297a79bd7f332ce89b8f0cd50589f03b95408405df362a41f58688e1fb818deaccf36eedbabc1762215102de02125dc79450d47dc04ba88cd507bdf1690ae6c1dbb44352c29687e3f60e0d3d9ed8758aa1495f4976477bda7e3cdbf37078f615dfde8330df46aebe393a665fa3f9b906498ef59ac5a0da50ebeb91c80ac0d8ba3d9bcb4e23f37e416dbe679d633834b8351085a321314d8b0276b24de1dc41091f9bdf765f2879ef0d624927a649bb693386b5a22af2ec5b67b8298abadf1e4ffa10a794ebb9924761d08ad75b595ef11118b33a8f5e649e0b8351600be077a164c806a7ee2aba58de06177ccd18e8822d35c2d6843378f254d64e5a1ee52d9c5b3f63ae262c3d6d5b63baf4e2faf436d51d6318ac9d05cf4fe3e203b2b047bdb1b4f4f8d5645a5d59ab506afc423f3a0ae5691e7f755dc5bff3b6b4f08c61614b62f63b03ce30d35a2c0d", + "length": 40, + "seed": "000102030405060708090a0b0c0d0e0f" +} diff --git a/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json b/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json new file mode 100644 index 0000000000..510cc539e1 --- /dev/null +++ b/third_party/rust/prio/src/vdaf/test_vec/XofHmacSha256Aes128.json @@ -0,0 +1,8 @@ +{ + "binder": "62696e64657220737472696e67", + "derived_seed": "e826c9564c620fb63357fbee88dc9bb3de2c41764adb44bea344024e1da124c6", + "dst": "646f6d61696e2073657061726174696f6e20746167", + "expanded_vec_field128": "e826c9564c620fb63357fbee88dc9bb3de2c41764adb44bea344024e1da124c6172f208e79762fed92c73cea422b312860008ee80e30f31d2d87840890604f39db37983f5c3483407333cecdb1b9ea550c26bc4f2d999fda91963054c6cb35a8ad8d28ee74a48e28aa475d67124e7c4417149955e506690d62e17f0730b7d4db8a9754f80603b7720205819d26bcfe4a4663d05c98c12705ea7dc333d5746d9c8ba697bb3d5be95d26ccb73052cb8fb19edfc35eaebaa22779436d3015512c9b536003d98b04a0f46feddbff762007c377c28a04039f72657650885bd40ed37acea63facd3c33d1ecb5048641053af5b4018b0c373d9ed7440da9fc6c76666c2eb8ed2943a64bbf6dae93ac91fcc26d7225c2ae42349161522fcce0b92d209411af8566b0adbaa36a8479737017efd2c359ea43924cdf432650dcd742e358af55ff6c321d0ebaae2abf5812d58b060cc147395e8137f99db58d2c425f2704da067df3a41c0443918375c177fa53545d8190d828c6045bbe5930e4762588ea14dc0a9db6cd903216ccae968ca0b11f0ac04e4dfc69a99986841dc99c851e314c7d4b10f4ef72e1244b543465fed076a7e9f50baca4ad7dccc73bfc55310f2ae6eaeaf7ee7a4d41fec76bff3b04e67d1f83e4da59f1fcb45877adfc3e4a2b1d5e3f136131ca2a02f34bdba1c5d2dafb2178674dc002d247662497b7f5818880cff308e5222e6df0bcdf6f68ebfaa8d0551530fa00ec29646441961e33b50872ada911591e16e3021baa5e7869756d3d812a63e3c7fa2c0ec2dc4cabe11c0256829b360ad9431536ab96efbe5a364cd1c323de8fbe405a2c87b9c58e5740bfb118af0ca1a23afb4a04e9cec3b9d1e57834cbc0fa17d5d7285f1f013df05e92a7343", + "length": 40, + "seed": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" +} diff --git a/third_party/rust/prio/src/vdaf/xof.rs b/third_party/rust/prio/src/vdaf/xof.rs index b38d176467..67881419df 100644 --- a/third_party/rust/prio/src/vdaf/xof.rs +++ b/third_party/rust/prio/src/vdaf/xof.rs @@ -1,8 +1,14 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-07]]. +//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ + +/// Value of the domain separation byte "D" used by XofTurboShake128 when invoking TurboSHAKE128. +const XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION: u8 = 1; +/// Value of the domain separation byte "D" used by XofFixedKeyAes128 when invoking TurboSHAKE128. +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +const XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION: u8 = 2; use crate::{ field::FieldElement, @@ -21,13 +27,17 @@ use aes::{ }; #[cfg(feature = "crypto-dependencies")] use ctr::Ctr64BE; +#[cfg(feature = "crypto-dependencies")] +use hmac::{Hmac, Mac}; use rand_core::{ impls::{next_u32_via_fill, next_u64_via_fill}, RngCore, SeedableRng, }; +#[cfg(feature = "crypto-dependencies")] +use sha2::Sha256; use sha3::{ digest::{ExtendableOutput, Update, XofReader}, - Shake128, Shake128Core, Shake128Reader, + TurboShake128, TurboShake128Core, TurboShake128Reader, }; #[cfg(feature = "crypto-dependencies")] use std::fmt::Formatter; @@ -76,8 +86,9 @@ impl<const SEED_SIZE: usize> ConstantTimeEq for Seed<SEED_SIZE> { } impl<const SEED_SIZE: usize> Encode for Seed<SEED_SIZE> { - fn encode(&self, bytes: &mut Vec<u8>) { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { bytes.extend_from_slice(&self.0[..]); + Ok(()) } fn encoded_len(&self) -> Option<usize> { @@ -105,9 +116,9 @@ impl<S: RngCore> IntoFieldVec for S { } } -/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-07]]. +/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-08]]. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ pub trait Xof<const SEED_SIZE: usize>: Clone + Debug { /// The type of stream produced by this XOF. type SeedStream: RngCore + Sized; @@ -145,7 +156,9 @@ pub struct SeedStreamAes128(Ctr64BE<Aes128>); #[cfg(feature = "crypto-dependencies")] impl SeedStreamAes128 { - pub(crate) fn new(key: &[u8], iv: &[u8]) -> Self { + /// Construct an instance of the seed stream with the given AES key `key` and initialization + /// vector `iv`. + pub fn new(key: &[u8], iv: &[u8]) -> Self { SeedStreamAes128(<Ctr64BE<Aes128> as KeyIvInit>::new(key.into(), iv.into())) } @@ -187,17 +200,19 @@ impl Debug for SeedStreamAes128 { } } -/// The XOF based on SHA-3 as specified in [[draft-irtf-cfrg-vdaf-07]]. +/// The XOF based on TurboSHAKE128 as specified in [[draft-irtf-cfrg-vdaf-08]]. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[derive(Clone, Debug)] -pub struct XofShake128(Shake128); +pub struct XofTurboShake128(TurboShake128); -impl Xof<16> for XofShake128 { - type SeedStream = SeedStreamSha3; +impl Xof<16> for XofTurboShake128 { + type SeedStream = SeedStreamTurboShake128; fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self { - let mut xof = Self(Shake128::from_core(Shake128Core::default())); + let mut xof = Self(TurboShake128::from_core(TurboShake128Core::new( + XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION, + ))); Update::update( &mut xof.0, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -211,21 +226,21 @@ impl Xof<16> for XofShake128 { Update::update(&mut self.0, data); } - fn into_seed_stream(self) -> SeedStreamSha3 { - SeedStreamSha3::new(self.0.finalize_xof()) + fn into_seed_stream(self) -> SeedStreamTurboShake128 { + SeedStreamTurboShake128::new(self.0.finalize_xof()) } } -/// The seed stream produced by SHAKE128. -pub struct SeedStreamSha3(Shake128Reader); +/// The seed stream produced by TurboSHAKE128. +pub struct SeedStreamTurboShake128(TurboShake128Reader); -impl SeedStreamSha3 { - pub(crate) fn new(reader: Shake128Reader) -> Self { +impl SeedStreamTurboShake128 { + pub(crate) fn new(reader: TurboShake128Reader) -> Self { Self(reader) } } -impl RngCore for SeedStreamSha3 { +impl RngCore for SeedStreamTurboShake128 { fn fill_bytes(&mut self, dest: &mut [u8]) { XofReader::read(&mut self.0, dest); } @@ -244,13 +259,13 @@ impl RngCore for SeedStreamSha3 { } } -/// A `rand`-compatible interface to construct XofShake128 seed streams, with the domain separation tag -/// and binder string both fixed as the empty string. -impl SeedableRng for SeedStreamSha3 { +/// A `rand`-compatible interface to construct XofTurboShake128 seed streams, with the domain +/// separation tag and binder string both fixed as the empty string. +impl SeedableRng for SeedStreamTurboShake128 { type Seed = [u8; 16]; fn from_seed(seed: Self::Seed) -> Self { - XofShake128::init(&seed, b"").into_seed_stream() + XofTurboShake128::init(&seed, b"").into_seed_stream() } } @@ -269,7 +284,9 @@ pub struct XofFixedKeyAes128Key { impl XofFixedKeyAes128Key { /// Derive the fixed key from the domain separation tag and binder string. pub fn new(dst: &[u8], binder: &[u8]) -> Self { - let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default()); + let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new( + XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION, + )); Update::update( &mut fixed_key_deriver, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -293,15 +310,15 @@ impl XofFixedKeyAes128Key { } } -/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-07]]. This XOF is NOT RECOMMENDED for +/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-08]]. This XOF is NOT RECOMMENDED for /// general use; see Section 9 ("Security Considerations") for details. /// -/// This XOF combines SHA-3 and a fixed-key mode of operation for AES-128. The key is "fixed" in -/// the sense that it is derived (using SHAKE128) from the domain separation tag and binder -/// strings, and depending on the application, these strings can be hard-coded. The seed is used to -/// construct each block of input passed to a hash function built from AES-128. +/// This XOF combines TurboSHAKE128 and a fixed-key mode of operation for AES-128. The key is +/// "fixed" in the sense that it is derived (using TurboSHAKE128) from the domain separation tag and +/// binder strings, and depending on the application, these strings can be hard-coded. The seed is +/// used to construct each block of input passed to a hash function built from AES-128. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[derive(Clone, Debug)] #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[cfg_attr( @@ -309,7 +326,7 @@ impl XofFixedKeyAes128Key { doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) )] pub struct XofFixedKeyAes128 { - fixed_key_deriver: Shake128, + fixed_key_deriver: TurboShake128, base_block: Block, } @@ -318,7 +335,7 @@ impl Xof<16> for XofFixedKeyAes128 { type SeedStream = SeedStreamFixedKeyAes128; fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self { - let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default()); + let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new(2u8)); Update::update( &mut fixed_key_deriver, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -433,6 +450,37 @@ impl RngCore for SeedStreamFixedKeyAes128 { } } +/// XOF based on HMAC-SHA256 and AES128. This XOF is not part of the VDAF spec. +#[cfg(feature = "crypto-dependencies")] +#[cfg_attr(docsrs, doc(cfg(feature = "crypto-dependencies")))] +#[derive(Clone, Debug)] +pub struct XofHmacSha256Aes128(Hmac<Sha256>); + +#[cfg(feature = "crypto-dependencies")] +impl Xof<32> for XofHmacSha256Aes128 { + type SeedStream = SeedStreamAes128; + + fn init(seed_bytes: &[u8; 32], dst: &[u8]) -> Self { + let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(seed_bytes).unwrap(); + Mac::update( + &mut mac, + &[dst.len().try_into().expect("dst must be at most 255 bytes")], + ); + Mac::update(&mut mac, dst); + Self(mac) + } + + fn update(&mut self, data: &[u8]) { + Mac::update(&mut self.0, data); + } + + fn into_seed_stream(self) -> SeedStreamAes128 { + let tag = Mac::finalize(self.0).into_bytes(); + let (key, iv) = tag.split_at(16); + SeedStreamAes128::new(key, iv) + } +} + #[cfg(test)] mod tests { use super::*; @@ -480,10 +528,34 @@ mod tests { } #[test] - fn xof_shake128() { + fn xof_turboshake128() { let t: XofTestVector = - serde_json::from_str(include_str!("test_vec/07/XofShake128.json")).unwrap(); - let mut xof = XofShake128::init(&t.seed.try_into().unwrap(), &t.dst); + serde_json::from_str(include_str!("test_vec/08/XofTurboShake128.json")).unwrap(); + let mut xof = XofTurboShake128::init(&t.seed.try_into().unwrap(), &t.dst); + xof.update(&t.binder); + + assert_eq!( + xof.clone().into_seed(), + Seed(t.derived_seed.try_into().unwrap()) + ); + + let mut bytes = Cursor::new(t.expanded_vec_field128.as_slice()); + let mut want = Vec::with_capacity(t.length); + while (bytes.position() as usize) < t.expanded_vec_field128.len() { + want.push(Field128::decode(&mut bytes).unwrap()) + } + let got: Vec<Field128> = xof.clone().into_seed_stream().into_field_vec(t.length); + assert_eq!(got, want); + + test_xof::<XofTurboShake128, 16>(); + } + + #[test] + fn xof_hmac_sha256_aes128() { + let t: XofTestVector = + serde_json::from_str(include_str!("test_vec/XofHmacSha256Aes128.json")).unwrap(); + + let mut xof = XofHmacSha256Aes128::init(&t.seed.try_into().unwrap(), &t.dst); xof.update(&t.binder); assert_eq!( @@ -499,14 +571,14 @@ mod tests { let got: Vec<Field128> = xof.clone().into_seed_stream().into_field_vec(t.length); assert_eq!(got, want); - test_xof::<XofShake128, 16>(); + test_xof::<XofHmacSha256Aes128, 32>(); } #[cfg(feature = "experimental")] #[test] fn xof_fixed_key_aes128() { let t: XofTestVector = - serde_json::from_str(include_str!("test_vec/07/XofFixedKeyAes128.json")).unwrap(); + serde_json::from_str(include_str!("test_vec/08/XofFixedKeyAes128.json")).unwrap(); let mut xof = XofFixedKeyAes128::init(&t.seed.try_into().unwrap(), &t.dst); xof.update(&t.binder); diff --git a/third_party/rust/prio/src/vidpf.rs b/third_party/rust/prio/src/vidpf.rs new file mode 100644 index 0000000000..c8ba5db22c --- /dev/null +++ b/third_party/rust/prio/src/vidpf.rs @@ -0,0 +1,827 @@ +// SPDX-License-Identifier: MPL-2.0 + +//! Verifiable Incremental Distributed Point Function (VIDPF). +//! +//! The VIDPF construction is specified in [[draft-mouris-cfrg-mastic]] and builds +//! on techniques from [[MST23]] and [[CP22]] to lift an IDPF to a VIDPF. +//! +//! [CP22]: https://eprint.iacr.org/2021/580 +//! [MST23]: https://eprint.iacr.org/2023/080 +//! [draft-mouris-cfrg-mastic]: https://datatracker.ietf.org/doc/draft-mouris-cfrg-mastic/02/ + +use core::{ + iter::zip, + ops::{Add, AddAssign, BitXor, BitXorAssign, Index, Sub}, +}; + +use bitvec::field::BitField; +use rand_core::RngCore; +use std::io::Cursor; +use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable}; + +use crate::{ + codec::{CodecError, Encode, ParameterizedDecode}, + field::FieldElement, + idpf::{ + conditional_select_seed, conditional_swap_seed, conditional_xor_seeds, xor_seeds, + IdpfInput, IdpfValue, + }, + vdaf::xof::{Seed, Xof, XofFixedKeyAes128, XofTurboShake128}, +}; + +/// VIDPF-related errors. +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum VidpfError { + /// Error when key's identifier are equal. + #[error("key's identifier should be different")] + SameKeyId, + + /// Error when level does not fit in a 32-bit number. + #[error("level is not representable as a 32-bit integer")] + LevelTooBig, + + /// Error during VIDPF evaluation: tried to access a level index out of bounds. + #[error("level index out of bounds")] + IndexLevel, + + /// Error when weight's length mismatches the length in weight's parameter. + #[error("invalid weight length")] + InvalidWeightLength, + + /// Failure when calling getrandom(). + #[error("getrandom: {0}")] + GetRandom(#[from] getrandom::Error), +} + +/// Represents the domain of an incremental point function. +pub type VidpfInput = IdpfInput; + +/// Represents the codomain of an incremental point function. +pub trait VidpfValue: IdpfValue + Clone {} + +/// A VIDPF instance. +pub struct Vidpf<W: VidpfValue, const NONCE_SIZE: usize> { + /// Any parameters required to instantiate a weight value. + weight_parameter: W::ValueParameter, +} + +impl<W: VidpfValue, const NONCE_SIZE: usize> Vidpf<W, NONCE_SIZE> { + /// Creates a VIDPF instance. + /// + /// # Arguments + /// + /// * `weight_parameter`, any parameters required to instantiate a weight value. + pub const fn new(weight_parameter: W::ValueParameter) -> Self { + Self { weight_parameter } + } + + /// The [`Vidpf::gen`] method splits an incremental point function `F` into two private keys + /// used by the aggregation servers, and a common public share. + /// + /// The incremental point function is defined as `F`: [`VidpfInput`] --> [`VidpfValue`] + /// such that: + /// + /// ```txt + /// F(x) = weight, if x is a prefix of the input. + /// F(x) = 0, if x is not a prefix of the input. + /// ``` + /// + /// # Arguments + /// + /// * `input`, determines the input of the function. + /// * `weight`, determines the input's weight of the function. + /// * `nonce`, used to cryptographically bind some information. + pub fn gen( + &self, + input: &VidpfInput, + weight: &W, + nonce: &[u8; NONCE_SIZE], + ) -> Result<(VidpfPublicShare<W>, [VidpfKey; 2]), VidpfError> { + let keys = [ + VidpfKey::gen(VidpfServerId::S0)?, + VidpfKey::gen(VidpfServerId::S1)?, + ]; + let public = self.gen_with_keys(&keys, input, weight, nonce)?; + Ok((public, keys)) + } + + /// [`Vidpf::gen_with_keys`] works as the [`Vidpf::gen`] method, except that two different + /// keys must be provided. + fn gen_with_keys( + &self, + keys: &[VidpfKey; 2], + input: &VidpfInput, + weight: &W, + nonce: &[u8; NONCE_SIZE], + ) -> Result<VidpfPublicShare<W>, VidpfError> { + if keys[0].id == keys[1].id { + return Err(VidpfError::SameKeyId); + } + + let mut s_i = [keys[0].value, keys[1].value]; + let mut t_i = [Choice::from(keys[0].id), Choice::from(keys[1].id)]; + + let n = input.len(); + let mut cw = Vec::with_capacity(n); + let mut cs = Vec::with_capacity(n); + + for level in 0..n { + let alpha_i = Choice::from(u8::from(input.get(level).ok_or(VidpfError::IndexLevel)?)); + + // If alpha_i == 0 then + // (same_seed, diff_seed) = (right_seed, left_seed) + // else + // (same_seed, diff_seed) = (left_seed, right_seed) + let seq_0 = Self::prg(&s_i[0], nonce); + let (same_seed_0, diff_seed_0) = &mut (seq_0.right_seed, seq_0.left_seed); + conditional_swap_seed(same_seed_0, diff_seed_0, alpha_i); + + let seq_1 = Self::prg(&s_i[1], nonce); + let (same_seed_1, diff_seed_1) = &mut (seq_1.right_seed, seq_1.left_seed); + conditional_swap_seed(same_seed_1, diff_seed_1, alpha_i); + + // If alpha_i == 0 then + // diff_control_bit = left_control_bit + // else + // diff_control_bit = right_control_bit + let diff_control_bit_0 = Choice::conditional_select( + &seq_0.left_control_bit, + &seq_0.right_control_bit, + alpha_i, + ); + let diff_control_bit_1 = Choice::conditional_select( + &seq_1.left_control_bit, + &seq_1.right_control_bit, + alpha_i, + ); + + let s_cw = xor_seeds(same_seed_0, same_seed_1); + let t_cw_l = + seq_0.left_control_bit ^ seq_1.left_control_bit ^ alpha_i ^ Choice::from(1); + let t_cw_r = seq_0.right_control_bit ^ seq_1.right_control_bit ^ alpha_i; + let t_cw_diff = Choice::conditional_select(&t_cw_l, &t_cw_r, alpha_i); + + let s_tilde_i_0 = conditional_xor_seeds(diff_seed_0, &s_cw, t_i[0]); + let s_tilde_i_1 = conditional_xor_seeds(diff_seed_1, &s_cw, t_i[1]); + + t_i[0] = diff_control_bit_0 ^ (t_i[0] & t_cw_diff); + t_i[1] = diff_control_bit_1 ^ (t_i[1] & t_cw_diff); + + let w_i_0; + let w_i_1; + (s_i[0], w_i_0) = self.convert(s_tilde_i_0, nonce); + (s_i[1], w_i_1) = self.convert(s_tilde_i_1, nonce); + + let mut w_cw = w_i_1 - w_i_0 + weight.clone(); + w_cw.conditional_negate(t_i[1]); + + let cw_i = VidpfCorrectionWord { + seed: s_cw, + left_control_bit: t_cw_l, + right_control_bit: t_cw_r, + weight: w_cw, + }; + cw.push(cw_i); + + let pi_tilde_0 = Self::node_proof(input, level, &s_i[0])?; + let pi_tilde_1 = Self::node_proof(input, level, &s_i[1])?; + let cs_i = xor_proof(pi_tilde_0, &pi_tilde_1); + cs.push(cs_i); + } + + Ok(VidpfPublicShare { cw, cs }) + } + + /// [`Vidpf::eval`] evaluates the entire `input` and produces a share of the + /// input's weight. + pub fn eval( + &self, + key: &VidpfKey, + public: &VidpfPublicShare<W>, + input: &VidpfInput, + nonce: &[u8; NONCE_SIZE], + ) -> Result<VidpfValueShare<W>, VidpfError> { + let mut state = VidpfEvalState::init_from_key(key); + let mut share = W::zero(&self.weight_parameter); + + let n = input.len(); + for level in 0..n { + (state, share) = self.eval_next(key.id, public, input, level, &state, nonce)?; + } + + Ok(VidpfValueShare { + share, + proof: state.proof, + }) + } + + /// [`Vidpf::eval_next`] evaluates the `input` at the given level using the provided initial + /// state, and returns a new state and a share of the input's weight at that level. + fn eval_next( + &self, + id: VidpfServerId, + public: &VidpfPublicShare<W>, + input: &VidpfInput, + level: usize, + state: &VidpfEvalState, + nonce: &[u8; NONCE_SIZE], + ) -> Result<(VidpfEvalState, W), VidpfError> { + let cw = public.cw.get(level).ok_or(VidpfError::IndexLevel)?; + + let seq_tilde = Self::prg(&state.seed, nonce); + + let t_i = state.control_bit; + let sl = conditional_xor_seeds(&seq_tilde.left_seed, &cw.seed, t_i); + let sr = conditional_xor_seeds(&seq_tilde.right_seed, &cw.seed, t_i); + let tl = seq_tilde.left_control_bit ^ (t_i & cw.left_control_bit); + let tr = seq_tilde.right_control_bit ^ (t_i & cw.right_control_bit); + + let x_i = Choice::from(u8::from(input.get(level).ok_or(VidpfError::IndexLevel)?)); + let s_tilde_i = conditional_select_seed(x_i, &[sl, sr]); + + let next_control_bit = Choice::conditional_select(&tl, &tr, x_i); + let (next_seed, w_i) = self.convert(s_tilde_i, nonce); + + let zero = <W as IdpfValue>::zero(&self.weight_parameter); + let mut y = <W as IdpfValue>::conditional_select(&zero, &cw.weight, next_control_bit); + y += w_i; + y.conditional_negate(Choice::from(id)); + + let pi_i = &state.proof; + let cs_i = public.cs.get(level).ok_or(VidpfError::IndexLevel)?; + let pi_tilde = Self::node_proof(input, level, &next_seed)?; + let h2_input = xor_proof( + conditional_xor_proof(pi_tilde, cs_i, next_control_bit), + pi_i, + ); + let next_proof = xor_proof(Self::node_proof_adjustment(h2_input), pi_i); + + let next_state = VidpfEvalState { + seed: next_seed, + control_bit: next_control_bit, + proof: next_proof, + }; + + Ok((next_state, y)) + } + + fn prg(seed: &VidpfSeed, nonce: &[u8]) -> VidpfPrgOutput { + let mut rng = XofFixedKeyAes128::seed_stream(&Seed(*seed), VidpfDomainSepTag::PRG, nonce); + + let mut left_seed = VidpfSeed::default(); + let mut right_seed = VidpfSeed::default(); + rng.fill_bytes(&mut left_seed); + rng.fill_bytes(&mut right_seed); + // Use the LSB of seeds as control bits, and clears the bit, + // i.e., seeds produced by `prg` always have their LSB = 0. + // This ensures `prg` costs two AES calls only. + let left_control_bit = Choice::from(left_seed[0] & 0x01); + let right_control_bit = Choice::from(right_seed[0] & 0x01); + left_seed[0] &= 0xFE; + right_seed[0] &= 0xFE; + + VidpfPrgOutput { + left_seed, + left_control_bit, + right_seed, + right_control_bit, + } + } + + fn convert(&self, seed: VidpfSeed, nonce: &[u8; NONCE_SIZE]) -> (VidpfSeed, W) { + let mut rng = + XofFixedKeyAes128::seed_stream(&Seed(seed), VidpfDomainSepTag::CONVERT, nonce); + + let mut out_seed = VidpfSeed::default(); + rng.fill_bytes(&mut out_seed); + let value = <W as IdpfValue>::generate(&mut rng, &self.weight_parameter); + + (out_seed, value) + } + + fn node_proof( + input: &VidpfInput, + level: usize, + seed: &VidpfSeed, + ) -> Result<VidpfProof, VidpfError> { + let mut shake = XofTurboShake128::init(seed, VidpfDomainSepTag::NODE_PROOF); + for chunk128 in input + .index(..=level) + .chunks(128) + .map(BitField::load_le::<u128>) + .map(u128::to_le_bytes) + { + shake.update(&chunk128); + } + shake.update( + &u16::try_from(level) + .map_err(|_e| VidpfError::LevelTooBig)? + .to_le_bytes(), + ); + let mut rng = shake.into_seed_stream(); + + let mut proof = VidpfProof::default(); + rng.fill_bytes(&mut proof); + + Ok(proof) + } + + fn node_proof_adjustment(mut proof: VidpfProof) -> VidpfProof { + let mut rng = XofTurboShake128::seed_stream( + &Seed(Default::default()), + VidpfDomainSepTag::NODE_PROOF_ADJUST, + &proof, + ); + rng.fill_bytes(&mut proof); + + proof + } +} + +/// Contains the domain separation tags for invoking different oracles. +struct VidpfDomainSepTag; +impl VidpfDomainSepTag { + const PRG: &'static [u8] = b"Prg"; + const CONVERT: &'static [u8] = b"Convert"; + const NODE_PROOF: &'static [u8] = b"NodeProof"; + const NODE_PROOF_ADJUST: &'static [u8] = b"NodeProofAdjust"; +} + +/// Private key of an aggregation server. +pub struct VidpfKey { + id: VidpfServerId, + value: [u8; 16], +} + +impl VidpfKey { + /// Generates a key at random. + /// + /// # Errors + /// Triggers an error if the random generator fails. + pub(crate) fn gen(id: VidpfServerId) -> Result<Self, VidpfError> { + let mut value = [0; 16]; + getrandom::getrandom(&mut value)?; + Ok(Self { id, value }) + } +} + +/// Identifies the two aggregation servers. +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) enum VidpfServerId { + /// S0 is the first server. + S0, + /// S1 is the second server. + S1, +} + +impl From<VidpfServerId> for Choice { + fn from(value: VidpfServerId) -> Self { + match value { + VidpfServerId::S0 => Self::from(0), + VidpfServerId::S1 => Self::from(1), + } + } +} + +/// Adjusts values of shares during the VIDPF evaluation. +#[derive(Debug)] +struct VidpfCorrectionWord<W: VidpfValue> { + seed: VidpfSeed, + left_control_bit: Choice, + right_control_bit: Choice, + weight: W, +} + +/// Common public information used by aggregation servers. +#[derive(Debug)] +pub struct VidpfPublicShare<W: VidpfValue> { + cw: Vec<VidpfCorrectionWord<W>>, + cs: Vec<VidpfProof>, +} + +/// Contains the values produced during input evaluation at a given level. +pub struct VidpfEvalState { + seed: VidpfSeed, + control_bit: Choice, + proof: VidpfProof, +} + +impl VidpfEvalState { + fn init_from_key(key: &VidpfKey) -> Self { + Self { + seed: key.value, + control_bit: Choice::from(key.id), + proof: VidpfProof::default(), + } + } +} + +/// Contains a share of the input's weight together with a proof for verification. +pub struct VidpfValueShare<W: VidpfValue> { + /// Secret share of the input's weight. + pub share: W, + /// Proof used to verify the share. + pub proof: VidpfProof, +} + +/// Proof size in bytes. +const VIDPF_PROOF_SIZE: usize = 32; + +/// Allows to validate user input and shares after evaluation. +type VidpfProof = [u8; VIDPF_PROOF_SIZE]; + +fn xor_proof(mut lhs: VidpfProof, rhs: &VidpfProof) -> VidpfProof { + zip(&mut lhs, rhs).for_each(|(a, b)| a.bitxor_assign(b)); + lhs +} + +fn conditional_xor_proof(mut lhs: VidpfProof, rhs: &VidpfProof, choice: Choice) -> VidpfProof { + zip(&mut lhs, rhs).for_each(|(a, b)| a.conditional_assign(&a.bitxor(b), choice)); + lhs +} + +/// Feeds a pseudorandom generator during evaluation. +type VidpfSeed = [u8; 16]; + +/// Contains the seeds and control bits produced by [`Vidpf::prg`]. +struct VidpfPrgOutput { + left_seed: VidpfSeed, + left_control_bit: Choice, + right_seed: VidpfSeed, + right_control_bit: Choice, +} + +/// Represents an array of field elements that implements the [`VidpfValue`] trait. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct VidpfWeight<F: FieldElement>(Vec<F>); + +impl<F: FieldElement> From<Vec<F>> for VidpfWeight<F> { + fn from(value: Vec<F>) -> Self { + Self(value) + } +} + +impl<F: FieldElement> VidpfValue for VidpfWeight<F> {} + +impl<F: FieldElement> IdpfValue for VidpfWeight<F> { + /// The parameter determines the number of field elements in the vector. + type ValueParameter = usize; + + fn generate<S: RngCore>(seed_stream: &mut S, length: &Self::ValueParameter) -> Self { + Self( + (0..*length) + .map(|_| <F as IdpfValue>::generate(seed_stream, &())) + .collect(), + ) + } + + fn zero(length: &Self::ValueParameter) -> Self { + Self((0..*length).map(|_| <F as IdpfValue>::zero(&())).collect()) + } + + /// Panics if weight lengths are different. + fn conditional_select(lhs: &Self, rhs: &Self, choice: Choice) -> Self { + assert_eq!( + lhs.0.len(), + rhs.0.len(), + "{}", + VidpfError::InvalidWeightLength + ); + + Self( + zip(&lhs.0, &rhs.0) + .map(|(a, b)| <F as IdpfValue>::conditional_select(a, b, choice)) + .collect(), + ) + } +} + +impl<F: FieldElement> ConditionallyNegatable for VidpfWeight<F> { + fn conditional_negate(&mut self, choice: Choice) { + self.0.iter_mut().for_each(|a| a.conditional_negate(choice)); + } +} + +impl<F: FieldElement> Add for VidpfWeight<F> { + type Output = Self; + + /// Panics if weight lengths are different. + fn add(self, rhs: Self) -> Self::Output { + assert_eq!( + self.0.len(), + rhs.0.len(), + "{}", + VidpfError::InvalidWeightLength + ); + + Self(zip(self.0, rhs.0).map(|(a, b)| a.add(b)).collect()) + } +} + +impl<F: FieldElement> AddAssign for VidpfWeight<F> { + /// Panics if weight lengths are different. + fn add_assign(&mut self, rhs: Self) { + assert_eq!( + self.0.len(), + rhs.0.len(), + "{}", + VidpfError::InvalidWeightLength + ); + + zip(&mut self.0, rhs.0).for_each(|(a, b)| a.add_assign(b)); + } +} + +impl<F: FieldElement> Sub for VidpfWeight<F> { + type Output = Self; + + /// Panics if weight lengths are different. + fn sub(self, rhs: Self) -> Self::Output { + assert_eq!( + self.0.len(), + rhs.0.len(), + "{}", + VidpfError::InvalidWeightLength + ); + + Self(zip(self.0, rhs.0).map(|(a, b)| a.sub(b)).collect()) + } +} + +impl<F: FieldElement> Encode for VidpfWeight<F> { + fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> { + for e in &self.0 { + F::encode(e, bytes)?; + } + Ok(()) + } + + fn encoded_len(&self) -> Option<usize> { + Some(self.0.len() * F::ENCODED_SIZE) + } +} + +impl<F: FieldElement> ParameterizedDecode<<Self as IdpfValue>::ValueParameter> for VidpfWeight<F> { + fn decode_with_param( + decoding_parameter: &<Self as IdpfValue>::ValueParameter, + bytes: &mut Cursor<&[u8]>, + ) -> Result<Self, CodecError> { + let mut v = Vec::with_capacity(*decoding_parameter); + for _ in 0..*decoding_parameter { + v.push(F::decode_with_param(&(), bytes)?); + } + + Ok(Self(v)) + } +} + +#[cfg(test)] +mod tests { + use crate::field::Field128; + + use super::VidpfWeight; + + type TestWeight = VidpfWeight<Field128>; + const TEST_WEIGHT_LEN: usize = 3; + const TEST_NONCE_SIZE: usize = 16; + const TEST_NONCE: &[u8; TEST_NONCE_SIZE] = b"Test Nonce VIDPF"; + + mod vidpf { + use crate::{ + idpf::IdpfValue, + vidpf::{ + Vidpf, VidpfError, VidpfEvalState, VidpfInput, VidpfKey, VidpfPublicShare, + VidpfServerId, + }, + }; + + use super::{TestWeight, TEST_NONCE, TEST_NONCE_SIZE, TEST_WEIGHT_LEN}; + + fn vidpf_gen_setup( + input: &VidpfInput, + weight: &TestWeight, + ) -> ( + Vidpf<TestWeight, TEST_NONCE_SIZE>, + VidpfPublicShare<TestWeight>, + [VidpfKey; 2], + [u8; TEST_NONCE_SIZE], + ) { + let vidpf = Vidpf::new(TEST_WEIGHT_LEN); + let (public, keys) = vidpf.gen(input, weight, TEST_NONCE).unwrap(); + (vidpf, public, keys, *TEST_NONCE) + } + + #[test] + fn gen_with_keys() { + let input = VidpfInput::from_bytes(&[0xFF]); + let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]); + let vidpf = Vidpf::new(TEST_WEIGHT_LEN); + let keys_with_same_id = [ + VidpfKey::gen(VidpfServerId::S0).unwrap(), + VidpfKey::gen(VidpfServerId::S0).unwrap(), + ]; + + let err = vidpf + .gen_with_keys(&keys_with_same_id, &input, &weight, TEST_NONCE) + .unwrap_err(); + + assert_eq!(err.to_string(), VidpfError::SameKeyId.to_string()); + } + + #[test] + fn correctness_at_last_level() { + let input = VidpfInput::from_bytes(&[0xFF]); + let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]); + let (vidpf, public, [key_0, key_1], nonce) = vidpf_gen_setup(&input, &weight); + + let value_share_0 = vidpf.eval(&key_0, &public, &input, &nonce).unwrap(); + let value_share_1 = vidpf.eval(&key_1, &public, &input, &nonce).unwrap(); + + assert_eq!( + value_share_0.share + value_share_1.share, + weight, + "shares must add up to the expected weight", + ); + + assert_eq!( + value_share_0.proof, value_share_1.proof, + "proofs must be equal" + ); + + let bad_input = VidpfInput::from_bytes(&[0x00]); + let zero = TestWeight::zero(&TEST_WEIGHT_LEN); + let value_share_0 = vidpf.eval(&key_0, &public, &bad_input, &nonce).unwrap(); + let value_share_1 = vidpf.eval(&key_1, &public, &bad_input, &nonce).unwrap(); + + assert_eq!( + value_share_0.share + value_share_1.share, + zero, + "shares must add up to zero", + ); + + assert_eq!( + value_share_0.proof, value_share_1.proof, + "proofs must be equal" + ); + } + + #[test] + fn correctness_at_each_level() { + let input = VidpfInput::from_bytes(&[0xFF]); + let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]); + let (vidpf, public, keys, nonce) = vidpf_gen_setup(&input, &weight); + + assert_eval_at_each_level(&vidpf, &keys, &public, &input, &weight, &nonce); + + let bad_input = VidpfInput::from_bytes(&[0x00]); + let zero = TestWeight::zero(&TEST_WEIGHT_LEN); + + assert_eval_at_each_level(&vidpf, &keys, &public, &bad_input, &zero, &nonce); + } + + fn assert_eval_at_each_level( + vidpf: &Vidpf<TestWeight, TEST_NONCE_SIZE>, + [key_0, key_1]: &[VidpfKey; 2], + public: &VidpfPublicShare<TestWeight>, + input: &VidpfInput, + weight: &TestWeight, + nonce: &[u8; TEST_NONCE_SIZE], + ) { + let mut state_0 = VidpfEvalState::init_from_key(key_0); + let mut state_1 = VidpfEvalState::init_from_key(key_1); + + let n = input.len(); + for level in 0..n { + let share_0; + let share_1; + (state_0, share_0) = vidpf + .eval_next(key_0.id, public, input, level, &state_0, nonce) + .unwrap(); + (state_1, share_1) = vidpf + .eval_next(key_1.id, public, input, level, &state_1, nonce) + .unwrap(); + + assert_eq!( + share_0 + share_1, + *weight, + "shares must add up to the expected weight at the current level: {:?}", + level + ); + + assert_eq!( + state_0.proof, state_1.proof, + "proofs must be equal at the current level: {:?}", + level + ); + } + } + } + + mod weight { + use std::io::Cursor; + use subtle::{Choice, ConditionallyNegatable}; + + use crate::{ + codec::{Encode, ParameterizedDecode}, + idpf::IdpfValue, + vdaf::xof::{Seed, Xof, XofTurboShake128}, + }; + + use super::{TestWeight, TEST_WEIGHT_LEN}; + + #[test] + fn roundtrip_codec() { + let weight = TestWeight::from(vec![21.into(), 22.into(), 23.into()]); + + let mut bytes = vec![]; + weight.encode(&mut bytes).unwrap(); + + let expected_bytes = [ + [vec![21], vec![0u8; 15]].concat(), + [vec![22], vec![0u8; 15]].concat(), + [vec![23], vec![0u8; 15]].concat(), + ] + .concat(); + + assert_eq!(weight.encoded_len().unwrap(), expected_bytes.len()); + // Check endianness of encoding + assert_eq!(bytes, expected_bytes); + + let decoded = + TestWeight::decode_with_param(&TEST_WEIGHT_LEN, &mut Cursor::new(&bytes)).unwrap(); + assert_eq!(weight, decoded); + } + + #[test] + fn add_sub() { + let [a, b] = compatible_weights(); + let mut c = a.clone(); + c += a.clone(); + + assert_eq!( + (a.clone() + b.clone()) + (a.clone() - b.clone()), + c, + "a: {:?} b:{:?}", + a, + b + ); + } + + #[test] + fn conditional_negate() { + let [a, _] = compatible_weights(); + let mut c = a.clone(); + c.conditional_negate(Choice::from(0)); + let mut d = a.clone(); + d.conditional_negate(Choice::from(1)); + let zero = TestWeight::zero(&TEST_WEIGHT_LEN); + + assert_eq!(c + d, zero, "a: {:?}", a); + } + + #[test] + #[should_panic = "invalid weight length"] + fn add_panics() { + let [w0, w1] = incompatible_weights(); + let _ = w0 + w1; + } + + #[test] + #[should_panic = "invalid weight length"] + fn add_assign_panics() { + let [mut w0, w1] = incompatible_weights(); + w0 += w1; + } + + #[test] + #[should_panic = "invalid weight length"] + fn sub_panics() { + let [w0, w1] = incompatible_weights(); + let _ = w0 - w1; + } + + #[test] + #[should_panic = "invalid weight length"] + fn conditional_select_panics() { + let [w0, w1] = incompatible_weights(); + TestWeight::conditional_select(&w0, &w1, Choice::from(0)); + } + + fn compatible_weights() -> [TestWeight; 2] { + let mut xof = XofTurboShake128::seed_stream(&Seed(Default::default()), &[], &[]); + [ + TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN), + TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN), + ] + } + + fn incompatible_weights() -> [TestWeight; 2] { + let mut xof = XofTurboShake128::seed_stream(&Seed(Default::default()), &[], &[]); + [ + TestWeight::generate(&mut xof, &TEST_WEIGHT_LEN), + TestWeight::generate(&mut xof, &(2 * TEST_WEIGHT_LEN)), + ] + } + } +} |