diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 132ff95f6bb..00e3856133c 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -347,7 +347,6 @@ pub fn do_test(data: &[u8], logger: &Arc) { let mut config = UserConfig::default(); config.channel_options.fee_proportional_millionths = slice_to_be32(get_slice!(4)); config.channel_options.announced_channel = get_slice!(1)[0] != 0; - config.peer_channel_config_limits.min_dust_limit_satoshis = 0; let network = Network::Bitcoin; let genesis_hash = genesis_block(network).block_hash(); let params = ChainParameters { diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 60512c7ad25..1289493eb63 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -429,7 +429,6 @@ pub const OUR_MAX_HTLCS: u16 = 50; //TODO /// really allow for this, so instead we're stuck closing it out at that point. const UNCONF_THRESHOLD: u32 = 6; const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4 -const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?) #[cfg(not(test))] const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; @@ -454,6 +453,12 @@ pub const MAX_FUNDING_SATOSHIS: u64 = 1 << 24; /// upper bound to avoid negotiation conflicts with other implementations. pub const MAX_DUST_LIMIT_SATOSHIS: u64 = 2 * 330; +/// A typical p2wsh output is 43 bytes big to which Core's `GetDustThreshold()` sums up a minimal +/// spend of 67 bytes (even if a p2wsh witnessScript might be *effectively* smaller), `dustRelayFee` +/// is set to 3000sat/kb, thus 110 * 3000 / 1000 = 330. Per-protocol rules, all time-sensitive outputs +/// are p2wsh, a value of 330 sats is the lower bound desired to ensure good propagation of transactions. +pub const HOLDER_DUST_LIMIT_SATOSHIS: u64 = 330; + /// Used to return a simple Error back to ChannelManager. Will get converted to a /// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our /// channel_id in ChannelManager. @@ -497,10 +502,6 @@ impl Channel { cmp::min(channel_value_satoshis, cmp::max(q, 1000)) //TODO } - fn derive_holder_dust_limit_satoshis(at_open_background_feerate: u32) -> u64 { - cmp::max(at_open_background_feerate as u64 * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO - } - // Constructors: pub fn new_outbound(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result, APIError> where K::Target: KeysInterface, @@ -521,7 +522,7 @@ impl Channel { return Err(APIError::APIMisuseError {err: format!("Configured with an unreasonable our_to_self_delay ({}) putting user funds at risks", holder_selected_contest_delay)}); } let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if Channel::::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis) < Channel::::derive_holder_dust_limit_satoshis(background_feerate) { + if Channel::::get_holder_selected_channel_reserve_satoshis(channel_value_satoshis) < HOLDER_DUST_LIMIT_SATOSHIS { return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate}); } @@ -579,7 +580,7 @@ impl Channel { feerate_per_kw: feerate, counterparty_dust_limit_satoshis: 0, - holder_dust_limit_satoshis: Channel::::derive_holder_dust_limit_satoshis(background_feerate), + holder_dust_limit_satoshis: HOLDER_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: 0, counterparty_selected_channel_reserve_satoshis: 0, counterparty_htlc_minimum_msat: 0, @@ -697,8 +698,8 @@ impl Channel { if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs { return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs))); } - if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.min_dust_limit_satoshis))); + if msg.dust_limit_satoshis < HOLDER_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, HOLDER_DUST_LIMIT_SATOSHIS))); } if msg.dust_limit_satoshis > MAX_DUST_LIMIT_SATOSHIS { return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS))); @@ -717,13 +718,12 @@ impl Channel { let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - let holder_dust_limit_satoshis = Channel::::derive_holder_dust_limit_satoshis(background_feerate); let holder_selected_channel_reserve_satoshis = Channel::::get_holder_selected_channel_reserve_satoshis(msg.funding_satoshis); - if holder_selected_channel_reserve_satoshis < holder_dust_limit_satoshis { - return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, holder_dust_limit_satoshis))); + if holder_selected_channel_reserve_satoshis < HOLDER_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("Suitable channel reserve not found. remote_channel_reserve was ({}). dust_limit_satoshis is ({}).", holder_selected_channel_reserve_satoshis, HOLDER_DUST_LIMIT_SATOSHIS))); } - if msg.channel_reserve_satoshis < holder_dust_limit_satoshis { - return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, holder_dust_limit_satoshis))); + if msg.channel_reserve_satoshis < HOLDER_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("channel_reserve_satoshis ({}) is smaller than our dust limit ({})", msg.channel_reserve_satoshis, HOLDER_DUST_LIMIT_SATOSHIS))); } if holder_selected_channel_reserve_satoshis < msg.dust_limit_satoshis { return Err(ChannelError::Close(format!("Dust limit ({}) too high for the channel reserve we require the remote to keep ({})", msg.dust_limit_satoshis, holder_selected_channel_reserve_satoshis))); @@ -815,7 +815,7 @@ impl Channel { feerate_per_kw: msg.feerate_per_kw, channel_value_satoshis: msg.funding_satoshis, counterparty_dust_limit_satoshis: msg.dust_limit_satoshis, - holder_dust_limit_satoshis, + holder_dust_limit_satoshis: HOLDER_DUST_LIMIT_SATOSHIS, counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), counterparty_selected_channel_reserve_satoshis: msg.channel_reserve_satoshis, counterparty_htlc_minimum_msat: msg.htlc_minimum_msat, @@ -1436,8 +1436,8 @@ impl Channel { if msg.max_accepted_htlcs < config.peer_channel_config_limits.min_max_accepted_htlcs { return Err(ChannelError::Close(format!("max_accepted_htlcs ({}) is less than the user specified limit ({})", msg.max_accepted_htlcs, config.peer_channel_config_limits.min_max_accepted_htlcs))); } - if msg.dust_limit_satoshis < config.peer_channel_config_limits.min_dust_limit_satoshis { - return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, config.peer_channel_config_limits.min_dust_limit_satoshis))); + if msg.dust_limit_satoshis < HOLDER_DUST_LIMIT_SATOSHIS { + return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is less than the user specified limit ({})", msg.dust_limit_satoshis, HOLDER_DUST_LIMIT_SATOSHIS))); } if msg.dust_limit_satoshis > MAX_DUST_LIMIT_SATOSHIS { return Err(ChannelError::Close(format!("dust_limit_satoshis ({}) is greater than the implementation limit ({})", msg.dust_limit_satoshis, MAX_DUST_LIMIT_SATOSHIS))); @@ -4818,7 +4818,6 @@ mod tests { // Create Node B's channel by receiving Node A's open_channel message // Make sure A's dust limit is as we expect. let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); - assert_eq!(open_channel_msg.dust_limit_satoshis, 1560); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), &open_channel_msg, 7, &config).unwrap(); @@ -4826,6 +4825,7 @@ mod tests { let mut accept_channel_msg = node_b_chan.get_accept_channel(); accept_channel_msg.dust_limit_satoshis = 546; node_a_chan.accept_channel(&accept_channel_msg, &config, InitFeatures::known()).unwrap(); + node_a_chan.holder_dust_limit_satoshis = 1560; // Put some inbound and outbound HTLCs in A's channel. let htlc_amount_msat = 11_092_000; // put an amount below A's effective dust limit but above B's. diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 9ea45ebeca1..54ae1387849 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -1793,7 +1793,7 @@ fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() { // transaction fee with 0 HTLCs (183 sats)). create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 98817000, InitFeatures::known(), InitFeatures::known()); - let dust_amt = 546000; // Dust amount + let dust_amt = 329000; // Dust amount // In the previous code, routing this dust payment would cause nodes[0] to perceive a channel // reserve violation even though it's a dust HTLC and therefore shouldn't count towards the // commitment transaction fee. diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 328be2bf054..23b9069b07c 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -95,16 +95,6 @@ pub struct ChannelHandshakeLimits { /// /// Default value: 0. pub min_max_accepted_htlcs: u16, - /// Outputs below a certain value will not be added to on-chain transactions. The dust value is - /// required to always be higher than this value so this only applies to HTLC outputs (and - /// potentially to-self outputs before any payments have been made). - /// Thus, HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain. - /// This setting allows you to set a minimum dust limit for their commitment transactions, - /// reflecting the reality that tiny outputs are not considered standard transactions and will - /// not propagate through the Bitcoin network. - /// - /// Default value: 546, the current dust limit on the Bitcoin network. - pub min_dust_limit_satoshis: u64, /// Before a channel is usable the funding transaction will need to be confirmed by at least a /// certain number of blocks, specified by the node which is not the funder (as the funder can /// assume they aren't going to double-spend themselves). @@ -136,7 +126,6 @@ impl Default for ChannelHandshakeLimits { min_max_htlc_value_in_flight_msat: 0, max_channel_reserve_satoshis: ::max_value(), min_max_accepted_htlcs: 0, - min_dust_limit_satoshis: 546, max_minimum_depth: 144, force_announced_channel_preference: true, their_to_self_delay: MAX_LOCAL_BREAKDOWN_TIMEOUT,