-
Notifications
You must be signed in to change notification settings - Fork 450
Include failure context in splice events #4514
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?
Changes from all commits
2f8125b
1035615
f320e58
47bd416
3cd1d05
b51a7d5
36c511b
f707945
2fd414e
e834852
df6b58b
e34b3ac
4a57ac8
8946f49
bfabcb5
3ee03ae
8b0148a
d35271c
44ecc06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ use crate::blinded_path::payment::{ | |
| use crate::chain::transaction; | ||
| use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; | ||
| use crate::ln::channelmanager::{InterceptId, PaymentId}; | ||
| use crate::ln::funding::FundingContribution; | ||
| use crate::ln::msgs; | ||
| use crate::ln::onion_utils::LocalHTLCFailureReason; | ||
| use crate::ln::outbound_payment::RecipientOnionFields; | ||
|
|
@@ -99,6 +100,65 @@ impl_writeable_tlv_based_enum!(FundingInfo, | |
| } | ||
| ); | ||
|
|
||
| /// The reason a funding negotiation round failed. | ||
| /// | ||
| /// Each negotiation attempt (initial or RBF) resolves to either success or failure. This enum | ||
| /// indicates what caused the failure. | ||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||
| pub enum NegotiationFailureReason { | ||
| /// The reason was not available (e.g., from an older serialization). | ||
| Unknown, | ||
| /// The peer disconnected during negotiation. Retry by calling | ||
| /// [`ChannelManager::splice_channel`] after the peer reconnects. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| PeerDisconnected, | ||
| /// The counterparty aborted the negotiation by sending `tx_abort`. Retry by calling | ||
| /// [`ChannelManager::splice_channel`], or wait for the counterparty to initiate. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| CounterpartyAborted, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the "Message data" in |
||
| /// An error occurred while negotiating the interactive transaction (e.g., the counterparty | ||
| /// sent an invalid message). Retry by calling [`ChannelManager::splice_channel`]. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| NegotiationError, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note we could have this wrap |
||
| /// The funding contribution was invalid (e.g., insufficient balance for the splice amount). | ||
| /// Adjust the contribution and retry via [`ChannelManager::splice_channel`]. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| ContributionInvalid, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does seem like some of these could use more details (error message string?). As-is given the recommendation for ~all enum variants is "retry by calling
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, the docs could be improved here. Maybe re-calling So it does seem like different actions are required depending on the variant.
We could have a top-level
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably not other than when / how should you retry in case of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose given we don't know when the peer will reconnect, we might as well just process it the same and call |
||
| /// The negotiation was locally abandoned via `ChannelManager::abandon_splice`. | ||
| LocallyAbandoned, | ||
| /// The channel was not in a state to accept the funding contribution. Retry by calling | ||
| /// [`ChannelManager::splice_channel`] once [`ChannelDetails::is_usable`] returns `true`. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| /// [`ChannelDetails::is_usable`]: crate::ln::channel_state::ChannelDetails::is_usable | ||
| ChannelNotReady, | ||
| /// The channel is closing, so the negotiation cannot continue. See [`Event::ChannelClosed`] | ||
| /// for the closure reason. | ||
| ChannelClosing, | ||
| /// The contribution's feerate was too low. Retry with a higher feerate by calling | ||
| /// [`ChannelManager::splice_channel`] to obtain a new [`FundingTemplate`]. | ||
| /// | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| /// [`FundingTemplate`]: crate::ln::funding::FundingTemplate | ||
| FeeRateTooLow, | ||
| } | ||
|
|
||
| impl_writeable_tlv_based_enum_upgradable!(NegotiationFailureReason, | ||
| (0, Unknown) => {}, | ||
| (2, PeerDisconnected) => {}, | ||
| (4, CounterpartyAborted) => {}, | ||
| (6, NegotiationError) => {}, | ||
| (8, ContributionInvalid) => {}, | ||
| (10, LocallyAbandoned) => {}, | ||
| (12, ChannelNotReady) => {}, | ||
| (14, ChannelClosing) => {}, | ||
| (16, FeeRateTooLow) => {}, | ||
| ); | ||
|
|
||
| /// Some information provided on receipt of payment depends on whether the payment received is a | ||
| /// spontaneous payment or a "conventional" lightning payment that's paying an invoice. | ||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||
|
|
@@ -1541,8 +1601,8 @@ pub enum Event { | |
| /// # Failure Behavior and Persistence | ||
| /// This event will eventually be replayed after failures-to-handle (i.e., the event handler | ||
| /// returning `Err(ReplayEvent ())`) and will be persisted across restarts. | ||
| SplicePending { | ||
| /// The `channel_id` of the channel that has a pending splice funding transaction. | ||
| SpliceNegotiated { | ||
| /// The `channel_id` of the channel with the negotiated splice funding transaction. | ||
| channel_id: ChannelId, | ||
| /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound | ||
| /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels. | ||
|
|
@@ -1560,19 +1620,20 @@ pub enum Event { | |
| /// The witness script that is used to lock the channel's funding output to commitment transactions. | ||
| new_funding_redeem_script: ScriptBuf, | ||
| }, | ||
| /// Used to indicate that a splice for the given `channel_id` has failed. | ||
| /// Used to indicate that a splice negotiation round for the given `channel_id` has failed. | ||
| /// | ||
| /// This event may be emitted if a splice fails after it has been initiated but prior to signing | ||
| /// any negotiated funding transaction. | ||
| /// Each splice attempt (initial or RBF) resolves to either [`Event::SpliceNegotiated`] on | ||
| /// success or this event on failure. Prior successfully negotiated splice transactions are | ||
| /// unaffected. | ||
| /// | ||
| /// Any UTXOs contributed to be spent by the funding transaction may be reused and will be | ||
| /// given in `contributed_inputs`. | ||
| /// Any UTXOs contributed to the failed round that are not committed to a prior negotiated | ||
| /// splice transaction will be returned via a preceding [`Event::DiscardFunding`]. | ||
| /// | ||
| /// # Failure Behavior and Persistence | ||
| /// This event will eventually be replayed after failures-to-handle (i.e., the event handler | ||
| /// returning `Err(ReplayEvent ())`) and will be persisted across restarts. | ||
| SpliceFailed { | ||
| /// The `channel_id` of the channel for which the splice failed. | ||
| SpliceNegotiationFailed { | ||
| /// The `channel_id` of the channel for which the splice negotiation round failed. | ||
| channel_id: ChannelId, | ||
| /// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound | ||
| /// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels. | ||
|
|
@@ -1582,10 +1643,17 @@ pub enum Event { | |
| user_channel_id: u128, | ||
| /// The `node_id` of the channel counterparty. | ||
| counterparty_node_id: PublicKey, | ||
| /// The outpoint of the channel's splice funding transaction, if one was created. | ||
| abandoned_funding_txo: Option<OutPoint>, | ||
| /// The features that this channel will operate with, if available. | ||
| channel_type: Option<ChannelTypeFeatures>, | ||
|
Comment on lines
-1585
to
-1588
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Didn't feel like there was much value to these.
|
||
| /// The reason the splice negotiation failed. | ||
| reason: NegotiationFailureReason, | ||
| /// The funding contribution from the failed negotiation round, if available. This can be | ||
| /// fed back to [`ChannelManager::funding_contributed`] to retry with the same parameters. | ||
| /// Alternatively, call [`ChannelManager::splice_channel`] to obtain a fresh | ||
| /// [`FundingTemplate`] and build a new contribution. | ||
| /// | ||
| /// [`ChannelManager::funding_contributed`]: crate::ln::channelmanager::ChannelManager::funding_contributed | ||
| /// [`ChannelManager::splice_channel`]: crate::ln::channelmanager::ChannelManager::splice_channel | ||
| /// [`FundingTemplate`]: crate::ln::funding::FundingTemplate | ||
| contribution: Option<FundingContribution>, | ||
| }, | ||
| /// Used to indicate to the user that they can abandon the funding transaction and recycle the | ||
| /// inputs for another purpose. | ||
|
|
@@ -2355,7 +2423,7 @@ impl Writeable for Event { | |
| // We never write out FundingTransactionReadyForSigning events as they will be regenerated when | ||
| // necessary. | ||
| }, | ||
| &Event::SplicePending { | ||
| &Event::SpliceNegotiated { | ||
| ref channel_id, | ||
| ref user_channel_id, | ||
| ref counterparty_node_id, | ||
|
|
@@ -2373,20 +2441,20 @@ impl Writeable for Event { | |
| (11, new_funding_redeem_script, required), | ||
| }); | ||
| }, | ||
| &Event::SpliceFailed { | ||
| &Event::SpliceNegotiationFailed { | ||
| ref channel_id, | ||
| ref user_channel_id, | ||
| ref counterparty_node_id, | ||
| ref abandoned_funding_txo, | ||
| ref channel_type, | ||
| ref reason, | ||
| ref contribution, | ||
| } => { | ||
| 52u8.write(writer)?; | ||
| write_tlv_fields!(writer, { | ||
| (1, channel_id, required), | ||
| (3, channel_type, option), | ||
| (5, user_channel_id, required), | ||
| (7, counterparty_node_id, required), | ||
| (9, abandoned_funding_txo, option), | ||
| (11, reason, required), | ||
| (13, contribution, option), | ||
| }); | ||
| }, | ||
| // Note that, going forward, all new events must only write data inside of | ||
|
|
@@ -3012,7 +3080,7 @@ impl MaybeReadable for Event { | |
| (11, new_funding_redeem_script, required), | ||
| }); | ||
|
|
||
| Ok(Some(Event::SplicePending { | ||
| Ok(Some(Event::SpliceNegotiated { | ||
| channel_id: channel_id.0.unwrap(), | ||
| user_channel_id: user_channel_id.0.unwrap(), | ||
| counterparty_node_id: counterparty_node_id.0.unwrap(), | ||
|
|
@@ -3027,18 +3095,18 @@ impl MaybeReadable for Event { | |
| let mut f = || { | ||
| _init_and_read_len_prefixed_tlv_fields!(reader, { | ||
| (1, channel_id, required), | ||
| (3, channel_type, option), | ||
| (5, user_channel_id, required), | ||
| (7, counterparty_node_id, required), | ||
| (9, abandoned_funding_txo, option), | ||
| (11, reason, upgradable_option), | ||
| (13, contribution, option), | ||
| }); | ||
|
|
||
| Ok(Some(Event::SpliceFailed { | ||
| Ok(Some(Event::SpliceNegotiationFailed { | ||
| channel_id: channel_id.0.unwrap(), | ||
| user_channel_id: user_channel_id.0.unwrap(), | ||
| counterparty_node_id: counterparty_node_id.0.unwrap(), | ||
| abandoned_funding_txo, | ||
| channel_type, | ||
| reason: reason.unwrap_or(NegotiationFailureReason::Unknown), | ||
| contribution, | ||
| })) | ||
| }; | ||
| f() | ||
|
|
||
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.
Almost each docstring says "Retry by calling splice_channel". That doesn't seem like particularly helpful advice especially in cases where the counterparty rejected implying just trying again is unlikely to fix it?