5 use std::sync::atomic::Ordering;
7 use bitcoin::BlockHash;
8 use bitcoin::secp256k1::PublicKey;
10 use lightning::ln::msgs::{
11 DecodeError, ErrorAction, LightningError, 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 default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
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;
131 let channel_flags: u8 = Readable::read(read_cursor)?;
133 // flags are always sent in full, and hence always need updating
134 let standard_channel_flags = channel_flags & 0b_0000_0011;
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 {
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,
146 fee_base_msat: default_fee_base_msat,
147 fee_proportional_millionths: default_fee_proportional_millionths,
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
155 .get(&short_channel_id)
156 .ok_or(LightningError {
157 err: "Couldn't find channel for update".to_owned(),
158 action: ErrorAction::IgnoreError,
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,
168 UnsignedChannelUpdate {
171 timestamp: backdated_timestamp,
172 flags: standard_channel_flags,
173 cltv_expiry_delta: directional_info.cltv_expiry_delta,
174 htlc_minimum_msat: directional_info.htlc_minimum_msat,
175 htlc_maximum_msat: directional_info.htlc_maximum_msat,
176 fee_base_msat: directional_info.fees.base_msat,
177 fee_proportional_millionths: directional_info.fees.proportional_millionths,
182 if channel_flags & 0b_0100_0000 > 0 {
183 let cltv_expiry_delta: u16 = Readable::read(read_cursor)?;
184 synthetic_update.cltv_expiry_delta = cltv_expiry_delta;
187 if channel_flags & 0b_0010_0000 > 0 {
188 let htlc_minimum_msat: u64 = Readable::read(read_cursor)?;
189 synthetic_update.htlc_minimum_msat = htlc_minimum_msat;
192 if channel_flags & 0b_0001_0000 > 0 {
193 let fee_base_msat: u32 = Readable::read(read_cursor)?;
194 synthetic_update.fee_base_msat = fee_base_msat;
197 if channel_flags & 0b_0000_1000 > 0 {
198 let fee_proportional_millionths: u32 = Readable::read(read_cursor)?;
199 synthetic_update.fee_proportional_millionths = fee_proportional_millionths;
202 if channel_flags & 0b_0000_0100 > 0 {
203 let htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
204 synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
207 network_graph.update_channel_unsigned(&synthetic_update)?;
210 self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
211 self.is_initial_sync_complete.store(true, Ordering::Release);
212 Ok(latest_seen_timestamp)
218 use bitcoin::blockdata::constants::genesis_block;
219 use bitcoin::Network;
221 use lightning::ln::msgs::DecodeError;
222 use lightning::routing::gossip::NetworkGraph;
223 use lightning::util::test_utils::TestLogger;
225 use crate::error::GraphSyncError;
226 use crate::RapidGossipSync;
229 fn network_graph_fails_to_update_from_clipped_input() {
230 let block_hash = genesis_block(Network::Bitcoin).block_hash();
231 let logger = TestLogger::new();
232 let network_graph = NetworkGraph::new(block_hash, &logger);
234 let example_input = vec![
235 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
236 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
237 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
238 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
239 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
240 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
241 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
242 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
243 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
244 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
245 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,
246 0, 0, 2, 224, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 36, 0, 0,
247 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,
250 let rapid_sync = RapidGossipSync::new(&network_graph);
251 let update_result = rapid_sync.update_network_graph(&example_input[..]);
252 assert!(update_result.is_err());
253 if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
254 // this is the expected error type
256 panic!("Unexpected update result: {:?}", update_result)
261 fn incremental_only_update_fails_without_prior_announcements() {
262 let incremental_update_input = vec![
263 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
264 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
265 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,
266 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,
267 68, 226, 0, 6, 11, 0, 1, 128,
270 let block_hash = genesis_block(Network::Bitcoin).block_hash();
271 let logger = TestLogger::new();
272 let network_graph = NetworkGraph::new(block_hash, &logger);
274 assert_eq!(network_graph.read_only().channels().len(), 0);
276 let rapid_sync = RapidGossipSync::new(&network_graph);
277 let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
278 assert!(update_result.is_err());
279 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
280 assert_eq!(lightning_error.err, "Couldn't find channel for update");
282 panic!("Unexpected update result: {:?}", update_result)
287 fn incremental_only_update_fails_without_prior_updates() {
288 let announced_update_input = vec![
289 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
290 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
291 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
292 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
293 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
294 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
295 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
296 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
297 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
298 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
299 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,
300 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,
301 2, 68, 226, 0, 6, 11, 0, 1, 128,
304 let block_hash = genesis_block(Network::Bitcoin).block_hash();
305 let logger = TestLogger::new();
306 let network_graph = NetworkGraph::new(block_hash, &logger);
308 assert_eq!(network_graph.read_only().channels().len(), 0);
310 let rapid_sync = RapidGossipSync::new(&network_graph);
311 let update_result = rapid_sync.update_network_graph(&announced_update_input[..]);
312 assert!(update_result.is_err());
313 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
316 "Couldn't find previous directional data for update"
319 panic!("Unexpected update result: {:?}", update_result)
324 fn incremental_only_update_fails_without_prior_same_direction_updates() {
325 let initialization_input = vec![
326 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
327 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
328 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
329 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
330 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
331 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
332 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
333 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
334 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
335 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
336 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,
337 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0,
338 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 let block_hash = genesis_block(Network::Bitcoin).block_hash();
342 let logger = TestLogger::new();
343 let network_graph = NetworkGraph::new(block_hash, &logger);
345 assert_eq!(network_graph.read_only().channels().len(), 0);
347 let rapid_sync = RapidGossipSync::new(&network_graph);
348 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
349 if initialization_result.is_err() {
351 "Unexpected initialization result: {:?}",
352 initialization_result
356 assert_eq!(network_graph.read_only().channels().len(), 2);
357 let initialized = network_graph.to_string();
359 .contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643"));
361 .contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b"));
363 .contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432"));
365 .contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61"));
366 assert!(initialized.contains("619737530008010752"));
367 assert!(initialized.contains("783241506229452801"));
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,
376 let update_result = rapid_sync.update_network_graph(&opposite_direction_incremental_update_input[..]);
377 assert!(update_result.is_err());
378 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
381 "Couldn't find previous directional data for update"
384 panic!("Unexpected update result: {:?}", update_result)
389 fn incremental_update_succeeds_with_prior_announcements_and_full_updates() {
390 let initialization_input = vec![
391 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
392 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
393 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
394 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
395 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
396 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
397 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
398 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
399 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
400 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
401 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,
402 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
403 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,
404 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 let block_hash = genesis_block(Network::Bitcoin).block_hash();
409 let logger = TestLogger::new();
410 let network_graph = NetworkGraph::new(block_hash, &logger);
412 assert_eq!(network_graph.read_only().channels().len(), 0);
414 let rapid_sync = RapidGossipSync::new(&network_graph);
415 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
416 assert!(initialization_result.is_ok());
418 let single_direction_incremental_update_input = vec![
419 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
420 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
421 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,
422 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,
423 68, 226, 0, 6, 11, 0, 1, 128,
425 let update_result = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
426 if update_result.is_err() {
427 panic!("Unexpected update result: {:?}", update_result)
430 assert_eq!(network_graph.read_only().channels().len(), 2);
431 let after = network_graph.to_string();
433 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
436 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
439 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
442 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
444 assert!(after.contains("619737530008010752"));
445 assert!(after.contains("783241506229452801"));
449 fn full_update_succeeds() {
450 let valid_input = vec![
451 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
452 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
453 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
454 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
455 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
456 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
457 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
458 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
459 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
460 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
461 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,
462 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
463 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,
464 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
468 let block_hash = genesis_block(Network::Bitcoin).block_hash();
469 let logger = TestLogger::new();
470 let network_graph = NetworkGraph::new(block_hash, &logger);
472 assert_eq!(network_graph.read_only().channels().len(), 0);
474 let rapid_sync = RapidGossipSync::new(&network_graph);
475 let update_result = rapid_sync.update_network_graph(&valid_input[..]);
476 if update_result.is_err() {
477 panic!("Unexpected update result: {:?}", update_result)
480 assert_eq!(network_graph.read_only().channels().len(), 2);
481 let after = network_graph.to_string();
483 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
486 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
489 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
492 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
494 assert!(after.contains("619737530008010752"));
495 assert!(after.contains("783241506229452801"));