1use crate::{alerts::AlertMessage, Data, Hasher, PartialMultisignature, Recipient, Signature};
2use codec::{Decode, Encode};
3use std::fmt::Debug;
4
5mod hub;
6mod unit;
7
8pub use hub::Hub;
9pub use unit::UnitMessage;
10
11pub type UnitMessageTo<H, D, S> = (UnitMessage<H, D, S>, Recipient);
12
13#[derive(Clone, Eq, PartialEq, Debug, Decode, Encode)]
14pub(crate) enum NetworkDataInner<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> {
15 Units(UnitMessage<H, D, S>),
16 Alert(AlertMessage<H, D, S, MS>),
17}
18
19impl<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> NetworkDataInner<H, D, S, MS> {
20 pub(crate) fn included_data(&self) -> Vec<D> {
21 match self {
22 Self::Units(message) => message.included_data(),
23 Self::Alert(message) => message.included_data(),
24 }
25 }
26}
27
28#[derive(Clone, Eq, PartialEq, Debug, Decode, Encode)]
30pub struct NetworkData<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature>(
31 pub(crate) NetworkDataInner<H, D, S, MS>,
32);
33
34impl<H: Hasher, D: Data, S: Signature, MS: PartialMultisignature> NetworkData<H, D, S, MS> {
35 pub fn included_data(&self) -> Vec<D> {
40 self.0.included_data()
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::{
47 alerts::AlertMessage,
48 network::{
49 NetworkDataInner::{Alert, Units},
50 UnitMessage,
51 },
52 units::{ControlHash, FullUnit, PreUnit, UncheckedSignedUnit, UnitCoord},
53 Hasher, NodeIndex, Round, Signed,
54 };
55 use aleph_bft_mock::{Data, Hasher64, Keychain, PartialMultisignature, Signature};
56 use aleph_bft_types::NodeMap;
57 use codec::{Decode, Encode};
58
59 fn test_unchecked_unit(
60 creator: NodeIndex,
61 round: Round,
62 data: Data,
63 ) -> UncheckedSignedUnit<Hasher64, Data, Signature> {
64 let control_hash = ControlHash::new(&NodeMap::with_size(7.into()));
65 let pu = PreUnit::new(creator, round, control_hash);
66 let signable = FullUnit::new(pu, Some(data), 0);
67 Signed::sign(signable, &Keychain::new(0.into(), creator)).into_unchecked()
68 }
69
70 type TestNetworkData = super::NetworkData<Hasher64, Data, Signature, PartialMultisignature>;
71 impl TestNetworkData {
72 fn new(
73 inner: super::NetworkDataInner<Hasher64, Data, Signature, PartialMultisignature>,
74 ) -> Self {
75 super::NetworkData::<Hasher64, Data, Signature, PartialMultisignature>(inner)
76 }
77 }
78
79 #[test]
80 fn decoding_network_data_units_new_unit() {
81 use UnitMessage::Unit;
82
83 let uu = test_unchecked_unit(5.into(), 43, 1729);
84 let included_data = uu.as_signable().included_data();
85 let nd = TestNetworkData::new(Units(Unit(uu.clone())));
86 let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
87 assert!(decoded.is_ok(), "Bug in encode/decode for Unit");
88 let decoded = decoded.unwrap();
89 assert_eq!(
90 decoded.included_data(),
91 included_data,
92 "data decoded incorrectly"
93 );
94 if let Units(Unit(decoded_unchecked)) = decoded.0 {
95 assert_eq!(
96 uu.as_signable(),
97 decoded_unchecked.as_signable(),
98 "decoded should equal encoded"
99 );
100 } else {
101 panic!("Decoded Unit as something else");
102 }
103 }
104
105 #[test]
106 fn decoding_network_data_units_request_coord() {
107 use UnitMessage::CoordRequest;
108
109 let ni = 7.into();
110 let uc = UnitCoord::new(3, 13.into());
111 let nd = TestNetworkData::new(Units(CoordRequest(ni, uc)));
112 let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
113 assert!(decoded.is_ok(), "Bug in encode/decode for CoordRequest");
114 let decoded = decoded.unwrap();
115 assert!(
116 decoded.included_data().is_empty(),
117 "data returned from a coord request"
118 );
119 if let Units(CoordRequest(dni, duc)) = decoded.0 {
120 assert!(ni == dni && uc == duc, "decoded should equal encoded");
121 } else {
122 panic!("Decoded CoordRequest as something else");
123 }
124 }
125
126 #[test]
127 fn decoding_network_data_units_request_parents() {
128 use UnitMessage::ParentsRequest;
129
130 let ni = 7.into();
131 let h = 43.using_encoded(Hasher64::hash);
132 let nd = TestNetworkData::new(Units(ParentsRequest(ni, h)));
133 let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
134 assert!(decoded.is_ok(), "Bug in encode/decode for ParentsRequest");
135 let decoded = decoded.unwrap();
136 assert!(
137 decoded.included_data().is_empty(),
138 "data returned from a parent request"
139 );
140 if let Units(ParentsRequest(dni, dh)) = decoded.0 {
141 assert!(ni == dni && h == dh, "decoded should equal encoded");
142 } else {
143 panic!("Decoded ParentsRequest as something else");
144 }
145 }
146
147 #[test]
148 fn decoding_network_data_units_response_parents() {
149 use UnitMessage::ParentsResponse;
150
151 let h = 43.using_encoded(Hasher64::hash);
152 let p1 = test_unchecked_unit(5.into(), 43, 1729);
153 let p2 = test_unchecked_unit(13.into(), 43, 1729);
154 let p3 = test_unchecked_unit(17.into(), 43, 1729);
155 let included_data: Vec<Data> = p1
156 .as_signable()
157 .included_data()
158 .into_iter()
159 .chain(p2.as_signable().included_data())
160 .chain(p3.as_signable().included_data())
161 .collect();
162 let parents = vec![p1, p2, p3];
163
164 let nd = TestNetworkData::new(Units(ParentsResponse(h, parents.clone())));
165 let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
166 assert!(decoded.is_ok(), "Bug in encode/decode for ParentsResponse");
167 let decoded = decoded.unwrap();
168 assert_eq!(
169 decoded.included_data(),
170 included_data,
171 "data decoded incorrectly"
172 );
173 if let Units(ParentsResponse(dh, dparents)) = decoded.0 {
174 assert_eq!(h, dh, "decoded should equal encoded");
175 assert_eq!(
176 parents.len(),
177 dparents.len(),
178 "decoded should equal encoded"
179 );
180 for (p, dp) in parents.iter().zip(dparents.iter()) {
181 assert_eq!(
182 p.as_signable(),
183 dp.as_signable(),
184 "decoded should equal encoded"
185 );
186 }
187 } else {
188 panic!("Decoded ParentsResponse as something else");
189 }
190 }
191
192 #[test]
193 fn decoding_network_data_alert_fork_alert() {
194 use AlertMessage::ForkAlert;
195
196 let forker = 9.into();
197 let f1 = test_unchecked_unit(forker, 10, 0);
198 let f2 = test_unchecked_unit(forker, 10, 1);
199 let lu1 = test_unchecked_unit(forker, 11, 0);
200 let lu2 = test_unchecked_unit(forker, 12, 0);
201 let mut included_data = lu1.as_signable().included_data();
202 included_data.extend(lu2.as_signable().included_data());
203 let sender: NodeIndex = 7.into();
204 let alert = crate::alerts::Alert::new(sender, (f1, f2), vec![lu1, lu2]);
205
206 let nd = TestNetworkData::new(Alert(ForkAlert(
207 Signed::sign(alert.clone(), &Keychain::new(0.into(), sender)).into_unchecked(),
208 )));
209 let decoded = TestNetworkData::decode(&mut &nd.encode()[..]);
210 assert!(decoded.is_ok(), "Bug in encode/decode for ForkAlert");
211 let decoded = decoded.unwrap();
212 assert_eq!(
213 decoded.included_data(),
214 included_data,
215 "data decoded incorrectly"
216 );
217 if let Alert(ForkAlert(unchecked_alert)) = decoded.0 {
218 assert_eq!(
219 &alert,
220 unchecked_alert.as_signable(),
221 "decoded should equal encoded"
222 )
223 } else {
224 panic!("Decoded ForkAlert as something else");
225 }
226 }
227}