Skip to content

Commit 3872586

Browse files
committed
Consider funding scopes in get_available_balances
A FundedChannel may have more than one pending FundingScope during splicing, one for the splice attempt and one or more for any RBF attempts. When calling get_available_balances, consider all funding scopes and take the minimum by next_outbound_htlc_limit_msat. This is used both informationally and to determine which channel to use to forward an HTLC. The choice of next_outbound_htlc_limit_msat is somewhat arbitrary but matches the field used when determining which channel used to forward an HTLC. Any field should do since each field should be adjusted by the same amount relative to another FundingScope given the nature of the fields (i.e., inbound/outbound capacity, min/max HTLC limit). Using the minimum was chosen since an order for an HTLC to be sent over the channel, it must be possible for each funding scope -- both the confirmed one and any pending scopes, one of which may eventually confirm.
1 parent 41c52cb commit 3872586

File tree

3 files changed

+58
-14
lines changed

3 files changed

+58
-14
lines changed

lightning/src/ln/channel.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,16 @@ impl<SP: Deref> Channel<SP> where
12441244
}
12451245
}
12461246

1247+
pub fn pending_funding(&self) -> &[FundingScope] {
1248+
match &self.phase {
1249+
ChannelPhase::Undefined => unreachable!(),
1250+
ChannelPhase::Funded(chan) => &chan.pending_funding,
1251+
ChannelPhase::UnfundedOutboundV1(_) => &[],
1252+
ChannelPhase::UnfundedInboundV1(_) => &[],
1253+
ChannelPhase::UnfundedV2(_) => &[],
1254+
}
1255+
}
1256+
12471257
pub fn unfunded_context_mut(&mut self) -> Option<&mut UnfundedChannelContext> {
12481258
match &mut self.phase {
12491259
ChannelPhase::Undefined => unreachable!(),
@@ -4112,6 +4122,20 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41124122
/// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
41134123
/// corner case properly.
41144124
pub fn get_available_balances<F: Deref>(
4125+
&self, funding: &FundingScope, pending_funding: &[FundingScope],
4126+
fee_estimator: &LowerBoundedFeeEstimator<F>,
4127+
) -> AvailableBalances
4128+
where
4129+
F::Target: FeeEstimator,
4130+
{
4131+
core::iter::once(funding)
4132+
.chain(pending_funding.iter())
4133+
.map(|funding| self.get_available_balances_for_scope(funding, fee_estimator))
4134+
.min_by_key(|balances| balances.next_outbound_htlc_limit_msat)
4135+
.expect("At least one FundingScope is always provided")
4136+
}
4137+
4138+
fn get_available_balances_for_scope<F: Deref>(
41154139
&self, funding: &FundingScope, fee_estimator: &LowerBoundedFeeEstimator<F>,
41164140
) -> AvailableBalances
41174141
where
@@ -4848,7 +4872,7 @@ pub(super) struct DualFundingChannelContext {
48484872
// Counterparty designates channel data owned by the another channel participant entity.
48494873
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48504874
pub funding: FundingScope,
4851-
pending_funding: Vec<FundingScope>,
4875+
pub(super) pending_funding: Vec<FundingScope>,
48524876
commitment_signed_batch: Vec<msgs::CommitmentSigned>,
48534877
pub context: ChannelContext<SP>,
48544878
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
@@ -8504,7 +8528,7 @@ impl<SP: Deref> FundedChannel<SP> where
85048528
return Err(ChannelError::Ignore("Cannot send 0-msat HTLC".to_owned()));
85058529
}
85068530

8507-
let available_balances = self.context.get_available_balances(&self.funding, fee_estimator);
8531+
let available_balances = self.get_available_balances(fee_estimator);
85088532
if amount_msat < available_balances.next_outbound_htlc_minimum_msat {
85098533
return Err(ChannelError::Ignore(format!("Cannot send less than our next-HTLC minimum - {} msat",
85108534
available_balances.next_outbound_htlc_minimum_msat)));
@@ -8576,6 +8600,15 @@ impl<SP: Deref> FundedChannel<SP> where
85768600
Ok(Some(res))
85778601
}
85788602

8603+
pub fn get_available_balances<F: Deref>(
8604+
&self, fee_estimator: &LowerBoundedFeeEstimator<F>,
8605+
) -> AvailableBalances
8606+
where
8607+
F::Target: FeeEstimator,
8608+
{
8609+
self.context.get_available_balances(&self.funding, &self.pending_funding, fee_estimator)
8610+
}
8611+
85798612
fn build_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger {
85808613
log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
85818614
// We can upgrade the status of some HTLCs that are waiting on a commitment, even if we

lightning/src/ln/channel_state.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,15 @@ impl ChannelDetails {
476476
}
477477

478478
pub(super) fn from_channel_context<SP: Deref, F: Deref>(
479-
context: &ChannelContext<SP>, funding: &FundingScope, best_block_height: u32,
480-
latest_features: InitFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
479+
context: &ChannelContext<SP>, funding: &FundingScope, pending_funding: &[FundingScope],
480+
best_block_height: u32, latest_features: InitFeatures,
481+
fee_estimator: &LowerBoundedFeeEstimator<F>,
481482
) -> Self
482483
where
483484
SP::Target: SignerProvider,
484485
F::Target: FeeEstimator,
485486
{
486-
let balance = context.get_available_balances(funding, fee_estimator);
487+
let balance = context.get_available_balances(funding, pending_funding, fee_estimator);
487488
let (to_remote_reserve_satoshis, to_self_reserve_satoshis) =
488489
funding.get_holder_counterparty_selected_channel_reserve_satoshis();
489490
#[allow(deprecated)] // TODO: Remove once balance_msat is removed.

lightning/src/ln/channelmanager.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -3790,8 +3790,11 @@ where
37903790
.filter_map(|(chan_id, chan)| chan.as_funded().map(|chan| (chan_id, chan)))
37913791
.filter(f)
37923792
.map(|(_channel_id, channel)| {
3793-
ChannelDetails::from_channel_context(&channel.context, &channel.funding, best_block_height,
3794-
peer_state.latest_features.clone(), &self.fee_estimator)
3793+
ChannelDetails::from_channel_context(
3794+
&channel.context, &channel.funding, &channel.pending_funding,
3795+
best_block_height, peer_state.latest_features.clone(),
3796+
&self.fee_estimator,
3797+
)
37953798
})
37963799
);
37973800
}
@@ -3815,9 +3818,13 @@ where
38153818
for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
38163819
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
38173820
let peer_state = &mut *peer_state_lock;
3818-
for (context, funding) in peer_state.channel_by_id.iter().map(|(_, chan)| (chan.context(), chan.funding())) {
3819-
let details = ChannelDetails::from_channel_context(context, funding, best_block_height,
3820-
peer_state.latest_features.clone(), &self.fee_estimator);
3821+
for (context, funding, pending_funding) in peer_state.channel_by_id.iter()
3822+
.map(|(_, chan)| (chan.context(), chan.funding(), chan.pending_funding()))
3823+
{
3824+
let details = ChannelDetails::from_channel_context(
3825+
context, funding, pending_funding, best_block_height,
3826+
peer_state.latest_features.clone(), &self.fee_estimator,
3827+
);
38213828
res.push(details);
38223829
}
38233830
}
@@ -3847,12 +3854,15 @@ where
38473854
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
38483855
let peer_state = &mut *peer_state_lock;
38493856
let features = &peer_state.latest_features;
3850-
let context_to_details = |(context, funding)| {
3851-
ChannelDetails::from_channel_context(context, funding, best_block_height, features.clone(), &self.fee_estimator)
3857+
let context_to_details = |(context, funding, pending_funding)| {
3858+
ChannelDetails::from_channel_context(
3859+
context, funding, pending_funding, best_block_height, features.clone(),
3860+
&self.fee_estimator,
3861+
)
38523862
};
38533863
return peer_state.channel_by_id
38543864
.iter()
3855-
.map(|(_, chan)| (chan.context(), chan.funding()))
3865+
.map(|(_, chan)| (chan.context(), chan.funding(), chan.pending_funding()))
38563866
.map(context_to_details)
38573867
.collect();
38583868
}
@@ -6007,7 +6017,7 @@ where
60076017
let maybe_optimal_channel = peer_state.channel_by_id.values_mut()
60086018
.filter_map(Channel::as_funded_mut)
60096019
.filter_map(|chan| {
6010-
let balances = chan.context.get_available_balances(&chan.funding, &self.fee_estimator);
6020+
let balances = chan.get_available_balances(&self.fee_estimator);
60116021
if outgoing_amt_msat <= balances.next_outbound_htlc_limit_msat &&
60126022
outgoing_amt_msat >= balances.next_outbound_htlc_minimum_msat &&
60136023
chan.context.is_usable() {

0 commit comments

Comments
 (0)