use crate::sign::EntropySource;
use crate::chain::transaction::OutPoint;
use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason, PaymentPurpose};
-use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
+use crate::ln::channel::{EXPIRE_PREV_CONFIG_TICKS, commit_tx_fee_msat, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI};
use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo};
-use crate::ln::features::Bolt11InvoiceFeatures;
-use crate::ln::{msgs, ChannelId, PaymentSecret, PaymentPreimage};
+use crate::ln::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures};
+use crate::ln::{msgs, ChannelId, PaymentHash, PaymentSecret, PaymentPreimage};
use crate::ln::msgs::ChannelMessageHandler;
+use crate::ln::onion_utils;
use crate::ln::outbound_payment::{IDEMPOTENCY_TIMEOUT_TICKS, Retry};
use crate::routing::gossip::{EffectiveCapacity, RoutingFees};
use crate::routing::router::{get_route, Path, PaymentParameters, Route, Router, RouteHint, RouteHintHop, RouteHop, RouteParameters, find_route};
use crate::util::ser::Writeable;
use crate::util::string::UntrustedString;
+use bitcoin::hashes::Hash;
+use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::network::constants::Network;
+use bitcoin::secp256k1::{Secp256k1, SecretKey};
use crate::prelude::*;
+use crate::ln::functional_test_utils;
use crate::ln::functional_test_utils::*;
use crate::routing::gossip::NodeId;
#[cfg(feature = "std")]
let amt_msat = 1_000_000;
let max_total_routing_fee_msat = 50_000;
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[3].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap();
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(
nodes[0], nodes[3], payment_params, amt_msat, Some(max_total_routing_fee_msat));
let path = route.paths[0].clone();
// Check the remaining max total routing fee for the second attempt is 50_000 - 1_000 msat fee
// used by the first path
route_params.max_total_routing_fee_msat = Some(max_total_routing_fee_msat - 1_000);
+ route.route_params = Some(route_params.clone());
nodes[0].router.expect_find_route(route_params, Ok(route));
nodes[0].node.process_pending_htlc_forwards();
check_added_monitors!(nodes[0], 1);
let max_total_routing_fee_msat = Some(1_000_000);
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[3].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap();
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(
nodes[0], nodes[3], payment_params, amt_msat, max_total_routing_fee_msat);
route.paths.remove(0);
route_params.final_value_msat -= first_path_value;
- route.route_params.as_mut().map(|p| p.final_value_msat -= first_path_value);
route_params.payment_params.previously_failed_channels.push(chan_4_update.contents.short_channel_id);
-
// Check the remaining max total routing fee for the second attempt accounts only for 1_000 msat
// base fee, but not for overpaid value of the first try.
route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 1000);
+
+ route.route_params = Some(route_params.clone());
nodes[0].router.expect_find_route(route_params, Ok(route));
nodes[0].node.process_pending_htlc_forwards();
let route_params = RouteParameters::from_payment_params_and_value(
PaymentParameters::for_keysend(payee_pubkey, 40, false), 10000);
- let network_graph = nodes[0].network_graph.clone();
+ let network_graph = nodes[0].network_graph;
let channels = nodes[0].node.list_usable_channels();
let first_hops = channels.iter().collect::<Vec<_>>();
let first_hops = if public_node { None } else { Some(first_hops.as_slice()) };
create_announced_chan_between_nodes(&nodes, 0, 2);
create_announced_chan_between_nodes(&nodes, 1, 3);
create_announced_chan_between_nodes(&nodes, 2, 3);
- let network_graph = nodes[0].network_graph.clone();
+ let network_graph = nodes[0].network_graph;
let payer_pubkey = nodes[0].node.get_our_node_id();
let payee_pubkey = nodes[3].node.get_our_node_id();
let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
let as_err = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(as_err.len(), 1);
- match as_err[0] {
+ assert_eq!(as_err.len(), 2);
+ match as_err[1] {
MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => {
assert_eq!(node_id, nodes[1].node.get_our_node_id());
nodes[1].node.handle_error(&nodes[0].node.get_our_node_id(), msg);
let bs_reestablish = get_chan_reestablish_msgs!(nodes[1], nodes[0]).pop().unwrap();
nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
let as_err = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(as_err.len(), 1);
+ assert_eq!(as_err.len(), 2);
let bs_commitment_tx;
- match as_err[0] {
+ match as_err[1] {
MessageSendEvent::HandleError { node_id, action: msgs::ErrorAction::SendErrorMessage { ref msg } } => {
assert_eq!(node_id, nodes[1].node.get_our_node_id());
nodes[1].node.handle_error(&nodes[0].node.get_our_node_id(), msg);
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs, None).unwrap();
let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap();
let scorer = test_utils::TestScorer::new();
let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
create_announced_chan_between_nodes(&nodes, 0, 1);
create_announced_chan_between_nodes(&nodes, 1, 2);
- let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], 100_000);
+ let recv_value = 100_000;
+ let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], recv_value);
- let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
+ let res = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
- // node[0] -- update_add_htlcs -> node[1]
- check_added_monitors!(nodes[0], 1);
- let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
- let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
- nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]);
- check_added_monitors!(nodes[1], 0);
- commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false);
- expect_pending_htlcs_forwardable!(nodes[1]);
+ let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2]]];
- // node[1] -- update_add_htlcs -> node[2]
- check_added_monitors!(nodes[1], 1);
- let updates = get_htlc_update_msgs!(nodes[1], nodes[2].node.get_our_node_id());
- let probe_event = SendEvent::from_commitment_update(nodes[1].node.get_our_node_id(), updates);
- nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &probe_event.msgs[0]);
- check_added_monitors!(nodes[2], 0);
- commitment_signed_dance!(nodes[2], nodes[1], probe_event.commitment_msg, true, true);
+ send_probe_along_route(&nodes[0], expected_route);
- // node[1] <- update_fail_htlcs -- node[2]
- let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
- nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
- check_added_monitors!(nodes[1], 0);
- commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, true);
+ expect_probe_successful_events(&nodes[0], vec![res]);
- // node[0] <- update_fail_htlcs -- node[1]
- let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
- nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
- check_added_monitors!(nodes[0], 0);
- commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
-
- let mut events = nodes[0].node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
- match events.drain(..).next().unwrap() {
- crate::events::Event::ProbeSuccessful { payment_id: ev_pid, payment_hash: ev_ph, .. } => {
- assert_eq!(payment_id, ev_pid);
- assert_eq!(payment_hash, ev_ph);
- },
- _ => panic!(),
- };
assert!(!nodes[0].node.has_pending_payments());
}
assert!(!nodes[0].node.has_pending_payments());
}
+#[test]
+fn preflight_probes_yield_event_skip_private_hop() {
+ let chanmon_cfgs = create_chanmon_cfgs(5);
+ let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
+
+ // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that.
+ let mut no_htlc_limit_config = test_default_channel_config();
+ no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100;
+
+ let user_configs = std::iter::repeat(no_htlc_limit_config).take(5).map(|c| Some(c)).collect::<Vec<Option<UserConfig>>>();
+ let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &user_configs);
+ let nodes = create_network(5, &node_cfgs, &node_chanmgrs);
+
+ // Setup channel topology:
+ // N0 -(1M:0)- N1 -(1M:0)- N2 -(70k:0)- N3 -(50k:0)- N4
+
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
+ create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 70_000, 0);
+ create_unannounced_chan_between_nodes_with_value(&nodes, 3, 4, 50_000, 0);
+
+ let mut invoice_features = Bolt11InvoiceFeatures::empty();
+ invoice_features.set_basic_mpp_optional();
+
+ let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
+ .with_bolt11_features(invoice_features).unwrap();
+
+ let recv_value = 50_000_000;
+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value);
+ let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap();
+
+ let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[2], &nodes[3]]];
+
+ assert_eq!(res.len(), expected_route.len());
+
+ send_probe_along_route(&nodes[0], expected_route);
+
+ expect_probe_successful_events(&nodes[0], res.clone());
+
+ assert!(!nodes[0].node.has_pending_payments());
+}
+
+#[test]
+fn preflight_probes_yield_event() {
+ let chanmon_cfgs = create_chanmon_cfgs(4);
+ let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+
+ // We alleviate the HTLC max-in-flight limit, as otherwise we'd always be limited through that.
+ let mut no_htlc_limit_config = test_default_channel_config();
+ no_htlc_limit_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel = 100;
+
+ let user_configs = std::iter::repeat(no_htlc_limit_config).take(4).map(|c| Some(c)).collect::<Vec<Option<UserConfig>>>();
+ let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &user_configs);
+ let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+ // Setup channel topology:
+ // (1M:0)- N1 -(30k:0)
+ // / \
+ // N0 N4
+ // \ /
+ // (1M:0)- N2 -(70k:0)
+ //
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0);
+ create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 30_000, 0);
+ create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 70_000, 0);
+
+ let mut invoice_features = Bolt11InvoiceFeatures::empty();
+ invoice_features.set_basic_mpp_optional();
+
+ let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
+ .with_bolt11_features(invoice_features).unwrap();
+
+ let recv_value = 50_000_000;
+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value);
+ let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap();
+
+ let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]];
+
+ assert_eq!(res.len(), expected_route.len());
+
+ send_probe_along_route(&nodes[0], expected_route);
+
+ expect_probe_successful_events(&nodes[0], res.clone());
+
+ assert!(!nodes[0].node.has_pending_payments());
+}
+
#[test]
fn preflight_probes_yield_event_and_skip() {
let chanmon_cfgs = create_chanmon_cfgs(5);
// \ /
// (70k:0)- N3 -(1M:0)
//
- let first_chan_update = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0).0;
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0);
create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 30_000, 0);
create_announced_chan_between_nodes_with_value(&nodes, 1, 3, 70_000, 0);
create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 1_000_000, 0);
let mut invoice_features = Bolt11InvoiceFeatures::empty();
invoice_features.set_basic_mpp_optional();
- let mut payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV)
+ let payment_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id(), TEST_FINAL_CLTV)
.with_bolt11_features(invoice_features).unwrap();
- let route_params = RouteParameters::from_payment_params_and_value(payment_params, 80_000_000);
+ let recv_value = 80_000_000;
+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value);
let res = nodes[0].node.send_preflight_probes(route_params, None).unwrap();
+ let expected_route : &[&[&Node]] = &[&[&nodes[1], &nodes[2], &nodes[4]]];
+
// We check that only one probe was sent, the other one was skipped due to limited liquidity.
assert_eq!(res.len(), 1);
- let log_msg = format!("Skipped sending payment probe to avoid putting channel {} under the liquidity limit.",
- first_chan_update.contents.short_channel_id);
- node_cfgs[0].logger.assert_log_contains("lightning::ln::channelmanager", &log_msg, 1);
-
- let (payment_hash, payment_id) = res.first().unwrap();
-
- // node[0] -- update_add_htlcs -> node[1]
- check_added_monitors!(nodes[0], 1);
- let probe_event = SendEvent::from_node(&nodes[0]);
- nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &probe_event.msgs[0]);
- check_added_monitors!(nodes[1], 0);
- commitment_signed_dance!(nodes[1], nodes[0], probe_event.commitment_msg, false);
- expect_pending_htlcs_forwardable!(nodes[1]);
- // node[1] -- update_add_htlcs -> node[2]
- check_added_monitors!(nodes[1], 1);
- let probe_event = SendEvent::from_node(&nodes[1]);
- nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &probe_event.msgs[0]);
- check_added_monitors!(nodes[2], 0);
- commitment_signed_dance!(nodes[2], nodes[1], probe_event.commitment_msg, false);
- expect_pending_htlcs_forwardable!(nodes[2]);
+ send_probe_along_route(&nodes[0], expected_route);
- // node[2] -- update_add_htlcs -> node[4]
- check_added_monitors!(nodes[2], 1);
- let probe_event = SendEvent::from_node(&nodes[2]);
- nodes[4].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &probe_event.msgs[0]);
- check_added_monitors!(nodes[4], 0);
- commitment_signed_dance!(nodes[4], nodes[2], probe_event.commitment_msg, true, true);
-
- // node[2] <- update_fail_htlcs -- node[4]
- let updates = get_htlc_update_msgs!(nodes[4], nodes[2].node.get_our_node_id());
- nodes[2].node.handle_update_fail_htlc(&nodes[4].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
- check_added_monitors!(nodes[2], 0);
- commitment_signed_dance!(nodes[2], nodes[4], updates.commitment_signed, true);
-
- // node[1] <- update_fail_htlcs -- node[2]
- let updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id());
- nodes[1].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
- check_added_monitors!(nodes[1], 0);
- commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, true);
-
- // node[0] <- update_fail_htlcs -- node[1]
- let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
- nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
- check_added_monitors!(nodes[0], 0);
- commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false);
+ expect_probe_successful_events(&nodes[0], res.clone());
- let mut events = nodes[0].node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
- match events.drain(..).next().unwrap() {
- crate::events::Event::ProbeSuccessful { payment_id: ev_pid, payment_hash: ev_ph, .. } => {
- assert_eq!(*payment_id, ev_pid);
- assert_eq!(*payment_hash, ev_ph);
- },
- _ => panic!(),
- };
assert!(!nodes[0].node.has_pending_payments());
}
htlc_maximum_msat: None,
}])
]).unwrap()
- .with_bolt11_features(nodes[2].node.invoice_features()).unwrap();
- let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat,);
- let route = get_route(&nodes[0].node.get_our_node_id(), &route_params,
- &nodes[0].network_graph.read_only(), None, nodes[0].logger, &scorer, &Default::default(),
- &random_seed_bytes).unwrap();
+ .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap();
+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
+ let route = get_route(
+ &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), None,
+ nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes
+ ).unwrap();
let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
nodes[0].node.send_payment_with_route(&route, payment_hash,
// Check for unknown channel id error.
let unknown_chan_id_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &ChannelId::from_bytes([42; 32]), nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err();
assert_eq!(unknown_chan_id_err , APIError::ChannelUnavailable {
- err: format!("Channel with id {} not found for the passed counterparty node_id {}.",
+ err: format!("Channel with id {} not found for the passed counterparty node_id {}",
log_bytes!([42; 32]), nodes[2].node.get_our_node_id()) });
if test == InterceptTest::Fail {
expect_payment_failed_conditions(&nodes[0], payment_hash, false, fail_conditions);
} else if test == InterceptTest::Forward {
// Check that we'll fail as expected when sending to a channel that isn't in `ChannelReady` yet.
- let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None).unwrap();
+ let temp_chan_id = nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap();
let unusable_chan_err = nodes[1].node.forward_intercepted_htlc(intercept_id, &temp_chan_id, nodes[2].node.get_our_node_id(), expected_outbound_amount_msat).unwrap_err();
assert_eq!(unusable_chan_err , APIError::ChannelUnavailable {
err: format!("Channel with id {} for the passed counterparty node_id {} is still opening.",
}
let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
.with_route_hints(route_hints).unwrap()
- .with_bolt11_features(nodes[2].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[2].node.bolt11_invoice_features()).unwrap();
let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
let mut retry_params = RouteParameters::from_payment_params_and_value(pay_params, 100_000_000);
retry_params.max_total_routing_fee_msat = None;
- route.route_params.as_mut().unwrap().final_value_msat = 100_000_000;
+ route.route_params = Some(retry_params.clone());
nodes[0].router.expect_find_route(retry_params, Ok(route.clone()));
{
maybe_announced_channel: true,
}], blinded_tail: None },
],
- route_params: Some(RouteParameters::from_payment_params_and_value(
- PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV),
- 100_000_001)),
+ route_params: Some(route_params.clone()),
};
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
// On retry, split the payment across both channels.
route.paths[1].hops[0].fee_msat = 50_000_001;
let mut pay_params = route_params.payment_params.clone();
pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap());
- nodes[0].router.expect_find_route(
- RouteParameters::from_payment_params_and_value(pay_params, amt_msat),
- Ok(route.clone()));
+ let retry_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat);
+ route.route_params = Some(retry_params.clone());
+ nodes[0].router.expect_find_route(retry_params, Ok(route.clone()));
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
route.paths[0].hops[1].fee_msat = amt_msat;
let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat);
retry_params.max_total_routing_fee_msat = None;
+ route.route_params = Some(retry_params.clone());
nodes[0].router.expect_find_route(retry_params, Ok(route.clone()));
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
route.paths.remove(0);
let mut retry_params = RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2);
retry_params.max_total_routing_fee_msat = None;
- route.route_params.as_mut().unwrap().final_value_msat = amt_msat / 2;
+ route.route_params = Some(retry_params.clone());
nodes[0].router.expect_find_route(retry_params, Ok(route.clone()));
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
// from here on out, the retry `RouteParameters` amount will be amt/1000
route_params.final_value_msat /= 1000;
- route.route_params.as_mut().unwrap().final_value_msat /= 1000;
+ route.route_params = Some(route_params.clone());
route.paths.pop();
let end_time = Instant::now() + Duration::from_secs(1);
new_route_params.payment_params.previously_failed_channels = previously_failed_channels.clone();
new_route_params.max_total_routing_fee_msat.as_mut().map(|m| *m -= 100_000);
route.paths[0].hops[1].short_channel_id += 1;
+ route.route_params = Some(new_route_params.clone());
nodes[0].router.expect_find_route(new_route_params, Ok(route.clone()));
let bs_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
create_announced_chan_between_nodes(&nodes, 2, 3);
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[3]);
- let mut route_params = RouteParameters::from_payment_params_and_value(
- PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[1].node.invoice_features()).unwrap(),
- 10_000_000);
+ let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
+ .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap();
+ let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000_000);
let mut route = nodes[0].router.find_route(&nodes[0].node.get_our_node_id(), &route_params,
None, nodes[0].node.compute_inflight_htlcs()).unwrap();
// Make sure the route is ordered as the B->D path before C->D
send_payment(&nodes[2], &vec!(&nodes[1])[..], 1_500_000);
let amt_msat = 1_000_000;
- let (route, payment_hash, payment_preimage, payment_secret) =
+ let (mut route, payment_hash, payment_preimage, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
// Initiate the payment
// Retry the payment and make sure it succeeds
route_params.payment_params.previously_failed_channels.push(chan_2_update.contents.short_channel_id);
+ route.route_params = Some(route_params.clone());
nodes[0].router.expect_find_route(route_params, Ok(route));
nodes[0].node.process_pending_htlc_forwards();
check_added_monitors!(nodes[0], 1);
let chan_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 100_000, 0);
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[3].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[3].node.bolt11_invoice_features()).unwrap();
let mut route = get_route!(nodes[0], payment_params, 15_000_000).unwrap();
assert_eq!(route.paths.len(), 2);
route.paths.sort_by(|path_a, _| {
let payment_metadata = vec![44, 49, 52, 142];
let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
- .with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
+ .with_bolt11_features(nodes[1].node.bolt11_invoice_features()).unwrap();
let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
// Send the MPP payment, delivering the updated commitment state to nodes[1].
do_test_payment_metadata_consistency(false, true);
do_test_payment_metadata_consistency(false, false);
}
+
+#[test]
+fn test_htlc_forward_considers_anchor_outputs_value() {
+ // Tests that:
+ //
+ // 1) Forwarding nodes don't forward HTLCs that would cause their balance to dip below the
+ // reserve when considering the value of anchor outputs.
+ //
+ // 2) Recipients of `update_add_htlc` properly reject HTLCs that would cause the initiator's
+ // balance to dip below the reserve when considering the value of anchor outputs.
+ let mut config = test_default_channel_config();
+ config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
+ config.manually_accept_inbound_channels = true;
+ config.channel_config.forwarding_fee_base_msat = 0;
+ config.channel_config.forwarding_fee_proportional_millionths = 0;
+
+ // Set up a test network of three nodes that replicates a production failure leading to the
+ // discovery of this bug.
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(config)]);
+ let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+ const CHAN_AMT: u64 = 1_000_000;
+ const PUSH_MSAT: u64 = 900_000_000;
+ create_announced_chan_between_nodes_with_value(&nodes, 0, 1, CHAN_AMT, 500_000_000);
+ let (_, _, chan_id_2, _) = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, CHAN_AMT, PUSH_MSAT);
+
+ let channel_reserve_msat = get_holder_selected_channel_reserve_satoshis(CHAN_AMT, &config) * 1000;
+ let commitment_fee_msat = commit_tx_fee_msat(
+ *nodes[1].fee_estimator.sat_per_kw.lock().unwrap(), 2, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies()
+ );
+ let anchor_outpus_value_msat = ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000;
+ let sendable_balance_msat = CHAN_AMT * 1000 - PUSH_MSAT - channel_reserve_msat - commitment_fee_msat - anchor_outpus_value_msat;
+ let channel_details = nodes[1].node.list_channels().into_iter().find(|channel| channel.channel_id == chan_id_2).unwrap();
+ assert!(sendable_balance_msat >= channel_details.next_outbound_htlc_minimum_msat);
+ assert!(sendable_balance_msat <= channel_details.next_outbound_htlc_limit_msat);
+
+ send_payment(&nodes[0], &[&nodes[1], &nodes[2]], sendable_balance_msat);
+ send_payment(&nodes[2], &[&nodes[1], &nodes[0]], sendable_balance_msat);
+
+ // Send out an HTLC that would cause the forwarding node to dip below its reserve when
+ // considering the value of anchor outputs.
+ let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(
+ nodes[0], nodes[2], sendable_balance_msat + anchor_outpus_value_msat
+ );
+ nodes[0].node.send_payment_with_route(
+ &route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)
+ ).unwrap();
+ check_added_monitors!(nodes[0], 1);
+
+ let mut events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ let mut update_add_htlc = if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() {
+ nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
+ check_added_monitors(&nodes[1], 0);
+ commitment_signed_dance!(nodes[1], nodes[0], &updates.commitment_signed, false);
+ updates.update_add_htlcs[0].clone()
+ } else {
+ panic!("Unexpected event");
+ };
+
+ // The forwarding node should reject forwarding it as expected.
+ expect_pending_htlcs_forwardable!(nodes[1]);
+ expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[1], vec![HTLCDestination::NextHopChannel {
+ node_id: Some(nodes[2].node.get_our_node_id()),
+ channel_id: chan_id_2
+ }]);
+ check_added_monitors(&nodes[1], 1);
+
+ let mut events = nodes[1].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 1);
+ if let MessageSendEvent::UpdateHTLCs { updates, .. } = events.pop().unwrap() {
+ nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+ check_added_monitors(&nodes[0], 0);
+ commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false);
+ } else {
+ panic!("Unexpected event");
+ }
+
+ expect_payment_failed!(nodes[0], payment_hash, false);
+
+ // Assume that the forwarding node did forward it, and make sure the recipient rejects it as an
+ // invalid update and closes the channel.
+ update_add_htlc.channel_id = chan_id_2;
+ nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &update_add_htlc);
+ check_closed_event(&nodes[2], 1, ClosureReason::ProcessingError {
+ err: "Remote HTLC add would put them under remote reserve value".to_owned()
+ }, false, &[nodes[1].node.get_our_node_id()], 1_000_000);
+ check_closed_broadcast(&nodes[2], 1, true);
+ check_added_monitors(&nodes[2], 1);
+}
+
+#[test]
+fn peel_payment_onion_custom_tlvs() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ let secp_ctx = Secp256k1::new();
+
+ let amt_msat = 1000;
+ let payment_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(),
+ TEST_FINAL_CLTV, false);
+ let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
+ let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap();
+ let mut recipient_onion = RecipientOnionFields::spontaneous_empty()
+ .with_custom_tlvs(vec![(414141, vec![42; 1200])]).unwrap();
+ let prng_seed = chanmon_cfgs[0].keys_manager.get_secure_random_bytes();
+ let session_priv = SecretKey::from_slice(&prng_seed[..]).expect("RNG is busted");
+ let keysend_preimage = PaymentPreimage([42; 32]);
+ let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array());
+
+ let (onion_routing_packet, first_hop_msat, cltv_expiry) = onion_utils::create_payment_onion(
+ &secp_ctx, &route.paths[0], &session_priv, amt_msat, recipient_onion.clone(),
+ nodes[0].best_block_info().1, &payment_hash, &Some(keysend_preimage), prng_seed
+ ).unwrap();
+
+ let update_add = msgs::UpdateAddHTLC {
+ channel_id: ChannelId([0; 32]),
+ htlc_id: 42,
+ amount_msat: first_hop_msat,
+ payment_hash,
+ cltv_expiry,
+ skimmed_fee_msat: None,
+ onion_routing_packet,
+ blinding_point: None,
+ };
+ let peeled_onion = crate::ln::onion_payment::peel_payment_onion(
+ &update_add, &&chanmon_cfgs[1].keys_manager, &&chanmon_cfgs[1].logger, &secp_ctx,
+ nodes[1].best_block_info().1, true, false
+ ).unwrap();
+ assert_eq!(peeled_onion.incoming_amt_msat, Some(amt_msat));
+ match peeled_onion.routing {
+ PendingHTLCRouting::ReceiveKeysend {
+ payment_data, payment_metadata, custom_tlvs, ..
+ } => {
+ #[cfg(not(c_bindings))]
+ assert_eq!(&custom_tlvs, recipient_onion.custom_tlvs());
+ #[cfg(c_bindings)]
+ assert_eq!(custom_tlvs, recipient_onion.custom_tlvs());
+ assert!(payment_metadata.is_none());
+ assert!(payment_data.is_none());
+ },
+ _ => panic!()
+ }
+}