-
Notifications
You must be signed in to change notification settings - Fork 417
Add splice-out support #3979
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
base: main
Are you sure you want to change the base?
Add splice-out support #3979
Conversation
🎉 This PR is now ready for review! |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3979 +/- ##
==========================================
- Coverage 88.94% 88.93% -0.02%
==========================================
Files 174 174
Lines 124200 124211 +11
Branches 124200 124211 +11
==========================================
- Hits 110471 110462 -9
- Misses 11253 11261 +8
- Partials 2476 2488 +12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
acab158
to
2d39059
Compare
Splice contributions should never exceed the total bitcoin supply. This check prevents a potential overflow when converting the contribution from sats to msats. The commit additionally begins to store the contribution using SignedAmount.
…text Once the counterparty supplies their funding contribution, there is no longer a need to store it in FundingNegotiationContext as it will have already been used to create a FundingScope.
Specify what inputs and outputs to contribute to a funding transaction using an enum. This will make the splice-in and upcoming splice-out use cases explicit.
TransactionU16LenLimited was used to limit Transaction serialization size to u16::MAX. This was because messages can not be longer than u16::MAX bytes when serialized for the transport layer. However, this limit doesn't take into account other fields in a message containing a Transaction, including the length of the transaction itself. Remove TransactionU16LenLimited and instead check any user supplied transactions in the context of the enclosing message (e.g. TxAddInput).
In preparation for having ChannelManager::splice_channel take FundingTxContributions, add a weight to the FundingTxContributions::InputsOnly, which supports the splice-in use case.
Using FundingTxContributions for ChannelManager::splice_channel allows supporting both splice-in and splice-out using the same method, with a descriptive enum for the contributions.
Update FundingTxContributions with a variant used to support splice-out (i.e., removing funds from a channel). The TxOut values must not exceed the users channel balance after accounting for fees and the reserve requirement.
2d39059
to
381fba6
Compare
🔔 1st Reminder Hey @wpaulino! This PR has been waiting for your review. |
pub enum FundingTxContributions { | ||
/// When only inputs -- except for a possible change output -- are contributed to the funding | ||
/// transaction. This must correspond to a positive contribution amount. | ||
InputsOnly { |
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.
We should also include the contribution amount in each variant as they'll be slightly different: InputsOnly
must be > 0, OutputsOnly
must be < 0, and the mixed case can be SignedAmount
.
@@ -6071,6 +6074,30 @@ impl FundingNegotiationContext { | |||
} | |||
} | |||
|
|||
/// The components of a funding transaction that are contributed by one party. | |||
pub enum FundingTxContributions { |
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.
Does this mean we'll have higher-level variants for splicing and dual-funding that map to this one? I would like being able to name these SpliceIn/Out
for splicing.
shared_input_txid: None, | ||
}; | ||
let message_len = MESSAGE_TEMPLATE.serialized_length() + tx.serialized_length(); | ||
if message_len > u16::MAX as usize { |
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: use LN_MAX_MSG_LEN
let message_len = MESSAGE_TEMPLATE.serialized_length() + tx.serialized_length(); | ||
if message_len > u16::MAX as usize { | ||
return Err(APIError::APIMisuseError { | ||
err: format!("Funding input's prevtx is too large for tx_add_input"), |
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: include the index or outpoint in the error
@@ -6079,7 +6081,7 @@ pub enum FundingTxContributions { | |||
InputsOnly { | |||
/// The inputs used to meet the contributed amount. Any excess amount will be sent to a | |||
/// change output. | |||
inputs: Vec<(TxIn, Transaction)>, | |||
inputs: Vec<(TxIn, Transaction, Weight)>, |
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.
Let's make this a struct now so we can properly document each field. The weight here should be the witness_weight
for the input to be spent. We may even be able to reuse bump_transaction::Utxo
.
@@ -1894,6 +1894,7 @@ pub(super) fn calculate_change_output_value( | |||
.get(txin.previous_output.vout as usize) | |||
.ok_or(AbortReason::PrevTxOutInvalid)?; | |||
total_input_satoshis = total_input_satoshis.saturating_add(output.value.to_sat()); | |||
// FIXME: Can we use the Weight from context.funding_tx_contributions.inputs()? |
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.
Yes, but that weight is only for the witness, so we'd also have to account for BASE_INPUT_WEIGHT
and EMPTY_SCRIPT_SIG_WEIGHT
for each input.
}, | ||
/// When both inputs and outputs are contributed to the funding transaction. | ||
#[cfg(test)] | ||
InputsAndOutputs { |
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 we should wait to add this as a follow-up
our_funding_contribution_satoshis, | ||
); | ||
// FIXME: Should we check value_to_self instead? Do HTLCs need to be accounted for? | ||
// FIXME: Check that we can pay for the outputs from the channel value? |
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.
We probably don't even need our_funding_contribution
for a splice out, we can just assume it from adding all the output values
self.funding.get_value_satoshis(), | ||
our_funding_contribution_satoshis, | ||
); | ||
// FIXME: Should we check value_to_self instead? Do HTLCs need to be accounted for? |
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.
Definitely value_to_self
, and we need to make sure we stay above the reserve and can still afford fees if we're the channel initiator
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
Splice-in support was added in #3736. This PR expands
ChannelManager::splice_channel
to support splice-out (i.e., removing funds from a channel). This is accomplished by adding aFundingTxContributions
enum to cover both use cases.Depends on #3736.