Skip to content

Commit

Permalink
Merge pull request #1378 from ViktorTigerstrom/2022-03-include-htlc-m…
Browse files Browse the repository at this point in the history
…in-max

Include htlc min/max for ChannelDetails and ChannelCounterparty
  • Loading branch information
TheBlueMatt authored Apr 21, 2022
2 parents d0f69f7 + 3c67687 commit 637fb88
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 5 deletions.
4 changes: 4 additions & 0 deletions fuzz/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
features: InitFeatures::known(),
unspendable_punishment_reserve: 0,
forwarding_info: None,
outbound_htlc_minimum_msat: None,
outbound_htlc_maximum_msat: None,
},
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
channel_type: None,
Expand All @@ -227,6 +229,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
is_usable: true, is_public: true,
balance_msat: 0,
outbound_capacity_msat: 0,
inbound_htlc_minimum_msat: None,
inbound_htlc_maximum_msat: None,
});
}
Some(&first_hops_vec[..])
Expand Down
45 changes: 41 additions & 4 deletions lightning-invoice/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,8 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
proportional_millionths: forwarding_info.fee_proportional_millionths,
},
cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
htlc_minimum_msat: None,
htlc_maximum_msat: None,}])
htlc_minimum_msat: channel.inbound_htlc_minimum_msat,
htlc_maximum_msat: channel.inbound_htlc_maximum_msat,}])
};
// If all channels are private, return the route hint for the highest inbound capacity channel
// per counterparty node. If channels with an higher inbound capacity than the
Expand Down Expand Up @@ -535,10 +535,13 @@ mod test {

// Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
// available.
let chan = &nodes[1].node.list_usable_channels()[0];
assert_eq!(invoice.route_hints().len(), 1);
assert_eq!(invoice.route_hints()[0].0.len(), 1);
assert_eq!(invoice.route_hints()[0].0[0].short_channel_id,
nodes[1].node.list_usable_channels()[0].inbound_scid_alias.unwrap());
assert_eq!(invoice.route_hints()[0].0[0].short_channel_id, chan.inbound_scid_alias.unwrap());

assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat);
assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat);

let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
.with_features(invoice.features().unwrap().clone())
Expand Down Expand Up @@ -879,6 +882,40 @@ mod test {
}
}

#[test]
#[cfg(feature = "std")]
fn test_multi_node_hints_has_htlc_min_max_values() {
let mut chanmon_cfgs = create_chanmon_cfgs(3);
let seed_1 = [42 as u8; 32];
let seed_2 = [43 as u8; 32];
let cross_node_seed = [44 as u8; 32];
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);

create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());

let payment_amt = 20_000;
let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
let route_hints = vec![
nodes[1].node.get_phantom_route_hints(),
nodes[2].node.get_phantom_route_hints(),
];

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();

let chan_0_1 = &nodes[1].node.list_usable_channels()[0];
assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat);
assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan_0_1.inbound_htlc_maximum_msat);

let chan_0_2 = &nodes[2].node.list_usable_channels()[0];
assert_eq!(invoice.route_hints()[1].0[0].htlc_minimum_msat, chan_0_2.inbound_htlc_minimum_msat);
assert_eq!(invoice.route_hints()[1].0[0].htlc_maximum_msat, chan_0_2.inbound_htlc_maximum_msat);
}

#[test]
#[cfg(feature = "std")]
fn create_phantom_invoice_with_description_hash() {
Expand Down
21 changes: 20 additions & 1 deletion lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4321,11 +4321,15 @@ impl<Signer: Sign> Channel<Signer> {
}

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

/// Allowed in any state (including after shutdown), but will return none before TheirInitSent
pub fn get_holder_htlc_maximum_msat(&self) -> Option<u64> {
self.get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat)
}

/// Allowed in any state (including after shutdown)
pub fn get_announced_htlc_max_msat(&self) -> u64 {
return cmp::min(
Expand All @@ -4343,6 +4347,21 @@ impl<Signer: Sign> Channel<Signer> {
self.counterparty_htlc_minimum_msat
}

/// Allowed in any state (including after shutdown), but will return none before TheirInitSent
pub fn get_counterparty_htlc_maximum_msat(&self) -> Option<u64> {
self.get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat)
}

fn get_htlc_maximum_msat(&self, party_max_htlc_value_in_flight_msat: u64) -> Option<u64> {
self.counterparty_selected_channel_reserve_satoshis.map(|counterparty_reserve| {
let holder_reserve = self.holder_selected_channel_reserve_satoshis;
cmp::min(
(self.channel_value_satoshis - counterparty_reserve - holder_reserve) * 1000,
party_max_htlc_value_in_flight_msat
)
})
}

pub fn get_value_satoshis(&self) -> u64 {
self.channel_value_satoshis
}
Expand Down
25 changes: 25 additions & 0 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,12 @@ pub struct ChannelCounterparty {
/// Information on the fees and requirements that the counterparty requires when forwarding
/// payments to us through this channel.
pub forwarding_info: Option<CounterpartyForwardingInfo>,
/// The smallest value HTLC (in msat) the remote peer will accept, for this channel. This field
/// is only `None` before we have received either the `OpenChannel` or `AcceptChannel` message
/// from the remote peer, or for `ChannelCounterparty` objects serialized prior to LDK 0.0.107.
pub outbound_htlc_minimum_msat: Option<u64>,
/// The largest value HTLC (in msat) the remote peer currently will accept, for this channel.
pub outbound_htlc_maximum_msat: Option<u64>,
}

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

impl ChannelDetails {
Expand Down Expand Up @@ -1670,6 +1681,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
features: InitFeatures::empty(),
unspendable_punishment_reserve: to_remote_reserve_satoshis,
forwarding_info: channel.counterparty_forwarding_info(),
// Ensures that we have actually received the `htlc_minimum_msat` value
// from the counterparty through the `OpenChannel` or `AcceptChannel`
// message (as they are always the first message from the counterparty).
// Else `Channel::get_counterparty_htlc_minimum_msat` could return the
// default `0` value set by `Channel::new_outbound`.
outbound_htlc_minimum_msat: if channel.have_received_message() {
Some(channel.get_counterparty_htlc_minimum_msat()) } else { None },
outbound_htlc_maximum_msat: channel.get_counterparty_htlc_maximum_msat(),
},
funding_txo: channel.get_funding_txo(),
// Note that accept_channel (or open_channel) is always the first message, so
Expand All @@ -1689,6 +1708,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
is_funding_locked: channel.is_usable(),
is_usable: channel.is_live(),
is_public: channel.should_announce(),
inbound_htlc_minimum_msat: Some(channel.get_holder_htlc_minimum_msat()),
inbound_htlc_maximum_msat: channel.get_holder_htlc_maximum_msat()
});
}
}
Expand Down Expand Up @@ -5900,6 +5921,8 @@ impl_writeable_tlv_based!(ChannelCounterparty, {
(4, features, required),
(6, unspendable_punishment_reserve, required),
(8, forwarding_info, option),
(9, outbound_htlc_minimum_msat, option),
(11, outbound_htlc_maximum_msat, option),
});

impl_writeable_tlv_based!(ChannelDetails, {
Expand All @@ -5921,6 +5944,8 @@ impl_writeable_tlv_based!(ChannelDetails, {
(28, is_funding_locked, required),
(30, is_usable, required),
(32, is_public, required),
(33, inbound_htlc_minimum_msat, option),
(35, inbound_htlc_maximum_msat, option),
});

impl_writeable_tlv_based!(PhantomRouteHints, {
Expand Down
8 changes: 8 additions & 0 deletions lightning/src/routing/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,8 @@ mod tests {
node_id,
unspendable_punishment_reserve: 0,
forwarding_info: None,
outbound_htlc_minimum_msat: None,
outbound_htlc_maximum_msat: None,
},
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
channel_type: None,
Expand All @@ -1750,6 +1752,8 @@ mod tests {
force_close_spend_delay: None,
is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
inbound_htlc_minimum_msat: None,
inbound_htlc_maximum_msat: None,
}
}

Expand Down Expand Up @@ -5456,6 +5460,8 @@ mod benches {
node_id,
unspendable_punishment_reserve: 0,
forwarding_info: None,
outbound_htlc_minimum_msat: None,
outbound_htlc_maximum_msat: None,
},
funding_txo: Some(OutPoint {
txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
Expand All @@ -5475,6 +5481,8 @@ mod benches {
is_funding_locked: true,
is_usable: true,
is_public: true,
inbound_htlc_minimum_msat: None,
inbound_htlc_maximum_msat: None,
}
}

Expand Down

0 comments on commit 637fb88

Please sign in to comment.