fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
let logger = test_logger::TestLogger::new("".to_owned(), out);
let network_graph = lightning::routing::gossip::NetworkGraph::new(bitcoin::Network::Bitcoin, &logger);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let _ = rapid_sync.update_network_graph(data);
}
let params = ChainParameters { network, best_block };
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), router.clone(), logger.clone(), keys_manager.clone(), keys_manager.clone(), keys_manager.clone(), UserConfig::default(), params));
let p2p_gossip_sync = Arc::new(P2PGossipSync::new(network_graph.clone(), Some(chain_source.clone()), logger.clone()));
- let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone()));
+ let rapid_gossip_sync = Arc::new(RapidGossipSync::new(network_graph.clone(), logger.clone()));
let msg_handler = MessageHandler { chan_handler: Arc::new(test_utils::TestChannelMessageHandler::new()), route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: IgnoringMessageHandler{}};
let peer_manager = Arc::new(PeerManager::new(msg_handler, 0, &seed, logger.clone(), IgnoringMessageHandler{}, keys_manager.clone()));
let node = Node { node: manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, persister, tx_broadcaster, network_graph, logger, best_block, scorer };
//! # let logger = FakeLogger {};
//!
//! let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
-//! let rapid_sync = RapidGossipSync::new(&network_graph);
+//! let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
//! let snapshot_contents: &[u8] = &[0; 0];
//! let new_last_sync_timestamp_result = rapid_sync.update_network_graph(snapshot_contents);
//! ```
pub struct RapidGossipSync<NG: Deref<Target=NetworkGraph<L>>, L: Deref>
where L::Target: Logger {
network_graph: NG,
+ logger: L,
is_initial_sync_complete: AtomicBool
}
impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
/// Instantiate a new [`RapidGossipSync`] instance.
- pub fn new(network_graph: NG) -> Self {
+ pub fn new(network_graph: NG, logger: L) -> Self {
Self {
network_graph,
+ logger,
is_initial_sync_complete: AtomicBool::new(false)
}
}
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let sync_result = rapid_sync.sync_network_graph_with_file_path(&graph_sync_test_file);
if sync_result.is_err() {
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let start = std::time::Instant::now();
let sync_result = rapid_sync
.sync_network_graph_with_file_path("./res/full_graph.lngossip");
let logger = TestLogger::new();
b.iter(|| {
let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let sync_result = rapid_sync.sync_network_graph_with_file_path("./res/full_graph.lngossip");
if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-bc08df7542-2022-05-05.bin\n\n{:?}", io_error);
};
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
+use lightning::{log_warn, log_trace, log_given_level};
use lightning::util::ser::{BigSize, Readable};
use lightning::io;
if let ErrorAction::IgnoreDuplicateGossip = lightning_error.action {
// everything is fine, just a duplicate channel announcement
} else {
+ log_warn!(self.logger, "Failed to process channel announcement: {:?}", lightning_error);
return Err(lightning_error.into());
}
}
if (channel_flags & 0b_1000_0000) != 0 {
// incremental update, field flags will indicate mutated values
let read_only_network_graph = network_graph.read_only();
- if let Some(channel) = read_only_network_graph
- .channels()
- .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,
- })?;
-
+ if let Some(directional_info) =
+ read_only_network_graph.channels().get(&short_channel_id)
+ .and_then(|channel| channel.get_directional_info(channel_flags))
+ {
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 {
+ log_trace!(self.logger,
+ "Skipping application of channel update for chan {} with flags {} as original data is missing.",
+ short_channel_id, channel_flags);
skip_update_for_unknown_channel = true;
}
};
match network_graph.update_channel_unsigned(&synthetic_update) {
Ok(_) => {},
Err(LightningError { action: ErrorAction::IgnoreDuplicateGossip, .. }) => {},
- Err(LightningError { action: ErrorAction::IgnoreAndLog(_), .. }) => {},
+ Err(LightningError { action: ErrorAction::IgnoreAndLog(level), err }) => {
+ log_given_level!(self.logger, level, "Failed to apply channel update: {:?}", err);
+ },
Err(LightningError { action: ErrorAction::IgnoreError, .. }) => {},
Err(e) => return Err(e.into()),
}
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,
0, 3, 232, 0, 0, 0,
];
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph(&example_input[..]);
assert!(update_result.is_err());
if let Err(GraphSyncError::DecodeError(DecodeError::ShortRead)) = update_result {
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph(&incremental_update_input[..]);
assert!(update_result.is_ok());
}
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
- let update_result = rapid_sync.update_network_graph(&announced_update_input[..]);
- assert!(update_result.is_err());
- if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
- assert_eq!(
- lightning_error.err,
- "Couldn't find previous directional data for update"
- );
- } else {
- panic!("Unexpected update result: {:?}", update_result)
- }
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
+ rapid_sync.update_network_graph(&announced_update_input[..]).unwrap();
}
#[test]
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
if initialization_result.is_err() {
panic!(
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 = rapid_sync.update_network_graph(&opposite_direction_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 previous directional data for update"
- );
- } else {
- panic!("Unexpected update result: {:?}", update_result)
- }
+ rapid_sync.update_network_graph(&opposite_direction_incremental_update_input[..]).unwrap();
}
#[test]
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
assert!(initialization_result.is_ok());
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let initialization_result = rapid_sync.update_network_graph(&initialization_input[..]);
assert!(initialization_result.is_ok());
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph(&VALID_RGS_BINARY);
if update_result.is_err() {
panic!("Unexpected update result: {:?}", update_result)
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
// this is mostly for checking uint underflow issues before the fuzzer does
let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(0));
assert!(update_result.is_ok());
let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(latest_succeeding_time));
assert!(update_result.is_ok());
assert_eq!(network_graph.read_only().channels().len(), 2);
let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
assert_eq!(network_graph.read_only().channels().len(), 0);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph_no_std(&VALID_RGS_BINARY, Some(earliest_failing_time));
assert!(update_result.is_err());
if let Err(GraphSyncError::LightningError(lightning_error)) = update_result {
let logger = TestLogger::new();
let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
- let rapid_sync = RapidGossipSync::new(&network_graph);
+ let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
let update_result = rapid_sync.update_network_graph(&unknown_version_input[..]);
assert!(update_result.is_err());
/// actually backed by a [`HashMap`], with some additional tracking to ensure we can iterate over
/// keys in the order defined by [`Ord`].
///
+/// (C-not exported) as bindings provide alternate accessors rather than exposing maps directly.
+///
/// [`BTreeMap`]: alloc::collections::BTreeMap
#[derive(Clone, Debug, Eq)]
pub struct IndexedMap<K: Hash + Ord, V> {
}
/// An iterator over a range of values in an [`IndexedMap`]
+///
+/// (C-not exported) as bindings provide alternate accessors rather than exposing maps directly.
pub struct Range<'a, K: Hash + Ord, V> {
inner_range: Iter<'a, K>,
map: &'a HashMap<K, V>,
}
/// An [`Entry`] for a key which currently has no value
+///
+/// (C-not exported) as bindings provide alternate accessors rather than exposing maps directly.
pub struct VacantEntry<'a, K: Hash + Ord, V> {
#[cfg(feature = "hashbrown")]
underlying_entry: hash_map::VacantEntry<'a, K, V, hash_map::DefaultHashBuilder>,
}
/// An [`Entry`] for an existing key-value pair
+///
+/// (C-not exported) as bindings provide alternate accessors rather than exposing maps directly.
pub struct OccupiedEntry<'a, K: Hash + Ord, V> {
#[cfg(feature = "hashbrown")]
underlying_entry: hash_map::OccupiedEntry<'a, K, V, hash_map::DefaultHashBuilder>,
/// A mutable reference to a position in the map. This can be used to reference, add, or update the
/// value at a fixed key.
+///
+/// (C-not exported) as bindings provide alternate accessors rather than exposing maps directly.
pub enum Entry<'a, K: Hash + Ord, V> {
/// A mutable reference to a position within the map where there is no value.
Vacant(VacantEntry<'a, K, V>),
($logger: expr, $lvl:expr, $($arg:tt)+) => (
match $lvl {
#[cfg(not(any(feature = "max_level_off")))]
- $crate::util::logger::Level::Error => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Error => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(not(any(feature = "max_level_off", feature = "max_level_error")))]
- $crate::util::logger::Level::Warn => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Warn => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(not(any(feature = "max_level_off", feature = "max_level_error", feature = "max_level_warn")))]
- $crate::util::logger::Level::Info => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Info => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(not(any(feature = "max_level_off", feature = "max_level_error", feature = "max_level_warn", feature = "max_level_info")))]
- $crate::util::logger::Level::Debug => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Debug => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(not(any(feature = "max_level_off", feature = "max_level_error", feature = "max_level_warn", feature = "max_level_info", feature = "max_level_debug")))]
- $crate::util::logger::Level::Trace => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Trace => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(not(any(feature = "max_level_off", feature = "max_level_error", feature = "max_level_warn", feature = "max_level_info", feature = "max_level_debug", feature = "max_level_trace")))]
- $crate::util::logger::Level::Gossip => log_internal!($logger, $lvl, $($arg)*),
+ $crate::util::logger::Level::Gossip => $crate::log_internal!($logger, $lvl, $($arg)*),
#[cfg(any(feature = "max_level_off", feature = "max_level_error", feature = "max_level_warn", feature = "max_level_info", feature = "max_level_debug", feature = "max_level_trace"))]
_ => {
#[macro_export]
macro_rules! log_error {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Error, $($arg)*);
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Error, $($arg)*);
)
}
#[macro_export]
macro_rules! log_warn {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Warn, $($arg)*);
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Warn, $($arg)*);
)
}
#[macro_export]
macro_rules! log_info {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Info, $($arg)*);
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Info, $($arg)*);
)
}
#[macro_export]
macro_rules! log_debug {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Debug, $($arg)*);
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Debug, $($arg)*);
)
}
#[macro_export]
macro_rules! log_trace {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Trace, $($arg)*)
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Trace, $($arg)*)
)
}
#[macro_export]
macro_rules! log_gossip {
($logger: expr, $($arg:tt)*) => (
- log_given_level!($logger, $crate::util::logger::Level::Gossip, $($arg)*);
+ $crate::log_given_level!($logger, $crate::util::logger::Level::Gossip, $($arg)*);
)
}
/// Writer that only tracks the amount of data written - useful if you need to calculate the length
/// of some data when serialized but don't yet need the full data.
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct LengthCalculatingWriter(pub usize);
impl Writer for LengthCalculatingWriter {
#[inline]
/// Essentially [`std::io::Take`] but a bit simpler and with a method to walk the underlying stream
/// forward to ensure we always consume exactly the fixed length specified.
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct FixedLengthReader<R: Read> {
read: R,
bytes_read: u64,
/// A [`Read`] implementation which tracks whether any bytes have been read at all. This allows us to distinguish
/// between "EOF reached before we started" and "EOF reached mid-read".
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct ReadTrackingReader<R: Read> {
read: R,
/// Returns whether we have read from this reader or not yet.
}
/// Wrapper to read a required (non-optional) TLV record.
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct RequiredWrapper<T>(pub Option<T>);
impl<T: Readable> Readable for RequiredWrapper<T> {
#[inline]
/// Wrapper to read a required (non-optional) TLV record that may have been upgraded without
/// backwards compat.
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct UpgradableRequired<T: MaybeReadable>(pub Option<T>);
impl<T: MaybeReadable> MaybeReadable for UpgradableRequired<T> {
#[inline]
/// A type for variable-length values within TLV record where the length is encoded as part of the record.
/// Used to prevent encoding the length twice.
+///
+/// (C-not exported) as manual TLV building is not currently supported in bindings
pub struct WithoutLength<T>(pub T);
impl Writeable for WithoutLength<&String> {