fedimint_server/consensus/aleph_bft/
network.rs

1use bitcoin::hashes::{Hash, sha256};
2use fedimint_core::config::P2PMessage;
3use fedimint_core::encoding::Encodable;
4use fedimint_core::net::peers::{DynP2PConnections, Recipient};
5use parity_scale_codec::{Decode, Encode, IoReader};
6
7use super::data_provider::UnitData;
8use super::keychain::Keychain;
9
10#[derive(Debug, Clone, Eq, PartialEq)]
11pub struct Hasher;
12
13impl aleph_bft::Hasher for Hasher {
14    type Hash = [u8; 32];
15
16    fn hash(input: &[u8]) -> Self::Hash {
17        input.consensus_hash::<sha256::Hash>().to_byte_array()
18    }
19}
20
21pub type NetworkData = aleph_bft::NetworkData<
22    Hasher,
23    UnitData,
24    <Keychain as aleph_bft::Keychain>::Signature,
25    <Keychain as aleph_bft::MultiKeychain>::PartialMultisignature,
26>;
27
28pub struct Network {
29    connections: DynP2PConnections<P2PMessage>,
30}
31
32impl Network {
33    pub fn new(connections: DynP2PConnections<P2PMessage>) -> Self {
34        Self { connections }
35    }
36}
37
38#[async_trait::async_trait]
39impl aleph_bft::Network<NetworkData> for Network {
40    fn send(&self, network_data: NetworkData, recipient: aleph_bft::Recipient) {
41        // convert from aleph_bft::Recipient to session::Recipient
42        let recipient = match recipient {
43            aleph_bft::Recipient::Node(node_index) => {
44                Recipient::Peer(super::to_peer_id(node_index))
45            }
46            aleph_bft::Recipient::Everyone => Recipient::Everyone,
47        };
48
49        self.connections
50            .try_send(recipient, P2PMessage::Aleph(network_data.encode()));
51    }
52
53    async fn next_event(&mut self) -> Option<NetworkData> {
54        loop {
55            if let P2PMessage::Aleph(bytes) = self.connections.receive().await?.1 {
56                if let Ok(network_data) = NetworkData::decode(&mut IoReader(bytes.as_slice())) {
57                    // in order to bound the RAM consumption of a session we have to bound an
58                    // individual units size, hence the size of its attached unitdata in memory
59                    if network_data.included_data().iter().all(UnitData::is_valid) {
60                        return Some(network_data);
61                    }
62                }
63            }
64        }
65    }
66}