Skip to content
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

Move channel -> peer tracking to OutPoints from Channel IDs #2795

Merged

Conversation

TheBlueMatt
Copy link
Collaborator

For backwards compatibility reasons, we need to track a mapping
from funding outpoints to channel ids. To reduce diff, this was
previously done with channel IDs, converting the OutPoints to
channel IDs before using the map.

This worked fine, but is somewhat brittle - because we allow
redundant channel IDs across different peers, we had to avoid
insertion until we had a real channel ID, and thus also had to be
careful to avoid removal unless we were using a real channel ID,
rather than a temporary one.

This brittleness actually crept in to handling of errors in funding
acceptance, allowing a remote party to get us to remove an entry by
sending a overlapping temporary channel ID with a separate real
channel ID.

Luckily, this map is relatively infrequently used, only used in the
case we see a monitor update completion from a rather ancient
monitor which is unaware of the counterparty node.

Even after this change, the channel -> peer tracking storage is
still somewhat brittle, as we rely on entries not being added until
we are confident no conflicting OutPoints have been used across
channels, and similarly not removing unless that check has
completed.

For backwards compatibility reasons, we need to track a mapping
from funding outpoints to channel ids. To reduce diff, this was
previously done with channel IDs, converting the `OutPoint`s to
channel IDs before using the map.

This worked fine, but is somewhat brittle - because we allow
redundant channel IDs across different peers, we had to avoid
insertion until we had a real channel ID, and thus also had to be
careful to avoid removal unless we were using a real channel ID,
rather than a temporary one.

This brittleness actually crept in to handling of errors in funding
acceptance, allowing a remote party to get us to remove an entry by
sending a overlapping temporary channel ID with a separate real
channel ID.

Luckily, this map is relatively infrequently used, only used in the
case we see a monitor update completion from a rather ancient
monitor which is unaware of the counterparty node.

Even after this change, the channel -> peer tracking storage is
still somewhat brittle, as we rely on entries not being added until
we are confident no conflicting `OutPoint`s have been used across
channels, and similarly not removing unless that check has
completed.
Historically, `ChannelMonitor`s had idea who their counterparty
was. This was fine, until `ChannelManager` started indexing by
peer, at which point it needed to know the counterparty when it saw
a `ChannelMonitorUpdate` complete. To address this, a "temporary"
map from channel ID to peer was added, but no upgrade path was
created for existing `ChannelMonitor`s to not rely on this map.

This commit adds such an upgrade path, setting the
`counterparty_node_id` on all `ChannelMonitor`s as they're updated,
allowing us to eventually break backwards compatibility and remove
`ChannelManager::outpoint_to_peer`.
Now that we provide the counterparty node id, we can set logging
metadata with a counterparty node id and and channel id, which we
do here.
@TheBlueMatt TheBlueMatt added this to the 0.0.119 milestone Dec 14, 2023
@TheBlueMatt
Copy link
Collaborator Author

Oops, fixed one more case pointed out by @wpaulino .

wpaulino
wpaulino previously approved these changes Dec 14, 2023
@wpaulino
Copy link
Contributor

error[E0425]: cannot find value `err` in this scope
    --> lightning/src/ln/channelmanager.rs:6313:16
     |
6313 |                 fail_chan!(err);

wpaulino
wpaulino previously approved these changes Dec 14, 2023
@codecov-commenter
Copy link

codecov-commenter commented Dec 14, 2023

Codecov Report

Attention: 15 lines in your changes are missing coverage. Please review.

Comparison is base (68e25c6) 88.62% compared to head (08ee5b2) 90.08%.
Report is 60 commits behind head on main.

❗ Current head 08ee5b2 differs from pull request most recent head e9452c7. Consider uploading reports for the commit e9452c7 to get more accurate results

Files Patch % Lines
lightning/src/ln/channelmanager.rs 91.13% 6 Missing and 1 partial ⚠️
lightning/src/chain/channelmonitor.rs 73.33% 3 Missing and 1 partial ⚠️
lightning/src/chain/chainmonitor.rs 0.00% 2 Missing ⚠️
lightning/src/ln/channel.rs 90.90% 2 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2795      +/-   ##
==========================================
+ Coverage   88.62%   90.08%   +1.45%     
==========================================
  Files         115      115              
  Lines       91221    98770    +7549     
  Branches    91221    98770    +7549     
==========================================
+ Hits        80844    88975    +8131     
+ Misses       7922     7416     -506     
+ Partials     2455     2379      -76     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

lightning/src/ln/channelmanager.rs Show resolved Hide resolved
lightning/src/ln/functional_tests.rs Outdated Show resolved Hide resolved
lightning/src/ln/functional_tests.rs Outdated Show resolved Hide resolved
lightning/src/ln/functional_tests.rs Outdated Show resolved Hide resolved
lightning/src/ln/channelmanager.rs Show resolved Hide resolved
@TheBlueMatt
Copy link
Collaborator Author

Addressed dangling comment reference introduced in an intermediate PR:

$ git diff-tree -U1 4dceeace 08ee5b2ddiff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index cbc0d8647..6a101dff3 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -6243,4 +6243,4 @@ where
 			// `update_maps_on_chan_removal`), we'll remove the existing channel
-			// from `id_to_peer`. Thus, we must first unset the funding outpoint on
-			// the channel.
+			// from `outpoint_to_peer`. Thus, we must first unset the funding outpoint
+			// on the channel.
 			let err = ChannelError::Close($err.to_owned());
diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs
index 05510eac6..fca6abb35 100644
--- a/lightning/src/ln/functional_tests.rs
+++ b/lightning/src/ln/functional_tests.rs
@@ -8973,6 +8973,6 @@ fn test_duplicate_temporary_channel_id_from_different_peers() {
 #[test]
-fn test_duplicate_funding_funding_err() {
+fn test_duplicate_funding_err_in_funding() {
 	// Test that if we have a live channel with one peer, then another peer comes along and tries
 	// to create a second channel with the same txid we'll fail and not overwrite the
-	// outpoint_to_channel map in `ChannelManager`.
+	// outpoint_to_peer map in `ChannelManager`.
 	//

// on the channel.
let err = ChannelError::Close($err.to_owned());
chan.unset_funding_info(msg.temporary_channel_id);
return Err(convert_chan_phase_err!(self, err, &mut ChannelPhase::Funded(chan), &funded_channel_id).1);
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't matter what ChannelPhase is used here, right? I think ChannelPhase variants could use some docs, hard to tell that this is the correct phase here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It doesnt. The only thing that changes is whether we broadcast a closing channel_update, which we won't anyway cause we don't have an SCID.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sadly the struct is type Channel which means we have to use Funded. That said, its clearly "wrong" - the channel is not (any longer) funded, I skipped the phase wrapping and used the macro form that explicitly states the funding status.

return Err(MsgHandleErrInternal::send_err_msg_no_close(
"The funding_created message had the same funding_txid as an existing channel - funding is not possible".to_owned(),
channel_id));
fail_chan!("Duplicate funding outpoint");
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing test coverage for this change. It looks like a behavior change? Doesn't seem harmful though and the spec doesn't seem to weigh in on what to do here.

Copy link
Collaborator Author

@TheBlueMatt TheBlueMatt Dec 15, 2023

Choose a reason for hiding this comment

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

We absolutely need to fail here. If we have two channels open with the same funding we'll happily let that funding amount get double-counted. But, its not a behavior change, we always failed here (the channel has been taken out of the map, we're just gonna drop it either way).

When we fail to accept a counterparty's funding for various
reasons, we should ensure we call the correct cleanup methods in
`internal_funding_created` to remove the temporary data for the
channel in our various internal structs (primarily the SCID alias
map).

This adds the missing cleanup, using `convert_chan_phase_err`
consistently in all the error paths.

This also ensures we get a `ChannelClosed` event when relevant.
@TheBlueMatt
Copy link
Collaborator Author

I went ahead and changed the failure macro to call the UNFUNDED_CHANNEL variant. While it doesn't change anything (except not bothering to call get_channel_update_for_broadcast, which will always fail anyway), it still seems more correct and potentially less likely to cause issues later.

$ git diff-tree -U3 08ee5b2d e9452c70diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 6a101dff3..08296c434 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -6245,7 +6245,7 @@ where
 			// on the channel.
 			let err = ChannelError::Close($err.to_owned());
 			chan.unset_funding_info(msg.temporary_channel_id);
-			return Err(convert_chan_phase_err!(self, err, &mut ChannelPhase::Funded(chan), &funded_channel_id).1);
+			return Err(convert_chan_phase_err!(self, err, chan, &funded_channel_id, UNFUNDED_CHANNEL).1);
 		} } }

 		match peer_state.channel_by_id.entry(funded_channel_id) {

@wpaulino wpaulino merged commit f5e87d8 into lightningdevkit:main Dec 15, 2023
13 of 15 checks passed
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.

4 participants