Add BOLT 12 features to PaymentParams
[rust-lightning] / lightning / src / ln / chan_utils.rs
index 4690d298aedee2a7f16b18adf09ffee8ac202c4e..9699cc78a1a3253a7635277d22c133a3517b2804 100644 (file)
 // licenses.
 
 //! Various utilities for building scripts and deriving keys related to channels. These are
-//! largely of interest for those implementing chain::keysinterface::Sign message signing by hand.
+//! largely of interest for those implementing the traits on [`chain::keysinterface`] by hand.
 
 use bitcoin::blockdata::script::{Script,Builder};
 use bitcoin::blockdata::opcodes;
-use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, SigHashType};
-use bitcoin::util::bip143;
+use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, EcdsaSighashType};
+use bitcoin::util::sighash;
+use bitcoin::util::address::Payload;
 
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::ripemd160::Hash as Ripemd160;
 use bitcoin::hash_types::{Txid, PubkeyHash};
 
-use ln::{PaymentHash, PaymentPreimage};
-use ln::msgs::DecodeError;
-use util::ser::{Readable, Writeable, Writer};
-use util::byte_utils;
+use crate::chain::keysinterface::EntropySource;
+use crate::ln::{PaymentHash, PaymentPreimage};
+use crate::ln::msgs::DecodeError;
+use crate::util::ser::{Readable, Writeable, Writer};
+use crate::util::transaction_utils;
 
-use bitcoin::hash_types::WPubkeyHash;
-use bitcoin::secp256k1::key::{SecretKey, PublicKey};
-use bitcoin::secp256k1::{Secp256k1, Signature, Message};
-use bitcoin::secp256k1::Error as SecpError;
-use bitcoin::secp256k1;
+use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar};
+use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message};
+use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
+use bitcoin::PublicKey as BitcoinPublicKey;
 
-use io;
-use prelude::*;
+use crate::io;
+use crate::prelude::*;
 use core::cmp;
-use ln::chan_utils;
-use util::transaction_utils::sort_outputs;
-use ln::channel::INITIAL_COMMITMENT_NUMBER;
+use crate::ln::chan_utils;
+use crate::util::transaction_utils::sort_outputs;
+use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI};
 use core::ops::Deref;
-use chain;
-
-pub(crate) const MAX_HTLCS: u16 = 483;
+use crate::chain;
+use crate::util::crypto::{sign, sign_with_aux_rand};
+
+/// Maximum number of one-way in-flight HTLC (protocol-level value).
+pub const MAX_HTLCS: u16 = 483;
+/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor variant.
+pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
+/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, anchor variant.
+pub const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136;
+
+/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value.
+/// We define a range that encompasses both its non-anchors and anchors variants.
+pub(crate) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 136;
+/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value.
+/// We define a range that encompasses both its non-anchors and anchors variants.
+/// This is the maximum post-anchor value.
+pub const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143;
+
+/// Gets the weight for an HTLC-Success transaction.
+#[inline]
+pub fn htlc_success_tx_weight(opt_anchors: bool) -> u64 {
+       const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
+       const HTLC_SUCCESS_ANCHOR_TX_WEIGHT: u64 = 706;
+       if opt_anchors { HTLC_SUCCESS_ANCHOR_TX_WEIGHT } else { HTLC_SUCCESS_TX_WEIGHT }
+}
 
-pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
-pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
+/// Gets the weight for an HTLC-Timeout transaction.
+#[inline]
+pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 {
+       const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
+       const HTLC_TIMEOUT_ANCHOR_TX_WEIGHT: u64 = 666;
+       if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT }
+}
 
-#[derive(PartialEq)]
-pub(crate) enum HTLCType {
-       AcceptedHTLC,
-       OfferedHTLC
+/// Describes the type of HTLC claim as determined by analyzing the witness.
+#[derive(PartialEq, Eq)]
+pub enum HTLCClaim {
+       /// Claims an offered output on a commitment transaction through the timeout path.
+       OfferedTimeout,
+       /// Claims an offered output on a commitment transaction through the success path.
+       OfferedPreimage,
+       /// Claims an accepted output on a commitment transaction through the timeout path.
+       AcceptedTimeout,
+       /// Claims an accepted output on a commitment transaction through the success path.
+       AcceptedPreimage,
+       /// Claims an offered/accepted output on a commitment transaction through the revocation path.
+       Revocation,
 }
 
-impl HTLCType {
-       /// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
-       pub(crate) fn scriptlen_to_htlctype(witness_script_len: usize) ->  Option<HTLCType> {
-               if witness_script_len == 133 {
-                       Some(HTLCType::OfferedHTLC)
-               } else if witness_script_len >= 136 && witness_script_len <= 139 {
-                       Some(HTLCType::AcceptedHTLC)
+impl HTLCClaim {
+       /// Check if a given input witness attempts to claim a HTLC.
+       pub fn from_witness(witness: &Witness) -> Option<Self> {
+               debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
+               if witness.len() < 2 {
+                       return None;
+               }
+               let witness_script = witness.last().unwrap();
+               let second_to_last = witness.second_to_last().unwrap();
+               if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT {
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 32 {
+                               // <remotehtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::OfferedPreimage)
+                       } else if witness.len() == 5 && second_to_last.len() == 0 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+                               Some(Self::OfferedTimeout)
+                       } else {
+                               None
+                       }
+               } else if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS {
+                       // It's possible for the weight of `offered_htlc_script` and `accepted_htlc_script` to
+                       // match so we check for both here.
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 32 {
+                               // <remotehtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::OfferedPreimage)
+                       } else if witness.len() == 5 && second_to_last.len() == 0 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+                               Some(Self::OfferedTimeout)
+                       } else if witness.len() == 3 && second_to_last.len() == 0 {
+                               // <remotehtlcsig> <> <witness_script>
+                               Some(Self::AcceptedTimeout)
+                       } else if witness.len() == 5 && second_to_last.len() == 32 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::AcceptedPreimage)
+                       } else {
+                               None
+                       }
+               } else if witness_script.len() > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT &&
+                       witness_script.len() <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT {
+                       // Handle remaining range of ACCEPTED_HTLC_SCRIPT_WEIGHT.
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 0 {
+                               // <remotehtlcsig> <> <witness_script>
+                               Some(Self::AcceptedTimeout)
+                       } else if witness.len() == 5 && second_to_last.len() == 32 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::AcceptedPreimage)
+                       } else {
+                               None
+                       }
                } else {
                        None
                }
@@ -80,16 +168,61 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32]
        res
 }
 
+/// Build a closing transaction
+pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value_sat: u64, to_holder_script: Script, to_counterparty_script: Script, funding_outpoint: OutPoint) -> Transaction {
+       let txins = {
+               let mut ins: Vec<TxIn> = Vec::new();
+               ins.push(TxIn {
+                       previous_output: funding_outpoint,
+                       script_sig: Script::new(),
+                       sequence: Sequence::MAX,
+                       witness: Witness::new(),
+               });
+               ins
+       };
+
+       let mut txouts: Vec<(TxOut, ())> = Vec::new();
+
+       if to_counterparty_value_sat > 0 {
+               txouts.push((TxOut {
+                       script_pubkey: to_counterparty_script,
+                       value: to_counterparty_value_sat
+               }, ()));
+       }
+
+       if to_holder_value_sat > 0 {
+               txouts.push((TxOut {
+                       script_pubkey: to_holder_script,
+                       value: to_holder_value_sat
+               }, ()));
+       }
+
+       transaction_utils::sort_outputs(&mut txouts, |_, _| { cmp::Ordering::Equal }); // Ordering doesnt matter if they used our pubkey...
+
+       let mut outputs: Vec<TxOut> = Vec::new();
+       for out in txouts.drain(..) {
+               outputs.push(out.0);
+       }
+
+       Transaction {
+               version: 2,
+               lock_time: PackedLockTime::ZERO,
+               input: txins,
+               output: outputs,
+       }
+}
+
 /// Implements the per-commitment secret storage scheme from
-/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
+/// [BOLT 3](https://github.com/lightning/bolts/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
 ///
-/// Allows us to keep track of all of the revocation secrets of counterarties in just 50*32 bytes
+/// Allows us to keep track of all of the revocation secrets of our counterparty in just 50*32 bytes
 /// or so.
 #[derive(Clone)]
-pub(crate) struct CounterpartyCommitmentSecrets {
+pub struct CounterpartyCommitmentSecrets {
        old_secrets: [([u8; 32], u64); 49],
 }
 
+impl Eq for CounterpartyCommitmentSecrets {}
 impl PartialEq for CounterpartyCommitmentSecrets {
        fn eq(&self, other: &Self) -> bool {
                for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in self.old_secrets.iter().zip(other.old_secrets.iter()) {
@@ -102,7 +235,8 @@ impl PartialEq for CounterpartyCommitmentSecrets {
 }
 
 impl CounterpartyCommitmentSecrets {
-       pub(crate) fn new() -> Self {
+       /// Creates a new empty `CounterpartyCommitmentSecrets` structure.
+       pub fn new() -> Self {
                Self { old_secrets: [([0; 32], 1 << 48); 49], }
        }
 
@@ -116,7 +250,9 @@ impl CounterpartyCommitmentSecrets {
                48
        }
 
-       pub(crate) fn get_min_seen_secret(&self) -> u64 {
+       /// Returns the minimum index of all stored secrets. Note that indexes start
+       /// at 1 << 48 and get decremented by one for each new secret.
+       pub fn get_min_seen_secret(&self) -> u64 {
                //TODO This can be optimized?
                let mut min = 1 << 48;
                for &(_, idx) in self.old_secrets.iter() {
@@ -140,7 +276,9 @@ impl CounterpartyCommitmentSecrets {
                res
        }
 
-       pub(crate) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> {
+       /// Inserts the `secret` at `idx`. Returns `Ok(())` if the secret
+       /// was generated in accordance with BOLT 3 and is consistent with previous secrets.
+       pub fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> {
                let pos = Self::place_secret(idx);
                for i in 0..pos {
                        let (old_secret, old_idx) = self.old_secrets[i as usize];
@@ -155,8 +293,9 @@ impl CounterpartyCommitmentSecrets {
                Ok(())
        }
 
-       /// Can only fail if idx is < get_min_seen_secret
-       pub(crate) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
+       /// Returns the secret at `idx`.
+       /// Returns `None` if `idx` is < [`CounterpartyCommitmentSecrets::get_min_seen_secret`].
+       pub fn get_secret(&self, idx: u64) -> Option<[u8; 32]> {
                for i in 0..self.old_secrets.len() {
                        if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 {
                                return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx))
@@ -171,7 +310,7 @@ impl Writeable for CounterpartyCommitmentSecrets {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                for &(ref secret, ref idx) in self.old_secrets.iter() {
                        writer.write_all(secret)?;
-                       writer.write_all(&byte_utils::be64_to_array(*idx))?;
+                       writer.write_all(&idx.to_be_bytes())?;
                }
                write_tlv_fields!(writer, {});
                Ok(())
@@ -191,46 +330,40 @@ impl Readable for CounterpartyCommitmentSecrets {
 
 /// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key)
 /// from the base secret and the per_commitment_point.
-///
-/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
-/// generated (ie our own).
-pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
+pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> SecretKey {
        let mut sha = Sha256::engine();
        sha.input(&per_commitment_point.serialize());
        sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize());
        let res = Sha256::from_engine(sha).into_inner();
 
-       let mut key = base_secret.clone();
-       key.add_assign(&res)?;
-       Ok(key)
+       base_secret.clone().add_tweak(&Scalar::from_be_bytes(res).unwrap())
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
 }
 
 /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
 /// from the base point and the per_commitment_key. This is the public equivalent of
 /// derive_private_key - using only public keys to derive a public key instead of private keys.
-///
-/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
-/// generated (ie our own).
-pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, SecpError> {
+pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
        let mut sha = Sha256::engine();
        sha.input(&per_commitment_point.serialize());
        sha.input(&base_point.serialize());
        let res = Sha256::from_engine(sha).into_inner();
 
-       let hashkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&res)?);
+       let hashkey = PublicKey::from_secret_key(&secp_ctx,
+               &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
        base_point.combine(&hashkey)
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
 }
 
 /// Derives a per-commitment-transaction revocation key from its constituent parts.
 ///
-/// Only the cheating participant owns a valid witness to propagate a revoked 
+/// Only the cheating participant owns a valid witness to propagate a revoked
 /// commitment transaction, thus per_commitment_secret always come from cheater
 /// and revocation_base_secret always come from punisher, which is the broadcaster
 /// of the transaction spending with this key knowledge.
-///
-/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
-/// generated (ie our own).
-pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, countersignatory_revocation_base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
+pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
+       per_commitment_secret: &SecretKey, countersignatory_revocation_base_secret: &SecretKey)
+-> SecretKey {
        let countersignatory_revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &countersignatory_revocation_base_secret);
        let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
 
@@ -249,26 +382,28 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
                Sha256::from_engine(sha).into_inner()
        };
 
-       let mut countersignatory_contrib = countersignatory_revocation_base_secret.clone();
-       countersignatory_contrib.mul_assign(&rev_append_commit_hash_key)?;
-       let mut broadcaster_contrib = per_commitment_secret.clone();
-       broadcaster_contrib.mul_assign(&commit_append_rev_hash_key)?;
-       countersignatory_contrib.add_assign(&broadcaster_contrib[..])?;
-       Ok(countersignatory_contrib)
+       let countersignatory_contrib = countersignatory_revocation_base_secret.clone().mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+               .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs");
+       let broadcaster_contrib = per_commitment_secret.clone().mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+               .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs");
+       countersignatory_contrib.add_tweak(&Scalar::from_be_bytes(broadcaster_contrib.secret_bytes()).unwrap())
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
 }
 
 /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
 /// the public equivalend of derive_private_revocation_key - using only public keys to derive a
 /// public key instead of private keys.
 ///
-/// Only the cheating participant owns a valid witness to propagate a revoked 
+/// Only the cheating participant owns a valid witness to propagate a revoked
 /// commitment transaction, thus per_commitment_point always come from cheater
 /// and revocation_base_point always come from punisher, which is the broadcaster
 /// of the transaction spending with this key knowledge.
 ///
 /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
 /// generated (ie our own).
-pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, countersignatory_revocation_base_point: &PublicKey) -> Result<PublicKey, SecpError> {
+pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>,
+       per_commitment_point: &PublicKey, countersignatory_revocation_base_point: &PublicKey)
+-> PublicKey {
        let rev_append_commit_hash_key = {
                let mut sha = Sha256::engine();
                sha.input(&countersignatory_revocation_base_point.serialize());
@@ -284,11 +419,12 @@ pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp2
                Sha256::from_engine(sha).into_inner()
        };
 
-       let mut countersignatory_contrib = countersignatory_revocation_base_point.clone();
-       countersignatory_contrib.mul_assign(&secp_ctx, &rev_append_commit_hash_key)?;
-       let mut broadcaster_contrib = per_commitment_point.clone();
-       broadcaster_contrib.mul_assign(&secp_ctx, &commit_append_rev_hash_key)?;
+       let countersignatory_contrib = countersignatory_revocation_base_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+               .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+       let broadcaster_contrib = per_commitment_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+               .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
        countersignatory_contrib.combine(&broadcaster_contrib)
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
 }
 
 /// The set of public keys which are used in the creation of one commitment transaction.
@@ -302,7 +438,7 @@ pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp2
 /// channel basepoints via the new function, or they were obtained via
 /// CommitmentTransaction.trust().keys() because we trusted the source of the
 /// pre-calculated keys.
-#[derive(PartialEq, Clone)]
+#[derive(PartialEq, Eq, Clone)]
 pub struct TxCreationKeys {
        /// The broadcaster's per-commitment public key which was used to derive the other keys.
        pub per_commitment_point: PublicKey,
@@ -327,7 +463,7 @@ impl_writeable_tlv_based!(TxCreationKeys, {
 });
 
 /// One counterparty's public keys which do not change over the life of a channel.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct ChannelPublicKeys {
        /// The public key which is used to sign all commitment transactions, as it appears in the
        /// on-chain channel lock-in 2-of-2 multisig output.
@@ -361,19 +497,19 @@ impl_writeable_tlv_based!(ChannelPublicKeys, {
 impl TxCreationKeys {
        /// Create per-state keys from channel base points and the per-commitment point.
        /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions.
-       pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> Result<TxCreationKeys, SecpError> {
-               Ok(TxCreationKeys {
+       pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> TxCreationKeys {
+               TxCreationKeys {
                        per_commitment_point: per_commitment_point.clone(),
-                       revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base)?,
-                       broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base)?,
-                       countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base)?,
-                       broadcaster_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base)?,
-               })
+                       revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base),
+                       broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base),
+                       countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base),
+                       broadcaster_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base),
+               }
        }
 
        /// Generate per-state keys from channel static keys.
        /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions.
-       pub fn from_channel_static_keys<T: secp256k1::Signing + secp256k1::Verification>(per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> Result<TxCreationKeys, SecpError> {
+       pub fn from_channel_static_keys<T: secp256k1::Signing + secp256k1::Verification>(per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> TxCreationKeys {
                TxCreationKeys::derive_new(
                        &secp_ctx,
                        &per_commitment_point,
@@ -408,8 +544,8 @@ pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, contest_delay: u1
        res
 }
 
-#[derive(Clone, PartialEq)]
 /// Information about an HTLC as it appears in a commitment transaction
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct HTLCOutputInCommitment {
        /// Whether the HTLC was "offered" (ie outbound in relation to this commitment transaction).
        /// Note that this is not the same as whether it is ountbound *from us*. To determine that you
@@ -438,10 +574,10 @@ impl_writeable_tlv_based!(HTLCOutputInCommitment, {
 });
 
 #[inline]
-pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, broadcaster_htlc_key: &PublicKey, countersignatory_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script {
+pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, opt_anchors: bool, broadcaster_htlc_key: &PublicKey, countersignatory_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script {
        let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner();
        if htlc.offered {
-               Builder::new().push_opcode(opcodes::all::OP_DUP)
+               let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP)
                              .push_opcode(opcodes::all::OP_HASH160)
                              .push_slice(&PubkeyHash::hash(&revocation_key.serialize())[..])
                              .push_opcode(opcodes::all::OP_EQUAL)
@@ -465,11 +601,16 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit
                              .push_slice(&payment_hash160)
                              .push_opcode(opcodes::all::OP_EQUALVERIFY)
                              .push_opcode(opcodes::all::OP_CHECKSIG)
-                             .push_opcode(opcodes::all::OP_ENDIF)
-                             .push_opcode(opcodes::all::OP_ENDIF)
-                             .into_script()
+                             .push_opcode(opcodes::all::OP_ENDIF);
+               if opt_anchors {
+                       bldr = bldr.push_opcode(opcodes::all::OP_PUSHNUM_1)
+                               .push_opcode(opcodes::all::OP_CSV)
+                               .push_opcode(opcodes::all::OP_DROP);
+               }
+               bldr.push_opcode(opcodes::all::OP_ENDIF)
+                       .into_script()
        } else {
-               Builder::new().push_opcode(opcodes::all::OP_DUP)
+                       let mut bldr = Builder::new().push_opcode(opcodes::all::OP_DUP)
                              .push_opcode(opcodes::all::OP_HASH160)
                              .push_slice(&PubkeyHash::hash(&revocation_key.serialize())[..])
                              .push_opcode(opcodes::all::OP_EQUAL)
@@ -496,17 +637,22 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit
                              .push_opcode(opcodes::all::OP_CLTV)
                              .push_opcode(opcodes::all::OP_DROP)
                              .push_opcode(opcodes::all::OP_CHECKSIG)
-                             .push_opcode(opcodes::all::OP_ENDIF)
-                             .push_opcode(opcodes::all::OP_ENDIF)
-                             .into_script()
+                             .push_opcode(opcodes::all::OP_ENDIF);
+               if opt_anchors {
+                       bldr = bldr.push_opcode(opcodes::all::OP_PUSHNUM_1)
+                               .push_opcode(opcodes::all::OP_CSV)
+                               .push_opcode(opcodes::all::OP_DROP);
+               }
+               bldr.push_opcode(opcodes::all::OP_ENDIF)
+                       .into_script()
        }
 }
 
 /// Gets the witness redeemscript for an HTLC output in a commitment transaction. Note that htlc
 /// does not need to have its previous_output_index filled.
 #[inline]
-pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Script {
-       get_htlc_redeemscript_with_explicit_keys(htlc, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key)
+pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, opt_anchors: bool, keys: &TxCreationKeys) -> Script {
+       get_htlc_redeemscript_with_explicit_keys(htlc, opt_anchors, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key)
 }
 
 /// Gets the redeemscript for a funding output from the two funding public keys.
@@ -515,13 +661,17 @@ pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &Pub
        let broadcaster_funding_key = broadcaster.serialize();
        let countersignatory_funding_key = countersignatory.serialize();
 
+       make_funding_redeemscript_from_slices(&broadcaster_funding_key, &countersignatory_funding_key)
+}
+
+pub(crate) fn make_funding_redeemscript_from_slices(broadcaster_funding_key: &[u8], countersignatory_funding_key: &[u8]) -> Script {
        let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2);
        if broadcaster_funding_key[..] < countersignatory_funding_key[..] {
-               builder.push_slice(&broadcaster_funding_key)
-                       .push_slice(&countersignatory_funding_key)
+               builder.push_slice(broadcaster_funding_key)
+                       .push_slice(countersignatory_funding_key)
        } else {
-               builder.push_slice(&countersignatory_funding_key)
-                       .push_slice(&broadcaster_funding_key)
+               builder.push_slice(countersignatory_funding_key)
+                       .push_slice(broadcaster_funding_key)
        }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script()
 }
 
@@ -532,36 +682,129 @@ pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &Pub
 ///
 /// Panics if htlc.transaction_output_index.is_none() (as such HTLCs do not appear in the
 /// commitment transaction).
-pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
+pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, opt_anchors: bool, use_non_zero_fee_anchors: bool, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
        let mut txins: Vec<TxIn> = Vec::new();
-       txins.push(TxIn {
+       txins.push(build_htlc_input(commitment_txid, htlc, opt_anchors));
+
+       let mut txouts: Vec<TxOut> = Vec::new();
+       txouts.push(build_htlc_output(
+               feerate_per_kw, contest_delay, htlc, opt_anchors, use_non_zero_fee_anchors,
+               broadcaster_delayed_payment_key, revocation_key
+       ));
+
+       Transaction {
+               version: 2,
+               lock_time: PackedLockTime(if htlc.offered { htlc.cltv_expiry } else { 0 }),
+               input: txins,
+               output: txouts,
+       }
+}
+
+pub(crate) fn build_htlc_input(commitment_txid: &Txid, htlc: &HTLCOutputInCommitment, opt_anchors: bool) -> TxIn {
+       TxIn {
                previous_output: OutPoint {
                        txid: commitment_txid.clone(),
                        vout: htlc.transaction_output_index.expect("Can't build an HTLC transaction for a dust output"),
                },
                script_sig: Script::new(),
-               sequence: 0,
-               witness: Vec::new(),
-       });
+               sequence: Sequence(if opt_anchors { 1 } else { 0 }),
+               witness: Witness::new(),
+       }
+}
 
-       let total_fee = if htlc.offered {
-                       feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000
-               } else {
-                       feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000
-               };
+pub(crate) fn build_htlc_output(
+       feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, opt_anchors: bool,
+       use_non_zero_fee_anchors: bool, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey
+) -> TxOut {
+       let weight = if htlc.offered {
+               htlc_timeout_tx_weight(opt_anchors)
+       } else {
+               htlc_success_tx_weight(opt_anchors)
+       };
+       let output_value = if opt_anchors && !use_non_zero_fee_anchors {
+               htlc.amount_msat / 1000
+       } else {
+               let total_fee = feerate_per_kw as u64 * weight / 1000;
+               htlc.amount_msat / 1000 - total_fee
+       };
 
-       let mut txouts: Vec<TxOut> = Vec::new();
-       txouts.push(TxOut {
+       TxOut {
                script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_v0_p2wsh(),
-               value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
-       });
+               value: output_value,
+       }
+}
 
-       Transaction {
-               version: 2,
-               lock_time: if htlc.offered { htlc.cltv_expiry } else { 0 },
-               input: txins,
-               output: txouts,
+/// Returns the witness required to satisfy and spend a HTLC input.
+pub fn build_htlc_input_witness(
+       local_sig: &Signature, remote_sig: &Signature, preimage: &Option<PaymentPreimage>,
+       redeem_script: &Script, opt_anchors: bool,
+) -> Witness {
+       let remote_sighash_type = if opt_anchors {
+               EcdsaSighashType::SinglePlusAnyoneCanPay
+       } else {
+               EcdsaSighashType::All
+       };
+
+       let mut witness = Witness::new();
+       // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
+       witness.push(vec![]);
+       witness.push_bitcoin_signature(&remote_sig.serialize_der(), remote_sighash_type);
+       witness.push_bitcoin_signature(&local_sig.serialize_der(), EcdsaSighashType::All);
+       if let Some(preimage) = preimage {
+               witness.push(preimage.0.to_vec());
+       } else {
+               // Due to BIP146 (MINIMALIF) this must be a zero-length element to relay.
+               witness.push(vec![]);
        }
+       witness.push(redeem_script.to_bytes());
+       witness
+}
+
+/// Gets the witnessScript for the to_remote output when anchors are enabled.
+#[inline]
+pub fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script {
+       Builder::new()
+               .push_slice(&payment_point.serialize()[..])
+               .push_opcode(opcodes::all::OP_CHECKSIGVERIFY)
+               .push_int(1)
+               .push_opcode(opcodes::all::OP_CSV)
+               .into_script()
+}
+
+/// Gets the witnessScript for an anchor output from the funding public key.
+/// The witness in the spending input must be:
+/// <BIP 143 funding_signature>
+/// After 16 blocks of confirmation, an alternative satisfying witness could be:
+/// <>
+/// (empty vector required to satisfy compliance with MINIMALIF-standard rule)
+#[inline]
+pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script {
+       Builder::new().push_slice(&funding_pubkey.serialize()[..])
+               .push_opcode(opcodes::all::OP_CHECKSIG)
+               .push_opcode(opcodes::all::OP_IFDUP)
+               .push_opcode(opcodes::all::OP_NOTIF)
+               .push_int(16)
+               .push_opcode(opcodes::all::OP_CSV)
+               .push_opcode(opcodes::all::OP_ENDIF)
+               .into_script()
+}
+
+#[cfg(anchors)]
+/// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`.
+pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> {
+       let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh();
+       commitment_tx.output.iter().enumerate()
+               .find(|(_, txout)| txout.script_pubkey == anchor_script)
+               .map(|(idx, txout)| (idx as u32, txout))
+}
+
+/// Returns the witness required to satisfy and spend an anchor input.
+pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
+       let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
+       let mut ret = Witness::new();
+       ret.push_bitcoin_signature(&funding_sig.serialize_der(), EcdsaSighashType::All);
+       ret.push(anchor_redeem_script.as_bytes());
+       ret
 }
 
 /// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
@@ -569,7 +812,7 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte
 ///
 /// Normally, this is converted to the broadcaster/countersignatory-organized DirectedChannelTransactionParameters
 /// before use, via the as_holder_broadcastable and as_counterparty_broadcastable functions.
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct ChannelTransactionParameters {
        /// Holder public keys
        pub holder_pubkeys: ChannelPublicKeys,
@@ -583,10 +826,17 @@ pub struct ChannelTransactionParameters {
        pub counterparty_parameters: Option<CounterpartyChannelTransactionParameters>,
        /// The late-bound funding outpoint
        pub funding_outpoint: Option<chain::transaction::OutPoint>,
+       /// Are anchors (zero fee HTLC transaction variant) used for this channel. Boolean is
+       /// serialization backwards-compatible.
+       pub opt_anchors: Option<()>,
+       /// Are non-zero-fee anchors are enabled (used in conjuction with opt_anchors)
+       /// It is intended merely for backwards compatibility with signers that need it.
+       /// There is no support for this feature in LDK channel negotiation.
+       pub opt_non_zero_fee_anchors: Option<()>,
 }
 
 /// Late-bound per-channel counterparty data used to build transactions.
-#[derive(Clone)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct CounterpartyChannelTransactionParameters {
        /// Counter-party public keys
        pub pubkeys: ChannelPublicKeys,
@@ -636,6 +886,8 @@ impl_writeable_tlv_based!(ChannelTransactionParameters, {
        (4, is_outbound_from_holder, required),
        (6, counterparty_parameters, option),
        (8, funding_outpoint, option),
+       (10, opt_anchors, option),
+       (12, opt_non_zero_fee_anchors, option),
 });
 
 /// Static channel fields used to build transactions given per-commitment fields, organized by
@@ -688,6 +940,11 @@ impl<'a> DirectedChannelTransactionParameters<'a> {
        pub fn funding_outpoint(&self) -> OutPoint {
                self.inner.funding_outpoint.unwrap().into_bitcoin_outpoint()
        }
+
+       /// Whether to use anchors for this channel
+       pub fn opt_anchors(&self) -> bool {
+               self.inner.opt_anchors.is_some()
+       }
 }
 
 /// Information needed to build and sign a holder's commitment transaction.
@@ -711,6 +968,7 @@ impl Deref for HolderCommitmentTransaction {
        fn deref(&self) -> &Self::Target { &self.inner }
 }
 
+impl Eq for HolderCommitmentTransaction {}
 impl PartialEq for HolderCommitmentTransaction {
        // We dont care whether we are signed in equality comparison
        fn eq(&self, o: &Self) -> bool {
@@ -727,10 +985,10 @@ impl_writeable_tlv_based!(HolderCommitmentTransaction, {
 
 impl HolderCommitmentTransaction {
        #[cfg(test)]
-       pub fn dummy() -> Self {
+       pub fn dummy(htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> Self {
                let secp_ctx = Secp256k1::new();
                let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
-               let dummy_sig = secp_ctx.sign(&secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
+               let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
 
                let keys = TxCreationKeys {
                        per_commitment_point: dummy_key.clone(),
@@ -751,14 +1009,20 @@ impl HolderCommitmentTransaction {
                        holder_selected_contest_delay: 0,
                        is_outbound_from_holder: false,
                        counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: channel_pubkeys.clone(), selected_contest_delay: 0 }),
-                       funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 })
+                       funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }),
+                       opt_anchors: None,
+                       opt_non_zero_fee_anchors: None,
                };
-               let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
-               let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
+               let mut counterparty_htlc_sigs = Vec::new();
+               for _ in 0..htlcs.len() {
+                       counterparty_htlc_sigs.push(dummy_sig);
+               }
+               let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, false, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
+               htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
                HolderCommitmentTransaction {
                        inner,
                        counterparty_sig: dummy_sig,
-                       counterparty_htlc_sigs: Vec::new(),
+                       counterparty_htlc_sigs,
                        holder_sig_first: false
                }
        }
@@ -780,14 +1044,12 @@ impl HolderCommitmentTransaction {
                tx.input[0].witness.push(Vec::new());
 
                if self.holder_sig_first {
-                       tx.input[0].witness.push(holder_sig.serialize_der().to_vec());
-                       tx.input[0].witness.push(self.counterparty_sig.serialize_der().to_vec());
+                       tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
+                       tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
                } else {
-                       tx.input[0].witness.push(self.counterparty_sig.serialize_der().to_vec());
-                       tx.input[0].witness.push(holder_sig.serialize_der().to_vec());
+                       tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
+                       tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
                }
-               tx.input[0].witness[1].push(SigHashType::All as u8);
-               tx.input[0].witness[2].push(SigHashType::All as u8);
 
                tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
                tx
@@ -816,7 +1078,139 @@ impl BuiltCommitmentTransaction {
        ///
        /// This can be used to verify a signature.
        pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
-               let sighash = &bip143::SigHashCache::new(&self.transaction).signature_hash(0, funding_redeemscript, channel_value_satoshis, SigHashType::All)[..];
+               let sighash = &sighash::SighashCache::new(&self.transaction).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
+               hash_to_message!(sighash)
+       }
+
+       /// Signs the counterparty's commitment transaction.
+       pub fn sign_counterparty_commitment<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
+               let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+               sign(secp_ctx, &sighash, funding_key)
+       }
+
+       /// Signs the holder commitment transaction because we are about to broadcast it.
+       pub fn sign_holder_commitment<T: secp256k1::Signing, ES: Deref>(
+               &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64,
+               entropy_source: &ES, secp_ctx: &Secp256k1<T>
+       ) -> Signature where ES::Target: EntropySource {
+               let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+               sign_with_aux_rand(secp_ctx, &sighash, funding_key, entropy_source)
+       }
+}
+
+/// This class tracks the per-transaction information needed to build a closing transaction and will
+/// actually build it and sign.
+///
+/// This class can be used inside a signer implementation to generate a signature given the relevant
+/// secret key.
+#[derive(Clone, Hash, PartialEq, Eq)]
+pub struct ClosingTransaction {
+       to_holder_value_sat: u64,
+       to_counterparty_value_sat: u64,
+       to_holder_script: Script,
+       to_counterparty_script: Script,
+       built: Transaction,
+}
+
+impl ClosingTransaction {
+       /// Construct an object of the class
+       pub fn new(
+               to_holder_value_sat: u64,
+               to_counterparty_value_sat: u64,
+               to_holder_script: Script,
+               to_counterparty_script: Script,
+               funding_outpoint: OutPoint,
+       ) -> Self {
+               let built = build_closing_transaction(
+                       to_holder_value_sat, to_counterparty_value_sat,
+                       to_holder_script.clone(), to_counterparty_script.clone(),
+                       funding_outpoint
+               );
+               ClosingTransaction {
+                       to_holder_value_sat,
+                       to_counterparty_value_sat,
+                       to_holder_script,
+                       to_counterparty_script,
+                       built
+               }
+       }
+
+       /// Trust our pre-built transaction.
+       ///
+       /// Applies a wrapper which allows access to the transaction.
+       ///
+       /// This should only be used if you fully trust the builder of this object. It should not
+       /// be used by an external signer - instead use the verify function.
+       pub fn trust(&self) -> TrustedClosingTransaction {
+               TrustedClosingTransaction { inner: self }
+       }
+
+       /// Verify our pre-built transaction.
+       ///
+       /// Applies a wrapper which allows access to the transaction.
+       ///
+       /// An external validating signer must call this method before signing
+       /// or using the built transaction.
+       pub fn verify(&self, funding_outpoint: OutPoint) -> Result<TrustedClosingTransaction, ()> {
+               let built = build_closing_transaction(
+                       self.to_holder_value_sat, self.to_counterparty_value_sat,
+                       self.to_holder_script.clone(), self.to_counterparty_script.clone(),
+                       funding_outpoint
+               );
+               if self.built != built {
+                       return Err(())
+               }
+               Ok(TrustedClosingTransaction { inner: self })
+       }
+
+       /// The value to be sent to the holder, or zero if the output will be omitted
+       pub fn to_holder_value_sat(&self) -> u64 {
+               self.to_holder_value_sat
+       }
+
+       /// The value to be sent to the counterparty, or zero if the output will be omitted
+       pub fn to_counterparty_value_sat(&self) -> u64 {
+               self.to_counterparty_value_sat
+       }
+
+       /// The destination of the holder's output
+       pub fn to_holder_script(&self) -> &Script {
+               &self.to_holder_script
+       }
+
+       /// The destination of the counterparty's output
+       pub fn to_counterparty_script(&self) -> &Script {
+               &self.to_counterparty_script
+       }
+}
+
+/// A wrapper on ClosingTransaction indicating that the built bitcoin
+/// transaction is trusted.
+///
+/// See trust() and verify() functions on CommitmentTransaction.
+///
+/// This structure implements Deref.
+pub struct TrustedClosingTransaction<'a> {
+       inner: &'a ClosingTransaction,
+}
+
+impl<'a> Deref for TrustedClosingTransaction<'a> {
+       type Target = ClosingTransaction;
+
+       fn deref(&self) -> &Self::Target { self.inner }
+}
+
+impl<'a> TrustedClosingTransaction<'a> {
+       /// The pre-built Bitcoin commitment transaction
+       pub fn built_transaction(&self) -> &Transaction {
+               &self.inner.built
+       }
+
+       /// Get the SIGHASH_ALL sighash value of the transaction.
+       ///
+       /// This can be used to verify a signature.
+       pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
+               let sighash = &sighash::SighashCache::new(&self.inner.built).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
                hash_to_message!(sighash)
        }
 
@@ -824,11 +1218,11 @@ impl BuiltCommitmentTransaction {
        /// because we are about to broadcast a holder transaction.
        pub fn sign<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
                let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
-               secp_ctx.sign(&sighash, funding_key)
+               sign(secp_ctx, &sighash, funding_key)
        }
 }
 
-/// This class tracks the per-transaction information needed to build a commitment transaction and to
+/// This class tracks the per-transaction information needed to build a commitment transaction and will
 /// actually build it and sign.  It is used for holder transactions that we sign only when needed
 /// and for transactions we sign for the counterparty.
 ///
@@ -841,12 +1235,17 @@ pub struct CommitmentTransaction {
        to_countersignatory_value_sat: u64,
        feerate_per_kw: u32,
        htlcs: Vec<HTLCOutputInCommitment>,
+       // A boolean that is serialization backwards-compatible
+       opt_anchors: Option<()>,
+       // Whether non-zero-fee anchors should be used
+       opt_non_zero_fee_anchors: Option<()>,
        // A cache of the parties' pubkeys required to construct the transaction, see doc for trust()
        keys: TxCreationKeys,
        // For access to the pre-built transaction, see doc for trust()
        built: BuiltCommitmentTransaction,
 }
 
+impl Eq for CommitmentTransaction {}
 impl PartialEq for CommitmentTransaction {
        fn eq(&self, o: &Self) -> bool {
                let eq = self.commitment_number == o.commitment_number &&
@@ -854,6 +1253,7 @@ impl PartialEq for CommitmentTransaction {
                        self.to_countersignatory_value_sat == o.to_countersignatory_value_sat &&
                        self.feerate_per_kw == o.feerate_per_kw &&
                        self.htlcs == o.htlcs &&
+                       self.opt_anchors == o.opt_anchors &&
                        self.keys == o.keys;
                if eq {
                        debug_assert_eq!(self.built.transaction, o.built.transaction);
@@ -871,6 +1271,8 @@ impl_writeable_tlv_based!(CommitmentTransaction, {
        (8, keys, required),
        (10, built, required),
        (12, htlcs, vec_type),
+       (14, opt_anchors, option),
+       (16, opt_non_zero_fee_anchors, option),
 });
 
 impl CommitmentTransaction {
@@ -883,10 +1285,10 @@ impl CommitmentTransaction {
        ///
        /// Only include HTLCs that are above the dust limit for the channel.
        ///
-       /// (C-not exported) due to the generic though we likely should expose a version without
-       pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
+       /// This is not exported to bindings users due to the generic though we likely should expose a version without
+       pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, opt_anchors: bool, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
                // Sort outputs and populate output indices while keeping track of the auxiliary data
-               let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
+               let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, opt_anchors, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
 
                let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
                let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
@@ -897,19 +1299,29 @@ impl CommitmentTransaction {
                        to_countersignatory_value_sat,
                        feerate_per_kw,
                        htlcs,
+                       opt_anchors: if opt_anchors { Some(()) } else { None },
                        keys,
                        built: BuiltCommitmentTransaction {
                                transaction,
                                txid
                        },
+                       opt_non_zero_fee_anchors: None,
                }
        }
 
-       fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters) -> Result<BuiltCommitmentTransaction, ()> {
+       /// Use non-zero fee anchors
+       ///
+       /// This is not exported to bindings users due to move, and also not likely to be useful for binding users
+       pub fn with_non_zero_fee_anchors(mut self) -> Self {
+               self.opt_non_zero_fee_anchors = Some(());
+               self
+       }
+
+       fn internal_rebuild_transaction(&self, keys: &TxCreationKeys, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<BuiltCommitmentTransaction, ()> {
                let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(self.commitment_number, channel_parameters);
 
                let mut htlcs_with_aux = self.htlcs.iter().map(|h| (h.clone(), ())).collect();
-               let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters)?;
+               let (outputs, _) = Self::internal_build_outputs(keys, self.to_broadcaster_value_sat, self.to_countersignatory_value_sat, &mut htlcs_with_aux, channel_parameters, self.opt_anchors.is_some(), broadcaster_funding_key, countersignatory_funding_key)?;
 
                let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
                let txid = transaction.txid();
@@ -923,7 +1335,7 @@ impl CommitmentTransaction {
        fn make_transaction(obscured_commitment_transaction_number: u64, txins: Vec<TxIn>, outputs: Vec<TxOut>) -> Transaction {
                Transaction {
                        version: 2,
-                       lock_time: ((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
+                       lock_time: PackedLockTime(((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32)),
                        input: txins,
                        output: outputs,
                }
@@ -933,14 +1345,18 @@ impl CommitmentTransaction {
        // - initial sorting of outputs / HTLCs in the constructor, in which case T is auxiliary data the
        //   caller needs to have sorted together with the HTLCs so it can keep track of the output index
        // - building of a bitcoin transaction during a verify() call, in which case T is just ()
-       fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
+       fn internal_build_outputs<T>(keys: &TxCreationKeys, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, opt_anchors: bool, broadcaster_funding_key: &PublicKey, countersignatory_funding_key: &PublicKey) -> Result<(Vec<TxOut>, Vec<HTLCOutputInCommitment>), ()> {
                let countersignatory_pubkeys = channel_parameters.countersignatory_pubkeys();
                let contest_delay = channel_parameters.contest_delay();
 
                let mut txouts: Vec<(TxOut, Option<&mut HTLCOutputInCommitment>)> = Vec::new();
 
                if to_countersignatory_value_sat > 0 {
-                       let script = script_for_p2wpkh(&countersignatory_pubkeys.payment_point);
+                       let script = if opt_anchors {
+                           get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_v0_p2wsh()
+                       } else {
+                           Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)).unwrap().script_pubkey()
+                       };
                        txouts.push((
                                TxOut {
                                        script_pubkey: script.clone(),
@@ -965,9 +1381,33 @@ impl CommitmentTransaction {
                        ));
                }
 
+               if opt_anchors {
+                       if to_broadcaster_value_sat > 0 || !htlcs_with_aux.is_empty() {
+                               let anchor_script = get_anchor_redeemscript(broadcaster_funding_key);
+                               txouts.push((
+                                       TxOut {
+                                               script_pubkey: anchor_script.to_v0_p2wsh(),
+                                               value: ANCHOR_OUTPUT_VALUE_SATOSHI,
+                                       },
+                                       None,
+                               ));
+                       }
+
+                       if to_countersignatory_value_sat > 0 || !htlcs_with_aux.is_empty() {
+                               let anchor_script = get_anchor_redeemscript(countersignatory_funding_key);
+                               txouts.push((
+                                       TxOut {
+                                               script_pubkey: anchor_script.to_v0_p2wsh(),
+                                               value: ANCHOR_OUTPUT_VALUE_SATOSHI,
+                                       },
+                                       None,
+                               ));
+                       }
+               }
+
                let mut htlcs = Vec::with_capacity(htlcs_with_aux.len());
                for (htlc, _) in htlcs_with_aux {
-                       let script = chan_utils::get_htlc_redeemscript(&htlc, &keys);
+                       let script = chan_utils::get_htlc_redeemscript(&htlc, opt_anchors, &keys);
                        let txout = TxOut {
                                script_pubkey: script.to_v0_p2wsh(),
                                value: htlc.amount_msat / 1000,
@@ -982,7 +1422,7 @@ impl CommitmentTransaction {
                                if let &Some(ref b_htlcout) = b {
                                        a_htlcout.cltv_expiry.cmp(&b_htlcout.cltv_expiry)
                                                // Note that due to hash collisions, we have to have a fallback comparison
-                                               // here for fuzztarget mode (otherwise at least chanmon_fail_consistency
+                                               // here for fuzzing mode (otherwise at least chanmon_fail_consistency
                                                // may fail)!
                                                .then(a_htlcout.payment_hash.0.cmp(&b_htlcout.payment_hash.0))
                                // For non-HTLC outputs, if they're copying our SPK we don't really care if we
@@ -1019,9 +1459,9 @@ impl CommitmentTransaction {
                        ins.push(TxIn {
                                previous_output: channel_parameters.funding_outpoint(),
                                script_sig: Script::new(),
-                               sequence: ((0x80 as u32) << 8 * 3)
-                                       | ((obscured_commitment_transaction_number >> 3 * 8) as u32),
-                               witness: Vec::new(),
+                               sequence: Sequence(((0x80 as u32) << 8 * 3)
+                                       | ((obscured_commitment_transaction_number >> 3 * 8) as u32)),
+                               witness: Witness::new(),
                        });
                        ins
                };
@@ -1052,7 +1492,7 @@ impl CommitmentTransaction {
        /// which were included in this commitment transaction in output order.
        /// The transaction index is always populated.
        ///
-       /// (C-not exported) as we cannot currently convert Vec references to/from C, though we should
+       /// This is not exported to bindings users as we cannot currently convert Vec references to/from C, though we should
        /// expose a less effecient version which creates a Vec of references in the future.
        pub fn htlcs(&self) -> &Vec<HTLCOutputInCommitment> {
                &self.htlcs
@@ -1063,7 +1503,7 @@ impl CommitmentTransaction {
        /// Applies a wrapper which allows access to these fields.
        ///
        /// This should only be used if you fully trust the builder of this object.  It should not
-       ///     be used by an external signer - instead use the verify function.
+       /// be used by an external signer - instead use the verify function.
        pub fn trust(&self) -> TrustedCommitmentTransaction {
                TrustedCommitmentTransaction { inner: self }
        }
@@ -1077,11 +1517,11 @@ impl CommitmentTransaction {
        pub fn verify<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> Result<TrustedCommitmentTransaction, ()> {
                // This is the only field of the key cache that we trust
                let per_commitment_point = self.keys.per_commitment_point;
-               let keys = TxCreationKeys::from_channel_static_keys(&per_commitment_point, broadcaster_keys, countersignatory_keys, secp_ctx).unwrap();
+               let keys = TxCreationKeys::from_channel_static_keys(&per_commitment_point, broadcaster_keys, countersignatory_keys, secp_ctx);
                if keys != self.keys {
                        return Err(());
                }
-               let tx = self.internal_rebuild_transaction(&keys, channel_parameters)?;
+               let tx = self.internal_rebuild_transaction(&keys, channel_parameters, &broadcaster_keys.funding_pubkey, &countersignatory_keys.funding_pubkey)?;
                if self.built.transaction != tx.transaction || self.built.txid != tx.txid {
                        return Err(());
                }
@@ -1121,25 +1561,35 @@ impl<'a> TrustedCommitmentTransaction<'a> {
                &self.inner.keys
        }
 
+       /// Should anchors be used.
+       pub fn opt_anchors(&self) -> bool {
+               self.opt_anchors.is_some()
+       }
+
        /// Get a signature for each HTLC which was included in the commitment transaction (ie for
        /// which HTLCOutputInCommitment::transaction_output_index.is_some()).
        ///
        /// The returned Vec has one entry for each HTLC, and in the same order.
-       pub fn get_htlc_sigs<T: secp256k1::Signing>(&self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<T>) -> Result<Vec<Signature>, ()> {
+       ///
+       /// This function is only valid in the holder commitment context, it always uses EcdsaSighashType::All.
+       pub fn get_htlc_sigs<T: secp256k1::Signing, ES: Deref>(
+               &self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters,
+               entropy_source: &ES, secp_ctx: &Secp256k1<T>,
+       ) -> Result<Vec<Signature>, ()> where ES::Target: EntropySource {
                let inner = self.inner;
                let keys = &inner.keys;
                let txid = inner.built.txid;
                let mut ret = Vec::with_capacity(inner.htlcs.len());
-               let holder_htlc_key = derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key).map_err(|_| ())?;
+               let holder_htlc_key = derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key);
 
                for this_htlc in inner.htlcs.iter() {
                        assert!(this_htlc.transaction_output_index.is_some());
-                       let htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
+                       let htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, self.opt_anchors(), self.opt_non_zero_fee_anchors.is_some(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
 
-                       let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
+                       let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
 
-                       let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, SigHashType::All)[..]);
-                       ret.push(secp_ctx.sign(&sighash, &holder_htlc_key));
+                       let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]);
+                       ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source));
                }
                Ok(ret)
        }
@@ -1156,26 +1606,13 @@ impl<'a> TrustedCommitmentTransaction<'a> {
                // Further, we should never be provided the preimage for an HTLC-Timeout transaction.
                if  this_htlc.offered && preimage.is_some() { unreachable!(); }
 
-               let mut htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
-
-               let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
-
-               // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
-               htlc_tx.input[0].witness.push(Vec::new());
-
-               htlc_tx.input[0].witness.push(counterparty_signature.serialize_der().to_vec());
-               htlc_tx.input[0].witness.push(signature.serialize_der().to_vec());
-               htlc_tx.input[0].witness[1].push(SigHashType::All as u8);
-               htlc_tx.input[0].witness[2].push(SigHashType::All as u8);
+               let mut htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, self.opt_anchors(), self.opt_non_zero_fee_anchors.is_some(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
 
-               if this_htlc.offered {
-                       // Due to BIP146 (MINIMALIF) this must be a zero-length element to relay.
-                       htlc_tx.input[0].witness.push(Vec::new());
-               } else {
-                       htlc_tx.input[0].witness.push(preimage.unwrap().0.to_vec());
-               }
+               let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
 
-               htlc_tx.input[0].witness.push(htlc_redeemscript.as_bytes().to_vec());
+               htlc_tx.input[0].witness = chan_utils::build_htlc_input_witness(
+                       signature, counterparty_signature, preimage, &htlc_redeemscript, self.opt_anchors(),
+               );
                htlc_tx
        }
 }
@@ -1210,17 +1647,149 @@ pub fn get_commitment_transaction_number_obscure_factor(
                | ((res[31] as u64) << 0 * 8)
 }
 
-fn script_for_p2wpkh(key: &PublicKey) -> Script {
-       Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
-               .push_slice(&WPubkeyHash::hash(&key.serialize())[..])
-               .into_script()
-}
-
 #[cfg(test)]
 mod tests {
        use super::CounterpartyCommitmentSecrets;
-       use hex;
-       use prelude::*;
+       use crate::{hex, chain};
+       use crate::prelude::*;
+       use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
+       use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
+       use crate::util::test_utils;
+       use crate::chain::keysinterface::{ChannelSigner, SignerProvider};
+       use bitcoin::{Network, Txid};
+       use bitcoin::hashes::Hash;
+       use crate::ln::PaymentHash;
+       use bitcoin::hashes::hex::ToHex;
+       use bitcoin::util::address::Payload;
+       use bitcoin::PublicKey as BitcoinPublicKey;
+
+       #[test]
+       fn test_anchors() {
+               let secp_ctx = Secp256k1::new();
+
+               let seed = [42; 32];
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
+               let signer = keys_provider.derive_channel_signer(3000, keys_provider.generate_channel_keys_id(false, 1_000_000, 0));
+               let counterparty_signer = keys_provider.derive_channel_signer(3000, keys_provider.generate_channel_keys_id(true, 1_000_000, 1));
+               let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint;
+               let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
+               let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
+               let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
+               let holder_pubkeys = signer.pubkeys();
+               let counterparty_pubkeys = counterparty_signer.pubkeys();
+               let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
+               let mut channel_parameters = ChannelTransactionParameters {
+                       holder_pubkeys: holder_pubkeys.clone(),
+                       holder_selected_contest_delay: 0,
+                       is_outbound_from_holder: false,
+                       counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), selected_contest_delay: 0 }),
+                       funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }),
+                       opt_anchors: None,
+                       opt_non_zero_fee_anchors: None,
+               };
+
+               let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
+
+               // Generate broadcaster and counterparty outputs
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 1000, 2000,
+                       false,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 2);
+               assert_eq!(tx.built.transaction.output[1].script_pubkey, Payload::p2wpkh(&BitcoinPublicKey::new(counterparty_pubkeys.payment_point)).unwrap().script_pubkey());
+
+               // Generate broadcaster and counterparty outputs as well as two anchors
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 1000, 2000,
+                       true,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 4);
+               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_to_countersignatory_with_anchors_redeemscript(&counterparty_pubkeys.payment_point).to_v0_p2wsh());
+
+               // Generate broadcaster output and anchor
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 3000, 0,
+                       true,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 2);
+
+               // Generate counterparty output and anchor
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 0, 3000,
+                       true,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 2);
+
+               let received_htlc = HTLCOutputInCommitment {
+                       offered: false,
+                       amount_msat: 400000,
+                       cltv_expiry: 100,
+                       payment_hash: PaymentHash([42; 32]),
+                       transaction_output_index: None,
+               };
+
+               let offered_htlc = HTLCOutputInCommitment {
+                       offered: true,
+                       amount_msat: 600000,
+                       cltv_expiry: 100,
+                       payment_hash: PaymentHash([43; 32]),
+                       transaction_output_index: None,
+               };
+
+               // Generate broadcaster output and received and offered HTLC outputs,  w/o anchors
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 3000, 0,
+                       false,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())],
+                       &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 3);
+               assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, false, &keys).to_v0_p2wsh());
+               assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, false, &keys).to_v0_p2wsh());
+               assert_eq!(get_htlc_redeemscript(&received_htlc, false, &keys).to_v0_p2wsh().to_hex(),
+                                  "0020e43a7c068553003fe68fcae424fb7b28ec5ce48cd8b6744b3945631389bad2fb");
+               assert_eq!(get_htlc_redeemscript(&offered_htlc, false, &keys).to_v0_p2wsh().to_hex(),
+                                  "0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d");
+
+               // Generate broadcaster output and received and offered HTLC outputs,  with anchors
+               channel_parameters.opt_anchors = Some(());
+               let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
+                       0, 3000, 0,
+                       true,
+                       holder_pubkeys.funding_pubkey,
+                       counterparty_pubkeys.funding_pubkey,
+                       keys.clone(), 1,
+                       &mut vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())],
+                       &channel_parameters.as_holder_broadcastable()
+               );
+               assert_eq!(tx.built.transaction.output.len(), 5);
+               assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, true, &keys).to_v0_p2wsh());
+               assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, true, &keys).to_v0_p2wsh());
+               assert_eq!(get_htlc_redeemscript(&received_htlc, true, &keys).to_v0_p2wsh().to_hex(),
+                                  "0020b70d0649c72b38756885c7a30908d912a7898dd5d79457a7280b8e9a20f3f2bc");
+               assert_eq!(get_htlc_redeemscript(&offered_htlc, true, &keys).to_v0_p2wsh().to_hex(),
+                                  "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7");
+       }
 
        #[test]
        fn test_per_commitment_storage() {