Skip to content

Commit 637fb88

Browse files
authored
Merge pull request #1378 from ViktorTigerstrom/2022-03-include-htlc-min-max
Include htlc min/max for ChannelDetails and ChannelCounterparty
2 parents d0f69f7 + 3c67687 commit 637fb88

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

fuzz/src/router.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
213213
features: InitFeatures::known(),
214214
unspendable_punishment_reserve: 0,
215215
forwarding_info: None,
216+
outbound_htlc_minimum_msat: None,
217+
outbound_htlc_maximum_msat: None,
216218
},
217219
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
218220
channel_type: None,
@@ -227,6 +229,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
227229
is_usable: true, is_public: true,
228230
balance_msat: 0,
229231
outbound_capacity_msat: 0,
232+
inbound_htlc_minimum_msat: None,
233+
inbound_htlc_maximum_msat: None,
230234
});
231235
}
232236
Some(&first_hops_vec[..])

lightning-invoice/src/utils.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,8 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
412412
proportional_millionths: forwarding_info.fee_proportional_millionths,
413413
},
414414
cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
415-
htlc_minimum_msat: None,
416-
htlc_maximum_msat: None,}])
415+
htlc_minimum_msat: channel.inbound_htlc_minimum_msat,
416+
htlc_maximum_msat: channel.inbound_htlc_maximum_msat,}])
417417
};
418418
// If all channels are private, return the route hint for the highest inbound capacity channel
419419
// per counterparty node. If channels with an higher inbound capacity than the
@@ -535,10 +535,13 @@ mod test {
535535

536536
// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
537537
// available.
538+
let chan = &nodes[1].node.list_usable_channels()[0];
538539
assert_eq!(invoice.route_hints().len(), 1);
539540
assert_eq!(invoice.route_hints()[0].0.len(), 1);
540-
assert_eq!(invoice.route_hints()[0].0[0].short_channel_id,
541-
nodes[1].node.list_usable_channels()[0].inbound_scid_alias.unwrap());
541+
assert_eq!(invoice.route_hints()[0].0[0].short_channel_id, chan.inbound_scid_alias.unwrap());
542+
543+
assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat);
544+
assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat);
542545

543546
let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
544547
.with_features(invoice.features().unwrap().clone())
@@ -879,6 +882,40 @@ mod test {
879882
}
880883
}
881884

885+
#[test]
886+
#[cfg(feature = "std")]
887+
fn test_multi_node_hints_has_htlc_min_max_values() {
888+
let mut chanmon_cfgs = create_chanmon_cfgs(3);
889+
let seed_1 = [42 as u8; 32];
890+
let seed_2 = [43 as u8; 32];
891+
let cross_node_seed = [44 as u8; 32];
892+
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
893+
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
894+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
895+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
896+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
897+
898+
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
899+
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
900+
901+
let payment_amt = 20_000;
902+
let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
903+
let route_hints = vec![
904+
nodes[1].node.get_phantom_route_hints(),
905+
nodes[2].node.get_phantom_route_hints(),
906+
];
907+
908+
let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), Some(payment_hash), "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
909+
910+
let chan_0_1 = &nodes[1].node.list_usable_channels()[0];
911+
assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat);
912+
assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan_0_1.inbound_htlc_maximum_msat);
913+
914+
let chan_0_2 = &nodes[2].node.list_usable_channels()[0];
915+
assert_eq!(invoice.route_hints()[1].0[0].htlc_minimum_msat, chan_0_2.inbound_htlc_minimum_msat);
916+
assert_eq!(invoice.route_hints()[1].0[0].htlc_maximum_msat, chan_0_2.inbound_htlc_maximum_msat);
917+
}
918+
882919
#[test]
883920
#[cfg(feature = "std")]
884921
fn create_phantom_invoice_with_description_hash() {

lightning/src/ln/channel.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4321,11 +4321,15 @@ impl<Signer: Sign> Channel<Signer> {
43214321
}
43224322

43234323
/// Allowed in any state (including after shutdown)
4324-
#[cfg(test)]
43254324
pub fn get_holder_htlc_minimum_msat(&self) -> u64 {
43264325
self.holder_htlc_minimum_msat
43274326
}
43284327

4328+
/// Allowed in any state (including after shutdown), but will return none before TheirInitSent
4329+
pub fn get_holder_htlc_maximum_msat(&self) -> Option<u64> {
4330+
self.get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat)
4331+
}
4332+
43294333
/// Allowed in any state (including after shutdown)
43304334
pub fn get_announced_htlc_max_msat(&self) -> u64 {
43314335
return cmp::min(
@@ -4343,6 +4347,21 @@ impl<Signer: Sign> Channel<Signer> {
43434347
self.counterparty_htlc_minimum_msat
43444348
}
43454349

4350+
/// Allowed in any state (including after shutdown), but will return none before TheirInitSent
4351+
pub fn get_counterparty_htlc_maximum_msat(&self) -> Option<u64> {
4352+
self.get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat)
4353+
}
4354+
4355+
fn get_htlc_maximum_msat(&self, party_max_htlc_value_in_flight_msat: u64) -> Option<u64> {
4356+
self.counterparty_selected_channel_reserve_satoshis.map(|counterparty_reserve| {
4357+
let holder_reserve = self.holder_selected_channel_reserve_satoshis;
4358+
cmp::min(
4359+
(self.channel_value_satoshis - counterparty_reserve - holder_reserve) * 1000,
4360+
party_max_htlc_value_in_flight_msat
4361+
)
4362+
})
4363+
}
4364+
43464365
pub fn get_value_satoshis(&self) -> u64 {
43474366
self.channel_value_satoshis
43484367
}

lightning/src/ln/channelmanager.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,12 @@ pub struct ChannelCounterparty {
922922
/// Information on the fees and requirements that the counterparty requires when forwarding
923923
/// payments to us through this channel.
924924
pub forwarding_info: Option<CounterpartyForwardingInfo>,
925+
/// The smallest value HTLC (in msat) the remote peer will accept, for this channel. This field
926+
/// is only `None` before we have received either the `OpenChannel` or `AcceptChannel` message
927+
/// from the remote peer, or for `ChannelCounterparty` objects serialized prior to LDK 0.0.107.
928+
pub outbound_htlc_minimum_msat: Option<u64>,
929+
/// The largest value HTLC (in msat) the remote peer currently will accept, for this channel.
930+
pub outbound_htlc_maximum_msat: Option<u64>,
925931
}
926932

927933
/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
@@ -1046,6 +1052,11 @@ pub struct ChannelDetails {
10461052
pub is_usable: bool,
10471053
/// True if this channel is (or will be) publicly-announced.
10481054
pub is_public: bool,
1055+
/// The smallest value HTLC (in msat) we will accept, for this channel. This field
1056+
/// is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.107
1057+
pub inbound_htlc_minimum_msat: Option<u64>,
1058+
/// The largest value HTLC (in msat) we currently will accept, for this channel.
1059+
pub inbound_htlc_maximum_msat: Option<u64>,
10491060
}
10501061

10511062
impl ChannelDetails {
@@ -1670,6 +1681,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16701681
features: InitFeatures::empty(),
16711682
unspendable_punishment_reserve: to_remote_reserve_satoshis,
16721683
forwarding_info: channel.counterparty_forwarding_info(),
1684+
// Ensures that we have actually received the `htlc_minimum_msat` value
1685+
// from the counterparty through the `OpenChannel` or `AcceptChannel`
1686+
// message (as they are always the first message from the counterparty).
1687+
// Else `Channel::get_counterparty_htlc_minimum_msat` could return the
1688+
// default `0` value set by `Channel::new_outbound`.
1689+
outbound_htlc_minimum_msat: if channel.have_received_message() {
1690+
Some(channel.get_counterparty_htlc_minimum_msat()) } else { None },
1691+
outbound_htlc_maximum_msat: channel.get_counterparty_htlc_maximum_msat(),
16731692
},
16741693
funding_txo: channel.get_funding_txo(),
16751694
// Note that accept_channel (or open_channel) is always the first message, so
@@ -1689,6 +1708,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16891708
is_funding_locked: channel.is_usable(),
16901709
is_usable: channel.is_live(),
16911710
is_public: channel.should_announce(),
1711+
inbound_htlc_minimum_msat: Some(channel.get_holder_htlc_minimum_msat()),
1712+
inbound_htlc_maximum_msat: channel.get_holder_htlc_maximum_msat()
16921713
});
16931714
}
16941715
}
@@ -5900,6 +5921,8 @@ impl_writeable_tlv_based!(ChannelCounterparty, {
59005921
(4, features, required),
59015922
(6, unspendable_punishment_reserve, required),
59025923
(8, forwarding_info, option),
5924+
(9, outbound_htlc_minimum_msat, option),
5925+
(11, outbound_htlc_maximum_msat, option),
59035926
});
59045927

59055928
impl_writeable_tlv_based!(ChannelDetails, {
@@ -5921,6 +5944,8 @@ impl_writeable_tlv_based!(ChannelDetails, {
59215944
(28, is_funding_locked, required),
59225945
(30, is_usable, required),
59235946
(32, is_public, required),
5947+
(33, inbound_htlc_minimum_msat, option),
5948+
(35, inbound_htlc_maximum_msat, option),
59245949
});
59255950

59265951
impl_writeable_tlv_based!(PhantomRouteHints, {

lightning/src/routing/router.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,8 @@ mod tests {
17351735
node_id,
17361736
unspendable_punishment_reserve: 0,
17371737
forwarding_info: None,
1738+
outbound_htlc_minimum_msat: None,
1739+
outbound_htlc_maximum_msat: None,
17381740
},
17391741
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
17401742
channel_type: None,
@@ -1750,6 +1752,8 @@ mod tests {
17501752
force_close_spend_delay: None,
17511753
is_outbound: true, is_funding_locked: true,
17521754
is_usable: true, is_public: true,
1755+
inbound_htlc_minimum_msat: None,
1756+
inbound_htlc_maximum_msat: None,
17531757
}
17541758
}
17551759

@@ -5456,6 +5460,8 @@ mod benches {
54565460
node_id,
54575461
unspendable_punishment_reserve: 0,
54585462
forwarding_info: None,
5463+
outbound_htlc_minimum_msat: None,
5464+
outbound_htlc_maximum_msat: None,
54595465
},
54605466
funding_txo: Some(OutPoint {
54615467
txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
@@ -5475,6 +5481,8 @@ mod benches {
54755481
is_funding_locked: true,
54765482
is_usable: true,
54775483
is_public: true,
5484+
inbound_htlc_minimum_msat: None,
5485+
inbound_htlc_maximum_msat: None,
54785486
}
54795487
}
54805488

0 commit comments

Comments
 (0)