Skip to main content

primitives/correlated_randomness/bundler/
mod.rs

1use std::{
2    fmt::Debug,
3    ops::{Add, AddAssign, Sub, SubAssign},
4};
5
6use crate::correlated_randomness::{
7    bundler::errors::BundlerError,
8    stream::{CorrelatedStreamError, PrefetchHandle},
9};
10
11pub mod errors;
12
13/// The per-type correlation counts a [`BundleIterator`] holds (or that a fetch/prefetch requests).
14pub type SizeOf<I> = <I as BundleIterator>::Size;
15
16/// The error type of a [`BundleIterator`]'s correlation futures.
17pub type ErrorOf<I> = <I as BundleIterator>::Error;
18
19/// Bundles together multiple correlation generators/streams to fetch all correlations
20///  required by a given consumer, e.g., a circuit, a protocol, a layer...
21pub trait Bundler {
22    /// A type to hold the futures to all requested correlations.
23    type Iterator: BundleIterator;
24
25    /// Fetches the requested correlations and returns a ready-to-use iterator.
26    fn fetch(&mut self, size: &SizeOf<Self::Iterator>) -> Result<Self::Iterator, BundlerError>;
27
28    /// Fetches the requested correlations and returns a ready-to-use iterator.
29    fn fetch_for<Consumer: BundleConsumer<Iterator = Self::Iterator>>(
30        &mut self,
31        consumer: &Consumer,
32    ) -> Result<Self::Iterator, BundlerError> {
33        let size = consumer.required_preprocessing();
34        self.fetch(&size)
35    }
36
37    /// Proactively generates the correlations for `size` so a later [`fetch`](Self::fetch) need not
38    /// wait on generation. Fire-and-forget, and delivers nothing, so positions do not advance.
39    /// `Ok` means the generation happened or was unnecessary.
40    ///
41    /// All-or-nothing per stream: a `size` beyond a stream's buffer resolves with
42    /// [`RequestTooLarge`](CorrelatedStreamError::RequestTooLarge) or
43    /// [`RateLimitExceeded`](CorrelatedStreamError::RateLimitExceeded).
44    fn prefetch(&self, size: &SizeOf<Self::Iterator>) -> PrefetchHandle<ErrorOf<Self::Iterator>>;
45
46    /// Prefetches everything `consumer` will require. See [`prefetch`](Self::prefetch).
47    fn prefetch_for<Consumer: BundleConsumer<Iterator = Self::Iterator>>(
48        &self,
49        consumer: &Consumer,
50    ) -> PrefetchHandle<ErrorOf<Self::Iterator>> {
51        let size = consumer.required_preprocessing();
52        self.prefetch(&size)
53    }
54}
55
56impl<B: Bundler> Bundler for &mut B {
57    type Iterator = B::Iterator;
58
59    fn fetch(&mut self, size: &SizeOf<Self::Iterator>) -> Result<Self::Iterator, BundlerError> {
60        (**self).fetch(size)
61    }
62
63    fn prefetch(&self, size: &SizeOf<Self::Iterator>) -> PrefetchHandle<ErrorOf<Self::Iterator>> {
64        (**self).prefetch(size)
65    }
66}
67
68/// A consumer of a bundle of correlations, e.g., a circuit, a protocol, a layer...
69pub trait BundleConsumer {
70    /// An iterator holding futures to all correlations required by the consumer
71    ///  (e.g., F_q triples, binary singlets, ...)
72    type Iterator: BundleIterator;
73
74    /// Returns the size of the preprocessing required by the consumer.
75    fn required_preprocessing(&self) -> SizeOf<Self::Iterator>;
76
77    /// Fetches all preprocessing required by `consumer` and returns a ready-to-use iterator.
78    fn fetch_preprocessing_from<PB: Bundler<Iterator = Self::Iterator>>(
79        &self,
80        bundler: &mut PB,
81    ) -> Result<Self::Iterator, BundlerError> {
82        let size = self.required_preprocessing();
83        bundler.fetch(&size)
84    }
85
86    /// Prefetches all preprocessing this consumer will require. See [`Bundler::prefetch`].
87    fn prefetch_preprocessing_from<PB: Bundler<Iterator = Self::Iterator>>(
88        &self,
89        bundler: &PB,
90    ) -> PrefetchHandle<ErrorOf<Self::Iterator>> {
91        let size = self.required_preprocessing();
92        bundler.prefetch(&size)
93    }
94}
95
96/// An iterator that holds futures to all correlations required by a consumer.
97pub trait BundleIterator {
98    /// The size of the iterator, i.e., the number of correlations per type that it holds.
99    type Size: Debug + Clone + Default + Eq + Add + Sub + AddAssign + SubAssign;
100
101    /// The error type of the correlation futures held by the iterator.
102    type Error: Debug + Clone + From<CorrelatedStreamError> + Send + 'static;
103
104    /// Returns the size of the iterator, i.e., the number of correlations per type that it holds.
105    fn len(&self) -> Self::Size;
106
107    /// Returns `true` if the iterator is empty, i.e., it holds no correlations.
108    fn is_empty(&self) -> bool {
109        self.len() == Self::Size::default()
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use std::cell::Cell;
116
117    use super::*;
118
119    /// Minimal bundle whose `Size` is a plain count.
120    struct Bundle(usize);
121
122    impl BundleIterator for Bundle {
123        type Size = usize;
124        type Error = CorrelatedStreamError;
125
126        fn len(&self) -> usize {
127            self.0
128        }
129    }
130
131    /// Records what it was asked to prefetch.
132    #[derive(Default)]
133    struct Recorder(Cell<Option<usize>>);
134
135    impl Bundler for Recorder {
136        type Iterator = Bundle;
137
138        fn fetch(&mut self, size: &usize) -> Result<Bundle, BundlerError> {
139            Ok(Bundle(*size))
140        }
141
142        fn prefetch(&self, size: &usize) -> PrefetchHandle<CorrelatedStreamError> {
143            self.0.set(Some(*size));
144            PrefetchHandle::ready(Ok(()))
145        }
146    }
147
148    struct Consumer(usize);
149
150    impl BundleConsumer for Consumer {
151        type Iterator = Bundle;
152
153        fn required_preprocessing(&self) -> usize {
154            self.0
155        }
156    }
157
158    /// Both consumer-driven entry points forward the consumer's required size to the bundler.
159    #[tokio::test]
160    async fn consumer_driven_prefetch_forwards_the_required_size() {
161        let bundler = Recorder::default();
162        bundler.prefetch_for(&Consumer(11)).await.unwrap();
163        assert_eq!(bundler.0.get(), Some(11));
164
165        let bundler = Recorder::default();
166        Consumer(23)
167            .prefetch_preprocessing_from(&bundler)
168            .await
169            .unwrap();
170        assert_eq!(bundler.0.get(), Some(23));
171    }
172
173    /// `&mut B` forwards `prefetch` to `B`.
174    #[tokio::test]
175    async fn mut_ref_forwards_prefetch() {
176        let mut bundler = Recorder::default();
177        let forwarded = &mut bundler;
178        forwarded.prefetch(&5).await.unwrap();
179        assert_eq!(bundler.0.get(), Some(5));
180    }
181}