Skip to content

Commit 6b8ad4e

Browse files
authored
Merge pull request #1398 from jkczyz/2022-03-middle-hop-fix
Router fixes
2 parents aeeafed + 8ddfe66 commit 6b8ad4e

File tree

3 files changed

+44
-25
lines changed

3 files changed

+44
-25
lines changed

lightning/src/ln/channel.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6289,44 +6289,39 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<Signer>
62896289

62906290
#[cfg(test)]
62916291
mod tests {
6292-
use bitcoin::util::bip143;
6293-
use bitcoin::consensus::encode::serialize;
62946292
use bitcoin::blockdata::script::{Script, Builder};
6295-
use bitcoin::blockdata::transaction::{Transaction, TxOut, SigHashType};
6293+
use bitcoin::blockdata::transaction::{Transaction, TxOut};
62966294
use bitcoin::blockdata::constants::genesis_block;
62976295
use bitcoin::blockdata::opcodes;
62986296
use bitcoin::network::constants::Network;
6299-
use bitcoin::hashes::hex::FromHex;
63006297
use hex;
6301-
use ln::{PaymentPreimage, PaymentHash};
6298+
use ln::PaymentHash;
63026299
use ln::channelmanager::{HTLCSource, PaymentId};
6303-
use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys};
6300+
use ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
63046301
use ln::channel::MAX_FUNDING_SATOSHIS;
63056302
use ln::features::InitFeatures;
63066303
use ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate};
63076304
use ln::script::ShutdownScript;
63086305
use ln::chan_utils;
6309-
use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight};
6306+
use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
63106307
use chain::BestBlock;
63116308
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
6312-
use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign};
6309+
use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface};
63136310
use chain::transaction::OutPoint;
63146311
use util::config::UserConfig;
63156312
use util::enforcing_trait_impls::EnforcingSigner;
63166313
use util::errors::APIError;
63176314
use util::test_utils;
63186315
use util::test_utils::OnGetShutdownScriptpubkey;
6319-
use util::logger::Logger;
6320-
use bitcoin::secp256k1::{Secp256k1, Message, Signature, All};
6316+
use bitcoin::secp256k1::{Secp256k1, Signature};
63216317
use bitcoin::secp256k1::ffi::Signature as FFISignature;
63226318
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
63236319
use bitcoin::secp256k1::recovery::RecoverableSignature;
63246320
use bitcoin::hashes::sha256::Hash as Sha256;
63256321
use bitcoin::hashes::Hash;
6326-
use bitcoin::hash_types::{Txid, WPubkeyHash};
6322+
use bitcoin::hash_types::WPubkeyHash;
63276323
use core::num::NonZeroU8;
63286324
use bitcoin::bech32::u5;
6329-
use sync::Arc;
63306325
use prelude::*;
63316326

63326327
struct TestFeeEstimator {
@@ -6380,7 +6375,8 @@ mod tests {
63806375
fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
63816376
}
63826377

6383-
fn public_from_secret_hex(secp_ctx: &Secp256k1<All>, hex: &str) -> PublicKey {
6378+
#[cfg(not(feature = "grind_signatures"))]
6379+
fn public_from_secret_hex(secp_ctx: &Secp256k1<bitcoin::secp256k1::All>, hex: &str) -> PublicKey {
63846380
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap())
63856381
}
63866382

@@ -6669,6 +6665,19 @@ mod tests {
66696665
#[cfg(not(feature = "grind_signatures"))]
66706666
#[test]
66716667
fn outbound_commitment_test() {
6668+
use bitcoin::util::bip143;
6669+
use bitcoin::consensus::encode::serialize;
6670+
use bitcoin::blockdata::transaction::SigHashType;
6671+
use bitcoin::hashes::hex::FromHex;
6672+
use bitcoin::hash_types::Txid;
6673+
use bitcoin::secp256k1::Message;
6674+
use chain::keysinterface::BaseSign;
6675+
use ln::PaymentPreimage;
6676+
use ln::channel::{HTLCOutputInCommitment ,TxCreationKeys};
6677+
use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
6678+
use util::logger::Logger;
6679+
use sync::Arc;
6680+
66726681
// Test vectors from BOLT 3 Appendices C and F (anchors):
66736682
let feeest = TestFeeEstimator{fee_est: 15000};
66746683
let logger : Arc<Logger> = Arc::new(test_utils::TestLogger::new());

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ impl core::hash::Hash for HTLCSource {
498498
}
499499
}
500500
}
501+
#[cfg(not(feature = "grind_signatures"))]
501502
#[cfg(test)]
502503
impl HTLCSource {
503504
pub fn dummy() -> Self {

lightning/src/routing/router.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ impl<'a> PaymentPath<'a> {
511511
return result;
512512
}
513513

514+
fn get_cost_msat(&self) -> u64 {
515+
self.get_total_fee_paid_msat().saturating_add(self.get_path_penalty_msat())
516+
}
517+
514518
// If the amount transferred by the path is updated, the fees should be adjusted. Any other way
515519
// to change fees may result in an inconsistency.
516520
//
@@ -912,14 +916,20 @@ where L::Target: Logger {
912916
let over_path_minimum_msat = amount_to_transfer_over_msat >= $candidate.htlc_minimum_msat() &&
913917
amount_to_transfer_over_msat >= $next_hops_path_htlc_minimum_msat;
914918

919+
#[allow(unused_comparisons)] // $next_hops_path_htlc_minimum_msat is 0 in some calls so rustc complains
920+
let may_overpay_to_meet_path_minimum_msat =
921+
((amount_to_transfer_over_msat < $candidate.htlc_minimum_msat() &&
922+
recommended_value_msat > $candidate.htlc_minimum_msat()) ||
923+
(amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
924+
recommended_value_msat > $next_hops_path_htlc_minimum_msat));
925+
915926
// If HTLC minimum is larger than the amount we're going to transfer, we shouldn't
916-
// bother considering this channel.
917-
// Since we're choosing amount_to_transfer_over_msat as maximum possible, it can
918-
// be only reduced later (not increased), so this channel should just be skipped
919-
// as not sufficient.
920-
if !over_path_minimum_msat && doesnt_exceed_cltv_delta_limit {
927+
// bother considering this channel. If retrying with recommended_value_msat may
928+
// allow us to hit the HTLC minimum limit, set htlc_minimum_limit so that we go
929+
// around again with a higher amount.
930+
if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit && may_overpay_to_meet_path_minimum_msat {
921931
hit_minimum_limit = true;
922-
} else if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit {
932+
} else if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit && over_path_minimum_msat {
923933
// Note that low contribution here (limited by available_liquidity_msat)
924934
// might violate htlc_minimum_msat on the hops which are next along the
925935
// payment path (upstream to the payee). To avoid that, we recompute
@@ -1390,7 +1400,7 @@ where L::Target: Logger {
13901400
// If we weren't capped by hitting a liquidity limit on a channel in the path,
13911401
// we'll probably end up picking the same path again on the next iteration.
13921402
// Decrease the available liquidity of a hop in the middle of the path.
1393-
let victim_scid = payment_path.hops[(payment_path.hops.len() - 1) / 2].0.candidate.short_channel_id();
1403+
let victim_scid = payment_path.hops[(payment_path.hops.len()) / 2].0.candidate.short_channel_id();
13941404
log_trace!(logger, "Disabling channel {} for future path building iterations to avoid duplicates.", victim_scid);
13951405
let victim_liquidity = bookkept_channels_liquidity_available_msat.get_mut(&victim_scid).unwrap();
13961406
*victim_liquidity = 0;
@@ -1502,9 +1512,8 @@ where L::Target: Logger {
15021512
// prefer lower cost paths.
15031513
cur_route.sort_unstable_by(|a, b| {
15041514
a.get_value_msat().cmp(&b.get_value_msat())
1505-
// Reverse ordering for fees, so we drop higher-fee paths first
1506-
.then_with(|| b.get_total_fee_paid_msat().saturating_add(b.get_path_penalty_msat())
1507-
.cmp(&a.get_total_fee_paid_msat().saturating_add(a.get_path_penalty_msat())))
1515+
// Reverse ordering for cost, so we drop higher-cost paths first
1516+
.then_with(|| b.get_cost_msat().cmp(&a.get_cost_msat()))
15081517
});
15091518

15101519
// We should make sure that at least 1 path left.
@@ -1548,8 +1557,8 @@ where L::Target: Logger {
15481557
}
15491558

15501559
// Step (9).
1551-
// Select the best route by lowest total fee.
1552-
drawn_routes.sort_unstable_by_key(|paths| paths.iter().map(|path| path.get_total_fee_paid_msat()).sum::<u64>());
1560+
// Select the best route by lowest total cost.
1561+
drawn_routes.sort_unstable_by_key(|paths| paths.iter().map(|path| path.get_cost_msat()).sum::<u64>());
15531562
let mut selected_paths = Vec::<Vec<Result<RouteHop, LightningError>>>::new();
15541563
for payment_path in drawn_routes.first().unwrap() {
15551564
let mut path = payment_path.hops.iter().map(|(payment_hop, node_features)| {

0 commit comments

Comments
 (0)