Merge pull request #3086 from alecchendev/2024-05-holder-commitment
[rust-lightning] / lightning / src / ln / channel.rs
index afe265c8a6afb74f531252231e01e29230dcb333..d6ab1876ae0a31af8dfacc5bac01e35ed438e008 100644 (file)
@@ -7,6 +7,7 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
 use bitcoin::blockdata::transaction::Transaction;
@@ -29,7 +30,8 @@ use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::DecodeError;
 use crate::ln::script::{self, ShutdownScript};
-use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT, ChannelShutdownState};
+use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
+use crate::ln::channelmanager::{self, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
 use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
 use crate::ln::chan_utils;
 use crate::ln::onion_utils::HTLCFailReason;
@@ -37,7 +39,7 @@ use crate::chain::BestBlock;
 use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
 use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID};
 use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
+use crate::sign::ecdsa::EcdsaChannelSigner;
 use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
 use crate::events::ClosureReason;
 use crate::routing::gossip::NodeId;
@@ -185,45 +187,6 @@ enum InboundHTLCState {
        LocalRemoved(InboundHTLCRemovalReason),
 }
 
-/// Exposes the state of pending inbound HTLCs.
-///
-/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
-/// through the following states in the state machine:
-/// - Announced for addition by the originating node through the update_add_htlc message.
-/// - Added to the commitment transaction of the receiving node and originating node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
-///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
-/// - Removed from the commitment transaction of the originating node and receiving node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-///
-/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
-#[derive(Clone, Debug, PartialEq)]
-pub enum InboundHTLCStateDetails {
-       /// We have added this HTLC in our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// before this HTLC is included on the remote commitment transaction.
-       AwaitingRemoteRevokeToAdd,
-       /// This HTLC has been included in the commitment_signed and revoke_and_ack messages on both sides
-       /// and is included in both commitment transactions.
-       ///
-       /// This HTLC is now safe to either forward or be claimed as a payment by us. The HTLC will
-       /// remain in this state until the forwarded upstream HTLC has been resolved and we resolve this
-       /// HTLC correspondingly, or until we claim it as a payment. If it is part of a multipart
-       /// payment, it will only be claimed together with other required parts.
-       Committed,
-       /// We have received the preimage for this HTLC and it is being removed by fulfilling it with
-       /// update_fulfill_htlc. This HTLC is still on both commitment transactions, but we are awaiting
-       /// the appropriate revoke_and_ack's from the remote before this HTLC is removed from the remote
-       /// commitment transaction after update_fulfill_htlc.
-       AwaitingRemoteRevokeToRemoveFulfill,
-       /// The HTLC is being removed by failing it with update_fail_htlc or update_fail_malformed_htlc.
-       /// This HTLC is still on both commitment transactions, but we are awaiting the appropriate
-       /// revoke_and_ack's from the remote before this HTLC is removed from the remote commitment
-       /// transaction.
-       AwaitingRemoteRevokeToRemoveFail,
-}
-
 impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
        fn from(state: &InboundHTLCState) -> Option<InboundHTLCStateDetails> {
                match state {
@@ -244,13 +207,6 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
        }
 }
 
-impl_writeable_tlv_based_enum_upgradable!(InboundHTLCStateDetails,
-       (0, AwaitingRemoteRevokeToAdd) => {},
-       (2, Committed) => {},
-       (4, AwaitingRemoteRevokeToRemoveFulfill) => {},
-       (6, AwaitingRemoteRevokeToRemoveFail) => {};
-);
-
 struct InboundHTLCOutput {
        htlc_id: u64,
        amount_msat: u64,
@@ -259,53 +215,6 @@ struct InboundHTLCOutput {
        state: InboundHTLCState,
 }
 
-/// Exposes details around pending inbound HTLCs.
-#[derive(Clone, Debug, PartialEq)]
-pub struct InboundHTLCDetails {
-       /// The HTLC ID.
-       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
-       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
-       /// and not part of any commitment transaction.
-       pub htlc_id: u64,
-       /// The amount in msat.
-       pub amount_msat: u64,
-       /// The block height at which this HTLC expires.
-       pub cltv_expiry: u32,
-       /// The payment hash.
-       pub payment_hash: PaymentHash,
-       /// The state of the HTLC in the state machine.
-       ///
-       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
-       /// waiting for to advance to the next state.
-       ///
-       /// See [`InboundHTLCStateDetails`] for information on the specific states.
-       ///
-       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
-       /// states may result in `None` here.
-       pub state: Option<InboundHTLCStateDetails>,
-       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
-       /// from the local commitment transaction and added to the commitment transaction fee.
-       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
-       /// transactions as well.
-       ///
-       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
-       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
-       /// fee.
-       ///
-       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
-       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
-       pub is_dust: bool,
-}
-
-impl_writeable_tlv_based!(InboundHTLCDetails, {
-       (0, htlc_id, required),
-       (2, amount_msat, required),
-       (4, cltv_expiry, required),
-       (6, payment_hash, required),
-       (7, state, upgradable_option),
-       (8, is_dust, required),
-});
-
 #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
 enum OutboundHTLCState {
        /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
@@ -339,42 +248,6 @@ enum OutboundHTLCState {
        AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome),
 }
 
-/// Exposes the state of pending outbound HTLCs.
-///
-/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes
-/// through the following states in the state machine:
-/// - Announced for addition by the originating node through the update_add_htlc message.
-/// - Added to the commitment transaction of the receiving node and originating node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of
-///   the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages.
-/// - Removed from the commitment transaction of the originating node and receiving node in turn
-///   through the exchange of commitment_signed and revoke_and_ack messages.
-///
-/// This can be used to inspect what next message an HTLC is waiting for to advance its state.
-#[derive(Clone, Debug, PartialEq)]
-pub enum OutboundHTLCStateDetails {
-       /// We are awaiting the appropriate revoke_and_ack's from the remote before the HTLC is added
-       /// on the remote's commitment transaction after update_add_htlc.
-       AwaitingRemoteRevokeToAdd,
-       /// The HTLC has been added to the remote's commitment transaction by sending commitment_signed
-       /// and receiving revoke_and_ack in return.
-       ///
-       /// The HTLC will remain in this state until the remote node resolves the HTLC, or until we
-       /// unilaterally close the channel due to a timeout with an uncooperative remote node.
-       Committed,
-       /// The HTLC has been fulfilled successfully by the remote with a preimage in update_fulfill_htlc,
-       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// for the removal from its commitment transaction.
-       AwaitingRemoteRevokeToRemoveSuccess,
-       /// The HTLC has been failed by the remote with update_fail_htlc or update_fail_malformed_htlc,
-       /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and
-       /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote
-       /// for the removal from its commitment transaction.
-       AwaitingRemoteRevokeToRemoveFailure,
-}
-
 impl From<&OutboundHTLCState> for OutboundHTLCStateDetails {
        fn from(state: &OutboundHTLCState) -> OutboundHTLCStateDetails {
                match state {
@@ -398,13 +271,6 @@ impl From<&OutboundHTLCState> for OutboundHTLCStateDetails {
        }
 }
 
-impl_writeable_tlv_based_enum_upgradable!(OutboundHTLCStateDetails,
-       (0, AwaitingRemoteRevokeToAdd) => {},
-       (2, Committed) => {},
-       (4, AwaitingRemoteRevokeToRemoveSuccess) => {},
-       (6, AwaitingRemoteRevokeToRemoveFailure) => {};
-);
-
 #[derive(Clone)]
 #[cfg_attr(test, derive(Debug, PartialEq))]
 enum OutboundHTLCOutcome {
@@ -443,58 +309,6 @@ struct OutboundHTLCOutput {
        skimmed_fee_msat: Option<u64>,
 }
 
-/// Exposes details around pending outbound HTLCs.
-#[derive(Clone, Debug, PartialEq)]
-pub struct OutboundHTLCDetails {
-       /// The HTLC ID.
-       /// The IDs are incremented by 1 starting from 0 for each offered HTLC.
-       /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced
-       /// and not part of any commitment transaction.
-       ///
-       /// Not present when we are awaiting a remote revocation and the HTLC is not added yet.
-       pub htlc_id: Option<u64>,
-       /// The amount in msat.
-       pub amount_msat: u64,
-       /// The block height at which this HTLC expires.
-       pub cltv_expiry: u32,
-       /// The payment hash.
-       pub payment_hash: PaymentHash,
-       /// The state of the HTLC in the state machine.
-       ///
-       /// Determines on which commitment transactions the HTLC is included and what message the HTLC is
-       /// waiting for to advance to the next state.
-       ///
-       /// See [`OutboundHTLCStateDetails`] for information on the specific states.
-       ///
-       /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new
-       /// states may result in `None` here.
-       pub state: Option<OutboundHTLCStateDetails>,
-       /// The extra fee being skimmed off the top of this HTLC.
-       pub skimmed_fee_msat: Option<u64>,
-       /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed
-       /// from the local commitment transaction and added to the commitment transaction fee.
-       /// For non-anchor channels, this takes into account the cost of the second-stage HTLC
-       /// transactions as well.
-       ///
-       /// When the local commitment transaction is broadcasted as part of a unilateral closure,
-       /// the value of this HTLC will therefore not be claimable but instead burned as a transaction
-       /// fee.
-       ///
-       /// Note that dust limits are specific to each party. An HTLC can be dust for the local
-       /// commitment transaction but not for the counterparty's commitment transaction and vice versa.
-       pub is_dust: bool,
-}
-
-impl_writeable_tlv_based!(OutboundHTLCDetails, {
-       (0, htlc_id, required),
-       (2, amount_msat, required),
-       (4, cltv_expiry, required),
-       (6, payment_hash, required),
-       (7, state, upgradable_option),
-       (8, skimmed_fee_msat, required),
-       (10, is_dust, required),
-});
-
 /// See AwaitingRemoteRevoke ChannelState for more info
 #[cfg_attr(test, derive(Clone, Debug, PartialEq))]
 enum HTLCUpdateAwaitingACK {
@@ -923,25 +737,28 @@ pub(super) struct WithChannelContext<'a, L: Deref> where L::Target: Logger {
        pub logger: &'a L,
        pub peer_id: Option<PublicKey>,
        pub channel_id: Option<ChannelId>,
+       pub payment_hash: Option<PaymentHash>,
 }
 
 impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger {
        fn log(&self, mut record: Record) {
                record.peer_id = self.peer_id;
                record.channel_id = self.channel_id;
+               record.payment_hash = self.payment_hash;
                self.logger.log(record)
        }
 }
 
 impl<'a, 'b, L: Deref> WithChannelContext<'a, L>
 where L::Target: Logger {
-       pub(super) fn from<S: Deref>(logger: &'a L, context: &'b ChannelContext<S>) -> Self
+       pub(super) fn from<S: Deref>(logger: &'a L, context: &'b ChannelContext<S>, payment_hash: Option<PaymentHash>) -> Self
        where S::Target: SignerProvider
        {
                WithChannelContext {
                        logger,
                        peer_id: Some(context.counterparty_node_id),
                        channel_id: Some(context.channel_id),
+                       payment_hash
                }
        }
 }
@@ -998,14 +815,16 @@ enum HTLCInitiator {
        RemoteOffered,
 }
 
-/// An enum gathering stats on pending HTLCs, either inbound or outbound side.
+/// Current counts of various HTLCs, useful for calculating current balances available exactly.
 struct HTLCStats {
-       pending_htlcs: u32,
-       pending_htlcs_value_msat: u64,
+       pending_inbound_htlcs: usize,
+       pending_outbound_htlcs: usize,
+       pending_inbound_htlcs_value_msat: u64,
+       pending_outbound_htlcs_value_msat: u64,
        on_counterparty_tx_dust_exposure_msat: u64,
        on_holder_tx_dust_exposure_msat: u64,
-       holding_cell_msat: u64,
-       on_holder_tx_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
+       outbound_holding_cell_msat: u64,
+       on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
 }
 
 /// An enum gathering stats on commitment transaction, either local or remote.
@@ -1114,6 +933,75 @@ pub(crate) struct ShutdownResult {
        pub(crate) channel_funding_txo: Option<OutPoint>,
 }
 
+/// Tracks the transaction number, along with current and next commitment points.
+/// This consolidates the logic to advance our commitment number and request new
+/// commitment points from our signer.
+#[derive(Debug, Copy, Clone)]
+enum HolderCommitmentPoint {
+       // TODO: add a variant for before our first commitment point is retrieved
+       /// We've advanced our commitment number and are waiting on the next commitment point.
+       /// Until the `get_per_commitment_point` signer method becomes async, this variant
+       /// will not be used.
+       PendingNext { transaction_number: u64, current: PublicKey },
+       /// Our current commitment point is ready, we've cached our next point,
+       /// and we are not pending a new one.
+       Available { transaction_number: u64, current: PublicKey, next: PublicKey },
+}
+
+impl HolderCommitmentPoint {
+       pub fn new<SP: Deref>(signer: &ChannelSignerType<SP>, secp_ctx: &Secp256k1<secp256k1::All>) -> Self
+               where SP::Target: SignerProvider
+       {
+               HolderCommitmentPoint::Available {
+                       transaction_number: INITIAL_COMMITMENT_NUMBER,
+                       current: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx),
+                       next: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx),
+               }
+       }
+
+       pub fn is_available(&self) -> bool {
+               if let HolderCommitmentPoint::Available { .. } = self { true } else { false }
+       }
+
+       pub fn transaction_number(&self) -> u64 {
+               match self {
+                       HolderCommitmentPoint::PendingNext { transaction_number, .. } => *transaction_number,
+                       HolderCommitmentPoint::Available { transaction_number, .. } => *transaction_number,
+               }
+       }
+
+       pub fn current_point(&self) -> PublicKey {
+               match self {
+                       HolderCommitmentPoint::PendingNext { current, .. } => *current,
+                       HolderCommitmentPoint::Available { current, .. } => *current,
+               }
+       }
+
+       pub fn next_point(&self) -> Option<PublicKey> {
+               match self {
+                       HolderCommitmentPoint::PendingNext { .. } => None,
+                       HolderCommitmentPoint::Available { next, .. } => Some(*next),
+               }
+       }
+
+       pub fn advance<SP: Deref, L: Deref>(&mut self, signer: &ChannelSignerType<SP>, secp_ctx: &Secp256k1<secp256k1::All>, logger: &L)
+               where SP::Target: SignerProvider, L::Target: Logger
+       {
+               if let HolderCommitmentPoint::Available { transaction_number, next, .. } = self {
+                       *self = HolderCommitmentPoint::PendingNext {
+                               transaction_number: *transaction_number - 1,
+                               current: *next,
+                       };
+               }
+
+               if let HolderCommitmentPoint::PendingNext { transaction_number, current } = self {
+                       let next = signer.as_ref().get_per_commitment_point(*transaction_number - 1, secp_ctx);
+                       log_trace!(logger, "Retrieved next per-commitment point {}", *transaction_number - 1);
+                       *self = HolderCommitmentPoint::Available { transaction_number: *transaction_number, current: *current, next };
+               }
+       }
+}
+
 /// If the majority of the channels funds are to the fundee and the initiator holds only just
 /// enough funds to cover their reserve value, channels are at risk of getting "stuck". Because the
 /// initiator controls the feerate, if they then go to increase the channel fee, they may have no
@@ -1292,7 +1180,7 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
        // generation start at 0 and count up...this simplifies some parts of implementation at the
        // cost of others, but should really just be changed.
 
-       cur_holder_commitment_transaction_number: u64,
+       holder_commitment_point: HolderCommitmentPoint,
        cur_counterparty_commitment_transaction_number: u64,
        value_to_self_msat: u64, // Excluding all pending_htlcs, fees, and anchor outputs
        pending_inbound_htlcs: Vec<InboundHTLCOutput>,
@@ -1398,7 +1286,7 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
        /// Either the height at which this channel was created or the height at which it was last
        /// serialized if it was serialized by versions prior to 0.0.103.
        /// We use this to close if funding is never broadcasted.
-       channel_creation_height: u32,
+       pub(super) channel_creation_height: u32,
 
        counterparty_dust_limit_satoshis: u64,
 
@@ -1569,7 +1457,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                        L::Target: Logger,
                        SP::Target: SignerProvider,
        {
-               let logger = WithContext::from(logger, Some(counterparty_node_id), Some(open_channel_fields.temporary_channel_id));
+               let logger = WithContext::from(logger, Some(counterparty_node_id), Some(open_channel_fields.temporary_channel_id), None);
                let announced_channel = if (open_channel_fields.channel_flags & 1) == 1 { true } else { false };
 
                let channel_value_satoshis = our_funding_satoshis.saturating_add(open_channel_fields.funding_satoshis);
@@ -1734,6 +1622,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
 
                let value_to_self_msat = our_funding_satoshis * 1000 + msg_push_msat;
 
+               let holder_signer = ChannelSignerType::Ecdsa(holder_signer);
+               let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx);
+
                // TODO(dual_funding): Checks for `funding_feerate_sat_per_1000_weight`?
 
                let channel_context = ChannelContext {
@@ -1759,11 +1650,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
 
                        latest_monitor_update_id: 0,
 
-                       holder_signer: ChannelSignerType::Ecdsa(holder_signer),
+                       holder_signer,
                        shutdown_scriptpubkey,
                        destination_script,
 
-                       cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
+                       holder_commitment_point,
                        cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
                        value_to_self_msat,
 
@@ -1958,6 +1849,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
 
                let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
 
+               let holder_signer = ChannelSignerType::Ecdsa(holder_signer);
+               let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx);
+
                Ok(Self {
                        user_id,
 
@@ -1981,11 +1875,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
 
                        latest_monitor_update_id: 0,
 
-                       holder_signer: ChannelSignerType::Ecdsa(holder_signer),
+                       holder_signer,
                        shutdown_scriptpubkey,
                        destination_script,
 
-                       cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
+                       holder_commitment_point,
                        cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER,
                        value_to_self_msat,
 
@@ -2337,15 +2231,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
        }
 
-       pub fn get_max_dust_htlc_exposure_msat<F: Deref>(&self,
-               fee_estimator: &LowerBoundedFeeEstimator<F>) -> u64
-       where F::Target: FeeEstimator
-       {
+       fn get_dust_exposure_limiting_feerate<F: Deref>(&self,
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
+       ) -> u32 where F::Target: FeeEstimator {
+               fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::OnChainSweep)
+       }
+
+       pub fn get_max_dust_htlc_exposure_msat(&self, limiting_feerate_sat_per_kw: u32) -> u64 {
                match self.config.options.max_dust_htlc_exposure {
                        MaxDustHTLCExposure::FeeRateMultiplier(multiplier) => {
-                               let feerate_per_kw = fee_estimator.bounded_sat_per_1000_weight(
-                                       ConfirmationTarget::OnChainSweep) as u64;
-                               feerate_per_kw.saturating_mul(multiplier)
+                               (limiting_feerate_sat_per_kw as u64).saturating_mul(multiplier)
                        },
                        MaxDustHTLCExposure::FixedLimitMsat(limit) => limit,
                }
@@ -2678,8 +2573,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
        /// our counterparty!)
        /// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction)
        /// TODO Some magic rust shit to compile-time check this?
-       fn build_holder_transaction_keys(&self, commitment_number: u64) -> TxCreationKeys {
-               let per_commitment_point = self.holder_signer.as_ref().get_per_commitment_point(commitment_number, &self.secp_ctx);
+       fn build_holder_transaction_keys(&self) -> TxCreationKeys {
+               let per_commitment_point = self.holder_commitment_point.current_point();
                let delayed_payment_base = &self.get_holder_pubkeys().delayed_payment_basepoint;
                let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint;
                let counterparty_pubkeys = self.get_counterparty_pubkeys();
@@ -2738,86 +2633,111 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                self.counterparty_forwarding_info.clone()
        }
 
-       /// Returns a HTLCStats about inbound pending htlcs
-       fn get_inbound_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>) -> HTLCStats {
+       /// Returns a HTLCStats about pending htlcs
+       fn get_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>, dust_exposure_limiting_feerate: u32) -> HTLCStats {
                let context = self;
-               let mut stats = HTLCStats {
-                       pending_htlcs: context.pending_inbound_htlcs.len() as u32,
-                       pending_htlcs_value_msat: 0,
-                       on_counterparty_tx_dust_exposure_msat: 0,
-                       on_holder_tx_dust_exposure_msat: 0,
-                       holding_cell_msat: 0,
-                       on_holder_tx_holding_cell_htlcs_count: 0,
-               };
+               let uses_0_htlc_fee_anchors = self.get_channel_type().supports_anchors_zero_fee_htlc_tx();
 
-               let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
+               let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update);
+               let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if uses_0_htlc_fee_anchors {
                        (0, 0)
                } else {
-                       let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64;
-                       (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000,
-                               dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000)
+                       (dust_buffer_feerate as u64 * htlc_timeout_tx_weight(context.get_channel_type()) / 1000,
+                               dust_buffer_feerate as u64 * htlc_success_tx_weight(context.get_channel_type()) / 1000)
                };
-               let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis;
-               let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis;
-               for ref htlc in context.pending_inbound_htlcs.iter() {
-                       stats.pending_htlcs_value_msat += htlc.amount_msat;
-                       if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
-                               stats.on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
-                       }
-                       if htlc.amount_msat / 1000 < holder_dust_limit_success_sat {
-                               stats.on_holder_tx_dust_exposure_msat += htlc.amount_msat;
-                       }
-               }
-               stats
-       }
 
-       /// Returns a HTLCStats about pending outbound htlcs, *including* pending adds in our holding cell.
-       fn get_outbound_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>) -> HTLCStats {
-               let context = self;
-               let mut stats = HTLCStats {
-                       pending_htlcs: context.pending_outbound_htlcs.len() as u32,
-                       pending_htlcs_value_msat: 0,
-                       on_counterparty_tx_dust_exposure_msat: 0,
-                       on_holder_tx_dust_exposure_msat: 0,
-                       holding_cell_msat: 0,
-                       on_holder_tx_holding_cell_htlcs_count: 0,
-               };
+               let mut on_holder_tx_dust_exposure_msat = 0;
+               let mut on_counterparty_tx_dust_exposure_msat = 0;
 
-               let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
-                       (0, 0)
-               } else {
-                       let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64;
-                       (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000,
-                               dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000)
-               };
-               let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis;
-               let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis;
-               for ref htlc in context.pending_outbound_htlcs.iter() {
-                       stats.pending_htlcs_value_msat += htlc.amount_msat;
-                       if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
-                               stats.on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
-                       }
-                       if htlc.amount_msat / 1000 < holder_dust_limit_timeout_sat {
-                               stats.on_holder_tx_dust_exposure_msat += htlc.amount_msat;
+               let mut on_counterparty_tx_offered_nondust_htlcs = 0;
+               let mut on_counterparty_tx_accepted_nondust_htlcs = 0;
+
+               let mut pending_inbound_htlcs_value_msat = 0;
+
+               {
+                       let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis;
+                       let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis;
+                       for ref htlc in context.pending_inbound_htlcs.iter() {
+                               pending_inbound_htlcs_value_msat += htlc.amount_msat;
+                               if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
+                                       on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
+                               } else {
+                                       on_counterparty_tx_offered_nondust_htlcs += 1;
+                               }
+                               if htlc.amount_msat / 1000 < holder_dust_limit_success_sat {
+                                       on_holder_tx_dust_exposure_msat += htlc.amount_msat;
+                               }
                        }
                }
 
-               for update in context.holding_cell_htlc_updates.iter() {
-                       if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update {
-                               stats.pending_htlcs += 1;
-                               stats.pending_htlcs_value_msat += amount_msat;
-                               stats.holding_cell_msat += amount_msat;
-                               if *amount_msat / 1000 < counterparty_dust_limit_success_sat {
-                                       stats.on_counterparty_tx_dust_exposure_msat += amount_msat;
-                               }
-                               if *amount_msat / 1000 < holder_dust_limit_timeout_sat {
-                                       stats.on_holder_tx_dust_exposure_msat += amount_msat;
+               let mut pending_outbound_htlcs_value_msat = 0;
+               let mut outbound_holding_cell_msat = 0;
+               let mut on_holder_tx_outbound_holding_cell_htlcs_count = 0;
+               let mut pending_outbound_htlcs = self.pending_outbound_htlcs.len();
+               {
+                       let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis;
+                       let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis;
+                       for ref htlc in context.pending_outbound_htlcs.iter() {
+                               pending_outbound_htlcs_value_msat += htlc.amount_msat;
+                               if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
+                                       on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
                                } else {
-                                       stats.on_holder_tx_holding_cell_htlcs_count += 1;
+                                       on_counterparty_tx_accepted_nondust_htlcs += 1;
+                               }
+                               if htlc.amount_msat / 1000 < holder_dust_limit_timeout_sat {
+                                       on_holder_tx_dust_exposure_msat += htlc.amount_msat;
+                               }
+                       }
+
+                       for update in context.holding_cell_htlc_updates.iter() {
+                               if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update {
+                                       pending_outbound_htlcs += 1;
+                                       pending_outbound_htlcs_value_msat += amount_msat;
+                                       outbound_holding_cell_msat += amount_msat;
+                                       if *amount_msat / 1000 < counterparty_dust_limit_success_sat {
+                                               on_counterparty_tx_dust_exposure_msat += amount_msat;
+                                       } else {
+                                               on_counterparty_tx_accepted_nondust_htlcs += 1;
+                                       }
+                                       if *amount_msat / 1000 < holder_dust_limit_timeout_sat {
+                                               on_holder_tx_dust_exposure_msat += amount_msat;
+                                       } else {
+                                               on_holder_tx_outbound_holding_cell_htlcs_count += 1;
+                                       }
                                }
                        }
                }
-               stats
+
+               // Include any mining "excess" fees in the dust calculation
+               let excess_feerate_opt = outbound_feerate_update
+                       .or(self.pending_update_fee.map(|(fee, _)| fee))
+                       .unwrap_or(self.feerate_per_kw)
+                       .checked_sub(dust_exposure_limiting_feerate);
+               if let Some(excess_feerate) = excess_feerate_opt {
+                       let on_counterparty_tx_nondust_htlcs =
+                               on_counterparty_tx_accepted_nondust_htlcs + on_counterparty_tx_offered_nondust_htlcs;
+                       on_counterparty_tx_dust_exposure_msat +=
+                               commit_tx_fee_msat(excess_feerate, on_counterparty_tx_nondust_htlcs, &self.channel_type);
+                       if !self.channel_type.supports_anchors_zero_fee_htlc_tx() {
+                               on_counterparty_tx_dust_exposure_msat +=
+                                       on_counterparty_tx_accepted_nondust_htlcs as u64 * htlc_success_tx_weight(&self.channel_type)
+                                       * excess_feerate as u64 / 1000;
+                               on_counterparty_tx_dust_exposure_msat +=
+                                       on_counterparty_tx_offered_nondust_htlcs as u64 * htlc_timeout_tx_weight(&self.channel_type)
+                                       * excess_feerate as u64 / 1000;
+                       }
+               }
+
+               HTLCStats {
+                       pending_inbound_htlcs: self.pending_inbound_htlcs.len(),
+                       pending_outbound_htlcs,
+                       pending_inbound_htlcs_value_msat,
+                       pending_outbound_htlcs_value_msat,
+                       on_counterparty_tx_dust_exposure_msat,
+                       on_holder_tx_dust_exposure_msat,
+                       outbound_holding_cell_msat,
+                       on_holder_tx_outbound_holding_cell_htlcs_count,
+               }
        }
 
        /// Returns information on all pending inbound HTLCs.
@@ -2922,9 +2842,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
        where F::Target: FeeEstimator
        {
                let context = &self;
-               // Note that we have to handle overflow due to the above case.
-               let inbound_stats = context.get_inbound_pending_htlc_stats(None);
-               let outbound_stats = context.get_outbound_pending_htlc_stats(None);
+               // Note that we have to handle overflow due to the case mentioned in the docs in general
+               // here.
+
+               let dust_exposure_limiting_feerate = self.get_dust_exposure_limiting_feerate(&fee_estimator);
+               let htlc_stats = context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
 
                let mut balance_msat = context.value_to_self_msat;
                for ref htlc in context.pending_inbound_htlcs.iter() {
@@ -2932,10 +2854,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                                balance_msat += htlc.amount_msat;
                        }
                }
-               balance_msat -= outbound_stats.pending_htlcs_value_msat;
+               balance_msat -= htlc_stats.pending_outbound_htlcs_value_msat;
 
                let outbound_capacity_msat = context.value_to_self_msat
-                               .saturating_sub(outbound_stats.pending_htlcs_value_msat)
+                               .saturating_sub(htlc_stats.pending_outbound_htlcs_value_msat)
                                .saturating_sub(
                                        context.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000);
 
@@ -2995,7 +2917,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
 
                        let holder_selected_chan_reserve_msat = context.holder_selected_channel_reserve_satoshis * 1000;
                        let remote_balance_msat = (context.channel_value_satoshis * 1000 - context.value_to_self_msat)
-                               .saturating_sub(inbound_stats.pending_htlcs_value_msat);
+                               .saturating_sub(htlc_stats.pending_inbound_htlcs_value_msat);
 
                        if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat + anchor_outputs_value_msat {
                                // If another HTLC's fee would reduce the remote's balance below the reserve limit
@@ -3012,7 +2934,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                // send above the dust limit (as the router can always overpay to meet the dust limit).
                let mut remaining_msat_below_dust_exposure_limit = None;
                let mut dust_exposure_dust_limit_msat = 0;
-               let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(fee_estimator);
+               let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
 
                let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
                        (context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis)
@@ -3021,18 +2943,32 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                        (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000,
                         context.holder_dust_limit_satoshis       + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000)
                };
-               let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
-               if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
+
+               let excess_feerate_opt = self.feerate_per_kw.checked_sub(dust_exposure_limiting_feerate);
+               if let Some(excess_feerate) = excess_feerate_opt {
+                       let htlc_dust_exposure_msat =
+                               per_outbound_htlc_counterparty_commit_tx_fee_msat(excess_feerate, &context.channel_type);
+                       let nondust_htlc_counterparty_tx_dust_exposure =
+                               htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_dust_exposure_msat);
+                       if nondust_htlc_counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
+                               // If adding an extra HTLC would put us over the dust limit in total fees, we cannot
+                               // send any non-dust HTLCs.
+                               available_capacity_msat = cmp::min(available_capacity_msat, htlc_success_dust_limit * 1000);
+                       }
+               }
+
+               if htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_success_dust_limit * 1000) > max_dust_htlc_exposure_msat.saturating_add(1) {
+                       // Note that we don't use the `counterparty_tx_dust_exposure` (with
+                       // `htlc_dust_exposure_msat`) here as it only applies to non-dust HTLCs.
                        remaining_msat_below_dust_exposure_limit =
-                               Some(max_dust_htlc_exposure_msat.saturating_sub(on_counterparty_dust_htlc_exposure_msat));
+                               Some(max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_counterparty_tx_dust_exposure_msat));
                        dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000);
                }
 
-               let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
-               if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
+               if htlc_stats.on_holder_tx_dust_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
                        remaining_msat_below_dust_exposure_limit = Some(cmp::min(
                                remaining_msat_below_dust_exposure_limit.unwrap_or(u64::max_value()),
-                               max_dust_htlc_exposure_msat.saturating_sub(on_holder_dust_htlc_exposure_msat)));
+                               max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_holder_tx_dust_exposure_msat)));
                        dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000);
                }
 
@@ -3045,16 +2981,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                }
 
                available_capacity_msat = cmp::min(available_capacity_msat,
-                       context.counterparty_max_htlc_value_in_flight_msat - outbound_stats.pending_htlcs_value_msat);
+                       context.counterparty_max_htlc_value_in_flight_msat - htlc_stats.pending_outbound_htlcs_value_msat);
 
-               if outbound_stats.pending_htlcs + 1 > context.counterparty_max_accepted_htlcs as u32 {
+               if htlc_stats.pending_outbound_htlcs + 1 > context.counterparty_max_accepted_htlcs as usize {
                        available_capacity_msat = 0;
                }
 
                AvailableBalances {
                        inbound_capacity_msat: cmp::max(context.channel_value_satoshis as i64 * 1000
                                        - context.value_to_self_msat as i64
-                                       - context.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
+                                       - htlc_stats.pending_inbound_htlcs_value_msat as i64
                                        - context.holder_selected_channel_reserve_satoshis as i64 * 1000,
                                0) as u64,
                        outbound_capacity_msat,
@@ -3523,6 +3459,17 @@ pub(crate) fn commit_tx_fee_msat(feerate_per_kw: u32, num_htlcs: usize, channel_
        (commitment_tx_base_weight(channel_type_features) + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * feerate_per_kw as u64 / 1000 * 1000
 }
 
+pub(crate) fn per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate_per_kw: u32, channel_type_features: &ChannelTypeFeatures) -> u64 {
+       // Note that we need to divide before multiplying to round properly,
+       // since the lowest denomination of bitcoin on-chain is the satoshi.
+       let commitment_tx_fee = COMMITMENT_TX_WEIGHT_PER_HTLC * feerate_per_kw as u64 / 1000 * 1000;
+       if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
+               commitment_tx_fee + htlc_success_tx_weight(channel_type_features) * feerate_per_kw as u64 / 1000
+       } else {
+               commitment_tx_fee
+       }
+}
+
 /// Context for dual-funded channels.
 #[cfg(any(dual_funding, splicing))]
 pub(super) struct DualFundingChannelContext {
@@ -3612,7 +3559,7 @@ impl FailHTLCMessageName for msgs::UpdateFailMalformedHTLC {
 
 impl<SP: Deref> Channel<SP> where
        SP::Target: SignerProvider,
-       <SP::Target as SignerProvider>::EcdsaSigner: WriteableEcdsaChannelSigner
+       <SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner
 {
        fn check_remote_fee<F: Deref, L: Deref>(
                channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -4120,9 +4067,10 @@ impl<SP: Deref> Channel<SP> where
                Ok(self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block.height, logger))
        }
 
-       pub fn update_add_htlc(
+       pub fn update_add_htlc<F: Deref>(
                &mut self, msg: &msgs::UpdateAddHTLC, pending_forward_status: PendingHTLCStatus,
-       ) -> Result<(), ChannelError> {
+               fee_estimator: &LowerBoundedFeeEstimator<F>,
+       ) -> Result<(), ChannelError> where F::Target: FeeEstimator {
                if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
                        return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state".to_owned()));
                }
@@ -4143,11 +4091,12 @@ impl<SP: Deref> Channel<SP> where
                        return Err(ChannelError::Close(format!("Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})", self.context.holder_htlc_minimum_msat, msg.amount_msat)));
                }
 
-               let inbound_stats = self.context.get_inbound_pending_htlc_stats(None);
-               if inbound_stats.pending_htlcs + 1 > self.context.holder_max_accepted_htlcs as u32 {
+               let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
+               let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
+               if htlc_stats.pending_inbound_htlcs + 1 > self.context.holder_max_accepted_htlcs as usize {
                        return Err(ChannelError::Close(format!("Remote tried to push more than our max accepted HTLCs ({})", self.context.holder_max_accepted_htlcs)));
                }
-               if inbound_stats.pending_htlcs_value_msat + msg.amount_msat > self.context.holder_max_htlc_value_in_flight_msat {
+               if htlc_stats.pending_inbound_htlcs_value_msat + msg.amount_msat > self.context.holder_max_htlc_value_in_flight_msat {
                        return Err(ChannelError::Close(format!("Remote HTLC add would put them over our max HTLC value ({})", self.context.holder_max_htlc_value_in_flight_msat)));
                }
 
@@ -4173,7 +4122,7 @@ impl<SP: Deref> Channel<SP> where
                }
 
                let pending_value_to_self_msat =
-                       self.context.value_to_self_msat + inbound_stats.pending_htlcs_value_msat - removed_outbound_total_msat;
+                       self.context.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat;
                let pending_remote_value_msat =
                        self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat;
                if pending_remote_value_msat < msg.amount_msat {
@@ -4321,9 +4270,9 @@ impl<SP: Deref> Channel<SP> where
 
                let funding_script = self.context.get_funding_redeemscript();
 
-               let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
+               let keys = self.context.build_holder_transaction_keys();
 
-               let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger);
+               let commitment_stats = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, false, logger);
                let commitment_txid = {
                        let trusted_tx = commitment_stats.tx.trust();
                        let bitcoin_tx = trusted_tx.built_transaction();
@@ -4399,7 +4348,7 @@ impl<SP: Deref> Channel<SP> where
 
                                let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys);
                                let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
-                               let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]);
+                               let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
                                log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
                                        log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
                                        encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
@@ -4486,7 +4435,7 @@ impl<SP: Deref> Channel<SP> where
                        channel_id: Some(self.context.channel_id()),
                };
 
-               self.context.cur_holder_commitment_transaction_number -= 1;
+               self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger);
                self.context.expecting_peer_commitment_signed = false;
                // Note that if we need_commitment & !AwaitingRemoteRevoke we'll call
                // build_commitment_no_status_check() next which will reset this to RAAFirst.
@@ -4995,12 +4944,12 @@ impl<SP: Deref> Channel<SP> where
                }
 
                // Before proposing a feerate update, check that we can actually afford the new fee.
-               let inbound_stats = self.context.get_inbound_pending_htlc_stats(Some(feerate_per_kw));
-               let outbound_stats = self.context.get_outbound_pending_htlc_stats(Some(feerate_per_kw));
-               let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
-               let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger);
-               let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
-               let holder_balance_msat = commitment_stats.local_balance_msat - outbound_stats.holding_cell_msat;
+               let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
+               let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
+               let keys = self.context.build_holder_transaction_keys();
+               let commitment_stats = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, true, logger);
+               let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
+               let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
                if holder_balance_msat < buffer_fee_msat  + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
                        //TODO: auto-close after a number of failures?
                        log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@@ -5008,14 +4957,12 @@ impl<SP: Deref> Channel<SP> where
                }
 
                // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
-               let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
-               let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
-               let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
-               if holder_tx_dust_exposure > max_dust_htlc_exposure_msat {
+               let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
+               if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
                        log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
                        return None;
                }
-               if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
+               if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
                        log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
                        return None;
                }
@@ -5182,12 +5129,7 @@ impl<SP: Deref> Channel<SP> where
                        assert!(!self.context.is_outbound() || self.context.minimum_depth == Some(0),
                                "Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
                        self.context.monitor_pending_channel_ready = false;
-                       let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
-                       Some(msgs::ChannelReady {
-                               channel_id: self.context.channel_id(),
-                               next_per_commitment_point,
-                               short_channel_id_alias: Some(self.context.outbound_scid_alias),
-                       })
+                       Some(self.get_channel_ready())
                } else { None };
 
                let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block_height, logger);
@@ -5248,20 +5190,16 @@ impl<SP: Deref> Channel<SP> where
                self.context.pending_update_fee = Some((msg.feerate_per_kw, FeeUpdateState::RemoteAnnounced));
                self.context.update_time_counter += 1;
                // Check that we won't be pushed over our dust exposure limit by the feerate increase.
-               if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() {
-                       let inbound_stats = self.context.get_inbound_pending_htlc_stats(None);
-                       let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
-                       let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
-                       let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
-                       let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
-                       if holder_tx_dust_exposure > max_dust_htlc_exposure_msat {
-                               return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
-                                       msg.feerate_per_kw, holder_tx_dust_exposure)));
-                       }
-                       if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
-                               return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
-                                       msg.feerate_per_kw, counterparty_tx_dust_exposure)));
-                       }
+               let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
+               let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
+               let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
+               if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
+                       return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
+                               msg.feerate_per_kw, htlc_stats.on_holder_tx_dust_exposure_msat)));
+               }
+               if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
+                       return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
+                               msg.feerate_per_kw, htlc_stats.on_counterparty_tx_dust_exposure_msat)));
                }
                Ok(())
        }
@@ -5277,7 +5215,7 @@ impl<SP: Deref> Channel<SP> where
                        self.context.get_funding_signed_msg(logger).1
                } else { None };
                let channel_ready = if funding_signed.is_some() {
-                       self.check_get_channel_ready(0)
+                       self.check_get_channel_ready(0, logger)
                } else { None };
 
                log_trace!(logger, "Signer unblocked with {} commitment_update, {} funding_signed and {} channel_ready",
@@ -5293,8 +5231,11 @@ impl<SP: Deref> Channel<SP> where
        }
 
        fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK {
-               let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
-               let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2);
+               debug_assert!(self.context.holder_commitment_point.transaction_number() <= INITIAL_COMMITMENT_NUMBER + 2);
+               // TODO: handle non-available case when get_per_commitment_point becomes async
+               debug_assert!(self.context.holder_commitment_point.is_available());
+               let next_per_commitment_point = self.context.holder_commitment_point.current_point();
+               let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.holder_commitment_point.transaction_number() + 2);
                msgs::RevokeAndACK {
                        channel_id: self.context.channel_id,
                        per_commitment_secret,
@@ -5427,7 +5368,7 @@ impl<SP: Deref> Channel<SP> where
                        return Err(ChannelError::Close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned()));
                }
 
-               let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number - 1;
+               let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number() - 1;
                if msg.next_remote_commitment_number > 0 {
                        let expected_point = self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.context.secp_ctx);
                        let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret)
@@ -5489,13 +5430,8 @@ impl<SP: Deref> Channel<SP> where
                        }
 
                        // We have OurChannelReady set!
-                       let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
                        return Ok(ReestablishResponses {
-                               channel_ready: Some(msgs::ChannelReady {
-                                       channel_id: self.context.channel_id(),
-                                       next_per_commitment_point,
-                                       short_channel_id_alias: Some(self.context.outbound_scid_alias),
-                               }),
+                               channel_ready: Some(self.get_channel_ready()),
                                raa: None, commitment_update: None,
                                order: RAACommitmentOrder::CommitmentFirst,
                                shutdown_msg, announcement_sigs,
@@ -5532,14 +5468,9 @@ impl<SP: Deref> Channel<SP> where
                }
                let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER - self.context.cur_counterparty_commitment_transaction_number + if is_awaiting_remote_revoke { 1 } else { 0 };
 
-               let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number == 1 {
+               let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number() == 1 {
                        // We should never have to worry about MonitorUpdateInProgress resending ChannelReady
-                       let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
-                       Some(msgs::ChannelReady {
-                               channel_id: self.context.channel_id(),
-                               next_per_commitment_point,
-                               short_channel_id_alias: Some(self.context.outbound_scid_alias),
-                       })
+                       Some(self.get_channel_ready())
                } else { None };
 
                if msg.next_local_commitment_number == next_counterparty_commitment_number {
@@ -5913,7 +5844,7 @@ impl<SP: Deref> Channel<SP> where
                };
 
                for outp in closing_tx.trust().built_transaction().output.iter() {
-                       if !outp.script_pubkey.is_witness_program() && outp.value < MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS {
+                       if !outp.script_pubkey.is_witness_program() && outp.value < Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS) {
                                return Err(ChannelError::Close("Remote sent us a closing_signed with a dust output. Always use segwit closing scripts!".to_owned()));
                        }
                }
@@ -6105,9 +6036,9 @@ impl<SP: Deref> Channel<SP> where
                        return Err(("Shutdown was already sent", 0x4000|8))
                }
 
-               let inbound_stats = self.context.get_inbound_pending_htlc_stats(None);
-               let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
-               let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
+               let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
+               let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
+               let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
                let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
                        (0, 0)
                } else {
@@ -6117,17 +6048,27 @@ impl<SP: Deref> Channel<SP> where
                };
                let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis;
                if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
-                       let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat;
+                       let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat;
                        if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
                                log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
                                        on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
                                return Err(("Exceeded our dust exposure limit on counterparty commitment tx", 0x1000|7))
                        }
+               } else {
+                       let htlc_dust_exposure_msat =
+                               per_outbound_htlc_counterparty_commit_tx_fee_msat(self.context.feerate_per_kw, &self.context.channel_type);
+                       let counterparty_tx_dust_exposure =
+                               htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_dust_exposure_msat);
+                       if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
+                               log_info!(logger, "Cannot accept value that would put our exposure to tx fee dust at {} over the limit {} on counterparty commitment tx",
+                                       counterparty_tx_dust_exposure, max_dust_htlc_exposure_msat);
+                               return Err(("Exceeded our tx fee dust exposure limit on counterparty commitment tx", 0x1000|7))
+                       }
                }
 
                let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis;
                if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
-                       let on_holder_tx_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat;
+                       let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat;
                        if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
                                log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
                                        on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
@@ -6151,7 +6092,7 @@ impl<SP: Deref> Channel<SP> where
                }
 
                let pending_value_to_self_msat =
-                       self.context.value_to_self_msat + inbound_stats.pending_htlcs_value_msat - removed_outbound_total_msat;
+                       self.context.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat;
                let pending_remote_value_msat =
                        self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat;
 
@@ -6175,7 +6116,7 @@ impl<SP: Deref> Channel<SP> where
        }
 
        pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 {
-               self.context.cur_holder_commitment_transaction_number + 1
+               self.context.holder_commitment_point.transaction_number() + 1
        }
 
        pub fn get_cur_counterparty_commitment_transaction_number(&self) -> u64 {
@@ -6290,7 +6231,7 @@ impl<SP: Deref> Channel<SP> where
                        debug_assert!(self.context.minimum_depth.unwrap_or(1) > 0);
                        return true;
                }
-               if self.context.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 &&
+               if self.context.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER - 1 &&
                        self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 {
                        // If we're a 0-conf channel, we'll move beyond AwaitingChannelReady immediately even while
                        // waiting for the initial monitor persistence. Thus, we check if our commitment
@@ -6349,7 +6290,9 @@ impl<SP: Deref> Channel<SP> where
                self.context.channel_update_status = status;
        }
 
-       fn check_get_channel_ready(&mut self, height: u32) -> Option<msgs::ChannelReady> {
+       fn check_get_channel_ready<L: Deref>(&mut self, height: u32, logger: &L) -> Option<msgs::ChannelReady>
+               where L::Target: Logger
+       {
                // Called:
                //  * always when a new block/transactions are confirmed with the new height
                //  * when funding is signed with a height of 0
@@ -6369,6 +6312,8 @@ impl<SP: Deref> Channel<SP> where
                // If we're still pending the signature on a funding transaction, then we're not ready to send a
                // channel_ready yet.
                if self.context.signer_pending_funding {
+                       // TODO: set signer_pending_channel_ready
+                       log_debug!(logger, "Can't produce channel_ready: the signer is pending funding.");
                        return None;
                }
 
@@ -6401,22 +6346,35 @@ impl<SP: Deref> Channel<SP> where
                        false
                };
 
-               if need_commitment_update {
-                       if !self.context.channel_state.is_monitor_update_in_progress() {
-                               if !self.context.channel_state.is_peer_disconnected() {
-                                       let next_per_commitment_point =
-                                               self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx);
-                                       return Some(msgs::ChannelReady {
-                                               channel_id: self.context.channel_id,
-                                               next_per_commitment_point,
-                                               short_channel_id_alias: Some(self.context.outbound_scid_alias),
-                                       });
-                               }
-                       } else {
-                               self.context.monitor_pending_channel_ready = true;
-                       }
+               if !need_commitment_update {
+                       log_debug!(logger, "Not producing channel_ready: we do not need a commitment update");
+                       return None;
+               }
+
+               if self.context.channel_state.is_monitor_update_in_progress() {
+                       log_debug!(logger, "Not producing channel_ready: a monitor update is in progress. Setting monitor_pending_channel_ready.");
+                       self.context.monitor_pending_channel_ready = true;
+                       return None;
+               }
+
+               if self.context.channel_state.is_peer_disconnected() {
+                       log_debug!(logger, "Not producing channel_ready: the peer is disconnected.");
+                       return None;
+               }
+
+               // TODO: when get_per_commiment_point becomes async, check if the point is
+               // available, if not, set signer_pending_channel_ready and return None
+
+               Some(self.get_channel_ready())
+       }
+
+       fn get_channel_ready(&self) -> msgs::ChannelReady {
+               debug_assert!(self.context.holder_commitment_point.is_available());
+               msgs::ChannelReady {
+                       channel_id: self.context.channel_id(),
+                       next_per_commitment_point: self.context.holder_commitment_point.current_point(),
+                       short_channel_id_alias: Some(self.context.outbound_scid_alias),
                }
-               None
        }
 
        /// When a transaction is confirmed, we check whether it is or spends the funding transaction
@@ -6438,8 +6396,8 @@ impl<SP: Deref> Channel<SP> where
                                if self.context.funding_tx_confirmation_height == 0 {
                                        if tx.txid() == funding_txo.txid {
                                                let txo_idx = funding_txo.index as usize;
-                                               if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() ||
-                                                               tx.output[txo_idx].value != self.context.channel_value_satoshis {
+                                               if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_p2wsh() ||
+                                                               tx.output[txo_idx].value.to_sat() != self.context.channel_value_satoshis {
                                                        if self.context.is_outbound() {
                                                                // If we generated the funding transaction and it doesn't match what it
                                                                // should, the client is really broken and we should just panic and
@@ -6454,7 +6412,7 @@ impl<SP: Deref> Channel<SP> where
                                                        return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() });
                                                } else {
                                                        if self.context.is_outbound() {
-                                                               if !tx.is_coin_base() {
+                                                               if !tx.is_coinbase() {
                                                                        for input in tx.input.iter() {
                                                                                if input.witness.is_empty() {
                                                                                        // We generated a malleable funding transaction, implying we've
@@ -6474,7 +6432,7 @@ impl<SP: Deref> Channel<SP> where
                                                }
                                                // If this is a coinbase transaction and not a 0-conf channel
                                                // we should update our min_depth to 100 to handle coinbase maturity
-                                               if tx.is_coin_base() &&
+                                               if tx.is_coinbase() &&
                                                        self.context.minimum_depth.unwrap_or(0) > 0 &&
                                                        self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
                                                        self.context.minimum_depth = Some(COINBASE_MATURITY);
@@ -6483,7 +6441,7 @@ impl<SP: Deref> Channel<SP> where
                                        // If we allow 1-conf funding, we may need to check for channel_ready here and
                                        // send it immediately instead of waiting for a best_block_updated call (which
                                        // may have already happened for this block).
-                                       if let Some(channel_ready) = self.check_get_channel_ready(height) {
+                                       if let Some(channel_ready) = self.check_get_channel_ready(height, logger) {
                                                log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id);
                                                let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger);
                                                msgs = (Some(channel_ready), announcement_sigs);
@@ -6549,7 +6507,7 @@ impl<SP: Deref> Channel<SP> where
 
                self.context.update_time_counter = cmp::max(self.context.update_time_counter, highest_header_time);
 
-               if let Some(channel_ready) = self.check_get_channel_ready(height) {
+               if let Some(channel_ready) = self.check_get_channel_ready(height, logger) {
                        let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer {
                                self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger)
                        } else { None };
@@ -6852,7 +6810,7 @@ impl<SP: Deref> Channel<SP> where
 
                        // next_local_commitment_number is the next commitment_signed number we expect to
                        // receive (indicating if they need to resend one that we missed).
-                       next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number,
+                       next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number(),
                        // We have to set next_remote_commitment_number to the next revoke_and_ack we expect to
                        // receive, however we track it by the next commitment number for a remote transaction
                        // (which is one further, as they always revoke previous commitment transaction, not
@@ -7404,7 +7362,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                }
                if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
                                self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
-                               self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+                               self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
                }
 
@@ -7418,7 +7376,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
 
                // If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100.
                // We can skip this if it is a zero-conf channel.
-               if funding_transaction.is_coin_base() &&
+               if funding_transaction.is_coinbase() &&
                        self.context.minimum_depth.unwrap_or(0) > 0 &&
                        self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY {
                        self.context.minimum_depth = Some(COINBASE_MATURITY);
@@ -7456,6 +7414,12 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                Ok(self.get_open_channel(chain_hash))
        }
 
+       /// Returns true if we can resume the channel by sending the [`msgs::OpenChannel`] again.
+       pub fn is_resumable(&self) -> bool {
+               !self.context.have_received_message() &&
+                       self.context.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER
+       }
+
        pub fn get_open_channel(&self, chain_hash: ChainHash) -> msgs::OpenChannel {
                if !self.context.is_outbound() {
                        panic!("Tried to open a channel for an inbound channel?");
@@ -7464,11 +7428,12 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                        panic!("Cannot generate an open_channel after we've moved forward");
                }
 
-               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+               if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        panic!("Tried to send an open_channel for a channel that has already advanced");
                }
 
-               let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
+               debug_assert!(self.context.holder_commitment_point.is_available());
+               let first_per_commitment_point = self.context.holder_commitment_point.current_point();
                let keys = self.context.get_holder_pubkeys();
 
                msgs::OpenChannel {
@@ -7649,7 +7614,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                }
                if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
                                self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
-                               self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+                               self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
                }
 
@@ -7663,8 +7628,8 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}",
                        &self.context.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction));
 
-               let holder_signer = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
-               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &holder_signer, true, false, logger).tx;
+               let holder_signer = self.context.build_holder_transaction_keys();
+               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &holder_signer, true, false, logger).tx;
                {
                        let trusted_tx = initial_commitment_tx.trust();
                        let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
@@ -7691,7 +7656,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
 
                let funding_redeemscript = self.context.get_funding_redeemscript();
                let funding_txo = self.context.get_funding_txo().unwrap();
-               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
+               let funding_txo_script = funding_redeemscript.to_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
                let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
                let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
@@ -7717,7 +7682,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                } else {
                        self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
                }
-               self.context.cur_holder_commitment_transaction_number -= 1;
+               self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger);
                self.context.cur_counterparty_commitment_transaction_number -= 1;
 
                log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id());
@@ -7728,7 +7693,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
                        dual_funding_channel_context: None,
                };
 
-               let need_channel_ready = channel.check_get_channel_ready(0).is_some();
+               let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
                channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
                Ok((channel, channel_monitor))
        }
@@ -7798,7 +7763,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                          F::Target: FeeEstimator,
                          L::Target: Logger,
        {
-               let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id));
+               let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id), None);
 
                // First check the channel type is known, failing before we do anything else if we don't
                // support this channel type.
@@ -7853,7 +7818,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                ) {
                        panic!("Tried to send accept_channel after channel had moved forward");
                }
-               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+               if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        panic!("Tried to send an accept_channel for a channel that has already advanced");
                }
 
@@ -7866,7 +7831,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
        ///
        /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
        fn generate_accept_channel_message(&self) -> msgs::AcceptChannel {
-               let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
+               debug_assert!(self.context.holder_commitment_point.is_available());
+               let first_per_commitment_point = self.context.holder_commitment_point.current_point();
                let keys = self.context.get_holder_pubkeys();
 
                msgs::AcceptChannel {
@@ -7908,8 +7874,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
        fn check_funding_created_signature<L: Deref>(&mut self, sig: &Signature, logger: &L) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
                let funding_script = self.context.get_funding_redeemscript();
 
-               let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
-               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger).tx;
+               let keys = self.context.build_holder_transaction_keys();
+               let initial_commitment_tx = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, false, logger).tx;
                let trusted_tx = initial_commitment_tx.trust();
                let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
                let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis);
@@ -7943,7 +7909,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                }
                if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) ||
                                self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER ||
-                               self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+                               self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
                }
 
@@ -7983,12 +7949,12 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new());
                self.context.channel_id = ChannelId::v1_from_funding_outpoint(funding_txo);
                self.context.cur_counterparty_commitment_transaction_number -= 1;
-               self.context.cur_holder_commitment_transaction_number -= 1;
+               self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger);
 
                let (counterparty_initial_commitment_tx, funding_signed) = self.context.get_funding_signed_msg(logger);
 
                let funding_redeemscript = self.context.get_funding_redeemscript();
-               let funding_txo_script = funding_redeemscript.to_v0_p2wsh();
+               let funding_txo_script = funding_redeemscript.to_p2wsh();
                let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound());
                let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner());
                let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id);
@@ -8017,7 +7983,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
                        #[cfg(any(dual_funding, splicing))]
                        dual_funding_channel_context: None,
                };
-               let need_channel_ready = channel.check_get_channel_ready(0).is_some();
+               let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
                channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
 
                Ok((channel, funding_signed, channel_monitor))
@@ -8104,15 +8070,15 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
                        debug_assert!(false, "Cannot generate an open_channel2 after we've moved forward");
                }
 
-               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+               if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        debug_assert!(false, "Tried to send an open_channel2 for a channel that has already advanced");
                }
 
                let first_per_commitment_point = self.context.holder_signer.as_ref()
-                       .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number,
+                       .get_per_commitment_point(self.context.holder_commitment_point.transaction_number(),
                                &self.context.secp_ctx);
                let second_per_commitment_point = self.context.holder_signer.as_ref()
-                       .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number - 1,
+                       .get_per_commitment_point(self.context.holder_commitment_point.transaction_number() - 1,
                                &self.context.secp_ctx);
                let keys = self.context.get_holder_pubkeys();
 
@@ -8246,7 +8212,7 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
                ) {
                        debug_assert!(false, "Tried to send accept_channel2 after channel had moved forward");
                }
-               if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER {
+               if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER {
                        debug_assert!(false, "Tried to send an accept_channel2 for a channel that has already advanced");
                }
 
@@ -8260,9 +8226,9 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
        /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2
        fn generate_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
                let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
-                       self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx);
+                       self.context.holder_commitment_point.transaction_number(), &self.context.secp_ctx);
                let second_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(
-                       self.context.cur_holder_commitment_transaction_number - 1, &self.context.secp_ctx);
+                       self.context.holder_commitment_point.transaction_number() - 1, &self.context.secp_ctx);
                let keys = self.context.get_holder_pubkeys();
 
                msgs::AcceptChannelV2 {
@@ -8435,7 +8401,7 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
                }
                self.context.destination_script.write(writer)?;
 
-               self.context.cur_holder_commitment_transaction_number.write(writer)?;
+               self.context.holder_commitment_point.transaction_number().write(writer)?;
                self.context.cur_counterparty_commitment_transaction_number.write(writer)?;
                self.context.value_to_self_msat.write(writer)?;
 
@@ -8709,6 +8675,10 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
                        monitor_pending_update_adds = Some(&self.context.monitor_pending_update_adds);
                }
 
+               // `current_point` will become optional when async signing is implemented.
+               let cur_holder_commitment_point = Some(self.context.holder_commitment_point.current_point());
+               let next_holder_commitment_point = self.context.holder_commitment_point.next_point();
+
                write_tlv_fields!(writer, {
                        (0, self.context.announcement_sigs, option),
                        // minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -8745,7 +8715,8 @@ impl<SP: Deref> Writeable for Channel<SP> where SP::Target: SignerProvider {
                        (39, pending_outbound_blinding_points, optional_vec),
                        (41, holding_cell_blinding_points, optional_vec),
                        (43, malformed_htlcs, optional_vec), // Added in 0.0.119
-                       // 45 and 47 are reserved for async signing
+                       (45, cur_holder_commitment_point, option),
+                       (47, next_holder_commitment_point, option),
                        (49, self.context.local_initiated_shutdown, option), // Added in 0.0.122
                });
 
@@ -9056,6 +9027,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                let mut malformed_htlcs: Option<Vec<(u64, u16, [u8; 32])>> = None;
                let mut monitor_pending_update_adds: Option<Vec<msgs::UpdateAddHTLC>> = None;
 
+               let mut cur_holder_commitment_point_opt: Option<PublicKey> = None;
+               let mut next_holder_commitment_point_opt: Option<PublicKey> = None;
+
                read_tlv_fields!(reader, {
                        (0, announcement_sigs, option),
                        (1, minimum_depth, option),
@@ -9086,7 +9060,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                        (39, pending_outbound_blinding_points_opt, optional_vec),
                        (41, holding_cell_blinding_points_opt, optional_vec),
                        (43, malformed_htlcs, optional_vec), // Added in 0.0.119
-                       // 45 and 47 are reserved for async signing
+                       (45, cur_holder_commitment_point_opt, option),
+                       (47, next_holder_commitment_point_opt, option),
                        (49, local_initiated_shutdown, option),
                });
 
@@ -9198,6 +9173,24 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                        }
                }
 
+               // If we're restoring this channel for the first time after an upgrade, then we require that the
+               // signer be available so that we can immediately populate the current commitment point. Channel
+               // restoration will fail if this is not possible.
+               let holder_commitment_point = match (cur_holder_commitment_point_opt, next_holder_commitment_point_opt) {
+                       (Some(current), Some(next)) => HolderCommitmentPoint::Available {
+                               transaction_number: cur_holder_commitment_transaction_number, current, next
+                       },
+                       (Some(current), _) => HolderCommitmentPoint::Available {
+                               transaction_number: cur_holder_commitment_transaction_number, current,
+                               next: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number - 1, &secp_ctx),
+                       },
+                       (_, _) => HolderCommitmentPoint::Available {
+                               transaction_number: cur_holder_commitment_transaction_number,
+                               current: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number, &secp_ctx),
+                               next: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number - 1, &secp_ctx),
+                       },
+               };
+
                Ok(Channel {
                        context: ChannelContext {
                                user_id,
@@ -9223,7 +9216,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
                                shutdown_scriptpubkey,
                                destination_script,
 
-                               cur_holder_commitment_transaction_number,
+                               holder_commitment_point,
                                cur_counterparty_commitment_transaction_number,
                                value_to_self_msat,
 
@@ -9332,11 +9325,12 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
 #[cfg(test)]
 mod tests {
        use std::cmp;
+       use bitcoin::amount::Amount;
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::blockdata::script::{ScriptBuf, Builder};
-       use bitcoin::blockdata::transaction::{Transaction, TxOut};
+       use bitcoin::blockdata::transaction::{Transaction, TxOut, Version};
        use bitcoin::blockdata::opcodes;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use crate::ln::onion_utils::INVALID_ONION_BLINDING;
        use crate::ln::types::{PaymentHash, PaymentPreimage};
        use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint};
@@ -9365,9 +9359,8 @@ mod tests {
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::hex::FromHex;
-       use bitcoin::hash_types::WPubkeyHash;
        use bitcoin::blockdata::locktime::absolute::LockTime;
-       use bitcoin::address::{WitnessProgram, WitnessVersion};
+       use bitcoin::{WitnessProgram, WitnessVersion, WPubkeyHash};
        use crate::prelude::*;
 
        #[test]
@@ -9523,8 +9516,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -9652,8 +9645,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -9841,8 +9834,8 @@ mod tests {
 
                // Node A --> Node B: funding created
                let output_script = node_a_chan.context.get_funding_redeemscript();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: output_script.clone(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap();
@@ -9908,8 +9901,8 @@ mod tests {
                        &features, &outbound_chan.get_open_channel(ChainHash::using_genesis_block(network)), 7, &config, 0, &&logger, false
                ).unwrap();
                outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(), &config.channel_handshake_limits, &features).unwrap();
-               let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
-                       value: 10000000, script_pubkey: outbound_chan.context.get_funding_redeemscript(),
+               let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut {
+                       value: Amount::from_sat(10000000), script_pubkey: outbound_chan.context.get_funding_redeemscript(),
                }]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
                let funding_created = outbound_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap().unwrap();
@@ -10166,7 +10159,7 @@ mod tests {
                                                &htlc, $opt_anchors, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
                                        let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys);
                                        let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
-                                       let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap();
+                                       let htlc_sighash = Message::from_digest(sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap().as_raw_hash().to_byte_array());
                                        assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key.to_public_key()).is_ok(), "verify counterparty htlc sig");
 
                                        let mut preimage: Option<PaymentPreimage> = None;
@@ -11032,15 +11025,15 @@ mod tests {
                // Fund the channel with a batch funding transaction.
                let output_script = node_a_chan.context.get_funding_redeemscript();
                let tx = Transaction {
-                       version: 1,
+                       version: Version::ONE,
                        lock_time: LockTime::ZERO,
                        input: Vec::new(),
                        output: vec![
                                TxOut {
-                                       value: 10000000, script_pubkey: output_script.clone(),
+                                       value: Amount::from_sat(10000000), script_pubkey: output_script.clone(),
                                },
                                TxOut {
-                                       value: 10000000, script_pubkey: Builder::new().into_script(),
+                                       value: Amount::from_sat(10000000), script_pubkey: Builder::new().into_script(),
                                },
                        ]};
                let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
@@ -11097,6 +11090,6 @@ mod tests {
                // Clear the ChannelState::WaitingForBatch only when called by ChannelManager.
                node_a_chan.set_batch_ready();
                assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
-               assert!(node_a_chan.check_get_channel_ready(0).is_some());
+               assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
        }
 }