Update ChannelUpdate::timestamp when channels are dis-/en-abled

We update the `Channel::update_time_counter` field (which is copied
into `ChannelUpdate::timestamp`) only when the channel is
initialized or closes, and when a new block is connected. However,
if a peer disconnects or reconnects, we may wish to generate
`ChannelUpdate` updates in between new blocks. In such a case, we
need to make sure the `timestamp` field is newer than any previous
updates' `timestamp` fields, which we do here by simply
incrementing it when the channel status is changed.

As a side effect of this we have to update
`test_background_processor` to ensure it eventually succeeds even
if the serialization of the `ChannelManager` changes after the test
begins.
This commit is contained in:
Matt Corallo 2021-11-13 01:06:09 +00:00
parent 74828d2435
commit 8f89371bae
3 changed files with 20 additions and 15 deletions

View file

@ -493,9 +493,10 @@ mod tests {
macro_rules! check_persisted_data { macro_rules! check_persisted_data {
($node: expr, $filepath: expr, $expected_bytes: expr) => { ($node: expr, $filepath: expr, $expected_bytes: expr) => {
match $node.write(&mut $expected_bytes) { loop {
Ok(()) => { $expected_bytes.clear();
loop { match $node.write(&mut $expected_bytes) {
Ok(()) => {
match std::fs::read($filepath) { match std::fs::read($filepath) {
Ok(bytes) => { Ok(bytes) => {
if bytes == $expected_bytes { if bytes == $expected_bytes {
@ -506,9 +507,9 @@ mod tests {
}, },
Err(_) => continue Err(_) => continue
} }
} },
}, Err(e) => panic!("Unexpected error: {}", e)
Err(e) => panic!("Unexpected error: {}", e) }
} }
} }
} }

View file

@ -4167,6 +4167,7 @@ impl<Signer: Sign> Channel<Signer> {
} }
pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) { pub fn set_channel_update_status(&mut self, status: ChannelUpdateStatus) {
self.update_time_counter += 1;
self.channel_update_status = status; self.channel_update_status = status;
} }

View file

@ -7313,9 +7313,9 @@ fn test_announce_disable_channels() {
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let short_id_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
let short_id_2 = create_announced_chan_between_nodes(&nodes, 1, 0, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; create_announced_chan_between_nodes(&nodes, 1, 0, InitFeatures::known(), InitFeatures::known());
let short_id_3 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
// Disconnect peers // Disconnect peers
nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
@ -7325,13 +7325,13 @@ fn test_announce_disable_channels() {
nodes[0].node.timer_tick_occurred(); // DisabledStaged -> Disabled nodes[0].node.timer_tick_occurred(); // DisabledStaged -> Disabled
let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 3); assert_eq!(msg_events.len(), 3);
let mut chans_disabled: HashSet<u64> = [short_id_1, short_id_2, short_id_3].iter().map(|a| *a).collect(); let mut chans_disabled = HashMap::new();
for e in msg_events { for e in msg_events {
match e { match e {
MessageSendEvent::BroadcastChannelUpdate { ref msg } => { MessageSendEvent::BroadcastChannelUpdate { ref msg } => {
assert_eq!(msg.contents.flags & (1<<1), 1<<1); // The "channel disabled" bit should be set assert_eq!(msg.contents.flags & (1<<1), 1<<1); // The "channel disabled" bit should be set
// Check that each channel gets updated exactly once // Check that each channel gets updated exactly once
if !chans_disabled.remove(&msg.contents.short_channel_id) { if chans_disabled.insert(msg.contents.short_channel_id, msg.contents.timestamp).is_some() {
panic!("Generated ChannelUpdate for wrong chan!"); panic!("Generated ChannelUpdate for wrong chan!");
} }
}, },
@ -7367,19 +7367,22 @@ fn test_announce_disable_channels() {
nodes[0].node.timer_tick_occurred(); nodes[0].node.timer_tick_occurred();
let msg_events = nodes[0].node.get_and_clear_pending_msg_events(); let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 3); assert_eq!(msg_events.len(), 3);
chans_disabled = [short_id_1, short_id_2, short_id_3].iter().map(|a| *a).collect();
for e in msg_events { for e in msg_events {
match e { match e {
MessageSendEvent::BroadcastChannelUpdate { ref msg } => { MessageSendEvent::BroadcastChannelUpdate { ref msg } => {
assert_eq!(msg.contents.flags & (1<<1), 0); // The "channel disabled" bit should be off assert_eq!(msg.contents.flags & (1<<1), 0); // The "channel disabled" bit should be off
// Check that each channel gets updated exactly once match chans_disabled.remove(&msg.contents.short_channel_id) {
if !chans_disabled.remove(&msg.contents.short_channel_id) { // Each update should have a higher timestamp than the previous one, replacing
panic!("Generated ChannelUpdate for wrong chan!"); // the old one.
Some(prev_timestamp) => assert!(msg.contents.timestamp > prev_timestamp),
None => panic!("Generated ChannelUpdate for wrong chan!"),
} }
}, },
_ => panic!("Unexpected event"), _ => panic!("Unexpected event"),
} }
} }
// Check that each channel gets updated exactly once
assert!(chans_disabled.is_empty());
} }
#[test] #[test]