/// of [`KeysManager`] and [`DefaultRouter`].
///
/// This is not exported to bindings users as Arcs don't make sense in bindings
-pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = ChannelManager<&'a M, &'b T, &'c KeysManager, &'c KeysManager, &'c KeysManager, &'d F, &'e DefaultRouter<&'f NetworkGraph<&'g L>, &'g L, &'h Mutex<ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>, ProbabilisticScoringFeeParameters, ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>, &'g L>;
+pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> =
+ ChannelManager<
+ &'a M,
+ &'b T,
+ &'c KeysManager,
+ &'c KeysManager,
+ &'c KeysManager,
+ &'d F,
+ &'e DefaultRouter<
+ &'f NetworkGraph<&'g L>,
+ &'g L,
+ &'h Mutex<ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>>,
+ ProbabilisticScoringFeeParameters,
+ ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L>
+ >,
+ &'g L
+ >;
macro_rules! define_test_pub_trait { ($vis: vis) => {
/// A trivial trait which describes any [`ChannelManager`] used in testing.
///
/// [`confirmations_required`]: ChannelDetails::confirmations_required
pub is_channel_ready: bool,
+ /// The stage of the channel's shutdown.
+ /// `None` for `ChannelDetails` serialized on LDK versions prior to 0.0.116.
+ pub channel_shutdown_state: Option<ChannelShutdownState>,
/// True if the channel is (a) confirmed and channel_ready messages have been exchanged, (b)
/// the peer is connected, and (c) the channel is not currently negotiating a shutdown.
///
inbound_htlc_minimum_msat: Some(context.get_holder_htlc_minimum_msat()),
inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(),
config: Some(context.config()),
+ channel_shutdown_state: Some(context.shutdown_state()),
}
}
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+/// Further information on the details of the channel shutdown.
+/// Upon channels being forced closed (i.e. commitment transaction confirmation detected
+/// by `ChainMonitor`), ChannelShutdownState will be set to `ShutdownComplete` or
+/// the channel will be removed shortly.
+/// Also note, that in normal operation, peers could disconnect at any of these states
+/// and require peer re-connection before making progress onto other states
+pub enum ChannelShutdownState {
+ /// Channel has not sent or received a shutdown message.
+ NotShuttingDown,
+ /// Local node has sent a shutdown message for this channel.
+ ShutdownInitiated,
+ /// Shutdown message exchanges have concluded and the channels are in the midst of
+ /// resolving all existing open HTLCs before closing can continue.
+ ResolvingHTLCs,
+ /// All HTLCs have been resolved, nodes are currently negotiating channel close onchain fee rates.
+ NegotiatingClosingFee,
+ /// We've successfully negotiated a closing_signed dance. At this point `ChannelManager` is about
+ /// to drop the channel.
+ ShutdownComplete,
+}
+
/// Used by [`ChannelManager::list_recent_payments`] to express the status of recent payments.
/// These include payments that have yet to find a successful path, or have unresolved HTLCs.
#[derive(Debug, PartialEq)]
{
/// Constructs a new `ChannelManager` to hold several channels and route between them.
///
+ /// The current time or latest block header time can be provided as the `current_timestamp`.
+ ///
/// This is the main "logic hub" for all channel-related actions, and implements
/// [`ChannelMessageHandler`].
///
/// [`block_connected`]: chain::Listen::block_connected
/// [`block_disconnected`]: chain::Listen::block_disconnected
/// [`params.best_block.block_hash`]: chain::BestBlock::block_hash
- pub fn new(fee_est: F, chain_monitor: M, tx_broadcaster: T, router: R, logger: L, entropy_source: ES, node_signer: NS, signer_provider: SP, config: UserConfig, params: ChainParameters) -> Self {
+ pub fn new(
+ fee_est: F, chain_monitor: M, tx_broadcaster: T, router: R, logger: L, entropy_source: ES,
+ node_signer: NS, signer_provider: SP, config: UserConfig, params: ChainParameters,
+ current_timestamp: u32,
+ ) -> Self {
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
let inbound_pmt_key_material = node_signer.get_inbound_payment_key_material();
probing_cookie_secret: entropy_source.get_secure_random_bytes(),
- highest_seen_timestamp: AtomicUsize::new(0),
+ highest_seen_timestamp: AtomicUsize::new(current_timestamp as usize),
per_peer_state: FairRwLock::new(HashMap::new()),
(35, self.inbound_htlc_maximum_msat, option),
(37, user_channel_id_high_opt, option),
(39, self.feerate_sat_per_1000_weight, option),
+ (41, self.channel_shutdown_state, option),
});
Ok(())
}
(35, inbound_htlc_maximum_msat, option),
(37, user_channel_id_high_opt, option),
(39, feerate_sat_per_1000_weight, option),
+ (41, channel_shutdown_state, option),
});
// `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with
inbound_htlc_minimum_msat,
inbound_htlc_maximum_msat,
feerate_sat_per_1000_weight,
+ channel_shutdown_state,
})
}
}
}
}
+impl_writeable_tlv_based_enum!(ChannelShutdownState,
+ (0, NotShuttingDown) => {},
+ (2, ShutdownInitiated) => {},
+ (4, ResolvingHTLCs) => {},
+ (6, NegotiatingClosingFee) => {},
+ (8, ShutdownComplete) => {}, ;
+);
+
/// Arguments for the creation of a ChannelManager that are not deserialized.
///
/// At a high-level, the process for deserializing a ChannelManager and resuming normal operation
// Note that this is unrealistic as each payment send will require at least two fsync
// calls per node.
let network = bitcoin::Network::Testnet;
+ let genesis_block = bitcoin::blockdata::constants::genesis_block(network);
let tx_broadcaster = test_utils::TestBroadcaster::new(network);
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) };
let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &router, &logger_a, &keys_manager_a, &keys_manager_a, &keys_manager_a, config.clone(), ChainParameters {
network,
best_block: BestBlock::from_network(network),
- });
+ }, genesis_block.header.time);
let node_a_holder = ANodeHolder { node: &node_a };
let logger_b = test_utils::TestLogger::with_id("node a".to_owned());
let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &router, &logger_b, &keys_manager_b, &keys_manager_b, &keys_manager_b, config.clone(), ChainParameters {
network,
best_block: BestBlock::from_network(network),
- });
+ }, genesis_block.header.time);
let node_b_holder = ANodeHolder { node: &node_b };
node_a.peer_connected(&node_b.get_our_node_id(), &Init {