Delay DelayedPaymentOutput spendable events until the CSV delay
[rust-lightning] / lightning / src / chain / channelmonitor.rs
index 777bc06bfb882745545c3db089c2f918a43c9b95..8ae4c13309f5585e23829faa13f503f24c1318bc 100644 (file)
@@ -22,7 +22,6 @@
 
 use bitcoin::blockdata::block::{Block, BlockHeader};
 use bitcoin::blockdata::transaction::{TxOut,Transaction};
-use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
 use bitcoin::blockdata::script::{Script, Builder};
 use bitcoin::blockdata::opcodes;
 
@@ -34,26 +33,29 @@ use bitcoin::secp256k1::{Secp256k1,Signature};
 use bitcoin::secp256k1::key::{SecretKey,PublicKey};
 use bitcoin::secp256k1;
 
+use ln::{PaymentHash, PaymentPreimage};
 use ln::msgs::DecodeError;
 use ln::chan_utils;
 use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCType, ChannelTransactionParameters, HolderCommitmentTransaction};
-use ln::channelmanager::{BestBlock, HTLCSource, PaymentPreimage, PaymentHash};
-use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
+use ln::channelmanager::{BestBlock, HTLCSource};
 use chain;
 use chain::WatchedOutput;
 use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
 use chain::transaction::{OutPoint, TransactionData};
 use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
+use chain::onchaintx::OnchainTxHandler;
+use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
 use chain::Filter;
 use util::logger::Logger;
 use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48};
 use util::byte_utils;
 use util::events::Event;
 
+use prelude::*;
 use std::collections::{HashMap, HashSet};
-use std::{cmp, mem};
+use core::{cmp, mem};
 use std::io::Error;
-use std::ops::Deref;
+use core::ops::Deref;
 use std::sync::Mutex;
 
 /// An update generated by the underlying Channel itself which contains some new information the
@@ -84,7 +86,7 @@ pub struct ChannelMonitorUpdate {
 /// then we allow the `ChannelManager` to send a `ChannelMonitorUpdate` with this update ID,
 /// with the update providing said payment preimage. No other update types are allowed after
 /// force-close.
-pub const CLOSED_CHANNEL_UPDATE_ID: u64 = std::u64::MAX;
+pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
 
 impl Writeable for ChannelMonitorUpdate {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
@@ -100,7 +102,7 @@ impl Readable for ChannelMonitorUpdate {
        fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
                let update_id: u64 = Readable::read(r)?;
                let len: u64 = Readable::read(r)?;
-               let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::std::mem::size_of::<ChannelMonitorUpdateStep>()));
+               let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::core::mem::size_of::<ChannelMonitorUpdateStep>()));
                for _ in 0..len {
                        updates.push(Readable::read(r)?);
                }
@@ -205,7 +207,7 @@ pub(crate) const CLTV_SHARED_CLAIM_BUFFER: u32 = 12;
 /// HTLC-Success transaction.
 /// In other words, this is an upper bound on how many blocks we think it can take us to get a
 /// transaction confirmed (and we use it in a few more, equivalent, places).
-pub(crate) const CLTV_CLAIM_BUFFER: u32 = 6;
+pub(crate) const CLTV_CLAIM_BUFFER: u32 = 18;
 /// Number of blocks by which point we expect our counterparty to have seen new blocks on the
 /// network and done a full update_fail_htlc/commitment_signed dance (+ we've updated all our
 /// copies of ChannelMonitors, including watchtowers). We could enforce the contract by failing
@@ -221,11 +223,11 @@ pub(crate) const CLTV_CLAIM_BUFFER: u32 = 6;
 pub(crate) const LATENCY_GRACE_PERIOD_BLOCKS: u32 = 3;
 /// Number of blocks we wait on seeing a HTLC output being solved before we fail corresponding inbound
 /// HTLCs. This prevents us from failing backwards and then getting a reorg resulting in us losing money.
-/// We use also this delay to be sure we can remove our in-flight claim txn from bump candidates buffer.
-/// It may cause spurrious generation of bumped claim txn but that's allright given the outpoint is already
-/// solved by a previous claim tx. What we want to avoid is reorg evicting our claim tx and us not
-/// keeping bumping another claim tx to solve the outpoint.
-pub(crate) const ANTI_REORG_DELAY: u32 = 6;
+// We also use this delay to be sure we can remove our in-flight claim txn from bump candidates buffer.
+// It may cause spurious generation of bumped claim txn but that's alright given the outpoint is already
+// solved by a previous claim tx. What we want to avoid is reorg evicting our claim tx and us not
+// keep bumping another claim tx to solve the outpoint.
+pub const ANTI_REORG_DELAY: u32 = 6;
 /// Number of blocks before confirmation at which we fail back an un-relayed HTLC or at which we
 /// refuse to accept a new HTLC.
 ///
@@ -320,151 +322,6 @@ impl Readable for CounterpartyCommitmentTransaction {
        }
 }
 
-/// When ChannelMonitor discovers an onchain outpoint being a step of a channel and that it needs
-/// to generate a tx to push channel state forward, we cache outpoint-solving tx material to build
-/// a new bumped one in case of lenghty confirmation delay
-#[derive(Clone, PartialEq)]
-pub(crate) enum InputMaterial {
-       Revoked {
-               per_commitment_point: PublicKey,
-               counterparty_delayed_payment_base_key: PublicKey,
-               counterparty_htlc_base_key: PublicKey,
-               per_commitment_key: SecretKey,
-               input_descriptor: InputDescriptors,
-               amount: u64,
-               htlc: Option<HTLCOutputInCommitment>,
-               on_counterparty_tx_csv: u16,
-       },
-       CounterpartyHTLC {
-               per_commitment_point: PublicKey,
-               counterparty_delayed_payment_base_key: PublicKey,
-               counterparty_htlc_base_key: PublicKey,
-               preimage: Option<PaymentPreimage>,
-               htlc: HTLCOutputInCommitment
-       },
-       HolderHTLC {
-               preimage: Option<PaymentPreimage>,
-               amount: u64,
-       },
-       Funding {
-               funding_redeemscript: Script,
-       }
-}
-
-impl Writeable for InputMaterial  {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &InputMaterial::Revoked { ref per_commitment_point, ref counterparty_delayed_payment_base_key, ref counterparty_htlc_base_key, ref per_commitment_key, ref input_descriptor, ref amount, ref htlc, ref on_counterparty_tx_csv} => {
-                               writer.write_all(&[0; 1])?;
-                               per_commitment_point.write(writer)?;
-                               counterparty_delayed_payment_base_key.write(writer)?;
-                               counterparty_htlc_base_key.write(writer)?;
-                               writer.write_all(&per_commitment_key[..])?;
-                               input_descriptor.write(writer)?;
-                               writer.write_all(&byte_utils::be64_to_array(*amount))?;
-                               htlc.write(writer)?;
-                               on_counterparty_tx_csv.write(writer)?;
-                       },
-                       &InputMaterial::CounterpartyHTLC { ref per_commitment_point, ref counterparty_delayed_payment_base_key, ref counterparty_htlc_base_key, ref preimage, ref htlc} => {
-                               writer.write_all(&[1; 1])?;
-                               per_commitment_point.write(writer)?;
-                               counterparty_delayed_payment_base_key.write(writer)?;
-                               counterparty_htlc_base_key.write(writer)?;
-                               preimage.write(writer)?;
-                               htlc.write(writer)?;
-                       },
-                       &InputMaterial::HolderHTLC { ref preimage, ref amount } => {
-                               writer.write_all(&[2; 1])?;
-                               preimage.write(writer)?;
-                               writer.write_all(&byte_utils::be64_to_array(*amount))?;
-                       },
-                       &InputMaterial::Funding { ref funding_redeemscript } => {
-                               writer.write_all(&[3; 1])?;
-                               funding_redeemscript.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for InputMaterial {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               let input_material = match <u8 as Readable>::read(reader)? {
-                       0 => {
-                               let per_commitment_point = Readable::read(reader)?;
-                               let counterparty_delayed_payment_base_key = Readable::read(reader)?;
-                               let counterparty_htlc_base_key = Readable::read(reader)?;
-                               let per_commitment_key = Readable::read(reader)?;
-                               let input_descriptor = Readable::read(reader)?;
-                               let amount = Readable::read(reader)?;
-                               let htlc = Readable::read(reader)?;
-                               let on_counterparty_tx_csv = Readable::read(reader)?;
-                               InputMaterial::Revoked {
-                                       per_commitment_point,
-                                       counterparty_delayed_payment_base_key,
-                                       counterparty_htlc_base_key,
-                                       per_commitment_key,
-                                       input_descriptor,
-                                       amount,
-                                       htlc,
-                                       on_counterparty_tx_csv
-                               }
-                       },
-                       1 => {
-                               let per_commitment_point = Readable::read(reader)?;
-                               let counterparty_delayed_payment_base_key = Readable::read(reader)?;
-                               let counterparty_htlc_base_key = Readable::read(reader)?;
-                               let preimage = Readable::read(reader)?;
-                               let htlc = Readable::read(reader)?;
-                               InputMaterial::CounterpartyHTLC {
-                                       per_commitment_point,
-                                       counterparty_delayed_payment_base_key,
-                                       counterparty_htlc_base_key,
-                                       preimage,
-                                       htlc
-                               }
-                       },
-                       2 => {
-                               let preimage = Readable::read(reader)?;
-                               let amount = Readable::read(reader)?;
-                               InputMaterial::HolderHTLC {
-                                       preimage,
-                                       amount,
-                               }
-                       },
-                       3 => {
-                               InputMaterial::Funding {
-                                       funding_redeemscript: Readable::read(reader)?,
-                               }
-                       }
-                       _ => return Err(DecodeError::InvalidValue),
-               };
-               Ok(input_material)
-       }
-}
-
-/// ClaimRequest is a descriptor structure to communicate between detection
-/// and reaction module. They are generated by ChannelMonitor while parsing
-/// onchain txn leaked from a channel and handed over to OnchainTxHandler which
-/// is responsible for opportunistic aggregation, selecting and enforcing
-/// bumping logic, building and signing transactions.
-pub(crate) struct ClaimRequest {
-       // Block height before which claiming is exclusive to one party,
-       // after reaching it, claiming may be contentious.
-       pub(crate) absolute_timelock: u32,
-       // Timeout tx must have nLocktime set which means aggregating multiple
-       // ones must take the higher nLocktime among them to satisfy all of them.
-       // Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
-       // of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
-       // Do simplify we mark them as non-aggregable.
-       pub(crate) aggregable: bool,
-       // Basic bitcoin outpoint (txid, vout)
-       pub(crate) outpoint: BitcoinOutPoint,
-       // Following outpoint type, set of data needed to generate transaction digest
-       // and satisfy witness program.
-       pub(crate) witness_data: InputMaterial
-}
-
 /// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the
 /// transaction causing it.
 ///
@@ -478,7 +335,15 @@ struct OnchainEventEntry {
 
 impl OnchainEventEntry {
        fn confirmation_threshold(&self) -> u32 {
-               self.height + ANTI_REORG_DELAY - 1
+               let mut conf_threshold = self.height + ANTI_REORG_DELAY - 1;
+               if let OnchainEvent::MaturingOutput {
+                       descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor)
+               } = self.event {
+                       // A CSV'd transaction is confirmable in block (input height) + CSV delay, which means
+                       // it's broadcastable when we see the previous block.
+                       conf_threshold = cmp::max(conf_threshold, self.height + descriptor.to_self_delay as u32 - 1);
+               }
+               conf_threshold
        }
 
        fn has_reached_confirmation_threshold(&self, height: u32) -> bool {
@@ -501,9 +366,6 @@ enum OnchainEvent {
        },
 }
 
-const SERIALIZATION_VERSION: u8 = 1;
-const MIN_SERIALIZATION_VERSION: u8 = 1;
-
 #[cfg_attr(any(test, feature = "fuzztarget", feature = "_test_utils"), derive(PartialEq))]
 #[derive(Clone)]
 pub(crate) enum ChannelMonitorUpdateStep {
@@ -746,7 +608,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
 }
 
 /// Transaction outputs to watch for on-chain spends.
-pub(super) type TransactionOutputs = (Txid, Vec<(u32, TxOut)>);
+pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>);
 
 #[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))]
 /// Used only in testing and fuzztarget to check serialization roundtrips don't change the
@@ -804,17 +666,17 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
 
 impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
-               //TODO: We still write out all the serialization here manually instead of using the fancy
-               //serialization framework we have, we should migrate things over to it.
-               writer.write_all(&[SERIALIZATION_VERSION; 1])?;
-               writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
-
                self.inner.lock().unwrap().write(writer)
        }
 }
 
+const SERIALIZATION_VERSION: u8 = 1;
+const MIN_SERIALIZATION_VERSION: u8 = 1;
+
 impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
+               write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
+
                self.latest_update_id.write(writer)?;
 
                // Set in initial Channel-object creation, so should always be set by now:
@@ -990,6 +852,8 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
                self.lockdown_from_offchain.write(writer)?;
                self.holder_tx_signed.write(writer)?;
 
+               write_tlv_fields!(writer, {}, {});
+
                Ok(())
        }
 }
@@ -1311,11 +1175,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
        /// outputs to watch. See [`block_connected`] for details.
        ///
        /// Used instead of [`block_connected`] by clients that are notified of transactions rather than
-       /// blocks. May be called before or after [`update_best_block`] for transactions in the
-       /// corresponding block. See [`update_best_block`] for further calling expectations. 
+       /// blocks. See [`chain::Confirm`] for calling expectations.
        ///
        /// [`block_connected`]: Self::block_connected
-       /// [`update_best_block`]: Self::update_best_block
        pub fn transactions_confirmed<B: Deref, F: Deref, L: Deref>(
                &self,
                header: &BlockHeader,
@@ -1337,11 +1199,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
        /// Processes a transaction that was reorganized out of the chain.
        ///
        /// Used instead of [`block_disconnected`] by clients that are notified of transactions rather
-       /// than blocks. May be called before or after [`update_best_block`] for transactions in the
-       /// corresponding block. See [`update_best_block`] for further calling expectations.
+       /// than blocks. See [`chain::Confirm`] for calling expectations.
        ///
        /// [`block_disconnected`]: Self::block_disconnected
-       /// [`update_best_block`]: Self::update_best_block
        pub fn transaction_unconfirmed<B: Deref, F: Deref, L: Deref>(
                &self,
                txid: &Txid,
@@ -1361,18 +1221,10 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
        /// [`block_connected`] for details.
        ///
        /// Used instead of [`block_connected`] by clients that are notified of transactions rather than
-       /// blocks. May be called before or after [`transactions_confirmed`] for the corresponding
-       /// block.
-       ///
-       /// Must be called after new blocks become available for the most recent block. Intermediary
-       /// blocks, however, may be safely skipped. In the event of a chain re-organization, this only
-       /// needs to be called for the most recent block assuming `transaction_unconfirmed` is called
-       /// for any affected transactions.
+       /// blocks. See [`chain::Confirm`] for calling expectations.
        ///
        /// [`block_connected`]: Self::block_connected
-       /// [`transactions_confirmed`]: Self::transactions_confirmed
-       /// [`transaction_unconfirmed`]: Self::transaction_unconfirmed
-       pub fn update_best_block<B: Deref, F: Deref, L: Deref>(
+       pub fn best_block_updated<B: Deref, F: Deref, L: Deref>(
                &self,
                header: &BlockHeader,
                height: u32,
@@ -1385,7 +1237,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                F::Target: FeeEstimator,
                L::Target: Logger,
        {
-               self.inner.lock().unwrap().update_best_block(
+               self.inner.lock().unwrap().best_block_updated(
                        header, height, broadcaster, fee_estimator, logger)
        }
 
@@ -1543,7 +1395,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                macro_rules! claim_htlcs {
                        ($commitment_number: expr, $txid: expr) => {
                                let htlc_claim_reqs = self.get_counterparty_htlc_output_claim_reqs($commitment_number, $txid, None);
-                               self.onchain_tx_handler.update_claims_view(&Vec::new(), htlc_claim_reqs, None, broadcaster, fee_estimator, logger);
+                               self.onchain_tx_handler.update_claims_view(&Vec::new(), htlc_claim_reqs, self.best_block.height(), broadcaster, fee_estimator, logger);
                        }
                }
                if let Some(txid) = self.current_counterparty_commitment_txid {
@@ -1565,11 +1417,11 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                // *we* sign a holder commitment transaction, not when e.g. a watchtower broadcasts one of our
                // holder commitment transactions.
                if self.broadcasted_holder_revokable_script.is_some() {
-                       let (claim_reqs, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx);
-                       self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, None, broadcaster, fee_estimator, logger);
+                       let (claim_reqs, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, 0);
+                       self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), broadcaster, fee_estimator, logger);
                        if let Some(ref tx) = self.prev_holder_signed_commitment_tx {
-                               let (claim_reqs, _) = self.get_broadcasted_holder_claims(&tx);
-                               self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, None, broadcaster, fee_estimator, logger);
+                               let (claim_reqs, _) = self.get_broadcasted_holder_claims(&tx, 0);
+                               self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, self.best_block.height(), broadcaster, fee_estimator, logger);
                        }
                }
        }
@@ -1579,6 +1431,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                        L::Target: Logger,
        {
                for tx in self.get_latest_holder_commitment_txn(logger).iter() {
+                       log_info!(logger, "Broadcasting local {}", log_tx!(tx));
                        broadcaster.broadcast_transaction(tx);
                }
                self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));
@@ -1694,7 +1547,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        /// HTLC-Success/HTLC-Timeout transactions.
        /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
        /// revoked counterparty commitment tx
-       fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, TransactionOutputs) where L::Target: Logger {
+       fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<PackageTemplate>, TransactionOutputs) where L::Target: Logger {
                // Most secp and related errors trying to create keys means we have no hope of constructing
                // a spend transaction...so we return no transactions to broadcast
                let mut claimable_outpoints = Vec::new();
@@ -1726,8 +1579,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                        // First, process non-htlc outputs (to_holder & to_counterparty)
                        for (idx, outp) in tx.output.iter().enumerate() {
                                if outp.script_pubkey == revokeable_p2wsh {
-                                       let witness_data = InputMaterial::Revoked { per_commitment_point, counterparty_delayed_payment_base_key: self.counterparty_tx_cache.counterparty_delayed_payment_base_key, counterparty_htlc_base_key: self.counterparty_tx_cache.counterparty_htlc_base_key, per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: outp.value, htlc: None, on_counterparty_tx_csv: self.counterparty_tx_cache.on_counterparty_tx_csv};
-                                       claimable_outpoints.push(ClaimRequest { absolute_timelock: height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 }, witness_data});
+                                       let revk_outp = RevokedOutput::build(per_commitment_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, per_commitment_key, outp.value, self.counterparty_tx_cache.on_counterparty_tx_csv);
+                                       let justice_package = PackageTemplate::build_package(commitment_txid, idx as u32, PackageSolvingData::RevokedOutput(revk_outp), height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, true, height);
+                                       claimable_outpoints.push(justice_package);
                                }
                        }
 
@@ -1739,8 +1593,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                                tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
                                                        return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
                                                }
-                                               let witness_data = InputMaterial::Revoked { per_commitment_point, counterparty_delayed_payment_base_key: self.counterparty_tx_cache.counterparty_delayed_payment_base_key, counterparty_htlc_base_key: self.counterparty_tx_cache.counterparty_htlc_base_key, per_commitment_key, input_descriptor: if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }, amount: tx.output[transaction_output_index as usize].value, htlc: Some(htlc.clone()), on_counterparty_tx_csv: self.counterparty_tx_cache.on_counterparty_tx_csv};
-                                               claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
+                                               let revk_htlc_outp = RevokedHTLCOutput::build(per_commitment_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, per_commitment_key, htlc.amount_msat / 1000, htlc.clone());
+                                               let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedHTLCOutput(revk_htlc_outp), htlc.cltv_expiry, true, height);
+                                               claimable_outpoints.push(justice_package);
                                        }
                                }
                        }
@@ -1862,8 +1717,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                (claimable_outpoints, (commitment_txid, watch_outputs))
        }
 
-       fn get_counterparty_htlc_output_claim_reqs(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>) -> Vec<ClaimRequest> {
-               let mut claims = Vec::new();
+       fn get_counterparty_htlc_output_claim_reqs(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>) -> Vec<PackageTemplate> {
+               let mut claimable_outpoints = Vec::new();
                if let Some(htlc_outputs) = self.counterparty_claimable_outpoints.get(&commitment_txid) {
                        if let Some(revocation_points) = self.their_cur_revocation_points {
                                let revocation_point_option =
@@ -1882,30 +1737,26 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                        if let Some(transaction) = tx {
                                                                if transaction_output_index as usize >= transaction.output.len() ||
                                                                        transaction.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
-                                                                               return claims; // Corrupted per_commitment_data, fuck this user
+                                                                               return claimable_outpoints; // Corrupted per_commitment_data, fuck this user
                                                                        }
                                                        }
-                                                       let preimage =
-                                                               if htlc.offered {
-                                                                       if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) {
-                                                                               Some(*p)
-                                                                       } else { None }
-                                                               } else { None };
-                                                       let aggregable = if !htlc.offered { false } else { true };
+                                                       let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
                                                        if preimage.is_some() || !htlc.offered {
-                                                               let witness_data = InputMaterial::CounterpartyHTLC { per_commitment_point: *revocation_point, counterparty_delayed_payment_base_key: self.counterparty_tx_cache.counterparty_delayed_payment_base_key, counterparty_htlc_base_key: self.counterparty_tx_cache.counterparty_htlc_base_key, preimage, htlc: htlc.clone() };
-                                                               claims.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
+                                                               let counterparty_htlc_outp = if htlc.offered { PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(*revocation_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, preimage.unwrap(), htlc.clone())) } else { PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(*revocation_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, htlc.clone())) };
+                                                               let aggregation = if !htlc.offered { false } else { true };
+                                                               let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, counterparty_htlc_outp, htlc.cltv_expiry,aggregation, 0);
+                                                               claimable_outpoints.push(counterparty_package);
                                                        }
                                                }
                                        }
                                }
                        }
                }
-               claims
+               claimable_outpoints
        }
 
        /// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
-       fn check_spend_counterparty_htlc<L: Deref>(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec<ClaimRequest>, Option<TransactionOutputs>) where L::Target: Logger {
+       fn check_spend_counterparty_htlc<L: Deref>(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec<PackageTemplate>, Option<TransactionOutputs>) where L::Target: Logger {
                let htlc_txid = tx.txid();
                if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 {
                        return (Vec::new(), None)
@@ -1925,16 +1776,17 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
 
                log_trace!(logger, "Counterparty HTLC broadcast {}:{}", htlc_txid, 0);
-               let witness_data = InputMaterial::Revoked { per_commitment_point, counterparty_delayed_payment_base_key: self.counterparty_tx_cache.counterparty_delayed_payment_base_key, counterparty_htlc_base_key: self.counterparty_tx_cache.counterparty_htlc_base_key,  per_commitment_key, input_descriptor: InputDescriptors::RevokedOutput, amount: tx.output[0].value, htlc: None, on_counterparty_tx_csv: self.counterparty_tx_cache.on_counterparty_tx_csv };
-               let claimable_outpoints = vec!(ClaimRequest { absolute_timelock: height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0}, witness_data });
+               let revk_outp = RevokedOutput::build(per_commitment_point, self.counterparty_tx_cache.counterparty_delayed_payment_base_key, self.counterparty_tx_cache.counterparty_htlc_base_key, per_commitment_key, tx.output[0].value, self.counterparty_tx_cache.on_counterparty_tx_csv);
+               let justice_package = PackageTemplate::build_package(htlc_txid, 0, PackageSolvingData::RevokedOutput(revk_outp), height + self.counterparty_tx_cache.on_counterparty_tx_csv as u32, true, height);
+               let claimable_outpoints = vec!(justice_package);
                let outputs = vec![(0, tx.output[0].clone())];
                (claimable_outpoints, Some((htlc_txid, outputs)))
        }
 
-       // Returns (1) `ClaimRequest`s that can be given to the OnChainTxHandler, so that the handler can
+       // Returns (1) `PackageTemplate`s that can be given to the OnChainTxHandler, so that the handler can
        // broadcast transactions claiming holder HTLC commitment outputs and (2) a holder revokable
        // script so we can detect whether a holder transaction has been seen on-chain.
-       fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx) -> (Vec<ClaimRequest>, Option<(Script, PublicKey, PublicKey)>) {
+       fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx, height: u32) -> (Vec<PackageTemplate>, Option<(Script, PublicKey, PublicKey)>) {
                let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len());
 
                let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key);
@@ -1942,18 +1794,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 
                for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
                        if let Some(transaction_output_index) = htlc.transaction_output_index {
-                               claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: holder_tx.txid, vout: transaction_output_index as u32 },
-                                       witness_data: InputMaterial::HolderHTLC {
-                                               preimage: if !htlc.offered {
-                                                               if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
-                                                                       Some(preimage.clone())
-                                                               } else {
-                                                                       // We can't build an HTLC-Success transaction without the preimage
-                                                                       continue;
-                                                               }
-                                                       } else { None },
-                                               amount: htlc.amount_msat,
-                               }});
+                               let htlc_output = if htlc.offered {
+                                               HolderHTLCOutput::build_offered(htlc.amount_msat, htlc.cltv_expiry)
+                                       } else {
+                                               let payment_preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
+                                                       preimage.clone()
+                                               } else {
+                                                       // We can't build an HTLC-Success transaction without the preimage
+                                                       continue;
+                                               };
+                                               HolderHTLCOutput::build_accepted(payment_preimage, htlc.amount_msat)
+                                       };
+                               let htlc_package = PackageTemplate::build_package(holder_tx.txid, transaction_output_index, PackageSolvingData::HolderHTLCOutput(htlc_output), height, false, height);
+                               claim_requests.push(htlc_package);
                        }
                }
 
@@ -1974,7 +1827,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
        /// revoked using data in holder_claimable_outpoints.
        /// Should not be used if check_spend_revoked_transaction succeeds.
-       fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, TransactionOutputs) where L::Target: Logger {
+       fn check_spend_holder_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<PackageTemplate>, TransactionOutputs) where L::Target: Logger {
                let commitment_txid = tx.txid();
                let mut claim_requests = Vec::new();
                let mut watch_outputs = Vec::new();
@@ -2014,14 +1867,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                if self.current_holder_commitment_tx.txid == commitment_txid {
                        is_holder_tx = true;
                        log_trace!(logger, "Got latest holder commitment tx broadcast, searching for available HTLCs to claim");
-                       let res = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx);
+                       let res = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, height);
                        let mut to_watch = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, tx);
                        append_onchain_update!(res, to_watch);
                } else if let &Some(ref holder_tx) = &self.prev_holder_signed_commitment_tx {
                        if holder_tx.txid == commitment_txid {
                                is_holder_tx = true;
                                log_trace!(logger, "Got previous holder commitment tx broadcast, searching for available HTLCs to claim");
-                               let res = self.get_broadcasted_holder_claims(holder_tx);
+                               let res = self.get_broadcasted_holder_claims(holder_tx, height);
                                let mut to_watch = self.get_broadcasted_holder_watch_outputs(holder_tx, tx);
                                append_onchain_update!(res, to_watch);
                        }
@@ -2054,7 +1907,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                self.holder_tx_signed = true;
                let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
                let txid = commitment_tx.txid();
-               let mut res = vec![commitment_tx];
+               let mut holder_transactions = vec![commitment_tx];
                for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
                        if let Some(vout) = htlc.0.transaction_output_index {
                                let preimage = if !htlc.0.offered {
@@ -2062,24 +1915,32 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                // We can't build an HTLC-Success transaction without the preimage
                                                continue;
                                        }
+                               } else if htlc.0.cltv_expiry > self.best_block.height() + 1 {
+                                       // Don't broadcast HTLC-Timeout transactions immediately as they don't meet the
+                                       // current locktime requirements on-chain. We will broadcast them in
+                                       // `block_confirmed` when `would_broadcast_at_height` returns true.
+                                       // Note that we add + 1 as transactions are broadcastable when they can be
+                                       // confirmed in the next block.
+                                       continue;
                                } else { None };
                                if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(
                                        &::bitcoin::OutPoint { txid, vout }, &preimage) {
-                                       res.push(htlc_tx);
+                                       holder_transactions.push(htlc_tx);
                                }
                        }
                }
                // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
                // The data will be re-generated and tracked in check_spend_holder_transaction if we get a confirmation.
-               return res;
+               holder_transactions
        }
 
        #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
+       /// Note that this includes possibly-locktimed-in-the-future transactions!
        fn unsafe_get_latest_holder_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
                log_trace!(logger, "Getting signed copy of latest holder commitment transaction!");
                let commitment_tx = self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript);
                let txid = commitment_tx.txid();
-               let mut res = vec![commitment_tx];
+               let mut holder_transactions = vec![commitment_tx];
                for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() {
                        if let Some(vout) = htlc.0.transaction_output_index {
                                let preimage = if !htlc.0.offered {
@@ -2090,11 +1951,11 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                } else { None };
                                if let Some(htlc_tx) = self.onchain_tx_handler.unsafe_get_fully_signed_htlc_tx(
                                        &::bitcoin::OutPoint { txid, vout }, &preimage) {
-                                       res.push(htlc_tx);
+                                       holder_transactions.push(htlc_tx);
                                }
                        }
                }
-               return res
+               holder_transactions
        }
 
        pub fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: L) -> Vec<TransactionOutputs>
@@ -2109,7 +1970,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger)
        }
 
-       fn update_best_block<B: Deref, F: Deref, L: Deref>(
+       fn best_block_updated<B: Deref, F: Deref, L: Deref>(
                &mut self,
                header: &BlockHeader,
                height: u32,
@@ -2213,7 +2074,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                height: u32,
                txn_matched: Vec<&Transaction>,
                mut watch_outputs: Vec<TransactionOutputs>,
-               mut claimable_outpoints: Vec<ClaimRequest>,
+               mut claimable_outpoints: Vec<PackageTemplate>,
                broadcaster: B,
                fee_estimator: F,
                logger: L,
@@ -2225,11 +2086,13 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        {
                let should_broadcast = self.would_broadcast_at_height(height, &logger);
                if should_broadcast {
-                       claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { funding_redeemscript: self.funding_redeemscript.clone() }});
+                       let funding_outp = HolderFundingOutput::build(self.funding_redeemscript.clone());
+                       let commitment_package = PackageTemplate::build_package(self.funding_info.0.txid.clone(), self.funding_info.0.index as u32, PackageSolvingData::HolderFundingOutput(funding_outp), height, false, height);
+                       claimable_outpoints.push(commitment_package);
                        self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));
                        let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript);
                        self.holder_tx_signed = true;
-                       let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx);
+                       let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, height);
                        let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx);
                        if !new_outputs.is_empty() {
                                watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs));
@@ -2297,7 +2160,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                        }
                }
 
-               self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, Some(height), &&*broadcaster, &&*fee_estimator, &&*logger);
+               self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, height, &&*broadcaster, &&*fee_estimator, &&*logger);
 
                // Determine new outputs to watch by comparing against previously known outputs to watch,
                // updating the latter in the process.
@@ -2604,7 +2467,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
        fn is_paying_spendable_output<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger {
                let mut spendable_output = None;
                for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us
-                       if i > ::std::u16::MAX as usize {
+                       if i > ::core::u16::MAX as usize {
                                // While it is possible that an output exists on chain which is greater than the
                                // 2^16th output in a given transaction, this is only possible if the output is not
                                // in a lightning transaction and was instead placed there by some third party who
@@ -2675,7 +2538,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 /// transaction and losing money. This is a risk because previous channel states
 /// are toxic, so it's important that whatever channel state is persisted is
 /// kept up-to-date.
-pub trait Persist<ChannelSigner: Sign>: Send + Sync {
+pub trait Persist<ChannelSigner: Sign> {
        /// Persist a new channel's data. The data can be stored any way you want, but
        /// the identifier provided by Rust-Lightning is the channel's outpoint (and
        /// it is up to you to maintain a correct mapping between the outpoint and the
@@ -2727,6 +2590,29 @@ where
        }
 }
 
+impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Confirm for (ChannelMonitor<Signer>, T, F, L)
+where
+       T::Target: BroadcasterInterface,
+       F::Target: FeeEstimator,
+       L::Target: Logger,
+{
+       fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) {
+               self.0.transactions_confirmed(header, txdata, height, &*self.1, &*self.2, &*self.3);
+       }
+
+       fn transaction_unconfirmed(&self, txid: &Txid) {
+               self.0.transaction_unconfirmed(txid, &*self.1, &*self.2, &*self.3);
+       }
+
+       fn best_block_updated(&self, header: &BlockHeader, height: u32) {
+               self.0.best_block_updated(header, height, &*self.1, &*self.2, &*self.3);
+       }
+
+       fn get_relevant_txids(&self) -> Vec<Txid> {
+               self.0.get_relevant_txids()
+       }
+}
+
 const MAX_ALLOC_SIZE: usize = 64*1024;
 
 impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
@@ -2741,11 +2627,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                        }
                }
 
-               let _ver: u8 = Readable::read(reader)?;
-               let min_ver: u8 = Readable::read(reader)?;
-               if min_ver > SERIALIZATION_VERSION {
-                       return Err(DecodeError::UnknownVersion);
-               }
+               let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
 
                let latest_update_id: u64 = Readable::read(reader)?;
                let commitment_transaction_number_obscure_factor = <U48 as Readable>::read(reader)?.0;
@@ -2966,6 +2848,8 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                let lockdown_from_offchain = Readable::read(reader)?;
                let holder_tx_signed = Readable::read(reader)?;
 
+               read_tlv_fields!(reader, {}, {});
+
                let mut secp_ctx = Secp256k1::new();
                secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
 
@@ -3036,9 +2920,10 @@ mod tests {
        use bitcoin::network::constants::Network;
        use hex;
        use chain::channelmonitor::ChannelMonitor;
+       use chain::package::{WEIGHT_OFFERED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_RECEIVED_HTLC, WEIGHT_REVOKED_OUTPUT};
        use chain::transaction::OutPoint;
-       use ln::channelmanager::{BestBlock, PaymentPreimage, PaymentHash};
-       use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
+       use ln::{PaymentPreimage, PaymentHash};
+       use ln::channelmanager::BestBlock;
        use ln::chan_utils;
        use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
        use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};
@@ -3046,12 +2931,13 @@ mod tests {
        use bitcoin::secp256k1::Secp256k1;
        use std::sync::{Arc, Mutex};
        use chain::keysinterface::InMemorySigner;
+       use prelude::*;
 
        #[test]
        fn test_prune_preimages() {
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(TestLogger::new());
-               let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
+               let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))});
                let fee_estimator = Arc::new(TestFeeEstimator { sat_per_kw: 253 });
 
                let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
@@ -3194,25 +3080,25 @@ mod tests {
                let mut sum_actual_sigs = 0;
 
                macro_rules! sign_input {
-                       ($sighash_parts: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
+                       ($sighash_parts: expr, $idx: expr, $amount: expr, $weight: expr, $sum_actual_sigs: expr) => {
                                let htlc = HTLCOutputInCommitment {
-                                       offered: if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::OfferedHTLC { true } else { false },
+                                       offered: if *$weight == WEIGHT_REVOKED_OFFERED_HTLC || *$weight == WEIGHT_OFFERED_HTLC { true } else { false },
                                        amount_msat: 0,
                                        cltv_expiry: 2 << 16,
                                        payment_hash: PaymentHash([1; 32]),
                                        transaction_output_index: Some($idx as u32),
                                };
-                               let redeem_script = if *$input_type == InputDescriptors::RevokedOutput { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
+                               let redeem_script = if *$weight == WEIGHT_REVOKED_OUTPUT { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
                                let sighash = hash_to_message!(&$sighash_parts.signature_hash($idx, &redeem_script, $amount, SigHashType::All)[..]);
                                let sig = secp_ctx.sign(&sighash, &privkey);
                                $sighash_parts.access_witness($idx).push(sig.serialize_der().to_vec());
                                $sighash_parts.access_witness($idx)[0].push(SigHashType::All as u8);
                                sum_actual_sigs += $sighash_parts.access_witness($idx)[0].len();
-                               if *$input_type == InputDescriptors::RevokedOutput {
+                               if *$weight == WEIGHT_REVOKED_OUTPUT {
                                        $sighash_parts.access_witness($idx).push(vec!(1));
-                               } else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
+                               } else if *$weight == WEIGHT_REVOKED_OFFERED_HTLC || *$weight == WEIGHT_REVOKED_RECEIVED_HTLC {
                                        $sighash_parts.access_witness($idx).push(pubkey.clone().serialize().to_vec());
-                               } else if *$input_type == InputDescriptors::ReceivedHTLC {
+                               } else if *$weight == WEIGHT_RECEIVED_HTLC {
                                        $sighash_parts.access_witness($idx).push(vec![0]);
                                } else {
                                        $sighash_parts.access_witness($idx).push(PaymentPreimage([1; 32]).0.to_vec());
@@ -3245,14 +3131,16 @@ mod tests {
                        value: 0,
                });
                let base_weight = claim_tx.get_weight();
-               let inputs_des = vec![InputDescriptors::RevokedOutput, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedReceivedHTLC];
+               let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_RECEIVED_HTLC];
+               let mut inputs_total_weight = 2; // count segwit flags
                {
                        let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
-                       for (idx, inp) in inputs_des.iter().enumerate() {
+                       for (idx, inp) in inputs_weight.iter().enumerate() {
                                sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                               inputs_total_weight += inp;
                        }
                }
-               assert_eq!(base_weight + OnchainTxHandler::<InMemorySigner>::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
+               assert_eq!(base_weight + inputs_total_weight as usize,  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
 
                // Claim tx with 1 offered HTLCs, 3 received HTLCs
                claim_tx.input.clear();
@@ -3269,14 +3157,16 @@ mod tests {
                        });
                }
                let base_weight = claim_tx.get_weight();
-               let inputs_des = vec![InputDescriptors::OfferedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC];
+               let inputs_weight = vec![WEIGHT_OFFERED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_RECEIVED_HTLC];
+               let mut inputs_total_weight = 2; // count segwit flags
                {
                        let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
-                       for (idx, inp) in inputs_des.iter().enumerate() {
+                       for (idx, inp) in inputs_weight.iter().enumerate() {
                                sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                               inputs_total_weight += inp;
                        }
                }
-               assert_eq!(base_weight + OnchainTxHandler::<InMemorySigner>::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
+               assert_eq!(base_weight + inputs_total_weight as usize,  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
 
                // Justice tx with 1 revoked HTLC-Success tx output
                claim_tx.input.clear();
@@ -3291,14 +3181,16 @@ mod tests {
                        witness: Vec::new(),
                });
                let base_weight = claim_tx.get_weight();
-               let inputs_des = vec![InputDescriptors::RevokedOutput];
+               let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT];
+               let mut inputs_total_weight = 2; // count segwit flags
                {
                        let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
-                       for (idx, inp) in inputs_des.iter().enumerate() {
+                       for (idx, inp) in inputs_weight.iter().enumerate() {
                                sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                               inputs_total_weight += inp;
                        }
                }
-               assert_eq!(base_weight + OnchainTxHandler::<InMemorySigner>::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() - sum_actual_sigs));
+               assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_weight.len() - sum_actual_sigs));
        }
 
        // Further testing is done in the ChannelManager integration tests.