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