Skip to content

Implement channel closing for block_disconnected on ChainListener + test #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

ariard
Copy link

@ariard ariard commented Jul 17, 2018

I implemented taking care of potential deadlock between channel_state and call to close_channel. Test is really basic, creating a channel, disconnecting blocks and checking it going to LocalShutdownSent state.

for channel in closing_channel {
match self.close_channel(&channel) {
Ok(_msg) => {}
Err(_e) => {} //TODO: if error is stir up by pending HTLC, after timer, try to call close_channel again ?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we have 2 way to handle errors (like pending HTLCs) on channel close: 1/ we return a vec of tuple (channel_id, false) to caller of block_disconnected, 2/ we push a timer on event with a new call to block_disconnected. Former is cumbersome for the caller, latter for dealing internally with timer events.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to be more aggressive. Generally, when dealing with a confirmation-tx-unconf error, we'd really prefer to force-close and initiate the race instead of letting our counterparty participate in the shutdown, as its more of a last-ditch thing. Should be able to just do a force_shutdown() and remove the channel from our channels maps, I think.

@@ -1844,6 +1844,15 @@ impl Channel {
self.channel_update_count
}

pub fn get_channel_id(&self) -> Uint256 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant with channel_id(&self), a few lines up.

}

#[test]
pub fn get_channel_state(&self) -> u32 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'd prefer this not be exposed, especially given we may want to change the enum values at some point without having to recall that the tests use it. It should be easy to instead test for an outbound Shutdown message having been generated to see the close occurring instead of getting the channel state explicitly.

for channel in closing_channel {
match self.close_channel(&channel) {
Ok(_msg) => {}
Err(_e) => {} //TODO: if error is stir up by pending HTLC, after timer, try to call close_channel again ?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to be more aggressive. Generally, when dealing with a confirmation-tx-unconf error, we'd really prefer to force-close and initiate the race instead of letting our counterparty participate in the shutdown, as its more of a last-ditch thing. Should be able to just do a force_shutdown() and remove the channel from our channels maps, I think.

@ariard ariard force-pushed the block_disconnected_close_chan branch from 1e5c0cb to 286cc3a Compare July 19, 2018 01:41
@@ -231,7 +231,7 @@ const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 |

// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling get_channel_id() before we're set up or things like get_outbound_funding_signed on an
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason at first why I added get_channel_id(), but I think that channel_id() is that.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, looking good!

for channel in channel_state.by_id.values_mut() {
if channel.block_disconnected(header) {
//TODO Close channel here
channel.force_shutdown();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to broadcast the transactions returned here.

//TODO Close channel here
channel.force_shutdown();
if let Some(chan_id) = channel.get_short_channel_id() {
closed_channel.push(chan_id.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to remove this by changing the loop to a retain().

@ariard ariard force-pushed the block_disconnected_close_chan branch from 286cc3a to 11adae4 Compare July 20, 2018 00:45
@ariard
Copy link
Author

ariard commented Jul 20, 2018

Updated, spec was unclear on what doing in this case, what theoretically prevent us to just "freeze" the channel and put it again alive if it gets again enough confirmations ? (

fn block_disconnected(&self, header: &BlockHeader) {
let mut closed_channel = Vec::new();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can skip this, too, if you switch back to the borrow_parts() (since borrow_parts() is used to let you get around the borrow checker for stuff like this :))

Copy link
Author

@ariard ariard Jul 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry are you sure it works with closure? I get a E500 or E0499 each time, I'm still a beginner in magic spells against borrowck

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff works for me (though no guarantees about older rustcs, lets see what travis says): https://0bin.net/paste/at3mwfdpXIeugIQ4#X62nrP-X/OYnkLEJ75jrbpR9FRY8DxcOudBzraNDW98

@ariard ariard force-pushed the block_disconnected_close_chan branch from 11adae4 to 1b8544f Compare July 20, 2018 02:38
@ariard
Copy link
Author

ariard commented Jul 20, 2018

Updated, thanks, get it works on 1.22 and my 1.28-nightly!

@TheBlueMatt TheBlueMatt merged commit de523c4 into lightningdevkit:master Jul 20, 2018
@ariard ariard deleted the block_disconnected_close_chan branch September 7, 2018 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants