Skip to content

Commit a67367b

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 0715cd3 commit a67367b

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};
@@ -1514,6 +1514,7 @@ impl<SP: Deref> Channel<SP> where
15141514
};
15151515
let mut funded_channel = FundedChannel {
15161516
funding: chan.funding,
1517+
pending_funding: vec![],
15171518
context: chan.context,
15181519
interactive_tx_signing_session: chan.interactive_tx_signing_session,
15191520
holder_commitment_point,
@@ -1660,6 +1661,63 @@ pub(super) struct FundingScope {
16601661
funding_transaction: Option<Transaction>,
16611662
}
16621663

1664+
impl Writeable for FundingScope {
1665+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
1666+
#[cfg(any(test, fuzzing))]
1667+
self.next_local_commitment_tx_fee_info_cached.write(writer)?;
1668+
#[cfg(any(test, fuzzing))]
1669+
self.next_remote_commitment_tx_fee_info_cached.write(writer)?;
1670+
1671+
write_tlv_fields!(writer, {
1672+
(0, self.value_to_self_msat, required),
1673+
(1, self.counterparty_selected_channel_reserve_satoshis, option),
1674+
(2, self.holder_selected_channel_reserve_satoshis, required),
1675+
(3, self.channel_transaction_parameters, (required: ReadableArgs, None)),
1676+
(4, self.funding_transaction, option),
1677+
});
1678+
Ok(())
1679+
}
1680+
}
1681+
1682+
impl Readable for FundingScope {
1683+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
1684+
let mut value_to_self_msat = RequiredWrapper(None);
1685+
let mut counterparty_selected_channel_reserve_satoshis = None;
1686+
let mut holder_selected_channel_reserve_satoshis = RequiredWrapper(None);
1687+
let mut channel_transaction_parameters = RequiredWrapper(None);
1688+
let mut funding_transaction = None;
1689+
1690+
#[cfg(any(test, fuzzing))]
1691+
let next_local_commitment_tx_fee_info_cached = Readable::read(reader)?;
1692+
#[cfg(any(test, fuzzing))]
1693+
let next_remote_commitment_tx_fee_info_cached = Readable::read(reader)?;
1694+
1695+
read_tlv_fields!(reader, {
1696+
(0, value_to_self_msat, required),
1697+
(1, counterparty_selected_channel_reserve_satoshis, option),
1698+
(2, holder_selected_channel_reserve_satoshis, required),
1699+
(3, channel_transaction_parameters, (required: ReadableArgs, None)),
1700+
(4, funding_transaction, option),
1701+
});
1702+
1703+
Ok(Self {
1704+
value_to_self_msat: value_to_self_msat.0.unwrap(),
1705+
counterparty_selected_channel_reserve_satoshis,
1706+
holder_selected_channel_reserve_satoshis: holder_selected_channel_reserve_satoshis.0.unwrap(),
1707+
#[cfg(debug_assertions)]
1708+
holder_max_commitment_tx_output: Mutex::new((0, 0)),
1709+
#[cfg(debug_assertions)]
1710+
counterparty_max_commitment_tx_output: Mutex::new((0, 0)),
1711+
channel_transaction_parameters: channel_transaction_parameters.0.unwrap(),
1712+
funding_transaction,
1713+
#[cfg(any(test, fuzzing))]
1714+
next_local_commitment_tx_fee_info_cached,
1715+
#[cfg(any(test, fuzzing))]
1716+
next_remote_commitment_tx_fee_info_cached,
1717+
})
1718+
}
1719+
}
1720+
16631721
impl FundingScope {
16641722
pub fn get_value_satoshis(&self) -> u64 {
16651723
self.channel_transaction_parameters.channel_value_satoshis
@@ -3522,7 +3580,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35223580
if let Some(info) = projected_commit_tx_info {
35233581
let total_pending_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len()
35243582
+ self.holding_cell_htlc_updates.len();
3525-
if info.total_pending_htlcs == total_pending_htlcs
3583+
if info.total_pending_htlcs == total_pending_htlcs as u64
35263584
&& info.next_holder_htlc_id == self.next_holder_htlc_id
35273585
&& info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
35283586
&& info.feerate == self.feerate_per_kw {
@@ -4342,7 +4400,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
43424400
+ context.holding_cell_htlc_updates.len();
43434401
let commitment_tx_info = CommitmentTxInfoCached {
43444402
fee,
4345-
total_pending_htlcs,
4403+
total_pending_htlcs: total_pending_htlcs as u64,
43464404
next_holder_htlc_id: match htlc.origin {
43474405
HTLCInitiator::LocalOffered => context.next_holder_htlc_id + 1,
43484406
HTLCInitiator::RemoteOffered => context.next_holder_htlc_id,
@@ -4438,7 +4496,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
44384496
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len();
44394497
let commitment_tx_info = CommitmentTxInfoCached {
44404498
fee,
4441-
total_pending_htlcs,
4499+
total_pending_htlcs: total_pending_htlcs as u64,
44424500
next_holder_htlc_id: match htlc.origin {
44434501
HTLCInitiator::LocalOffered => context.next_holder_htlc_id + 1,
44444502
HTLCInitiator::RemoteOffered => context.next_holder_htlc_id,
@@ -4890,6 +4948,7 @@ pub(super) struct DualFundingChannelContext {
48904948
// Counterparty designates channel data owned by the another channel participant entity.
48914949
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48924950
pub funding: FundingScope,
4951+
pending_funding: Vec<FundingScope>,
48934952
pub context: ChannelContext<SP>,
48944953
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
48954954
holder_commitment_point: HolderCommitmentPoint,
@@ -4904,12 +4963,21 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49044963
#[cfg(any(test, fuzzing))]
49054964
struct CommitmentTxInfoCached {
49064965
fee: u64,
4907-
total_pending_htlcs: usize,
4966+
total_pending_htlcs: u64,
49084967
next_holder_htlc_id: u64,
49094968
next_counterparty_htlc_id: u64,
49104969
feerate: u32,
49114970
}
49124971

4972+
#[cfg(any(test, fuzzing))]
4973+
impl_writeable_tlv_based!(CommitmentTxInfoCached, {
4974+
(0, fee, required),
4975+
(1, total_pending_htlcs, required),
4976+
(2, next_holder_htlc_id, required),
4977+
(3, next_counterparty_htlc_id, required),
4978+
(4, feerate, required),
4979+
});
4980+
49134981
/// Partial data from ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo used to simplify the
49144982
/// return type of `ChannelContext::validate_commitment_signed`.
49154983
struct LatestHolderCommitmentTXInfo {
@@ -8770,7 +8838,7 @@ impl<SP: Deref> FundedChannel<SP> where
87708838
*self.funding.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
87718839
if let Some(info) = projected_commit_tx_info {
87728840
let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len();
8773-
if info.total_pending_htlcs == total_pending_htlcs
8841+
if info.total_pending_htlcs == total_pending_htlcs as u64
87748842
&& info.next_holder_htlc_id == self.context.next_holder_htlc_id
87758843
&& info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id
87768844
&& info.feerate == self.context.feerate_per_kw {
@@ -9472,6 +9540,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
94729540

94739541
let mut channel = FundedChannel {
94749542
funding: self.funding,
9543+
pending_funding: vec![],
94759544
context: self.context,
94769545
interactive_tx_signing_session: None,
94779546
is_v2_established: false,
@@ -9748,6 +9817,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
97489817
// `ChannelMonitor`.
97499818
let mut channel = FundedChannel {
97509819
funding: self.funding,
9820+
pending_funding: vec![],
97519821
context: self.context,
97529822
interactive_tx_signing_session: None,
97539823
is_v2_established: false,
@@ -10542,6 +10612,7 @@ impl<SP: Deref> Writeable for FundedChannel<SP> where SP::Target: SignerProvider
1054210612
(49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
1054310613
(51, is_manual_broadcast, option), // Added in 0.0.124
1054410614
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
10615+
(55, self.pending_funding, optional_vec), // Added in 0.2
1054510616
});
1054610617

1054710618
Ok(())
@@ -10766,7 +10837,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1076610837
_ => return Err(DecodeError::InvalidValue),
1076710838
};
1076810839

10769-
let mut channel_parameters: ChannelTransactionParameters = ReadableArgs::<u64>::read(reader, channel_value_satoshis)?;
10840+
let mut channel_parameters: ChannelTransactionParameters = ReadableArgs::<Option<u64>>::read(reader, Some(channel_value_satoshis))?;
1077010841
let funding_transaction: Option<Transaction> = Readable::read(reader)?;
1077110842

1077210843
let counterparty_cur_commitment_point = Readable::read(reader)?;
@@ -10833,6 +10904,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1083310904
let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
1083410905
let mut is_manual_broadcast = None;
1083510906

10907+
let mut pending_funding = Some(Vec::new());
10908+
1083610909
read_tlv_fields!(reader, {
1083710910
(0, announcement_sigs, option),
1083810911
(1, minimum_depth, option),
@@ -10868,6 +10941,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1086810941
(49, local_initiated_shutdown, option),
1086910942
(51, is_manual_broadcast, option),
1087010943
(53, funding_tx_broadcast_safe_event_emitted, option),
10944+
(55, pending_funding, optional_vec), // Added in 0.2
1087110945
});
1087210946

1087310947
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -11009,6 +11083,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1100911083
channel_transaction_parameters: channel_parameters,
1101011084
funding_transaction,
1101111085
},
11086+
pending_funding: pending_funding.unwrap(),
1101211087
context: ChannelContext {
1101311088
user_id,
1101411089

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, channel_value_satoshis.0)),
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, channel_value_satoshis.0)),
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, value_satoshis.0)),
563563
});
564564

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

0 commit comments

Comments
 (0)