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

Handle fallible per commitment point for RAA #3150

Merged

Conversation

alecchendev
Copy link
Contributor

@alecchendev alecchendev commented Jun 30, 2024

Builds on #3149.

This is the first PR to handle async get_per_commitment_point, and only handles the Err cases for retrieving revoke_and_ack. We still need to handle this during funding (#3109) and channel reestablish (no PR yet) in upcoming PRs.

For all async signing, we try to go about our normal business, and when we fail to get a signature from our signer, we pause our channel, and only unpause upon the user calling ChannelManager::signer_unblocked. With the signer_pending_revoke_and_ack flag being added in the prereq PR, we simply set the flag and allow get_last_revoke_and_ack to return an Option. We also make sure that in cases where we must send RAA then CS, that we defer sending a CS (even if it's available) until the signature for the RAA is unblocked.

@codecov-commenter
Copy link

codecov-commenter commented Jun 30, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 79.48718% with 24 lines in your changes missing coverage. Please review.

Project coverage is 90.02%. Comparing base (6035c83) to head (45c0a0f).
Report is 20 commits behind head on main.

Files Patch % Lines
lightning/src/ln/channel.rs 77.66% 20 Missing and 3 partials ⚠️
lightning/src/util/test_channel_signer.rs 80.00% 0 Missing and 1 partial ⚠️

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

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3150      +/-   ##
==========================================
+ Coverage   89.74%   90.02%   +0.27%     
==========================================
  Files         121      121              
  Lines       99858   103150    +3292     
  Branches    99858   103150    +3292     
==========================================
+ Hits        89622    92863    +3241     
- Misses       7561     7646      +85     
+ Partials     2675     2641      -34     

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

@alecchendev
Copy link
Contributor Author

(rebased after changes to #3149)

@TheBlueMatt
Copy link
Collaborator

Looks like the test code doesn't currently compile on this one.

lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
lightning/src/sign/mod.rs Outdated Show resolved Hide resolved
@alecchendev alecchendev force-pushed the 2024-06-async-commit-point-raa branch 3 times, most recently from 6bf0b5a to 28f4678 Compare July 10, 2024 01:25
TheBlueMatt
TheBlueMatt previously approved these changes Jul 10, 2024
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.

LGTM, feel free to squash we'll need to get a second review to glance.

log_trace!(logger, "Last revoke-and-ack pending in channel {} for sequence {} because the next per-commitment point is not available",
&self.context.channel_id(), self.context.holder_commitment_point.transaction_number());
self.context.signer_pending_revoke_and_ack = true;
None
Copy link
Collaborator

Choose a reason for hiding this comment

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

It might be worth mentioning in a comment why we don't want to send an RAA here. If we have HolderCommitmentPoint::PendingNext we still have current and can in theory build a RevokeAndACK, but if we send one immediately in response to a commitment_signed we'll just get another commitment_signed and be out of points anyway and unable to send a RevokeAndACK, and avoiding sending the RAA is a neat way to avoid having to deal with ever actually not having the current point available. Obviously once we make release_commitment_secret async we'll have to block on the signer anyway, so blocking here on a different signer operation doesnt add latency and simplifies our code by making our peer be blocked waiting on our signer, not just us.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

squashed + added a comment for this

lightning/src/ln/async_signer_tests.rs Outdated Show resolved Hide resolved
lightning/src/sign/mod.rs Outdated Show resolved Hide resolved
lightning/src/sign/mod.rs Show resolved Hide resolved
lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
lightning/src/ln/channel.rs Show resolved Hide resolved
lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
// in revoke_and_ack, which requires unblocking our signer and completing
// the advance to the next point. So if we get here, either we've messed
// up, or our counterparty has.
debug_assert!(false, "We should be ready to advance our commitment point by the time we receive commitment_signed");
Copy link
Contributor

Choose a reason for hiding this comment

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

To be clear, is this reachable with a misbehaving counterparty? Because we're currently closing the channel after advancing some state above like the latest monitor update id, may be worth adding some test coverage for this (maybe in follow-up)

Copy link
Collaborator

Choose a reason for hiding this comment

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

It shouldn't be. Without our commitment point provided in the last RAA our counterparty shouldn't be able to give us a CS that passes our signature checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, i think maybe a way to handle this is to check self.holder_commitment_point.is_available() with our checks above before we start updating state, then when we get here it's easier to know that this is unreachable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

or maybe just move this to be the first thing we update?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't feel strongly since Matt clarified that this should be unreachable. Could also update the comment to be more explicit about that, or what you suggested, up to you!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

just updated the last sentence of the comment to clarify this should be unreachable

lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
self.get_last_commitment_update_for_send(logger).ok()
} else { None };
if self.context.resend_order == RAACommitmentOrder::CommitmentFirst
&& self.context.signer_pending_commitment_update && raa.is_some() {
self.context.signer_pending_revoke_and_ack = true;
raa = None;
}
if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
&& self.context.signer_pending_revoke_and_ack {
self.context.signer_pending_commitment_update = true;
Copy link
Contributor

@valentinewallace valentinewallace Jul 11, 2024

Choose a reason for hiding this comment

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

Tests pass with this and the line below commented out

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added some test cases to cover here + the similar condition added in channel reestablish

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, tests still pass with these lines commented out. I don't wanna hold up the PR, though, so feel free to save this for follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, are you running with RUSTFLAGS="--cfg=async_signing"? they seem to fail when i comment out locally for me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nvm you're right specifically commenting out the self.context.signer_pending_commitment_update = true; still passes, will add coverage for this in a followup

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh you were right, I was using the cfg flag last review but not this one lol. But yeah sounds good!

Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

Need to revisit the last non-test commit tomorrow and I'm still somewhat playing catch-up with the past signer work but this should be close. Thanks for tackling async signing!

lightning/src/ln/channel.rs Show resolved Hide resolved
lightning/src/ln/channel.rs Show resolved Hide resolved
@alecchendev alecchendev force-pushed the 2024-06-async-commit-point-raa branch 2 times, most recently from ce899fa to 39da43c Compare July 12, 2024 20:39
Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

LGTM after squash. There are a few places missing test coverage but I'm good to save them for follow-up.

self.get_last_commitment_update_for_send(logger).ok()
} else { None };
if self.context.resend_order == RAACommitmentOrder::CommitmentFirst
&& self.context.signer_pending_commitment_update && raa.is_some() {
self.context.signer_pending_revoke_and_ack = true;
raa = None;
}
if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
&& self.context.signer_pending_revoke_and_ack {
self.context.signer_pending_commitment_update = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, tests still pass with these lines commented out. I don't wanna hold up the PR, though, so feel free to save this for follow-up.

let commitment_update = if self.context.resend_order == RAACommitmentOrder::RevokeAndACKFirst
&& self.context.signer_pending_revoke_and_ack {
log_trace!(logger, "Reconnected channel {} with lost outbound RAA and lost remote commitment tx, but unable to send due to resend order, waiting on signer for revoke and ack", &self.context.channel_id());
self.context.signer_pending_commitment_update = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing coverage here

@alecchendev alecchendev force-pushed the 2024-06-async-commit-point-raa branch from 39da43c to daa9baf Compare July 15, 2024 18:41
@alecchendev
Copy link
Contributor Author

squashed with one small change updating the comment for this. Planning to add more test coverage in a follow up

Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

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

LGTM if CI's happy ✨

TheBlueMatt
TheBlueMatt previously approved these changes Jul 15, 2024
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.

Lets land it! We can do followups or whatever.

lightning/src/ln/channel.rs Outdated Show resolved Hide resolved
lightning/src/sign/mod.rs Outdated Show resolved Hide resolved
Includes simple changes to test util signers and tests, as well as
handling the error case for get_per_commitment_point in
HolderCommitmentPoint. This leaves a couple `.expect`s in places
that will be addressed in a separate PR for handling funding.
Note: this does not test the CS -> RAA resend ordering, because this
requires handling async get_per_commitment_point for channel
reestablishment, which will be addressed in a follow up PR.
@alecchendev
Copy link
Contributor Author

failed rustfmt so i just fixed the nits

@TheBlueMatt
Copy link
Collaborator

Changes since @valentinewallace's ACK are pretty trivial, worst case we can hash them out in a followup:

$ git diff-tree -U1  daa9baf 45c0a0f
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 2bed16bc5..be9d2d3ea 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -5499,5 +5499,5 @@ impl<SP: Deref> Channel<SP> where

-	fn get_last_revoke_and_ack<L: Deref>(&mut self, _logger: &L) -> Option<msgs::RevokeAndACK> where L::Target: Logger {
+	fn get_last_revoke_and_ack<L: Deref>(&mut self, logger: &L) -> Option<msgs::RevokeAndACK> where L::Target: Logger {
 		debug_assert!(self.context.holder_commitment_point.transaction_number() <= INITIAL_COMMITMENT_NUMBER - 2);
-		self.context.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, _logger);
+		self.context.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
 		let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.holder_commitment_point.transaction_number() + 2);
@@ -5523,3 +5523,3 @@ impl<SP: Deref> Channel<SP> where
 				// we're only ever waiting on one commitment point at a time.
-				log_trace!(_logger, "Last revoke-and-ack pending in channel {} for sequence {} because the next per-commitment point is not available",
+				log_trace!(logger, "Last revoke-and-ack pending in channel {} for sequence {} because the next per-commitment point is not available",
 					&self.context.channel_id(), self.context.holder_commitment_point.transaction_number());
diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs
index 49f62a5bd..d684b4fe6 100644
--- a/lightning/src/sign/mod.rs
+++ b/lightning/src/sign/mod.rs
@@ -1358,4 +1358,5 @@ impl ChannelSigner for InMemorySigner {
 		let commitment_secret =
-			SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx));
-		commitment_secret.map(|secret| PublicKey::from_secret_key(secp_ctx, &secret)).map_err(|_| ())
+			SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx))
+				.unwrap();
+		Ok(PublicKey::from_secret_key(secp_ctx, &commitment_secret))
 	}
$

@TheBlueMatt TheBlueMatt merged commit 17d5baa into lightningdevkit:main Jul 16, 2024
15 of 17 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