use crate::{
alerts::AlertMessage, member::UnitMessage, Data, Hasher, PartialMultisignature, Signature,
};
use codec::{Decode, Encode};
use std::fmt::Debug;
mod hub;
pub use hub::Hub;
#[derive(Clone, Eq, PartialEq, Debug, Decode, Encode)]
pub(crate) enum NetworkDataInner<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> {
Units(UnitMessage<H, D, S>),
Alert(AlertMessage<H, D, S, MS>),
}
impl<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> NetworkDataInner<H, D, S, MS> {
pub(crate) fn included_data(&self) -> Vec<D> {
match self {
Self::Units(message) => message.included_data(),
Self::Alert(message) => message.included_data(),
}
}
}
#[derive(Clone, Eq, PartialEq, Debug, Decode, Encode)]
pub struct NetworkData<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature>(
pub(crate) NetworkDataInner<H, D, S, MS>,
);
impl<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> NetworkData<H, D, S, MS> {
pub fn included_data(&self) -> Vec<D> {
self.0.included_data()
}
}
#[cfg(test)]
mod tests {
use crate::{
alerts::AlertMessage,
member::UnitMessage,
network::NetworkDataInner::{Alert, Units},
units::{ControlHash, FullUnit, PreUnit, UncheckedSignedUnit, UnitCoord},
Hasher, NodeIndex, Round, Signed,
};
use aleph_bft_mock::{Data, Hasher64, Keychain, PartialMultisignature, Signature};
use aleph_bft_types::NodeMap;
use codec::{Decode, Encode};
fn test_unchecked_unit(
creator: NodeIndex,
round: Round,
data: Data,
) -> UncheckedSignedUnit<Hasher64, Data, Signature> {
let control_hash = ControlHash::new(&NodeMap::with_size(7.into()));
let pu = PreUnit::new(creator, round, control_hash);
let signable = FullUnit::new(pu, Some(data), 0);
Signed::sign(signable, &Keychain::new(0.into(), creator)).into_unchecked()
}
type TestNetworkData = super::NetworkData<Hasher64, Data, Signature, PartialMultisignature>;
impl TestNetworkData {
fn new(
inner: super::NetworkDataInner<Hasher64, Data, Signature, PartialMultisignature>,
) -> Self {
super::NetworkData::<Hasher64, Data, Signature, PartialMultisignature>(inner)
}
}
#[test]
fn decoding_network_data_units_new_unit() {
use UnitMessage::NewUnit;
let uu = test_unchecked_unit(5.into(), 43, 1729);
let included_data = uu.as_signable().included_data();
let nd = TestNetworkData::new(Units(NewUnit(uu.clone())));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for NewUnit");
let decoded = decoded.unwrap();
assert_eq!(
decoded.included_data(),
included_data,
"data decoded incorrectly"
);
if let Units(NewUnit(decoded_unchecked)) = decoded.0 {
assert_eq!(
uu.as_signable(),
decoded_unchecked.as_signable(),
"decoded should equal encoded"
);
} else {
panic!("Decoded NewUnit as something else");
}
}
#[test]
fn decoding_network_data_units_request_coord() {
use UnitMessage::RequestCoord;
let ni = 7.into();
let uc = UnitCoord::new(3, 13.into());
let nd = TestNetworkData::new(Units(RequestCoord(ni, uc)));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for RequestCoord");
let decoded = decoded.unwrap();
assert!(
decoded.included_data().is_empty(),
"data returned from a coord request"
);
if let Units(RequestCoord(dni, duc)) = decoded.0 {
assert!(ni == dni && uc == duc, "decoded should equal encoded");
} else {
panic!("Decoded RequestCoord as something else");
}
}
#[test]
fn decoding_network_data_units_response_coord() {
use UnitMessage::ResponseCoord;
let uu = test_unchecked_unit(5.into(), 43, 1729);
let included_data = uu.as_signable().included_data();
let nd = TestNetworkData::new(Units(ResponseCoord(uu.clone())));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for ResponseCoord");
let decoded = decoded.unwrap();
assert_eq!(
decoded.included_data(),
included_data,
"data decoded incorrectly"
);
if let Units(ResponseCoord(decoded_unchecked)) = decoded.0 {
assert_eq!(
uu.as_signable(),
decoded_unchecked.as_signable(),
"decoded should equal encoded"
);
} else {
panic!("Decoded ResponseCoord as something else");
}
}
#[test]
fn decoding_network_data_units_request_parents() {
use UnitMessage::RequestParents;
let ni = 7.into();
let h = 43.using_encoded(Hasher64::hash);
let nd = TestNetworkData::new(Units(RequestParents(ni, h)));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for RequestParents");
let decoded = decoded.unwrap();
assert!(
decoded.included_data().is_empty(),
"data returned from a parent request"
);
if let Units(RequestParents(dni, dh)) = decoded.0 {
assert!(ni == dni && h == dh, "decoded should equal encoded");
} else {
panic!("Decoded RequestParents as something else");
}
}
#[test]
fn decoding_network_data_units_response_parents() {
use UnitMessage::ResponseParents;
let h = 43.using_encoded(Hasher64::hash);
let p1 = test_unchecked_unit(5.into(), 43, 1729);
let p2 = test_unchecked_unit(13.into(), 43, 1729);
let p3 = test_unchecked_unit(17.into(), 43, 1729);
let included_data: Vec<Data> = p1
.as_signable()
.included_data()
.into_iter()
.chain(p2.as_signable().included_data())
.chain(p3.as_signable().included_data())
.collect();
let parents = vec![p1, p2, p3];
let nd = TestNetworkData::new(Units(ResponseParents(h, parents.clone())));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for ResponseParents");
let decoded = decoded.unwrap();
assert_eq!(
decoded.included_data(),
included_data,
"data decoded incorrectly"
);
if let Units(ResponseParents(dh, dparents)) = decoded.0 {
assert_eq!(h, dh, "decoded should equal encoded");
assert_eq!(
parents.len(),
dparents.len(),
"decoded should equal encoded"
);
for (p, dp) in parents.iter().zip(dparents.iter()) {
assert_eq!(
p.as_signable(),
dp.as_signable(),
"decoded should equal encoded"
);
}
} else {
panic!("Decoded ResponseParents as something else");
}
}
#[test]
fn decoding_network_data_alert_fork_alert() {
use AlertMessage::ForkAlert;
let forker = 9.into();
let f1 = test_unchecked_unit(forker, 10, 0);
let f2 = test_unchecked_unit(forker, 10, 1);
let lu1 = test_unchecked_unit(forker, 11, 0);
let lu2 = test_unchecked_unit(forker, 12, 0);
let mut included_data = lu1.as_signable().included_data();
included_data.extend(lu2.as_signable().included_data());
let sender: NodeIndex = 7.into();
let alert = crate::alerts::Alert::new(sender, (f1, f2), vec![lu1, lu2]);
let nd = TestNetworkData::new(Alert(ForkAlert(
Signed::sign(alert.clone(), &Keychain::new(0.into(), sender)).into_unchecked(),
)));
let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
assert!(decoded.is_ok(), "Bug in encode/decode for ForkAlert");
let decoded = decoded.unwrap();
assert_eq!(
decoded.included_data(),
included_data,
"data decoded incorrectly"
);
if let Alert(ForkAlert(unchecked_alert)) = decoded.0 {
assert_eq!(
&alert,
unchecked_alert.as_signable(),
"decoded should equal encoded"
)
} else {
panic!("Decoded ForkAlert as something else");
}
}
}