Encode channel update type in failure messages.
[rust-lightning] / lightning / src / ln / channel.rs
index f6767e8a7d46555cecb48592ee52200aa4b53ded..43032c51a3c09cdc67988e96050835fd7a17d9d7 100644 (file)
@@ -8,8 +8,8 @@
 // licenses.
 
 use bitcoin::blockdata::script::{Script,Builder};
-use bitcoin::blockdata::transaction::{Transaction, SigHashType};
-use bitcoin::util::bip143;
+use bitcoin::blockdata::transaction::{Transaction, EcdsaSighashType};
+use bitcoin::util::sighash;
 use bitcoin::consensus::encode;
 
 use bitcoin::hashes::Hash;
@@ -18,8 +18,8 @@ use bitcoin::hashes::sha256d::Hash as Sha256d;
 use bitcoin::hash_types::{Txid, BlockHash};
 
 use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
-use bitcoin::secp256k1::key::{PublicKey,SecretKey};
-use bitcoin::secp256k1::{Secp256k1,Signature};
+use bitcoin::secp256k1::{PublicKey,SecretKey};
+use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
 use bitcoin::secp256k1;
 
 use ln::{PaymentPreimage, PaymentHash};
@@ -1946,6 +1946,10 @@ impl<Signer: Sign> Channel<Signer> {
                if msg.dust_limit_satoshis > self.holder_selected_channel_reserve_satoshis {
                        return Err(ChannelError::Close(format!("Dust limit ({}) is bigger than our channel reserve ({})", msg.dust_limit_satoshis, self.holder_selected_channel_reserve_satoshis)));
                }
+               if msg.channel_reserve_satoshis > self.channel_value_satoshis - self.holder_selected_channel_reserve_satoshis {
+                       return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than channel value minus our reserve ({})",
+                               msg.channel_reserve_satoshis, self.channel_value_satoshis - self.holder_selected_channel_reserve_satoshis)));
+               }
                let full_channel_value_msat = (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000;
                if msg.htlc_minimum_msat >= full_channel_value_msat {
                        return Err(ChannelError::Close(format!("Minimum htlc value ({}) is full channel value ({})", msg.htlc_minimum_msat, full_channel_value_msat)));
@@ -2063,7 +2067,7 @@ impl<Signer: Sign> Channel<Signer> {
                                log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
                                encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
                                encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));
-                       secp_check!(self.secp_ctx.verify(&sighash, &sig, self.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned());
+                       secp_check!(self.secp_ctx.verify_ecdsa(&sighash, &sig, self.counterparty_funding_pubkey()), "Invalid funding_created signature from peer".to_owned());
                }
 
                let counterparty_keys = self.build_remote_transaction_keys()?;
@@ -2195,7 +2199,7 @@ impl<Signer: Sign> Channel<Signer> {
                        let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
                        let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.channel_value_satoshis);
                        // They sign our commitment transaction, allowing us to broadcast the tx if we wish.
-                       if let Err(_) = self.secp_ctx.verify(&sighash, &msg.signature, &self.get_counterparty_pubkeys().funding_pubkey) {
+                       if let Err(_) = self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.get_counterparty_pubkeys().funding_pubkey) {
                                return Err(ChannelError::Close("Invalid funding_signed signature from peer".to_owned()));
                        }
                }
@@ -2833,7 +2837,7 @@ impl<Signer: Sign> Channel<Signer> {
                                log_bytes!(msg.signature.serialize_compact()[..]),
                                log_bytes!(self.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction),
                                log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));
-                       if let Err(_) = self.secp_ctx.verify(&sighash, &msg.signature, &self.counterparty_funding_pubkey()) {
+                       if let Err(_) = self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.counterparty_funding_pubkey()) {
                                return Err((None, ChannelError::Close("Invalid commitment tx signature from peer".to_owned())));
                        }
                        bitcoin_tx.txid
@@ -2883,12 +2887,12 @@ impl<Signer: Sign> Channel<Signer> {
                                        &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
 
                                let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, self.opt_anchors(), &keys);
-                               let htlc_sighashtype = if self.opt_anchors() { SigHashType::SinglePlusAnyoneCanPay } else { SigHashType::All };
-                               let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype)[..]);
+                               let htlc_sighashtype = if self.opt_anchors() { 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()[..]);
                                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.serialize()),
                                        encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), log_bytes!(self.channel_id()));
-                               if let Err(_) = self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) {
+                               if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) {
                                        return Err((None, ChannelError::Close("Invalid HTLC tx signature from peer".to_owned())));
                                }
                                htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source));
@@ -3756,6 +3760,15 @@ impl<Signer: Sign> Channel<Signer> {
                        }
                }
 
+               // Before we change the state of the channel, we check if the peer is sending a very old
+               // commitment transaction number, if yes we send a warning message.
+               let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number - 1;
+               if  msg.next_remote_commitment_number + 1 < our_commitment_transaction {
+                       return Err(
+                               ChannelError::Warn(format!("Peer attempted to reestablish channel with a very old local commitment transaction: {} (received) vs {} (expected)", msg.next_remote_commitment_number, our_commitment_transaction))
+                       );
+               }
+
                // Go ahead and unmark PeerDisconnected as various calls we may make check for it (and all
                // remaining cases either succeed or ErrorMessage-fail).
                self.channel_state &= !(ChannelState::PeerDisconnected as u32);
@@ -4125,15 +4138,17 @@ impl<Signer: Sign> Channel<Signer> {
 
                let funding_key = self.get_holder_pubkeys().funding_pubkey.serialize();
                let counterparty_funding_key = self.counterparty_funding_pubkey().serialize();
+               let mut holder_sig = sig.serialize_der().to_vec();
+               holder_sig.push(EcdsaSighashType::All as u8);
+               let mut cp_sig = counterparty_sig.serialize_der().to_vec();
+               cp_sig.push(EcdsaSighashType::All as u8);
                if funding_key[..] < counterparty_funding_key[..] {
-                       tx.input[0].witness.push(sig.serialize_der().to_vec());
-                       tx.input[0].witness.push(counterparty_sig.serialize_der().to_vec());
+                       tx.input[0].witness.push(holder_sig);
+                       tx.input[0].witness.push(cp_sig);
                } else {
-                       tx.input[0].witness.push(counterparty_sig.serialize_der().to_vec());
-                       tx.input[0].witness.push(sig.serialize_der().to_vec());
+                       tx.input[0].witness.push(cp_sig);
+                       tx.input[0].witness.push(holder_sig);
                }
-               tx.input[0].witness[1].push(SigHashType::All as u8);
-               tx.input[0].witness[2].push(SigHashType::All as u8);
 
                tx.input[0].witness.push(self.get_funding_redeemscript().into_bytes());
                tx
@@ -4171,14 +4186,14 @@ impl<Signer: Sign> Channel<Signer> {
                }
                let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.channel_value_satoshis);
 
-               match self.secp_ctx.verify(&sighash, &msg.signature, &self.get_counterparty_pubkeys().funding_pubkey) {
+               match self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.get_counterparty_pubkeys().funding_pubkey) {
                        Ok(_) => {},
                        Err(_e) => {
                                // The remote end may have decided to revoke their output due to inconsistent dust
                                // limits, so check for that case by re-checking the signature here.
                                closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
                                let sighash = closing_tx.trust().get_sighash_all(&funding_redeemscript, self.channel_value_satoshis);
-                               secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, self.counterparty_funding_pubkey()), "Invalid closing tx signature from peer".to_owned());
+                               secp_check!(self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, self.counterparty_funding_pubkey()), "Invalid closing tx signature from peer".to_owned());
                        },
                };
 
@@ -4379,7 +4394,7 @@ impl<Signer: Sign> Channel<Signer> {
                        // channel might have been used to route very small values (either by honest users or as DoS).
                        self.channel_value_satoshis * 1000 * 9 / 10,
 
-                       self.holder_max_htlc_value_in_flight_msat
+                       self.counterparty_max_htlc_value_in_flight_msat
                );
        }
 
@@ -4739,10 +4754,14 @@ impl<Signer: Sign> Channel<Signer> {
                        }
 
                        // If we've sent funding_locked (or have both sent and received funding_locked), and
-                       // the funding transaction's confirmation count has dipped below minimum_depth / 2,
+                       // the funding transaction has become unconfirmed,
                        // close the channel and hope we can get the latest state on chain (because presumably
                        // the funding transaction is at least still in the mempool of most nodes).
-                       if funding_tx_confirmations < self.minimum_depth.unwrap() as i64 / 2 {
+                       //
+                       // Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf channel,
+                       // but not doing so may lead to the `ChannelManager::short_to_id` map being
+                       // inconsistent, so we currently have to.
+                       if funding_tx_confirmations == 0 && self.funding_tx_confirmed_in.is_some() {
                                let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
                                        self.minimum_depth.unwrap(), funding_tx_confirmations);
                                return Err(ClosureReason::ProcessingError { err: err_reason });
@@ -5064,12 +5083,12 @@ impl<Signer: Sign> Channel<Signer> {
 
                let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]);
 
-               if self.secp_ctx.verify(&msghash, &msg.node_signature, &self.get_counterparty_node_id()).is_err() {
+               if self.secp_ctx.verify_ecdsa(&msghash, &msg.node_signature, &self.get_counterparty_node_id()).is_err() {
                        return Err(ChannelError::Close(format!(
                                "Bad announcement_signatures. Failed to verify node_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_node_key is {:?}",
                                 &announcement, self.get_counterparty_node_id())));
                }
-               if self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, self.counterparty_funding_pubkey()).is_err() {
+               if self.secp_ctx.verify_ecdsa(&msghash, &msg.bitcoin_signature, self.counterparty_funding_pubkey()).is_err() {
                        return Err(ChannelError::Close(format!(
                                "Bad announcement_signatures. Failed to verify bitcoin_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_bitcoin_key is ({:?})",
                                &announcement, self.counterparty_funding_pubkey())));
@@ -6378,15 +6397,15 @@ mod tests {
        use util::errors::APIError;
        use util::test_utils;
        use util::test_utils::OnGetShutdownScriptpubkey;
-       use bitcoin::secp256k1::{Secp256k1, Signature};
+       use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
        use bitcoin::secp256k1::ffi::Signature as FFISignature;
-       use bitcoin::secp256k1::key::{SecretKey,PublicKey};
-       use bitcoin::secp256k1::recovery::RecoverableSignature;
+       use bitcoin::secp256k1::{SecretKey,PublicKey};
+       use bitcoin::secp256k1::ecdsa::RecoverableSignature;
        use bitcoin::hashes::sha256::Hash as Sha256;
        use bitcoin::hashes::Hash;
        use bitcoin::hash_types::WPubkeyHash;
-       use core::num::NonZeroU8;
        use bitcoin::bech32::u5;
+       use bitcoin::util::address::WitnessVersion;
        use prelude::*;
 
        struct TestFeeEstimator {
@@ -6450,7 +6469,7 @@ mod tests {
        fn upfront_shutdown_script_incompatibility() {
                let features = InitFeatures::known().clear_shutdown_anysegwit();
                let non_v0_segwit_shutdown_script =
-                       ShutdownScript::new_witness_program(NonZeroU8::new(16).unwrap(), &[0, 40]).unwrap();
+                       ShutdownScript::new_witness_program(WitnessVersion::V16, &[0, 40]).unwrap();
 
                let seed = [42; 32];
                let network = Network::Testnet;
@@ -6680,6 +6699,79 @@ mod tests {
                }
        }
 
+       #[test]
+       fn test_configured_holder_max_htlc_value_in_flight() {
+               let feeest = TestFeeEstimator{fee_est: 15000};
+               let logger = test_utils::TestLogger::new();
+               let secp_ctx = Secp256k1::new();
+               let seed = [42; 32];
+               let network = Network::Testnet;
+               let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
+               let outbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+               let inbound_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
+
+               let mut config_2_percent = UserConfig::default();
+               config_2_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 2;
+               let mut config_99_percent = UserConfig::default();
+               config_99_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 99;
+               let mut config_0_percent = UserConfig::default();
+               config_0_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 0;
+               let mut config_101_percent = UserConfig::default();
+               config_101_percent.own_channel_config.max_inbound_htlc_value_in_flight_percent_of_channel = 101;
+
+               // Test that `new_outbound` creates a channel with the correct value for
+               // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
+               // which is set to the lower bound + 1 (2%) of the `channel_value`.
+               let chan_1 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_2_percent, 0, 42).unwrap();
+               let chan_1_value_msat = chan_1.channel_value_satoshis * 1000;
+               assert_eq!(chan_1.holder_max_htlc_value_in_flight_msat, (chan_1_value_msat as f64 * 0.02) as u64);
+
+               // Test with the upper bound - 1 of valid values (99%).
+               let chan_2 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_99_percent, 0, 42).unwrap();
+               let chan_2_value_msat = chan_2.channel_value_satoshis * 1000;
+               assert_eq!(chan_2.holder_max_htlc_value_in_flight_msat, (chan_2_value_msat as f64 * 0.99) as u64);
+
+               let chan_1_open_channel_msg = chan_1.get_open_channel(genesis_block(network).header.block_hash());
+
+               // Test that `new_from_req` creates a channel with the correct value for
+               // `holder_max_htlc_value_in_flight_msat`, when configured with a valid percentage value,
+               // which is set to the lower bound - 1 (2%) of the `channel_value`.
+               let chan_3 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_2_percent, 0, &&logger, 42).unwrap();
+               let chan_3_value_msat = chan_3.channel_value_satoshis * 1000;
+               assert_eq!(chan_3.holder_max_htlc_value_in_flight_msat, (chan_3_value_msat as f64 * 0.02) as u64);
+
+               // Test with the upper bound - 1 of valid values (99%).
+               let chan_4 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_99_percent, 0, &&logger, 42).unwrap();
+               let chan_4_value_msat = chan_4.channel_value_satoshis * 1000;
+               assert_eq!(chan_4.holder_max_htlc_value_in_flight_msat, (chan_4_value_msat as f64 * 0.99) as u64);
+
+               // Test that `new_outbound` uses the lower bound of the configurable percentage values (1%)
+               // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
+               let chan_5 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_0_percent, 0, 42).unwrap();
+               let chan_5_value_msat = chan_5.channel_value_satoshis * 1000;
+               assert_eq!(chan_5.holder_max_htlc_value_in_flight_msat, (chan_5_value_msat as f64 * 0.01) as u64);
+
+               // Test that `new_outbound` uses the upper bound of the configurable percentage values
+               // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
+               // than 100.
+               let chan_6 = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, outbound_node_id, &InitFeatures::known(), 10000000, 100000, 42, &config_101_percent, 0, 42).unwrap();
+               let chan_6_value_msat = chan_6.channel_value_satoshis * 1000;
+               assert_eq!(chan_6.holder_max_htlc_value_in_flight_msat, chan_6_value_msat);
+
+               // Test that `new_from_req` uses the lower bound of the configurable percentage values (1%)
+               // if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a value less than 1.
+               let chan_7 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_0_percent, 0, &&logger, 42).unwrap();
+               let chan_7_value_msat = chan_7.channel_value_satoshis * 1000;
+               assert_eq!(chan_7.holder_max_htlc_value_in_flight_msat, (chan_7_value_msat as f64 * 0.01) as u64);
+
+               // Test that `new_from_req` uses the upper bound of the configurable percentage values
+               // (100%) if `max_inbound_htlc_value_in_flight_percent_of_channel` is set to a larger value
+               // than 100.
+               let chan_8 = Channel::<EnforcingSigner>::new_from_req(&&feeest, &&keys_provider, inbound_node_id, &InitFeatures::known(), &chan_1_open_channel_msg, 7, &config_101_percent, 0, &&logger, 42).unwrap();
+               let chan_8_value_msat = chan_8.channel_value_satoshis * 1000;
+               assert_eq!(chan_8.holder_max_htlc_value_in_flight_msat, chan_8_value_msat);
+       }
+
        #[test]
        fn channel_update() {
                let feeest = TestFeeEstimator{fee_est: 15000};
@@ -6731,9 +6823,9 @@ mod tests {
        #[cfg(not(feature = "grind_signatures"))]
        #[test]
        fn outbound_commitment_test() {
-               use bitcoin::util::bip143;
+               use bitcoin::util::sighash;
                use bitcoin::consensus::encode::serialize;
-               use bitcoin::blockdata::transaction::SigHashType;
+               use bitcoin::blockdata::transaction::EcdsaSighashType;
                use bitcoin::hashes::hex::FromHex;
                use bitcoin::hash_types::Txid;
                use bitcoin::secp256k1::Message;
@@ -6842,7 +6934,7 @@ mod tests {
                                let counterparty_signature = Signature::from_der(&hex::decode($counterparty_sig_hex).unwrap()[..]).unwrap();
                                let sighash = unsigned_tx.get_sighash_all(&redeemscript, chan.channel_value_satoshis);
                                log_trace!(logger, "unsigned_tx = {}", hex::encode(serialize(&unsigned_tx.transaction)));
-                               assert!(secp_ctx.verify(&sighash, &counterparty_signature, chan.counterparty_funding_pubkey()).is_ok(), "verify counterparty commitment sig");
+                               assert!(secp_ctx.verify_ecdsa(&sighash, &counterparty_signature, chan.counterparty_funding_pubkey()).is_ok(), "verify counterparty commitment sig");
 
                                let mut per_htlc: Vec<(HTLCOutputInCommitment, Option<Signature>)> = Vec::new();
                                per_htlc.clear(); // Don't warn about excess mut for no-HTLC calls
@@ -6881,9 +6973,9 @@ mod tests {
                                                chan.get_counterparty_selected_contest_delay().unwrap(),
                                                &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 { SigHashType::SinglePlusAnyoneCanPay } else { SigHashType::All };
-                                       let htlc_sighash = Message::from_slice(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype)[..]).unwrap();
-                                       assert!(secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).is_ok(), "verify counterparty htlc sig");
+                                       let htlc_sighashtype = if $opt_anchors { 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();
+                                       assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).is_ok(), "verify counterparty htlc sig");
 
                                        let mut preimage: Option<PaymentPreimage> = None;
                                        if !htlc.offered {