Merge pull request #1201 from jkczyz/2021-12-idempotent-channelmanager
[rust-lightning] / lightning / src / chain / package.rs
index b5c1ffdf9bc4c92557f5c4dde08e9f1754b54d3e..6af41506fb36ed458ca149b0fa66ec901d09a47b 100644 (file)
@@ -31,6 +31,8 @@ use util::byte_utils;
 use util::logger::Logger;
 use util::ser::{Readable, Writer, Writeable};
 
+use io;
+use prelude::*;
 use core::cmp;
 use core::mem;
 use core::ops::Deref;
@@ -339,7 +341,7 @@ impl PackageSolvingData {
                        },
                        PackageSolvingData::RevokedHTLCOutput(ref outp) => {
                                if let Ok(chan_keys) = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint) {
-                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
+                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, onchain_handler.opt_anchors(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
                                        //TODO: should we panic on signer failure ?
                                        if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc(&bumped_tx, i, outp.amount, &outp.per_commitment_key, &outp.htlc, &onchain_handler.secp_ctx) {
                                                bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
@@ -351,7 +353,7 @@ impl PackageSolvingData {
                        },
                        PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => {
                                if let Ok(chan_keys) = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint) {
-                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
+                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, onchain_handler.opt_anchors(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
 
                                        if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
                                                bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
@@ -363,7 +365,7 @@ impl PackageSolvingData {
                        },
                        PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => {
                                if let Ok(chan_keys) = TxCreationKeys::derive_new(&onchain_handler.secp_ctx, &outp.per_commitment_point, &outp.counterparty_delayed_payment_base_key, &outp.counterparty_htlc_base_key, &onchain_handler.signer.pubkeys().revocation_basepoint, &onchain_handler.signer.pubkeys().htlc_basepoint) {
-                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
+                                       let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, onchain_handler.opt_anchors(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
 
                                        bumped_tx.lock_time = outp.htlc.cltv_expiry; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation
                                        if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
@@ -395,8 +397,8 @@ impl PackageSolvingData {
                        PackageSolvingData::RevokedOutput(_) => output_conf_height + 1,
                        PackageSolvingData::RevokedHTLCOutput(_) => output_conf_height + 1,
                        PackageSolvingData::CounterpartyOfferedHTLCOutput(_) => output_conf_height + 1,
-                       PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => std::cmp::max(outp.htlc.cltv_expiry, output_conf_height + 1),
-                       PackageSolvingData::HolderHTLCOutput(ref outp) => std::cmp::max(outp.cltv_expiry, output_conf_height + 1),
+                       PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => cmp::max(outp.htlc.cltv_expiry, output_conf_height + 1),
+                       PackageSolvingData::HolderHTLCOutput(ref outp) => cmp::max(outp.cltv_expiry, output_conf_height + 1),
                        PackageSolvingData::HolderFundingOutput(_) => output_conf_height + 1,
                };
                absolute_timelock
@@ -634,26 +636,25 @@ impl PackageTemplate {
                }
                current_height + LOW_FREQUENCY_BUMP_INTERVAL
        }
-       /// Returns value in satoshis to be included as package outgoing output amount and feerate with which package finalization should be done.
-       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+
+       /// Returns value in satoshis to be included as package outgoing output amount and feerate
+       /// which was used to generate the value. Will not return less than `dust_limit_sats` for the
+       /// value.
+       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
                where F::Target: FeeEstimator,
                      L::Target: Logger,
        {
                debug_assert!(self.malleability == PackageMalleability::Malleable, "The package output is fixed for non-malleable packages");
                let input_amounts = self.package_amount();
+               assert!(dust_limit_sats as i64 > 0, "Output script must be broadcastable/have a 'real' dust limit.");
                // If old feerate is 0, first iteration of this claim, use normal fee calculation
                if self.feerate_previous != 0 {
                        if let Some((new_fee, feerate)) = feerate_bump(predicted_weight, input_amounts, self.feerate_previous, fee_estimator, logger) {
-                               // If new computed fee is superior at the whole claimable amount burn all in fees
-                               if new_fee > input_amounts {
-                                       return Some((0, feerate));
-                               } else {
-                                       return Some((input_amounts - new_fee, feerate));
-                               }
+                               return Some((cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, feerate));
                        }
                } else {
                        if let Some((new_fee, feerate)) = compute_fee_from_spent_amounts(input_amounts, predicted_weight, fee_estimator, logger) {
-                               return Some((input_amounts - new_fee, feerate));
+                               return Some((cmp::max(input_amounts as i64 - new_fee as i64, dust_limit_sats as i64) as u64, feerate));
                        }
                }
                None
@@ -682,7 +683,7 @@ impl PackageTemplate {
 }
 
 impl Writeable for PackageTemplate {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                writer.write_all(&byte_utils::be64_to_array(self.inputs.len() as u64))?;
                for (ref outpoint, ref rev_outp) in self.inputs.iter() {
                        outpoint.write(writer)?;
@@ -699,7 +700,7 @@ impl Writeable for PackageTemplate {
 }
 
 impl Readable for PackageTemplate {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
                let inputs_count = <u64 as Readable>::read(reader)?;
                let mut inputs: Vec<(BitcoinOutPoint, PackageSolvingData)> = Vec::with_capacity(cmp::min(inputs_count as usize, MAX_ALLOC_SIZE / 128));
                for _ in 0..inputs_count {