Skip to content

Commit 89f93b9

Browse files
committed
Introduce FundingTransactionReadyForSignatures event
The `FundingTransactionReadyForSignatures` event requests witnesses from the client for their contributed inputs to an interactively constructed transaction. The client calls `ChannelManager::funding_transaction_signed` to provide the witnesses to LDK.
1 parent 1d507f2 commit 89f93b9

File tree

4 files changed

+199
-34
lines changed

4 files changed

+199
-34
lines changed

lightning/src/events/mod.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,48 @@ pub enum Event {
16761676
/// [`ChannelManager::send_static_invoice`]: crate::ln::channelmanager::ChannelManager::send_static_invoice
16771677
reply_path: Responder,
16781678
},
1679+
/// Indicates that a channel funding transaction constructed interactively is ready to be
1680+
/// signed. This event will only be triggered if at least one input was contributed.
1681+
///
1682+
/// The transaction contains all inputs provided by both parties along with the channel's funding
1683+
/// output and a change output if applicable.
1684+
///
1685+
/// No part of the transaction should be changed before signing as the content of the transaction
1686+
/// has already been negotiated with the counterparty.
1687+
///
1688+
/// Each signature MUST use the `SIGHASH_ALL` flag to avoid invalidation of the initial commitment and
1689+
/// hence possible loss of funds.
1690+
///
1691+
/// After signing, call [`ChannelManager::funding_transaction_signed`] with the (partially) signed
1692+
/// funding transaction.
1693+
///
1694+
/// Generated in [`ChannelManager`] message handling.
1695+
///
1696+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
1697+
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
1698+
FundingTransactionReadyForSigning {
1699+
/// The channel_id of the channel which you'll need to pass back into
1700+
/// [`ChannelManager::funding_transaction_signed`].
1701+
///
1702+
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
1703+
channel_id: ChannelId,
1704+
/// The counterparty's node_id, which you'll need to pass back into
1705+
/// [`ChannelManager::funding_transaction_signed`].
1706+
///
1707+
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
1708+
counterparty_node_id: PublicKey,
1709+
/// The `user_channel_id` value passed in for outbound channels, or for inbound channels if
1710+
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise
1711+
/// `user_channel_id` will be randomized for inbound channels.
1712+
///
1713+
/// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
1714+
user_channel_id: u128,
1715+
/// The unsigned transaction to be signed and passed back to
1716+
/// [`ChannelManager::funding_transaction_signed`].
1717+
///
1718+
/// [`ChannelManager::funding_transaction_signed`]: crate::ln::channelmanager::ChannelManager::funding_transaction_signed
1719+
unsigned_transaction: Transaction,
1720+
},
16791721
}
16801722

16811723
impl Writeable for Event {
@@ -2117,6 +2159,13 @@ impl Writeable for Event {
21172159
47u8.write(writer)?;
21182160
// Never write StaticInvoiceRequested events as buffered onion messages aren't serialized.
21192161
},
2162+
&Event::FundingTransactionReadyForSigning { .. } => {
2163+
49u8.write(writer)?;
2164+
// We never write out FundingTransactionReadyForSigning events as, upon disconnection, peers
2165+
// drop any V2-established/spliced channels which have not yet exchanged the initial `commitment_signed`.
2166+
// We only exhange the initial `commitment_signed` after the client calls
2167+
// `ChannelManager::funding_transaction_signed` and ALWAYS before we send a `tx_signatures`
2168+
},
21202169
// Note that, going forward, all new events must only write data inside of
21212170
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
21222171
// data via `write_tlv_fields`.
@@ -2694,6 +2743,8 @@ impl MaybeReadable for Event {
26942743
// Note that we do not write a length-prefixed TLV for StaticInvoiceRequested events.
26952744
#[cfg(async_payments)]
26962745
47u8 => Ok(None),
2746+
// Note that we do not write a length-prefixed TLV for FundingTransactionReadyForSigning events.
2747+
49u8 => Ok(None),
26972748
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
26982749
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
26992750
// reads.

lightning/src/ln/channel.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use bitcoin::constants::ChainHash;
1414
use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
1515
use bitcoin::sighash::EcdsaSighashType;
1616
use bitcoin::transaction::{Transaction, TxIn, TxOut};
17-
use bitcoin::Weight;
17+
use bitcoin::{Weight, Witness};
1818

1919
use bitcoin::hash_types::{BlockHash, Txid};
2020
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -36,7 +36,7 @@ use crate::chain::channelmonitor::{
3636
use crate::chain::transaction::{OutPoint, TransactionData};
3737
use crate::chain::BestBlock;
3838
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
39-
use crate::events::{ClosureReason, Event};
39+
use crate::events::ClosureReason;
4040
use crate::ln::chan_utils;
4141
#[cfg(splicing)]
4242
use crate::ln::chan_utils::FUNDING_TRANSACTION_WITNESS_WEIGHT;
@@ -1766,7 +1766,7 @@ where
17661766

17671767
pub fn funding_tx_constructed<L: Deref>(
17681768
&mut self, signing_session: InteractiveTxSigningSession, logger: &L,
1769-
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
1769+
) -> Result<(msgs::CommitmentSigned, Option<Transaction>), ChannelError>
17701770
where
17711771
L::Target: Logger,
17721772
{
@@ -2916,7 +2916,7 @@ where
29162916
#[rustfmt::skip]
29172917
pub fn funding_tx_constructed<L: Deref>(
29182918
&mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2919-
) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
2919+
) -> Result<(msgs::CommitmentSigned, Option<Transaction>), ChannelError>
29202920
where
29212921
L::Target: Logger
29222922
{
@@ -2954,7 +2954,7 @@ where
29542954
},
29552955
};
29562956

2957-
let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
2957+
let funding_tx_opt = if signing_session.local_inputs_count() == 0 {
29582958
debug_assert_eq!(our_funding_satoshis, 0);
29592959
if signing_session.provide_holder_witnesses(self.context.channel_id, Vec::new()).is_err() {
29602960
debug_assert!(
@@ -2967,27 +2967,7 @@ where
29672967
}
29682968
None
29692969
} else {
2970-
// TODO(dual_funding): Send event for signing if we've contributed funds.
2971-
// Inform the user that SIGHASH_ALL must be used for all signatures when contributing
2972-
// inputs/signatures.
2973-
// Also warn the user that we don't do anything to prevent the counterparty from
2974-
// providing non-standard witnesses which will prevent the funding transaction from
2975-
// confirming. This warning must appear in doc comments wherever the user is contributing
2976-
// funds, whether they are initiator or acceptor.
2977-
//
2978-
// The following warning can be used when the APIs allowing contributing inputs become available:
2979-
// <div class="warning">
2980-
// WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
2981-
// will prevent the funding transaction from being relayed on the bitcoin network and hence being
2982-
// confirmed.
2983-
// </div>
2984-
debug_assert!(
2985-
false,
2986-
"We don't support users providing inputs but somehow we had more than zero inputs",
2987-
);
2988-
let msg = "V2 channel rejected due to sender error";
2989-
let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2990-
return Err(ChannelError::Close((msg.to_owned(), reason)));
2970+
Some(signing_session.unsigned_tx().build_unsigned_tx())
29912971
};
29922972

29932973
let mut channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
@@ -2998,7 +2978,7 @@ where
29982978
self.interactive_tx_constructor.take();
29992979
self.interactive_tx_signing_session = Some(signing_session);
30002980

3001-
Ok((commitment_signed, funding_ready_for_sig_event))
2981+
Ok((commitment_signed, funding_tx_opt))
30022982
}
30032983
}
30042984

@@ -7605,6 +7585,45 @@ where
76057585
}
76067586
}
76077587

7588+
fn verify_interactive_tx_signatures(&mut self, _witnesses: &Vec<Witness>) {
7589+
if let Some(ref mut _signing_session) = self.interactive_tx_signing_session {
7590+
// Check that sighash_all was used:
7591+
// TODO(dual_funding): Check sig for sighash
7592+
}
7593+
}
7594+
7595+
pub fn funding_transaction_signed<L: Deref>(
7596+
&mut self, witnesses: Vec<Witness>, logger: &L,
7597+
) -> Result<Option<msgs::TxSignatures>, APIError>
7598+
where
7599+
L::Target: Logger,
7600+
{
7601+
self.verify_interactive_tx_signatures(&witnesses);
7602+
if let Some(ref mut signing_session) = self.interactive_tx_signing_session {
7603+
let logger = WithChannelContext::from(logger, &self.context, None);
7604+
if let Some(holder_tx_signatures) = signing_session
7605+
.provide_holder_witnesses(self.context.channel_id, witnesses)
7606+
.map_err(|err| APIError::APIMisuseError { err })?
7607+
{
7608+
if self.is_awaiting_initial_mon_persist() {
7609+
log_debug!(logger, "Not sending tx_signatures: a monitor update is in progress. Setting monitor_pending_tx_signatures.");
7610+
self.context.monitor_pending_tx_signatures = Some(holder_tx_signatures);
7611+
return Ok(None);
7612+
}
7613+
return Ok(Some(holder_tx_signatures));
7614+
} else {
7615+
return Ok(None);
7616+
}
7617+
} else {
7618+
return Err(APIError::APIMisuseError {
7619+
err: format!(
7620+
"Channel with id {} not expecting funding signatures",
7621+
self.context.channel_id
7622+
),
7623+
});
7624+
}
7625+
}
7626+
76087627
#[rustfmt::skip]
76097628
pub fn tx_signatures<L: Deref>(&mut self, msg: &msgs::TxSignatures, logger: &L) -> Result<(Option<Transaction>, Option<msgs::TxSignatures>), ChannelError>
76107629
where L::Target: Logger

lightning/src/ln/channelmanager.rs

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5890,6 +5890,86 @@ where
58905890
result
58915891
}
58925892

5893+
/// Handles a signed funding transaction generated by interactive transaction construction and
5894+
/// provided by the client.
5895+
///
5896+
/// Do NOT broadcast the funding transaction yourself. When we have safely received our
5897+
/// counterparty's signature(s) the funding transaction will automatically be broadcast via the
5898+
/// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed.
5899+
///
5900+
/// `SIGHASH_ALL` MUST be used for all signatures when providing signatures.
5901+
///
5902+
/// <div class="warning">
5903+
/// WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
5904+
/// will prevent the funding transaction from being relayed on the bitcoin network and hence being
5905+
/// confirmed.
5906+
/// </div>
5907+
///
5908+
/// Returns [`ChannelUnavailable`] when a channel is not found or an incorrect
5909+
/// `counterparty_node_id` is provided.
5910+
///
5911+
/// Returns [`APIMisuseError`] when a channel is not in a state where it is expecting funding
5912+
/// signatures.
5913+
///
5914+
/// [`ChannelUnavailable`]: APIError::ChannelUnavailable
5915+
/// [`APIMisuseError`]: APIError::APIMisuseError
5916+
pub fn funding_transaction_signed(
5917+
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, transaction: Transaction,
5918+
) -> Result<(), APIError> {
5919+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
5920+
let witnesses: Vec<_> = transaction
5921+
.input
5922+
.into_iter()
5923+
.filter_map(|input| if input.witness.is_empty() { None } else { Some(input.witness) })
5924+
.collect();
5925+
5926+
let per_peer_state = self.per_peer_state.read().unwrap();
5927+
let peer_state_mutex = per_peer_state.get(counterparty_node_id).ok_or_else(|| {
5928+
APIError::ChannelUnavailable {
5929+
err: format!(
5930+
"Can't find a peer matching the passed counterparty node_id {}",
5931+
counterparty_node_id
5932+
),
5933+
}
5934+
})?;
5935+
5936+
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
5937+
let peer_state = &mut *peer_state_lock;
5938+
5939+
match peer_state.channel_by_id.get_mut(channel_id) {
5940+
Some(channel) => match channel.as_funded_mut() {
5941+
Some(chan) => {
5942+
if let Some(tx_signatures) =
5943+
chan.funding_transaction_signed(witnesses, &self.logger)?
5944+
{
5945+
peer_state.pending_msg_events.push(MessageSendEvent::SendTxSignatures {
5946+
node_id: *counterparty_node_id,
5947+
msg: tx_signatures,
5948+
});
5949+
}
5950+
},
5951+
None => {
5952+
return Err(APIError::APIMisuseError {
5953+
err: format!(
5954+
"Channel with id {} not expecting funding signatures",
5955+
channel_id
5956+
),
5957+
})
5958+
},
5959+
},
5960+
None => {
5961+
return Err(APIError::ChannelUnavailable {
5962+
err: format!(
5963+
"Channel with id {} not found for the passed counterparty node_id {}",
5964+
channel_id, counterparty_node_id
5965+
),
5966+
})
5967+
},
5968+
}
5969+
5970+
Ok(())
5971+
}
5972+
58935973
/// Atomically applies partial updates to the [`ChannelConfig`] of the given channels.
58945974
///
58955975
/// Once the updates are applied, each eligible channel (advertised with a known short channel
@@ -9008,13 +9088,19 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
90089088
peer_state.pending_msg_events.push(msg_send_event);
90099089
};
90109090
if let Some(signing_session) = signing_session_opt {
9011-
let (commitment_signed, funding_ready_for_sig_event_opt) = chan_entry
9091+
let (commitment_signed, funding_tx_opt) = chan_entry
90129092
.get_mut()
90139093
.funding_tx_constructed(signing_session, &self.logger)
90149094
.map_err(|err| MsgHandleErrInternal::send_err_msg_no_close(format!("{}", err), msg.channel_id))?;
9015-
if let Some(funding_ready_for_sig_event) = funding_ready_for_sig_event_opt {
9095+
if let Some(unsigned_transaction) = funding_tx_opt {
90169096
let mut pending_events = self.pending_events.lock().unwrap();
9017-
pending_events.push_back((funding_ready_for_sig_event, None));
9097+
pending_events.push_back((
9098+
Event::FundingTransactionReadyForSigning {
9099+
unsigned_transaction,
9100+
counterparty_node_id,
9101+
channel_id: msg.channel_id,
9102+
user_channel_id: chan_entry.get().context().get_user_id(),
9103+
}, None));
90189104
}
90199105
peer_state.pending_msg_events.push(MessageSendEvent::UpdateHTLCs {
90209106
node_id: counterparty_node_id,

lightning/src/ln/interactivetxs.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,14 @@ impl InteractiveTxSigningSession {
447447
/// unsigned transaction.
448448
pub fn provide_holder_witnesses(
449449
&mut self, channel_id: ChannelId, witnesses: Vec<Witness>,
450-
) -> Result<(), ()> {
451-
if self.local_inputs_count() != witnesses.len() {
452-
return Err(());
450+
) -> Result<Option<TxSignatures>, String> {
451+
let local_inputs_count = self.local_inputs_count();
452+
if local_inputs_count != witnesses.len() {
453+
return Err(format!(
454+
"Provided witness count of {} does not match required count for {} inputs",
455+
witnesses.len(),
456+
local_inputs_count
457+
));
453458
}
454459

455460
self.unsigned_tx.add_local_witnesses(witnesses.clone());
@@ -460,7 +465,11 @@ impl InteractiveTxSigningSession {
460465
shared_input_signature: None,
461466
});
462467

463-
Ok(())
468+
if self.holder_sends_tx_signatures_first && self.has_received_commitment_signed {
469+
Ok(self.holder_tx_signatures.clone())
470+
} else {
471+
Ok(None)
472+
}
464473
}
465474

466475
pub fn remote_inputs_count(&self) -> usize {

0 commit comments

Comments
 (0)