Skip to content

Refactor ChannelTransactionParameters into FundingScope #3604

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

jkczyz
Copy link
Contributor

@jkczyz jkczyz commented Feb 14, 2025

Continues the work of #3592 by moving fields related to the funding transaction into FundingScope. This includes fields from ChannelContext for the funding transaction and ChannelTransactionParameters for the funding outpoint and pubkeys.

This primarily involves moving the entire ChannelTransactionParameters into FundingScope and channel_value_satoshis into ChannelTransactionParameters. The latter result in less API churn at the cost of duplicating parameters that don't change across each FundingScope. To that end, this PR also updates the EcdsaChannelSigner to take ChannelTransactionParameters which removes the need for ChannelSigner::provide_channel_parameters.

Since ChannelTransactionParameters contains channel_value_satoshis, implementation like InMemorySigner no longer need it. Thus, the NodeSigner trait is updated to no longer take the value when deriving signers, which is a breaking change.

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 14, 2025

@wpaulino This primarily moves fields from ChannelContext and duplicates the funding outpoint pubkeys from ChannelTransactionParameters into FundingScope. I skimmed through sign.rs to see how this would be affected. Thinking on it a bit, I'm wondering if instead of duplicating those fields we instead move the entire ChannelTransactionParameters from ChannelContext into FundingScope.

The drawback is we'd be duplicating fields that wouldn't change. But this seems better than duplicating fields that would change and risk having inconsistent data. Also, it could prevent us from needing to worry about changing other uses of ChannelTransactionParameters (e.g., by ChannelMonitor and OnchainTxHandler), outside needing to pass the appropriate ChannelTransactionParameters. Maybe we could reduce the duplication when persisting ChannelMonitor, though.

What are your thoughts?

@wpaulino
Copy link
Contributor

I was thinking we could deprecate the funding scope related fields from ChannelTransactionParameters and eventually remove them, so there wouldn't be any duplicate data in the long run.

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 18, 2025

I was thinking we could deprecate the funding scope related fields from ChannelTransactionParameters and eventually remove them, so there wouldn't be any duplicate data in the long run.

Yeah, this PR takes that approach. But when removing the fields we'd need to update all uses to take both ChannelTransactionParameters and FundingScope anywhere ChannelTransactionParameters is currently needed. So I'm wondering more based on the current uses if it makes sense to include the entire ChannelTransactionParameters in FundingScope?

For instance, writing an OnchainTxHandler writes ChannelTransactionParameters. So removing the deprecated fields would require a custom serialization to include the removed fields from FundingScope. And presumably OnchainTxHandler wouldn't need the other FundingScope fields since it currently doesn't.

There's also DirectedChannelTransactionParameters which has broadcaster_pubkeys and countersignatory_pubkeys methods where the returned ChannelPublicKeys needs to include the funding_pubkey. So we'd need to have AnchorDescriptor hold a FundingScope, for instance, and have a similar Directed variation. But all those additional fields in FundingScope aren't relevant.

I haven't looked exhaustively to see all usages, but it seems simpler to keep ChannelTransactionParameters as it is.

@wpaulino
Copy link
Contributor

Hm, I'm not opposed to always writing ChannelTransactionParameters, especially given the name already conveys it's tied to a specific channel transaction. It would also cover for any other currently static parameters changing due to some future protocol feature/upgrade. We would still be breaking the API somewhat since they are currently intended to be static throughout the channel's lifetime, but we can think of something there.

As for OnchainTxHandler, it will already need to know of the scope (or a subset of its fields) somehow to carry out signing requests. I'd love to avoid all of that completely by having the auxiliary data come from the claim request being handled, but that seems like quite the big change.

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 19, 2025

@wpaulino
Copy link
Contributor

Here's the alternative approach: https://github.com/jkczyz/rust-lightning/tree/2025-02-channel-funding-pubkeys-alt

Yeah this looks pretty simple, and would also allow us to handle transitioning to new channel types in a splice since it already tracks the channel type features. I don't think the duplicate data is all that bad here once we have multiple scopes since it will eventually go away when the splice confirms. We should at least be able to avoid persisting the duplicate data, if we choose to, by cloning it from the "main" (currently confirmed) scope when reading.

Thoughts on either of these approaches @TheBlueMatt?

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 20, 2025

@TheBlueMatt Added some more commits to the alternative branch after pairing with @wpaulino yesterday. They move channel_value_satoshis from FundingScope to ChannelTransactionParameters, which will be passed to EcdsaChannelSigner methods in lieu of calling provide_channel_parameters. This is done so far for sign_counterparty_commitment. The goal would be to get rid channel_value_satoshis and channel_parameters from InMemorySigner and instead access them through the passed ChannelTransactionParameters.

@TheBlueMatt
Copy link
Collaborator

Discussed this being supersceded by an alternative that tries to keep signer operations (across many splice versions) together as one call.

@jkczyz jkczyz force-pushed the 2025-02-channel-funding-pubkeys branch 2 times, most recently from df840cb to aff70ae Compare February 25, 2025 00:56
@jkczyz jkczyz changed the title Refactor funding-tx-related fields into FundingScope Refactor ChannelTransactionParameters into FundingScope Feb 25, 2025
Copy link

codecov bot commented Feb 25, 2025

Codecov Report

Attention: Patch coverage is 75.09579% with 65 lines in your changes missing coverage. Please review.

Project coverage is 88.59%. Comparing base (c9fd3a5) to head (aff70ae).

Files with missing lines Patch % Lines
lightning/src/util/test_channel_signer.rs 51.51% 9 Missing and 23 partials ⚠️
lightning/src/sign/mod.rs 76.13% 11 Missing and 10 partials ⚠️
lightning/src/ln/channelmanager.rs 85.29% 2 Missing and 3 partials ⚠️
lightning/src/util/test_utils.rs 50.00% 4 Missing ⚠️
lightning/src/chain/channelmonitor.rs 92.30% 0 Missing and 1 partial ⚠️
lightning/src/chain/onchaintx.rs 85.71% 0 Missing and 1 partial ⚠️
lightning/src/events/bump_transaction.rs 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3604      +/-   ##
==========================================
- Coverage   88.60%   88.59%   -0.02%     
==========================================
  Files         151      151              
  Lines      118409   118404       -5     
  Branches   118409   118404       -5     
==========================================
- Hits       104918   104900      -18     
+ Misses      10972    10968       -4     
- Partials     2519     2536      +17     

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

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 25, 2025

Updated the branch to use the alternative version. See updated PR description for details.

@jkczyz jkczyz marked this pull request as ready for review February 25, 2025 01:05
@jkczyz jkczyz added the weekly goal Someone wants to land this this week label Feb 25, 2025
@jkczyz jkczyz force-pushed the 2025-02-channel-funding-pubkeys branch 3 times, most recently from 339e0ca to a55149f Compare February 26, 2025 01:24
@@ -882,7 +882,9 @@ pub struct ChannelTransactionParameters {
pub funding_outpoint: Option<chain::transaction::OutPoint>,
/// This channel's type, as negotiated during channel open. For old objects where this field
/// wasn't serialized, it will default to static_remote_key at deserialization.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since we're providing these to the signer on every call now (and there's so much redundant data) I wonder if (I guess it could happen when we do splicing) we shouldn't have some partial-comparator for these that just checks that two of them are equal for the fields that shouldn't change across a splice?

@wpaulino
Copy link
Contributor

CI is sad

@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 26, 2025

CI is sad

Fixed now, I think. Will make add pending CHANGELOG item in a bit. For now, PTAL.

@jkczyz jkczyz requested a review from TheBlueMatt February 26, 2025 20:53
Rather than moving relevant fields of ChannelTransactionParameters to
FundingScope, move the entire struct there instead. This prevents API
churn wherever ChannelTransactionParameters is used, which otherwise
would need a FundingScope in addition.
Since the funding transactions changes for each new FudningScope,
include it there instead of ChannelContext.
InMemorySigner no longer holds channel_value_satoshis and
channel_parameters. Instead of writing 0 and None, respectively, drop
(de-)serialization support entirely since InMemorySigner hasn't been
serialized since SERIALIZATION_VERSION 2.
Since channel_value_satoshis is needed by the signer and may change for
each new FundingScope, included it in ChannelTransactionParameters so it
can be passed to each signer call in the upcoming commits.
Now that ChannelTransactionParameters are in FundingScope,
channel_value_satoshis can be dropped from the latter.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, pass the entire parameters when calling
each method on EcdsaChannelSigner. This will remove the need for
ChannelSigner::provide_channel_parameters. Instead, the parameters from
the FundingScope will be passed in to each method. This simplifies the
interaction with a ChannelSigner when needing to be called for more than
one FundingScope, which will be the case for pending splices and RBF
attempts.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, InMemorySigner no longer needs a copy.
Remove uses of the copy from sign_counterparty_payment_input.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, InMemorySigner no longer needs a copy.
Remove indirect uses of the copy from TestChannelSigner.
Now that the copy of ChannelTransactionParameters is no longer used by
InMemorySigner, remove it and all remaining uses. Since it was set by
ChannelSigner::provide_channel_parameters, this method is no longer
needed and can also be removed.
Now that channel_value_satoshis has been moved to
ChannelTransactionParameters, it no longer needs to be used when
deriving a signer. This is a breaking API change, though InMemorySigner
did not make use of channel_value_satoshis when being derived.
The custom derive_channel_signer methods on AnchorDescriptor and
HTLCDescriptor simply delegate to the passed SignerProvider now that
providing ChannelTransactionParameters is no longer needed. Drop these
methods and replace them with the method bodies at the call sites.
@wpaulino
Copy link
Contributor

Needs a rebase

@jkczyz jkczyz force-pushed the 2025-02-channel-funding-pubkeys branch from 3ce8659 to 0d127cf Compare February 27, 2025 20:23
@jkczyz
Copy link
Contributor Author

jkczyz commented Feb 27, 2025

Rebased to resolve merge conflicts.

@jkczyz jkczyz requested a review from wpaulino February 27, 2025 20:23
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.

Gonna land this but there's a few things here for a followup.

@@ -10311,21 +10327,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch

let latest_monitor_update_id = Readable::read(reader)?;

let mut keys_data = None;
if ver <= 2 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should explicitly reject reads of channels <= version 2.

Comment on lines +10653 to +10654
// ChannelTransactionParameters::channel_value_satoshis defaults to 0 prior to version 0.2.
channel_parameters.channel_value_satoshis = channel_value_satoshis;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can be dropped now.

pub(crate) fn make_funding_redeemscript(&self) -> ScriptBuf {
make_funding_redeemscript(
&self.holder_pubkeys.funding_pubkey,
&self.counterparty_parameters.as_ref().unwrap().pubkeys.funding_pubkey
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm really not a fan of a hidden unwrap. In general I think we should reconsider ChannelTransactionParameters to remove the many unwraps it generates - we should probably have something that requires the counterparty parameters as the type we use everywhere, with Channel having its own internal type which has them optional where required. This is quite old code so needs some refreshing...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, agreed. @wpaulino discussed a future refactor where ChannelTransactionParameters becomes two structs, where one transitions to the other when the counterparty's keys are obtained in order to avoid the Option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
weekly goal Someone wants to land this this week
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants