aleph_bft/
interface.rs

1use crate::{
2    Data, DataProvider, FinalizationHandler, Hasher, OrderedUnit, UnitFinalizationHandler,
3};
4use futures::{AsyncRead, AsyncWrite};
5use std::marker::PhantomData;
6
7/// This adapter allows to map an implementation of [`FinalizationHandler`] onto implementation of [`UnitFinalizationHandler`].
8pub struct FinalizationHandlerAdapter<FH, D, H> {
9    finalization_handler: FH,
10    _phantom: PhantomData<(D, H)>,
11}
12
13impl<FH, D, H> From<FH> for FinalizationHandlerAdapter<FH, D, H> {
14    fn from(value: FH) -> Self {
15        Self {
16            finalization_handler: value,
17            _phantom: PhantomData,
18        }
19    }
20}
21
22impl<D: Data, H: Hasher, FH: FinalizationHandler<D>> UnitFinalizationHandler
23    for FinalizationHandlerAdapter<FH, D, H>
24{
25    type Data = D;
26    type Hasher = H;
27
28    fn batch_finalized(&mut self, batch: Vec<OrderedUnit<Self::Data, Self::Hasher>>) {
29        for unit in batch {
30            if let Some(data) = unit.data {
31                self.finalization_handler.data_finalized(data)
32            }
33        }
34    }
35}
36
37/// The local interface of the consensus algorithm. Contains a [`DataProvider`] as a source of data
38/// to order, a [`UnitFinalizationHandler`] for handling ordered units, and a pair of read/write
39/// structs intended for saving and restorin the state of the algorithm within the session, as a
40/// contingency in the case of a crash.
41#[derive(Clone)]
42pub struct LocalIO<DP: DataProvider, UFH: UnitFinalizationHandler, US: AsyncWrite, UL: AsyncRead> {
43    data_provider: DP,
44    finalization_handler: UFH,
45    unit_saver: US,
46    unit_loader: UL,
47}
48
49impl<
50        H: Hasher,
51        DP: DataProvider,
52        FH: FinalizationHandler<DP::Output>,
53        US: AsyncWrite,
54        UL: AsyncRead,
55    > LocalIO<DP, FinalizationHandlerAdapter<FH, DP::Output, H>, US, UL>
56{
57    /// Create a new local interface. Note that this uses the simplified, and recommended,
58    /// finalization handler that only deals with ordered data.
59    pub fn new(
60        data_provider: DP,
61        finalization_handler: FH,
62        unit_saver: US,
63        unit_loader: UL,
64    ) -> Self {
65        Self {
66            data_provider,
67            finalization_handler: finalization_handler.into(),
68            unit_saver,
69            unit_loader,
70        }
71    }
72}
73
74impl<DP: DataProvider, UFH: UnitFinalizationHandler, US: AsyncWrite, UL: AsyncRead>
75    LocalIO<DP, UFH, US, UL>
76{
77    /// Create a new local interface, providing a full implementation of a
78    /// [`UnitFinalizationHandler`].Implementing [`UnitFinalizationHandler`] directly is more
79    /// complex, and should be unnecessary for most usecases. Implement [`FinalizationHandler`]
80    /// and use `new` instead, unless you absolutely know what you are doing.
81    pub fn new_with_unit_finalization_handler(
82        data_provider: DP,
83        finalization_handler: UFH,
84        unit_saver: US,
85        unit_loader: UL,
86    ) -> Self {
87        Self {
88            data_provider,
89            finalization_handler,
90            unit_saver,
91            unit_loader,
92        }
93    }
94
95    /// Disassemble the interface into components.
96    pub fn into_components(self) -> (DP, UFH, US, UL) {
97        let LocalIO {
98            data_provider,
99            finalization_handler,
100            unit_saver,
101            unit_loader,
102        } = self;
103        (data_provider, finalization_handler, unit_saver, unit_loader)
104    }
105}