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