Skip to content

Commit d316ce4

Browse files
authored
batch_evaluate without alloc (#48)
* `no_alloc` alternative to `VerifiableServer::batch_evaluate()` * Rename `PreparedT` to `PreparedTscalar`
1 parent 1c5e965 commit d316ce4

File tree

4 files changed

+251
-106
lines changed

4 files changed

+251
-106
lines changed

src/lib.rs

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,10 @@
331331
//! this case. In the following example, we show how to use the batch API to
332332
//! produce a single proof for 10 parallel VOPRF evaluations.
333333
//!
334-
//! This requires the crate feature `alloc`.
335-
//!
336334
//! First, the client produces 10 blindings, storing their resulting states and
337335
//! messages:
338336
//!
339337
//! ```
340-
//! # #[cfg(feature = "alloc")] {
341338
//! # #[cfg(feature = "ristretto255")]
342339
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
343340
//! # #[cfg(feature = "ristretto255")]
@@ -358,13 +355,54 @@
358355
//! client_states.push(client_blind_result.state);
359356
//! client_messages.push(client_blind_result.message);
360357
//! }
358+
//! ```
359+
//!
360+
//! Next, the server calls the [VerifiableServer::batch_evaluate_prepare] and
361+
//! [VerifiableServer::batch_evaluate_finish] function on a set of client
362+
//! messages, to produce a corresponding set of messages to be returned to the
363+
//! client (returned in the same order), along with a single proof:
364+
//!
365+
//! ```
366+
//! # #[cfg(feature = "ristretto255")]
367+
//! # type Group = curve25519_dalek::ristretto::RistrettoPoint;
368+
//! # #[cfg(feature = "ristretto255")]
369+
//! # type Hash = sha2::Sha512;
370+
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
371+
//! # type Group = p256_::ProjectivePoint;
372+
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
373+
//! # type Hash = sha2::Sha256;
374+
//! # use voprf::{VerifiableServerBatchEvaluatePrepareResult, VerifiableServerBatchEvaluateFinishResult, VerifiableClient};
375+
//! # use rand::{rngs::OsRng, RngCore};
376+
//! #
377+
//! # let mut client_rng = OsRng;
378+
//! # let mut client_states = vec![];
379+
//! # let mut client_messages = vec![];
380+
//! # for _ in 0..10 {
381+
//! # let client_blind_result = VerifiableClient::<Group, Hash>::blind(
382+
//! # b"input",
383+
//! # &mut client_rng,
384+
//! # ).expect("Unable to construct client");
385+
//! # client_states.push(client_blind_result.state);
386+
//! # client_messages.push(client_blind_result.message);
361387
//! # }
388+
//! # use voprf::VerifiableServer;
389+
//! let mut server_rng = OsRng;
390+
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
391+
//! # .expect("Unable to construct server");
392+
//! let VerifiableServerBatchEvaluatePrepareResult {
393+
//! prepared_evaluation_elements,
394+
//! t,
395+
//! } = server
396+
//! .batch_evaluate_prepare(client_messages.iter(), None)
397+
//! .expect("Unable to perform server batch evaluate");
398+
//! let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
399+
//! let VerifiableServerBatchEvaluateFinishResult { messages, proof } = VerifiableServer::batch_evaluate_finish(&mut server_rng, client_messages.iter(), &prepared_elements, &t)
400+
//! .expect("Unable to perform server batch evaluate");
401+
//! let messages: Vec<_> = messages.collect();
362402
//! ```
363403
//!
364-
//! Next, the server calls the [VerifiableServer::batch_evaluate] function on a
365-
//! set of client messages, to produce a corresponding set of messages to be
366-
//! returned to the client (returned in the same order), along with a single
367-
//! proof:
404+
//! If [`alloc`] is available, [VerifiableServer::batch_evaluate] can be called
405+
//! to avoid having to collect output manually:
368406
//!
369407
//! ```
370408
//! # #[cfg(feature = "alloc")] {
@@ -376,7 +414,7 @@
376414
//! # type Group = p256_::ProjectivePoint;
377415
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
378416
//! # type Hash = sha2::Sha256;
379-
//! # use voprf::VerifiableClient;
417+
//! # use voprf::{VerifiableServerBatchEvaluateResult, VerifiableClient};
380418
//! # use rand::{rngs::OsRng, RngCore};
381419
//! #
382420
//! # let mut client_rng = OsRng;
@@ -394,7 +432,7 @@
394432
//! let mut server_rng = OsRng;
395433
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
396434
//! # .expect("Unable to construct server");
397-
//! let server_batch_evaluate_result = server
435+
//! let VerifiableServerBatchEvaluateResult { messages, proof } = server
398436
//! .batch_evaluate(&mut server_rng, &client_messages, None)
399437
//! .expect("Unable to perform server batch evaluate");
400438
//! # }
@@ -415,7 +453,7 @@
415453
//! # type Group = p256_::ProjectivePoint;
416454
//! # #[cfg(all(feature = "p256", not(feature = "ristretto255")))]
417455
//! # type Hash = sha2::Sha256;
418-
//! # use voprf::VerifiableClient;
456+
//! # use voprf::{VerifiableServerBatchEvaluateResult, VerifiableClient};
419457
//! # use rand::{rngs::OsRng, RngCore};
420458
//! #
421459
//! # let mut client_rng = OsRng;
@@ -430,19 +468,17 @@
430468
//! # client_messages.push(client_blind_result.message);
431469
//! # }
432470
//! # use voprf::VerifiableServer;
433-
//! let mut server_rng = OsRng;
471+
//! # let mut server_rng = OsRng;
434472
//! # let server = VerifiableServer::<Group, Hash>::new(&mut server_rng)
435473
//! # .expect("Unable to construct server");
436-
//! # let server_batch_evaluate_result = server.batch_evaluate(
437-
//! # &mut server_rng,
438-
//! # &client_messages,
439-
//! # None,
440-
//! # ).expect("Unable to perform server batch evaluate");
474+
//! # let VerifiableServerBatchEvaluateResult { messages, proof } = server
475+
//! # .batch_evaluate(&mut server_rng, &client_messages, None)
476+
//! # .expect("Unable to perform server batch evaluate");
441477
//! let client_batch_finalize_result = VerifiableClient::batch_finalize(
442478
//! &[b"input"; 10],
443479
//! &client_states,
444-
//! &server_batch_evaluate_result.messages,
445-
//! &server_batch_evaluate_result.proof,
480+
//! &messages,
481+
//! &proof,
446482
//! server.get_public_key(),
447483
//! None,
448484
//! )
@@ -527,7 +563,8 @@ pub use crate::group::Group;
527563
pub use crate::voprf::VerifiableServerBatchEvaluateResult;
528564
pub use crate::voprf::{
529565
BlindedElement, EvaluationElement, NonVerifiableClient, NonVerifiableClientBlindResult,
530-
NonVerifiableServer, NonVerifiableServerEvaluateResult, Proof, VerifiableClient,
531-
VerifiableClientBatchFinalizeResult, VerifiableClientBlindResult, VerifiableServer,
532-
VerifiableServerEvaluateResult,
566+
NonVerifiableServer, NonVerifiableServerEvaluateResult, PreparedEvaluationElement,
567+
PreparedTscalar, Proof, VerifiableClient, VerifiableClientBatchFinalizeResult,
568+
VerifiableClientBlindResult, VerifiableServer, VerifiableServerBatchEvaluateFinishResult,
569+
VerifiableServerBatchEvaluatePrepareResult, VerifiableServerEvaluateResult,
533570
};

src/tests/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
66
// of this source tree.
77

8-
#[cfg(feature = "alloc")]
98
mod mock_rng;
109
mod parser;
1110
mod voprf_test_vectors;

src/tests/voprf_test_vectors.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,14 @@
88
use alloc::string::{String, ToString};
99
use alloc::vec;
1010
use alloc::vec::Vec;
11+
use core::ops::Add;
1112

1213
use digest::core_api::BlockSizeUser;
1314
use digest::{Digest, FixedOutputReset};
14-
use generic_array::GenericArray;
15+
use generic_array::typenum::Sum;
16+
use generic_array::{ArrayLength, GenericArray};
1517
use json::JsonValue;
16-
#[cfg(feature = "alloc")]
17-
use ::{
18-
core::ops::Add,
19-
generic_array::{typenum::Sum, ArrayLength},
20-
};
2118

22-
#[cfg(feature = "alloc")]
2319
use crate::tests::mock_rng::CycleRng;
2420
use crate::tests::parser::*;
2521
use crate::{
@@ -38,7 +34,6 @@ struct VOPRFTestVectorParameters {
3834
blinded_element: Vec<Vec<u8>>,
3935
evaluation_element: Vec<Vec<u8>>,
4036
proof: Vec<u8>,
41-
#[cfg(feature = "alloc")]
4237
proof_random_scalar: Vec<u8>,
4338
output: Vec<Vec<u8>>,
4439
}
@@ -54,7 +49,6 @@ fn populate_test_vectors(values: &JsonValue) -> VOPRFTestVectorParameters {
5449
blinded_element: decode_vec(values, "BlindedElement"),
5550
evaluation_element: decode_vec(values, "EvaluationElement"),
5651
proof: decode(values, "Proof"),
57-
#[cfg(feature = "alloc")]
5852
proof_random_scalar: decode(values, "ProofRandomScalar"),
5953
output: decode_vec(values, "Output"),
6054
}
@@ -118,7 +112,6 @@ fn test_vectors() -> Result<()> {
118112

119113
test_verifiable_seed_to_key::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
120114
test_verifiable_blind::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
121-
#[cfg(feature = "alloc")]
122115
test_verifiable_evaluate::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
123116
test_verifiable_finalize::<RistrettoPoint, Sha512>(&ristretto_verifiable_tvs)?;
124117
}
@@ -253,14 +246,17 @@ fn test_base_evaluate<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>(
253246
Ok(())
254247
}
255248

256-
#[cfg(feature = "alloc")]
257249
fn test_verifiable_evaluate<G: Group, H: BlockSizeUser + Digest + FixedOutputReset>(
258250
tvs: &[VOPRFTestVectorParameters],
259251
) -> Result<()>
260252
where
261253
G::ScalarLen: Add<G::ScalarLen>,
262254
Sum<G::ScalarLen, G::ScalarLen>: ArrayLength<u8>,
263255
{
256+
use crate::{
257+
VerifiableServerBatchEvaluateFinishResult, VerifiableServerBatchEvaluatePrepareResult,
258+
};
259+
264260
for parameters in tvs {
265261
let mut rng = CycleRng::new(parameters.proof_random_scalar.clone());
266262
let server = VerifiableServer::<G, H>::new_with_key(&parameters.sksm)?;
@@ -270,20 +266,25 @@ where
270266
blinded_elements.push(BlindedElement::deserialize(blinded_element_bytes)?);
271267
}
272268

273-
let batch_evaluate_result =
274-
server.batch_evaluate(&mut rng, &blinded_elements, Some(&parameters.info))?;
269+
let VerifiableServerBatchEvaluatePrepareResult {
270+
prepared_evaluation_elements,
271+
t,
272+
} = server.batch_evaluate_prepare(blinded_elements.iter(), Some(&parameters.info))?;
273+
let prepared_elements: Vec<_> = prepared_evaluation_elements.collect();
274+
let VerifiableServerBatchEvaluateFinishResult { messages, proof } =
275+
VerifiableServer::batch_evaluate_finish(
276+
&mut rng,
277+
blinded_elements.iter(),
278+
&prepared_elements,
279+
&t,
280+
)?;
281+
let messages: Vec<_> = messages.collect();
275282

276-
for i in 0..parameters.evaluation_element.len() {
277-
assert_eq!(
278-
&parameters.evaluation_element[i],
279-
&batch_evaluate_result.messages[i].serialize().as_slice(),
280-
);
283+
for (parameter, message) in parameters.evaluation_element.iter().zip(messages) {
284+
assert_eq!(&parameter, &message.serialize().as_slice(),);
281285
}
282286

283-
assert_eq!(
284-
&parameters.proof,
285-
&batch_evaluate_result.proof.serialize().as_slice()
286-
);
287+
assert_eq!(&parameters.proof, &proof.serialize().as_slice());
287288
}
288289
Ok(())
289290
}

0 commit comments

Comments
 (0)