batch_evaluate without alloc (#48)

* `no_alloc` alternative to `VerifiableServer::batch_evaluate()`

* Rename `PreparedT` to `PreparedTscalar`
This commit is contained in:
daxpedda
2021-12-29 03:14:28 -05:00
committed by GitHub
parent 1c5e965446
commit d316ce4c8d
4 changed files with 256 additions and 111 deletions
+60 -23
View File
@@ -331,13 +331,10 @@
//! this case. In the following example, we show how to use the batch API to //! this case. In the following example, we show how to use the batch API to
//! produce a single proof for 10 parallel VOPRF evaluations. //! produce a single proof for 10 parallel VOPRF evaluations.
//! //!
//! This requires the crate feature `alloc`.
//!
//! First, the client produces 10 blindings, storing their resulting states and //! First, the client produces 10 blindings, storing their resulting states and
//! messages: //! messages:
//! //!
//! ``` //! ```
//! # #[cfg(feature = "alloc")] {
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; //! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -358,16 +355,14 @@
//! client_states.push(client_blind_result.state); //! client_states.push(client_blind_result.state);
//! client_messages.push(client_blind_result.message); //! client_messages.push(client_blind_result.message);
//! } //! }
//! # }
//! ``` //! ```
//! //!
//! Next, the server calls the [VerifiableServer::batch_evaluate] function on a //! Next, the server calls the [VerifiableServer::batch_evaluate_prepare] and
//! set of client messages, to produce a corresponding set of messages to be //! [VerifiableServer::batch_evaluate_finish] function on a set of client
//! returned to the client (returned in the same order), along with a single //! messages, to produce a corresponding set of messages to be returned to the
//! proof: //! client (returned in the same order), along with a single proof:
//! //!
//! ``` //! ```
//! # #[cfg(feature = "alloc")] {
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint; //! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")] //! # #[cfg(feature = "ristretto255")]
@@ -376,7 +371,7 @@
//! # type Group = p256_::ProjectivePoint; //! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))] //! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256; //! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient; //! # use voprf::{VerifiableServerBatchEvaluatePrepareResult, VerifiableServerBatchEvaluateFinishResult, VerifiableClient};
//! # use rand::{rngs::OsRng, RngCore}; //! # use rand::{rngs::OsRng, RngCore};
//! # //! #
//! # let mut client_rng = OsRng; //! # let mut client_rng = OsRng;
@@ -394,7 +389,50 @@
//! let mut server_rng = OsRng; //! let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng) //! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server"); //! # .expect("Unable to construct server");
//! let server_batch_evaluate_result = server //! let VerifiableServerBatchEvaluatePrepareResult {
//! prepared_evaluation_elements,
//! t,
//! } = server
//! .batch_evaluate_prepare(client_messages.iter(), None)
//! .expect("Unable to perform server batch evaluate");
//! let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
//! let VerifiableServerBatchEvaluateFinishResult { messages, proof } = VerifiableServer::batch_evaluate_finish(&mut server_rng, client_messages.iter(), &prepared_elements, &t)
//! .expect("Unable to perform server batch evaluate");
//! let messages: Vec<_> = messages.collect();
//! ```
//!
//! If [`alloc`] is available, [VerifiableServer::batch_evaluate] can be called
//! to avoid having to collect output manually:
//!
//! ```
//! # #[cfg(feature = "alloc")] {
//! # #[cfg(feature = "ristretto255")]
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
//! # #[cfg(feature = "ristretto255")]
//! # type Hash = sha2::Sha512;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256;
//! # use voprf::{VerifiableServerBatchEvaluateResult, VerifiableClient};
//! # use rand::{rngs::OsRng, RngCore};
//! #
//! # let mut client_rng = OsRng;
//! # let mut client_states = vec![];
//! # let mut client_messages = vec![];
//! # for _ in 0..10 {
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
//! # b"input",
//! # &mut client_rng,
//! # ).expect("Unable to construct client");
//! # client_states.push(client_blind_result.state);
//! # client_messages.push(client_blind_result.message);
//! # }
//! # use voprf::VerifiableServer;
//! let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server");
//! let VerifiableServerBatchEvaluateResult { messages, proof } = server
//! .batch_evaluate(&mut server_rng, &client_messages, None) //! .batch_evaluate(&mut server_rng, &client_messages, None)
//! .expect("Unable to perform server batch evaluate"); //! .expect("Unable to perform server batch evaluate");
//! # } //! # }
@@ -415,7 +453,7 @@
//! # type Group = p256_::ProjectivePoint; //! # type Group = p256_::ProjectivePoint;
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))] //! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
//! # type Hash = sha2::Sha256; //! # type Hash = sha2::Sha256;
//! # use voprf::VerifiableClient; //! # use voprf::{VerifiableServerBatchEvaluateResult, VerifiableClient};
//! # use rand::{rngs::OsRng, RngCore}; //! # use rand::{rngs::OsRng, RngCore};
//! # //! #
//! # let mut client_rng = OsRng; //! # let mut client_rng = OsRng;
@@ -430,19 +468,17 @@
//! # client_messages.push(client_blind_result.message); //! # client_messages.push(client_blind_result.message);
//! # } //! # }
//! # use voprf::VerifiableServer; //! # use voprf::VerifiableServer;
//! let mut server_rng = OsRng; //! # let mut server_rng = OsRng;
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng) //! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
//! # .expect("Unable to construct server"); //! # .expect("Unable to construct server");
//! # let server_batch_evaluate_result = server.batch_evaluate( //! # let VerifiableServerBatchEvaluateResult { messages, proof } = server
//! # &mut server_rng, //! # .batch_evaluate(&mut server_rng, &client_messages, None)
//! # &client_messages, //! # .expect("Unable to perform server batch evaluate");
//! # None,
//! # ).expect("Unable to perform server batch evaluate");
//! let client_batch_finalize_result = VerifiableClient::batch_finalize( //! let client_batch_finalize_result = VerifiableClient::batch_finalize(
//! &[b"input"; 10], //! &[b"input"; 10],
//! &client_states, //! &client_states,
//! &server_batch_evaluate_result.messages, //! &messages,
//! &server_batch_evaluate_result.proof, //! &proof,
//! server.get_public_key(), //! server.get_public_key(),
//! None, //! None,
//! ) //! )
@@ -527,7 +563,8 @@ pub use crate::group::Group;
pub use crate::voprf::VerifiableServerBatchEvaluateResult; pub use crate::voprf::VerifiableServerBatchEvaluateResult;
pub use crate::voprf::{ pub use crate::voprf::{
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableClientBlindResult, BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableClientBlindResult,
NonVerifiableServer, NonVerifiableServerEvaluateResult, Proof, VerifiableClient, NonVerifiableServer, NonVerifiableServerEvaluateResult, PreparedEvaluationElement,
VerifiableClientBatchFinalizeResult, VerifiableClientBlindResult, VerifiableServer, PreparedTscalar, Proof, VerifiableClient, VerifiableClientBatchFinalizeResult,
VerifiableServerEvaluateResult, VerifiableClientBlindResult, VerifiableServer, VerifiableServerBatchEvaluateFinishResult,
VerifiableServerBatchEvaluatePrepareResult, VerifiableServerEvaluateResult,
}; };
-1
View File
@@ -5,7 +5,6 @@
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory // License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree. // of this source tree.
#[cfg(feature = "alloc")]
mod mock_rng; mod mock_rng;
mod parser; mod parser;
mod voprf_test_vectors; mod voprf_test_vectors;
+23 -22
View File
@@ -8,18 +8,14 @@
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ops::Add;
use digest::core_api::BlockSizeUser; use digest::core_api::BlockSizeUser;
use digest::{Digest, FixedOutputReset}; use digest::{Digest, FixedOutputReset};
use generic_array::GenericArray; use generic_array::typenum::Sum;
use generic_array::{ArrayLength, GenericArray};
use json::JsonValue; use json::JsonValue;
#[cfg(feature = "alloc")]
use ::{
core::ops::Add,
generic_array::{typenum::Sum, ArrayLength},
};
#[cfg(feature = "alloc")]
use crate::tests::mock_rng::CycleRng; use crate::tests::mock_rng::CycleRng;
use crate::tests::parser::*; use crate::tests::parser::*;
use crate::{ use crate::{
@@ -38,7 +34,6 @@ struct VOPRFTestVectorParameters {
blinded_element: Vec<Vec<u8>>, blinded_element: Vec<Vec<u8>>,
evaluation_element: Vec<Vec<u8>>, evaluation_element: Vec<Vec<u8>>,
proof: Vec<u8>, proof: Vec<u8>,
#[cfg(feature = "alloc")]
proof_random_scalar: Vec<u8>, proof_random_scalar: Vec<u8>,
output: Vec<Vec<u8>>, output: Vec<Vec<u8>>,
} }
@@ -54,7 +49,6 @@ fn populate_test_vectors(values: &JsonValue) -> VOPRFTestVectorParameters {
blinded_element: decode_vec(values, "BlindedElement"), blinded_element: decode_vec(values, "BlindedElement"),
evaluation_element: decode_vec(values, "EvaluationElement"), evaluation_element: decode_vec(values, "EvaluationElement"),
proof: decode(values, "Proof"), proof: decode(values, "Proof"),
#[cfg(feature = "alloc")]
proof_random_scalar: decode(values, "ProofRandomScalar"), proof_random_scalar: decode(values, "ProofRandomScalar"),
output: decode_vec(values, "Output"), output: decode_vec(values, "Output"),
} }
@@ -118,7 +112,6 @@ fn test_vectors() -> Result<()> {
test_verifiable_seed_to_key::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?; test_verifiable_seed_to_key::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_blind::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?; test_verifiable_blind::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
#[cfg(feature = "alloc")]
test_verifiable_evaluate::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?; test_verifiable_evaluate::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
test_verifiable_finalize::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?; test_verifiable_finalize::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
} }
@@ -253,7 +246,6 @@ fn test_base_evaluate<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>(
Ok(()) Ok(())
} }
#[cfg(feature = "alloc")]
fn test_verifiable_evaluate<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>( fn test_verifiable_evaluate<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>(
tvs: &[VOPRFTestVectorParameters], tvs: &[VOPRFTestVectorParameters],
) -> Result<()> ) -> Result<()>
@@ -261,6 +253,10 @@ where
G::ScalarLen: Add<G::ScalarLen>, G::ScalarLen: Add<G::ScalarLen>,
Sum<G::ScalarLen, G::ScalarLen>: ArrayLength<u8>, Sum<G::ScalarLen, G::ScalarLen>: ArrayLength<u8>,
{ {
use crate::{
VerifiableServerBatchEvaluateFinishResult, VerifiableServerBatchEvaluatePrepareResult,
};
for parameters in tvs { for parameters in tvs {
let mut rng = CycleRng::new(parameters.proof_random_scalar.clone()); let mut rng = CycleRng::new(parameters.proof_random_scalar.clone());
let server = VerifiableServer::<G, H>::new_with_key(&parameters.sksm)?; let server = VerifiableServer::<G, H>::new_with_key(&parameters.sksm)?;
@@ -270,20 +266,25 @@ where
blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?); blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?);
} }
let batch_evaluate_result = let VerifiableServerBatchEvaluatePrepareResult {
server.batch_evaluate(&mut rng, &blinded_elements, Some(&parameters.info))?; prepared_evaluation_elements,
t,
} = server.batch_evaluate_prepare(blinded_elements.iter(), Some(&parameters.info))?;
let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
let VerifiableServerBatchEvaluateFinishResult { messages, proof } =
VerifiableServer::batch_evaluate_finish(
&mut rng,
blinded_elements.iter(),
&prepared_elements,
&t,
)?;
let messages: Vec<_> = messages.collect();
for i in 0..parameters.evaluation_element.len() { for (parameter, message) in parameters.evaluation_element.iter().zip(messages) {
assert_eq!( assert_eq!(&parameter, &message.serialize().as_slice(),);
&parameters.evaluation_element[i],
&batch_evaluate_result.messages[i].serialize().as_slice(),
);
} }
assert_eq!( assert_eq!(&parameters.proof, &proof.serialize().as_slice());
&parameters.proof,
&batch_evaluate_result.proof.serialize().as_slice()
);
} }
Ok(()) Ok(())
} }
+173 -65
View File
@@ -511,23 +511,27 @@ impl<G: Group, H: BlockSizeUser + Digest + FixedOutputReset> VerifiableServer<G,
blinded_element: &BlindedElement<G, H>, blinded_element: &BlindedElement<G, H>,
metadata: Option<&[u8]>, metadata: Option<&[u8]>,
) -> Result<VerifiableServerEvaluateResult<G, H>> { ) -> Result<VerifiableServerEvaluateResult<G, H>> {
let (mut evaluation_elements, t) = let VerifiableServerBatchEvaluatePrepareResult {
self.batch_evaluate_1(Some(blinded_element.copy()).into_iter(), metadata)?; prepared_evaluation_elements: mut evaluation_elements,
let evaluation_element = evaluation_elements.next().unwrap();
let proof = Self::batch_evaluate_2(
rng,
Some(blinded_element.copy()).into_iter(),
Some(evaluation_element.copy()).into_iter(),
t, t,
} = self.batch_evaluate_prepare(Some(blinded_element).into_iter(), metadata)?;
let prepared_element = [evaluation_elements.next().unwrap()];
let VerifiableServerBatchEvaluateFinishResult {
mut messages,
proof,
} = Self::batch_evaluate_finish(
rng,
Some(blinded_element).into_iter(),
&prepared_element,
&t,
)?; )?;
let message = messages.next().unwrap();
//let batch_result = self.batch_evaluate(rng, blinded_elements, metadata)?; //let batch_result = self.batch_evaluate(rng, blinded_elements, metadata)?;
Ok(VerifiableServerEvaluateResult { Ok(VerifiableServerEvaluateResult { message, proof })
message: evaluation_element,
proof,
})
} }
/// Allows for batching of the evaluation of multiple [BlindedElement] /// Allows for batching of the evaluation of multiple [BlindedElement]
@@ -545,37 +549,36 @@ impl<G: Group, H: BlockSizeUser + Digest + FixedOutputReset> VerifiableServer<G,
&'a I: IntoIterator<Item = &'a BlindedElement<G, H>>, &'a I: IntoIterator<Item = &'a BlindedElement<G, H>>,
<&'a I as IntoIterator>::IntoIter: ExactSizeIterator, <&'a I as IntoIterator>::IntoIter: ExactSizeIterator,
{ {
let (evaluation_elements, t) = self.batch_evaluate_1( let VerifiableServerBatchEvaluatePrepareResult {
blinded_elements.into_iter().map(BlindedElement::copy), prepared_evaluation_elements: evaluation_elements,
metadata,
)?;
let evaluation_elements: Vec<_> = evaluation_elements.collect();
let proof = Self::batch_evaluate_2(
rng,
blinded_elements.into_iter().map(BlindedElement::copy),
evaluation_elements.iter().map(EvaluationElement::copy),
t, t,
)?; } = self.batch_evaluate_prepare(blinded_elements.into_iter(), metadata)?;
let prepared_elements = evaluation_elements.collect();
let VerifiableServerBatchEvaluateFinishResult { messages, proof } =
Self::batch_evaluate_finish::<_, _, Vec<_>>(
rng,
blinded_elements.into_iter(),
&prepared_elements,
&t,
)?;
Ok(VerifiableServerBatchEvaluateResult { Ok(VerifiableServerBatchEvaluateResult {
messages: evaluation_elements, messages: messages.collect(),
proof, proof,
}) })
} }
fn batch_evaluate_1<I>( /// Alternative version of [`batch_evaluate`](Self::batch_evaluate) without
/// memory allocation. Returned [`PreparedEvaluationElement`] have to be
/// [`collect`](Iterator::collect)ed and passed into
/// [`batch_evaluate_finish`](Self::batch_evaluate_finish).
pub fn batch_evaluate_prepare<'a, I: Iterator<Item = &'a BlindedElement<G, H>>>(
&self, &self,
blinded_elements: I, blinded_elements: I,
metadata: Option<&[u8]>, metadata: Option<&[u8]>,
) -> Result<( ) -> Result<VerifiableServerBatchEvaluatePrepareResult<'a, G, H, I>> {
impl Iterator<Item = EvaluationElement<G, H>> + ExactSizeIterator,
G::Scalar,
)>
where
I: Iterator<Item = BlindedElement<G, H>> + ExactSizeIterator,
{
chain!(context, chain!(context,
STR_CONTEXT => |x| Some(x.as_ref()), STR_CONTEXT => |x| Some(x.as_ref()),
get_context_string::<G>(Mode::Verifiable)? => |x| Some(x.as_slice()), get_context_string::<G>(Mode::Verifiable)? => |x| Some(x.as_slice()),
@@ -585,30 +588,62 @@ impl<G: Group, H: BlockSizeUser + Digest + FixedOutputReset> VerifiableServer<G,
.concat(get_context_string::<G>(Mode::Verifiable)?); .concat(get_context_string::<G>(Mode::Verifiable)?);
let m = G::hash_to_scalar::<H, _, _>(context, dst)?; let m = G::hash_to_scalar::<H, _, _>(context, dst)?;
let t = self.sk + &m; let t = self.sk + &m;
let evaluation_elements = blinded_elements.map(move |x| EvaluationElement { let evaluation_elements = blinded_elements
value: x.value * &G::scalar_invert(&t), // To make a return type possible, we have to convert to a `fn` pointer, which isn't
hash: PhantomData, // possible if we `move` from context.
}); .zip(iter::repeat(G::scalar_invert(&t)))
.map(<fn((&BlindedElement<G, H>, _)) -> _>::from(|(x, t)| {
PreparedEvaluationElement(EvaluationElement {
value: x.value * &t,
hash: PhantomData,
})
}));
Ok((evaluation_elements, t)) Ok(VerifiableServerBatchEvaluatePrepareResult {
prepared_evaluation_elements: evaluation_elements,
t: PreparedTscalar {
t,
hash: PhantomData,
},
})
} }
/// Allows for batching of the evaluation of multiple [BlindedElement] /// See [`batch_evaluate_prepare`](Self::batch_evaluate_prepare) for more
/// messages from a [VerifiableClient] /// details.
fn batch_evaluate_2<R: RngCore + CryptoRng, IE, IB>( pub fn batch_evaluate_finish<'a, 'b, R: RngCore + CryptoRng, IB, IE>(
rng: &mut R, rng: &mut R,
blinded_elements: IB, blinded_elements: IB,
evaluation_elements: IE, evaluation_elements: &'b IE,
t: G::Scalar, PreparedTscalar { t, .. }: &PreparedTscalar<G, H>,
) -> Result<Proof<G, H>> ) -> Result<VerifiableServerBatchEvaluateFinishResult<'b, G, H, IE>>
where where
IB: Iterator<Item = BlindedElement<G, H>> + ExactSizeIterator, G: 'a + 'b,
IE: Iterator<Item = EvaluationElement<G, H>> + ExactSizeIterator, H: 'a + 'b,
IB: Iterator<Item = &'a BlindedElement<G, H>> + ExactSizeIterator,
&'b IE: IntoIterator<Item = &'b PreparedEvaluationElement<G, H>>,
<&'b IE as IntoIterator>::IntoIter: ExactSizeIterator,
{ {
let g = G::base_point(); let g = G::base_point();
let u = g * &t; let u = g * t;
generate_proof(rng, t, g, u, evaluation_elements, blinded_elements) let proof = generate_proof(
rng,
*t,
g,
u,
evaluation_elements
.into_iter()
.map(|element| element.0.copy()),
blinded_elements.map(BlindedElement::copy),
)?;
let messages =
evaluation_elements
.into_iter()
.map(<fn(&PreparedEvaluationElement<G, H>) -> _>::from(
|element| element.0.copy(),
));
Ok(VerifiableServerBatchEvaluateFinishResult { messages, proof })
} }
/// Retrieves the server's public key /// Retrieves the server's public key
@@ -662,6 +697,59 @@ pub struct VerifiableServerEvaluateResult<G: Group, H: BlockSizeUser + Digest +
pub proof: Proof<G, H>, pub proof: Proof<G, H>,
} }
/// Contains prepared [`EvaluationElement`]s by a verifiable server batch
/// evaluate preparation.
pub struct PreparedEvaluationElement<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>(
EvaluationElement<G, H>,
);
/// Contains the prepared `t` by a verifiable server batch evaluate preparation.
#[derive(DeriveWhere)]
#[derive_where(Zeroize(drop))]
pub struct PreparedTscalar<G: Group, H: BlockSizeUser + Digest + FixedOutputReset> {
t: G::Scalar,
#[derive_where(skip)]
hash: PhantomData<H>,
}
/// Contains the fields that are returned by a verifiable server batch evaluate
/// preparation.
pub struct VerifiableServerBatchEvaluatePrepareResult<
'a,
G: 'a + Group,
H: 'a + BlockSizeUser + Digest + FixedOutputReset,
I: Iterator<Item = &'a BlindedElement<G, H>>,
> {
/// Prepared [`EvaluationElement`]s that will become messages.
#[allow(clippy::type_complexity)]
pub prepared_evaluation_elements: Map<
Zip<I, Repeat<G::Scalar>>,
fn((&BlindedElement<G, H>, G::Scalar)) -> PreparedEvaluationElement<G, H>,
>,
/// Prepared `t` needed to finish the verifiable server batch evaluation.
pub t: PreparedTscalar<G, H>,
}
/// Contains the fields that are returned by a verifiable server batch evaluate
/// finish.
pub struct VerifiableServerBatchEvaluateFinishResult<
'a,
G: 'a + Group,
H: 'a + BlockSizeUser + Digest + FixedOutputReset,
I,
> where
&'a I: IntoIterator<Item = &'a PreparedEvaluationElement<G, H>>,
{
/// The messages to send to the client
#[allow(clippy::type_complexity)]
pub messages: Map<
<&'a I as IntoIterator>::IntoIter,
fn(&PreparedEvaluationElement<G, H>) -> EvaluationElement<G, H>,
>,
/// The proof for the client to verify
pub proof: Proof<G, H>,
}
/// Contains the fields that are returned by a verifiable server batch evaluate /// Contains the fields that are returned by a verifiable server batch evaluate
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub struct VerifiableServerBatchEvaluateResult< pub struct VerifiableServerBatchEvaluateResult<
@@ -1008,12 +1096,12 @@ fn get_context_string<G: Group>(mode: Mode) -> Result<GenericArray<u8, U11>> {
mod tests { mod tests {
use core::ops::Add; use core::ops::Add;
use ::alloc::vec;
use ::alloc::vec::Vec;
use generic_array::typenum::Sum; use generic_array::typenum::Sum;
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use zeroize::Zeroize; use zeroize::Zeroize;
#[cfg(feature = "alloc")]
use ::{alloc::vec, alloc::vec::Vec};
use super::*; use super::*;
use crate::Group; use crate::Group;
@@ -1087,7 +1175,6 @@ mod tests {
assert_eq!(client_finalize_result, res2); assert_eq!(client_finalize_result, res2);
} }
#[cfg(feature = "alloc")]
fn verifiable_bad_public_key<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() { fn verifiable_bad_public_key<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() {
let input = b"input"; let input = b"input";
let info = b"info"; let info = b"info";
@@ -1111,7 +1198,6 @@ mod tests {
assert!(client_finalize_result.is_err()); assert!(client_finalize_result.is_err());
} }
#[cfg(feature = "alloc")]
fn verifiable_batch_retrieval<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() { fn verifiable_batch_retrieval<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() {
let info = b"info"; let info = b"info";
let mut rng = OsRng; let mut rng = OsRng;
@@ -1128,14 +1214,27 @@ mod tests {
client_messages.push(client_blind_result.message); client_messages.push(client_blind_result.message);
} }
let server = VerifiableServer::<G, H>::new(&mut rng).unwrap(); let server = VerifiableServer::<G, H>::new(&mut rng).unwrap();
let server_result = server let VerifiableServerBatchEvaluatePrepareResult {
.batch_evaluate(&mut rng, &client_messages, Some(info)) prepared_evaluation_elements,
t,
} = server
.batch_evaluate_prepare(client_messages.iter(), Some(info))
.unwrap(); .unwrap();
let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
let VerifiableServerBatchEvaluateFinishResult { messages, proof } =
VerifiableServer::batch_evaluate_finish(
&mut rng,
client_messages.iter(),
&prepared_elements,
&t,
)
.unwrap();
let messages: Vec<_> = messages.collect();
let client_finalize_result = VerifiableClient::batch_finalize( let client_finalize_result = VerifiableClient::batch_finalize(
&inputs, &inputs,
&client_states, &client_states,
&server_result.messages, &messages,
&server_result.proof, &proof,
server.get_public_key(), server.get_public_key(),
Some(info), Some(info),
) )
@@ -1150,7 +1249,6 @@ mod tests {
assert_eq!(client_finalize_result, res2); assert_eq!(client_finalize_result, res2);
} }
#[cfg(feature = "alloc")]
fn verifiable_batch_bad_public_key<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() { fn verifiable_batch_bad_public_key<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>() {
let info = b"info"; let info = b"info";
let mut rng = OsRng; let mut rng = OsRng;
@@ -1167,9 +1265,22 @@ mod tests {
client_messages.push(client_blind_result.message); client_messages.push(client_blind_result.message);
} }
let server = VerifiableServer::<G, H>::new(&mut rng).unwrap(); let server = VerifiableServer::<G, H>::new(&mut rng).unwrap();
let server_result = server let VerifiableServerBatchEvaluatePrepareResult {
.batch_evaluate(&mut rng, &client_messages, Some(info)) prepared_evaluation_elements,
t,
} = server
.batch_evaluate_prepare(client_messages.iter(), Some(info))
.unwrap(); .unwrap();
let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
let VerifiableServerBatchEvaluateFinishResult { messages, proof } =
VerifiableServer::batch_evaluate_finish(
&mut rng,
client_messages.iter(),
&prepared_elements,
&t,
)
.unwrap();
let messages: Vec<_> = messages.collect();
let wrong_pk = { let wrong_pk = {
// Choose a group element that is unlikely to be the right public key // Choose a group element that is unlikely to be the right public key
G::hash_to_curve::<H, _>(b"msg", (*b"dst").into()).unwrap() G::hash_to_curve::<H, _>(b"msg", (*b"dst").into()).unwrap()
@@ -1177,8 +1288,8 @@ mod tests {
let client_finalize_result = VerifiableClient::batch_finalize( let client_finalize_result = VerifiableClient::batch_finalize(
&inputs, &inputs,
&client_states, &client_states,
&server_result.messages, &messages,
&server_result.proof, &proof,
wrong_pk, wrong_pk,
Some(info), Some(info),
); );
@@ -1309,11 +1420,8 @@ mod tests {
base_retrieval::<RistrettoPoint, Sha512>(); base_retrieval::<RistrettoPoint, Sha512>();
base_inversion_unsalted::<RistrettoPoint, Sha512>(); base_inversion_unsalted::<RistrettoPoint, Sha512>();
verifiable_retrieval::<RistrettoPoint, Sha512>(); verifiable_retrieval::<RistrettoPoint, Sha512>();
#[cfg(feature = "alloc")]
verifiable_batch_retrieval::<RistrettoPoint, Sha512>(); verifiable_batch_retrieval::<RistrettoPoint, Sha512>();
#[cfg(feature = "alloc")]
verifiable_bad_public_key::<RistrettoPoint, Sha512>(); verifiable_bad_public_key::<RistrettoPoint, Sha512>();
#[cfg(feature = "alloc")]
verifiable_batch_bad_public_key::<RistrettoPoint, Sha512>(); verifiable_batch_bad_public_key::<RistrettoPoint, Sha512>();
zeroize_base_client::<RistrettoPoint, Sha512>(); zeroize_base_client::<RistrettoPoint, Sha512>();