-
Notifications
You must be signed in to change notification settings - Fork 411
Disconnect announcement_signatures sending from funding_locked #1179
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
Disconnect announcement_signatures sending from funding_locked #1179
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1179 +/- ##
==========================================
+ Coverage 90.36% 90.38% +0.01%
==========================================
Files 69 69
Lines 36794 36980 +186
==========================================
+ Hits 33249 33424 +175
- Misses 3545 3556 +11
Continue to review full report at Codecov.
|
76e84b4
to
cc7a03a
Compare
@@ -3604,8 +3596,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | |||
return; | |||
} | |||
|
|||
let updates = channel.get_mut().monitor_updating_restored(&self.logger); | |||
let channel_update = if updates.funding_locked.is_some() && channel.get().is_usable() && !channel.get().should_announce() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think since we dropped the !channel.get().should_announce()
(why did we drop that?) the comment below needs amending (i.e. s/only generating a unicast channel_update if this is a private channel//)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, good point. Updated the comment. There's not really a good reason for or against sending it twice here, its kinda nice to just send it and remove the check to simplify things down, though, IMO.
cc7a03a
to
f4d944f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shaping up!
let announcement_sigs = if let Some((genesis_block_hash, node_pk)) = genesis_node_pk { | ||
self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger) | ||
} else { None }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To simplify, think you can move this call to get_announcement_sigs
outside the if let Some(funding_locked) ..
and get rid of the second call below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_announcement_sigs
updates our "message sent" state, so we really can't call it unless we're definitely about to return Ok
.
@@ -4182,7 +4296,8 @@ impl<Signer: Sign> Channel<Signer> { | |||
// may have already happened for this block). | |||
if let Some(funding_locked) = self.check_get_funding_locked(height) { | |||
log_info!(logger, "Sending a funding_locked to our peer for channel {}", log_bytes!(self.channel_id)); | |||
return Ok(Some(funding_locked)); | |||
let announcement_sigs = self.get_announcement_sigs(node_pk, genesis_block_hash, height, logger); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it'd make more sense if we always called get_announcement_sigs
at the beginning and always return its result (i.e. we'd also return its result at L4311, not just here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check_get_funding_locked
updates our local state flags, though, so it has to come after that.
@@ -3192,6 +3252,8 @@ impl<Signer: Sign> Channel<Signer> { | |||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preexisting, but I think it'd overall be nicer if we replaced each time we construct msgs::FundingLocked
(e.g. 4 lines up and elsewhere) with a call to check_get_funding_locked(..)
. Then that method could be responsible for setting self.monitor_pending_funding_locked = false
, and it's DRYer/more encapsulated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check_get_funding_locked
is a bit of a misnomer - it updates state and isn't really just a getter, its really just part of the block/transaction-connection logic refactored out into a poorly-named function :/
Squashed. |
94243a8
to
c4b22c3
Compare
This removes one more place where we directly access the node_id secret key in `ChannelManager`, slowly marching towards allowing the node_id secret key to be offline in the signer. More importantly, it allows more ChannelAnnouncement logic to move into the `Channel` without having to pass the node secret key around, avoiding the announcement logic being split across two files.
c4b22c3
to
a11bee9
Compare
Rebased to update the TLV numbering due to conflicts. |
lightning/src/ln/channel.rs
Outdated
/// for both loose and in response to an AnnouncementSignatures message from the remote peer. | ||
/// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly | ||
/// announceable and available for use (have exchanged FundingLocked messages in both | ||
/// directions). Should be used for both loose and in response to an AnnouncementSignatures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does "should be used for loose" mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this resolved...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reworked the documentation to no longer say "loose".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it looks like the updated comment was put in ed1163a
a11bee9
to
91b7b1f
Compare
Codecov Report
@@ Coverage Diff @@
## main #1179 +/- ##
==========================================
+ Coverage 90.38% 90.41% +0.03%
==========================================
Files 71 70 -1
Lines 38182 38315 +133
==========================================
+ Hits 34509 34643 +134
+ Misses 3673 3672 -1
Continue to review full report at Codecov.
|
This improves readability and makes it easier to add additional return fields.
While its generally harmless to do so (the messages will simply be dropped in `PeerManager`) there is a potential race condition where the FundingLocked message enters the outbound message queue, then the peer reconnects, and then the FundingLocked message is delivered prior to the normal ChannelReestablish flow. We also take this opportunity to rewrite `test_funding_peer_disconnect` to be explicit instead of using `reconnect_peers`. This allows it to check each message being sent carefully, whereas `reconnect_peers` is rather lazy and accepts that sometimes signatures will be exchanged, and sometimes not.
If we have not yet sent `funding_locked` only because of a pending channel monitor update, we shouldn't consider a channel `is_usable`. This has a number of downstream effects, including not attempting to route payments through the channel, not sending private `channel_update` messages to our counterparty, or sending channel_announcement messages if our couterparty has already signed for it. We further gate generation of `node_announcement`s on `is_usable`, preventing generation of those or `announcement_signatures` until we've sent our `funding_locked`. Finally, `during_funding_monitor_fail` is updated to test a case where we see the funding transaction lock in but have a pending monitor update failure, then receive `funding_locked` from our counterparty and ensure we don't generate the above messages until after the monitor update completes.
The spec actually requires we never send `announcement_signatures` (and, thus, `channel_announcement`s) until after six confirmations. However, we would happily have sent them prior to that as long as we exchange `funding_locked` messages with our countarparty. Thanks to re-broadcasting this issue is largely harmless, however it could have some negative interactions with less-robust peers. Much more importantly, this represents an important step towards supporting 0-conf channels, where `funding_locked` messages may be exchanged before we even have an SCID to construct the messages with. Because there is no ACK mechanism for `announcement_signatures` we rely on existing channel updates to stop rebroadcasting them - if we sent a `commitment_signed` after an `announcement_signatures` and later receive a `revoke_and_ack`, we know our counterparty also received our `announcement_signatures`. This may resolve some rare edge-cases where we send a `funding_locked` which our counterparty receives, but lose connection before the `announcement_signatures` (usually the very next message) arrives. Sadly, because the set of places where an `announcement_signatures` may now be generated more closely mirrors where `funding_locked` messages may be generated, but they are now separate, there is a substantial amount of code motion providing relevant parameters about current block information and ensuring we can return new `announcement_signatures` messages.
Channel::get_announcement_sigs is only used in contexts where we have a logger already, and the error returned is always ignored, so instead of returning an ignored error message we return an `Option` directly and log when it won't be too verbose.
91b7b1f
to
ed1163a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACKing
One aside: it's "Disconnect" with two _n_s. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nits. ACK ed1163a
/// Will only fail if we're not in a state where channel_announcement may be sent (including | ||
/// closing). | ||
/// | ||
/// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see | ||
/// https://github.com/lightningnetwork/lightning-rfc/issues/468 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This issue is closed, does this need updating?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix in a followup PR, since this has two acks.
lightning/src/ln/channel.rs
Outdated
/// for both loose and in response to an AnnouncementSignatures message from the remote peer. | ||
/// Gets an UnsignedChannelAnnouncement for this channel. The channel must be publicly | ||
/// announceable and available for use (have exchanged FundingLocked messages in both | ||
/// directions). Should be used for both loose and in response to an AnnouncementSignatures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, it looks like the updated comment was put in ed1163a
The spec actually requires we never send
announcement_signatures
(and, thus,
channel_announcement
s) until after six confirmations.However, we would happily have sent them prior to that as long as
we exchange
funding_locked
messages with our countarparty. Thanksto re-broadcasting this issue is largely harmless, however it could
have some negative interactions with less-robust peers. Much more
importantly, this represents an important step towards supporting
0-conf channels, where
funding_locked
messages may be exchangedbefore we even have an SCID to construct the messages with.
Because there is no ACK mechanism for
announcement_signatures
werely on existing channel updates to stop rebroadcasting them - if
we sent a
commitment_signed
after anannouncement_signatures
and later receive a
revoke_and_ack
, we know our counterparty alsoreceived our
announcement_signatures
. This may resolve some rareedge-cases where we send a
funding_locked
which our counterpartyreceives, but lose connection before the
announcement_signatures
(usually the very next message) arrives.
Sadly, because the set of places where an
announcement_signatures
may now be generated more closely mirrors where
funding_locked
messages may be generated, but they are now separate, there is a
substantial amount of code motion providing relevant parameters
about current block information and ensuring we can return new
announcement_signatures
messages.