Skip to main content

fedimint_hbbft/
transaction_queue.rs

1//! An interface for a transaction queue
2
3use std::collections::HashSet;
4use std::{cmp, fmt};
5
6use rand::{self, seq::SliceRandom, Rng};
7
8use crate::Contribution;
9
10/// An interface to the transaction queue. A transaction queue is a structural part of
11/// `QueueingHoneyBadger` that manages enqueueing of transactions for a future batch and dequeueing
12/// of transactions to become part of a current batch.
13pub trait TransactionQueue<T>: fmt::Debug + Default + Extend<T> + Sync + Send {
14    /// Checks whether the queue is empty.
15    fn is_empty(&self) -> bool;
16    /// Returns a new set of `amount` transactions, randomly chosen from the first `batch_size`.
17    /// No transactions are removed from the queue.
18    // TODO: Return references, once the `HoneyBadger` API accepts them.
19    fn choose<R: Rng>(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec<T>;
20    /// Removes the given transactions from the queue.
21    fn remove_multiple<'a, I>(&mut self, txs: I)
22    where
23        I: IntoIterator<Item = &'a T>,
24        T: 'a + Contribution;
25}
26
27impl<T> TransactionQueue<T> for Vec<T>
28where
29    T: Clone + fmt::Debug + Sync + Send,
30{
31    #[inline]
32    fn is_empty(&self) -> bool {
33        self.is_empty()
34    }
35
36    #[inline]
37    fn remove_multiple<'a, I>(&mut self, txs: I)
38    where
39        I: IntoIterator<Item = &'a T>,
40        T: 'a + Contribution,
41    {
42        let tx_set: HashSet<_> = txs.into_iter().collect();
43        self.retain(|tx| !tx_set.contains(tx));
44    }
45
46    // TODO: Return references, once the `HoneyBadger` API accepts them. Remove `Clone` bound.
47    #[inline]
48    fn choose<R: Rng>(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec<T> {
49        let limit = cmp::min(batch_size, self.len());
50        let sample = self[..limit].choose_multiple(rng, amount);
51        sample.cloned().collect()
52    }
53}