Skip to content

Commit 61a6b09

Browse files
committed
basic dust complaint
temp: alice and bob
1 parent 4a0ee9f commit 61a6b09

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10604,6 +10604,110 @@ fn test_nondust_htlc_fees_are_dust() {
1060410604
expect_payment_failed_conditions(&nodes[2], payment_hash, false, PaymentFailedConditions::new());
1060510605
}
1060610606

10607+
fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures) {
10608+
// Tests the increase in htlc dust exposure due to the excess mining fees of a single non-dust
10609+
// HTLC on the commitment transaction.
10610+
// Node 0 (funder) brings the dust exposure up to the threshold exactly using dust htlcs, then
10611+
// sends one single non-dust htlc. Node 1 (fundee) should complain about too much dust exposure.
10612+
10613+
let chanmon_cfgs = create_chanmon_cfgs(2);
10614+
10615+
const BASE_FEERATE: u64 = 253;
10616+
const EXCESS_FEERATE: u64 = 275;
10617+
const DELTA_FEERATE: u64 = EXCESS_FEERATE - BASE_FEERATE;
10618+
10619+
const DUST_HTLC_COUNT: u64 = 4;
10620+
const DUST_HTLC_MSAT: u64 = 125_000;
10621+
const BASE_DUST_LIMIT_MSAT: u64 = DUST_HTLC_COUNT * DUST_HTLC_MSAT;
10622+
10623+
const NON_DUST_HTLC_MSAT: u64 = 4_000_000;
10624+
10625+
// only_static_remote_key: 500_000 + 22 * 724 / 1_000 * 1_000 = 515_000
10626+
// anchors_zero_htlc_fee: 500_000 + 22 * 1_124 / 1_000 * 1_000 = 524_000
10627+
let threshold_dust_exposure_msat = BASE_DUST_LIMIT_MSAT + DELTA_FEERATE * commitment_tx_base_weight(&features) / 1000 * 1000;
10628+
10629+
// only_static_remote_key: 500_000 + 22 * (724 + 172) / 1000 * 1000 + 22 * 663 = 533_586
10630+
// anchors_zero_htlc_fee: 500_000 + 22 * (1_124 + 172) / 1000 * 1000 = 528_000
10631+
let mut expected_dust_exposure_msat = BASE_DUST_LIMIT_MSAT + DELTA_FEERATE * (commitment_tx_base_weight(&features) + COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000 * 1000;
10632+
10633+
if features == ChannelTypeFeatures::only_static_remote_key() {
10634+
expected_dust_exposure_msat += DELTA_FEERATE * htlc_timeout_tx_weight(&features);
10635+
assert_eq!(threshold_dust_exposure_msat, 515_000);
10636+
assert_eq!(expected_dust_exposure_msat, 533_586);
10637+
} else {
10638+
assert_eq!(threshold_dust_exposure_msat, 524_000);
10639+
assert_eq!(expected_dust_exposure_msat, 528_000);
10640+
}
10641+
10642+
{
10643+
// Set the feerate of the channel funder above the `dust_exposure_limiting_feerate` of
10644+
// the fundee. This delta means that the fundee will add the mining fees of the commitment and
10645+
// htlc transactions in excess of its `dust_exposure_limiting_feerate` to its total dust htlc
10646+
// exposure.
10647+
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
10648+
*feerate_lock = EXCESS_FEERATE as u32;
10649+
}
10650+
10651+
let mut default_config = test_default_channel_config();
10652+
if features == ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() {
10653+
default_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
10654+
// in addition to the one above, this setting is also needed to create an anchor channel
10655+
default_config.manually_accept_inbound_channels = true;
10656+
}
10657+
let mut fixed_limit_config = default_config.clone();
10658+
fixed_limit_config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FixedLimitMsat(threshold_dust_exposure_msat);
10659+
10660+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
10661+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(default_config), Some(fixed_limit_config)]);
10662+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
10663+
10664+
//create_announced_chan_between_nodes(&nodes, 0, 1);
10665+
create_chan_between_nodes_with_value(&nodes[0], &nodes[1], 100_000, 50_000_000);
10666+
10667+
// Skip the router complaint when node 1 will attempt to pay node 0
10668+
let (route_1_0, payment_hash_1_0, _, payment_secret_1_0) = get_route_and_payment_hash!(nodes[1], nodes[0], NON_DUST_HTLC_MSAT);
10669+
10670+
// Bring node 1's dust htlc exposure right up to its limit
10671+
for _ in 0..DUST_HTLC_COUNT {
10672+
route_payment(&nodes[0], &[&nodes[1]], DUST_HTLC_MSAT);
10673+
}
10674+
10675+
// Send an additional non-dust htlc, and check for the complaint exactly
10676+
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], NON_DUST_HTLC_MSAT);
10677+
nodes[0].node.send_payment_with_route(route, payment_hash,
10678+
RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
10679+
check_added_monitors!(nodes[0], 1);
10680+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
10681+
assert_eq!(events.len(), 1);
10682+
let payment_event = SendEvent::from_event(events.remove(0));
10683+
nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
10684+
commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
10685+
expect_pending_htlcs_forwardable!(nodes[1]);
10686+
expect_htlc_handling_failed_destinations!(nodes[1].node.get_and_clear_pending_events(), &[HTLCDestination::FailedPayment { payment_hash }]);
10687+
nodes[1].logger.assert_log("lightning::ln::channel",
10688+
format!("Cannot accept value that would put our exposure to tx fee dust at {} over the limit {} on counterparty commitment tx",
10689+
expected_dust_exposure_msat, threshold_dust_exposure_msat), 1);
10690+
let _ = nodes[1].node.get_and_clear_pending_msg_events();
10691+
10692+
unwrap_send_err!(nodes[1], nodes[1].node.send_payment_with_route(route_1_0, payment_hash_1_0,
10693+
RecipientOnionFields::secret_only(payment_secret_1_0), PaymentId(payment_hash_1_0.0)
10694+
), true, APIError::ChannelUnavailable { .. }, {});
10695+
// only_static_remote_key: counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_weight = 354000 + (2530 + 275) * 703 / 1000 * 1000 = 2325000
10696+
// anchors_zero_htlc_fee: counterparty_dust_limit_satoshis = 354000
10697+
let htlc_max = if features == ChannelTypeFeatures::only_static_remote_key() { 2325000 } else { 354000 };
10698+
nodes[1].logger.assert_log("lightning::ln::outbound_payment",
10699+
format!("Failed to send along path due to error: Channel unavailable: Cannot send more than our next-HTLC maximum - {} msat", htlc_max), 1);
10700+
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
10701+
10702+
let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
10703+
added_monitors.clear();
10704+
}
10705+
10706+
#[test]
10707+
fn test_nondust_htlc_fees_dust_exposure_delta() {
10708+
do_test_nondust_htlc_fees_dust_exposure_delta(ChannelTypeFeatures::only_static_remote_key());
10709+
do_test_nondust_htlc_fees_dust_exposure_delta(ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies());
10710+
}
1060710711

1060810712
#[test]
1060910713
fn test_non_final_funding_tx() {

0 commit comments

Comments
 (0)