/// the "reorg path" (ie call block_disconnected() until you get to a common block and then call
/// block_connected() to step towards your best block) upon deserialization before using the
/// object!
+///
+/// Note that ChannelManager is responsible for tracking liveness of its channels and generating
+/// ChannelUpdate messages informing peers that the channel is temporarily disabled. To avoid
+/// spam due to quick disconnection/reconnection, updates are not sent until the channel has been
+/// offline for a full minute. In order to track this, you must call
+/// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfec.
pub struct ChannelManager<'a> {
default_configuration: UserConfig,
genesis_hash: Sha256dHash,
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), htlc_source.0, &htlc_source.1, HTLCFailReason::Reason { failure_code: 0x4000 | 8, data: Vec::new() });
}
for tx in local_txn {
+ log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
self.tx_broadcaster.broadcast_transaction(&tx);
}
}
events.append(&mut new_events);
}
+ /// If a peer is disconnected we mark any channels with that peer as 'disabled'.
+ /// After some time, if channels are still disabled we need to broadcast a ChannelUpdate
+ /// to inform the network about the uselessness of these channels.
+ ///
+ /// This method handles all the details, and must be called roughly once per minute.
+ pub fn timer_chan_freshness_every_min(&self) {
+ let _ = self.total_consistency_lock.read().unwrap();
+ let mut channel_state_lock = self.channel_state.lock().unwrap();
+ let channel_state = channel_state_lock.borrow_parts();
+ for (_, chan) in channel_state.by_id {
+ if chan.is_disabled_staged() && !chan.is_live() {
+ if let Ok(update) = self.get_channel_update(&chan) {
+ channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
+ msg: update
+ });
+ }
+ chan.to_fresh();
+ } else if chan.is_disabled_staged() && chan.is_live() {
+ chan.to_fresh();
+ } else if chan.is_disabled_marked() {
+ chan.to_disabled_staged();
+ }
+ }
+ }
+
/// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect
/// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources
/// along the path (including in our own channel on which we received it).
}
};
if let Some(broadcast_tx) = tx {
+ log_trace!(self, "Broadcast onchain {}", log_tx!(broadcast_tx));
self.tx_broadcaster.broadcast_transaction(&broadcast_tx);
}
if let Some(chan) = chan_option {
log_debug!(self, "Marking channels with {} disconnected and generating channel_updates", log_pubkey!(their_node_id));
channel_state.by_id.retain(|_, chan| {
if chan.get_their_node_id() == *their_node_id {
- //TODO: mark channel disabled (and maybe announce such after a timeout).
let failed_adds = chan.remove_uncommitted_htlcs_and_mark_paused();
+ chan.to_disabled_marked();
if !failed_adds.is_empty() {
let chan_update = self.get_channel_update(&chan).map(|u| u.encode_with_len()).unwrap(); // Cannot add/recv HTLCs before we have a short_id so unwrap is safe
failed_payments.push((chan_update, failed_adds));