Merge pull request #1887 from TheBlueMatt/2022-11-definitely-valid
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Sat, 3 Dec 2022 19:01:15 +0000 (19:01 +0000)
committerGitHub <noreply@github.com>
Sat, 3 Dec 2022 19:01:15 +0000 (19:01 +0000)
Remove cryptographically unreachable error conditions

1  2 
lightning/src/ln/chan_utils.rs
lightning/src/ln/functional_tests.rs

index 7fc817995fbdba393809c73c264e6e010a5e27c0,b5b9d2ee77f97c36280cdbbbf6825b838d2ed8db..39106f0c775fee350116d8830fcab915b55d2ee6
@@@ -14,7 -14,6 +14,7 @@@ use bitcoin::blockdata::script::{Script
  use bitcoin::blockdata::opcodes;
  use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, EcdsaSighashType};
  use bitcoin::util::sighash;
 +use bitcoin::util::address::Payload;
  
  use bitcoin::hashes::{Hash, HashEngine};
  use bitcoin::hashes::sha256::Hash as Sha256;
@@@ -26,11 -25,10 +26,10 @@@ 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};
  use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message};
- use bitcoin::secp256k1::Error as SecpError;
  use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
 +use bitcoin::PublicKey as BitcoinPublicKey;
  
  use crate::io;
  use crate::prelude::*;
@@@ -42,20 -40,13 +41,20 @@@ use core::ops::Deref
  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.
 +/// Maximum number of one-way in-flight HTLC (protocol-level value).
 +pub const MAX_HTLCS: u16 = 483;
 +/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor variant.
 +pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
 +/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, anchor variant.
 +pub const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136;
 +
 +/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value.
 +/// We define a range that encompasses both its non-anchors and anchors variants.
  pub(crate) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 136;
 -pub(crate) const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143;
 +/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value.
 +/// We define a range that encompasses both its non-anchors and anchors variants.
 +/// This is the maximum post-anchor value.
 +pub const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143;
  
  /// Gets the weight for an HTLC-Success transaction.
  #[inline]
@@@ -73,24 -64,18 +72,24 @@@ pub fn htlc_timeout_tx_weight(opt_ancho
        if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT }
  }
  
 +/// Describes the type of HTLC claim as determined by analyzing the witness.
  #[derive(PartialEq, Eq)]
 -pub(crate) enum HTLCClaim {
 +pub enum HTLCClaim {
 +      /// Claims an offered output on a commitment transaction through the timeout path.
        OfferedTimeout,
 +      /// Claims an offered output on a commitment transaction through the success path.
        OfferedPreimage,
 +      /// Claims an accepted output on a commitment transaction through the timeout path.
        AcceptedTimeout,
 +      /// Claims an accepted output on a commitment transaction through the success path.
        AcceptedPreimage,
 +      /// Claims an offered/accepted output on a commitment transaction through the revocation path.
        Revocation,
  }
  
  impl HTLCClaim {
        /// Check if a given input witness attempts to claim a HTLC.
 -      pub(crate) fn from_witness(witness: &Witness) -> Option<Self> {
 +      pub fn from_witness(witness: &Witness) -> Option<Self> {
                debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT);
                if witness.len() < 2 {
                        return None;
@@@ -330,32 -315,29 +329,29 @@@ impl Readable for CounterpartyCommitmen
  
  /// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key)
  /// from the base secret and the per_commitment_point.
- ///
- /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
- /// generated (ie our own).
- pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
+ pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> SecretKey {
        let mut sha = Sha256::engine();
        sha.input(&per_commitment_point.serialize());
        sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize());
        let res = Sha256::from_engine(sha).into_inner();
  
        base_secret.clone().add_tweak(&Scalar::from_be_bytes(res).unwrap())
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
  }
  
  /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
  /// from the base point and the per_commitment_key. This is the public equivalent of
  /// derive_private_key - using only public keys to derive a public key instead of private keys.
- ///
- /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
- /// generated (ie our own).
- pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, SecpError> {
+ pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
        let mut sha = Sha256::engine();
        sha.input(&per_commitment_point.serialize());
        sha.input(&base_point.serialize());
        let res = Sha256::from_engine(sha).into_inner();
  
-       let hashkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&res)?);
+       let hashkey = PublicKey::from_secret_key(&secp_ctx,
+               &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
        base_point.combine(&hashkey)
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
  }
  
  /// Derives a per-commitment-transaction revocation key from its constituent parts.
  /// commitment transaction, thus per_commitment_secret always come from cheater
  /// and revocation_base_secret always come from punisher, which is the broadcaster
  /// of the transaction spending with this key knowledge.
- ///
- /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
- /// generated (ie our own).
- pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, countersignatory_revocation_base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
+ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
+       per_commitment_secret: &SecretKey, countersignatory_revocation_base_secret: &SecretKey)
+ -> SecretKey {
        let countersignatory_revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &countersignatory_revocation_base_secret);
        let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
  
                Sha256::from_engine(sha).into_inner()
        };
  
-       let countersignatory_contrib = countersignatory_revocation_base_secret.clone().mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())?;
-       let broadcaster_contrib = per_commitment_secret.clone().mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())?;
+       let countersignatory_contrib = countersignatory_revocation_base_secret.clone().mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+               .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs");
+       let broadcaster_contrib = per_commitment_secret.clone().mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+               .expect("Multiplying a secret key by a hash is expected to never fail per secp256k1 docs");
        countersignatory_contrib.add_tweak(&Scalar::from_be_bytes(broadcaster_contrib.secret_bytes()).unwrap())
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
  }
  
  /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
  ///
  /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
  /// generated (ie our own).
- pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, countersignatory_revocation_base_point: &PublicKey) -> Result<PublicKey, SecpError> {
+ pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>,
+       per_commitment_point: &PublicKey, countersignatory_revocation_base_point: &PublicKey)
+ -> PublicKey {
        let rev_append_commit_hash_key = {
                let mut sha = Sha256::engine();
                sha.input(&countersignatory_revocation_base_point.serialize());
                Sha256::from_engine(sha).into_inner()
        };
  
-       let countersignatory_contrib = countersignatory_revocation_base_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())?;
-       let broadcaster_contrib = per_commitment_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())?;
+       let countersignatory_contrib = countersignatory_revocation_base_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+               .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+       let broadcaster_contrib = per_commitment_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+               .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
        countersignatory_contrib.combine(&broadcaster_contrib)
+               .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.")
  }
  
  /// The set of public keys which are used in the creation of one commitment transaction.
@@@ -493,19 -482,19 +496,19 @@@ impl_writeable_tlv_based!(ChannelPublic
  impl TxCreationKeys {
        /// Create per-state keys from channel base points and the per-commitment point.
        /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions.
-       pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> Result<TxCreationKeys, SecpError> {
-               Ok(TxCreationKeys {
+       pub fn derive_new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> TxCreationKeys {
+               TxCreationKeys {
                        per_commitment_point: per_commitment_point.clone(),
-                       revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base)?,
-                       broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base)?,
-                       countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base)?,
-                       broadcaster_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base)?,
-               })
+                       revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base),
+                       broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base),
+                       countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base),
+                       broadcaster_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base),
+               }
        }
  
        /// Generate per-state keys from channel static keys.
        /// Key set is asymmetric and can't be used as part of counter-signatory set of transactions.
-       pub fn from_channel_static_keys<T: secp256k1::Signing + secp256k1::Verification>(per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> Result<TxCreationKeys, SecpError> {
+       pub fn from_channel_static_keys<T: secp256k1::Signing + secp256k1::Verification>(per_commitment_point: &PublicKey, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> TxCreationKeys {
                TxCreationKeys::derive_new(
                        &secp_ctx,
                        &per_commitment_point,
@@@ -714,7 -703,7 +717,7 @@@ pub fn build_htlc_transaction(commitmen
  
  /// Gets the witnessScript for the to_remote output when anchors are enabled.
  #[inline]
 -pub(crate) fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script {
 +pub fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script {
        Builder::new()
                .push_slice(&payment_point.serialize()[..])
                .push_opcode(opcodes::all::OP_CHECKSIGVERIFY)
@@@ -1298,7 -1287,7 +1301,7 @@@ impl CommitmentTransaction 
                        let script = if opt_anchors {
                            get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_v0_p2wsh()
                        } else {
 -                          get_p2wpkh_redeemscript(&countersignatory_pubkeys.payment_point)
 +                          Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)).unwrap().script_pubkey()
                        };
                        txouts.push((
                                TxOut {
        pub fn verify<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_parameters: &DirectedChannelTransactionParameters, broadcaster_keys: &ChannelPublicKeys, countersignatory_keys: &ChannelPublicKeys, secp_ctx: &Secp256k1<T>) -> Result<TrustedCommitmentTransaction, ()> {
                // This is the only field of the key cache that we trust
                let per_commitment_point = self.keys.per_commitment_point;
-               let keys = TxCreationKeys::from_channel_static_keys(&per_commitment_point, broadcaster_keys, countersignatory_keys, secp_ctx).unwrap();
+               let keys = TxCreationKeys::from_channel_static_keys(&per_commitment_point, broadcaster_keys, countersignatory_keys, secp_ctx);
                if keys != self.keys {
                        return Err(());
                }
@@@ -1520,7 -1509,7 +1523,7 @@@ impl<'a> TrustedCommitmentTransaction<'
                let keys = &inner.keys;
                let txid = inner.built.txid;
                let mut ret = Vec::with_capacity(inner.htlcs.len());
-               let holder_htlc_key = derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key).map_err(|_| ())?;
+               let holder_htlc_key = derive_private_key(secp_ctx, &inner.keys.per_commitment_point, htlc_base_key);
  
                for this_htlc in inner.htlcs.iter() {
                        assert!(this_htlc.transaction_output_index.is_some());
@@@ -1604,12 -1593,18 +1607,12 @@@ pub fn get_commitment_transaction_numbe
                | ((res[31] as u64) << 0 * 8)
  }
  
 -fn get_p2wpkh_redeemscript(key: &PublicKey) -> Script {
 -      Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
 -              .push_slice(&WPubkeyHash::hash(&key.serialize())[..])
 -              .into_script()
 -}
 -
  #[cfg(test)]
  mod tests {
        use super::CounterpartyCommitmentSecrets;
        use 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 crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
        use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
        use crate::util::test_utils;
        use crate::chain::keysinterface::{KeysInterface, BaseSign};
        use bitcoin::hashes::Hash;
        use crate::ln::PaymentHash;
        use bitcoin::hashes::hex::ToHex;
 +      use bitcoin::util::address::Payload;
 +      use bitcoin::PublicKey as BitcoinPublicKey;
  
        #[test]
        fn test_anchors() {
                let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
                let holder_pubkeys = signer.pubkeys();
                let counterparty_pubkeys = counterparty_signer.pubkeys();
-               let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint).unwrap();
+               let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
                let mut channel_parameters = ChannelTransactionParameters {
                        holder_pubkeys: holder_pubkeys.clone(),
                        holder_selected_contest_delay: 0,
                        &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable()
                );
                assert_eq!(tx.built.transaction.output.len(), 2);
 -              assert_eq!(tx.built.transaction.output[1].script_pubkey, get_p2wpkh_redeemscript(&counterparty_pubkeys.payment_point));
 +              assert_eq!(tx.built.transaction.output[1].script_pubkey, Payload::p2wpkh(&BitcoinPublicKey::new(counterparty_pubkeys.payment_point)).unwrap().script_pubkey());
  
                // Generate broadcaster and counterparty outputs as well as two anchors
                let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
index c0d6eb2cd697379aaf6568641b8dbd523a026e38,d2f055dd5ec3d3ef1ecf9b139a2a223d3f17b384..56411a7de8939eeee782f36cc1dac6d5e168d8cf
@@@ -705,7 -705,7 +705,7 @@@ fn test_update_fee_that_funder_cannot_a
  
        // Assemble the set of keys we can use for signatures for our commitment_signed message.
        let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
-               &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
+               &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
  
        let res = {
                let local_chan_lock = nodes[0].node.channel_state.lock().unwrap();
@@@ -1412,7 -1412,7 +1412,7 @@@ fn test_fee_spike_violation_fails_htlc(
  
        // Assemble the set of keys we can use for signatures for our commitment_signed message.
        let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
-               &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
+               &remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
  
        // Build the remote commitment transaction so we can sign it, and then later use the
        // signature for the commitment_signed message.
@@@ -6023,7 -6023,7 +6023,7 @@@ fn test_update_add_htlc_bolt2_sender_cl
                .with_features(channelmanager::provided_invoice_features());
        let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000, 0);
        route.paths[0].last_mut().unwrap().cltv_expiry_delta = 500000001;
 -      unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), PaymentId(our_payment_hash.0)), true, APIError::RouteError { ref err },
 +      unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), PaymentId(our_payment_hash.0)), true, APIError::InvalidRoute { ref err },
                assert_eq!(err, &"Channel CLTV overflowed?"));
  }