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 /// 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<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
30 pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
32 mut read_cursor: &mut R,
33 ) -> Result<u32, GraphSyncError> {
34 let mut prefix = [0u8; 4];
35 read_cursor.read_exact(&mut prefix)?;
40 return Err(DecodeError::UnknownVersion.into());
44 let chain_hash: BlockHash = Readable::read(read_cursor)?;
45 let latest_seen_timestamp: u32 = Readable::read(read_cursor)?;
46 // backdate the applied timestamp by a week
47 let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
49 let node_id_count: u32 = Readable::read(read_cursor)?;
50 let mut node_ids: Vec<PublicKey> = Vec::with_capacity(std::cmp::min(
52 MAX_INITIAL_NODE_ID_VECTOR_CAPACITY,
54 for _ in 0..node_id_count {
55 let current_node_id = Readable::read(read_cursor)?;
56 node_ids.push(current_node_id);
59 let network_graph = &self.network_graph;
61 let mut previous_scid: u64 = 0;
62 let announcement_count: u32 = Readable::read(read_cursor)?;
63 for _ in 0..announcement_count {
64 let features = Readable::read(read_cursor)?;
67 let scid_delta: BigSize = Readable::read(read_cursor)?;
68 let short_channel_id = previous_scid
69 .checked_add(scid_delta.0)
70 .ok_or(DecodeError::InvalidValue)?;
71 previous_scid = short_channel_id;
73 let node_id_1_index: BigSize = Readable::read(read_cursor)?;
74 let node_id_2_index: BigSize = Readable::read(read_cursor)?;
75 if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
76 return Err(DecodeError::InvalidValue.into());
78 let node_id_1 = node_ids[node_id_1_index.0 as usize];
79 let node_id_2 = node_ids[node_id_2_index.0 as usize];
81 let announcement_result = network_graph.add_channel_from_partial_announcement(
83 backdated_timestamp as u64,
88 if let Err(lightning_error) = announcement_result {
89 if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action {
90 // everything is fine, just a duplicate channel announcement
92 return Err(lightning_error.into());
97 previous_scid = 0; // updates start at a new scid
99 let update_count: u32 = Readable::read(read_cursor)?;
100 if update_count == 0 {
101 return Ok(latest_seen_timestamp);
104 // obtain default values for non-incremental updates
105 let default_cltv_expiry_delta: u16 = Readable::read(&mut read_cursor)?;
106 let default_htlc_minimum_msat: u64 = Readable::read(&mut read_cursor)?;
107 let default_fee_base_msat: u32 = Readable::read(&mut read_cursor)?;
108 let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
109 let default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
111 for _ in 0..update_count {
112 let scid_delta: BigSize = Readable::read(read_cursor)?;
113 let short_channel_id = previous_scid
114 .checked_add(scid_delta.0)
115 .ok_or(DecodeError::InvalidValue)?;
116 previous_scid = short_channel_id;
118 let channel_flags: u8 = Readable::read(read_cursor)?;
120 // flags are always sent in full, and hence always need updating
121 let standard_channel_flags = channel_flags & 0b_0000_0011;
123 let mut synthetic_update = if channel_flags & 0b_1000_0000 == 0 {
124 // full update, field flags will indicate deviations from the default
125 UnsignedChannelUpdate {
128 timestamp: backdated_timestamp,
129 flags: standard_channel_flags,
130 cltv_expiry_delta: default_cltv_expiry_delta,
131 htlc_minimum_msat: default_htlc_minimum_msat,
132 htlc_maximum_msat: default_htlc_maximum_msat,
133 fee_base_msat: default_fee_base_msat,
134 fee_proportional_millionths: default_fee_proportional_millionths,
138 // incremental update, field flags will indicate mutated values
139 let read_only_network_graph = network_graph.read_only();
140 let channel = read_only_network_graph
142 .get(&short_channel_id)
143 .ok_or(LightningError {
144 err: "Couldn't find channel for update".to_owned(),
145 action: ErrorAction::IgnoreError,
148 let directional_info = channel
149 .get_directional_info(channel_flags)
150 .ok_or(LightningError {
151 err: "Couldn't find previous directional data for update".to_owned(),
152 action: ErrorAction::IgnoreError,
155 UnsignedChannelUpdate {
158 timestamp: backdated_timestamp,
159 flags: standard_channel_flags,
160 cltv_expiry_delta: directional_info.cltv_expiry_delta,
161 htlc_minimum_msat: directional_info.htlc_minimum_msat,
162 htlc_maximum_msat: directional_info.htlc_maximum_msat,
163 fee_base_msat: directional_info.fees.base_msat,
164 fee_proportional_millionths: directional_info.fees.proportional_millionths,
169 if channel_flags & 0b_0100_0000 > 0 {
170 let cltv_expiry_delta: u16 = Readable::read(read_cursor)?;
171 synthetic_update.cltv_expiry_delta = cltv_expiry_delta;
174 if channel_flags & 0b_0010_0000 > 0 {
175 let htlc_minimum_msat: u64 = Readable::read(read_cursor)?;
176 synthetic_update.htlc_minimum_msat = htlc_minimum_msat;
179 if channel_flags & 0b_0001_0000 > 0 {
180 let fee_base_msat: u32 = Readable::read(read_cursor)?;
181 synthetic_update.fee_base_msat = fee_base_msat;
184 if channel_flags & 0b_0000_1000 > 0 {
185 let fee_proportional_millionths: u32 = Readable::read(read_cursor)?;
186 synthetic_update.fee_proportional_millionths = fee_proportional_millionths;
189 if channel_flags & 0b_0000_0100 > 0 {
190 let htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
191 synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
194 network_graph.update_channel_unsigned(&synthetic_update)?;
197 self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
198 self.is_initial_sync_complete.store(true, Ordering::Release);
199 Ok(latest_seen_timestamp)
205 use bitcoin::blockdata::constants::genesis_block;
206 use bitcoin::Network;
208 use lightning::ln::msgs::DecodeError;
209 use lightning::routing::gossip::NetworkGraph;
210 use lightning::util::test_utils::TestLogger;
212 use crate::error::GraphSyncError;
213 use crate::RapidGossipSync;
216 fn network_graph_fails_to_update_from_clipped_input() {
217 let block_hash = genesis_block(Network::Bitcoin).block_hash();
218 let logger = TestLogger::new();
219 let network_graph = NetworkGraph::new(block_hash, &logger);
221 let example_input = vec![
222 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
223 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
224 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
225 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
226 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
227 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
228 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
229 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
230 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
231 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
232 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,
233 0, 0, 2, 224, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 36, 0, 0,
234 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,
237 let rapid_sync = RapidGossipSync::new(&network_graph);
238 let update_result = rapid_sync.update_network_graph(&example_input[..]);
239 assert!(update_result.is_err());
240 if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
241 // this is the expected error type
243 panic!("Unexpected update result: {:?}", update_result)
248 fn incremental_only_update_fails_without_prior_announcements() {
249 let incremental_update_input = vec![
250 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
251 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
252 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,
253 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,
254 68, 226, 0, 6, 11, 0, 1, 128,
257 let block_hash = genesis_block(Network::Bitcoin).block_hash();
258 let logger = TestLogger::new();
259 let network_graph = NetworkGraph::new(block_hash, &logger);
261 assert_eq!(network_graph.read_only().channels().len(), 0);
263 let rapid_sync = RapidGossipSync::new(&network_graph);
264 let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
265 assert!(update_result.is_err());
266 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
267 assert_eq!(lightning_error.err, "Couldn't find channel for update");
269 panic!("Unexpected update result: {:?}", update_result)
274 fn incremental_only_update_fails_without_prior_updates() {
275 let announced_update_input = vec![
276 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
277 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
278 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
279 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
280 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
281 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
282 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
283 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
284 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
285 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
286 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,
287 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,
288 2, 68, 226, 0, 6, 11, 0, 1, 128,
291 let block_hash = genesis_block(Network::Bitcoin).block_hash();
292 let logger = TestLogger::new();
293 let network_graph = NetworkGraph::new(block_hash, &logger);
295 assert_eq!(network_graph.read_only().channels().len(), 0);
297 let rapid_sync = RapidGossipSync::new(&network_graph);
298 let update_result = rapid_sync.update_network_graph(&announced_update_input[..]);
299 assert!(update_result.is_err());
300 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
303 "Couldn't find previous directional data for update"
306 panic!("Unexpected update result: {:?}", update_result)
311 fn incremental_only_update_fails_without_prior_same_direction_updates() {
312 let initialization_input = vec![
313 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
314 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
315 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
316 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
317 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
318 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
319 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
320 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
321 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
322 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
323 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,
324 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 25, 0, 0,
325 0, 1, 0, 0, 0, 125, 255, 2, 68, 226, 0, 6, 11, 0, 1, 5, 0, 0, 0, 0, 29, 129, 25, 192,
328 let block_hash = genesis_block(Network::Bitcoin).block_hash();
329 let logger = TestLogger::new();
330 let network_graph = NetworkGraph::new(block_hash, &logger);
332 assert_eq!(network_graph.read_only().channels().len(), 0);
334 let rapid_sync = RapidGossipSync::new(&network_graph);
335 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
336 if initialization_result.is_err() {
338 "Unexpected initialization result: {:?}",
339 initialization_result
343 assert_eq!(network_graph.read_only().channels().len(), 2);
344 let initialized = network_graph.to_string();
346 .contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643"));
348 .contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b"));
350 .contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432"));
352 .contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61"));
353 assert!(initialized.contains("619737530008010752"));
354 assert!(initialized.contains("783241506229452801"));
356 let opposite_direction_incremental_update_input = vec![
357 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
358 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
359 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,
360 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,
361 68, 226, 0, 6, 11, 0, 1, 128,
363 let update_result = rapid_sync.update_network_graph(&opposite_direction_incremental_update_input[..]);
364 assert!(update_result.is_err());
365 if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
368 "Couldn't find previous directional data for update"
371 panic!("Unexpected update result: {:?}", update_result)
376 fn incremental_update_succeeds_with_prior_announcements_and_full_updates() {
377 let initialization_input = vec![
378 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
379 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
380 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
381 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
382 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
383 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
384 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
385 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
386 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
387 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
388 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,
389 0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
390 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,
391 68, 226, 0, 6, 11, 0, 1, 4, 0, 0, 0, 0, 29, 129, 25, 192, 0, 5, 0, 0, 0, 0, 29, 129,
395 let block_hash = genesis_block(Network::Bitcoin).block_hash();
396 let logger = TestLogger::new();
397 let network_graph = NetworkGraph::new(block_hash, &logger);
399 assert_eq!(network_graph.read_only().channels().len(), 0);
401 let rapid_sync = RapidGossipSync::new(&network_graph);
402 let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
403 assert!(initialization_result.is_ok());
405 let single_direction_incremental_update_input = vec![
406 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
407 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
408 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,
409 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,
410 68, 226, 0, 6, 11, 0, 1, 128,
412 let update_result = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
413 if update_result.is_err() {
414 panic!("Unexpected update result: {:?}", update_result)
417 assert_eq!(network_graph.read_only().channels().len(), 2);
418 let after = network_graph.to_string();
420 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
423 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
426 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
429 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
431 assert!(after.contains("619737530008010752"));
432 assert!(after.contains("783241506229452801"));
436 fn full_update_succeeds() {
437 let valid_input = vec![
438 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
439 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
440 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
441 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
442 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
443 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
444 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
445 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
446 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
447 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
448 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,
449 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
450 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,
451 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
455 let block_hash = genesis_block(Network::Bitcoin).block_hash();
456 let logger = TestLogger::new();
457 let network_graph = NetworkGraph::new(block_hash, &logger);
459 assert_eq!(network_graph.read_only().channels().len(), 0);
461 let rapid_sync = RapidGossipSync::new(&network_graph);
462 let update_result = rapid_sync.update_network_graph(&valid_input[..]);
463 if update_result.is_err() {
464 panic!("Unexpected update result: {:?}", update_result)
467 assert_eq!(network_graph.read_only().channels().len(), 2);
468 let after = network_graph.to_string();
470 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
473 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
476 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
479 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
481 assert!(after.contains("619737530008010752"));
482 assert!(after.contains("783241506229452801"));