3a60b7c986c85354ee5789f8dadeaf3f3e6d519f
[rust-lightning] / lightning-rapid-gossip-sync / src / processing.rs
1 use core::cmp::max;
2 use core::ops::Deref;
3 use core::sync::atomic::Ordering;
4
5 use bitcoin::BlockHash;
6 use bitcoin::secp256k1::PublicKey;
7
8 use lightning::ln::msgs::{
9         DecodeError, ErrorAction, LightningError, UnsignedChannelUpdate,
10 };
11 use lightning::routing::gossip::NetworkGraph;
12 use lightning::util::logger::Logger;
13 use lightning::util::ser::{BigSize, Readable};
14 use lightning::io;
15
16 use crate::error::GraphSyncError;
17 use crate::RapidGossipSync;
18
19 #[cfg(not(feature = "std"))]
20 use alloc::{vec::Vec, borrow::ToOwned};
21
22 /// The purpose of this prefix is to identify the serialization format, should other rapid gossip
23 /// sync formats arise in the future.
24 ///
25 /// The fourth byte is the protocol version in case our format gets updated.
26 const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
27
28 /// Maximum vector allocation capacity for distinct node IDs. This constraint is necessary to
29 /// avoid malicious updates being able to trigger excessive memory allocation.
30 const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000;
31
32 impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
33         pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
34                 &self,
35                 mut read_cursor: &mut R,
36         ) -> Result<u32, GraphSyncError> {
37                 let mut prefix = [0u8; 4];
38                 read_cursor.read_exact(&mut prefix)?;
39
40                 match prefix {
41                         GOSSIP_PREFIX => {}
42                         _ => {
43                                 return Err(DecodeError::UnknownVersion.into());
44                         }
45                 };
46
47                 let chain_hash: BlockHash = Readable::read(read_cursor)?;
48                 let latest_seen_timestamp: u32 = Readable::read(read_cursor)?;
49                 // backdate the applied timestamp by a week
50                 let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
51
52                 let node_id_count: u32 = Readable::read(read_cursor)?;
53                 let mut node_ids: Vec<PublicKey> = Vec::with_capacity(core::cmp::min(
54                         node_id_count,
55                         MAX_INITIAL_NODE_ID_VECTOR_CAPACITY,
56                 ) as usize);
57                 for _ in 0..node_id_count {
58                         let current_node_id = Readable::read(read_cursor)?;
59                         node_ids.push(current_node_id);
60                 }
61
62                 let network_graph = &self.network_graph;
63
64                 let mut previous_scid: u64 = 0;
65                 let announcement_count: u32 = Readable::read(read_cursor)?;
66                 for _ in 0..announcement_count {
67                         let features = Readable::read(read_cursor)?;
68
69                         // handle SCID
70                         let scid_delta: BigSize = Readable::read(read_cursor)?;
71                         let short_channel_id = previous_scid
72                                 .checked_add(scid_delta.0)
73                                 .ok_or(DecodeError::InvalidValue)?;
74                         previous_scid = short_channel_id;
75
76                         let node_id_1_index: BigSize = Readable::read(read_cursor)?;
77                         let node_id_2_index: BigSize = Readable::read(read_cursor)?;
78                         if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
79                                 return Err(DecodeError::InvalidValue.into());
80                         };
81                         let node_id_1 = node_ids[node_id_1_index.0 as usize];
82                         let node_id_2 = node_ids[node_id_2_index.0 as usize];
83
84                         let announcement_result = network_graph.add_channel_from_partial_announcement(
85                                 short_channel_id,
86                                 backdated_timestamp as u64,
87                                 features,
88                                 node_id_1,
89                                 node_id_2,
90                         );
91                         if let Err(lightning_error) = announcement_result {
92                                 if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action {
93                                         // everything is fine, just a duplicate channel announcement
94                                 } else {
95                                         return Err(lightning_error.into());
96                                 }
97                         }
98                 }
99
100                 previous_scid = 0; // updates start at a new scid
101
102                 let update_count: u32 = Readable::read(read_cursor)?;
103                 if update_count == 0 {
104                         return Ok(latest_seen_timestamp);
105                 }
106
107                 // obtain default values for non-incremental updates
108                 let default_cltv_expiry_delta: u16 = Readable::read(&mut read_cursor)?;
109                 let default_htlc_minimum_msat: u64 = Readable::read(&mut read_cursor)?;
110                 let default_fee_base_msat: u32 = Readable::read(&mut read_cursor)?;
111                 let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
112                 let default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
113
114                 for _ in 0..update_count {
115                         let scid_delta: BigSize = Readable::read(read_cursor)?;
116                         let short_channel_id = previous_scid
117                                 .checked_add(scid_delta.0)
118                                 .ok_or(DecodeError::InvalidValue)?;
119                         previous_scid = short_channel_id;
120
121                         let channel_flags: u8 = Readable::read(read_cursor)?;
122
123                         // flags are always sent in full, and hence always need updating
124                         let standard_channel_flags = channel_flags & 0b_0000_0011;
125
126                         let mut synthetic_update = if channel_flags & 0b_1000_0000 == 0 {
127                                 // full update, field flags will indicate deviations from the default
128                                 UnsignedChannelUpdate {
129                                         chain_hash,
130                                         short_channel_id,
131                                         timestamp: backdated_timestamp,
132                                         flags: standard_channel_flags,
133                                         cltv_expiry_delta: default_cltv_expiry_delta,
134                                         htlc_minimum_msat: default_htlc_minimum_msat,
135                                         htlc_maximum_msat: default_htlc_maximum_msat,
136                                         fee_base_msat: default_fee_base_msat,
137                                         fee_proportional_millionths: default_fee_proportional_millionths,
138                                         excess_data: Vec::new(),
139                                 }
140                         } else {
141                                 // incremental update, field flags will indicate mutated values
142                                 let read_only_network_graph = network_graph.read_only();
143                                 let channel = read_only_network_graph
144                                         .channels()
145                                         .get(&short_channel_id)
146                                         .ok_or(LightningError {
147                                                 err: "Couldn't find channel for update".to_owned(),
148                                                 action: ErrorAction::IgnoreError,
149                                         })?;
150
151                                 let directional_info = channel
152                                         .get_directional_info(channel_flags)
153                                         .ok_or(LightningError {
154                                                 err: "Couldn't find previous directional data for update".to_owned(),
155                                                 action: ErrorAction::IgnoreError,
156                                         })?;
157
158                                 UnsignedChannelUpdate {
159                                         chain_hash,
160                                         short_channel_id,
161                                         timestamp: backdated_timestamp,
162                                         flags: standard_channel_flags,
163                                         cltv_expiry_delta: directional_info.cltv_expiry_delta,
164                                         htlc_minimum_msat: directional_info.htlc_minimum_msat,
165                                         htlc_maximum_msat: directional_info.htlc_maximum_msat,
166                                         fee_base_msat: directional_info.fees.base_msat,
167                                         fee_proportional_millionths: directional_info.fees.proportional_millionths,
168                                         excess_data: Vec::new(),
169                                 }
170                         };
171
172                         if channel_flags & 0b_0100_0000 > 0 {
173                                 let cltv_expiry_delta: u16 = Readable::read(read_cursor)?;
174                                 synthetic_update.cltv_expiry_delta = cltv_expiry_delta;
175                         }
176
177                         if channel_flags & 0b_0010_0000 > 0 {
178                                 let htlc_minimum_msat: u64 = Readable::read(read_cursor)?;
179                                 synthetic_update.htlc_minimum_msat = htlc_minimum_msat;
180                         }
181
182                         if channel_flags & 0b_0001_0000 > 0 {
183                                 let fee_base_msat: u32 = Readable::read(read_cursor)?;
184                                 synthetic_update.fee_base_msat = fee_base_msat;
185                         }
186
187                         if channel_flags & 0b_0000_1000 > 0 {
188                                 let fee_proportional_millionths: u32 = Readable::read(read_cursor)?;
189                                 synthetic_update.fee_proportional_millionths = fee_proportional_millionths;
190                         }
191
192                         if channel_flags & 0b_0000_0100 > 0 {
193                                 let htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
194                                 synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
195                         }
196
197                         network_graph.update_channel_unsigned(&synthetic_update)?;
198                 }
199
200                 self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
201                 self.is_initial_sync_complete.store(true, Ordering::Release);
202                 Ok(latest_seen_timestamp)
203         }
204 }
205
206 #[cfg(test)]
207 mod tests {
208         use bitcoin::blockdata::constants::genesis_block;
209         use bitcoin::Network;
210
211         use lightning::ln::msgs::DecodeError;
212         use lightning::routing::gossip::NetworkGraph;
213         use lightning::util::test_utils::TestLogger;
214
215         use crate::error::GraphSyncError;
216         use crate::RapidGossipSync;
217
218         #[test]
219         fn network_graph_fails_to_update_from_clipped_input() {
220                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
221                 let logger = TestLogger::new();
222                 let network_graph = NetworkGraph::new(block_hash, &logger);
223
224                 let example_input = vec![
225                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
226                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
227                         0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
228                         187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
229                         157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
230                         88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
231                         204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
232                         181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
233                         110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
234                         76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
235                         226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 2, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 0, 100,
236                         0, 0, 2, 224, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 36, 0, 0,
237                         0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1, 24, 0,
238                         0, 3, 232, 0, 0, 0,
239                 ];
240                 let rapid_sync = RapidGossipSync::new(&network_graph);
241                 let update_result = rapid_sync.update_network_graph(&example_input[..]);
242                 assert!(update_result.is_err());
243                 if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
244                         // this is the expected error type
245                 } else {
246                         panic!("Unexpected update result: {:?}", update_result)
247                 }
248         }
249
250         #[test]
251         fn incremental_only_update_fails_without_prior_announcements() {
252                 let incremental_update_input = vec![
253                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
254                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
255                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256                         0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255, 2,
257                         68, 226, 0, 6, 11, 0, 1, 128,
258                 ];
259
260                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
261                 let logger = TestLogger::new();
262                 let network_graph = NetworkGraph::new(block_hash, &logger);
263
264                 assert_eq!(network_graph.read_only().channels().len(), 0);
265
266                 let rapid_sync = RapidGossipSync::new(&network_graph);
267                 let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
268                 assert!(update_result.is_err());
269                 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
270                         assert_eq!(lightning_error.err, "Couldn't find channel for update");
271                 } else {
272                         panic!("Unexpected update result: {:?}", update_result)
273                 }
274         }
275
276         #[test]
277         fn incremental_only_update_fails_without_prior_updates() {
278                 let announced_update_input = vec![
279                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
280                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
281                         0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
282                         187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
283                         157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
284                         88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
285                         204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
286                         181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
287                         110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
288                         76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
289                         226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255,
291                         2, 68, 226, 0, 6, 11, 0, 1, 128,
292                 ];
293
294                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
295                 let logger = TestLogger::new();
296                 let network_graph = NetworkGraph::new(block_hash, &logger);
297
298                 assert_eq!(network_graph.read_only().channels().len(), 0);
299
300                 let rapid_sync = RapidGossipSync::new(&network_graph);
301                 let update_result = rapid_sync.update_network_graph(&announced_update_input[..]);
302                 assert!(update_result.is_err());
303                 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
304                         assert_eq!(
305                                 lightning_error.err,
306                                 "Couldn't find previous directional data for update"
307                         );
308                 } else {
309                         panic!("Unexpected update result: {:?}", update_result)
310                 }
311         }
312
313         #[test]
314         fn incremental_only_update_fails_without_prior_same_direction_updates() {
315                 let initialization_input = vec![
316                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
317                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
318                         0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
319                         187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
320                         157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
321                         88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
322                         204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
323                         181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
324                         110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
325                         76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
326                         226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 2, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232,
327                         0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0,
328                         0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192,
329                 ];
330
331                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
332                 let logger = TestLogger::new();
333                 let network_graph = NetworkGraph::new(block_hash, &logger);
334
335                 assert_eq!(network_graph.read_only().channels().len(), 0);
336
337                 let rapid_sync = RapidGossipSync::new(&network_graph);
338                 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
339                 if initialization_result.is_err() {
340                         panic!(
341                                 "Unexpected initialization result: {:?}",
342                                 initialization_result
343                         )
344                 }
345
346                 assert_eq!(network_graph.read_only().channels().len(), 2);
347                 let initialized = network_graph.to_string();
348                 assert!(initialized
349                         .contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643"));
350                 assert!(initialized
351                         .contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b"));
352                 assert!(initialized
353                         .contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432"));
354                 assert!(initialized
355                         .contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61"));
356                 assert!(initialized.contains("619737530008010752"));
357                 assert!(initialized.contains("783241506229452801"));
358
359                 let opposite_direction_incremental_update_input = vec![
360                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
361                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
362                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
363                         0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255, 2,
364                         68, 226, 0, 6, 11, 0, 1, 128,
365                 ];
366                 let update_result = rapid_sync.update_network_graph(&opposite_direction_incremental_update_input[..]);
367                 assert!(update_result.is_err());
368                 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
369                         assert_eq!(
370                                 lightning_error.err,
371                                 "Couldn't find previous directional data for update"
372                         );
373                 } else {
374                         panic!("Unexpected update result: {:?}", update_result)
375                 }
376         }
377
378         #[test]
379         fn incremental_update_succeeds_with_prior_announcements_and_full_updates() {
380                 let initialization_input = vec![
381                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
382                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
383                         0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
384                         187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
385                         157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
386                         88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
387                         204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
388                         181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
389                         110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
390                         76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
391                         226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232,
392                         0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
393                         0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, 0, 25, 0, 0, 0, 1, 0, 0, 0, 125, 255, 2,
394                         68, 226, 0, 6, 11, 0, 1, 4, 0, 0, 0, 0, 29, 129, 25, 192, 0, 5, 0, 0, 0, 0, 29, 129,
395                         25, 192,
396                 ];
397
398                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
399                 let logger = TestLogger::new();
400                 let network_graph = NetworkGraph::new(block_hash, &logger);
401
402                 assert_eq!(network_graph.read_only().channels().len(), 0);
403
404                 let rapid_sync = RapidGossipSync::new(&network_graph);
405                 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
406                 assert!(initialization_result.is_ok());
407
408                 let single_direction_incremental_update_input = vec![
409                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
410                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
411                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
412                         0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 136, 0, 0, 0, 221, 255, 2,
413                         68, 226, 0, 6, 11, 0, 1, 128,
414                 ];
415                 let update_result = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
416                 if update_result.is_err() {
417                         panic!("Unexpected update result: {:?}", update_result)
418                 }
419
420                 assert_eq!(network_graph.read_only().channels().len(), 2);
421                 let after = network_graph.to_string();
422                 assert!(
423                         after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
424                 );
425                 assert!(
426                         after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
427                 );
428                 assert!(
429                         after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
430                 );
431                 assert!(
432                         after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
433                 );
434                 assert!(after.contains("619737530008010752"));
435                 assert!(after.contains("783241506229452801"));
436         }
437
438         #[test]
439         fn full_update_succeeds() {
440                 let valid_input = vec![
441                         76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
442                         79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
443                         0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
444                         187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
445                         157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
446                         88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
447                         204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
448                         181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
449                         110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
450                         76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
451                         226, 0, 6, 11, 0, 1, 2, 3, 0, 0, 0, 4, 0, 40, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, 3, 232,
452                         0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
453                         0, 0, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 2, 224, 0, 0, 0, 0, 58, 85, 116, 216, 0, 29, 0,
454                         0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
455                         0, 0, 1,
456                 ];
457
458                 let block_hash = genesis_block(Network::Bitcoin).block_hash();
459                 let logger = TestLogger::new();
460                 let network_graph = NetworkGraph::new(block_hash, &logger);
461
462                 assert_eq!(network_graph.read_only().channels().len(), 0);
463
464                 let rapid_sync = RapidGossipSync::new(&network_graph);
465                 let update_result = rapid_sync.update_network_graph(&valid_input[..]);
466                 if update_result.is_err() {
467                         panic!("Unexpected update result: {:?}", update_result)
468                 }
469
470                 assert_eq!(network_graph.read_only().channels().len(), 2);
471                 let after = network_graph.to_string();
472                 assert!(
473                         after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
474                 );
475                 assert!(
476                         after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
477                 );
478                 assert!(
479                         after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
480                 );
481                 assert!(
482                         after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
483                 );
484                 assert!(after.contains("619737530008010752"));
485                 assert!(after.contains("783241506229452801"));
486         }
487 }