Skip to content

Commit 7591eda

Browse files
authored
Merge pull request #407 from TheBlueMatt/2019-11-396-english
#396 with a few english fixes
2 parents be7d3d1 + fbe3943 commit 7591eda

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,20 @@ const MULTI_STATE_FLAGS: u32 = (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::PeerDis
210210

211211
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
212212

213+
/// Liveness is called to fluctuate given peer disconnecton/monitor failures/closing.
214+
/// If channel is public, network should have a liveness view announced by us on a
215+
/// best-effort, which means we may filter out some status transitions to avoid spam.
216+
/// See further timer_chan_freshness_every_min.
217+
#[derive(PartialEq)]
218+
enum UpdateStatus {
219+
/// Status has been gossiped.
220+
Fresh,
221+
/// Status has been changed.
222+
DisabledMarked,
223+
/// Status has been marked to be gossiped at next flush
224+
DisabledStaged,
225+
}
226+
213227
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
214228
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
215229
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
@@ -340,6 +354,8 @@ pub(super) struct Channel {
340354

341355
channel_monitor: ChannelMonitor,
342356

357+
network_sync: UpdateStatus,
358+
343359
logger: Arc<Logger>,
344360
}
345361

@@ -517,6 +533,8 @@ impl Channel {
517533

518534
channel_monitor: channel_monitor,
519535

536+
network_sync: UpdateStatus::Fresh,
537+
520538
logger,
521539
})
522540
}
@@ -734,6 +752,8 @@ impl Channel {
734752

735753
channel_monitor: channel_monitor,
736754

755+
network_sync: UpdateStatus::Fresh,
756+
737757
logger,
738758
};
739759

@@ -2993,6 +3013,26 @@ impl Channel {
29933013
} else { false }
29943014
}
29953015

3016+
pub fn to_disabled_staged(&mut self) {
3017+
self.network_sync = UpdateStatus::DisabledStaged;
3018+
}
3019+
3020+
pub fn to_disabled_marked(&mut self) {
3021+
self.network_sync = UpdateStatus::DisabledMarked;
3022+
}
3023+
3024+
pub fn to_fresh(&mut self) {
3025+
self.network_sync = UpdateStatus::Fresh;
3026+
}
3027+
3028+
pub fn is_disabled_staged(&self) -> bool {
3029+
self.network_sync == UpdateStatus::DisabledStaged
3030+
}
3031+
3032+
pub fn is_disabled_marked(&self) -> bool {
3033+
self.network_sync == UpdateStatus::DisabledMarked
3034+
}
3035+
29963036
/// Called by channelmanager based on chain blocks being connected.
29973037
/// Note that we only need to use this to detect funding_signed, anything else is handled by
29983038
/// the channel_monitor.
@@ -4091,6 +4131,8 @@ impl<R : ::std::io::Read> ReadableArgs<R, Arc<Logger>> for Channel {
40914131

40924132
channel_monitor,
40934133

4134+
network_sync: UpdateStatus::Fresh,
4135+
40944136
logger,
40954137
})
40964138
}

lightning/src/ln/channelmanager.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assum
318318
/// the "reorg path" (ie call block_disconnected() until you get to a common block and then call
319319
/// block_connected() to step towards your best block) upon deserialization before using the
320320
/// object!
321+
///
322+
/// Note that ChannelManager is responsible for tracking liveness of its channels and generating
323+
/// ChannelUpdate messages informing peers that the channel is temporarily disabled. To avoid
324+
/// spam due to quick disconnection/reconnection, updates are not sent until the channel has been
325+
/// offline for a full minute. In order to track this, you must call
326+
/// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfec.
321327
pub struct ChannelManager<'a> {
322328
default_configuration: UserConfig,
323329
genesis_hash: Sha256dHash,
@@ -1488,6 +1494,31 @@ impl<'a> ChannelManager<'a> {
14881494
events.append(&mut new_events);
14891495
}
14901496

1497+
/// If a peer is disconnected we mark any channels with that peer as 'disabled'.
1498+
/// After some time, if channels are still disabled we need to broadcast a ChannelUpdate
1499+
/// to inform the network about the uselessness of these channels.
1500+
///
1501+
/// This method handles all the details, and must be called roughly once per minute.
1502+
pub fn timer_chan_freshness_every_min(&self) {
1503+
let _ = self.total_consistency_lock.read().unwrap();
1504+
let mut channel_state_lock = self.channel_state.lock().unwrap();
1505+
let channel_state = channel_state_lock.borrow_parts();
1506+
for (_, chan) in channel_state.by_id {
1507+
if chan.is_disabled_staged() && !chan.is_live() {
1508+
if let Ok(update) = self.get_channel_update(&chan) {
1509+
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
1510+
msg: update
1511+
});
1512+
}
1513+
chan.to_fresh();
1514+
} else if chan.is_disabled_staged() && chan.is_live() {
1515+
chan.to_fresh();
1516+
} else if chan.is_disabled_marked() {
1517+
chan.to_disabled_staged();
1518+
}
1519+
}
1520+
}
1521+
14911522
/// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect
14921523
/// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources
14931524
/// along the path (including in our own channel on which we received it).
@@ -2797,8 +2828,8 @@ impl<'a> ChannelMessageHandler for ChannelManager<'a> {
27972828
log_debug!(self, "Marking channels with {} disconnected and generating channel_updates", log_pubkey!(their_node_id));
27982829
channel_state.by_id.retain(|_, chan| {
27992830
if chan.get_their_node_id() == *their_node_id {
2800-
//TODO: mark channel disabled (and maybe announce such after a timeout).
28012831
let failed_adds = chan.remove_uncommitted_htlcs_and_mark_paused();
2832+
chan.to_disabled_marked();
28022833
if !failed_adds.is_empty() {
28032834
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
28042835
failed_payments.push((chan_update, failed_adds));

lightning/src/ln/functional_tests.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6256,3 +6256,63 @@ fn test_check_htlc_underpaying() {
62566256
}
62576257
nodes[1].node.get_and_clear_pending_events();
62586258
}
6259+
6260+
#[test]
6261+
fn test_announce_disable_channels() {
6262+
// Create 2 channels between A and B. Disconnect B. Call timer_chan_freshness_every_min and check for generated
6263+
// ChannelUpdate. Reconnect B, reestablish and check there is non-generated ChannelUpdate.
6264+
6265+
let nodes = create_network(2, &[None, None]);
6266+
6267+
let short_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new()).0.contents.short_channel_id;
6268+
let short_id_2 = create_announced_chan_between_nodes(&nodes, 1, 0, LocalFeatures::new(), LocalFeatures::new()).0.contents.short_channel_id;
6269+
let short_id_3 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new()).0.contents.short_channel_id;
6270+
6271+
// Disconnect peers
6272+
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
6273+
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
6274+
6275+
nodes[0].node.timer_chan_freshness_every_min(); // dirty -> stagged
6276+
nodes[0].node.timer_chan_freshness_every_min(); // staged -> fresh
6277+
let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
6278+
assert_eq!(msg_events.len(), 3);
6279+
for e in msg_events {
6280+
match e {
6281+
MessageSendEvent::BroadcastChannelUpdate { ref msg } => {
6282+
let short_id = msg.contents.short_channel_id;
6283+
// Check generated channel_update match list in PendingChannelUpdate
6284+
if short_id != short_id_1 && short_id != short_id_2 && short_id != short_id_3 {
6285+
panic!("Generated ChannelUpdate for wrong chan!");
6286+
}
6287+
},
6288+
_ => panic!("Unexpected event"),
6289+
}
6290+
}
6291+
// Reconnect peers
6292+
nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
6293+
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
6294+
assert_eq!(reestablish_1.len(), 3);
6295+
nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
6296+
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
6297+
assert_eq!(reestablish_2.len(), 3);
6298+
6299+
// Reestablish chan_1
6300+
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]).unwrap();
6301+
handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
6302+
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]).unwrap();
6303+
handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
6304+
// Reestablish chan_2
6305+
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[1]).unwrap();
6306+
handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
6307+
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[1]).unwrap();
6308+
handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
6309+
// Reestablish chan_3
6310+
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[2]).unwrap();
6311+
handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
6312+
nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[2]).unwrap();
6313+
handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
6314+
6315+
nodes[0].node.timer_chan_freshness_every_min();
6316+
let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
6317+
assert_eq!(msg_events.len(), 0);
6318+
}

0 commit comments

Comments
 (0)