ext_from_hex("0c005e", &mut test);
// the funding transaction
ext_from_hex("020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions, one per line
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// by now client should have sent a channel_ready (CHECK 3: SendChannelReady to 03000000 for chan 3d000000)
// inbound read from peer id 0 of len 18
ext_from_hex("0c007d", &mut test);
// the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000
ext_from_hex("02000000013a000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200204b0000000000000000000000000000000000000000000000000000000000000014c0000000000000160014280000000000000000000000000000000000000005000020", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
//
// connect a block with one transaction of len 94
ext_from_hex("0c005e", &mut test);
// the HTLC timeout transaction
ext_from_hex("0200000001730000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020b20000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// connect a block with no transactions
ext_from_hex("0c0000", &mut test);
+ ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
// process the now-pending HTLC forward
ext_from_hex("07", &mut test);
}
}
+ pub fn check_for_stale_feerate<L: Logger>(&mut self, logger: &L, min_feerate: u32) -> Result<(), ClosureReason> {
+ if self.context.is_outbound() {
+ // While its possible our fee is too low for an outbound channel because we've been
+ // unable to increase the fee, we don't try to force-close directly here.
+ return Ok(());
+ }
+ if self.context.feerate_per_kw < min_feerate {
+ log_info!(logger,
+ "Closing channel as feerate of {} is below required {} (the minimum required rate over the past day)",
+ self.context.feerate_per_kw, min_feerate
+ );
+ Err(ClosureReason::PeerFeerateTooLow {
+ peer_feerate_sat_per_kw: self.context.feerate_per_kw,
+ required_feerate_sat_per_kw: min_feerate,
+ })
+ } else {
+ Ok(())
+ }
+ }
+
pub fn update_fee<F: Deref, L: Deref>(&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, msg: &msgs::UpdateFee, logger: &L) -> Result<(), ChannelError>
where F::Target: FeeEstimator, L::Target: Logger
{
/// accepted. An unaccepted channel that exceeds this limit will be abandoned.
const UNACCEPTED_INBOUND_CHANNEL_AGE_LIMIT_TICKS: i32 = 2;
+/// The number of blocks of historical feerate estimates we keep around and consider when deciding
+/// to force-close a channel for having too-low fees. Also the number of blocks we have to see
+/// after startup before we consider force-closing channels for having too-low fees.
+const FEERATE_TRACKING_BLOCKS: usize = 144;
+
/// Stores a PaymentSecret and any other data we may need to validate an inbound payment is
/// actually ours and not some duplicate HTLC sent to us by a node along the route.
///
/// Tracks the message events that are to be broadcasted when we are connected to some peer.
pending_broadcast_messages: Mutex<Vec<MessageSendEvent>>,
+ /// We only want to force-close our channels on peers based on stale feerates when we're
+ /// confident the feerate on the channel is *really* stale, not just became stale recently.
+ /// Thus, we store the fee estimates we had as of the last [`FEERATE_TRACKING_BLOCKS`] blocks
+ /// (after startup completed) here, and only force-close when channels have a lower feerate
+ /// than we predicted any time in the last [`FEERATE_TRACKING_BLOCKS`] blocks.
+ ///
+ /// We only keep this in memory as we assume any feerates we receive immediately after startup
+ /// may be bunk (as they often are if Bitcoin Core crashes) and want to delay taking any
+ /// actions for a day anyway.
+ ///
+ /// The first element in the pair is the
+ /// [`ConfirmationTarget::MinAllowedAnchorChannelRemoteFee`] estimate, the second the
+ /// [`ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee`] estimate.
+ last_days_feerates: Mutex<VecDeque<(u32, u32)>>,
+
entropy_source: ES,
node_signer: NS,
signer_provider: SP,
pending_offers_messages: Mutex::new(Vec::new()),
pending_broadcast_messages: Mutex::new(Vec::new()),
+ last_days_feerates: Mutex::new(VecDeque::new()),
+
entropy_source,
node_signer,
signer_provider,
self, || -> NotifyOption { NotifyOption::DoPersist });
*self.best_block.write().unwrap() = BestBlock::new(block_hash, height);
- self.do_chain_event(Some(height), |channel| channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None)));
+ let mut min_anchor_feerate = None;
+ let mut min_non_anchor_feerate = None;
+ if self.background_events_processed_since_startup.load(Ordering::Relaxed) {
+ // If we're past the startup phase, update our feerate cache
+ let mut last_days_feerates = self.last_days_feerates.lock().unwrap();
+ if last_days_feerates.len() >= FEERATE_TRACKING_BLOCKS {
+ last_days_feerates.pop_front();
+ }
+ let anchor_feerate = self.fee_estimator
+ .bounded_sat_per_1000_weight(ConfirmationTarget::MinAllowedAnchorChannelRemoteFee);
+ let non_anchor_feerate = self.fee_estimator
+ .bounded_sat_per_1000_weight(ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee);
+ last_days_feerates.push_back((anchor_feerate, non_anchor_feerate));
+ if last_days_feerates.len() >= FEERATE_TRACKING_BLOCKS {
+ min_anchor_feerate = last_days_feerates.iter().map(|(f, _)| f).min().copied();
+ min_non_anchor_feerate = last_days_feerates.iter().map(|(_, f)| f).min().copied();
+ }
+ }
+
+ self.do_chain_event(Some(height), |channel| {
+ let logger = WithChannelContext::from(&self.logger, &channel.context, None);
+ if channel.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
+ if let Some(feerate) = min_anchor_feerate {
+ channel.check_for_stale_feerate(&logger, feerate)?;
+ }
+ } else {
+ if let Some(feerate) = min_non_anchor_feerate {
+ channel.check_for_stale_feerate(&logger, feerate)?;
+ }
+ }
+ channel.best_block_updated(height, header.time, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context, None))
+ });
macro_rules! max_time {
($timestamp: expr) => {
node_signer: args.node_signer,
signer_provider: args.signer_provider,
+ last_days_feerates: Mutex::new(VecDeque::new()),
+
logger: args.logger,
default_configuration: args.default_config,
};