diff --git a/src/field.rs b/src/field.rs index 1215eaee4..2938ec5b8 100644 --- a/src/field.rs +++ b/src/field.rs @@ -56,7 +56,8 @@ pub enum FieldError { 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, @@ -134,6 +135,7 @@ pub trait FieldElement: /// Ideally we would implement `From<&[F: FieldElement]> for Vec` 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 { let mut vec = Vec::with_capacity(values.len() * Self::ENCODED_SIZE); encode_fieldvec(values, &mut vec); @@ -154,13 +156,15 @@ pub trait FieldElement: /// Ideally we would implement `From<&[u8]> for Vec` 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, 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) } @@ -1026,9 +1030,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(); @@ -1041,13 +1048,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::(), 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::(), Some(FieldError::ModulusOverflow)); + }); + } let insufficient = vec![0u8; F::ENCODED_SIZE - 1]; let err = F::try_from(insufficient.as_ref()).unwrap_err(); diff --git a/src/prng.rs b/src/prng.rs index 0325e5256..01ec0e218 100644 --- a/src/prng.rs +++ b/src/prng.rs @@ -126,6 +126,8 @@ where #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "prio2")] + use crate::field::encode_fieldvec; use crate::{ codec::Decode, field::{Field64, FieldPrio2}, @@ -164,7 +166,8 @@ mod tests { let seed = BASE64_STANDARD.decode(seed_base64).unwrap(); let random_data = extract_share_from_seed::(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); let mut hasher = Sha256::new(); hasher.update(&random_bytes); diff --git a/src/vdaf/prio2/client.rs b/src/vdaf/prio2/client.rs index dbce39ee3..143ccb39f 100644 --- a/src/vdaf/prio2/client.rs +++ b/src/vdaf/prio2/client.rs @@ -4,7 +4,8 @@ //! 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}, @@ -32,9 +33,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)] diff --git a/src/vdaf/prio2/server.rs b/src/vdaf/prio2/server.rs index 11c161bab..0ad81bfe3 100644 --- a/src/vdaf/prio2/server.rs +++ b/src/vdaf/prio2/server.rs @@ -101,9 +101,13 @@ pub(crate) fn is_valid_share( #[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, 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 { @@ -289,7 +298,10 @@ mod tests { let share1_original = shares[0].get_encoded(); let share2 = shares[1].get_encoded(); - let mut share1_field = FieldPrio2::byte_slice_into_vec(&share1_original).unwrap(); + let mut share1_field: Vec = 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,7 @@ mod tests { }; // reserialize altered share1 - let share1_modified = FieldPrio2::slice_into_byte_vec(&share1_field); + let share1_modified = Share::::Leader(share1_field).get_encoded(); let mut prng = Prng::from_prio2_seed(&random()); let eval_at = vdaf.choose_eval_at(&mut prng); diff --git a/src/vdaf/prio2/test_vector.rs b/src/vdaf/prio2/test_vector.rs index ae2b8b0f9..6c5c5e439 100644 --- a/src/vdaf/prio2/test_vector.rs +++ b/src/vdaf/prio2/test_vector.rs @@ -48,7 +48,12 @@ 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}; @@ -68,16 +73,19 @@ mod base64 { } pub fn serialize_field(v: &[FieldPrio2], s: S) -> Result { - String::serialize( - &BASE64_STANDARD.encode(FieldPrio2::slice_into_byte_vec(v)), - s, - ) + let mut bytes = Vec::new(); + encode_fieldvec(v, &mut bytes); + String::serialize(&BASE64_STANDARD.encode(&bytes), s) } pub fn deserialize_field<'de, D: Deserializer<'de>>(d: D) -> Result, 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) + let decoding_parameter = + ShareDecodingParameter::<32>::Leader(bytes.len() / FieldPrio2::ENCODED_SIZE); + let share = Share::::get_decoded_with_param(&decoding_parameter, &bytes) + .map_err(Error::custom)?; + assert_matches!(share, Share::Leader(vec) => Ok(vec)) } }