X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_tests.rs;h=271ff541a84981733090b30600956886c2845d40;hb=a358ba2e68c84d19e70d1d45d3f677eaf324e09d;hp=cba17b5eb38361ada8b790d5982e2bd5495d57eb;hpb=1d9a70952958bc02f426f1a04a1cfcc4bc6b0cff;p=rust-lightning diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index cba17b5e..271ff541 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -35,7 +35,7 @@ use crate::util::test_utils; use crate::util::errors::APIError; use crate::util::ser::{Writeable, ReadableArgs}; use crate::util::string::UntrustedString; -use crate::util::config::UserConfig; +use crate::util::config::{UserConfig, MaxDustHTLCExposure}; use bitcoin::hash_types::BlockHash; use bitcoin::blockdata::script::{Builder, Script}; @@ -1393,6 +1393,7 @@ fn test_fee_spike_violation_fails_htlc() { payment_hash: payment_hash, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet, + skimmed_fee_msat: None, }; nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg); @@ -1582,6 +1583,7 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { payment_hash: payment_hash, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet, + skimmed_fee_msat: None, }; nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &msg); @@ -1758,6 +1760,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { payment_hash: our_payment_hash_1, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet, + skimmed_fee_msat: None, }; nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg); @@ -3410,6 +3413,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() { payment_hash, cltv_expiry, onion_routing_packet, + skimmed_fee_msat: None, }; nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &update_add_htlc); } @@ -6259,6 +6263,7 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() { payment_hash: our_payment_hash, cltv_expiry: htlc_cltv, onion_routing_packet: onion_packet.clone(), + skimmed_fee_msat: None, }; for i in 0..50 { @@ -9510,7 +9515,7 @@ enum ExposureEvent { AtUpdateFeeOutbound, } -fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool) { +fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_event: ExposureEvent, on_holder_tx: bool, multiplier_dust_limit: bool) { // Test that we properly reject dust HTLC violating our `max_dust_htlc_exposure_msat` // policy. // @@ -9525,7 +9530,12 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e let chanmon_cfgs = create_chanmon_cfgs(2); let mut config = test_default_channel_config(); - config.channel_config.max_dust_htlc_exposure_msat = 5_000_000; // default setting value + config.channel_config.max_dust_htlc_exposure = if multiplier_dust_limit { + // Default test fee estimator rate is 253 sat/kw, so we set the multiplier to 5_000_000 / 253 + // to get roughly the same initial value as the default setting when this test was + // originally written. + MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253) + } else { MaxDustHTLCExposure::FixedLimitMsat(5_000_000) }; // initial default setting value let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); @@ -9569,20 +9579,21 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000); - let dust_buffer_feerate = { + let (dust_buffer_feerate, max_dust_htlc_exposure_msat) = { let per_peer_state = nodes[0].node.per_peer_state.read().unwrap(); let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap(); let chan = chan_lock.channel_by_id.get(&channel_id).unwrap(); - chan.context.get_dust_buffer_feerate(None) as u64 + (chan.context.get_dust_buffer_feerate(None) as u64, + chan.context.get_max_dust_htlc_exposure_msat(&LowerBoundedFeeEstimator(nodes[0].fee_estimator))) }; let dust_outbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_timeout_tx_weight(&channel_type_features) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000; - let dust_outbound_htlc_on_holder_tx: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat; + let dust_outbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_outbound_htlc_on_holder_tx_msat; let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(&channel_type_features) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000; - let dust_inbound_htlc_on_holder_tx: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat; + let dust_inbound_htlc_on_holder_tx: u64 = max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat; let dust_htlc_on_counterparty_tx: u64 = 4; - let dust_htlc_on_counterparty_tx_msat: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx; + let dust_htlc_on_counterparty_tx_msat: u64 = max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx; if on_holder_tx { if dust_outbound_balance { @@ -9634,7 +9645,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e ), true, APIError::ChannelUnavailable { .. }, {}); } } else if exposure_breach_event == ExposureEvent::AtHTLCReception { - let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 1 }); + let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 4 }); nodes[1].node.send_payment_with_route(&route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[1], 1); @@ -9647,18 +9658,24 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e // Outbound dust balance: 6399 sats let dust_inbound_overflow = dust_inbound_htlc_on_holder_tx_msat * (dust_inbound_htlc_on_holder_tx + 1); let dust_outbound_overflow = dust_outbound_htlc_on_holder_tx_msat * dust_outbound_htlc_on_holder_tx + dust_inbound_htlc_on_holder_tx_msat; - nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow }, config.channel_config.max_dust_htlc_exposure_msat), 1); + nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow }, max_dust_htlc_exposure_msat), 1); } else { // Outbound dust balance: 5200 sats nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", - dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx - 1) + dust_htlc_on_counterparty_tx_msat + 1, - config.channel_config.max_dust_htlc_exposure_msat), 1); + dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx - 1) + dust_htlc_on_counterparty_tx_msat + 4, + max_dust_htlc_exposure_msat), 1); } } else if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound { route.paths[0].hops.last_mut().unwrap().fee_msat = 2_500_000; - nodes[0].node.send_payment_with_route(&route, payment_hash, - RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + // For the multiplier dust exposure limit, since it scales with feerate, + // we need to add a lot of HTLCs that will become dust at the new feerate + // to cross the threshold. + for _ in 0..20 { + let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(1_000), None); + nodes[0].node.send_payment_with_route(&route, payment_hash, + RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap(); + } { let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap(); *feerate_lock = *feerate_lock * 10; @@ -9673,20 +9690,25 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e added_monitors.clear(); } +fn do_test_max_dust_htlc_exposure_by_threshold_type(multiplier_dust_limit: bool) { + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, false, multiplier_dust_limit); + do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, true, multiplier_dust_limit); +} + #[test] fn test_max_dust_htlc_exposure() { - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, true); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, true); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, true); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCReception, false); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCForward, false); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, false); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtHTLCReception, true); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtHTLCForward, false); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, true); - do_test_max_dust_htlc_exposure(true, ExposureEvent::AtUpdateFeeOutbound, false); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, false); - do_test_max_dust_htlc_exposure(false, ExposureEvent::AtUpdateFeeOutbound, true); + do_test_max_dust_htlc_exposure_by_threshold_type(false); + do_test_max_dust_htlc_exposure_by_threshold_type(true); } #[test]