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