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