1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::fmt::Debug;
use crate::{correlated_randomness::CorrelatedBatch, utils::TryFuture};
/// Generates preprocessing elements for a given preprocessing type.
pub trait CorrelationGenerator<PB: CorrelatedBatch>: Send {
/// The interface to the network used to send/receive messages.
type Net: Send;
/// The error type returned by the generator.
type Error: Debug + Clone + Send;
/// Whether one party may skip ahead independently, without all parties drawing identical
/// amounts in lockstep: `true` for dealer-style generators (deterministic per index), `false`
/// for interactive ones (where an asymmetric skip would desync the joint protocol).
///
/// If set to `true` you **must** override [`skip`](Self::skip) — the default panics (it can't
/// construct a `Self::Error`). When `false`, `skip` is never called.
const SUPPORTS_UNILATERAL_SKIP: bool = false;
/// Runs the preprocessing generation protocol and produces a batch of preprocessing elements
/// with compile-time known size.
fn run(&mut self, net: &mut Self::Net) -> impl TryFuture<Ok = PB, Error = Self::Error>;
/// Advances the logical position by `n_elements` without materializing the skipped elements,
/// to burn correlated elements during resync. Only called when
/// [`SUPPORTS_UNILATERAL_SKIP`](Self::SUPPORTS_UNILATERAL_SKIP) is `true`; the default panics.
fn skip(
&mut self,
_n_elements: usize,
_net: &mut Self::Net,
) -> impl TryFuture<Ok = (), Error = Self::Error> {
async move {
unreachable!(
"skip() called on a generator without SUPPORTS_UNILATERAL_SKIP; the stream \
dispatcher must guard on the const before ever calling skip()"
)
}
}
/// Runs the preprocessing generation protocol until at least `n_elements` are produced, and
/// returns a vector of preprocessing elements.
fn run_for(
&mut self,
n_elements: usize,
net: &mut Self::Net,
) -> impl TryFuture<Ok = Vec<PB::Item>, Error = Self::Error> {
let n_batches = n_elements.div_ceil(PB::batch_size());
let mut result = Vec::with_capacity(n_batches * PB::batch_size());
async move {
for _ in 0..n_batches {
let batch = self.run(net).await?;
result.extend(batch.into_iter());
}
Ok(result)
}
}
}