X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fpackage.rs;h=c888118bcba4e13b3400027249e8e14eb4e535da;hb=955e81086f7ba0b738eb473dcaac5ae561b0b153;hp=891d7d1da33bddbeb8777c1349e1eda0a4c5a668;hpb=ed5f9f6a9b9f9fc84810cdc1c04ff0a1caa888ff;p=rust-lightning diff --git a/lightning/src/chain/package.rs b/lightning/src/chain/package.rs index 891d7d1d..c888118b 100644 --- a/lightning/src/chain/package.rs +++ b/lightning/src/chain/package.rs @@ -26,16 +26,13 @@ use crate::ln::chan_utils; use crate::ln::msgs::DecodeError; use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; use crate::sign::WriteableEcdsaChannelSigner; -#[cfg(anchors)] -use crate::chain::onchaintx::ExternalHTLCClaim; -use crate::chain::onchaintx::OnchainTxHandler; +use crate::chain::onchaintx::{ExternalHTLCClaim, OnchainTxHandler}; use crate::util::logger::Logger; use crate::util::ser::{Readable, Writer, Writeable, RequiredWrapper}; use crate::io; use crate::prelude::*; use core::cmp; -#[cfg(anchors)] use core::convert::TryInto; use core::mem; use core::ops::Deref; @@ -250,7 +247,7 @@ impl Readable for CounterpartyOfferedHTLCOutput { let mut counterparty_htlc_base_key = RequiredWrapper(None); let mut preimage = RequiredWrapper(None); let mut htlc = RequiredWrapper(None); - let mut legacy_deserialization_prevention_marker: Option<()> = None; + let mut _legacy_deserialization_prevention_marker: Option<()> = None; let mut channel_type_features = None; read_tlv_fields!(reader, { @@ -259,7 +256,7 @@ impl Readable for CounterpartyOfferedHTLCOutput { (4, counterparty_htlc_base_key, required), (6, preimage, required), (8, htlc, required), - (10, legacy_deserialization_prevention_marker, option), + (10, _legacy_deserialization_prevention_marker, option), (11, channel_type_features, option), }); @@ -324,7 +321,7 @@ impl Readable for CounterpartyReceivedHTLCOutput { let mut counterparty_delayed_payment_base_key = RequiredWrapper(None); let mut counterparty_htlc_base_key = RequiredWrapper(None); let mut htlc = RequiredWrapper(None); - let mut legacy_deserialization_prevention_marker: Option<()> = None; + let mut _legacy_deserialization_prevention_marker: Option<()> = None; let mut channel_type_features = None; read_tlv_fields!(reader, { @@ -332,7 +329,7 @@ impl Readable for CounterpartyReceivedHTLCOutput { (2, counterparty_delayed_payment_base_key, required), (4, counterparty_htlc_base_key, required), (6, htlc, required), - (8, legacy_deserialization_prevention_marker, option), + (8, _legacy_deserialization_prevention_marker, option), (9, channel_type_features, option), }); @@ -402,14 +399,14 @@ impl Readable for HolderHTLCOutput { let mut amount_msat = RequiredWrapper(None); let mut cltv_expiry = RequiredWrapper(None); let mut preimage = None; - let mut legacy_deserialization_prevention_marker: Option<()> = None; + let mut _legacy_deserialization_prevention_marker: Option<()> = None; let mut channel_type_features = None; read_tlv_fields!(reader, { (0, amount_msat, required), (2, cltv_expiry, required), (4, preimage, option), - (6, legacy_deserialization_prevention_marker, option), + (6, _legacy_deserialization_prevention_marker, option), (7, channel_type_features, option), }); @@ -432,7 +429,7 @@ impl Readable for HolderHTLCOutput { #[derive(Clone, PartialEq, Eq)] pub(crate) struct HolderFundingOutput { funding_redeemscript: Script, - funding_amount: Option, + pub(crate) funding_amount: Option, channel_type_features: ChannelTypeFeatures, } @@ -463,14 +460,14 @@ impl Writeable for HolderFundingOutput { impl Readable for HolderFundingOutput { fn read(reader: &mut R) -> Result { let mut funding_redeemscript = RequiredWrapper(None); - let mut legacy_deserialization_prevention_marker: Option<()> = None; + let mut _legacy_deserialization_prevention_marker: Option<()> = None; let mut channel_type_features = None; let mut funding_amount = None; read_tlv_fields!(reader, { (0, funding_redeemscript, required), (1, channel_type_features, option), - (2, legacy_deserialization_prevention_marker, option), + (2, _legacy_deserialization_prevention_marker, option), (3, funding_amount, option) }); @@ -554,6 +551,32 @@ impl PackageSolvingData { _ => { mem::discriminant(self) == mem::discriminant(&input) } } } + fn as_tx_input(&self, previous_output: BitcoinOutPoint) -> TxIn { + let sequence = match self { + PackageSolvingData::RevokedOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME, + PackageSolvingData::RevokedHTLCOutput(_) => Sequence::ENABLE_RBF_NO_LOCKTIME, + PackageSolvingData::CounterpartyOfferedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + Sequence::from_consensus(1) + } else { + Sequence::ENABLE_RBF_NO_LOCKTIME + }, + PackageSolvingData::CounterpartyReceivedHTLCOutput(outp) => if outp.channel_type_features.supports_anchors_zero_fee_htlc_tx() { + Sequence::from_consensus(1) + } else { + Sequence::ENABLE_RBF_NO_LOCKTIME + }, + _ => { + debug_assert!(false, "This should not be reachable by 'untractable' or 'malleable with external funding' packages"); + Sequence::ENABLE_RBF_NO_LOCKTIME + }, + }; + TxIn { + previous_output, + script_sig: Script::new(), + sequence, + witness: Witness::new(), + } + } fn finalize_input(&self, bumped_tx: &mut Transaction, i: usize, onchain_handler: &mut OnchainTxHandler) -> bool { match self { PackageSolvingData::RevokedOutput(ref outp) => { @@ -866,7 +889,6 @@ impl PackageTemplate { let output_weight = (8 + 1 + destination_script.len()) * WITNESS_SCALE_FACTOR; inputs_weight + witnesses_weight + transaction_weight + output_weight } - #[cfg(anchors)] pub(crate) fn construct_malleable_package_with_external_funding( &self, onchain_handler: &mut OnchainTxHandler, ) -> Option> { @@ -899,13 +921,8 @@ impl PackageTemplate { value, }], }; - for (outpoint, _) in self.inputs.iter() { - bumped_tx.input.push(TxIn { - previous_output: *outpoint, - script_sig: Script::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - witness: Witness::new(), - }); + for (outpoint, outp) in self.inputs.iter() { + bumped_tx.input.push(outp.as_tx_input(*outpoint)); } for (i, (outpoint, out)) in self.inputs.iter().enumerate() { log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); @@ -971,7 +988,6 @@ impl PackageTemplate { None } - #[cfg(anchors)] /// Computes a feerate based on the given confirmation target. If a previous feerate was used, /// the new feerate is below it, and `force_feerate_bump` is set, we'll use a 25% increase of /// the previous feerate instead of the new feerate. @@ -981,14 +997,23 @@ impl PackageTemplate { ) -> u32 where F::Target: FeeEstimator { let feerate_estimate = fee_estimator.bounded_sat_per_1000_weight(conf_target); if self.feerate_previous != 0 { - // If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee... + // Use the new fee estimate if it's higher than the one previously used. if feerate_estimate as u64 > self.feerate_previous { feerate_estimate } else if !force_feerate_bump { self.feerate_previous.try_into().unwrap_or(u32::max_value()) } else { - // ...else just increase the previous feerate by 25% (because that's a nice number) - (self.feerate_previous + (self.feerate_previous / 4)).try_into().unwrap_or(u32::max_value()) + // Our fee estimate has decreased, but our transaction remains unconfirmed after + // using our previous fee estimate. This may point to an unreliable fee estimator, + // so we choose to bump our previous feerate by 25%, making sure we don't use a + // lower feerate or overpay by a large margin by limiting it to 5x the new fee + // estimate. + let previous_feerate = self.feerate_previous.try_into().unwrap_or(u32::max_value()); + let mut new_feerate = previous_feerate.saturating_add(previous_feerate / 4); + if new_feerate > feerate_estimate * 5 { + new_feerate = cmp::max(feerate_estimate * 5, previous_feerate); + } + new_feerate } } else { feerate_estimate