Skip to content

Commit df5db06

Browse files
committed
Rework ChannelManager::funding_transaction_signed
Previously, we'd emit a FundingTransactionReadyForSigning event once the initial commitment_signed is exchanged for a splicing/dual-funding attempt and require users to call back with their signed inputs using ChannelManager::funding_transaction_signed. While this approach worked in practice, it prevents us from abandoning a splice if we cannot or no longer wish to sign as the splice has already been committed to by this point. This commit reworks the API such that this is now possible. After exchanging tx_complete, we will no longer immediately send our initial commitment_signed. We will now emit the FundingTransactionReadyForSigning event and wait for the user to call back before releasing both our initial commitment_signed and our tx_signatures. As a result, the event is now persisted, as there is only one possible path in which it is generated. Note that we continue to only emit the event if a local contribution to negotiated transaction was made. Future work will expose a cancellation API such that we can abandon splice attempts safely (we can just force close the channel with dual-funding).
1 parent 8cdc86a commit df5db06

File tree

5 files changed

+350
-354
lines changed

5 files changed

+350
-354
lines changed

lightning/src/ln/channel.rs

Lines changed: 111 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,10 +1904,7 @@ where
19041904

19051905
pub fn tx_complete<L: Deref>(
19061906
&mut self, msg: &msgs::TxComplete, logger: &L,
1907-
) -> Result<
1908-
(Option<InteractiveTxMessageSend>, Option<msgs::CommitmentSigned>),
1909-
(ChannelError, Option<SpliceFundingFailed>),
1910-
>
1907+
) -> Result<TxCompleteResult, (ChannelError, Option<SpliceFundingFailed>)>
19111908
where
19121909
L::Target: Logger,
19131910
{
@@ -1934,13 +1931,38 @@ where
19341931
let funding_outpoint = if let Some(funding_outpoint) = negotiation_complete {
19351932
funding_outpoint
19361933
} else {
1937-
return Ok((interactive_tx_msg_send, None));
1934+
return Ok(TxCompleteResult {
1935+
interactive_tx_msg_send,
1936+
event_unsigned_tx: None,
1937+
funding_tx_signed: None,
1938+
});
19381939
};
19391940

1940-
let commitment_signed = self
1941-
.funding_tx_constructed(funding_outpoint, logger)
1941+
self.funding_tx_constructed(funding_outpoint)
19421942
.map_err(|abort_reason| self.fail_interactive_tx_negotiation(abort_reason, logger))?;
1943-
Ok((interactive_tx_msg_send, Some(commitment_signed)))
1943+
1944+
let signing_session = self
1945+
.context()
1946+
.interactive_tx_signing_session
1947+
.as_ref()
1948+
.expect("The signing session must have been initialized in funding_tx_constructed");
1949+
let has_local_contribution = signing_session.has_local_contribution();
1950+
1951+
let event_unsigned_tx =
1952+
has_local_contribution.then(|| signing_session.unsigned_tx().tx().clone());
1953+
1954+
let funding_tx_signed = if !has_local_contribution {
1955+
let funding_txid = signing_session.unsigned_tx().tx().compute_txid();
1956+
if let ChannelPhase::Funded(chan) = &mut self.phase {
1957+
chan.funding_transaction_signed(funding_txid, vec![], 0, logger).ok()
1958+
} else {
1959+
None
1960+
}
1961+
} else {
1962+
None
1963+
};
1964+
1965+
Ok(TxCompleteResult { interactive_tx_msg_send, event_unsigned_tx, funding_tx_signed })
19441966
}
19451967

19461968
pub fn tx_abort<L: Deref>(
@@ -2046,14 +2068,8 @@ where
20462068
result.map(|monitor| (self.as_funded_mut().expect("Channel should be funded"), monitor))
20472069
}
20482070

2049-
fn funding_tx_constructed<L: Deref>(
2050-
&mut self, funding_outpoint: OutPoint, logger: &L,
2051-
) -> Result<msgs::CommitmentSigned, AbortReason>
2052-
where
2053-
L::Target: Logger,
2054-
{
2055-
let logger = WithChannelContext::from(logger, self.context(), None);
2056-
let (interactive_tx_constructor, commitment_signed) = match &mut self.phase {
2071+
fn funding_tx_constructed(&mut self, funding_outpoint: OutPoint) -> Result<(), AbortReason> {
2072+
let interactive_tx_constructor = match &mut self.phase {
20572073
ChannelPhase::UnfundedV2(chan) => {
20582074
debug_assert_eq!(
20592075
chan.context.channel_state,
@@ -2072,24 +2088,9 @@ where
20722088
chan.funding.channel_transaction_parameters.funding_outpoint =
20732089
Some(funding_outpoint);
20742090

2075-
let interactive_tx_constructor = chan
2076-
.interactive_tx_constructor
2091+
chan.interactive_tx_constructor
20772092
.take()
2078-
.expect("PendingV2Channel::interactive_tx_constructor should be set");
2079-
2080-
let commitment_signed =
2081-
chan.context.get_initial_commitment_signed_v2(&chan.funding, &&logger);
2082-
let commitment_signed = match commitment_signed {
2083-
Some(commitment_signed) => commitment_signed,
2084-
// TODO(dual_funding): Support async signing
2085-
None => {
2086-
return Err(AbortReason::InternalError(
2087-
"Failed to compute commitment_signed signatures",
2088-
));
2089-
},
2090-
};
2091-
2092-
(interactive_tx_constructor, commitment_signed)
2093+
.expect("PendingV2Channel::interactive_tx_constructor should be set")
20932094
},
20942095
ChannelPhase::Funded(chan) => {
20952096
if let Some(pending_splice) = chan.pending_splice.as_mut() {
@@ -2098,12 +2099,19 @@ where
20982099
.take()
20992100
.and_then(|funding_negotiation| {
21002101
if let FundingNegotiation::ConstructingTransaction {
2101-
funding,
2102+
mut funding,
21022103
interactive_tx_constructor,
21032104
} = funding_negotiation
21042105
{
21052106
let is_initiator = interactive_tx_constructor.is_initiator();
2106-
Some((is_initiator, funding, interactive_tx_constructor))
2107+
funding.channel_transaction_parameters.funding_outpoint =
2108+
Some(funding_outpoint);
2109+
pending_splice.funding_negotiation =
2110+
Some(FundingNegotiation::AwaitingSignatures {
2111+
is_initiator,
2112+
funding,
2113+
});
2114+
Some(interactive_tx_constructor)
21072115
} else {
21082116
// Replace the taken state for later error handling
21092117
pending_splice.funding_negotiation = Some(funding_negotiation);
@@ -2114,34 +2122,6 @@ where
21142122
AbortReason::InternalError(
21152123
"Got a tx_complete message in an invalid state",
21162124
)
2117-
})
2118-
.and_then(|(is_initiator, mut funding, interactive_tx_constructor)| {
2119-
funding.channel_transaction_parameters.funding_outpoint =
2120-
Some(funding_outpoint);
2121-
match chan.context.get_initial_commitment_signed_v2(&funding, &&logger)
2122-
{
2123-
Some(commitment_signed) => {
2124-
// Advance the state
2125-
pending_splice.funding_negotiation =
2126-
Some(FundingNegotiation::AwaitingSignatures {
2127-
is_initiator,
2128-
funding,
2129-
});
2130-
Ok((interactive_tx_constructor, commitment_signed))
2131-
},
2132-
// TODO(splicing): Support async signing
2133-
None => {
2134-
// Restore the taken state for later error handling
2135-
pending_splice.funding_negotiation =
2136-
Some(FundingNegotiation::ConstructingTransaction {
2137-
funding,
2138-
interactive_tx_constructor,
2139-
});
2140-
Err(AbortReason::InternalError(
2141-
"Failed to compute commitment_signed signatures",
2142-
))
2143-
},
2144-
}
21452125
})?
21462126
} else {
21472127
return Err(AbortReason::InternalError(
@@ -2159,7 +2139,7 @@ where
21592139

21602140
let signing_session = interactive_tx_constructor.into_signing_session();
21612141
self.context_mut().interactive_tx_signing_session = Some(signing_session);
2162-
Ok(commitment_signed)
2142+
Ok(())
21632143
}
21642144

21652145
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
@@ -2911,6 +2891,7 @@ where
29112891
/// send it first.
29122892
resend_order: RAACommitmentOrder,
29132893

2894+
monitor_pending_tx_signatures: bool,
29142895
monitor_pending_channel_ready: bool,
29152896
monitor_pending_revoke_and_ack: bool,
29162897
monitor_pending_commitment_signed: bool,
@@ -3642,6 +3623,7 @@ where
36423623

36433624
resend_order: RAACommitmentOrder::CommitmentFirst,
36443625

3626+
monitor_pending_tx_signatures: false,
36453627
monitor_pending_channel_ready: false,
36463628
monitor_pending_revoke_and_ack: false,
36473629
monitor_pending_commitment_signed: false,
@@ -3881,6 +3863,7 @@ where
38813863

38823864
resend_order: RAACommitmentOrder::CommitmentFirst,
38833865

3866+
monitor_pending_tx_signatures: false,
38843867
monitor_pending_channel_ready: false,
38853868
monitor_pending_revoke_and_ack: false,
38863869
monitor_pending_commitment_signed: false,
@@ -6860,8 +6843,25 @@ type BestBlockUpdatedRes = (
68606843
Option<msgs::AnnouncementSignatures>,
68616844
);
68626845

6846+
/// The result of handling a `tx_complete` message during interactive transaction construction.
6847+
pub(crate) struct TxCompleteResult {
6848+
/// The message to send to the counterparty, if any.
6849+
pub interactive_tx_msg_send: Option<InteractiveTxMessageSend>,
6850+
6851+
/// If the negotiation completed and the holder has local contributions, this contains the
6852+
/// unsigned funding transaction for the `FundingTransactionReadyForSigning` event.
6853+
pub event_unsigned_tx: Option<Transaction>,
6854+
6855+
/// If the negotiation completed and the holder has no local contributions, this contains
6856+
/// the result of automatically calling `funding_transaction_signed` with empty witnesses.
6857+
pub funding_tx_signed: Option<FundingTxSigned>,
6858+
}
6859+
68636860
/// The result of signing a funding transaction negotiated using the interactive-tx protocol.
68646861
pub struct FundingTxSigned {
6862+
/// The initial `commitment_signed` message to send to the counterparty, if necessary.
6863+
pub commitment_signed: Option<msgs::CommitmentSigned>,
6864+
68656865
/// Signatures that should be sent to the counterparty, if necessary.
68666866
pub tx_signatures: Option<msgs::TxSignatures>,
68676867

@@ -8051,6 +8051,7 @@ where
80518051
Vec::new(),
80528052
logger,
80538053
);
8054+
self.context.monitor_pending_tx_signatures = true;
80548055

80558056
Ok(self.push_ret_blockable_mon_update(monitor_update))
80568057
}
@@ -9104,6 +9105,7 @@ where
91049105
// Our `tx_signatures` either should've been the first time we processed them,
91059106
// or we're waiting for our counterparty to send theirs first.
91069107
return Ok(FundingTxSigned {
9108+
commitment_signed: None,
91079109
tx_signatures: None,
91089110
funding_tx: None,
91099111
splice_negotiated: None,
@@ -9117,6 +9119,7 @@ where
91179119
// We may be handling a duplicate call and the funding was already locked so we
91189120
// no longer have the signing session present.
91199121
return Ok(FundingTxSigned {
9122+
commitment_signed: None,
91209123
tx_signatures: None,
91219124
funding_tx: None,
91229125
splice_negotiated: None,
@@ -9178,7 +9181,21 @@ where
91789181
(None, None)
91799182
};
91809183

9181-
Ok(FundingTxSigned { tx_signatures, funding_tx, splice_negotiated, splice_locked })
9184+
let funding = self
9185+
.pending_splice
9186+
.as_ref()
9187+
.and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
9188+
.and_then(|funding_negotiation| funding_negotiation.as_funding())
9189+
.unwrap_or(&self.funding);
9190+
let commitment_signed = self.context.get_initial_commitment_signed_v2(funding, &&logger);
9191+
9192+
Ok(FundingTxSigned {
9193+
commitment_signed,
9194+
tx_signatures,
9195+
funding_tx,
9196+
splice_negotiated,
9197+
splice_locked,
9198+
})
91829199
}
91839200

91849201
pub fn tx_signatures<L: Deref>(
@@ -9246,6 +9263,7 @@ where
92469263
};
92479264

92489265
Ok(FundingTxSigned {
9266+
commitment_signed: None,
92499267
tx_signatures: holder_tx_signatures,
92509268
funding_tx,
92519269
splice_negotiated,
@@ -9451,6 +9469,25 @@ where
94519469
self.context.channel_state.clear_monitor_update_in_progress();
94529470
assert_eq!(self.blocked_monitor_updates_pending(), 0);
94539471

9472+
let mut tx_signatures = self
9473+
.context
9474+
.monitor_pending_tx_signatures
9475+
.then(|| ())
9476+
.and_then(|_| self.context.interactive_tx_signing_session.as_ref())
9477+
.and_then(|signing_session| signing_session.holder_tx_signatures().clone());
9478+
if tx_signatures.is_some() {
9479+
// We want to clear that the monitor update for our `tx_signatures` has completed, but
9480+
// we may still need to hold back the message until it's ready to be sent.
9481+
self.context.monitor_pending_tx_signatures = false;
9482+
let signing_session = self.context.interactive_tx_signing_session.as_ref()
9483+
.expect("We have a tx_signatures message so we must have a valid signing session");
9484+
if !signing_session.holder_sends_tx_signatures_first()
9485+
&& !signing_session.has_received_tx_signatures()
9486+
{
9487+
tx_signatures.take();
9488+
}
9489+
}
9490+
94549491
// If we're past (or at) the AwaitingChannelReady stage on an outbound (or V2-established) channel,
94559492
// try to (re-)broadcast the funding transaction as we may have declined to broadcast it when we
94569493
// first received the funding_signed.
@@ -9539,7 +9576,7 @@ where
95399576
match commitment_order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"});
95409577
MonitorRestoreUpdates {
95419578
raa, commitment_update, commitment_order, accepted_htlcs, failed_htlcs, finalized_claimed_htlcs,
9542-
pending_update_adds, funding_broadcastable, channel_ready, announcement_sigs, tx_signatures: None,
9579+
pending_update_adds, funding_broadcastable, channel_ready, announcement_sigs, tx_signatures,
95439580
channel_ready_order,
95449581
}
95459582
}
@@ -15074,6 +15111,9 @@ where
1507415111
let pending_splice =
1507515112
self.pending_splice.as_ref().filter(|_| !self.should_reset_pending_splice_state(false));
1507615113

15114+
let monitor_pending_tx_signatures =
15115+
self.context.monitor_pending_tx_signatures.then_some(());
15116+
1507715117
write_tlv_fields!(writer, {
1507815118
(0, self.context.announcement_sigs, option),
1507915119
// minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -15093,6 +15133,7 @@ where
1509315133
(9, self.context.target_closing_feerate_sats_per_kw, option),
1509415134
(10, monitor_pending_update_adds, option), // Added in 0.0.122
1509515135
(11, self.context.monitor_pending_finalized_fulfills, required_vec),
15136+
(12, monitor_pending_tx_signatures, option), // Added in 0.3
1509615137
(13, self.context.channel_creation_height, required),
1509715138
(15, preimages, required_vec),
1509815139
(17, self.context.announcement_sigs_state, required),
@@ -15524,6 +15565,8 @@ where
1552415565
let mut holding_cell_accountable: Option<Vec<bool>> = None;
1552515566
let mut pending_outbound_accountable: Option<Vec<bool>> = None;
1552615567

15568+
let mut monitor_pending_tx_signatures: Option<()> = None;
15569+
1552715570
read_tlv_fields!(reader, {
1552815571
(0, announcement_sigs, option),
1552915572
(1, minimum_depth, option),
@@ -15537,6 +15580,7 @@ where
1553715580
(9, target_closing_feerate_sats_per_kw, option),
1553815581
(10, monitor_pending_update_adds, option), // Added in 0.0.122
1553915582
(11, monitor_pending_finalized_fulfills, optional_vec),
15583+
(12, monitor_pending_tx_signatures, option), // Added in 0.3
1554015584
(13, channel_creation_height, required),
1554115585
(15, preimages, required_vec), // The preimages transitioned from optional to required in 0.2
1554215586
(17, announcement_sigs_state, required),
@@ -15949,6 +15993,7 @@ where
1594915993

1595015994
resend_order,
1595115995

15996+
monitor_pending_tx_signatures: monitor_pending_tx_signatures.is_some(),
1595215997
monitor_pending_channel_ready,
1595315998
monitor_pending_revoke_and_ack,
1595415999
monitor_pending_commitment_signed,

0 commit comments

Comments
 (0)