use crate::events::{ClosureReason, Event, HTLCHandlingFailureType, PaymentPurpose};
use crate::ln::chan_utils::{
self, commit_tx_fee_sat, commitment_tx_base_weight, second_stage_tx_fees_sat,
shared_anchor_script_pubkey, CommitmentTransaction, HTLCOutputInCommitment,
COMMITMENT_TX_WEIGHT_PER_HTLC, TRUC_CHILD_MAX_WEIGHT,
};
use crate::ln::channel::{
get_holder_selected_channel_reserve_satoshis, Channel, ANCHOR_OUTPUT_VALUE_SATOSHI,
FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT,
MIN_CHAN_DUST_LIMIT_SATOSHIS,
};
use crate::ln::channel_state::ChannelDetails;
use crate::ln::channelmanager::{PaymentId, RAACommitmentOrder, TrustedChannelFeatures};
use crate::ln::functional_test_utils::*;
use crate::ln::msgs::{self, BaseMessageHandler, ChannelMessageHandler, MessageSendEvent};
use crate::ln::onion_utils::{self, AttributionData};
use crate::ln::outbound_payment::RecipientOnionFields;
use crate::ln::types::ChannelId;
use crate::routing::router::PaymentParameters;
use crate::sign::ecdsa::EcdsaChannelSigner;
use crate::sign::tx_builder::{SpecTxBuilder, TxBuilder};
use crate::sign::ChannelSigner;
use crate::types::features::ChannelTypeFeatures;
use crate::types::payment::{PaymentHash, PaymentPreimage};
use crate::util::config::UserConfig;
use crate::util::errors::APIError;
use lightning_macros::xtest;
use bitcoin::secp256k1::{Secp256k1, SecretKey};
use bitcoin::{Amount, Transaction};
fn do_test_counterparty_no_reserve(send_from_initiator: bool) {
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);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let default_config = UserConfig::default();
let mut push_amt = 100_000_000;
let feerate_per_kw = 253;
let channel_type_features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
push_amt -= feerate_per_kw as u64
* (commitment_tx_base_weight(&channel_type_features) + 4 * COMMITMENT_TX_WEIGHT_PER_HTLC)
/ 1000 * 1000;
push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, 0, &default_config, false)
.unwrap()
* 1000;
push_amt -= 2 * 330_000;
let push = if send_from_initiator { 0 } else { push_amt };
let temp_channel_id =
nodes[0].node.create_channel(node_b_id, 100_000, push, 42, None, None).unwrap();
let mut open_channel_message =
get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id);
if !send_from_initiator {
open_channel_message.channel_reserve_satoshis = 0;
open_channel_message.common_fields.max_htlc_value_in_flight_msat = 100_000_000;
}
handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message);
let mut accept_channel_message =
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id);
if send_from_initiator {
accept_channel_message.channel_reserve_satoshis = 0;
accept_channel_message.common_fields.max_htlc_value_in_flight_msat = 100_000_000;
}
nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message);
{
let sender_node = if send_from_initiator { &nodes[1] } else { &nodes[0] };
let counterparty_node = if send_from_initiator { &nodes[0] } else { &nodes[1] };
let mut sender_node_per_peer_lock;
let mut sender_node_peer_state_lock;
let channel = get_channel_ref!(
sender_node,
counterparty_node,
sender_node_per_peer_lock,
sender_node_peer_state_lock,
temp_channel_id
);
assert!(channel.is_unfunded_v1());
channel.funding_mut().holder_selected_channel_reserve_satoshis = 0;
channel.context_mut().holder_max_htlc_value_in_flight_msat = 100_000_000;
}
let funding_tx = sign_funding_transaction(&nodes[0], &nodes[1], 100_000, temp_channel_id);
let funding_msgs =
create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &funding_tx);
create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_msgs.0);
if send_from_initiator {
send_payment(
&nodes[0],
&[&nodes[1]],
100_000_000
- commit_tx_fee_msat(feerate_per_kw, 2, &channel_type_features)
- 2 * 330_000,
);
} else {
send_payment(&nodes[1], &[&nodes[0]], push_amt);
}
}
#[xtest(feature = "_externalize_tests")]
pub fn test_counterparty_no_reserve() {
do_test_counterparty_no_reserve(true);
do_test_counterparty_no_reserve(false);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_channel_reserve_holding_cell_htlcs() {
let chanmon_cfgs = create_chanmon_cfgs(3);
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
let mut config = test_legacy_channel_config();
config.channel_config.forwarding_fee_base_msat = 239;
let configs = [Some(config.clone()), Some(config.clone()), Some(config.clone())];
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &configs);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let node_c_id = nodes[2].node.get_our_node_id();
let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001);
let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001);
let chan_2_user_id = nodes[2].node.list_channels()[0].user_channel_id;
let mut stat01 = get_channel_value_stat!(nodes[0], nodes[1], chan_1.2);
let mut stat11 = get_channel_value_stat!(nodes[1], nodes[0], chan_1.2);
let mut stat12 = get_channel_value_stat!(nodes[1], nodes[2], chan_2.2);
let mut stat22 = get_channel_value_stat!(nodes[2], nodes[1], chan_2.2);
macro_rules! expect_forward {
($node: expr) => {{
let mut events = $node.node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
check_added_monitors(&$node, 1);
let payment_event = SendEvent::from_event(events.remove(0));
payment_event
}};
}
let feemsat = 239; let total_fee_msat = (nodes.len() - 2) as u64 * feemsat;
let feerate = get_feerate!(nodes[0], nodes[1], chan_1.2);
let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan_1.2);
let recv_value_0 = stat01.counterparty_max_htlc_value_in_flight_msat - total_fee_msat;
{
let payment_params = PaymentParameters::from_node_id(node_c_id, TEST_FINAL_CLTV)
.with_bolt11_features(nodes[2].node.bolt11_invoice_features())
.unwrap()
.with_max_channel_saturation_power_of_half(0);
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, recv_value_0);
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
assert!(route.paths[0].hops.iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
loop {
let amt_msat = recv_value_0 + total_fee_msat;
let commit_tx_fee_all_htlcs =
2 * commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features);
let ensure_htlc_amounts_above_dust_buffer =
3 * (stat01.counterparty_dust_limit_msat + 1000);
if stat01.value_to_self_msat
< stat01.channel_reserve_msat
+ commit_tx_fee_all_htlcs
+ ensure_htlc_amounts_above_dust_buffer
+ amt_msat
{
break;
}
let payment_params = PaymentParameters::from_node_id(node_c_id, TEST_FINAL_CLTV)
.with_bolt11_features(nodes[2].node.bolt11_invoice_features())
.unwrap()
.with_max_channel_saturation_power_of_half(0);
let route = get_route!(nodes[0], payment_params, recv_value_0).unwrap();
let (payment_preimage, ..) =
send_along_route(&nodes[0], route, &[&nodes[1], &nodes[2]], recv_value_0);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
let (stat01_, stat11_, stat12_, stat22_) = (
get_channel_value_stat!(nodes[0], nodes[1], chan_1.2),
get_channel_value_stat!(nodes[1], nodes[0], chan_1.2),
get_channel_value_stat!(nodes[1], nodes[2], chan_2.2),
get_channel_value_stat!(nodes[2], nodes[1], chan_2.2),
);
assert_eq!(stat01_.value_to_self_msat, stat01.value_to_self_msat - amt_msat);
assert_eq!(stat11_.value_to_self_msat, stat11.value_to_self_msat + amt_msat);
assert_eq!(stat12_.value_to_self_msat, stat12.value_to_self_msat - (amt_msat - feemsat));
assert_eq!(stat22_.value_to_self_msat, stat22.value_to_self_msat + (amt_msat - feemsat));
stat01 = stat01_;
stat11 = stat11_;
stat12 = stat12_;
stat22 = stat22_;
}
let commit_tx_fee_2_htlcs = 2 * commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features);
let recv_value_1 = (stat01.value_to_self_msat
- stat01.channel_reserve_msat
- total_fee_msat
- commit_tx_fee_2_htlcs)
/ 2;
let amt_msat_1 = recv_value_1 + total_fee_msat;
let (route_1, our_payment_hash_1, our_payment_preimage_1, our_payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1);
let payment_event_1 = {
let route = route_1.clone();
let onion = RecipientOnionFields::secret_only(our_payment_secret_1, recv_value_1);
let id = PaymentId(our_payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
SendEvent::from_event(events.remove(0))
};
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event_1.msgs[0]);
let recv_value_2 = stat01.value_to_self_msat
- amt_msat_1
- stat01.channel_reserve_msat
- total_fee_msat
- commit_tx_fee_2_htlcs;
{
let mut route = route_1.clone();
route.paths[0].hops.last_mut().unwrap().fee_msat = recv_value_2 + 1;
let (_, our_payment_hash, our_payment_secret) =
get_payment_preimage_hash(&nodes[2], None, None);
let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
let commit_tx_fee_3_htlcs = 2 * commit_tx_fee_msat(feerate, 3 + 1, &channel_type_features);
let additional_htlc_cost_msat = commit_tx_fee_3_htlcs - commit_tx_fee_2_htlcs;
let recv_value_21 = recv_value_2 / 2 - additional_htlc_cost_msat / 2;
let recv_value_22 = recv_value_2 - recv_value_21 - total_fee_msat - additional_htlc_cost_msat;
{
let stat = get_channel_value_stat!(nodes[0], nodes[1], chan_1.2);
assert_eq!(
stat.value_to_self_msat
- (stat.pending_outbound_htlcs_amount_msat
+ recv_value_21 + recv_value_22
+ total_fee_msat + total_fee_msat
+ commit_tx_fee_3_htlcs),
stat.channel_reserve_msat
);
}
let (route_21, our_payment_hash_21, our_payment_preimage_21, our_payment_secret_21) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21);
let onion = RecipientOnionFields::secret_only(our_payment_secret_21, recv_value_21);
let id = PaymentId(our_payment_hash_21.0);
nodes[0].node.send_payment_with_route(route_21, our_payment_hash_21, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 0);
{
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22);
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
let (route_22, our_payment_hash_22, our_payment_preimage_22, our_payment_secret_22) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22);
let onion = RecipientOnionFields::secret_only(our_payment_secret_22, recv_value_22);
let id = PaymentId(our_payment_hash_22.0);
nodes[0].node.send_payment_with_route(route_22, our_payment_hash_22, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &payment_event_1.commitment_msg);
let (as_revoke_and_ack, as_commitment_signed) = get_revoke_commit_msgs(&nodes[1], &node_a_id);
check_added_monitors(&nodes[1], 1);
nodes[0].node.handle_revoke_and_ack(node_b_id, &as_revoke_and_ack);
check_added_monitors(&nodes[0], 1);
let commitment_update_2 = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &as_commitment_signed);
let bs_revoke_and_ack = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_b_id);
check_added_monitors(&nodes[0], 1);
nodes[1].node.handle_revoke_and_ack(node_a_id, &bs_revoke_and_ack);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
check_added_monitors(&nodes[1], 1);
expect_and_process_pending_htlcs(&nodes[1], false);
let ref payment_event_11 = expect_forward!(nodes[1]);
nodes[2].node.handle_update_add_htlc(node_b_id, &payment_event_11.msgs[0]);
let commitment = &payment_event_11.commitment_msg;
do_commitment_signed_dance(&nodes[2], &nodes[1], commitment, false, false);
expect_and_process_pending_htlcs(&nodes[2], false);
expect_payment_claimable!(nodes[2], our_payment_hash_1, our_payment_secret_1, recv_value_1);
assert_eq!(commitment_update_2.update_add_htlcs.len(), 2);
nodes[1].node.handle_update_add_htlc(node_a_id, &commitment_update_2.update_add_htlcs[0]);
nodes[1].node.handle_update_add_htlc(node_a_id, &commitment_update_2.update_add_htlcs[1]);
let commitment = &commitment_update_2.commitment_signed;
do_commitment_signed_dance(&nodes[1], &nodes[0], commitment, false, false);
expect_and_process_pending_htlcs(&nodes[1], false);
let ref payment_event_3 = expect_forward!(nodes[1]);
assert_eq!(payment_event_3.msgs.len(), 2);
nodes[2].node.handle_update_add_htlc(node_b_id, &payment_event_3.msgs[0]);
nodes[2].node.handle_update_add_htlc(node_b_id, &payment_event_3.msgs[1]);
do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_3.commitment_msg, false, false);
expect_and_process_pending_htlcs(&nodes[2], false);
let events = nodes[2].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
match events[0] {
Event::PaymentClaimable {
ref payment_hash,
ref purpose,
amount_msat,
receiver_node_id,
ref receiving_channel_ids,
..
} => {
assert_eq!(our_payment_hash_21, *payment_hash);
assert_eq!(recv_value_21, amount_msat);
assert_eq!(node_c_id, receiver_node_id.unwrap());
assert_eq!(*receiving_channel_ids, vec![(chan_2.2, Some(chan_2_user_id))]);
match &purpose {
PaymentPurpose::Bolt11InvoicePayment {
payment_preimage, payment_secret, ..
} => {
assert!(payment_preimage.is_none());
assert_eq!(our_payment_secret_21, *payment_secret);
},
_ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"),
}
},
_ => panic!("Unexpected event"),
}
match events[1] {
Event::PaymentClaimable {
ref payment_hash,
ref purpose,
amount_msat,
receiver_node_id,
ref receiving_channel_ids,
..
} => {
assert_eq!(our_payment_hash_22, *payment_hash);
assert_eq!(recv_value_22, amount_msat);
assert_eq!(node_c_id, receiver_node_id.unwrap());
assert_eq!(*receiving_channel_ids, vec![(chan_2.2, Some(chan_2_user_id))]);
match &purpose {
PaymentPurpose::Bolt11InvoicePayment {
payment_preimage, payment_secret, ..
} => {
assert!(payment_preimage.is_none());
assert_eq!(our_payment_secret_22, *payment_secret);
},
_ => panic!("expected PaymentPurpose::Bolt11InvoicePayment"),
}
},
_ => panic!("Unexpected event"),
}
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage_1);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage_21);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage_22);
let commit_tx_fee_0_htlcs = 2 * commit_tx_fee_msat(feerate, 1, &channel_type_features);
let recv_value_3 = commit_tx_fee_2_htlcs - commit_tx_fee_0_htlcs - total_fee_msat;
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], recv_value_3);
let commit_tx_fee_1_htlc = 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features);
let expected_value_to_self = stat01.value_to_self_msat
- (recv_value_1 + total_fee_msat)
- (recv_value_21 + total_fee_msat)
- (recv_value_22 + total_fee_msat)
- (recv_value_3 + total_fee_msat);
let stat0 = get_channel_value_stat!(nodes[0], nodes[1], chan_1.2);
assert_eq!(stat0.value_to_self_msat, expected_value_to_self);
assert_eq!(stat0.value_to_self_msat, stat0.channel_reserve_msat + commit_tx_fee_1_htlc);
let stat2 = get_channel_value_stat!(nodes[2], nodes[1], chan_2.2);
assert_eq!(
stat2.value_to_self_msat,
stat22.value_to_self_msat + recv_value_1 + recv_value_21 + recv_value_22 + recv_value_3
);
}
#[xtest(feature = "_externalize_tests")]
pub fn channel_reserve_in_flight_removes() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
let b_chan_values = get_channel_value_stat!(nodes[1], nodes[0], chan_1.2);
let payment_value_1 =
b_chan_values.channel_reserve_msat - b_chan_values.value_to_self_msat - 10000;
let (payment_preimage_1, payment_hash_1, ..) =
route_payment(&nodes[0], &[&nodes[1]], payment_value_1);
let (payment_preimage_2, payment_hash_2, ..) = route_payment(&nodes[0], &[&nodes[1]], 20_000);
let (route, payment_hash_3, payment_preimage_3, payment_secret_3) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
let send_1 = {
let onion = RecipientOnionFields::secret_only(payment_secret_3, 100000);
let id = PaymentId(payment_hash_3.0);
nodes[0].node.send_payment_with_route(route, payment_hash_3, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
SendEvent::from_event(events.remove(0))
};
nodes[1].node.claim_funds(payment_preimage_1);
expect_payment_claimed!(nodes[1], payment_hash_1, payment_value_1);
check_added_monitors(&nodes[1], 1);
let mut bs_removes = get_htlc_update_msgs(&nodes[1], &node_a_id);
nodes[1].node.claim_funds(payment_preimage_2);
expect_payment_claimed!(nodes[1], payment_hash_2, 20_000);
check_added_monitors(&nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].node.handle_update_fulfill_htlc(node_b_id, bs_removes.update_fulfill_htlcs.remove(0));
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &bs_removes.commitment_signed);
check_added_monitors(&nodes[0], 1);
let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_b_id);
expect_payment_sent(&nodes[0], payment_preimage_1, None, false, false);
nodes[1].node.handle_update_add_htlc(node_a_id, &send_1.msgs[0]);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &send_1.commitment_msg);
check_added_monitors(&nodes[1], 1);
let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_a_id);
nodes[1].node.handle_revoke_and_ack(node_a_id, &as_raa);
check_added_monitors(&nodes[1], 1);
let mut bs_cs = get_htlc_update_msgs(&nodes[1], &node_a_id);
nodes[0].node.handle_revoke_and_ack(node_b_id, &bs_raa);
check_added_monitors(&nodes[0], 1);
let as_cs = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &as_cs.commitment_signed);
check_added_monitors(&nodes[1], 1);
let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_a_id);
nodes[0].node.handle_update_fulfill_htlc(node_b_id, bs_cs.update_fulfill_htlcs.remove(0));
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &bs_cs.commitment_signed);
check_added_monitors(&nodes[0], 1);
let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_b_id);
expect_payment_sent(&nodes[0], payment_preimage_2, None, false, false);
nodes[1].node.handle_revoke_and_ack(node_a_id, &as_raa);
check_added_monitors(&nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
expect_and_process_pending_htlcs(&nodes[1], false);
expect_payment_claimable!(nodes[1], payment_hash_3, payment_secret_3, 100000);
nodes[0].node.handle_revoke_and_ack(node_b_id, &bs_raa);
check_added_monitors(&nodes[0], 1);
expect_payment_path_successful!(nodes[0]);
let as_cs = get_htlc_update_msgs(&nodes[0], &node_b_id);
let (route, payment_hash_4, payment_preimage_4, payment_secret_4) =
get_route_and_payment_hash!(nodes[1], nodes[0], 10000);
let send_2 = {
let onion = RecipientOnionFields::secret_only(payment_secret_4, 10000);
let id = PaymentId(payment_hash_4.0);
nodes[1].node.send_payment_with_route(route, payment_hash_4, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
SendEvent::from_event(events.remove(0))
};
nodes[0].node.handle_update_add_htlc(node_b_id, &send_2.msgs[0]);
nodes[0].node.handle_commitment_signed_batch_test(node_b_id, &send_2.commitment_msg);
check_added_monitors(&nodes[0], 1);
let as_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_b_id);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &as_cs.commitment_signed);
check_added_monitors(&nodes[1], 1);
let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_a_id);
nodes[1].node.handle_revoke_and_ack(node_a_id, &as_raa);
check_added_monitors(&nodes[1], 1);
nodes[0].node.handle_revoke_and_ack(node_b_id, &bs_raa);
check_added_monitors(&nodes[0], 1);
expect_payment_path_successful!(nodes[0]);
let as_cs = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &as_cs.commitment_signed);
check_added_monitors(&nodes[1], 1);
let bs_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_a_id);
nodes[0].node.handle_revoke_and_ack(node_b_id, &bs_raa);
check_added_monitors(&nodes[0], 1);
expect_and_process_pending_htlcs(&nodes[0], false);
expect_payment_claimable!(nodes[0], payment_hash_4, payment_secret_4, 10000);
claim_payment(&nodes[1], &[&nodes[0]], payment_preimage_4);
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage_3);
}
#[xtest(feature = "_externalize_tests")]
pub fn holding_cell_htlc_counting() {
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, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let node_c_id = nodes[2].node.get_our_node_id();
create_announced_chan_between_nodes(&nodes, 0, 1);
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
let (route, payment_hash_1, _, payment_secret_1) =
get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
let mut payments = Vec::new();
for _ in 0..50 {
let (route, payment_hash, payment_preimage, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
let onion = RecipientOnionFields::secret_only(payment_secret, 100000);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
payments.push((payment_preimage, payment_hash));
}
check_added_monitors(&nodes[1], 1);
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let initial_payment_event = SendEvent::from_event(events.pop().unwrap());
assert_eq!(initial_payment_event.node_id, node_c_id);
{
let onion = RecipientOnionFields::secret_only(payment_secret_1, 100000);
let id = PaymentId(payment_hash_1.0);
let res = nodes[1].node.send_payment_with_route(route, payment_hash_1, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
}
let (route, payment_hash_2, _, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[2], 100000);
let onion = RecipientOnionFields::secret_only(payment_secret_2, 100000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).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 payment_event = SendEvent::from_event(events.pop().unwrap());
assert_eq!(payment_event.node_id, node_b_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event.msgs[0]);
do_commitment_signed_dance(&nodes[1], &nodes[0], &payment_event.commitment_msg, false, false);
expect_and_process_pending_htlcs(&nodes[1], true);
let fail = HTLCHandlingFailureType::Forward { node_id: Some(node_c_id), channel_id: chan_2.2 };
let events = nodes[1].node.get_and_clear_pending_events();
expect_htlc_failure_conditions(events, &[fail]);
check_added_monitors(&nodes[1], 1);
let bs_fail_updates = get_htlc_update_msgs(&nodes[1], &node_a_id);
nodes[0].node.handle_update_fail_htlc(node_b_id, &bs_fail_updates.update_fail_htlcs[0]);
let commitment = &bs_fail_updates.commitment_signed;
do_commitment_signed_dance(&nodes[0], &nodes[1], commitment, false, true);
let failing_scid = chan_2.0.contents.short_channel_id;
expect_payment_failed_with_update!(nodes[0], payment_hash_2, false, failing_scid, false);
nodes[2].node.handle_update_add_htlc(node_b_id, &initial_payment_event.msgs[0]);
nodes[2]
.node
.handle_commitment_signed_batch_test(node_b_id, &initial_payment_event.commitment_msg);
check_added_monitors(&nodes[2], 1);
let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs(&nodes[2], &node_b_id);
nodes[1].node.handle_revoke_and_ack(node_c_id, &bs_revoke_and_ack);
check_added_monitors(&nodes[1], 1);
let as_updates = get_htlc_update_msgs(&nodes[1], &node_c_id);
nodes[1].node.handle_commitment_signed_batch_test(node_c_id, &bs_commitment_signed);
check_added_monitors(&nodes[1], 1);
let as_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_c_id);
for ref update in as_updates.update_add_htlcs.iter() {
nodes[2].node.handle_update_add_htlc(node_b_id, update);
}
nodes[2].node.handle_commitment_signed_batch_test(node_b_id, &as_updates.commitment_signed);
check_added_monitors(&nodes[2], 1);
nodes[2].node.handle_revoke_and_ack(node_b_id, &as_raa);
check_added_monitors(&nodes[2], 1);
let (bs_revoke_and_ack, bs_commitment_signed) = get_revoke_commit_msgs(&nodes[2], &node_b_id);
nodes[1].node.handle_revoke_and_ack(node_c_id, &bs_revoke_and_ack);
check_added_monitors(&nodes[1], 1);
nodes[1].node.handle_commitment_signed_batch_test(node_c_id, &bs_commitment_signed);
check_added_monitors(&nodes[1], 1);
let as_final_raa = get_event_msg!(nodes[1], MessageSendEvent::SendRevokeAndACK, node_c_id);
nodes[2].node.handle_revoke_and_ack(node_b_id, &as_final_raa);
check_added_monitors(&nodes[2], 1);
expect_and_process_pending_htlcs(&nodes[2], false);
let events = nodes[2].node.get_and_clear_pending_events();
assert_eq!(events.len(), payments.len());
for (event, &(_, ref hash)) in events.iter().zip(payments.iter()) {
match event {
&Event::PaymentClaimable { ref payment_hash, .. } => {
assert_eq!(*payment_hash, *hash);
},
_ => panic!("Unexpected event"),
};
}
for (preimage, _) in payments.drain(..) {
claim_payment(&nodes[1], &[&nodes[2]], preimage);
}
send_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_basic_channel_reserve() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let legacy_cfg = test_legacy_channel_config();
let node_chanmgrs =
create_node_chanmgrs(2, &node_cfgs, &[Some(legacy_cfg.clone()), Some(legacy_cfg)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
let channel_reserve = chan_stat.channel_reserve_msat;
let commit_tx_fee = 2 * commit_tx_fee_msat(
get_feerate!(nodes[0], nodes[1], chan.2),
1 + 1,
&get_channel_type_features!(nodes[0], nodes[1], chan.2),
);
let max_can_send = 5000000 - channel_reserve - commit_tx_fee;
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send);
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send + 1);
let id = PaymentId(our_payment_hash.0);
let err = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], err, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
send_payment(&nodes[0], &[&nodes[1]], max_can_send);
}
#[xtest(feature = "_externalize_tests")]
fn test_fee_spike_violation_fails_htlc() {
let cfg = test_legacy_channel_config();
do_test_fee_spike_buffer(Some(cfg), true)
}
#[test]
fn test_zero_fee_commitments_no_fee_spike_buffer() {
let mut cfg = test_default_channel_config();
cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
do_test_fee_spike_buffer(Some(cfg), false)
}
pub fn do_test_fee_spike_buffer(cfg: Option<UserConfig>, htlc_fails: bool) {
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, &[cfg.clone(), cfg]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan_amt_sat = 100000;
let push_amt_msat = 95000000;
let chan =
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, chan_amt_sat, push_amt_msat);
let (mut route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 3460000);
route.paths[0].hops[0].fee_msat += 1;
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).expect("RNG is bad!");
let cur_height = nodes[1].node.best_block.read().unwrap().height + 1;
let payment_amt_msat = 3460001;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv);
let recipient_onion_fields =
RecipientOnionFields::secret_only(payment_secret, payment_amt_msat);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::test_build_onion_payloads(
&route.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
let onion_packet =
onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash)
.unwrap();
let msg = msgs::UpdateAddHTLC {
channel_id: chan.2,
htlc_id: 0,
amount_msat: htlc_msat,
payment_hash,
cltv_expiry: htlc_cltv,
onion_routing_packet: onion_packet,
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
let feerate_per_kw = get_feerate!(nodes[0], nodes[1], chan.2);
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
let (local_secret, next_local_point) = {
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
let chan_lock = per_peer_state.get(&node_b_id).unwrap().lock().unwrap();
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
let chan_signer = local_chan.get_signer();
chan_signer.get_enforcement_state().last_holder_commitment -= 1;
(
chan_signer.release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap(),
)
};
let remote_point = {
let per_peer_lock;
let mut peer_state_lock;
let channel = get_channel_ref!(nodes[1], nodes[0], per_peer_lock, peer_state_lock, chan.2);
let chan_signer = channel.as_funded().unwrap().get_signer();
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
};
let accepted_htlc_info = HTLCOutputInCommitment {
offered: false,
amount_msat: payment_amt_msat,
cltv_expiry: htlc_cltv,
payment_hash,
transaction_output_index: Some(1),
};
let local_chan_balance_msat = chan_amt_sat * 1000 - push_amt_msat;
let commitment_number = INITIAL_COMMITMENT_NUMBER - 1;
let res = {
let per_peer_lock;
let mut peer_state_lock;
let channel = get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan.2);
let chan_signer = channel.as_funded().unwrap().get_signer();
let (commitment_tx, _stats) = SpecTxBuilder {}.build_commitment_transaction(
false,
commitment_number,
&remote_point,
&channel.funding().channel_transaction_parameters,
&secp_ctx,
local_chan_balance_msat,
vec![accepted_htlc_info],
feerate_per_kw,
MIN_CHAN_DUST_LIMIT_SATOSHIS,
&nodes[0].logger,
);
let params = &channel.funding().channel_transaction_parameters;
chan_signer
.sign_counterparty_commitment(params, &commitment_tx, Vec::new(), Vec::new(), &secp_ctx)
.unwrap()
};
let commit_signed_msg = msgs::CommitmentSigned {
channel_id: chan.2,
signature: res.0,
htlc_signatures: res.1,
funding_txid: None,
};
nodes[1].node.handle_commitment_signed(node_a_id, &commit_signed_msg);
let _ = nodes[1].node.get_and_clear_pending_msg_events();
let raa_msg = msgs::RevokeAndACK {
channel_id: chan.2,
per_commitment_secret: local_secret,
next_per_commitment_point: next_local_point,
release_htlc_message_paths: Vec::new(),
};
nodes[1].node.handle_revoke_and_ack(node_a_id, &raa_msg);
expect_and_process_pending_htlcs(&nodes[1], false);
if htlc_fails {
expect_htlc_handling_failed_destinations!(
nodes[1].node.get_and_clear_pending_events(),
&[HTLCHandlingFailureType::Receive { payment_hash }]
);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates: msgs::CommitmentUpdate { ref update_fail_htlcs, .. },
..
} => {
assert_eq!(update_fail_htlcs.len(), 1);
update_fail_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
};
nodes[1].logger.assert_log(
"lightning::ln::channel",
"Attempting to fail HTLC due to fee spike buffer violation. Rebalancing is required."
.to_string(),
1,
);
check_added_monitors(&nodes[1], 3);
} else {
expect_payment_claimable!(nodes[1], payment_hash, payment_secret, payment_amt_msat);
check_added_monitors(&nodes[1], 2);
}
}
#[xtest(feature = "_externalize_tests")]
pub fn test_chan_reserve_violation_outbound_htlc_inbound_chan() {
let mut chanmon_cfgs = create_chanmon_cfgs(2);
let feerate_per_kw = *chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let legacy_cfg = test_legacy_channel_config();
let node_chanmgrs =
create_node_chanmgrs(2, &node_cfgs, &[Some(legacy_cfg.clone()), Some(legacy_cfg)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let default_config = UserConfig::default();
let channel_type_features = ChannelTypeFeatures::only_static_remote_key();
let mut push_amt = 100_000_000;
push_amt -= commit_tx_fee_msat(
feerate_per_kw,
MIN_AFFORDABLE_HTLC_COUNT as u64,
&channel_type_features,
);
push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, 0, &default_config, false)
.unwrap()
* 1000;
let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], 1_000_000);
for _ in 0..MIN_AFFORDABLE_HTLC_COUNT {
route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
}
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1_000_000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
}
#[xtest(feature = "_externalize_tests")]
pub fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() {
let mut chanmon_cfgs = create_chanmon_cfgs(2);
let feerate_per_kw = *chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let legacy_cfg = test_legacy_channel_config();
let node_chanmgrs =
create_node_chanmgrs(2, &node_cfgs, &[Some(legacy_cfg.clone()), Some(legacy_cfg)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let default_config = UserConfig::default();
let channel_type_features = ChannelTypeFeatures::only_static_remote_key();
let mut push_amt = 100_000_000;
push_amt -= commit_tx_fee_msat(
feerate_per_kw,
MIN_AFFORDABLE_HTLC_COUNT as u64,
&channel_type_features,
);
push_amt -= get_holder_selected_channel_reserve_satoshis(100_000, 0, &default_config, false)
.unwrap()
* 1000;
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, push_amt);
let (_htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat) =
second_stage_tx_fees_sat(&channel_type_features, feerate_per_kw);
let dust_amt = crate::ln::channel::MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000
+ htlc_timeout_tx_fee_sat * 1000
- 1;
route_payment(&nodes[1], &[&nodes[0]], dust_amt);
for _ in 0..MIN_AFFORDABLE_HTLC_COUNT {
route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
}
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], dust_amt);
route.paths[0].hops[0].fee_msat += 1;
let onion = RecipientOnionFields::secret_only(our_payment_secret, dust_amt + 1);
let id = PaymentId(our_payment_hash.0);
let res = nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
}
#[xtest(feature = "_externalize_tests")]
pub fn test_chan_reserve_dust_inbound_htlcs_inbound_chan() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let legacy_cfg = test_legacy_channel_config();
let node_chanmgrs =
create_node_chanmgrs(2, &node_cfgs, &[Some(legacy_cfg.clone()), Some(legacy_cfg)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 98000000);
let payment_amt = 46000;
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
route_payment(&nodes[0], &[&nodes[1]], payment_amt);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
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, &[None, None, None]);
let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let _ = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000);
let feemsat = 239;
let total_routing_fee_msat = (nodes.len() - 2) as u64 * feemsat;
let chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
let feerate = get_feerate!(nodes[0], nodes[1], chan.2);
let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan.2);
let commit_tx_fee_2_htlc = 2 * commit_tx_fee_msat(feerate, 2 + 1, &channel_type_features);
let recv_value_1 = (chan_stat.value_to_self_msat
- chan_stat.channel_reserve_msat
- total_routing_fee_msat
- commit_tx_fee_2_htlc)
/ 2;
let amt_msat_1 = recv_value_1 + total_routing_fee_msat;
let (route_1, our_payment_hash_1, _, our_payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1);
let payment_event_1 = {
let onion = RecipientOnionFields::secret_only(our_payment_secret_1, amt_msat_1);
let id = PaymentId(our_payment_hash_1.0);
let route = route_1.clone();
nodes[0].node.send_payment_with_route(route, our_payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
SendEvent::from_event(events.remove(0))
};
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event_1.msgs[0]);
let commit_tx_fee_2_htlcs = commit_tx_fee_msat(feerate, 2, &channel_type_features);
let recv_value_2 = chan_stat.value_to_self_msat
- amt_msat_1
- chan_stat.channel_reserve_msat
- total_routing_fee_msat
- commit_tx_fee_2_htlcs
+ 1;
let amt_msat_2 = recv_value_2 + total_routing_fee_msat;
let mut route_2 = route_1.clone();
route_2.paths[0].hops.last_mut().unwrap().fee_msat = amt_msat_2;
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv);
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(recv_value_2);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::test_build_onion_payloads(
&route_2.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
let onion_packet = onion_utils::construct_onion_packet(
onion_payloads,
onion_keys,
[0; 32],
&our_payment_hash_1,
)
.unwrap();
let msg = msgs::UpdateAddHTLC {
channel_id: chan.2,
htlc_id: 1,
amount_msat: htlc_msat + 1,
payment_hash: our_payment_hash_1,
cltv_expiry: htlc_cltv,
onion_routing_packet: onion_packet,
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
nodes[1].logger.assert_log_contains(
"lightning::ln::channelmanager",
"Remote HTLC add would put them under remote reserve value",
3,
);
assert_eq!(nodes[1].node.list_channels().len(), 1);
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Remote HTLC add would put them under remote reserve value");
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data.clone() };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_payment_route_reaching_same_channel_twice() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_b_id = nodes[1].node.get_our_node_id();
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
let payment_params = PaymentParameters::from_node_id(node_b_id, 0)
.with_bolt11_features(nodes[1].node.bolt11_invoice_features())
.unwrap();
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000);
let cloned_hops = route.paths[0].hops.clone();
route.paths[0].hops.extend_from_slice(&cloned_hops);
unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash,
RecipientOnionFields::secret_only(our_payment_secret, 100000000), PaymentId(our_payment_hash.0)
), false, APIError::InvalidRoute { ref err },
assert_eq!(err, &"Path went through the same channel twice"));
assert!(nodes[0].node.list_recent_payments().is_empty());
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_sender_value_below_minimum_msat() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0].hops[0].fee_msat = 100;
let onion = RecipientOnionFields::secret_only(our_payment_secret, 100);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_sender_zero_value_msat() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0].hops[0].fee_msat = 0;
let onion = RecipientOnionFields::secret_only(our_payment_secret, 0);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res,
true, APIError::ChannelUnavailable { ref err },
assert_eq!(err, "Cannot send 0-msat HTLC"));
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
nodes[0].logger.assert_log_contains(
"lightning::ln::channelmanager",
"Cannot send 0-msat HTLC",
2,
);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_zero_value_msat() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].amount_msat = 0;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
nodes[1].logger.assert_log_contains(
"lightning::ln::channelmanager",
"Remote side tried to send a 0-msat HTLC",
3,
);
check_closed_broadcast(&nodes[1], 1, true);
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError {
err: "Remote side tried to send a 0-msat HTLC".to_string(),
};
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_b_id = nodes[1].node.get_our_node_id();
let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
let mut payment_params = PaymentParameters::from_node_id(node_b_id, 0)
.with_bolt11_features(nodes[1].node.bolt11_invoice_features())
.unwrap();
payment_params.max_total_cltv_expiry_delta = 500000001;
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000);
route.paths[0].hops.last_mut().unwrap().cltv_expiry_delta = 500000001;
let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::InvalidRoute { ref err },
assert_eq!(err, &"Channel CLTV overflowed?"));
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0);
let max_accepted_htlcs = {
let per_peer_lock;
let mut peer_state_lock;
let channel = get_channel_ref!(nodes[1], nodes[0], per_peer_lock, peer_state_lock, chan.2);
channel.context().counterparty_max_accepted_htlcs as u64
};
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
for i in 0..max_accepted_htlcs {
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
let payment_event = {
let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
if let MessageSendEvent::UpdateHTLCs {
updates: msgs::CommitmentUpdate { update_add_htlcs: ref htlcs, .. },
..
} = events[0]
{
assert_eq!(htlcs[0].htlc_id, i);
} else {
assert!(false);
}
SendEvent::from_event(events.remove(0))
};
nodes[1].node.handle_update_add_htlc(node_a_id, &payment_event.msgs[0]);
check_added_monitors(&nodes[1], 0);
let commitment = &payment_event.commitment_msg;
do_commitment_signed_dance(&nodes[1], &nodes[0], commitment, false, false);
expect_and_process_pending_htlcs(&nodes[1], false);
expect_payment_claimable!(nodes[1], our_payment_hash, our_payment_secret, 100000);
}
let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_value_in_flight() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let channel_value = 100000;
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 0);
let max_in_flight = get_channel_value_stat!(nodes[0], nodes[1], chan.2)
.counterparty_max_htlc_value_in_flight_msat;
send_payment(&nodes[0], &[&nodes[1]], max_in_flight);
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], max_in_flight);
route.paths[0].hops[0].fee_msat = max_in_flight + 1;
let onion = RecipientOnionFields::secret_only(our_payment_secret, max_in_flight + 1);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
send_payment(&nodes[0], &[&nodes[1]], max_in_flight);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let htlc_minimum_msat = {
let per_peer_lock;
let mut peer_state_lock;
let channel = get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan.2);
channel.context().get_holder_htlc_minimum_msat()
};
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], htlc_minimum_msat);
let onion = RecipientOnionFields::secret_only(our_payment_secret, htlc_minimum_msat);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat - 1;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert!(regex::Regex::new(r"Remote side tried to send less than our minimum HTLC value\. Lower limit: \(\d+\)\. Actual: \(\d+\)").unwrap().is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_sender_can_afford_amount_sent() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let legacy_cfg = test_legacy_channel_config();
let node_chanmgrs =
create_node_chanmgrs(2, &node_cfgs, &[Some(legacy_cfg.clone()), Some(legacy_cfg)]);
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
let channel_reserve = chan_stat.channel_reserve_msat;
let feerate = get_feerate!(nodes[0], nodes[1], chan.2);
let channel_type_features = get_channel_type_features!(nodes[0], nodes[1], chan.2);
let commit_tx_fee_outbound = 2 * commit_tx_fee_msat(feerate, 1 + 1, &channel_type_features);
let max_can_send = 5000000 - channel_reserve - commit_tx_fee_outbound;
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send);
let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].amount_msat = max_can_send + commit_tx_fee_outbound + 1;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Remote HTLC add would put them under remote reserve value");
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let send_amt = 3999999;
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000);
route.paths[0].hops[0].fee_msat = send_amt;
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height + 1;
let onion_keys = onion_utils::construct_onion_keys(
&Secp256k1::signing_only(),
&route.paths[0],
&session_priv,
);
let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret, send_amt);
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::test_build_onion_payloads(
&route.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
let onion_packet =
onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash)
.unwrap();
let mut msg = msgs::UpdateAddHTLC {
channel_id: chan.2,
htlc_id: 0,
amount_msat: 1000,
payment_hash: our_payment_hash,
cltv_expiry: htlc_cltv,
onion_routing_packet: onion_packet.clone(),
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
for i in 0..50 {
msg.htlc_id = i as u64;
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
}
msg.htlc_id = (50) as u64;
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert!(regex::Regex::new(r"Remote tried to push more than our max accepted HTLCs \(\d+\)")
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_check_max_in_flight_msat() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], nodes[0], chan.2)
.counterparty_max_htlc_value_in_flight_msat
+ 1;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert!(regex::Regex::new("Remote HTLC add would put them over our max HTLC value")
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 1000000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_check_cltv_expiry() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let reason = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, reason, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].cltv_expiry = 500000000;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Remote provided CLTV expiry in seconds instead of block height");
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
nodes[0].node.peer_disconnected(node_b_id);
nodes[1].node.peer_disconnected(node_a_id);
let init_msg = msgs::Init {
features: nodes[0].node.init_features(),
networks: None,
remote_network_address: None,
};
nodes[0].node.peer_connected(node_b_id, &init_msg, true).unwrap();
let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
assert_eq!(reestablish_1.len(), 1);
nodes[1].node.peer_connected(node_a_id, &init_msg, false).unwrap();
let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
assert_eq!(reestablish_2.len(), 1);
nodes[0].node.handle_channel_reestablish(node_b_id, &reestablish_2[0]);
handle_chan_reestablish_msgs!(nodes[0], nodes[1]);
nodes[1].node.handle_channel_reestablish(node_a_id, &reestablish_1[0]);
handle_chan_reestablish_msgs!(nodes[1], nodes[0]);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert_eq!(updates.commitment_signed.len(), 1);
assert_eq!(updates.commitment_signed[0].htlc_signatures.len(), 1);
nodes[1].node.handle_commitment_signed_batch_test(node_a_id, &updates.commitment_signed);
check_added_monitors(&nodes[1], 1);
let _bs_responses = get_revoke_commit_msgs(&nodes[1], &node_a_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
assert!(nodes[1].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert!(regex::Regex::new(r"Remote skipped HTLC ID \(skipped ID: \d+\)")
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[1], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_update_fulfill_htlc_before_commitment() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
let update_msg = msgs::UpdateFulfillHTLC {
channel_id: chan.2,
htlc_id: 0,
payment_preimage: our_payment_preimage,
attribution_data: None,
};
nodes[0].node.handle_update_fulfill_htlc(node_b_id, update_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert!(regex::Regex::new(
r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed"
)
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
let update_msg = msgs::UpdateFailHTLC {
channel_id: chan.2,
htlc_id: 0,
reason: Vec::new(),
attribution_data: Some(AttributionData::new()),
};
nodes[0].node.handle_update_fail_htlc(node_b_id, &update_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert!(regex::Regex::new(
r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed"
)
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_update_fail_malformed_htlc_before_commitment() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
let update_msg = msgs::UpdateFailMalformedHTLC {
channel_id: chan.2,
htlc_id: 0,
sha256_of_onion: [1; 32],
failure_code: 0x8000,
};
nodes[0].node.handle_update_fail_malformed_htlc(node_b_id, &update_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert!(regex::Regex::new(
r"Remote tried to fulfill/fail HTLC \(\d+\) before it had been committed"
)
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_incorrect_htlc_id() {
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);
let node_b_id = nodes[1].node.get_our_node_id();
create_announced_chan_between_nodes(&nodes, 0, 1);
let (our_payment_preimage, our_payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], 100_000);
nodes[1].node.claim_funds(our_payment_preimage);
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 100_000);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let mut update_fulfill_msg: msgs::UpdateFulfillHTLC = {
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates:
msgs::CommitmentUpdate {
ref update_add_htlcs,
ref update_fulfill_htlcs,
ref update_fail_htlcs,
ref update_fail_malformed_htlcs,
ref update_fee,
..
},
..
} => {
assert!(update_add_htlcs.is_empty());
assert_eq!(update_fulfill_htlcs.len(), 1);
assert!(update_fail_htlcs.is_empty());
assert!(update_fail_malformed_htlcs.is_empty());
assert!(update_fee.is_none());
update_fulfill_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
}
};
update_fulfill_msg.htlc_id = 1;
nodes[0].node.handle_update_fulfill_htlc(node_b_id, update_fulfill_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Remote tried to fulfill/fail an HTLC we couldn't find");
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_wrong_preimage() {
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);
let node_b_id = nodes[1].node.get_our_node_id();
create_announced_chan_between_nodes(&nodes, 0, 1);
let (our_payment_preimage, our_payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], 100_000);
nodes[1].node.claim_funds(our_payment_preimage);
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 100_000);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
let mut update_fulfill_msg: msgs::UpdateFulfillHTLC = {
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates:
msgs::CommitmentUpdate {
ref update_add_htlcs,
ref update_fulfill_htlcs,
ref update_fail_htlcs,
ref update_fail_malformed_htlcs,
ref update_fee,
..
},
..
} => {
assert!(update_add_htlcs.is_empty());
assert_eq!(update_fulfill_htlcs.len(), 1);
assert!(update_fail_htlcs.is_empty());
assert!(update_fail_malformed_htlcs.is_empty());
assert!(update_fee.is_none());
update_fulfill_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
}
};
update_fulfill_msg.payment_preimage = PaymentPreimage([1; 32]);
nodes[0].node.handle_update_fulfill_htlc(node_b_id, update_fulfill_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert!(regex::Regex::new(r"Remote tried to fulfill HTLC \(\d+\) with an incorrect preimage")
.unwrap()
.is_match(err_msg.data.as_str()));
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 100000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_message() {
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
let mut updates = get_htlc_update_msgs(&nodes[0], &node_b_id);
updates.update_add_htlcs[0].onion_routing_packet.version = 1;
nodes[1].node.handle_update_add_htlc(node_a_id, &updates.update_add_htlcs[0]);
check_added_monitors(&nodes[1], 0);
do_commitment_signed_dance(&nodes[1], &nodes[0], &updates.commitment_signed, false, true);
expect_and_process_pending_htlcs(&nodes[1], false);
expect_htlc_handling_failed_destinations!(
nodes[1].node.get_and_clear_pending_events(),
&[HTLCHandlingFailureType::InvalidOnion]
);
check_added_monitors(&nodes[1], 1);
let events = nodes[1].node.get_and_clear_pending_msg_events();
let mut update_msg: msgs::UpdateFailMalformedHTLC = {
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates:
msgs::CommitmentUpdate {
ref update_add_htlcs,
ref update_fulfill_htlcs,
ref update_fail_htlcs,
ref update_fail_malformed_htlcs,
ref update_fee,
..
},
..
} => {
assert!(update_add_htlcs.is_empty());
assert!(update_fulfill_htlcs.is_empty());
assert!(update_fail_htlcs.is_empty());
assert_eq!(update_fail_malformed_htlcs.len(), 1);
assert!(update_fee.is_none());
update_fail_malformed_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
}
};
update_msg.failure_code &= !0x8000;
nodes[0].node.handle_update_fail_malformed_htlc(node_b_id, &update_msg);
assert!(nodes[0].node.list_channels().is_empty());
let err_msg = check_closed_broadcast(&nodes[0], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Got update_fail_malformed_htlc with BADONION not set");
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::ProcessingError { err: err_msg.data };
check_closed_event(&nodes[0], 1, reason, &[node_b_id], 1000000);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_dust_limit_fee_accounting() {
do_test_dust_limit_fee_accounting(false);
do_test_dust_limit_fee_accounting(true);
}
pub fn do_test_dust_limit_fee_accounting(can_afford: bool) {
let channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
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 mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
const HTLC_AMT_SAT: u64 = 354;
const CHANNEL_VALUE_SAT: u64 = 100_000;
const FEERATE_PER_KW: u32 = 253;
let commit_tx_fee_sat =
chan_utils::commit_tx_fee_sat(FEERATE_PER_KW, MIN_AFFORDABLE_HTLC_COUNT, &channel_type);
let channel_reserve_satoshis = 1_000;
let node_0_balance_sat = commit_tx_fee_sat
+ channel_reserve_satoshis
+ 2 * crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI
+ MIN_AFFORDABLE_HTLC_COUNT as u64 * HTLC_AMT_SAT
- if can_afford { 0 } else { 1 };
let mut node_1_balance_sat = CHANNEL_VALUE_SAT - node_0_balance_sat;
let chan_id = create_chan_between_nodes_with_value(
&nodes[0],
&nodes[1],
CHANNEL_VALUE_SAT,
node_1_balance_sat * 1000,
)
.3;
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[1], nodes[0], per_peer_state_lock, peer_state_lock, chan_id);
assert_eq!(
chan.funding().holder_selected_channel_reserve_satoshis,
channel_reserve_satoshis
);
}
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[0], nodes[1], per_peer_state_lock, peer_state_lock, chan_id);
assert_eq!(chan.context().holder_dust_limit_satoshis, HTLC_AMT_SAT);
}
let (route_0_1, payment_hash_0_1, _, payment_secret_0_1) =
get_route_and_payment_hash!(nodes[0], nodes[1], HTLC_AMT_SAT * 1000);
let mut htlcs = Vec::new();
for _ in 0..MIN_AFFORDABLE_HTLC_COUNT - 1 {
let (_payment_preimage, payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], HTLC_AMT_SAT * 1000);
let accepted_htlc = HTLCOutputInCommitment {
offered: false,
amount_msat: HTLC_AMT_SAT * 1000,
cltv_expiry: 81,
payment_hash,
transaction_output_index: None,
};
htlcs.push(accepted_htlc);
}
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).expect("RNG is bad!");
let cur_height = nodes[1].node.best_block.read().unwrap().height + 1;
let onion_keys =
onion_utils::construct_onion_keys(&secp_ctx, &route_0_1.paths[0], &session_priv);
let recipient_onion_fields =
RecipientOnionFields::secret_only(payment_secret_0_1, HTLC_AMT_SAT * 1000);
let (onion_payloads, amount_msat, cltv_expiry) = onion_utils::test_build_onion_payloads(
&route_0_1.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
let onion_routing_packet =
onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash_0_1)
.unwrap();
assert_eq!(cltv_expiry, 81);
let msg = msgs::UpdateAddHTLC {
channel_id: chan_id,
htlc_id: MIN_AFFORDABLE_HTLC_COUNT as u64 - 1,
amount_msat,
payment_hash: payment_hash_0_1,
cltv_expiry,
onion_routing_packet,
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
if !can_afford {
let err = "Remote HTLC add would put them under remote reserve value".to_string();
nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", &err, 3);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 2);
let reason = ClosureReason::ProcessingError { err };
check_closed_event(&nodes[1], 1, reason, &[node_a_id], CHANNEL_VALUE_SAT);
check_added_monitors(&nodes[1], 1);
} else {
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
let (local_secret, next_local_point) = {
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
let chan_lock = per_peer_state.get(&node_b_id).unwrap().lock().unwrap();
let local_chan =
chan_lock.channel_by_id.get(&chan_id).and_then(Channel::as_funded).unwrap();
let chan_signer = local_chan.get_signer();
chan_signer.get_enforcement_state().last_holder_commitment -= 1;
(
chan_signer
.release_commitment_secret(
INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64 + 1,
)
.unwrap(),
chan_signer
.get_per_commitment_point(
INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64,
&secp_ctx,
)
.unwrap(),
)
};
let remote_point = {
let per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[1], nodes[0], per_peer_lock, peer_state_lock, chan_id);
let chan_signer = channel.as_funded().unwrap().get_signer();
chan_signer
.get_per_commitment_point(
INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64,
&secp_ctx,
)
.unwrap()
};
let local_chan_balance = node_0_balance_sat
- HTLC_AMT_SAT * MIN_AFFORDABLE_HTLC_COUNT as u64
- 2 * crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI
- chan_utils::commit_tx_fee_sat(
FEERATE_PER_KW,
MIN_AFFORDABLE_HTLC_COUNT,
&channel_type,
);
let accepted_htlc_info = HTLCOutputInCommitment {
offered: false,
amount_msat: HTLC_AMT_SAT * 1000,
cltv_expiry,
payment_hash: payment_hash_0_1,
transaction_output_index: None,
};
htlcs.push(accepted_htlc_info);
let commitment_number = INITIAL_COMMITMENT_NUMBER - MIN_AFFORDABLE_HTLC_COUNT as u64;
let res = {
let per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, chan_id);
let chan_signer = channel.as_funded().unwrap().get_signer();
let commitment_tx = CommitmentTransaction::new(
commitment_number,
&remote_point,
node_1_balance_sat,
local_chan_balance,
FEERATE_PER_KW,
htlcs,
&channel.funding().channel_transaction_parameters.as_counterparty_broadcastable(),
&secp_ctx,
);
let params = &channel.funding().channel_transaction_parameters;
chan_signer
.sign_counterparty_commitment(
params,
&commitment_tx,
Vec::new(),
Vec::new(),
&secp_ctx,
)
.unwrap()
};
let commit_signed_msg = msgs::CommitmentSigned {
channel_id: chan_id,
signature: res.0,
htlc_signatures: res.1,
funding_txid: None,
};
nodes[1].node.handle_commitment_signed(node_a_id, &commit_signed_msg);
let _ = nodes[1].node.get_and_clear_pending_msg_events();
let raa_msg = msgs::RevokeAndACK {
channel_id: chan_id,
per_commitment_secret: local_secret,
next_per_commitment_point: next_local_point,
release_htlc_message_paths: Vec::new(),
};
nodes[1].node.handle_revoke_and_ack(node_a_id, &raa_msg);
expect_and_process_pending_htlcs(&nodes[1], false);
expect_htlc_handling_failed_destinations!(
nodes[1].node.get_and_clear_pending_events(),
&[HTLCHandlingFailureType::Receive { payment_hash: payment_hash_0_1 }]
);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates: msgs::CommitmentUpdate { ref update_fail_htlcs, .. },
..
} => {
assert_eq!(update_fail_htlcs.len(), 1);
update_fail_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
};
nodes[1].logger.assert_log(
"lightning::ln::channel",
"Attempting to fail HTLC due to fee spike buffer violation. Rebalancing is required."
.to_string(),
1,
);
check_added_monitors(&nodes[1], 3);
}
}
#[xtest(feature = "_externalize_tests")]
fn test_create_channel_to_trusted_peer_0reserve() {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
let channel_type = do_test_create_channel_to_trusted_peer_0reserve(config.clone());
assert_eq!(channel_type, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies());
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
let channel_type = do_test_create_channel_to_trusted_peer_0reserve(config.clone());
assert_eq!(channel_type, ChannelTypeFeatures::anchors_zero_fee_commitments());
}
fn do_test_create_channel_to_trusted_peer_0reserve(mut config: UserConfig) -> ChannelTypeFeatures {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let channel_value_sat = 100_000;
let temp_channel_id = nodes[0]
.node
.create_channel_to_trusted_peer_0reserve(node_b_id, channel_value_sat, 0, 42, None, None)
.unwrap();
let mut open_channel_message =
get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id);
handle_and_accept_open_channel(&nodes[1], node_a_id, &open_channel_message);
let mut accept_channel_message =
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id);
nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_message);
let funding_tx = sign_funding_transaction(&nodes[0], &nodes[1], 100_000, temp_channel_id);
let funding_msgs =
create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &funding_tx);
create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_msgs.0);
let details = &nodes[0].node.list_channels()[0];
let reserve_sat = details.unspendable_punishment_reserve.unwrap();
assert_ne!(reserve_sat, 0);
let channel_type = details.channel_type.clone().unwrap();
let feerate_per_kw = details.feerate_sat_per_1000_weight.unwrap();
let anchors_sat =
if channel_type == ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() {
2 * 330
} else {
0
};
let reserved_commit_tx_fee_sat = chan_utils::commit_tx_fee_sat(
feerate_per_kw,
2, &channel_type,
);
let max_outbound_htlc_sat =
channel_value_sat - anchors_sat - reserved_commit_tx_fee_sat - reserve_sat;
assert_eq!(details.next_outbound_htlc_limit_msat, max_outbound_htlc_sat * 1000);
send_payment(&nodes[0], &[&nodes[1]], max_outbound_htlc_sat * 1000);
let details = &nodes[1].node.list_channels()[0];
assert_eq!(details.unspendable_punishment_reserve.unwrap(), 0);
assert_eq!(details.next_outbound_htlc_limit_msat, max_outbound_htlc_sat * 1000);
send_payment(&nodes[1], &[&nodes[0]], max_outbound_htlc_sat * 1000);
channel_type
}
#[xtest(feature = "_externalize_tests")]
fn test_accept_inbound_channel_from_trusted_peer_0reserve() {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
let channel_type = do_test_accept_inbound_channel_from_trusted_peer_0reserve(config.clone());
assert_eq!(channel_type, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies());
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
let channel_type = do_test_accept_inbound_channel_from_trusted_peer_0reserve(config.clone());
assert_eq!(channel_type, ChannelTypeFeatures::anchors_zero_fee_commitments());
}
fn do_test_accept_inbound_channel_from_trusted_peer_0reserve(
mut config: UserConfig,
) -> ChannelTypeFeatures {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let channel_value_sat = 100_000;
nodes[0].node.create_channel(node_b_id, channel_value_sat, 0, 42, None, None).unwrap();
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id);
nodes[1].node.handle_open_channel(node_a_id, &open_channel);
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::OpenChannelRequest { temporary_channel_id: chan_id, .. } => {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer(
&chan_id,
&node_a_id,
0,
TrustedChannelFeatures::ZeroReserve,
None,
)
.unwrap();
},
_ => panic!("Unexpected event"),
};
let mut accept_channel_msg =
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id);
nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_msg);
let (chan_id, tx, _) = create_funding_transaction(&nodes[0], &node_b_id, channel_value_sat, 42);
nodes[0].node.funding_transaction_generated(chan_id, node_b_id, tx.clone()).unwrap();
nodes[1].node.handle_funding_created(
node_a_id,
&get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id),
);
check_added_monitors(&nodes[1], 1);
expect_channel_pending_event(&nodes[1], &node_a_id);
nodes[0].node.handle_funding_signed(
node_b_id,
&get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id),
);
check_added_monitors(&nodes[0], 1);
expect_channel_pending_event(&nodes[0], &node_b_id);
let (channel_ready, _channel_id) =
create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
let (announcement, as_update, bs_update) =
create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
let details = &nodes[0].node.list_channels()[0];
assert_eq!(details.unspendable_punishment_reserve.unwrap(), 0);
let channel_type = details.channel_type.clone().unwrap();
let feerate_per_kw = details.feerate_sat_per_1000_weight.unwrap();
let anchors_sat =
if channel_type == ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() {
2 * 330
} else {
0
};
let reserved_commit_tx_fee_sat = chan_utils::commit_tx_fee_sat(
feerate_per_kw,
2, &channel_type,
);
let max_outbound_htlc_sat = channel_value_sat - reserved_commit_tx_fee_sat - anchors_sat;
assert_eq!(details.next_outbound_htlc_limit_msat, max_outbound_htlc_sat * 1000);
send_payment(&nodes[0], &[&nodes[1]], max_outbound_htlc_sat * 1000);
let details = &nodes[1].node.list_channels()[0];
let reserve_sat = details.unspendable_punishment_reserve.unwrap();
assert_ne!(reserve_sat, 0);
let max_outbound_htlc_sat = max_outbound_htlc_sat - reserve_sat;
assert_eq!(details.next_outbound_htlc_limit_msat, max_outbound_htlc_sat * 1000);
send_payment(&nodes[1], &[&nodes[0]], max_outbound_htlc_sat * 1000);
channel_type
}
#[xtest(feature = "_externalize_tests")]
fn test_0reserve_no_outputs() {
do_test_0reserve_no_outputs_keyed_anchors(true);
do_test_0reserve_no_outputs_keyed_anchors(false);
do_test_0reserve_no_outputs_p2a_anchor();
}
pub(crate) fn setup_0reserve_no_outputs_channels<'a, 'b, 'c, 'd>(
nodes: &'a Vec<Node<'b, 'c, 'd>>, channel_value_sat: u64, dust_limit_satoshis: u64,
) -> (ChannelId, Transaction) {
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
nodes[0]
.node
.create_channel_to_trusted_peer_0reserve(node_b_id, channel_value_sat, 0, 42, None, None)
.unwrap();
let mut open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id);
open_channel.common_fields.dust_limit_satoshis = dust_limit_satoshis;
nodes[1].node.handle_open_channel(node_a_id, &open_channel);
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::OpenChannelRequest { temporary_channel_id: chan_id, .. } => {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer(
&chan_id,
&node_a_id,
0,
TrustedChannelFeatures::ZeroReserve,
None,
)
.unwrap();
},
_ => panic!("Unexpected event"),
};
let mut accept_channel_msg =
get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id);
accept_channel_msg.common_fields.dust_limit_satoshis = dust_limit_satoshis;
nodes[0].node.handle_accept_channel(node_b_id, &accept_channel_msg);
let (chan_id, tx, _) = create_funding_transaction(&nodes[0], &node_b_id, channel_value_sat, 42);
nodes[0].node.funding_transaction_generated(chan_id, node_b_id, tx.clone()).unwrap();
nodes[1].node.handle_funding_created(
node_a_id,
&get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id),
);
check_added_monitors(&nodes[1], 1);
expect_channel_pending_event(&nodes[1], &node_a_id);
nodes[0].node.handle_funding_signed(
node_b_id,
&get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, node_a_id),
);
check_added_monitors(&nodes[0], 1);
expect_channel_pending_event(&nodes[0], &node_b_id);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
nodes[0].tx_broadcaster.clear();
let (channel_ready, channel_id) =
create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx);
let (announcement, as_update, bs_update) =
create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
update_nodes_with_chan_announce(nodes, 0, 1, &announcement, &as_update, &bs_update);
{
let mut per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, channel_id);
if let Some(mut chan) = channel.as_funded_mut() {
chan.context.holder_dust_limit_satoshis = dust_limit_satoshis;
} else {
panic!("Unexpected Channel phase");
}
}
{
let mut per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[1], nodes[0], per_peer_lock, peer_state_lock, channel_id);
if let Some(mut chan) = channel.as_funded_mut() {
chan.context.holder_dust_limit_satoshis = dust_limit_satoshis;
} else {
panic!("Unexpected Channel phase");
}
}
(channel_id, tx)
}
fn manually_trigger_update_fail_htlc<'a, 'b, 'c, 'd>(
nodes: &'a Vec<Node<'b, 'c, 'd>>, channel_id: ChannelId, value_to_self_msat: u64,
dust_limit_satoshis: u64, payment_hash: PaymentHash,
htlcs_in_commitment: Vec<HTLCOutputInCommitment>, can_afford_but_reserve_is_breached: bool,
) {
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let secp_ctx = Secp256k1::new();
let feerate_per_kw = get_feerate!(nodes[0], nodes[1], channel_id);
let (local_secret, next_local_point) = {
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
let chan_lock = per_peer_state.get(&node_b_id).unwrap().lock().unwrap();
let local_chan =
chan_lock.channel_by_id.get(&channel_id).and_then(Channel::as_funded).unwrap();
let chan_signer = local_chan.get_signer();
let commit_number = chan_signer.get_enforcement_state().last_holder_commitment;
chan_signer.get_enforcement_state().last_holder_commitment -= 1;
(
chan_signer.release_commitment_secret(commit_number).unwrap(),
chan_signer.get_per_commitment_point(commit_number - 2, &secp_ctx).unwrap(),
)
};
let (remote_commit_number, remote_point) = {
let per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[1], nodes[0], per_peer_lock, peer_state_lock, channel_id);
let chan_signer = channel.as_funded().unwrap().get_signer();
let commit_number = chan_signer.get_enforcement_state().last_holder_commitment;
let remote_point =
chan_signer.get_per_commitment_point(commit_number - 1, &secp_ctx).unwrap();
(commit_number - 1, remote_point)
};
let res = {
let per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, channel_id);
let chan_signer = channel.as_funded().unwrap().get_signer();
let (commitment_tx, _stats) = SpecTxBuilder {}.build_commitment_transaction(
false,
remote_commit_number,
&remote_point,
&channel.funding().channel_transaction_parameters,
&secp_ctx,
value_to_self_msat,
htlcs_in_commitment,
feerate_per_kw,
dust_limit_satoshis,
&nodes[0].logger,
);
let params = &channel.funding().channel_transaction_parameters;
chan_signer
.sign_counterparty_commitment(params, &commitment_tx, Vec::new(), Vec::new(), &secp_ctx)
.unwrap()
};
let commit_signed_msg = msgs::CommitmentSigned {
channel_id,
signature: res.0,
htlc_signatures: res.1,
funding_txid: None,
};
nodes[1].node.handle_commitment_signed(node_a_id, &commit_signed_msg);
let _ = nodes[1].node.get_and_clear_pending_msg_events();
let raa_msg = msgs::RevokeAndACK {
channel_id,
per_commitment_secret: local_secret,
next_per_commitment_point: next_local_point,
release_htlc_message_paths: Vec::new(),
};
nodes[1].node.handle_revoke_and_ack(node_a_id, &raa_msg);
expect_and_process_pending_htlcs(&nodes[1], false);
expect_htlc_handling_failed_destinations!(
nodes[1].node.get_and_clear_pending_events(),
&[HTLCHandlingFailureType::Receive { payment_hash }]
);
let events = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
match events[0] {
MessageSendEvent::UpdateHTLCs {
updates: msgs::CommitmentUpdate { ref update_fail_htlcs, .. },
..
} => {
assert_eq!(update_fail_htlcs.len(), 1);
update_fail_htlcs[0].clone()
},
_ => panic!("Unexpected event"),
};
let log_string =
if can_afford_but_reserve_is_breached {
String::from("Attempting to fail HTLC due to fee spike buffer violation. Rebalancing is required.")
} else {
String::from("Attempting to fail HTLC due to balance exhausted on remote commitment")
};
nodes[1].logger.assert_log("lightning::ln::channel", log_string, 1);
check_added_monitors(&nodes[1], 3);
}
fn do_test_0reserve_no_outputs_keyed_anchors(payment_success: bool) {
let mut config = test_default_channel_config();
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let _node_b_id = nodes[1].node.get_our_node_id();
let feerate_per_kw = 253;
let anchors_sat = 2 * ANCHOR_OUTPUT_VALUE_SATOSHI;
let dust_limit_satoshis: u64 = 546;
let channel_value_sat = {
let min_channel_size =
commit_tx_fee_sat(feerate_per_kw, MIN_AFFORDABLE_HTLC_COUNT, &channel_type)
+ anchors_sat + dust_limit_satoshis;
assert!(min_channel_size > 1002);
min_channel_size
};
let (channel_id, _funding_tx) =
setup_0reserve_no_outputs_channels(&nodes, channel_value_sat, dust_limit_satoshis);
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
let max_dust_htlc_sat = dust_limit_satoshis - 1;
assert!(
channel_value_sat
.saturating_sub(anchors_sat)
.saturating_sub(commit_tx_fee_sat(feerate_per_kw, 0, &channel_type))
.saturating_sub(max_dust_htlc_sat)
< dust_limit_satoshis
);
let capacity_minus_max_commitment_fee_sat =
channel_value_sat - anchors_sat - commit_tx_fee_sat(feerate_per_kw, 2, &channel_type);
assert!(capacity_minus_max_commitment_fee_sat > dust_limit_satoshis);
let details_0 = &nodes[0].node.list_channels()[0];
assert_eq!(details_0.next_outbound_htlc_minimum_msat, dust_limit_satoshis * 1000);
assert_eq!(
details_0.next_outbound_htlc_limit_msat,
capacity_minus_max_commitment_fee_sat * 1000
);
let sender_amount_msat = dust_limit_satoshis * 1000;
let (sender_amount_msat, receiver_amount_msat) = if payment_success {
(sender_amount_msat, sender_amount_msat)
} else {
(sender_amount_msat, sender_amount_msat - 1)
};
if payment_success {
send_payment(&nodes[0], &[&nodes[1]], sender_amount_msat);
assert_eq!(
nodes[1].node.list_channels()[0].next_outbound_htlc_limit_msat,
sender_amount_msat
);
send_payment(&nodes[1], &[&nodes[0]], sender_amount_msat);
} else {
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], sender_amount_msat);
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height + 1;
let onion_keys =
onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv);
let recipient_onion_fields =
RecipientOnionFields::secret_only(payment_secret, sender_amount_msat);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::test_build_onion_payloads(
&route.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
assert_eq!(htlc_msat, sender_amount_msat);
let onion_packet =
onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash)
.unwrap();
let msg = msgs::UpdateAddHTLC {
channel_id,
htlc_id: 0,
amount_msat: receiver_amount_msat,
payment_hash,
cltv_expiry: htlc_cltv,
onion_routing_packet: onion_packet,
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
nodes[1].logger.assert_log_contains(
"lightning::ln::channelmanager",
"Remote HTLC add would overdraw remaining funds",
3,
);
assert_eq!(nodes[1].node.list_channels().len(), 0);
let err_msg = check_closed_broadcast(&nodes[1], 1, true).pop().unwrap();
assert_eq!(err_msg.data, "Remote HTLC add would overdraw remaining funds");
let reason = ClosureReason::ProcessingError {
err: "Remote HTLC add would overdraw remaining funds".to_string(),
};
check_added_monitors(&nodes[1], 1);
check_closed_event(&nodes[1], 1, reason, &[node_a_id], channel_value_sat);
}
}
fn do_test_0reserve_no_outputs_p2a_anchor() {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::anchors_zero_fee_commitments();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _node_a_id = nodes[0].node.get_our_node_id();
let _node_b_id = nodes[1].node.get_our_node_id();
let dust_limit_satoshis: u64 = 546;
let channel_value_sat = 1000;
let _channel_id =
setup_0reserve_no_outputs_channels(&nodes, channel_value_sat, dust_limit_satoshis);
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
let max_dust_htlc_sat = dust_limit_satoshis - 1;
assert!(channel_value_sat.saturating_sub(max_dust_htlc_sat) < dust_limit_satoshis);
let details_0 = &nodes[0].node.list_channels()[0];
assert_eq!(details_0.next_outbound_htlc_minimum_msat, 1000);
assert_eq!(details_0.next_outbound_htlc_limit_msat, channel_value_sat * 1000);
let sender_amount_msat = max_dust_htlc_sat * 1000;
send_payment(&nodes[0], &[&nodes[1]], sender_amount_msat);
assert_eq!(nodes[1].node.list_channels()[0].next_outbound_htlc_limit_msat, sender_amount_msat);
send_payment(&nodes[1], &[&nodes[0]], sender_amount_msat);
}
#[xtest(feature = "_externalize_tests")]
pub fn test_0reserve_force_close_with_single_p2a_output() {
do_test_0reserve_force_close_with_single_p2a_output(false);
do_test_0reserve_force_close_with_single_p2a_output(true);
}
fn do_test_0reserve_force_close_with_single_p2a_output(high_feerate: bool) {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
let chanmon_cfgs = create_chanmon_cfgs(2);
if high_feerate {
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
*feerate_lock = 2500;
}
if high_feerate {
let mut feerate_lock = chanmon_cfgs[1].fee_estimator.sat_per_kw.lock().unwrap();
*feerate_lock = 2500;
}
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::anchors_zero_fee_commitments();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let coinbase_tx = provide_anchor_reserves(&nodes);
let _node_a_id = nodes[0].node.get_our_node_id();
let _node_b_id = nodes[1].node.get_our_node_id();
let dust_limit_satoshis: u64 = 546;
let channel_value_sat = 1002;
let (channel_id, funding_tx) =
setup_0reserve_no_outputs_channels(&nodes, channel_value_sat, dust_limit_satoshis);
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
let htlc_sat = channel_value_sat - dust_limit_satoshis + 1;
assert!(htlc_sat < dust_limit_satoshis);
route_payment(&nodes[0], &[&nodes[1]], htlc_sat * 1000);
let commitment_tx = get_local_commitment_txn!(nodes[0], channel_id).pop().unwrap();
let commitment_txid = commitment_tx.compute_txid();
let message = "Channel force-closed".to_owned();
nodes[0]
.node
.force_close_broadcasting_latest_txn(
&channel_id,
&nodes[1].node.get_our_node_id(),
message.clone(),
)
.unwrap();
check_closed_broadcast(&nodes[0], 1, true);
check_added_monitors(&nodes[0], 1);
let reason = ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(true), message };
check_closed_event(&nodes[0], 1, reason, &[nodes[1].node.get_our_node_id()], channel_value_sat);
let mut events = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events.pop().unwrap() {
Event::BumpTransaction(bump_event) => {
nodes[0].bump_tx_handler.handle_event(&bump_event);
},
_ => panic!("Unexpected event"),
}
let txns = nodes[0].tx_broadcaster.txn_broadcast();
if high_feerate {
assert_eq!(txns.len(), 2);
check_spends!(txns[1], txns[0], coinbase_tx);
assert!(txns[1].weight().to_wu() < TRUC_CHILD_MAX_WEIGHT);
assert_eq!(txns[1].input.len(), 2);
assert_eq!(txns[1].output.len(), 1);
assert_eq!(txns[0].compute_txid(), commitment_txid);
assert_eq!(txns[0].input.len(), 1);
assert_eq!(txns[0].output.len(), 1);
assert_eq!(txns[0].output[0].value, Amount::from_sat(240));
assert_eq!(txns[0].output[0].script_pubkey, shared_anchor_script_pubkey());
check_spends!(txns[0], funding_tx);
nodes[0].logger.assert_log(
"lightning::events::bump_transaction",
format!(
"Broadcasting anchor transaction {} to bump channel close with txid {}",
txns[1].compute_txid(),
txns[0].compute_txid()
),
1,
);
} else {
assert_eq!(txns.len(), 1);
assert_eq!(txns[0].compute_txid(), commitment_txid);
assert_eq!(txns[0].input.len(), 1);
assert_eq!(txns[0].output.len(), 1);
assert_eq!(txns[0].output[0].value, Amount::from_sat(240));
assert_eq!(txns[0].output[0].script_pubkey, shared_anchor_script_pubkey());
check_spends!(txns[0], funding_tx);
let weight = txns[0].weight();
let feerate = (channel_value_sat - 240) * 1000 / weight.to_wu();
nodes[0].logger.assert_log(
"lightning::events::bump_transaction",
format!(
"Pre-signed commitment {} already has feerate {} sat/kW above required 253 sat/kW, broadcasting.",
txns[0].compute_txid(),
feerate,
),
1,
);
}
}
#[xtest(feature = "_externalize_tests")]
fn test_0reserve_zero_conf_combined() {
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let mut config = test_default_channel_config();
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let node_b_id = nodes[1].node.get_our_node_id();
let channel_value_sat = 100_000;
nodes[0].node.create_channel(node_b_id, channel_value_sat, 0, 42, None, None).unwrap();
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, node_b_id);
nodes[1].node.handle_open_channel(node_a_id, &open_channel);
let events = nodes[1].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::OpenChannelRequest { temporary_channel_id: chan_id, .. } => {
nodes[1]
.node
.accept_inbound_channel_from_trusted_peer(
&chan_id,
&node_a_id,
0,
TrustedChannelFeatures::ZeroConfZeroReserve,
None,
)
.unwrap();
},
_ => panic!("Unexpected event"),
};
let accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, node_a_id);
assert_eq!(accept_channel.common_fields.minimum_depth, 0);
nodes[0].node.handle_accept_channel(node_b_id, &accept_channel);
let (temporary_channel_id, tx, _) =
create_funding_transaction(&nodes[0], &node_b_id, channel_value_sat, 42);
nodes[0]
.node
.funding_transaction_generated(temporary_channel_id, node_b_id, tx.clone())
.unwrap();
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, node_b_id);
nodes[1].node.handle_funding_created(node_a_id, &funding_created);
check_added_monitors(&nodes[1], 1);
let bs_signed_locked = nodes[1].node.get_and_clear_pending_msg_events();
assert_eq!(bs_signed_locked.len(), 2);
let as_channel_ready;
match &bs_signed_locked[0] {
MessageSendEvent::SendFundingSigned { node_id, msg } => {
assert_eq!(*node_id, node_a_id);
nodes[0].node.handle_funding_signed(node_b_id, &msg);
expect_channel_pending_event(&nodes[0], &node_b_id);
expect_channel_pending_event(&nodes[1], &node_a_id);
check_added_monitors(&nodes[0], 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
nodes[0].tx_broadcaster.clear();
as_channel_ready =
get_event_msg!(nodes[0], MessageSendEvent::SendChannelReady, node_b_id);
},
_ => panic!("Unexpected event"),
}
match &bs_signed_locked[1] {
MessageSendEvent::SendChannelReady { node_id, msg } => {
assert_eq!(*node_id, node_a_id);
nodes[0].node.handle_channel_ready(node_b_id, &msg);
expect_channel_ready_event(&nodes[0], &node_b_id);
},
_ => panic!("Unexpected event"),
}
nodes[1].node.handle_channel_ready(node_a_id, &as_channel_ready);
expect_channel_ready_event(&nodes[1], &node_a_id);
let as_channel_update =
get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, node_b_id);
let bs_channel_update =
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, node_a_id);
nodes[0].node.handle_channel_update(node_b_id, &bs_channel_update);
nodes[1].node.handle_channel_update(node_a_id, &as_channel_update);
assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
assert_eq!(nodes[1].node.list_usable_channels().len(), 1);
let details_a = &nodes[0].node.list_channels()[0];
let node_0_reserve = details_a.unspendable_punishment_reserve.unwrap();
let node_0_max_htlc = details_a.next_outbound_htlc_limit_msat;
let channel_type = details_a.channel_type.clone().unwrap();
assert_eq!(node_0_reserve, 0);
assert_eq!(channel_type, ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies());
assert!(details_a.is_usable);
assert_eq!(details_a.confirmations.unwrap(), 0);
assert_eq!(
node_0_max_htlc,
(channel_value_sat - commit_tx_fee_sat(253, 2, &channel_type) - 2 * 330) * 1000
);
let details_b = &nodes[1].node.list_channels()[0];
assert_ne!(details_b.unspendable_punishment_reserve.unwrap(), 0);
assert!(details_b.is_usable);
send_payment(&nodes[0], &[&nodes[1]], node_0_max_htlc);
let details_b = &nodes[1].node.list_channels()[0];
let node_1_reserve = details_b.unspendable_punishment_reserve.unwrap();
let node_1_max_htlc = details_b.next_outbound_htlc_limit_msat;
assert_eq!(node_1_reserve, 1000);
assert_eq!(node_1_max_htlc, node_0_max_htlc - node_1_reserve * 1000);
send_payment(&nodes[1], &[&nodes[0]], node_1_max_htlc);
}
#[xtest(feature = "_externalize_tests")]
fn test_outbound_vs_available_capacity_outbound_htlc_limit_spiked_feerate() {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::only_static_remote_key();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let _node_a_id = nodes[0].node.get_our_node_id();
let _node_b_id = nodes[1].node.get_our_node_id();
const FEERATE: u32 = 253;
const MULTIPLE: u32 = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
const SPIKED_FEERATE: u32 = FEERATE * MULTIPLE;
const DUST_LIMIT_MSAT: u64 = 354 * 1000;
const CHANNEL_VALUE_MSAT: u64 = 10_000 * 1000;
const NODE_0_VALUE_TO_SELF_MSAT: u64 = 5000 * 1000;
const NODE_1_VALUE_TO_SELF_MSAT: u64 = 5000 * 1000;
const CHANNEL_RESERVE_MSAT: u64 = 1000 * 1000;
const SPIKED_DUST_HTLC_MSAT: u64 = 688 * 1000;
const HTLC_SPIKE_DUST_LIMIT_MSAT: u64 = 689 * 1000;
let htlc_timeout_spike_tx_fee_msat =
second_stage_tx_fees_sat(&channel_type, SPIKED_FEERATE).1 * 1000;
assert_eq!(HTLC_SPIKE_DUST_LIMIT_MSAT, DUST_LIMIT_MSAT + htlc_timeout_spike_tx_fee_msat);
let channel_id =
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, CHANNEL_VALUE_MSAT / 1000, 0)
.2;
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
{
let mut per_peer_lock;
let mut peer_state_lock;
let channel =
get_channel_ref!(nodes[0], nodes[1], per_peer_lock, peer_state_lock, channel_id);
assert_eq!(channel.context().holder_dust_limit_satoshis * 1000, DUST_LIMIT_MSAT);
}
send_payment(&nodes[0], &[&nodes[1]], NODE_1_VALUE_TO_SELF_MSAT);
let count_total_htlcs = |details: &ChannelDetails| {
details.pending_outbound_htlcs.len() + details.pending_inbound_htlcs.len()
};
let count_node_0_nondust_htlcs = || {
let mut txs = get_local_commitment_txn!(nodes[0], channel_id);
let commitment_tx = &txs[0];
commitment_tx
.output
.iter()
.filter(|output| output.value.to_sat() * 1000 == SPIKED_DUST_HTLC_MSAT)
.count()
};
let count_node_1_nondust_htlcs = || {
let mut txs = get_local_commitment_txn!(nodes[1], channel_id);
let commitment_tx = &txs[0];
commitment_tx
.output
.iter()
.filter(|output| output.value.to_sat() * 1000 == SPIKED_DUST_HTLC_MSAT)
.count()
};
{
let reserved_fee_sat = commit_tx_fee_sat(SPIKED_FEERATE, 2, &channel_type);
let node_0_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT - CHANNEL_RESERVE_MSAT;
let node_0_available_capacity_msat =
node_0_outbound_capacity_msat - reserved_fee_sat * 1000;
let node_0_details = &nodes[0].node.list_channels()[0];
assert_eq!(node_0_details.outbound_capacity_msat, node_0_outbound_capacity_msat);
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, node_0_available_capacity_msat);
assert_eq!(count_total_htlcs(&node_0_details), 0);
assert_eq!(count_node_0_nondust_htlcs(), 0);
}
for i in 1..3 {
route_payment(&nodes[0], &[&nodes[1]], SPIKED_DUST_HTLC_MSAT);
let max_reserved_fee_msat = commit_tx_fee_sat(SPIKED_FEERATE, 2 + i, &channel_type) * 1000;
let node_0_outbound_capacity_msat =
NODE_0_VALUE_TO_SELF_MSAT - SPIKED_DUST_HTLC_MSAT * i as u64 - CHANNEL_RESERVE_MSAT;
let node_0_available_capacity_msat = node_0_outbound_capacity_msat - max_reserved_fee_msat;
assert!(node_0_available_capacity_msat >= HTLC_SPIKE_DUST_LIMIT_MSAT);
let node_0_details = &nodes[0].node.list_channels()[0];
assert_eq!(node_0_details.outbound_capacity_msat, node_0_outbound_capacity_msat);
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, node_0_available_capacity_msat);
assert_eq!(count_total_htlcs(&node_0_details), i);
assert_eq!(count_node_0_nondust_htlcs(), i);
}
let node_0_details = &nodes[0].node.list_channels()[0];
let local_nondust_htlc_count = 2;
assert_eq!(count_total_htlcs(&node_0_details), local_nondust_htlc_count);
assert_eq!(count_node_0_nondust_htlcs(), local_nondust_htlc_count);
assert_eq!(count_node_1_nondust_htlcs(), local_nondust_htlc_count);
let node_0_outbound_capacity_msat = node_0_details.outbound_capacity_msat;
for i in 1..3 {
route_payment(&nodes[1], &[&nodes[0]], SPIKED_DUST_HTLC_MSAT);
let node_1_outbound_capacity_msat =
NODE_1_VALUE_TO_SELF_MSAT - SPIKED_DUST_HTLC_MSAT * i as u64 - CHANNEL_RESERVE_MSAT;
assert!(node_1_outbound_capacity_msat >= HTLC_SPIKE_DUST_LIMIT_MSAT);
let node_1_details = &nodes[1].node.list_channels()[0];
assert_eq!(node_1_details.outbound_capacity_msat, node_1_outbound_capacity_msat);
assert_eq!(node_1_details.next_outbound_htlc_limit_msat, node_1_outbound_capacity_msat);
let nondust_htlc_count = 2 + i;
assert_eq!(count_node_0_nondust_htlcs(), nondust_htlc_count);
assert_eq!(count_node_1_nondust_htlcs(), nondust_htlc_count);
assert_eq!(
nodes[0].node.list_channels()[0].outbound_capacity_msat,
node_0_outbound_capacity_msat
);
let max_reserved_fee_msat =
commit_tx_fee_sat(SPIKED_FEERATE, nondust_htlc_count + 2, &channel_type) * 1000;
assert_eq!(
nodes[0].node.list_channels()[0].next_outbound_htlc_limit_msat,
node_0_outbound_capacity_msat - max_reserved_fee_msat
);
}
}
#[xtest(feature = "_externalize_tests")]
fn test_fail_cannot_afford_dust_htlcs_at_spike_multiple_if_nondust_at_base_feerate() {
let mut config = test_default_channel_config();
config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = false;
config.channel_handshake_config.negotiate_anchor_zero_fee_commitments = false;
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::only_static_remote_key();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let node_a_id = nodes[0].node.get_our_node_id();
let _node_b_id = nodes[1].node.get_our_node_id();
const FEERATE: u32 = 253;
const MULTIPLE: u32 = FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE as u32;
const SPIKED_FEERATE: u32 = FEERATE * MULTIPLE;
const DUST_LIMIT_MSAT: u64 = 354 * 1000;
const CHANNEL_VALUE_MSAT: u64 = 10_000 * 1000;
const NODE_0_VALUE_TO_SELF_MSAT: u64 = 5_000 * 1000;
const NODE_1_VALUE_TO_SELF_MSAT: u64 = 5_000 * 1000;
const CHANNEL_RESERVE_MSAT: u64 = 1_000 * 1_000;
let channel_id = create_announced_chan_between_nodes_with_value(
&nodes,
0,
1,
CHANNEL_VALUE_MSAT / 1000,
NODE_1_VALUE_TO_SELF_MSAT,
)
.2;
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
const SPIKED_DUST_HTLC_MSAT: u64 = 688 * 1000;
const HTLC_SPIKE_DUST_LIMIT_MSAT: u64 = 689 * 1000;
let htlc_timeout_spike_tx_fee_msat =
second_stage_tx_fees_sat(&channel_type, SPIKED_FEERATE).1 * 1000;
assert_eq!(HTLC_SPIKE_DUST_LIMIT_MSAT, DUST_LIMIT_MSAT + htlc_timeout_spike_tx_fee_msat);
let htlc_timeout_tx_fee_msat = second_stage_tx_fees_sat(&channel_type, FEERATE).1 * 1000;
let htlc_dust_limit_msat = DUST_LIMIT_MSAT + htlc_timeout_tx_fee_msat;
assert!(SPIKED_DUST_HTLC_MSAT > htlc_dust_limit_msat);
let mut sent_htlcs_count: usize = 0;
let mut payment_hashes = Vec::new();
while nodes[0].node.list_channels()[0].next_outbound_htlc_limit_msat >= htlc_dust_limit_msat {
let (_preimage, hash, _secret, _id) =
route_payment(&nodes[0], &[&nodes[1]], SPIKED_DUST_HTLC_MSAT);
payment_hashes.push(hash);
sent_htlcs_count += 1;
}
assert_eq!(sent_htlcs_count, 4);
let node_0_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT
- sent_htlcs_count as u64 * SPIKED_DUST_HTLC_MSAT
- CHANNEL_RESERVE_MSAT;
let node_0_details = &nodes[0].node.list_channels()[0];
assert_eq!(node_0_details.outbound_capacity_msat, node_0_outbound_capacity_msat);
let min_reserved_fee_msat =
commit_tx_fee_sat(SPIKED_FEERATE, sent_htlcs_count + 1, &channel_type) * 1000;
let node_0_available_capacity_msat = node_0_outbound_capacity_msat - min_reserved_fee_msat;
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, node_0_available_capacity_msat);
let spiked_commit_tx_fee_msat = commit_tx_fee_sat(SPIKED_FEERATE, 0, &channel_type) * 1000;
assert!((node_0_outbound_capacity_msat - SPIKED_DUST_HTLC_MSAT)
.checked_sub(spiked_commit_tx_fee_msat)
.is_some());
let real_commit_tx_fee_msat = commit_tx_fee_sat(FEERATE, 5, &channel_type) * 1000;
assert!((node_0_outbound_capacity_msat - SPIKED_DUST_HTLC_MSAT)
.checked_sub(real_commit_tx_fee_msat)
.is_some());
let expected_commit_tx_fee_msat = commit_tx_fee_sat(SPIKED_FEERATE, 5, &channel_type) * 1000;
assert!((node_0_outbound_capacity_msat - SPIKED_DUST_HTLC_MSAT)
.checked_sub(expected_commit_tx_fee_msat)
.is_none());
let sender_amount_msat = node_0_available_capacity_msat;
let receiver_amount_msat = SPIKED_DUST_HTLC_MSAT;
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], sender_amount_msat);
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv);
let recipient_onion_fields =
RecipientOnionFields::secret_only(payment_secret, sender_amount_msat);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::test_build_onion_payloads(
&route.paths[0],
&recipient_onion_fields,
cur_height,
&None,
None,
None,
)
.unwrap();
assert_eq!(htlc_msat, sender_amount_msat);
let onion_packet =
onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash)
.unwrap();
let msg = msgs::UpdateAddHTLC {
channel_id,
htlc_id: sent_htlcs_count as u64,
amount_msat: receiver_amount_msat,
payment_hash,
cltv_expiry: htlc_cltv,
onion_routing_packet: onion_packet,
skimmed_fee_msat: None,
blinding_point: None,
hold_htlc: None,
accountable: None,
};
nodes[1].node.handle_update_add_htlc(node_a_id, &msg);
let htlcs_in_tx = vec![
HTLCOutputInCommitment {
offered: false,
cltv_expiry: 81,
payment_hash: payment_hashes.iter().find(|hash| hash.0[0] == 0x75).unwrap().clone(),
amount_msat: 688_000,
transaction_output_index: Some(0),
},
HTLCOutputInCommitment {
offered: false,
cltv_expiry: 81,
payment_hash: payment_hashes.iter().find(|hash| hash.0[0] == 0x64).unwrap().clone(),
amount_msat: 688_000,
transaction_output_index: Some(1),
},
HTLCOutputInCommitment {
offered: false,
cltv_expiry: 81,
payment_hash,
amount_msat: 688_000,
transaction_output_index: Some(2),
},
HTLCOutputInCommitment {
offered: false,
cltv_expiry: 81,
payment_hash: payment_hashes.iter().find(|hash| hash.0[0] == 0x72).unwrap().clone(),
amount_msat: 688_000,
transaction_output_index: Some(3),
},
HTLCOutputInCommitment {
offered: false,
cltv_expiry: 81,
payment_hash: payment_hashes.iter().find(|hash| hash.0[0] == 0x66).unwrap().clone(),
amount_msat: 688_000,
transaction_output_index: Some(4),
},
];
manually_trigger_update_fail_htlc(
&nodes,
channel_id,
NODE_0_VALUE_TO_SELF_MSAT,
DUST_LIMIT_MSAT / 1000,
payment_hash,
htlcs_in_tx,
true,
);
}
#[xtest(feature = "_externalize_tests")]
fn test_available_balances_both_commitments_dust_on_funder_commitment() {
let mut config = test_default_channel_config();
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
const FEERATE: u32 = 253;
const TOTAL_ANCHORS_MSAT: u64 = 2 * 330_000;
const NODE_0_DUST_LIMIT_MSAT: u64 = 10_000 * 1000;
const NODE_1_DUST_LIMIT_MSAT: u64 = 354 * 1000;
const CHANNEL_VALUE_MSAT: u64 = 50_000 * 1000;
const NODE_0_VALUE_TO_SELF_MSAT: u64 = 25_000 * 1000;
const NODE_1_VALUE_TO_SELF_MSAT: u64 = 25_000 * 1000;
const NODE_0_SELECTED_CHANNEL_RESERVE_MSAT: u64 = 1_000 * 1_000;
const NODE_1_SELECTED_CHANNEL_RESERVE_MSAT: u64 = 10_000 * 1_000;
let channel_id = create_announced_chan_between_nodes_with_value(
&nodes,
0,
1,
CHANNEL_VALUE_MSAT / 1000,
NODE_1_VALUE_TO_SELF_MSAT,
)
.2;
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[0], nodes[1], per_peer_state_lock, peer_state_lock, channel_id);
chan.context_mut().holder_dust_limit_satoshis = NODE_0_DUST_LIMIT_MSAT / 1000;
chan.funding_mut().counterparty_selected_channel_reserve_satoshis =
Some(NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000);
assert_eq!(chan.context().counterparty_dust_limit_satoshis, NODE_1_DUST_LIMIT_MSAT / 1000);
assert_eq!(
chan.funding().holder_selected_channel_reserve_satoshis,
NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000
);
}
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[1], nodes[0], per_peer_state_lock, peer_state_lock, channel_id);
chan.context_mut().counterparty_dust_limit_satoshis = NODE_0_DUST_LIMIT_MSAT / 1000;
chan.funding_mut().holder_selected_channel_reserve_satoshis =
NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000;
assert_eq!(chan.context().holder_dust_limit_satoshis, NODE_1_DUST_LIMIT_MSAT / 1000);
assert_eq!(
chan.funding().counterparty_selected_channel_reserve_satoshis,
Some(NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000)
);
}
const SNEAKY_HTLC_MSAT: u64 = 5_000_000;
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
let node_1_details = &nodes[1].node.list_channels()[0];
let expected_outbound_capacity_msat =
NODE_1_VALUE_TO_SELF_MSAT - SNEAKY_HTLC_MSAT - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT;
assert_eq!(node_1_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let expected_available_capacity_msat = expected_outbound_capacity_msat;
assert_eq!(node_1_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let expected_splice_out_max =
NODE_1_VALUE_TO_SELF_MSAT / 1000 - SNEAKY_HTLC_MSAT / 1000 - NODE_1_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_1_details.next_splice_out_maximum_sat, expected_splice_out_max);
let node_0_details = &nodes[0].node.list_channels()[0];
let expected_outbound_capacity_msat =
NODE_0_VALUE_TO_SELF_MSAT - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT - TOTAL_ANCHORS_MSAT;
assert_eq!(node_0_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let expected_available_capacity_msat =
expected_outbound_capacity_msat - commit_tx_fee_sat(FEERATE, 3, &channel_type) * 1000;
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let expected_splice_out_max = NODE_0_VALUE_TO_SELF_MSAT / 1000
- TOTAL_ANCHORS_MSAT / 1000
- commit_tx_fee_sat(FEERATE, 2, &channel_type)
- NODE_0_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_0_details.next_splice_out_maximum_sat, expected_splice_out_max);
let node_0_payment_msat = expected_available_capacity_msat;
send_payment(&nodes[0], &[&nodes[1]], node_0_payment_msat);
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
let node_0_details = &nodes[0].node.list_channels()[0];
let expected_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT
- node_0_payment_msat
- NODE_1_SELECTED_CHANNEL_RESERVE_MSAT
- TOTAL_ANCHORS_MSAT;
assert_eq!(node_0_details.outbound_capacity_msat, expected_outbound_capacity_msat);
assert_eq!(
node_0_details.outbound_capacity_msat,
commit_tx_fee_sat(FEERATE, 3, &channel_type) * 1000
);
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, 0);
assert_eq!(node_0_details.next_splice_out_maximum_sat, 0);
let node_1_details = &nodes[1].node.list_channels()[0];
let expected_outbound_capacity_msat = NODE_1_VALUE_TO_SELF_MSAT + node_0_payment_msat
- 3 * SNEAKY_HTLC_MSAT
- NODE_0_SELECTED_CHANNEL_RESERVE_MSAT;
assert_eq!(node_1_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let (_htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat) =
second_stage_tx_fees_sat(&channel_type, FEERATE);
let expected_available_capacity_msat =
(NODE_1_DUST_LIMIT_MSAT / 1000 + htlc_timeout_tx_fee_sat) * 1000 - 1;
assert_eq!(node_1_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let expected_splice_out_max = NODE_1_VALUE_TO_SELF_MSAT / 1000 + node_0_payment_msat / 1000
- 3 * SNEAKY_HTLC_MSAT / 1000
- NODE_1_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_1_details.next_splice_out_maximum_sat, expected_splice_out_max);
}
#[xtest(feature = "_externalize_tests")]
fn test_available_balances_both_commitments_dust_on_fundee_commitment() {
let mut config = test_default_channel_config();
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
config.channel_handshake_config.announced_channel_max_inbound_htlc_value_in_flight_percentage =
100;
let channel_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config.clone()), Some(config)]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
const FEERATE: u32 = 253;
const TOTAL_ANCHORS_MSAT: u64 = 2 * 330_000;
const NODE_0_DUST_LIMIT_MSAT: u64 = 354 * 1000;
const NODE_1_DUST_LIMIT_MSAT: u64 = 10_000 * 1000;
const CHANNEL_VALUE_MSAT: u64 = 50_000 * 1000;
const NODE_0_VALUE_TO_SELF_MSAT: u64 = 25_000 * 1000;
const NODE_1_VALUE_TO_SELF_MSAT: u64 = 25_000 * 1000;
const NODE_0_SELECTED_CHANNEL_RESERVE_MSAT: u64 = 10_000 * 1_000;
const NODE_1_SELECTED_CHANNEL_RESERVE_MSAT: u64 = 1_000 * 1_000;
let channel_id = create_announced_chan_between_nodes_with_value(
&nodes,
0,
1,
CHANNEL_VALUE_MSAT / 1000,
NODE_1_VALUE_TO_SELF_MSAT,
)
.2;
assert_eq!(nodes[0].node.list_channels()[0].channel_type.as_ref().unwrap(), &channel_type);
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[0], nodes[1], per_peer_state_lock, peer_state_lock, channel_id);
chan.context_mut().counterparty_dust_limit_satoshis = NODE_1_DUST_LIMIT_MSAT / 1000;
chan.funding_mut().holder_selected_channel_reserve_satoshis =
NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000;
assert_eq!(chan.context().holder_dust_limit_satoshis, NODE_0_DUST_LIMIT_MSAT / 1000);
assert_eq!(
chan.funding().counterparty_selected_channel_reserve_satoshis,
Some(NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000)
);
}
{
let per_peer_state_lock;
let mut peer_state_lock;
let chan =
get_channel_ref!(nodes[1], nodes[0], per_peer_state_lock, peer_state_lock, channel_id);
chan.context_mut().holder_dust_limit_satoshis = NODE_1_DUST_LIMIT_MSAT / 1000;
chan.funding_mut().counterparty_selected_channel_reserve_satoshis =
Some(NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000);
assert_eq!(chan.context().counterparty_dust_limit_satoshis, NODE_0_DUST_LIMIT_MSAT / 1000);
assert_eq!(
chan.funding().holder_selected_channel_reserve_satoshis,
NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000
);
}
const SNEAKY_HTLC_MSAT: u64 = 5_000_000;
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
let node_1_details = &nodes[1].node.list_channels()[0];
let expected_outbound_capacity_msat =
NODE_1_VALUE_TO_SELF_MSAT - SNEAKY_HTLC_MSAT - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT;
assert_eq!(node_1_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let expected_available_capacity_msat = expected_outbound_capacity_msat;
assert_eq!(node_1_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let expected_splice_out_max =
NODE_1_VALUE_TO_SELF_MSAT / 1000 - SNEAKY_HTLC_MSAT / 1000 - NODE_1_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_1_details.next_splice_out_maximum_sat, expected_splice_out_max);
let node_0_details = &nodes[0].node.list_channels()[0];
let expected_outbound_capacity_msat =
NODE_0_VALUE_TO_SELF_MSAT - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT - TOTAL_ANCHORS_MSAT;
assert_eq!(node_0_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let expected_splice_out_max = NODE_0_VALUE_TO_SELF_MSAT / 1000
- TOTAL_ANCHORS_MSAT / 1000
- commit_tx_fee_sat(FEERATE, 2, &channel_type)
- NODE_0_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_0_details.next_splice_out_maximum_sat, expected_splice_out_max);
let expected_available_capacity_msat =
expected_outbound_capacity_msat - commit_tx_fee_sat(FEERATE, 3, &channel_type) * 1000;
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let node_0_payment_msat = expected_available_capacity_msat;
send_payment(&nodes[0], &[&nodes[1]], node_0_payment_msat);
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
route_payment(&nodes[1], &[&nodes[0]], SNEAKY_HTLC_MSAT);
let node_0_details = &nodes[0].node.list_channels()[0];
let expected_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT
- node_0_payment_msat
- NODE_1_SELECTED_CHANNEL_RESERVE_MSAT
- TOTAL_ANCHORS_MSAT;
assert_eq!(node_0_details.outbound_capacity_msat, expected_outbound_capacity_msat);
assert_eq!(
node_0_details.outbound_capacity_msat,
commit_tx_fee_sat(FEERATE, 3, &channel_type) * 1000
);
assert_eq!(node_0_details.next_outbound_htlc_limit_msat, 0);
let local_balance_before_fee_sat =
NODE_0_VALUE_TO_SELF_MSAT / 1000 - node_0_payment_msat / 1000 - TOTAL_ANCHORS_MSAT / 1000;
let post_splice_delta_above_reserve = commit_tx_fee_sat(FEERATE, 4, &channel_type);
let divident_sat = local_balance_before_fee_sat * 100 + 100
- (post_splice_delta_above_reserve * 100)
- CHANNEL_VALUE_MSAT / 1000;
let expected_splice_out_max = (divident_sat - 1) / 99;
assert_eq!(node_0_details.next_splice_out_maximum_sat, expected_splice_out_max);
let node_1_details = &nodes[1].node.list_channels()[0];
let expected_outbound_capacity_msat = NODE_1_VALUE_TO_SELF_MSAT + node_0_payment_msat
- 3 * SNEAKY_HTLC_MSAT
- NODE_0_SELECTED_CHANNEL_RESERVE_MSAT;
assert_eq!(node_1_details.outbound_capacity_msat, expected_outbound_capacity_msat);
let (htlc_success_tx_fee_sat, _htlc_timeout_tx_fee_sat) =
second_stage_tx_fees_sat(&channel_type, FEERATE);
let expected_available_capacity_msat =
(NODE_0_DUST_LIMIT_MSAT / 1000 + htlc_success_tx_fee_sat) * 1000 - 1;
assert_eq!(node_1_details.next_outbound_htlc_limit_msat, expected_available_capacity_msat);
let expected_splice_out_max = NODE_1_VALUE_TO_SELF_MSAT / 1000 + node_0_payment_msat / 1000
- 3 * SNEAKY_HTLC_MSAT / 1000
- NODE_1_DUST_LIMIT_MSAT / 1000;
assert_eq!(node_1_details.next_splice_out_maximum_sat, expected_splice_out_max);
}