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)?;
40 if prefix != GOSSIP_PREFIX {
41 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(core::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)?;
76 if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
77 return Err(DecodeError::InvalidValue.into());
79 let node_id_1 = node_ids[node_id_1_index.0 as usize];
80 let node_id_2 = node_ids[node_id_2_index.0 as usize];
82 let announcement_result = network_graph.add_channel_from_partial_announcement(
84 backdated_timestamp as u64,
89 if let Err(lightning_error) = announcement_result {
90 if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action {
91 // everything is fine, just a duplicate channel announcement
93 return Err(lightning_error.into());
98 previous_scid = 0; // updates start at a new scid
100 let update_count: u32 = Readable::read(read_cursor)?;
101 if update_count == 0 {
102 return Ok(latest_seen_timestamp);
105 // obtain default values for non-incremental updates
106 let default_cltv_expiry_delta: u16 = Readable::read(&mut read_cursor)?;
107 let default_htlc_minimum_msat: u64 = Readable::read(&mut read_cursor)?;
108 let default_fee_base_msat: u32 = Readable::read(&mut read_cursor)?;
109 let default_fee_proportional_millionths: u32 = Readable::read(&mut read_cursor)?;
110 let default_htlc_maximum_msat: u64 = Readable::read(&mut read_cursor)?;
112 for _ in 0..update_count {
113 let scid_delta: BigSize = Readable::read(read_cursor)?;
114 let short_channel_id = previous_scid
115 .checked_add(scid_delta.0)
116 .ok_or(DecodeError::InvalidValue)?;
117 previous_scid = short_channel_id;
119 let channel_flags: u8 = Readable::read(read_cursor)?;
121 // flags are always sent in full, and hence always need updating
122 let standard_channel_flags = channel_flags & 0b_0000_0011;
124 let mut synthetic_update = UnsignedChannelUpdate {
127 timestamp: backdated_timestamp,
128 flags: standard_channel_flags,
129 cltv_expiry_delta: default_cltv_expiry_delta,
130 htlc_minimum_msat: default_htlc_minimum_msat,
131 htlc_maximum_msat: default_htlc_maximum_msat,
132 fee_base_msat: default_fee_base_msat,
133 fee_proportional_millionths: default_fee_proportional_millionths,
134 excess_data: Vec::new(),
137 let mut skip_update_for_unknown_channel = false;
139 if (channel_flags & 0b_1000_0000) != 0 {
140 // incremental update, field flags will indicate mutated values
141 let read_only_network_graph = network_graph.read_only();
142 if let Some(channel) = read_only_network_graph
144 .get(&short_channel_id) {
146 let directional_info = channel
147 .get_directional_info(channel_flags)
148 .ok_or(LightningError {
149 err: "Couldn't find previous directional data for update".to_owned(),
150 action: ErrorAction::IgnoreError,
153 synthetic_update.cltv_expiry_delta = directional_info.cltv_expiry_delta;
154 synthetic_update.htlc_minimum_msat = directional_info.htlc_minimum_msat;
155 synthetic_update.htlc_maximum_msat = directional_info.htlc_maximum_msat;
156 synthetic_update.fee_base_msat = directional_info.fees.base_msat;
157 synthetic_update.fee_proportional_millionths = directional_info.fees.proportional_millionths;
160 skip_update_for_unknown_channel = true;
164 if channel_flags & 0b_0100_0000 > 0 {
165 let cltv_expiry_delta: u16 = Readable::read(read_cursor)?;
166 synthetic_update.cltv_expiry_delta = cltv_expiry_delta;
169 if channel_flags & 0b_0010_0000 > 0 {
170 let htlc_minimum_msat: u64 = Readable::read(read_cursor)?;
171 synthetic_update.htlc_minimum_msat = htlc_minimum_msat;
174 if channel_flags & 0b_0001_0000 > 0 {
175 let fee_base_msat: u32 = Readable::read(read_cursor)?;
176 synthetic_update.fee_base_msat = fee_base_msat;
179 if channel_flags & 0b_0000_1000 > 0 {
180 let fee_proportional_millionths: u32 = Readable::read(read_cursor)?;
181 synthetic_update.fee_proportional_millionths = fee_proportional_millionths;
184 if channel_flags & 0b_0000_0100 > 0 {
185 let htlc_maximum_msat: u64 = Readable::read(read_cursor)?;
186 synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
189 if skip_update_for_unknown_channel {
193 match network_graph.update_channel_unsigned(&synthetic_update) {
195 Err(LightningError { action: ErrorAction::IgnoreDuplicateGossip, .. }) => {},
196 Err(LightningError { action: ErrorAction::IgnoreAndLog(_), .. }) => {},
197 Err(LightningError { action: ErrorAction::IgnoreError, .. }) => {},
198 Err(e) => return Err(e.into()),
202 self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
203 self.is_initial_sync_complete.store(true, Ordering::Release);
204 Ok(latest_seen_timestamp)
210 use bitcoin::blockdata::constants::genesis_block;
211 use bitcoin::Network;
213 use lightning::ln::msgs::DecodeError;
214 use lightning::routing::gossip::NetworkGraph;
215 use lightning::util::test_utils::TestLogger;
217 use crate::error::GraphSyncError;
218 use crate::RapidGossipSync;
221 fn network_graph_fails_to_update_from_clipped_input() {
222 let block_hash = genesis_block(Network::Bitcoin).block_hash();
223 let logger = TestLogger::new();
224 let network_graph = NetworkGraph::new(block_hash, &logger);
226 let example_input = vec![
227 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
228 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
229 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
230 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
231 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
232 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
233 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
234 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
235 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
236 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
237 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,
238 0, 0, 2, 224, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 36, 0, 0,
239 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,
242 let rapid_sync = RapidGossipSync::new(&network_graph);
243 let update_result = rapid_sync.update_network_graph(&example_input[..]);
244 assert!(update_result.is_err());
245 if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
246 // this is the expected error type
248 panic!("Unexpected update result: {:?}", update_result)
253 fn incremental_only_update_ignores_missing_channel() {
254 let incremental_update_input = vec![
255 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
256 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
257 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,
258 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,
259 68, 226, 0, 6, 11, 0, 1, 128,
262 let block_hash = genesis_block(Network::Bitcoin).block_hash();
263 let logger = TestLogger::new();
264 let network_graph = NetworkGraph::new(block_hash, &logger);
266 assert_eq!(network_graph.read_only().channels().len(), 0);
268 let rapid_sync = RapidGossipSync::new(&network_graph);
269 let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
270 assert!(update_result.is_ok());
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 update_succeeds_when_duplicate_gossip_is_applied() {
437 let initialization_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, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
450 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,
451 68, 226, 0, 6, 11, 0, 1, 4, 0, 0, 0, 0, 29, 129, 25, 192, 0, 5, 0, 0, 0, 0, 29, 129,
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 initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
463 assert!(initialization_result.is_ok());
465 let single_direction_incremental_update_input = vec![
466 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
467 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
468 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,
469 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,
470 68, 226, 0, 6, 11, 0, 1, 128,
472 let update_result_1 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
473 // Apply duplicate update
474 let update_result_2 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
475 assert!(update_result_1.is_ok());
476 assert!(update_result_2.is_ok());
480 fn full_update_succeeds() {
481 let valid_input = vec![
482 76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
483 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
484 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
485 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
486 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
487 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
488 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
489 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
490 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
491 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
492 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,
493 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
494 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,
495 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
499 let block_hash = genesis_block(Network::Bitcoin).block_hash();
500 let logger = TestLogger::new();
501 let network_graph = NetworkGraph::new(block_hash, &logger);
503 assert_eq!(network_graph.read_only().channels().len(), 0);
505 let rapid_sync = RapidGossipSync::new(&network_graph);
506 let update_result = rapid_sync.update_network_graph(&valid_input[..]);
507 if update_result.is_err() {
508 panic!("Unexpected update result: {:?}", update_result)
511 assert_eq!(network_graph.read_only().channels().len(), 2);
512 let after = network_graph.to_string();
514 after.contains("021607cfce19a4c5e7e6e738663dfafbbbac262e4ff76c2c9b30dbeefc35c00643")
517 after.contains("02247d9db0dfafea745ef8c9e161eb322f73ac3f8858d8730b6fd97254747ce76b")
520 after.contains("029e01f279986acc83ba235d46d80aede0b7595f410353b93a8ab540bb677f4432")
523 after.contains("02c913118a8895b9e29c89af6e20ed00d95a1f64e4952edbafa84d048f26804c61")
525 assert!(after.contains("619737530008010752"));
526 assert!(after.contains("783241506229452801"));
530 pub fn update_fails_with_unknown_version() {
531 let unknown_version_input = vec![
532 76, 68, 75, 2, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
533 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
534 0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
535 187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
536 157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
537 88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
538 204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
539 181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
540 110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
541 76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
542 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,
543 0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
544 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,
545 0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
549 let block_hash = genesis_block(Network::Bitcoin).block_hash();
550 let logger = TestLogger::new();
551 let network_graph = NetworkGraph::new(block_hash, &logger);
552 let rapid_sync = RapidGossipSync::new(&network_graph);
553 let update_result = rapid_sync.update_network_graph(&unknown_version_input[..]);
555 assert!(update_result.is_err());
557 if let Err(GraphSyncError::DecodeError(DecodeError::UnknownVersion)) = update_result {
558 // this is the expected error type
560 panic!("Unexpected update result: {:?}", update_result)