bft_bench_core/bft_binding.rs
1use async_trait::async_trait;
2
3use bytes::Bytes;
4use rand::{RngCore, rngs::ThreadRng};
5use uuid::Uuid;
6
7use {crate::config::*, crate::result::*};
8
9/// A [`BftBinding`] can be stateful; it provides a [`new`](BftBinding::new) constructor and
10/// [`access`](BftBinding::access) to a [`Node`]. Depending on the type of node, access can
11/// be read-write or write-only.
12#[async_trait]
13pub trait BftBinding {
14 type Writer: BftWriter;
15 type Reader: BftReader;
16
17 fn new(config: &Config) -> Self;
18 async fn access(&mut self, node: Node) -> NodeAccess<Self::Writer, Self::Reader>;
19}
20
21pub enum NodeAccess<Writer: BftWriter, Reader: BftReader> {
22 ReadWriteAccess { writer: Writer, reader: Reader },
23 WriteOnlyAccess { writer: Writer },
24}
25
26/// A [`BftWriter`] allows to write a key-value pair to a node. It must be [`Clone`] because
27/// writes to a single node are scheduled at regular intervals, without waiting for previous
28/// writes to terminate, thus, writes to the same node can happen concurrently. The framework
29/// avoids locking as much as possible and requires thus cloneability. The binding is however
30/// free to implement cloneability with locking, i.e., with [`std::sync::Arc`] and a mutex.
31#[async_trait]
32pub trait BftWriter: Send + Clone {
33 async fn write(&mut self, key: Uuid) -> Result<()>;
34}
35
36/// A [`BftReader`] allows to read a key from a node. A BFT library/platform is expected to
37/// provide BFT ordering functionality, i.e., all nodes should provide a consistent ordering
38/// of written data to all readers, including when byzantine nodes are present.
39///
40/// BFT properties can vary but most private-network BFT protocols guarantee consistent
41/// ordering when at least `2f + 1` nodes are honest, where `f` is the maximum number
42/// of dishonest nodes.
43#[async_trait]
44pub trait BftReader: Send {
45 async fn read(&mut self) -> Result<Option<Uuid>>;
46}
47
48pub fn create_random_value(rng: &mut ThreadRng, value_size: usize) -> Bytes {
49 let mut value = vec![0u8; value_size];
50 rng.fill_bytes(&mut value);
51 log::debug!("Random value of size {} generated", value_size);
52 Bytes::from(value)
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_create_value() {
61 let mut rng = rand::rng();
62 assert_eq!(create_random_value(&mut rng, 2).len(), 2)
63 }
64}