hbbft/src/transaction_queue.rs

54 lines
1.8 KiB
Rust

//! An interface for a transaction queue
use std::collections::HashSet;
use std::{cmp, fmt};
use rand::{self, seq::SliceRandom, Rng};
use crate::Contribution;
/// An interface to the transaction queue. A transaction queue is a structural part of
/// `QueueingHoneyBadger` that manages enqueueing of transactions for a future batch and dequeueing
/// of transactions to become part of a current batch.
pub trait TransactionQueue<T>: fmt::Debug + Default + Extend<T> + Sync + Send {
/// Checks whether the queue is empty.
fn is_empty(&self) -> bool;
/// Returns a new set of `amount` transactions, randomly chosen from the first `batch_size`.
/// No transactions are removed from the queue.
// TODO: Return references, once the `HoneyBadger` API accepts them.
fn choose<R: Rng>(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec<T>;
/// Removes the given transactions from the queue.
fn remove_multiple<'a, I>(&mut self, txs: I)
where
I: IntoIterator<Item = &'a T>,
T: 'a + Contribution;
}
impl<T> TransactionQueue<T> for Vec<T>
where
T: Clone + fmt::Debug + Sync + Send,
{
#[inline]
fn is_empty(&self) -> bool {
self.is_empty()
}
#[inline]
fn remove_multiple<'a, I>(&mut self, txs: I)
where
I: IntoIterator<Item = &'a T>,
T: 'a + Contribution,
{
let tx_set: HashSet<_> = txs.into_iter().collect();
self.retain(|tx| !tx_set.contains(tx));
}
// TODO: Return references, once the `HoneyBadger` API accepts them. Remove `Clone` bound.
#[inline]
fn choose<R: Rng>(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec<T> {
let limit = cmp::min(batch_size, self.len());
let sample = self[..limit].choose_multiple(rng, amount);
sample.cloned().collect()
}
}