Skip to content

Commit 33bc387

Browse files
committed
Add pending funding scopes to FundedChannel
Once a channel is funded, it may be spliced to add or remove funds. The new funding transaction is pending until confirmed on chain and thus needs to be tracked. Additionally, it may be replaced by another transaction using RBF with a higher fee. Hence, there may be more than one pending FundingScope to track for a splice. This commit adds support for tracking pending funding scopes. The following commits will account for any pending scopes where applicable (e.g., when handling commitment_signed).
1 parent ba60b04 commit 33bc387

File tree

4 files changed

+99
-17
lines changed

4 files changed

+99
-17
lines changed

lightning/src/chain/onchaintx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
368368
let prev_holder_commitment = Readable::read(reader)?;
369369
let _prev_holder_htlc_sigs: Option<Vec<Option<(usize, Signature)>>> = Readable::read(reader)?;
370370

371-
let channel_parameters = ReadableArgs::<u64>::read(reader, channel_value_satoshis)?;
371+
let channel_parameters = ReadableArgs::<Option<u64>>::read(reader, Some(channel_value_satoshis))?;
372372

373373
// Read the serialized signer bytes, but don't deserialize them, as we'll obtain our signer
374374
// by re-deriving the private key material.

lightning/src/ln/chan_utils.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,8 +1034,8 @@ impl Writeable for ChannelTransactionParameters {
10341034
}
10351035
}
10361036

1037-
impl ReadableArgs<u64> for ChannelTransactionParameters {
1038-
fn read<R: io::Read>(reader: &mut R, read_args: u64) -> Result<Self, DecodeError> {
1037+
impl ReadableArgs<Option<u64>> for ChannelTransactionParameters {
1038+
fn read<R: io::Read>(reader: &mut R, read_args: Option<u64>) -> Result<Self, DecodeError> {
10391039
let mut holder_pubkeys = RequiredWrapper(None);
10401040
let mut holder_selected_contest_delay = RequiredWrapper(None);
10411041
let mut is_outbound_from_holder = RequiredWrapper(None);
@@ -1058,10 +1058,17 @@ impl ReadableArgs<u64> for ChannelTransactionParameters {
10581058
(13, channel_value_satoshis, option),
10591059
});
10601060

1061-
let channel_value_satoshis = channel_value_satoshis.unwrap_or(read_args);
1062-
if channel_value_satoshis != read_args {
1063-
return Err(DecodeError::InvalidValue);
1064-
}
1061+
let channel_value_satoshis = match read_args {
1062+
None => channel_value_satoshis.ok_or(DecodeError::InvalidValue)?,
1063+
Some(expected_value) => {
1064+
let channel_value_satoshis = channel_value_satoshis.unwrap_or(expected_value);
1065+
if channel_value_satoshis == expected_value {
1066+
channel_value_satoshis
1067+
} else {
1068+
return Err(DecodeError::InvalidValue);
1069+
}
1070+
},
1071+
};
10651072

10661073
let mut additional_features = ChannelTypeFeatures::empty();
10671074
additional_features.set_anchors_nonzero_fee_htlc_tx_required();

lightning/src/ln/channel.rs

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Reci
6060
use crate::events::{ClosureReason, Event};
6161
use crate::events::bump_transaction::BASE_INPUT_WEIGHT;
6262
use crate::routing::gossip::NodeId;
63-
use crate::util::ser::{Readable, ReadableArgs, TransactionU16LenLimited, Writeable, Writer};
63+
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, TransactionU16LenLimited, Writeable, Writer};
6464
use crate::util::logger::{Logger, Record, WithContext};
6565
use crate::util::errors::APIError;
6666
use crate::util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, MaxDustHTLCExposure};
@@ -1517,6 +1517,7 @@ impl<SP: Deref> Channel<SP> where
15171517
};
15181518
let mut funded_channel = FundedChannel {
15191519
funding: chan.funding,
1520+
pending_funding: vec![],
15201521
context: chan.context,
15211522
interactive_tx_signing_session: chan.interactive_tx_signing_session,
15221523
holder_commitment_point,
@@ -1663,6 +1664,63 @@ pub(super) struct FundingScope {
16631664
funding_transaction: Option<Transaction>,
16641665
}
16651666

1667+
impl Writeable for FundingScope {
1668+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1669+
#[cfg(any(test, fuzzing))]
1670+
self.next_local_commitment_tx_fee_info_cached.write(writer)?;
1671+
#[cfg(any(test, fuzzing))]
1672+
self.next_remote_commitment_tx_fee_info_cached.write(writer)?;
1673+
1674+
write_tlv_fields!(writer, {
1675+
(1, self.value_to_self_msat, required),
1676+
(3, self.counterparty_selected_channel_reserve_satoshis, option),
1677+
(5, self.holder_selected_channel_reserve_satoshis, required),
1678+
(7, self.channel_transaction_parameters, (required: ReadableArgs, None)),
1679+
(9, self.funding_transaction, option),
1680+
});
1681+
Ok(())
1682+
}
1683+
}
1684+
1685+
impl Readable for FundingScope {
1686+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1687+
let mut value_to_self_msat = RequiredWrapper(None);
1688+
let mut counterparty_selected_channel_reserve_satoshis = None;
1689+
let mut holder_selected_channel_reserve_satoshis = RequiredWrapper(None);
1690+
let mut channel_transaction_parameters = RequiredWrapper(None);
1691+
let mut funding_transaction = None;
1692+
1693+
#[cfg(any(test, fuzzing))]
1694+
let next_local_commitment_tx_fee_info_cached = Readable::read(reader)?;
1695+
#[cfg(any(test, fuzzing))]
1696+
let next_remote_commitment_tx_fee_info_cached = Readable::read(reader)?;
1697+
1698+
read_tlv_fields!(reader, {
1699+
(1, value_to_self_msat, required),
1700+
(3, counterparty_selected_channel_reserve_satoshis, option),
1701+
(5, holder_selected_channel_reserve_satoshis, required),
1702+
(7, channel_transaction_parameters, (required: ReadableArgs, None)),
1703+
(9, funding_transaction, option),
1704+
});
1705+
1706+
Ok(Self {
1707+
value_to_self_msat: value_to_self_msat.0.unwrap(),
1708+
counterparty_selected_channel_reserve_satoshis,
1709+
holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis.0.unwrap(),
1710+
#[cfg(debug_assertions)]
1711+
holder_max_commitment_tx_output: Mutex::new((0, 0)),
1712+
#[cfg(debug_assertions)]
1713+
counterparty_max_commitment_tx_output: Mutex::new((0, 0)),
1714+
channel_transaction_parameters: channel_transaction_parameters.0.unwrap(),
1715+
funding_transaction,
1716+
#[cfg(any(test, fuzzing))]
1717+
next_local_commitment_tx_fee_info_cached,
1718+
#[cfg(any(test, fuzzing))]
1719+
next_remote_commitment_tx_fee_info_cached,
1720+
})
1721+
}
1722+
}
1723+
16661724
impl FundingScope {
16671725
pub fn get_value_satoshis(&self) -> u64 {
16681726
self.channel_transaction_parameters.channel_value_satoshis
@@ -3527,7 +3585,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35273585
if let Some(info) = projected_commit_tx_info {
35283586
let total_pending_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len()
35293587
+ self.holding_cell_htlc_updates.len();
3530-
if info.total_pending_htlcs == total_pending_htlcs
3588+
if info.total_pending_htlcs == total_pending_htlcs as u64
35313589
&& info.next_holder_htlc_id == self.next_holder_htlc_id
35323590
&& info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
35333591
&& info.feerate == self.feerate_per_kw {
@@ -4319,7 +4377,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
43194377
+ context.holding_cell_htlc_updates.len();
43204378
let commitment_tx_info = CommitmentTxInfoCached {
43214379
fee,
4322-
total_pending_htlcs,
4380+
total_pending_htlcs: total_pending_htlcs as u64,
43234381
next_holder_htlc_id: match htlc.origin {
43244382
HTLCInitiator::LocalOffered => context.next_holder_htlc_id + 1,
43254383
HTLCInitiator::RemoteOffered => context.next_holder_htlc_id,
@@ -4415,7 +4473,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
44154473
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len();
44164474
let commitment_tx_info = CommitmentTxInfoCached {
44174475
fee,
4418-
total_pending_htlcs,
4476+
total_pending_htlcs: total_pending_htlcs as u64,
44194477
next_holder_htlc_id: match htlc.origin {
44204478
HTLCInitiator::LocalOffered => context.next_holder_htlc_id + 1,
44214479
HTLCInitiator::RemoteOffered => context.next_holder_htlc_id,
@@ -4868,6 +4926,7 @@ pub(super) struct DualFundingChannelContext {
48684926
// Counterparty designates channel data owned by the another channel participant entity.
48694927
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48704928
pub funding: FundingScope,
4929+
pending_funding: Vec<FundingScope>,
48714930
pub context: ChannelContext<SP>,
48724931
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
48734932
holder_commitment_point: HolderCommitmentPoint,
@@ -4882,12 +4941,21 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48824941
#[cfg(any(test, fuzzing))]
48834942
struct CommitmentTxInfoCached {
48844943
fee: u64,
4885-
total_pending_htlcs: usize,
4944+
total_pending_htlcs: u64,
48864945
next_holder_htlc_id: u64,
48874946
next_counterparty_htlc_id: u64,
48884947
feerate: u32,
48894948
}
48904949

4950+
#[cfg(any(test, fuzzing))]
4951+
impl_writeable_tlv_based!(CommitmentTxInfoCached, {
4952+
(0, fee, required),
4953+
(1, total_pending_htlcs, required),
4954+
(2, next_holder_htlc_id, required),
4955+
(3, next_counterparty_htlc_id, required),
4956+
(4, feerate, required),
4957+
});
4958+
48914959
/// Partial data from ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo used to simplify the
48924960
/// return type of `ChannelContext::validate_commitment_signed`.
48934961
struct LatestHolderCommitmentTXInfo {
@@ -8752,7 +8820,7 @@ impl<SP: Deref> FundedChannel<SP> where
87528820
*self.funding.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
87538821
if let Some(info) = projected_commit_tx_info {
87548822
let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len();
8755-
if info.total_pending_htlcs == total_pending_htlcs
8823+
if info.total_pending_htlcs == total_pending_htlcs as u64
87568824
&& info.next_holder_htlc_id == self.context.next_holder_htlc_id
87578825
&& info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id
87588826
&& info.feerate == self.context.feerate_per_kw {
@@ -9455,6 +9523,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
94559523

94569524
let mut channel = FundedChannel {
94579525
funding: self.funding,
9526+
pending_funding: vec![],
94589527
context: self.context,
94599528
interactive_tx_signing_session: None,
94609529
is_v2_established: false,
@@ -9731,6 +9800,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
97319800
// `ChannelMonitor`.
97329801
let mut channel = FundedChannel {
97339802
funding: self.funding,
9803+
pending_funding: vec![],
97349804
context: self.context,
97359805
interactive_tx_signing_session: None,
97369806
is_v2_established: false,
@@ -10525,6 +10595,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1052510595
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1052610596
(51, is_manual_broadcast, option), // Added in 0.0.124
1052710597
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10598+
(54, self.pending_funding, optional_vec), // Added in 0.2
1052810599
});
1052910600

1053010601
Ok(())
@@ -10749,7 +10820,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1074910820
_ => return Err(DecodeError::InvalidValue),
1075010821
};
1075110822

10752-
let mut channel_parameters: ChannelTransactionParameters = ReadableArgs::<u64>::read(reader, channel_value_satoshis)?;
10823+
let mut channel_parameters: ChannelTransactionParameters = ReadableArgs::<Option<u64>>::read(reader, Some(channel_value_satoshis))?;
1075310824
let funding_transaction: Option<Transaction> = Readable::read(reader)?;
1075410825

1075510826
let counterparty_cur_commitment_point = Readable::read(reader)?;
@@ -10816,6 +10887,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1081610887
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
1081710888
let mut is_manual_broadcast = None;
1081810889

10890+
let mut pending_funding = Some(Vec::new());
10891+
1081910892
read_tlv_fields!(reader, {
1082010893
(0, announcement_sigs, option),
1082110894
(1, minimum_depth, option),
@@ -10851,6 +10924,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1085110924
(49, local_initiated_shutdown, option),
1085210925
(51, is_manual_broadcast, option),
1085310926
(53, funding_tx_broadcast_safe_event_emitted, option),
10927+
(54, pending_funding, optional_vec), // Added in 0.2
1085410928
});
1085510929

1085610930
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -10992,6 +11066,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1099211066
channel_transaction_parameters: channel_parameters,
1099311067
funding_transaction,
1099411068
},
11069+
pending_funding: pending_funding.unwrap(),
1099511070
context: ChannelContext {
1099611071
user_id,
1099711072

lightning/src/sign/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl_writeable_tlv_based!(DelayedPaymentOutputDescriptor, {
124124
(8, revocation_pubkey, required),
125125
(10, channel_keys_id, required),
126126
(12, channel_value_satoshis, required),
127-
(13, channel_transaction_parameters, (option: ReadableArgs, channel_value_satoshis.0.unwrap())),
127+
(13, channel_transaction_parameters, (option: ReadableArgs, Some(channel_value_satoshis.0.unwrap()))),
128128
});
129129

130130
pub(crate) const P2WPKH_WITNESS_WEIGHT: u64 = 1 /* num stack items */ +
@@ -199,7 +199,7 @@ impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, {
199199
(2, output, required),
200200
(4, channel_keys_id, required),
201201
(6, channel_value_satoshis, required),
202-
(7, channel_transaction_parameters, (option: ReadableArgs, channel_value_satoshis.0.unwrap())),
202+
(7, channel_transaction_parameters, (option: ReadableArgs, Some(channel_value_satoshis.0.unwrap()))),
203203
});
204204

205205
/// Describes the necessary information to spend a spendable output.
@@ -559,7 +559,7 @@ pub struct ChannelDerivationParameters {
559559
impl_writeable_tlv_based!(ChannelDerivationParameters, {
560560
(0, value_satoshis, required),
561561
(2, keys_id, required),
562-
(4, transaction_parameters, (required: ReadableArgs, value_satoshis.0.unwrap())),
562+
(4, transaction_parameters, (required: ReadableArgs, Some(value_satoshis.0.unwrap()))),
563563
});
564564

565565
/// A descriptor used to sign for a commitment transaction's HTLC output.

0 commit comments

Comments
 (0)