Merge pull request #1843 from TheBlueMatt/2022-11-fix-bp-exit-docs
[rust-lightning] / lightning-rapid-gossip-sync / src / processing.rs
index 818e19fe4b42fa6f12a31597b8ca4798eee2b5cb..3e001ec45c4be1aa7becbaa6da9f9158f3d217fa 100644 (file)
@@ -1,8 +1,6 @@
-use std::cmp::max;
-use std::io;
-use std::io::Read;
-use std::ops::Deref;
-use std::sync::atomic::Ordering;
+use core::cmp::max;
+use core::ops::Deref;
+use core::sync::atomic::Ordering;
 
 use bitcoin::BlockHash;
 use bitcoin::secp256k1::PublicKey;
@@ -13,10 +11,14 @@ use lightning::ln::msgs::{
 use lightning::routing::gossip::NetworkGraph;
 use lightning::util::logger::Logger;
 use lightning::util::ser::{BigSize, Readable};
+use lightning::io;
 
 use crate::error::GraphSyncError;
 use crate::RapidGossipSync;
 
+#[cfg(not(feature = "std"))]
+use alloc::{vec::Vec, borrow::ToOwned};
+
 /// The purpose of this prefix is to identify the serialization format, should other rapid gossip
 /// sync formats arise in the future.
 ///
@@ -28,31 +30,16 @@ const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
 const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000;
 
 impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
-       /// Update network graph from binary data.
-       /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
-       ///
-       /// `network_graph`: network graph to be updated
-       ///
-       /// `update_data`: `&[u8]` binary stream that comprises the update data
-       pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
-               let mut read_cursor = io::Cursor::new(update_data);
-               self.update_network_graph_from_byte_stream(&mut read_cursor)
-       }
-
-
-       pub(crate) fn update_network_graph_from_byte_stream<R: Read>(
+       pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
                &self,
                mut read_cursor: &mut R,
        ) -> Result<u32, GraphSyncError> {
                let mut prefix = [0u8; 4];
                read_cursor.read_exact(&mut prefix)?;
 
-               match prefix {
-                       GOSSIP_PREFIX => {}
-                       _ => {
-                               return Err(DecodeError::UnknownVersion.into());
-                       }
-               };
+               if prefix != GOSSIP_PREFIX {
+                       return Err(DecodeError::UnknownVersion.into());
+               }
 
                let chain_hash: BlockHash = Readable::read(read_cursor)?;
                let latest_seen_timestamp: u32 = Readable::read(read_cursor)?;
@@ -60,7 +47,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
                let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7);
 
                let node_id_count: u32 = Readable::read(read_cursor)?;
-               let mut node_ids: Vec<PublicKey> = Vec::with_capacity(std::cmp::min(
+               let mut node_ids: Vec<PublicKey> = Vec::with_capacity(core::cmp::min(
                        node_id_count,
                        MAX_INITIAL_NODE_ID_VECTOR_CAPACITY,
                ) as usize);
@@ -85,6 +72,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
 
                        let node_id_1_index: BigSize = Readable::read(read_cursor)?;
                        let node_id_2_index: BigSize = Readable::read(read_cursor)?;
+
                        if max(node_id_1_index.0, node_id_2_index.0) >= node_id_count as u64 {
                                return Err(DecodeError::InvalidValue.into());
                        };
@@ -133,49 +121,43 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
                        // flags are always sent in full, and hence always need updating
                        let standard_channel_flags = channel_flags & 0b_0000_0011;
 
-                       let mut synthetic_update = if channel_flags & 0b_1000_0000 == 0 {
-                               // full update, field flags will indicate deviations from the default
-                               UnsignedChannelUpdate {
-                                       chain_hash,
-                                       short_channel_id,
-                                       timestamp: backdated_timestamp,
-                                       flags: standard_channel_flags,
-                                       cltv_expiry_delta: default_cltv_expiry_delta,
-                                       htlc_minimum_msat: default_htlc_minimum_msat,
-                                       htlc_maximum_msat: default_htlc_maximum_msat,
-                                       fee_base_msat: default_fee_base_msat,
-                                       fee_proportional_millionths: default_fee_proportional_millionths,
-                                       excess_data: vec![],
-                               }
-                       } else {
+                       let mut synthetic_update = UnsignedChannelUpdate {
+                               chain_hash,
+                               short_channel_id,
+                               timestamp: backdated_timestamp,
+                               flags: standard_channel_flags,
+                               cltv_expiry_delta: default_cltv_expiry_delta,
+                               htlc_minimum_msat: default_htlc_minimum_msat,
+                               htlc_maximum_msat: default_htlc_maximum_msat,
+                               fee_base_msat: default_fee_base_msat,
+                               fee_proportional_millionths: default_fee_proportional_millionths,
+                               excess_data: Vec::new(),
+                       };
+
+                       let mut skip_update_for_unknown_channel = false;
+
+                       if (channel_flags & 0b_1000_0000) != 0 {
                                // incremental update, field flags will indicate mutated values
                                let read_only_network_graph = network_graph.read_only();
-                               let channel = read_only_network_graph
+                               if let Some(channel) = read_only_network_graph
                                        .channels()
-                                       .get(&short_channel_id)
-                                       .ok_or(LightningError {
-                                               err: "Couldn't find channel for update".to_owned(),
-                                               action: ErrorAction::IgnoreError,
-                                       })?;
-
-                               let directional_info = channel
-                                       .get_directional_info(channel_flags)
-                                       .ok_or(LightningError {
-                                               err: "Couldn't find previous directional data for update".to_owned(),
-                                               action: ErrorAction::IgnoreError,
-                                       })?;
-
-                               UnsignedChannelUpdate {
-                                       chain_hash,
-                                       short_channel_id,
-                                       timestamp: backdated_timestamp,
-                                       flags: standard_channel_flags,
-                                       cltv_expiry_delta: directional_info.cltv_expiry_delta,
-                                       htlc_minimum_msat: directional_info.htlc_minimum_msat,
-                                       htlc_maximum_msat: directional_info.htlc_maximum_msat,
-                                       fee_base_msat: directional_info.fees.base_msat,
-                                       fee_proportional_millionths: directional_info.fees.proportional_millionths,
-                                       excess_data: vec![],
+                                       .get(&short_channel_id) {
+
+                                       let directional_info = channel
+                                               .get_directional_info(channel_flags)
+                                               .ok_or(LightningError {
+                                                       err: "Couldn't find previous directional data for update".to_owned(),
+                                                       action: ErrorAction::IgnoreError,
+                                               })?;
+
+                                       synthetic_update.cltv_expiry_delta = directional_info.cltv_expiry_delta;
+                                       synthetic_update.htlc_minimum_msat = directional_info.htlc_minimum_msat;
+                                       synthetic_update.htlc_maximum_msat = directional_info.htlc_maximum_msat;
+                                       synthetic_update.fee_base_msat = directional_info.fees.base_msat;
+                                       synthetic_update.fee_proportional_millionths = directional_info.fees.proportional_millionths;
+
+                               } else {
+                                       skip_update_for_unknown_channel = true;
                                }
                        };
 
@@ -204,7 +186,17 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
                                synthetic_update.htlc_maximum_msat = htlc_maximum_msat;
                        }
 
-                       network_graph.update_channel_unsigned(&synthetic_update)?;
+                       if skip_update_for_unknown_channel {
+                               continue;
+                       }
+
+                       match network_graph.update_channel_unsigned(&synthetic_update) {
+                               Ok(_) => {},
+                               Err(LightningError { action: ErrorAction::IgnoreDuplicateGossip, .. }) => {},
+                               Err(LightningError { action: ErrorAction::IgnoreAndLog(_), .. }) => {},
+                               Err(LightningError { action: ErrorAction::IgnoreError, .. }) => {},
+                               Err(e) => return Err(e.into()),
+                       }
                }
 
                self.network_graph.set_last_rapid_gossip_sync_timestamp(latest_seen_timestamp);
@@ -258,7 +250,7 @@ mod tests {
        }
 
        #[test]
-       fn incremental_only_update_fails_without_prior_announcements() {
+       fn incremental_only_update_ignores_missing_channel() {
                let incremental_update_input = vec![
                        76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
                        79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
@@ -275,12 +267,7 @@ mod tests {
 
                let rapid_sync = RapidGossipSync::new(&network_graph);
                let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
-               assert!(update_result.is_err());
-               if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
-                       assert_eq!(lightning_error.err, "Couldn't find channel for update");
-               } else {
-                       panic!("Unexpected update result: {:?}", update_result)
-               }
+               assert!(update_result.is_ok());
        }
 
        #[test]
@@ -445,6 +432,50 @@ mod tests {
                assert!(after.contains("783241506229452801"));
        }
 
+       #[test]
+       fn update_succeeds_when_duplicate_gossip_is_applied() {
+               let initialization_input = vec![
+                       76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
+                       79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
+                       0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
+                       187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
+                       157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
+                       88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
+                       204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
+                       181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
+                       110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
+                       76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
+                       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,
+                       0, 0, 0, 1, 0, 0, 0, 0, 58, 85, 116, 216, 255, 8, 153, 192, 0, 2, 27, 0, 0, 56, 0, 0,
+                       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,
+                       68, 226, 0, 6, 11, 0, 1, 4, 0, 0, 0, 0, 29, 129, 25, 192, 0, 5, 0, 0, 0, 0, 29, 129,
+                       25, 192,
+               ];
+
+               let block_hash = genesis_block(Network::Bitcoin).block_hash();
+               let logger = TestLogger::new();
+               let network_graph = NetworkGraph::new(block_hash, &logger);
+
+               assert_eq!(network_graph.read_only().channels().len(), 0);
+
+               let rapid_sync = RapidGossipSync::new(&network_graph);
+               let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
+               assert!(initialization_result.is_ok());
+
+               let single_direction_incremental_update_input = vec![
+                       76, 68, 75, 1, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
+                       79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 229, 183, 167,
+                       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,
+                       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,
+                       68, 226, 0, 6, 11, 0, 1, 128,
+               ];
+               let update_result_1 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
+               // Apply duplicate update
+               let update_result_2 = rapid_sync.update_network_graph(&single_direction_incremental_update_input[..]);
+               assert!(update_result_1.is_ok());
+               assert!(update_result_2.is_ok());
+       }
+
        #[test]
        fn full_update_succeeds() {
                let valid_input = vec![
@@ -494,4 +525,39 @@ mod tests {
                assert!(after.contains("619737530008010752"));
                assert!(after.contains("783241506229452801"));
        }
+
+       #[test]
+       pub fn update_fails_with_unknown_version() {
+               let unknown_version_input = vec![
+                       76, 68, 75, 2, 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247,
+                       79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, 97, 227, 98, 218,
+                       0, 0, 0, 4, 2, 22, 7, 207, 206, 25, 164, 197, 231, 230, 231, 56, 102, 61, 250, 251,
+                       187, 172, 38, 46, 79, 247, 108, 44, 155, 48, 219, 238, 252, 53, 192, 6, 67, 2, 36, 125,
+                       157, 176, 223, 175, 234, 116, 94, 248, 201, 225, 97, 235, 50, 47, 115, 172, 63, 136,
+                       88, 216, 115, 11, 111, 217, 114, 84, 116, 124, 231, 107, 2, 158, 1, 242, 121, 152, 106,
+                       204, 131, 186, 35, 93, 70, 216, 10, 237, 224, 183, 89, 95, 65, 3, 83, 185, 58, 138,
+                       181, 64, 187, 103, 127, 68, 50, 2, 201, 19, 17, 138, 136, 149, 185, 226, 156, 137, 175,
+                       110, 32, 237, 0, 217, 90, 31, 100, 228, 149, 46, 219, 175, 168, 77, 4, 143, 38, 128,
+                       76, 97, 0, 0, 0, 2, 0, 0, 255, 8, 153, 192, 0, 2, 27, 0, 0, 0, 1, 0, 0, 255, 2, 68,
+                       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,
+                       0, 0, 0, 1, 0, 0, 0, 0, 29, 129, 25, 192, 255, 8, 153, 192, 0, 2, 27, 0, 0, 60, 0, 0,
+                       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,
+                       0, 0, 1, 0, 0, 0, 125, 0, 0, 0, 0, 58, 85, 116, 216, 255, 2, 68, 226, 0, 6, 11, 0, 1,
+                       0, 0, 1,
+               ];
+
+               let block_hash = genesis_block(Network::Bitcoin).block_hash();
+               let logger = TestLogger::new();
+               let network_graph = NetworkGraph::new(block_hash, &logger);
+               let rapid_sync = RapidGossipSync::new(&network_graph);
+               let update_result = rapid_sync.update_network_graph(&unknown_version_input[..]);
+
+               assert!(update_result.is_err());
+
+               if let Err(GraphSyncError::DecodeError(DecodeError::UnknownVersion)) = update_result {
+                       // this is the expected error type
+               } else {
+                       panic!("Unexpected update result: {:?}", update_result)
+               }
+       }
 }