-
Notifications
You must be signed in to change notification settings - Fork 407
Send channel_update messages to direct peers on private channels #949
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
Send channel_update messages to direct peers on private channels #949
Conversation
Tested - correctly sends a |
cd10b7f
to
586d437
Compare
Fixed tests after rebasing on #954. |
Codecov Report
@@ Coverage Diff @@
## main #949 +/- ##
==========================================
+ Coverage 90.72% 91.68% +0.96%
==========================================
Files 60 60
Lines 30640 35745 +5105
==========================================
+ Hits 27798 32774 +4976
- Misses 2842 2971 +129
Continue to review full report at Codecov.
|
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.
Overall SGTM
a8093ee
to
f00c67d
Compare
7d053b7
to
5b78674
Compare
5b78674
to
314acb5
Compare
Rebased after all dependent PRs were merged. |
2119ccd
to
4d4aeca
Compare
Fixed bench + fuzz failures due to the new messages which they weren't expecting. |
Currently we always generate a `MessageSendEvent::BroadcastChannelUpdate` when a channel is closed even if the channel is private. Our immediate peers should ignore such messages as they haven't seen a corresponding `channel_announcement`, but we are still giving up some privacy by informing our immediate peers of which channels were ours. Here we split `ChannelManager::get_channel_update` into a `get_channel_update_for_broadcast` and `get_channel_update_for_unicast`. The first is used when we are broadcasting a `channel_update`, allowing us to refuse to do so for private channels. The second is used when failing a payment (in which case the recipient has already shown that they are aware of the channel so no such privacy concerns exist).
e2c7163
to
4d4aeca
Compare
4d4aeca
to
6cf22aa
Compare
@@ -3408,7 +3408,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | |||
} | |||
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id)); | |||
} | |||
try_chan_entry!(self, chan.get_mut().channel_update(&msg), channel_state, chan); | |||
let were_node_one = self.get_our_node_id().serialize()[..] < chan.get().get_counterparty_node_id().serialize()[..]; | |||
let msg_from_node_one = msg.contents.flags & 1 == 0; |
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.
Might be nicer to make ChannelFlags
into its own struct and have methods to check who's node_one, etc. Not necessary for this PR though
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.
Yea, that's probably a good idea for the channel_state
in Channel
too, but we can do it later.
/// [`MessageSendEvent::BroadcastChannelUpdate`] event. | ||
/// | ||
/// May be called with channel_state already locked! | ||
fn get_channel_update_for_broadcast(&self, chan: &Channel<Signer>) -> Result<msgs::ChannelUpdate, LightningError> { |
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.
nit: the fn signature is interchangeable with the unicast version, so there's no way to tell if the caller used the wrong one. but there might not be a way to meaningfully improve.
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.
Hmm, yea, happy to do something if you have a specific suggestion but I'm not sure what you really could do there. At least the broadcast
/unicast
naming makes it pretty clear IMO, especially when you're shoving it in a Broadcast
... event
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.
Could have two thin wrappers around msg::ChannelUpdate
for unicast/broadcast, but I haven't looked in detail whether it really makes sense.
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 dunno, its very explicit at the callsite already, making it more explicit doesn't seem like it'll solve anything IMO.
@@ -2947,6 +2981,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | |||
node_id: counterparty_node_id.clone(), | |||
msg: announcement_sigs, | |||
}); | |||
} else if chan.get().is_usable() { | |||
channel_state.pending_msg_events.push(events::MessageSendEvent::SendChannelUpdate { |
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.
is it appropriate to send this message if we haven't seen the locking block?
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.
Hmm, good point. The spec is mum on it (it only mentions that we have to wait until we receive a funding_locked
) see https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#requirements-3 so I think its fine. There isn't a ton of logical reason to wait, either, IMO, its just some fields the counterparty stores locally, so who cares when its received.
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.
OK, something to keep in mind if we see interop issues in this area.
If we are a public node and have a private channel, our counterparty needs to know the fees which we will charge to forward payments to them. Without sending them a channel_update, they have no way to learn that information, resulting in the channel being effectively useless for outbound-from-us payments. This commit fixes our lack of channel_update messages to private channel counterparties, ensuring we always send them a channel_update after the channel funding is confirmed.
If our channel party sends us our own channel_update message, we'll erroneously use the information in that message to update our view of the forwarding parameters our counterparty requires of us, ultimately generating invoices with bogus forwarding information. This fixes that behavior by checking the channel_update's directionality before handling it.
6cf22aa
to
ba600db
Compare
Squashed without diff, will merge after CI:
|
If we are a public node and have a private channel, our
counterparty needs to know the fees which we will charge to forward
payments to them. Without sending them a channel_update, they have
no way to learn that information, resulting in the channel being
effectively useless for outbound-from-us payments.
This commit fixes our lack of channel_update messages to private
channel counterparties, ensuring we always send them a
channel_update after the channel funding is confirmed.
Still need to fix existing tests/add new tests for the new behavior.