mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-03-15 15:39:09 +01:00
Merge pull request #2415 from wpaulino/update-fee-anchors
Add min mempool estimate for feerate updates on anchor channels
This commit is contained in:
commit
baf9731a21
4 changed files with 72 additions and 24 deletions
|
@ -78,7 +78,7 @@ impl FeeEstimator for FuzzEstimator {
|
|||
// Background feerate which is <= the minimum Normal feerate.
|
||||
match conf_target {
|
||||
ConfirmationTarget::HighPriority => MAX_FEE,
|
||||
ConfirmationTarget::Background => 253,
|
||||
ConfirmationTarget::Background|ConfirmationTarget::MempoolMinimum => 253,
|
||||
ConfirmationTarget::Normal => cmp::min(self.ret_val.load(atomic::Ordering::Acquire), MAX_FEE),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,15 +44,24 @@ pub trait BroadcasterInterface {
|
|||
fn broadcast_transactions(&self, txs: &[&Transaction]);
|
||||
}
|
||||
|
||||
/// An enum that represents the speed at which we want a transaction to confirm used for feerate
|
||||
/// An enum that represents the priority at which we want a transaction to confirm used for feerate
|
||||
/// estimation.
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum ConfirmationTarget {
|
||||
/// We are happy with this transaction confirming slowly when feerate drops some.
|
||||
/// We'd like a transaction to confirm in the future, but don't want to commit most of the fees
|
||||
/// required to do so yet. The remaining fees will come via a Child-Pays-For-Parent (CPFP) fee
|
||||
/// bump of the transaction.
|
||||
///
|
||||
/// The feerate returned should be the absolute minimum feerate required to enter most node
|
||||
/// mempools across the network. Note that if you are not able to obtain this feerate estimate,
|
||||
/// you should likely use the furthest-out estimate allowed by your fee estimator.
|
||||
MempoolMinimum,
|
||||
/// We are happy with a transaction confirming slowly, at least within a day or so worth of
|
||||
/// blocks.
|
||||
Background,
|
||||
/// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine.
|
||||
/// We'd like a transaction to confirm without major delayed, i.e., within the next 12-24 blocks.
|
||||
Normal,
|
||||
/// We'd like this transaction to confirm in the next few blocks.
|
||||
/// We'd like a transaction to confirm in the next few blocks.
|
||||
HighPriority,
|
||||
}
|
||||
|
||||
|
|
|
@ -2045,20 +2045,35 @@ struct CommitmentTxInfoCached {
|
|||
}
|
||||
|
||||
impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
|
||||
fn check_remote_fee<F: Deref, L: Deref>(fee_estimator: &LowerBoundedFeeEstimator<F>,
|
||||
feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L)
|
||||
-> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger,
|
||||
fn check_remote_fee<F: Deref, L: Deref>(
|
||||
channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
|
||||
feerate_per_kw: u32, cur_feerate_per_kw: Option<u32>, logger: &L
|
||||
) -> Result<(), ChannelError> where F::Target: FeeEstimator, L::Target: Logger,
|
||||
{
|
||||
// We only bound the fee updates on the upper side to prevent completely absurd feerates,
|
||||
// always accepting up to 25 sat/vByte or 10x our fee estimator's "High Priority" fee.
|
||||
// We generally don't care too much if they set the feerate to something very high, but it
|
||||
// could result in the channel being useless due to everything being dust.
|
||||
let upper_limit = cmp::max(250 * 25,
|
||||
fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 10);
|
||||
if feerate_per_kw as u64 > upper_limit {
|
||||
return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit)));
|
||||
// could result in the channel being useless due to everything being dust. This doesn't
|
||||
// apply to channels supporting anchor outputs since HTLC transactions are pre-signed with a
|
||||
// zero fee, so their fee is no longer considered to determine dust limits.
|
||||
if !channel_type.supports_anchors_zero_fee_htlc_tx() {
|
||||
let upper_limit = cmp::max(250 * 25,
|
||||
fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64 * 10);
|
||||
if feerate_per_kw as u64 > upper_limit {
|
||||
return Err(ChannelError::Close(format!("Peer's feerate much too high. Actual: {}. Our expected upper limit: {}", feerate_per_kw, upper_limit)));
|
||||
}
|
||||
}
|
||||
let lower_limit = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background);
|
||||
|
||||
// We can afford to use a lower bound with anchors than previously since we can now bump
|
||||
// fees when broadcasting our commitment. However, we must still make sure we meet the
|
||||
// minimum mempool feerate, until package relay is deployed, such that we can ensure the
|
||||
// commitment transaction propagates throughout node mempools on its own.
|
||||
let lower_limit_conf_target = if channel_type.supports_anchors_zero_fee_htlc_tx() {
|
||||
ConfirmationTarget::MempoolMinimum
|
||||
} else {
|
||||
ConfirmationTarget::Background
|
||||
};
|
||||
let lower_limit = fee_estimator.bounded_sat_per_1000_weight(lower_limit_conf_target);
|
||||
// Some fee estimators round up to the next full sat/vbyte (ie 250 sats per kw), causing
|
||||
// occasional issues with feerate disagreements between an initiator that wants a feerate
|
||||
// of 1.1 sat/vbyte and a receiver that wants 1.1 rounded up to 2. Thus, we always add 250
|
||||
|
@ -3688,7 +3703,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
|
|||
if self.context.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
|
||||
return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish".to_owned()));
|
||||
}
|
||||
Channel::<Signer>::check_remote_fee(fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?;
|
||||
Channel::<Signer>::check_remote_fee(&self.context.channel_type, fee_estimator, msg.feerate_per_kw, Some(self.context.feerate_per_kw), logger)?;
|
||||
let feerate_over_dust_buffer = msg.feerate_per_kw > self.context.get_dust_buffer_feerate(None);
|
||||
|
||||
self.context.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced));
|
||||
|
@ -5502,10 +5517,15 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
|
|||
let channel_type = Self::get_initial_channel_type(&config, their_features);
|
||||
debug_assert!(channel_type.is_subset(&channelmanager::provided_channel_type_features(&config)));
|
||||
|
||||
let feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
let commitment_conf_target = if channel_type.supports_anchors_zero_fee_htlc_tx() {
|
||||
ConfirmationTarget::MempoolMinimum
|
||||
} else {
|
||||
ConfirmationTarget::Normal
|
||||
};
|
||||
let commitment_feerate = fee_estimator.bounded_sat_per_1000_weight(commitment_conf_target);
|
||||
|
||||
let value_to_self_msat = channel_value_satoshis * 1000 - push_msat;
|
||||
let commitment_tx_fee = commit_tx_fee_msat(feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type);
|
||||
let commitment_tx_fee = commit_tx_fee_msat(commitment_feerate, MIN_AFFORDABLE_HTLC_COUNT, &channel_type);
|
||||
if value_to_self_msat < commitment_tx_fee {
|
||||
return Err(APIError::APIMisuseError{ err: format!("Funding amount ({}) can't even pay fee for initial commitment transaction fee of {}.", value_to_self_msat / 1000, commitment_tx_fee / 1000) });
|
||||
}
|
||||
|
@ -5599,7 +5619,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
|
|||
short_channel_id: None,
|
||||
channel_creation_height: current_chain_height,
|
||||
|
||||
feerate_per_kw: feerate,
|
||||
feerate_per_kw: commitment_feerate,
|
||||
counterparty_dust_limit_satoshis: 0,
|
||||
holder_dust_limit_satoshis: MIN_CHAN_DUST_LIMIT_SATOSHIS,
|
||||
counterparty_max_htlc_value_in_flight_msat: 0,
|
||||
|
@ -5753,7 +5773,12 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
|
|||
/// If we receive an error message, it may only be a rejection of the channel type we tried,
|
||||
/// not of our ability to open any channel at all. Thus, on error, we should first call this
|
||||
/// and see if we get a new `OpenChannel` message, otherwise the channel is failed.
|
||||
pub(crate) fn maybe_handle_error_without_close(&mut self, chain_hash: BlockHash) -> Result<msgs::OpenChannel, ()> {
|
||||
pub(crate) fn maybe_handle_error_without_close<F: Deref>(
|
||||
&mut self, chain_hash: BlockHash, fee_estimator: &LowerBoundedFeeEstimator<F>
|
||||
) -> Result<msgs::OpenChannel, ()>
|
||||
where
|
||||
F::Target: FeeEstimator
|
||||
{
|
||||
if !self.context.is_outbound() || self.context.channel_state != ChannelState::OurInitSent as u32 { return Err(()); }
|
||||
if self.context.channel_type == ChannelTypeFeatures::only_static_remote_key() {
|
||||
// We've exhausted our options
|
||||
|
@ -5770,6 +5795,7 @@ impl<Signer: WriteableEcdsaChannelSigner> OutboundV1Channel<Signer> {
|
|||
// whatever reason.
|
||||
if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() {
|
||||
self.context.channel_type.clear_anchors_zero_fee_htlc_tx();
|
||||
self.context.feerate_per_kw = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
assert!(!self.context.channel_transaction_parameters.channel_type_features.supports_anchors_nonzero_fee_htlc_tx());
|
||||
} else if self.context.channel_type.supports_scid_privacy() {
|
||||
self.context.channel_type.clear_scid_privacy();
|
||||
|
@ -6039,7 +6065,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> {
|
|||
if msg.htlc_minimum_msat >= full_channel_value_msat {
|
||||
return Err(ChannelError::Close(format!("Minimum htlc value ({}) was larger than full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat)));
|
||||
}
|
||||
Channel::<Signer>::check_remote_fee(fee_estimator, msg.feerate_per_kw, None, logger)?;
|
||||
Channel::<Signer>::check_remote_fee(&channel_type, fee_estimator, msg.feerate_per_kw, None, logger)?;
|
||||
|
||||
let max_counterparty_selected_contest_delay = u16::min(config.channel_handshake_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT);
|
||||
if msg.to_self_delay > max_counterparty_selected_contest_delay {
|
||||
|
@ -7441,7 +7467,8 @@ mod tests {
|
|||
// arithmetic, causing a panic with debug assertions enabled.
|
||||
let fee_est = TestFeeEstimator { fee_est: 42 };
|
||||
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_est);
|
||||
assert!(Channel::<InMemorySigner>::check_remote_fee(&bounded_fee_estimator,
|
||||
assert!(Channel::<InMemorySigner>::check_remote_fee(
|
||||
&ChannelTypeFeatures::only_static_remote_key(), &bounded_fee_estimator,
|
||||
u32::max_value(), None, &&test_utils::TestLogger::new()).is_err());
|
||||
}
|
||||
|
||||
|
|
|
@ -4258,13 +4258,19 @@ where
|
|||
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
|
||||
let mut should_persist = self.process_background_events();
|
||||
|
||||
let new_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
let normal_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
let min_mempool_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MempoolMinimum);
|
||||
|
||||
let per_peer_state = self.per_peer_state.read().unwrap();
|
||||
for (_cp_id, peer_state_mutex) in per_peer_state.iter() {
|
||||
let mut peer_state_lock = peer_state_mutex.lock().unwrap();
|
||||
let peer_state = &mut *peer_state_lock;
|
||||
for (chan_id, chan) in peer_state.channel_by_id.iter_mut() {
|
||||
let new_feerate = if chan.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
|
||||
min_mempool_feerate
|
||||
} else {
|
||||
normal_feerate
|
||||
};
|
||||
let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate);
|
||||
if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
|
||||
}
|
||||
|
@ -4294,7 +4300,8 @@ where
|
|||
PersistenceNotifierGuard::optionally_notify(&self.total_consistency_lock, &self.persistence_notifier, || {
|
||||
let mut should_persist = self.process_background_events();
|
||||
|
||||
let new_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
let normal_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||
let min_mempool_feerate = self.fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::MempoolMinimum);
|
||||
|
||||
let mut handle_errors: Vec<(Result<(), _>, _)> = Vec::new();
|
||||
let mut timed_out_mpp_htlcs = Vec::new();
|
||||
|
@ -4307,6 +4314,11 @@ where
|
|||
let pending_msg_events = &mut peer_state.pending_msg_events;
|
||||
let counterparty_node_id = *counterparty_node_id;
|
||||
peer_state.channel_by_id.retain(|chan_id, chan| {
|
||||
let new_feerate = if chan.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
|
||||
min_mempool_feerate
|
||||
} else {
|
||||
normal_feerate
|
||||
};
|
||||
let chan_needs_persist = self.update_channel_fee(chan_id, chan, new_feerate);
|
||||
if chan_needs_persist == NotifyOption::DoPersist { should_persist = NotifyOption::DoPersist; }
|
||||
|
||||
|
@ -7278,7 +7290,7 @@ where
|
|||
let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap();
|
||||
let peer_state = &mut *peer_state_lock;
|
||||
if let Some(chan) = peer_state.outbound_v1_channel_by_id.get_mut(&msg.channel_id) {
|
||||
if let Ok(msg) = chan.maybe_handle_error_without_close(self.genesis_hash) {
|
||||
if let Ok(msg) = chan.maybe_handle_error_without_close(self.genesis_hash, &self.fee_estimator) {
|
||||
peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel {
|
||||
node_id: *counterparty_node_id,
|
||||
msg,
|
||||
|
|
Loading…
Add table
Reference in a new issue