Skip to content

Commit 84ea044

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 99c2fd9 commit 84ea044

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
@@ -1248,6 +1248,16 @@ impl<SP: Deref> Channel<SP> where
12481248
}
12491249
}
12501250

1251+
pub fn pending_funding(&self) -> &[FundingScope] {
1252+
match &self.phase {
1253+
ChannelPhase::Undefined => unreachable!(),
1254+
ChannelPhase::Funded(chan) => &chan.pending_funding,
1255+
ChannelPhase::UnfundedOutboundV1(_) => &[],
1256+
ChannelPhase::UnfundedInboundV1(_) => &[],
1257+
ChannelPhase::UnfundedV2(_) => &[],
1258+
}
1259+
}
1260+
12511261
pub fn unfunded_context_mut(&mut self) -> Option<&mut UnfundedChannelContext> {
12521262
match &mut self.phase {
12531263
ChannelPhase::Undefined => unreachable!(),
@@ -4139,6 +4149,20 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41394149
/// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
41404150
/// corner case properly.
41414151
pub fn get_available_balances<F: Deref>(
4152+
&self, funding: &FundingScope, pending_funding: &[FundingScope],
4153+
fee_estimator: &LowerBoundedFeeEstimator<F>,
4154+
) -> AvailableBalances
4155+
where
4156+
F::Target: FeeEstimator,
4157+
{
4158+
core::iter::once(funding)
4159+
.chain(pending_funding.iter())
4160+
.map(|funding| self.get_available_balances_for_scope(funding, fee_estimator))
4161+
.min_by_key(|balances| balances.next_outbound_htlc_limit_msat)
4162+
.expect("At least one FundingScope is always provided")
4163+
}
4164+
4165+
fn get_available_balances_for_scope<F: Deref>(
41424166
&self, funding: &FundingScope, fee_estimator: &LowerBoundedFeeEstimator<F>,
41434167
) -> AvailableBalances
41444168
where
@@ -4929,7 +4953,7 @@ pub(super) struct DualFundingChannelContext {
49294953
// Counterparty designates channel data owned by the another channel participant entity.
49304954
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49314955
pub funding: FundingScope,
4932-
pending_funding: Vec<FundingScope>,
4956+
pub(super) pending_funding: Vec<FundingScope>,
49334957
commitment_signed_batch: BTreeMap<Txid, msgs::CommitmentSigned>,
49344958
pub context: ChannelContext<SP>,
49354959
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
@@ -8732,7 +8756,7 @@ impl<SP: Deref> FundedChannel<SP> where
87328756
return Err(ChannelError::Ignore("Cannot send 0-msat HTLC".to_owned()));
87338757
}
87348758

8735-
let available_balances = self.context.get_available_balances(&self.funding, fee_estimator);
8759+
let available_balances = self.get_available_balances(fee_estimator);
87368760
if amount_msat < available_balances.next_outbound_htlc_minimum_msat {
87378761
return Err(ChannelError::Ignore(format!("Cannot send less than our next-HTLC minimum - {} msat",
87388762
available_balances.next_outbound_htlc_minimum_msat)));
@@ -8804,6 +8828,15 @@ impl<SP: Deref> FundedChannel<SP> where
88048828
Ok(Some(res))
88058829
}
88068830

8831+
pub fn get_available_balances<F: Deref>(
8832+
&self, fee_estimator: &LowerBoundedFeeEstimator<F>,
8833+
) -> AvailableBalances
8834+
where
8835+
F::Target: FeeEstimator,
8836+
{
8837+
self.context.get_available_balances(&self.funding, &self.pending_funding, fee_estimator)
8838+
}
8839+
88078840
fn build_commitment_no_status_check<L: Deref>(&mut self, logger: &L) -> ChannelMonitorUpdate where L::Target: Logger {
88088841
log_trace!(logger, "Updating HTLC state for a newly-sent commitment_signed...");
88098842
// 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
@@ -3744,8 +3744,11 @@ where
37443744
.filter_map(|(chan_id, chan)| chan.as_funded().map(|chan| (chan_id, chan)))
37453745
.filter(f)
37463746
.map(|(_channel_id, channel)| {
3747-
ChannelDetails::from_channel_context(&channel.context, &channel.funding, best_block_height,
3748-
peer_state.latest_features.clone(), &self.fee_estimator)
3747+
ChannelDetails::from_channel_context(
3748+
&channel.context, &channel.funding, &channel.pending_funding,
3749+
best_block_height, peer_state.latest_features.clone(),
3750+
&self.fee_estimator,
3751+
)
37493752
})
37503753
);
37513754
}
@@ -3768,9 +3771,13 @@ where
37683771
for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
37693772
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
37703773
let peer_state = &mut *peer_state_lock;
3771-
for (context, funding) in peer_state.channel_by_id.iter().map(|(_, chan)| (chan.context(), chan.funding())) {
3772-
let details = ChannelDetails::from_channel_context(context, funding, best_block_height,
3773-
peer_state.latest_features.clone(), &self.fee_estimator);
3774+
for (context, funding, pending_funding) in peer_state.channel_by_id.iter()
3775+
.map(|(_, chan)| (chan.context(), chan.funding(), chan.pending_funding()))
3776+
{
3777+
let details = ChannelDetails::from_channel_context(
3778+
context, funding, pending_funding, best_block_height,
3779+
peer_state.latest_features.clone(), &self.fee_estimator,
3780+
);
37743781
res.push(details);
37753782
}
37763783
}
@@ -3800,12 +3807,15 @@ where
38003807
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
38013808
let peer_state = &mut *peer_state_lock;
38023809
let features = &peer_state.latest_features;
3803-
let context_to_details = |(context, funding)| {
3804-
ChannelDetails::from_channel_context(context, funding, best_block_height, features.clone(), &self.fee_estimator)
3810+
let context_to_details = |(context, funding, pending_funding)| {
3811+
ChannelDetails::from_channel_context(
3812+
context, funding, pending_funding, best_block_height, features.clone(),
3813+
&self.fee_estimator,
3814+
)
38053815
};
38063816
return peer_state.channel_by_id
38073817
.iter()
3808-
.map(|(_, chan)| (chan.context(), chan.funding()))
3818+
.map(|(_, chan)| (chan.context(), chan.funding(), chan.pending_funding()))
38093819
.map(context_to_details)
38103820
.collect();
38113821
}
@@ -6087,7 +6097,7 @@ where
60876097
let maybe_optimal_channel = peer_state.channel_by_id.values_mut()
60886098
.filter_map(Channel::as_funded_mut)
60896099
.filter_map(|chan| {
6090-
let balances = chan.context.get_available_balances(&chan.funding, &self.fee_estimator);
6100+
let balances = chan.get_available_balances(&self.fee_estimator);
60916101
if outgoing_amt_msat <= balances.next_outbound_htlc_limit_msat &&
60926102
outgoing_amt_msat >= balances.next_outbound_htlc_minimum_msat &&
60936103
chan.context.is_usable() {

0 commit comments

Comments
 (0)