5 use std::sync::atomic::Ordering;
7 use bitcoin::BlockHash;
8 use bitcoin::secp256k1::PublicKey;
10 use lightning::ln::msgs::{
11 DecodeError, ErrorAction, LightningError, OptionalField, UnsignedChannelUpdate,
13 use lightning::routing::network_graph::NetworkGraph;
14 use lightning::util::ser::{BigSize, Readable};
16 use crate::error::GraphSyncError;
17 use crate::RapidGossipSync;
19 /// The purpose of this prefix is to identify the serialization format, should other rapid gossip
20 /// sync formats arise in the future.
22 /// The fourth byte is the protocol version in case our format gets updated.
23 const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
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;
29 impl<NG: Deref<Target=NetworkGraph>> RapidGossipSync<NG> {
30 /// Update network graph from binary data.
31 /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
33 /// `network_graph`: network graph to be updated
35 /// `update_data`: `&[u8]` binary stream that comprises the update data
36 pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
37 let mut read_cursor = io::Cursor::new(update_data);
38 self.update_network_graph_from_byte_stream(&mut read_cursor)
42 pub(crate) fn update_network_graph_from_byte_stream<R: Read>(
44 mut read_cursor: &mut R,
45 ) -> Result<u32, GraphSyncError> {
46 let mut prefix = [0u8; 4];
47 read_cursor.read_exact(&mut prefix)?;
52 return Err(DecodeError::UnknownVersion.into());
56 let chain_hash: BlockHash = Readable::read(read_cursor)?;
57 let latest_seen_timestamp: u32 = Readable::read(read_cursor)?;
58 // backdate the applied timestamp by a week
59 let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
61 let node_id_count: u32 = Readable::read(read_cursor)?;
62 let mut node_ids: Vec<PublicKey> = Vec::with_capacity(std::cmp::min(
64 MAX_INITIAL_NODE_ID_VECTOR_CAPACITY,
66 for _ in 0..node_id_count {
67 let current_node_id = Readable::read(read_cursor)?;
68 node_ids.push(current_node_id);
71 let network_graph = &self.network_graph;
73 let mut previous_scid: u64 = 0;
74 let announcement_count: u32 = Readable::read(read_cursor)?;
75 for _ in 0..announcement_count {
76 let features = Readable::read(read_cursor)?;
79 let scid_delta: BigSize = Readable::read(read_cursor)?;
80 let short_channel_id = previous_scid
81 .checked_add(scid_delta.0)
82 .ok_or(DecodeError::InvalidValue)?;
83 previous_scid = short_channel_id;
85 let node_id_1_index: BigSize = Readable::read(read_cursor)?;
86 let node_id_2_index: BigSize = Readable::read(read_cursor)?;
87 if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
88 return Err(DecodeError::InvalidValue.into());
90 let node_id_1 = node_ids[node_id_1_index.0 as usize];
91 let node_id_2 = node_ids[node_id_2_index.0 as usize];
93 let announcement_result = network_graph.add_channel_from_partial_announcement(
95 backdated_timestamp as u64,
100 if let Err(lightning_error) = announcement_result {
101 if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action {
102 // everything is fine, just a duplicate channel announcement
104 return Err(lightning_error.into());
109 previous_scid = 0; // updates start at a new scid
111 let update_count: u32 = Readable::read(read_cursor)?;
112 if update_count == 0 {
113 return Ok(latest_seen_timestamp);
116 // obtain default values for non-incremental updates
117 let default_cltv_expiry_delta: u16 = Readable::read(&mut read_cursor)?;
118 let default_htlc_minimum_msat: u64 = Readable::read(&mut read_cursor)?;
119 let default_fee_base_msat: u32 = Readable::read(&mut read_cursor)?;
120 let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
121 let tentative_default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
122 let default_htlc_maximum_msat = if tentative_default_htlc_maximum_msat == u64::max_value() {
123 OptionalField::Absent
125 OptionalField::Present(tentative_default_htlc_maximum_msat)
128 for _ in 0..update_count {
129 let scid_delta: BigSize = Readable::read(read_cursor)?;
130 let short_channel_id = previous_scid
131 .checked_add(scid_delta.0)
132 .ok_or(DecodeError::InvalidValue)?;
133 previous_scid = short_channel_id;
135 let channel_flags: u8 = Readable::read(read_cursor)?;
137 // flags are always sent in full, and hence always need updating
138 let standard_channel_flags = channel_flags & 0b_0000_0011;
140 let mut synthetic_update = if channel_flags & 0b_1000_0000 == 0 {
141 // full update, field flags will indicate deviations from the default
142 UnsignedChannelUpdate {
145 timestamp: backdated_timestamp,
146 flags: standard_channel_flags,
147 cltv_expiry_delta: default_cltv_expiry_delta,
148 htlc_minimum_msat: default_htlc_minimum_msat,
149 htlc_maximum_msat: default_htlc_maximum_msat.clone(),
150 fee_base_msat: default_fee_base_msat,
151 fee_proportional_millionths: default_fee_proportional_millionths,
155 // incremental update, field flags will indicate mutated values
156 let read_only_network_graph = network_graph.read_only();
157 let channel = read_only_network_graph
159 .get(&short_channel_id)
160 .ok_or(LightningError {
161 err: "Couldn't find channel for update".to_owned(),
162 action: ErrorAction::IgnoreError,
165 let directional_info = channel
166 .get_directional_info(channel_flags)
167 .ok_or(LightningError {
168 err: "Couldn't find previous directional data for update".to_owned(),
169 action: ErrorAction::IgnoreError,
172 let htlc_maximum_msat =
173 if let Some(htlc_maximum_msat) = directional_info.htlc_maximum_msat {
174 OptionalField::Present(htlc_maximum_msat)
176 OptionalField::Absent
179 UnsignedChannelUpdate {
182 timestamp: backdated_timestamp,
183 flags: standard_channel_flags,
184 cltv_expiry_delta: directional_info.cltv_expiry_delta,
185 htlc_minimum_msat: directional_info.htlc_minimum_msat,
187 fee_base_msat: directional_info.fees.base_msat,
188 fee_proportional_millionths: directional_info.fees.proportional_millionths,
193 if channel_flags & 0b_0100_0000 > 0 {
194 let cltv_expiry_delta: u16 = Readable::read(read_cursor)?;
195 synthetic_update.cltv_expiry_delta = cltv_expiry_delta;
198 if channel_flags & 0b_0010_0000 > 0 {
199 let htlc_minimum_msat: u64 = Readable::read(read_cursor)?;
200 synthetic_update.htlc_minimum_msat = htlc_minimum_msat;
203 if channel_flags & 0b_0001_0000 > 0 {
204 let fee_base_msat: u32 = Readable::read(read_cursor)?;
205 synthetic_update.fee_base_msat = fee_base_msat;
208 if channel_flags & 0b_0000_1000 > 0 {
209 let fee_proportional_millionths: u32 = Readable::read(read_cursor)?;
210 synthetic_update.fee_proportional_millionths = fee_proportional_millionths;
213 if channel_flags & 0b_0000_0100 > 0 {
214 let tentative_htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
215 synthetic_update.htlc_maximum_msat = if tentative_htlc_maximum_msat == u64::max_value()
217 OptionalField::Absent
219 OptionalField::Present(tentative_htlc_maximum_msat)
223 network_graph.update_channel_unsigned(&synthetic_update)?;
226 self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
227 self.is_initial_sync_complete.store(true, Ordering::Release);
228 Ok(latest_seen_timestamp)
234 use bitcoin::blockdata::constants::genesis_block;
235 use bitcoin::Network;
237 use lightning::ln::msgs::DecodeError;
238 use lightning::routing::network_graph::NetworkGraph;
240 use crate::error::GraphSyncError;
241 use crate::RapidGossipSync;
244 fn network_graph_fails_to_update_from_clipped_input() {
245 let block_hash = genesis_block(Network::Bitcoin).block_hash();
246 let network_graph = NetworkGraph::new(block_hash);
248 let example_input = vec![
249 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
250 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
251 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
252 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
253 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
254 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
255 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
256 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
257 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
258 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
259 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,
260 0, 0, 2, 224, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 36, 0, 0,
261 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,
264 let rapid_sync = RapidGossipSync::new(&network_graph);
265 let update_result = rapid_sync.update_network_graph(&example_input[..]);
266 assert!(update_result.is_err());
267 if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
268 // this is the expected error type
270 panic!("Unexpected update result: {:?}", update_result)
275 fn incremental_only_update_fails_without_prior_announcements() {
276 let incremental_update_input = vec![
277 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
278 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
279 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,
280 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,
281 68, 226, 0, 6, 11, 0, 1, 128,
284 let block_hash = genesis_block(Network::Bitcoin).block_hash();
285 let network_graph = NetworkGraph::new(block_hash);
287 assert_eq!(network_graph.read_only().channels().len(), 0);
289 let rapid_sync = RapidGossipSync::new(&network_graph);
290 let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
291 assert!(update_result.is_err());
292 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
293 assert_eq!(lightning_error.err, "Couldn't find channel for update");
295 panic!("Unexpected update result: {:?}", update_result)
300 fn incremental_only_update_fails_without_prior_updates() {
301 let announced_update_input = vec![
302 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
303 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
304 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
305 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
306 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
307 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
308 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
309 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
310 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
311 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
312 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,
313 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,
314 2, 68, 226, 0, 6, 11, 0, 1, 128,
317 let block_hash = genesis_block(Network::Bitcoin).block_hash();
318 let network_graph = NetworkGraph::new(block_hash);
320 assert_eq!(network_graph.read_only().channels().len(), 0);
322 let rapid_sync = RapidGossipSync::new(&network_graph);
323 let update_result = rapid_sync.update_network_graph(&announced_update_input[..]);
324 assert!(update_result.is_err());
325 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
328 "Couldn't find previous directional data for update"
331 panic!("Unexpected update result: {:?}", update_result)
336 fn incremental_only_update_fails_without_prior_same_direction_updates() {
337 let initialization_input = vec![
338 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
339 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
340 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
341 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
342 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
343 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
344 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
345 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
346 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
347 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
348 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,
349 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0,
350 0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192,
353 let block_hash = genesis_block(Network::Bitcoin).block_hash();
354 let network_graph = NetworkGraph::new(block_hash);
356 assert_eq!(network_graph.read_only().channels().len(), 0);
358 let rapid_sync = RapidGossipSync::new(&network_graph);
359 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
360 if initialization_result.is_err() {
362 "Unexpected initialization result: {:?}",
363 initialization_result
367 assert_eq!(network_graph.read_only().channels().len(), 2);
368 let initialized = network_graph.to_string();
370 .contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643"));
372 .contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b"));
374 .contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432"));
376 .contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61"));
377 assert!(initialized.contains("619737530008010752"));
378 assert!(initialized.contains("783241506229452801"));
380 let opposite_direction_incremental_update_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, 229, 183, 167,
383 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,
384 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,
385 68, 226, 0, 6, 11, 0, 1, 128,
387 let update_result = rapid_sync.update_network_graph(&opposite_direction_incremental_update_input[..]);
388 assert!(update_result.is_err());
389 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
392 "Couldn't find previous directional data for update"
395 panic!("Unexpected update result: {:?}", update_result)
400 fn incremental_update_succeeds_with_prior_announcements_and_full_updates() {
401 let initialization_input = vec![
402 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
403 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
404 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
405 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
406 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
407 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
408 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
409 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
410 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
411 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
412 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,
413 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
414 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,
415 68, 226, 0, 6, 11, 0, 1, 4, 0, 0, 0, 0, 29, 129, 25, 192, 0, 5, 0, 0, 0, 0, 29, 129,
419 let block_hash = genesis_block(Network::Bitcoin).block_hash();
420 let network_graph = NetworkGraph::new(block_hash);
422 assert_eq!(network_graph.read_only().channels().len(), 0);
424 let rapid_sync = RapidGossipSync::new(&network_graph);
425 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
426 assert!(initialization_result.is_ok());
428 let single_direction_incremental_update_input = vec![
429 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
430 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
431 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,
432 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,
433 68, 226, 0, 6, 11, 0, 1, 128,
435 let update_result = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
436 if update_result.is_err() {
437 panic!("Unexpected update result: {:?}", update_result)
440 assert_eq!(network_graph.read_only().channels().len(), 2);
441 let after = network_graph.to_string();
443 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
446 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
449 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
452 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
454 assert!(after.contains("619737530008010752"));
455 assert!(after.contains("783241506229452801"));
459 fn full_update_succeeds() {
460 let valid_input = vec![
461 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
462 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
463 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
464 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
465 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
466 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
467 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
468 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
469 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
470 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
471 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,
472 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
473 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,
474 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
478 let block_hash = genesis_block(Network::Bitcoin).block_hash();
479 let network_graph = NetworkGraph::new(block_hash);
481 assert_eq!(network_graph.read_only().channels().len(), 0);
483 let rapid_sync = RapidGossipSync::new(&network_graph);
484 let update_result = rapid_sync.update_network_graph(&valid_input[..]);
485 if update_result.is_err() {
486 panic!("Unexpected update result: {:?}", update_result)
489 assert_eq!(network_graph.read_only().channels().len(), 2);
490 let after = network_graph.to_string();
492 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
495 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
498 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
501 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
503 assert!(after.contains("619737530008010752"));
504 assert!(after.contains("783241506229452801"));