Skip to content

Commit dd64b0c

Browse files
committed
Remove unnecessary funding tx clone & remote tx_sigs received check
We actually don't need to check if the counterparty had already sent their `tx_signatures` in `InteractiveTxSigningSession::received_tx_signatures`. Further, we can get rid of the clone of `funding_tx_opt` in `FundedChannel::tx_signatures` when setting the `ChannelContext::funding_transaction` as we don't actually need to propagate it through to `ChannelManager::internal_tx_complete` as we can use `ChannelContext::unbroadcasted_funding()` which clones the `ChannelContext::funding_transaction` anyway.
1 parent f75751a commit dd64b0c

File tree

5 files changed

+97
-65
lines changed

5 files changed

+97
-65
lines changed

lightning/src/ln/channel.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,6 +2188,7 @@ impl<SP: Deref> PendingV2Channel<SP> where SP::Target: SignerProvider {
21882188
context: self.context,
21892189
interactive_tx_signing_session: Some(signing_session),
21902190
holder_commitment_point,
2191+
is_v2_established: true,
21912192
};
21922193
Ok((funded_chan, commitment_signed, funding_ready_for_sig_event))
21932194
},
@@ -4542,6 +4543,9 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
45424543
pub context: ChannelContext<SP>,
45434544
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
45444545
holder_commitment_point: HolderCommitmentPoint,
4546+
/// Indicates whether this funded channel had been established with V2 channel
4547+
/// establishment (i.e. is a dual-funded channel).
4548+
is_v2_established: bool,
45454549
}
45464550

45474551
#[cfg(any(test, fuzzing))]
@@ -5996,10 +6000,10 @@ impl<SP: Deref> FundedChannel<SP> where
59966000
}
59976001
}
59986002

5999-
pub fn tx_signatures<L: Deref>(&mut self, msg: &msgs::TxSignatures, logger: &L) -> Result<(Option<msgs::TxSignatures>, Option<Transaction>), ChannelError>
6003+
pub fn tx_signatures<L: Deref>(&mut self, msg: &msgs::TxSignatures, logger: &L) -> Result<Option<msgs::TxSignatures>, ChannelError>
60006004
where L::Target: Logger
60016005
{
6002-
if !matches!(self.context.channel_state, ChannelState::FundingNegotiated) {
6006+
if !matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(_)) {
60036007
return Err(ChannelError::close("Received tx_signatures in strange state!".to_owned()));
60046008
}
60056009

@@ -6033,25 +6037,23 @@ impl<SP: Deref> FundedChannel<SP> where
60336037
// for spending. Doesn't seem to be anything in rust-bitcoin.
60346038
}
60356039

6036-
let (tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone())
6040+
let (holder_tx_signatures_opt, funding_tx_opt) = signing_session.received_tx_signatures(msg.clone())
60376041
.map_err(|_| ChannelError::Warn("Witness count did not match contributed input count".to_string()))?;
6042+
if holder_tx_signatures_opt.is_some() && self.is_awaiting_initial_mon_persist() {
6043+
log_debug!(logger, "Not sending tx_signatures: a monitor update is in progress. Setting monitor_pending_tx_signatures.");
6044+
self.context.monitor_pending_tx_signatures = holder_tx_signatures_opt;
6045+
return Ok(None);
6046+
}
60386047
if funding_tx_opt.is_some() {
6048+
// We have a persisted channel monitor and and a finalized funding transaction, so we can move
6049+
// the channel state forward, set the funding transaction and reset the signing session fields.
6050+
self.context.funding_transaction = funding_tx_opt;
6051+
self.context.next_funding_txid = None;
6052+
self.interactive_tx_signing_session = None;
60396053
self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
60406054
}
6041-
self.context.funding_transaction = funding_tx_opt.clone();
6042-
6043-
self.context.next_funding_txid = None;
6044-
6045-
// Clear out the signing session
6046-
self.interactive_tx_signing_session = None;
6047-
6048-
if tx_signatures_opt.is_some() && self.context.channel_state.is_monitor_update_in_progress() {
6049-
log_debug!(logger, "Not sending tx_signatures: a monitor update is in progress. Setting monitor_pending_tx_signatures.");
6050-
self.context.monitor_pending_tx_signatures = tx_signatures_opt;
6051-
return Ok((None, None));
6052-
}
60536055

6054-
Ok((tx_signatures_opt, funding_tx_opt))
6056+
Ok(holder_tx_signatures_opt)
60556057
} else {
60566058
Err(ChannelError::Close((
60576059
"Unexpected tx_signatures. No funding transaction awaiting signatures".to_string(),
@@ -6254,12 +6256,12 @@ impl<SP: Deref> FundedChannel<SP> where
62546256
assert!(self.context.channel_state.is_monitor_update_in_progress());
62556257
self.context.channel_state.clear_monitor_update_in_progress();
62566258

6257-
// If we're past (or at) the AwaitingChannelReady stage on an outbound channel, try to
6258-
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
6259+
// If we're past (or at) the AwaitingChannelReady stage on an outbound (or V2-established) channel,
6260+
// try to (re-)broadcast the funding transaction as we may have declined to broadcast it when we
62596261
// first received the funding_signed.
62606262
let mut funding_broadcastable = None;
62616263
if let Some(funding_transaction) = &self.context.funding_transaction {
6262-
if self.context.is_outbound() &&
6264+
if (self.context.is_outbound() || self.is_v2_established()) &&
62636265
(matches!(self.context.channel_state, ChannelState::AwaitingChannelReady(flags) if !flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH)) ||
62646266
matches!(self.context.channel_state, ChannelState::ChannelReady(_)))
62656267
{
@@ -8551,6 +8553,10 @@ impl<SP: Deref> FundedChannel<SP> where
85518553
})
85528554
.chain(self.context.pending_outbound_htlcs.iter().map(|htlc| (&htlc.source, &htlc.payment_hash)))
85538555
}
8556+
8557+
pub fn is_v2_established(&self) -> bool {
8558+
self.is_v2_established
8559+
}
85548560
}
85558561

85568562
/// A not-yet-funded outbound (from holder) channel using V1 channel establishment.
@@ -8814,6 +8820,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
88148820
let mut channel = FundedChannel {
88158821
context: self.context,
88168822
interactive_tx_signing_session: None,
8823+
is_v2_established: false,
88178824
holder_commitment_point,
88188825
};
88198826

@@ -9079,6 +9086,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
90799086
let mut channel = FundedChannel {
90809087
context: self.context,
90819088
interactive_tx_signing_session: None,
9089+
is_v2_established: false,
90829090
holder_commitment_point,
90839091
};
90849092
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9887,7 +9895,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
98879895
let mut _val: u64 = Readable::read(reader)?;
98889896
}
98899897

9890-
let channel_id = Readable::read(reader)?;
9898+
let channel_id: ChannelId = Readable::read(reader)?;
98919899
let channel_state = ChannelState::from_u32(Readable::read(reader)?).map_err(|_| DecodeError::InvalidValue)?;
98929900
let channel_value_satoshis = Readable::read(reader)?;
98939901

@@ -10323,6 +10331,10 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1032310331
}
1032410332
},
1032510333
};
10334+
let is_v2_established = channel_id.is_v2_channel_id(
10335+
&channel_parameters.holder_pubkeys.revocation_basepoint,
10336+
&channel_parameters.counterparty_parameters.as_ref()
10337+
.expect("Persisted channel must have counterparty parameters").pubkeys.revocation_basepoint);
1032610338

1032710339
Ok(FundedChannel {
1032810340
context: ChannelContext {
@@ -10460,6 +10472,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1046010472
next_funding_txid: None,
1046110473
},
1046210474
interactive_tx_signing_session: None,
10475+
is_v2_established,
1046310476
holder_commitment_point,
1046410477
})
1046510478
}

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8414,14 +8414,14 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
84148414
match chan_entry.get_mut().as_funded_mut() {
84158415
Some(chan) => {
84168416
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
8417-
let (tx_signatures_opt, funding_tx_opt) = try_channel_entry!(self, peer_state, chan.tx_signatures(msg, &&logger), chan_entry);
8417+
let tx_signatures_opt = try_channel_entry!(self, peer_state, chan.tx_signatures(msg, &&logger), chan_entry);
84188418
if let Some(tx_signatures) = tx_signatures_opt {
84198419
peer_state.pending_msg_events.push(events::MessageSendEvent::SendTxSignatures {
84208420
node_id: *counterparty_node_id,
84218421
msg: tx_signatures,
84228422
});
84238423
}
8424-
if let Some(ref funding_tx) = funding_tx_opt {
8424+
if let Some(ref funding_tx) = chan.context.unbroadcasted_funding() {
84258425
self.tx_broadcaster.broadcast_transactions(&[funding_tx]);
84268426
{
84278427
let mut pending_events = self.pending_events.lock().unwrap();

lightning/src/ln/dual_funding_tests.rs

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ use {
2323
crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint, RevocationBasepoint},
2424
crate::ln::functional_test_utils::*,
2525
crate::ln::msgs::ChannelMessageHandler,
26-
crate::ln::msgs::{CommitmentSigned, TxAddInput, TxAddOutput, TxComplete},
26+
crate::ln::msgs::{CommitmentSigned, TxAddInput, TxAddOutput, TxComplete, TxSignatures},
2727
crate::ln::types::ChannelId,
2828
crate::prelude::*,
2929
crate::sign::{ChannelSigner as _, P2WPKH_WITNESS_WEIGHT},
3030
crate::util::ser::TransactionU16LenLimited,
3131
crate::util::test_utils,
32-
bitcoin::Weight,
32+
bitcoin::{Weight, Witness},
3333
};
3434

3535
#[cfg(dual_funding)]
@@ -41,9 +41,7 @@ struct V2ChannelEstablishmentTestSession {
4141
#[cfg(dual_funding)]
4242
// TODO(dual_funding): Use real node and API for creating V2 channels as initiator when available,
4343
// instead of manually constructing messages.
44-
fn do_test_v2_channel_establishment(
45-
session: V2ChannelEstablishmentTestSession, test_async_persist: bool,
46-
) {
44+
fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession) {
4745
let chanmon_cfgs = create_chanmon_cfgs(2);
4846
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
4947
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
@@ -210,37 +208,23 @@ fn do_test_v2_channel_establishment(
210208
partial_signature_with_nonce: None,
211209
};
212210

213-
if test_async_persist {
214-
chanmon_cfgs[1]
215-
.persister
216-
.set_update_ret(crate::chain::ChannelMonitorUpdateStatus::InProgress);
217-
}
211+
chanmon_cfgs[1].persister.set_update_ret(crate::chain::ChannelMonitorUpdateStatus::InProgress);
218212

219213
// Handle the initial commitment_signed exchange. Order is not important here.
220214
nodes[1]
221215
.node
222216
.handle_commitment_signed(nodes[0].node.get_our_node_id(), &msg_commitment_signed_from_0);
223217
check_added_monitors(&nodes[1], 1);
224218

225-
if test_async_persist {
226-
let events = nodes[1].node.get_and_clear_pending_events();
227-
assert!(events.is_empty());
219+
// The funding transaction should not have been broadcast before persisting initial monitor has
220+
// been completed.
221+
assert_eq!(nodes[1].tx_broadcaster.txn_broadcast().len(), 0);
222+
assert_eq!(nodes[1].node.get_and_clear_pending_events().len(), 0);
228223

229-
chanmon_cfgs[1]
230-
.persister
231-
.set_update_ret(crate::chain::ChannelMonitorUpdateStatus::Completed);
232-
let (latest_update, _) = *nodes[1]
233-
.chain_monitor
234-
.latest_monitor_update_id
235-
.lock()
236-
.unwrap()
237-
.get(&channel_id)
238-
.unwrap();
239-
nodes[1]
240-
.chain_monitor
241-
.chain_monitor
242-
.force_channel_monitor_updated(channel_id, latest_update);
243-
}
224+
// Complete the persistence of the monitor.
225+
let events = nodes[1].node.get_and_clear_pending_events();
226+
assert!(events.is_empty());
227+
nodes[1].chain_monitor.complete_sole_pending_chan_update(&channel_id);
244228

245229
let events = nodes[1].node.get_and_clear_pending_events();
246230
assert_eq!(events.len(), 1);
@@ -256,19 +240,30 @@ fn do_test_v2_channel_establishment(
256240
);
257241

258242
assert_eq!(tx_signatures_msg.channel_id, channel_id);
243+
244+
let mut witness = Witness::new();
245+
witness.push([0x0]);
246+
// Receive tx_signatures from channel initiator.
247+
nodes[1].node.handle_tx_signatures(
248+
nodes[0].node.get_our_node_id(),
249+
&TxSignatures {
250+
channel_id,
251+
tx_hash: funding_outpoint.unwrap().txid,
252+
witnesses: vec![witness],
253+
shared_input_signature: None,
254+
},
255+
);
256+
257+
// For an inbound channel V2 channel the transaction should be broadcast once receiving a
258+
// tx_signature and applying local tx_signatures:
259+
let broadcasted_txs = nodes[1].tx_broadcaster.txn_broadcast();
260+
assert_eq!(broadcasted_txs.len(), 1);
259261
}
260262

261263
#[test]
262264
#[cfg(dual_funding)]
263265
fn test_v2_channel_establishment() {
264-
// Only initiator contributes, no persist pending
265-
do_test_v2_channel_establishment(
266-
V2ChannelEstablishmentTestSession { initiator_input_value_satoshis: 100_000 },
267-
false,
268-
);
269-
// Only initiator contributes, persist pending
270-
do_test_v2_channel_establishment(
271-
V2ChannelEstablishmentTestSession { initiator_input_value_satoshis: 100_000 },
272-
true,
273-
);
266+
do_test_v2_channel_establishment(V2ChannelEstablishmentTestSession {
267+
initiator_input_value_satoshis: 100_000,
268+
});
274269
}

lightning/src/ln/interactivetxs.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,14 +316,18 @@ impl InteractiveTxSigningSession {
316316

317317
/// Handles a `tx_signatures` message received from the counterparty.
318318
///
319+
/// If the holder is required to send their `tx_signatures` message and these signatures have
320+
/// already been provided to the signing session, then this return value will be `Some`, otherwise
321+
/// None.
322+
///
323+
/// If the holder has already provided their `tx_signatures` to the signing session, a funding
324+
/// transaction will be finalized and returned as Some, otherwise None.
325+
///
319326
/// Returns an error if the witness count does not equal the counterparty's input count in the
320327
/// unsigned transaction.
321328
pub fn received_tx_signatures(
322329
&mut self, tx_signatures: TxSignatures,
323330
) -> Result<(Option<TxSignatures>, Option<Transaction>), ()> {
324-
if self.counterparty_sent_tx_signatures {
325-
return Ok((None, None));
326-
};
327331
if self.remote_inputs_count() != tx_signatures.witnesses.len() {
328332
return Err(());
329333
}
@@ -336,13 +340,16 @@ impl InteractiveTxSigningSession {
336340
None
337341
};
338342

339-
let funding_tx = if self.holder_tx_signatures.is_some() {
343+
// Check if the holder has provided its signatures and if so,
344+
// return the finalized funding transaction.
345+
let funding_tx_opt = if self.holder_tx_signatures.is_some() {
340346
Some(self.finalize_funding_tx())
341347
} else {
348+
// This means we're still waiting for the holder to provide their signatures.
342349
None
343350
};
344351

345-
Ok((holder_tx_signatures, funding_tx))
352+
Ok((holder_tx_signatures, funding_tx_opt))
346353
}
347354

348355
/// Provides the holder witnesses for the unsigned transaction.

lightning/src/ln/types.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ impl ChannelId {
101101
pub fn temporary_v2_from_revocation_basepoint(our_revocation_basepoint: &RevocationBasepoint) -> Self {
102102
Self(Sha256::hash(&[[0u8; 33], our_revocation_basepoint.0.serialize()].concat()).to_byte_array())
103103
}
104+
105+
/// Indicates whether this is a V2 channel ID for the given local and remote revocation basepoints.
106+
pub fn is_v2_channel_id(&self, ours: &RevocationBasepoint, theirs: &RevocationBasepoint) -> bool {
107+
*self == Self::v2_from_revocation_basepoints(ours, theirs)
108+
}
104109
}
105110

106111
impl Writeable for ChannelId {
@@ -211,4 +216,16 @@ mod tests {
211216

212217
assert_eq!(ChannelId::v2_from_revocation_basepoints(&ours, &theirs), expected_id);
213218
}
219+
220+
#[test]
221+
fn test_is_v2_channel_id() {
222+
let ours = RevocationBasepoint(PublicKey::from_slice(&<Vec<u8>>::from_hex("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap());
223+
let theirs = RevocationBasepoint(PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap());
224+
225+
let channel_id = ChannelId::v2_from_revocation_basepoints(&ours, &theirs);
226+
assert!(channel_id.is_v2_channel_id(&ours, &theirs));
227+
228+
let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1);
229+
assert!(!channel_id.is_v2_channel_id(&ours, &theirs))
230+
}
214231
}

0 commit comments

Comments
 (0)