Drop verbose log entries in BP when no network graph is provided
[rust-lightning] / lightning / src / ln / chan_utils.rs
index d53863289bc5807464739f0707fbb390c25f9869..a8c9dcc826e540d91e4020c67789df23e30297a4 100644 (file)
@@ -20,10 +20,10 @@ use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hashes::ripemd160::Hash as Ripemd160;
 use bitcoin::hash_types::{Txid, PubkeyHash};
 
-use ln::{PaymentHash, PaymentPreimage};
-use ln::msgs::DecodeError;
-use util::ser::{Readable, Writeable, Writer};
-use util::{byte_utils, transaction_utils};
+use crate::ln::{PaymentHash, PaymentPreimage};
+use crate::ln::msgs::DecodeError;
+use crate::util::ser::{Readable, Writeable, Writer};
+use crate::util::{byte_utils, transaction_utils};
 
 use bitcoin::hash_types::WPubkeyHash;
 use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar};
@@ -31,17 +31,23 @@ use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message};
 use bitcoin::secp256k1::Error as SecpError;
 use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
 
-use io;
-use prelude::*;
+use crate::io;
+use crate::prelude::*;
 use core::cmp;
-use ln::chan_utils;
-use util::transaction_utils::sort_outputs;
-use ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI};
+use crate::ln::chan_utils;
+use crate::util::transaction_utils::sort_outputs;
+use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI};
 use core::ops::Deref;
-use chain;
-use util::crypto::sign;
+use crate::chain;
+use crate::util::crypto::sign;
 
 pub(crate) const MAX_HTLCS: u16 = 483;
+pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
+pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136;
+// The weight of `accepted_htlc_script` can vary in function of its CLTV argument value. We define a
+// range that encompasses both its non-anchors and anchors variants.
+pub(crate) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 136;
+pub(crate) const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143;
 
 /// Gets the weight for an HTLC-Success transaction.
 #[inline]
@@ -59,19 +65,73 @@ pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 {
        if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT }
 }
 
-#[derive(PartialEq)]
-pub(crate) enum HTLCType {
-       AcceptedHTLC,
-       OfferedHTLC
+#[derive(PartialEq, Eq)]
+pub(crate) enum HTLCClaim {
+       OfferedTimeout,
+       OfferedPreimage,
+       AcceptedTimeout,
+       AcceptedPreimage,
+       Revocation,
 }
 
-impl HTLCType {
-       /// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
-       pub(crate) fn scriptlen_to_htlctype(witness_script_len: usize) ->  Option<HTLCType> {
-               if witness_script_len == 133 {
-                       Some(HTLCType::OfferedHTLC)
-               } else if witness_script_len >= 136 && witness_script_len <= 139 {
-                       Some(HTLCType::AcceptedHTLC)
+impl HTLCClaim {
+       /// Check if a given input witness attempts to claim a HTLC.
+       pub(crate) fn from_witness(witness: &Witness) -> Option<Self> {
+               debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
+               if witness.len() < 2 {
+                       return None;
+               }
+               let witness_script = witness.last().unwrap();
+               let second_to_last = witness.second_to_last().unwrap();
+               if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT {
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 32 {
+                               // <remotehtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::OfferedPreimage)
+                       } else if witness.len() == 5 && second_to_last.len() == 0 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+                               Some(Self::OfferedTimeout)
+                       } else {
+                               None
+                       }
+               } else if witness_script.len() == OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS {
+                       // It's possible for the weight of `offered_htlc_script` and `accepted_htlc_script` to
+                       // match so we check for both here.
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 32 {
+                               // <remotehtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::OfferedPreimage)
+                       } else if witness.len() == 5 && second_to_last.len() == 0 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
+                               Some(Self::OfferedTimeout)
+                       } else if witness.len() == 3 && second_to_last.len() == 0 {
+                               // <remotehtlcsig> <> <witness_script>
+                               Some(Self::AcceptedTimeout)
+                       } else if witness.len() == 5 && second_to_last.len() == 32 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::AcceptedPreimage)
+                       } else {
+                               None
+                       }
+               } else if witness_script.len() > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT &&
+                       witness_script.len() <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT {
+                       // Handle remaining range of ACCEPTED_HTLC_SCRIPT_WEIGHT.
+                       if witness.len() == 3 && second_to_last.len() == 33 {
+                               // <revocation sig> <revocationpubkey> <witness_script>
+                               Some(Self::Revocation)
+                       } else if witness.len() == 3 && second_to_last.len() == 0 {
+                               // <remotehtlcsig> <> <witness_script>
+                               Some(Self::AcceptedTimeout)
+                       } else if witness.len() == 5 && second_to_last.len() == 32 {
+                               // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
+                               Some(Self::AcceptedPreimage)
+                       } else {
+                               None
+                       }
                } else {
                        None
                }
@@ -148,6 +208,7 @@ pub struct CounterpartyCommitmentSecrets {
        old_secrets: [([u8; 32], u64); 49],
 }
 
+impl Eq for CounterpartyCommitmentSecrets {}
 impl PartialEq for CounterpartyCommitmentSecrets {
        fn eq(&self, other: &Self) -> bool {
                for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in self.old_secrets.iter().zip(other.old_secrets.iter()) {
@@ -285,7 +346,7 @@ pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_com
 
 /// Derives a per-commitment-transaction revocation key from its constituent parts.
 ///
-/// Only the cheating participant owns a valid witness to propagate a revoked 
+/// Only the cheating participant owns a valid witness to propagate a revoked
 /// commitment transaction, thus per_commitment_secret always come from cheater
 /// and revocation_base_secret always come from punisher, which is the broadcaster
 /// of the transaction spending with this key knowledge.
@@ -320,7 +381,7 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
 /// the public equivalend of derive_private_revocation_key - using only public keys to derive a
 /// public key instead of private keys.
 ///
-/// Only the cheating participant owns a valid witness to propagate a revoked 
+/// Only the cheating participant owns a valid witness to propagate a revoked
 /// commitment transaction, thus per_commitment_point always come from cheater
 /// and revocation_base_point always come from punisher, which is the broadcaster
 /// of the transaction spending with this key knowledge.
@@ -359,7 +420,7 @@ pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp2
 /// channel basepoints via the new function, or they were obtained via
 /// CommitmentTransaction.trust().keys() because we trusted the source of the
 /// pre-calculated keys.
-#[derive(PartialEq, Clone)]
+#[derive(PartialEq, Eq, Clone)]
 pub struct TxCreationKeys {
        /// The broadcaster's per-commitment public key which was used to derive the other keys.
        pub per_commitment_point: PublicKey,
@@ -384,7 +445,7 @@ impl_writeable_tlv_based!(TxCreationKeys, {
 });
 
 /// One counterparty's public keys which do not change over the life of a channel.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct ChannelPublicKeys {
        /// The public key which is used to sign all commitment transactions, as it appears in the
        /// on-chain channel lock-in 2-of-2 multisig output.
@@ -465,8 +526,8 @@ pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, contest_delay: u1
        res
 }
 
-#[derive(Clone, PartialEq)]
 /// Information about an HTLC as it appears in a commitment transaction
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct HTLCOutputInCommitment {
        /// Whether the HTLC was "offered" (ie outbound in relation to this commitment transaction).
        /// Note that this is not the same as whether it is ountbound *from us*. To determine that you
@@ -616,12 +677,17 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte
        } else {
                htlc_success_tx_weight(opt_anchors)
        };
-       let total_fee = feerate_per_kw as u64 * weight / 1000;
+       let output_value = if opt_anchors {
+               htlc.amount_msat / 1000
+       } else {
+               let total_fee = feerate_per_kw as u64 * weight / 1000;
+               htlc.amount_msat / 1000 - total_fee
+       };
 
        let mut txouts: Vec<TxOut> = Vec::new();
        txouts.push(TxOut {
                script_pubkey: get_revokeable_redeemscript(revocation_key, contest_delay, broadcaster_delayed_payment_key).to_v0_p2wsh(),
-               value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
+               value: output_value,
        });
 
        Transaction {
@@ -661,6 +727,23 @@ pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script {
                .into_script()
 }
 
+#[cfg(anchors)]
+/// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`.
+pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> {
+       let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh();
+       commitment_tx.output.iter().enumerate()
+               .find(|(_, txout)| txout.script_pubkey == anchor_script)
+               .map(|(idx, txout)| (idx as u32, txout))
+}
+
+/// Returns the witness required to satisfy and spend an anchor input.
+pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
+       let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
+       let mut funding_sig = funding_sig.serialize_der().to_vec();
+       funding_sig.push(EcdsaSighashType::All as u8);
+       Witness::from_vec(vec![funding_sig, anchor_redeem_script.to_bytes()])
+}
+
 /// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
 /// The fields are organized by holder/counterparty.
 ///
@@ -680,7 +763,8 @@ pub struct ChannelTransactionParameters {
        pub counterparty_parameters: Option<CounterpartyChannelTransactionParameters>,
        /// The late-bound funding outpoint
        pub funding_outpoint: Option<chain::transaction::OutPoint>,
-       /// Are anchors used for this channel.  Boolean is serialization backwards-compatible
+       /// Are anchors (zero fee HTLC transaction variant) used for this channel. Boolean is
+       /// serialization backwards-compatible.
        pub opt_anchors: Option<()>
 }
 
@@ -816,6 +900,7 @@ impl Deref for HolderCommitmentTransaction {
        fn deref(&self) -> &Self::Target { &self.inner }
 }
 
+impl Eq for HolderCommitmentTransaction {}
 impl PartialEq for HolderCommitmentTransaction {
        // We dont care whether we are signed in equality comparison
        fn eq(&self, o: &Self) -> bool {
@@ -941,7 +1026,7 @@ impl BuiltCommitmentTransaction {
 ///
 /// This class can be used inside a signer implementation to generate a signature given the relevant
 /// secret key.
-#[derive(Clone, Hash, PartialEq)]
+#[derive(Clone, Hash, PartialEq, Eq)]
 pub struct ClosingTransaction {
        to_holder_value_sat: u64,
        to_counterparty_value_sat: u64,
@@ -1081,6 +1166,7 @@ pub struct CommitmentTransaction {
        built: BuiltCommitmentTransaction,
 }
 
+impl Eq for CommitmentTransaction {}
 impl PartialEq for CommitmentTransaction {
        fn eq(&self, o: &Self) -> bool {
                let eq = self.commitment_number == o.commitment_number &&
@@ -1495,15 +1581,15 @@ fn get_p2wpkh_redeemscript(key: &PublicKey) -> Script {
 #[cfg(test)]
 mod tests {
        use super::CounterpartyCommitmentSecrets;
-       use ::{hex, chain};
-       use prelude::*;
-       use ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, get_p2wpkh_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
+       use crate::{hex, chain};
+       use crate::prelude::*;
+       use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, get_p2wpkh_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
        use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
-       use util::test_utils;
-       use chain::keysinterface::{KeysInterface, BaseSign};
+       use crate::util::test_utils;
+       use crate::chain::keysinterface::{KeysInterface, BaseSign};
        use bitcoin::{Network, Txid};
        use bitcoin::hashes::Hash;
-       use ln::PaymentHash;
+       use crate::ln::PaymentHash;
        use bitcoin::hashes::hex::ToHex;
 
        #[test]