Skip to content

Commit 62edee5

Browse files
authored
Merge pull request #1435 from TheBlueMatt/2022-04-1126-first-step
2 parents df1c4ee + 61629bc commit 62edee5

File tree

5 files changed

+105
-79
lines changed

5 files changed

+105
-79
lines changed

fuzz/src/router.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use bitcoin::blockdata::constants::genesis_block;
2929

3030
use utils::test_logger;
3131

32+
use std::convert::TryInto;
3233
use std::collections::HashSet;
3334
use std::sync::Arc;
3435
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -205,7 +206,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
205206
count => {
206207
for _ in 0..count {
207208
scid += 1;
208-
let rnid = node_pks.iter().skip(slice_to_be16(get_slice!(2))as usize % node_pks.len()).next().unwrap();
209+
let rnid = node_pks.iter().skip(u16::from_be_bytes(get_slice!(2).try_into().unwrap()) as usize % node_pks.len()).next().unwrap();
210+
let capacity = u64::from_be_bytes(get_slice!(8).try_into().unwrap());
209211
first_hops_vec.push(ChannelDetails {
210212
channel_id: [0; 32],
211213
counterparty: ChannelCounterparty {
@@ -220,15 +222,16 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
220222
channel_type: None,
221223
short_channel_id: Some(scid),
222224
inbound_scid_alias: None,
223-
channel_value_satoshis: slice_to_be64(get_slice!(8)),
225+
channel_value_satoshis: capacity,
224226
user_channel_id: 0, inbound_capacity_msat: 0,
225227
unspendable_punishment_reserve: None,
226228
confirmations_required: None,
227229
force_close_spend_delay: None,
228230
is_outbound: true, is_funding_locked: true,
229231
is_usable: true, is_public: true,
230232
balance_msat: 0,
231-
outbound_capacity_msat: 0,
233+
outbound_capacity_msat: capacity.saturating_mul(1000),
234+
next_outbound_htlc_limit_msat: capacity.saturating_mul(1000),
232235
inbound_htlc_minimum_msat: None,
233236
inbound_htlc_maximum_msat: None,
234237
});

lightning/src/ln/channel.rs

+33-23
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ pub struct ChannelValueStat {
6262
pub counterparty_dust_limit_msat: u64,
6363
}
6464

65+
pub struct AvailableBalances {
66+
/// The amount that would go to us if we close the channel, ignoring any on-chain fees.
67+
pub balance_msat: u64,
68+
/// Total amount available for our counterparty to send to us.
69+
pub inbound_capacity_msat: u64,
70+
/// Total amount available for us to send to our counterparty.
71+
pub outbound_capacity_msat: u64,
72+
/// The maximum value we can assign to the next outbound HTLC
73+
pub next_outbound_htlc_limit_msat: u64,
74+
}
75+
6576
#[derive(Debug, Clone, Copy, PartialEq)]
6677
enum FeeUpdateState {
6778
// Inbound states mirroring InboundHTLCState
@@ -2330,40 +2341,39 @@ impl<Signer: Sign> Channel<Signer> {
23302341
stats
23312342
}
23322343

2333-
/// Get the available (ie not including pending HTLCs) inbound and outbound balance in msat.
2344+
/// Get the available balances, see [`AvailableBalances`]'s fields for more info.
23342345
/// Doesn't bother handling the
23352346
/// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
23362347
/// corner case properly.
2337-
/// The channel reserve is subtracted from each balance.
2338-
/// See also [`Channel::get_balance_msat`]
2339-
pub fn get_inbound_outbound_available_balance_msat(&self) -> (u64, u64) {
2348+
pub fn get_available_balances(&self) -> AvailableBalances {
23402349
// Note that we have to handle overflow due to the above case.
2341-
(
2342-
cmp::max(self.channel_value_satoshis as i64 * 1000
2343-
- self.value_to_self_msat as i64
2344-
- self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
2345-
- self.holder_selected_channel_reserve_satoshis as i64 * 1000,
2346-
0) as u64,
2347-
cmp::max(self.value_to_self_msat as i64
2348-
- self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
2349-
- self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) as i64 * 1000,
2350-
0) as u64
2351-
)
2352-
}
2350+
let outbound_stats = self.get_outbound_pending_htlc_stats(None);
23532351

2354-
/// Get our total balance in msat.
2355-
/// This is the amount that would go to us if we close the channel, ignoring any on-chain fees.
2356-
/// See also [`Channel::get_inbound_outbound_available_balance_msat`]
2357-
pub fn get_balance_msat(&self) -> u64 {
2358-
// Include our local balance, plus any inbound HTLCs we know the preimage for, minus any
2359-
// HTLCs sent or which will be sent after commitment signed's are exchanged.
23602352
let mut balance_msat = self.value_to_self_msat;
23612353
for ref htlc in self.pending_inbound_htlcs.iter() {
23622354
if let InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::Fulfill(_)) = htlc.state {
23632355
balance_msat += htlc.amount_msat;
23642356
}
23652357
}
2366-
balance_msat - self.get_outbound_pending_htlc_stats(None).pending_htlcs_value_msat
2358+
balance_msat -= outbound_stats.pending_htlcs_value_msat;
2359+
2360+
let outbound_capacity_msat = cmp::max(self.value_to_self_msat as i64
2361+
- outbound_stats.pending_htlcs_value_msat as i64
2362+
- self.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) as i64 * 1000,
2363+
0) as u64;
2364+
AvailableBalances {
2365+
inbound_capacity_msat: cmp::max(self.channel_value_satoshis as i64 * 1000
2366+
- self.value_to_self_msat as i64
2367+
- self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
2368+
- self.holder_selected_channel_reserve_satoshis as i64 * 1000,
2369+
0) as u64,
2370+
outbound_capacity_msat,
2371+
next_outbound_htlc_limit_msat: cmp::max(cmp::min(outbound_capacity_msat as i64,
2372+
self.counterparty_max_htlc_value_in_flight_msat as i64
2373+
- outbound_stats.pending_htlcs_value_msat as i64),
2374+
0) as u64,
2375+
balance_msat,
2376+
}
23672377
}
23682378

23692379
pub fn get_holder_counterparty_selected_channel_reserve_satoshis(&self) -> (u64, Option<u64>) {

lightning/src/ln/channelmanager.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,13 @@ pub struct ChannelDetails {
10051005
/// conflict-avoidance policy, exactly this amount is not likely to be spendable. However, we
10061006
/// should be able to spend nearly this amount.
10071007
pub outbound_capacity_msat: u64,
1008+
/// The available outbound capacity for sending a single HTLC to the remote peer. This is
1009+
/// similar to [`ChannelDetails::outbound_capacity_msat`] but it may be further restricted by
1010+
/// the current state and per-HTLC limit(s). This is intended for use when routing, allowing us
1011+
/// to use a limit as close as possible to the HTLC limit we can currently send.
1012+
///
1013+
/// See also [`ChannelDetails::balance_msat`] and [`ChannelDetails::outbound_capacity_msat`].
1014+
pub next_outbound_htlc_limit_msat: u64,
10081015
/// The available inbound capacity for the remote peer to send HTLCs to us. This does not
10091016
/// include any pending HTLCs which are not yet fully resolved (and, thus, whose balance is not
10101017
/// available for inclusion in new inbound HTLCs).
@@ -1670,8 +1677,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16701677
let channel_state = self.channel_state.lock().unwrap();
16711678
res.reserve(channel_state.by_id.len());
16721679
for (channel_id, channel) in channel_state.by_id.iter().filter(f) {
1673-
let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
1674-
let balance_msat = channel.get_balance_msat();
1680+
let balance = channel.get_available_balances();
16751681
let (to_remote_reserve_satoshis, to_self_reserve_satoshis) =
16761682
channel.get_holder_counterparty_selected_channel_reserve_satoshis();
16771683
res.push(ChannelDetails {
@@ -1698,9 +1704,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16981704
inbound_scid_alias: channel.latest_inbound_scid_alias(),
16991705
channel_value_satoshis: channel.get_value_satoshis(),
17001706
unspendable_punishment_reserve: to_self_reserve_satoshis,
1701-
balance_msat,
1702-
inbound_capacity_msat,
1703-
outbound_capacity_msat,
1707+
balance_msat: balance.balance_msat,
1708+
inbound_capacity_msat: balance.inbound_capacity_msat,
1709+
outbound_capacity_msat: balance.outbound_capacity_msat,
1710+
next_outbound_htlc_limit_msat: balance.next_outbound_htlc_limit_msat,
17041711
user_channel_id: channel.get_user_id(),
17051712
confirmations_required: channel.minimum_depth(),
17061713
force_close_spend_delay: channel.get_counterparty_selected_contest_delay(),
@@ -5936,6 +5943,9 @@ impl_writeable_tlv_based!(ChannelDetails, {
59365943
(14, user_channel_id, required),
59375944
(16, balance_msat, required),
59385945
(18, outbound_capacity_msat, required),
5946+
// Note that by the time we get past the required read above, outbound_capacity_msat will be
5947+
// filled in, so we can safely unwrap it here.
5948+
(19, next_outbound_htlc_limit_msat, (default_value, outbound_capacity_msat.0.unwrap())),
59395949
(20, inbound_capacity_msat, required),
59405950
(22, confirmations_required, option),
59415951
(24, force_close_spend_delay, option),

lightning/src/routing/router.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl<'a> CandidateRouteHop<'a> {
412412
fn effective_capacity(&self) -> EffectiveCapacity {
413413
match self {
414414
CandidateRouteHop::FirstHop { details } => EffectiveCapacity::ExactLiquidity {
415-
liquidity_msat: details.outbound_capacity_msat,
415+
liquidity_msat: details.next_outbound_htlc_limit_msat,
416416
},
417417
CandidateRouteHop::PublicHop { info, .. } => info.effective_capacity(),
418418
CandidateRouteHop::PrivateHop { .. } => EffectiveCapacity::Infinite,
@@ -818,7 +818,8 @@ where L::Target: Logger {
818818
// We don't want multiple paths (as per MPP) share liquidity of the same channels.
819819
// This map allows paths to be aware of the channel use by other paths in the same call.
820820
// This would help to make a better path finding decisions and not "overbook" channels.
821-
// It is unaware of the directions (except for `outbound_capacity_msat` in `first_hops`).
821+
// It is unaware of the directions (except for `next_outbound_htlc_limit_msat` in
822+
// `first_hops`).
822823
let mut bookkept_channels_liquidity_available_msat = HashMap::with_capacity(network_nodes.len());
823824

824825
// Keeping track of how much value we already collected across other paths. Helps to decide:
@@ -841,12 +842,12 @@ where L::Target: Logger {
841842
// sort channels above `recommended_value_msat` in ascending order, preferring channels
842843
// which have enough, but not too much, capacity for the payment.
843844
channels.sort_unstable_by(|chan_a, chan_b| {
844-
if chan_b.outbound_capacity_msat < recommended_value_msat || chan_a.outbound_capacity_msat < recommended_value_msat {
845+
if chan_b.next_outbound_htlc_limit_msat < recommended_value_msat || chan_a.next_outbound_htlc_limit_msat < recommended_value_msat {
845846
// Sort in descending order
846-
chan_b.outbound_capacity_msat.cmp(&chan_a.outbound_capacity_msat)
847+
chan_b.next_outbound_htlc_limit_msat.cmp(&chan_a.next_outbound_htlc_limit_msat)
847848
} else {
848849
// Sort in ascending order
849-
chan_a.outbound_capacity_msat.cmp(&chan_b.outbound_capacity_msat)
850+
chan_a.next_outbound_htlc_limit_msat.cmp(&chan_b.next_outbound_htlc_limit_msat)
850851
}
851852
});
852853
}
@@ -1746,6 +1747,7 @@ mod tests {
17461747
user_channel_id: 0,
17471748
balance_msat: 0,
17481749
outbound_capacity_msat,
1750+
next_outbound_htlc_limit_msat: outbound_capacity_msat,
17491751
inbound_capacity_msat: 42,
17501752
unspendable_punishment_reserve: None,
17511753
confirmations_required: None,
@@ -3407,7 +3409,7 @@ mod tests {
34073409
assert_eq!(path.last().unwrap().fee_msat, 250_000_000);
34083410
}
34093411

3410-
// Check that setting outbound_capacity_msat in first_hops limits the channels.
3412+
// Check that setting next_outbound_htlc_limit_msat in first_hops limits the channels.
34113413
// Disable channel #1 and use another first hop.
34123414
update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
34133415
chain_hash: genesis_block(Network::Testnet).header.block_hash(),
@@ -3422,7 +3424,7 @@ mod tests {
34223424
excess_data: Vec::new()
34233425
});
34243426

3425-
// Now, limit the first_hop by the outbound_capacity_msat of 200_000 sats.
3427+
// Now, limit the first_hop by the next_outbound_htlc_limit_msat of 200_000 sats.
34263428
let our_chans = vec![get_channel_details(Some(42), nodes[0].clone(), InitFeatures::from_le_bytes(vec![0b11]), 200_000_000)];
34273429

34283430
{
@@ -5476,6 +5478,7 @@ mod benches {
54765478
user_channel_id: 0,
54775479
balance_msat: 10_000_000,
54785480
outbound_capacity_msat: 10_000_000,
5481+
next_outbound_htlc_limit_msat: 10_000_000,
54795482
inbound_capacity_msat: 0,
54805483
unspendable_punishment_reserve: None,
54815484
confirmations_required: None,

lightning/src/util/events.rs

+41-41
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,47 @@ pub enum Event {
230230
/// [`Route::get_total_fees`]: crate::routing::router::Route::get_total_fees
231231
fee_paid_msat: Option<u64>,
232232
},
233+
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
234+
/// provide failure information for each MPP part in the payment.
235+
///
236+
/// This event is provided once there are no further pending HTLCs for the payment and the
237+
/// payment is no longer retryable, either due to a several-block timeout or because
238+
/// [`ChannelManager::abandon_payment`] was previously called for the corresponding payment.
239+
///
240+
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
241+
PaymentFailed {
242+
/// The id returned by [`ChannelManager::send_payment`] and used with
243+
/// [`ChannelManager::retry_payment`] and [`ChannelManager::abandon_payment`].
244+
///
245+
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
246+
/// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
247+
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
248+
payment_id: PaymentId,
249+
/// The hash that was given to [`ChannelManager::send_payment`].
250+
///
251+
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
252+
payment_hash: PaymentHash,
253+
},
254+
/// Indicates that a path for an outbound payment was successful.
255+
///
256+
/// Always generated after [`Event::PaymentSent`] and thus useful for scoring channels. See
257+
/// [`Event::PaymentSent`] for obtaining the payment preimage.
258+
PaymentPathSuccessful {
259+
/// The id returned by [`ChannelManager::send_payment`] and used with
260+
/// [`ChannelManager::retry_payment`].
261+
///
262+
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
263+
/// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
264+
payment_id: PaymentId,
265+
/// The hash that was given to [`ChannelManager::send_payment`].
266+
///
267+
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
268+
payment_hash: Option<PaymentHash>,
269+
/// The payment path that was successful.
270+
///
271+
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
272+
path: Vec<RouteHop>,
273+
},
233274
/// Indicates an outbound HTLC we sent failed. Probably some intermediary node dropped
234275
/// something. You may wish to retry with a different route.
235276
///
@@ -299,27 +340,6 @@ pub enum Event {
299340
#[cfg(test)]
300341
error_data: Option<Vec<u8>>,
301342
},
302-
/// Indicates an outbound payment failed. Individual [`Event::PaymentPathFailed`] events
303-
/// provide failure information for each MPP part in the payment.
304-
///
305-
/// This event is provided once there are no further pending HTLCs for the payment and the
306-
/// payment is no longer retryable, either due to a several-block timeout or because
307-
/// [`ChannelManager::abandon_payment`] was previously called for the corresponding payment.
308-
///
309-
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
310-
PaymentFailed {
311-
/// The id returned by [`ChannelManager::send_payment`] and used with
312-
/// [`ChannelManager::retry_payment`] and [`ChannelManager::abandon_payment`].
313-
///
314-
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
315-
/// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
316-
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
317-
payment_id: PaymentId,
318-
/// The hash that was given to [`ChannelManager::send_payment`].
319-
///
320-
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
321-
payment_hash: PaymentHash,
322-
},
323343
/// Used to indicate that [`ChannelManager::process_pending_htlc_forwards`] should be called at
324344
/// a time in the future.
325345
///
@@ -390,26 +410,6 @@ pub enum Event {
390410
/// The full transaction received from the user
391411
transaction: Transaction
392412
},
393-
/// Indicates that a path for an outbound payment was successful.
394-
///
395-
/// Always generated after [`Event::PaymentSent`] and thus useful for scoring channels. See
396-
/// [`Event::PaymentSent`] for obtaining the payment preimage.
397-
PaymentPathSuccessful {
398-
/// The id returned by [`ChannelManager::send_payment`] and used with
399-
/// [`ChannelManager::retry_payment`].
400-
///
401-
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
402-
/// [`ChannelManager::retry_payment`]: crate::ln::channelmanager::ChannelManager::retry_payment
403-
payment_id: PaymentId,
404-
/// The hash that was given to [`ChannelManager::send_payment`].
405-
///
406-
/// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
407-
payment_hash: Option<PaymentHash>,
408-
/// The payment path that was successful.
409-
///
410-
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
411-
path: Vec<RouteHop>,
412-
},
413413
/// Indicates a request to open a new channel by a peer.
414414
///
415415
/// To accept the request, call [`ChannelManager::accept_inbound_channel`]. To reject the

0 commit comments

Comments
 (0)