X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=1917ef5285eeabb7ddd90e2bcb5307f2df64ad9d;hb=eb97a7534dec781290b817b4d311994c1711f7b7;hp=ca4dc89c32e67e7dac0ed41805228d40e74c12a8;hpb=f2a2fd0d48be78972ed81481c2dfbfb68ecda44e;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index ca4dc89c..1917ef52 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -4,7 +4,7 @@ use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType}; use bitcoin::blockdata::opcodes; use bitcoin::util::hash::BitcoinHash; use bitcoin::util::bip143; -use bitcoin::consensus::encode::{self, Encodable, Decodable}; +use bitcoin::consensus::encode; use bitcoin_hashes::{Hash, HashEngine}; use bitcoin_hashes::sha256::Hash as Sha256; @@ -19,13 +19,13 @@ use ln::msgs; use ln::msgs::{DecodeError, OptionalField, LocalFeatures, DataLossProtect}; use ln::channelmonitor::ChannelMonitor; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; -use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; +use ln::chan_utils::{LocalCommitmentTransaction,TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::transaction_utils; -use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor}; +use util::ser::{Readable, ReadableArgs, Writeable, Writer}; use util::logger::{Logger, LogHolder}; use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; @@ -297,13 +297,7 @@ pub(super) struct Channel { /// Max to_local and to_remote outputs in a remote-generated commitment transaction max_commitment_tx_output_remote: ::std::sync::Mutex<(u64, u64)>, - #[cfg(test)] - // Used in ChannelManager's tests to send a revoked transaction - pub last_local_commitment_txn: Vec, - #[cfg(not(test))] - last_local_commitment_txn: Vec, - - last_sent_closing_fee: Option<(u64, u64)>, // (feerate, fee) + last_sent_closing_fee: Option<(u64, u64, Signature)>, // (feerate, fee, our_sig) /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this /// to detect unconfirmation after a serialize-unserialize roundtrip where we may not see a full @@ -456,7 +450,7 @@ impl Channel { let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); let secp_ctx = Secp256k1::new(); - let channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, keys_provider.get_destination_script(), logger.clone()); @@ -498,8 +492,6 @@ impl Channel { #[cfg(debug_assertions)] max_commitment_tx_output_remote: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)), - last_local_commitment_txn: Vec::new(), - last_sent_closing_fee: None, funding_tx_confirmed_in: None, @@ -652,11 +644,9 @@ impl Channel { } let secp_ctx = Secp256k1::new(); - let mut channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), - chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, - keys_provider.get_destination_script(), logger.clone()); - channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); - channel_monitor.set_their_to_self_delay(msg.to_self_delay); + let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(), + chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay, + keys_provider.get_destination_script(), logger.clone()); let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { match &msg.shutdown_scriptpubkey { @@ -716,8 +706,6 @@ impl Channel { #[cfg(debug_assertions)] max_commitment_tx_output_remote: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)), - last_local_commitment_txn: Vec::new(), - last_sent_closing_fee: None, funding_tx_confirmed_in: None, @@ -758,7 +746,8 @@ impl Channel { }; let obscure_factor = chan.get_commitment_transaction_number_obscure_factor(); - chan.channel_monitor.set_commitment_obscure_factor(obscure_factor); + let funding_redeemscript = chan.get_funding_redeemscript(); + chan.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, msg.funding_satoshis, obscure_factor); Ok(chan) } @@ -833,7 +822,7 @@ impl Channel { let mut local_htlc_total_msat = 0; let mut value_to_self_msat_offset = 0; - log_trace!(self, "Building commitment transaction number {} for {}, generated by {} with fee {}...", commitment_number, if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); + log_trace!(self, "Building commitment transaction number {} (really {} xor {}) for {}, generated by {} with fee {}...", commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number), self.get_commitment_transaction_number_obscure_factor(), if local { "us" } else { "remote" }, if generated_by_local { "us" } else { "remote" }, feerate_per_kw); macro_rules! get_htlc_in_commitment { ($htlc: expr, $offered: expr) => { @@ -1133,38 +1122,6 @@ impl Channel { }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script() } - fn sign_commitment_transaction(&self, tx: &mut Transaction, their_sig: &Signature) -> Signature { - if tx.input.len() != 1 { - panic!("Tried to sign commitment transaction that had input count != 1!"); - } - if tx.input[0].witness.len() != 0 { - panic!("Tried to re-sign commitment transaction"); - } - - let funding_redeemscript = self.get_funding_redeemscript(); - - let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, self.local_keys.funding_key()); - - tx.input[0].witness.push(Vec::new()); // First is the multisig dummy - - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); - let their_funding_key = self.their_funding_pubkey.unwrap().serialize(); - if our_funding_key[..] < their_funding_key[..] { - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - } else { - tx.input[0].witness.push(their_sig.serialize_der().to_vec()); - tx.input[0].witness.push(our_sig.serialize_der().to_vec()); - } - tx.input[0].witness[1].push(SigHashType::All as u8); - tx.input[0].witness[2].push(SigHashType::All as u8); - - tx.input[0].witness.push(funding_redeemscript.into_bytes()); - - our_sig - } - /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output /// @local is used only to convert relevant internal structures which refer to remote vs local /// to decide value of outputs and direction of HTLCs. @@ -1185,8 +1142,10 @@ impl Channel { Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx)) } + #[cfg(test)] /// Signs a transaction created by build_htlc_transaction. If the transaction is an /// HTLC-Success transaction (ie htlc.offered is false), preimage must be set! + /// TODO: Make this a chan_utils, use it in channelmonitor and tests, cause its unused now fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result { if tx.input.len() != 1 { panic!("Tried to sign HTLC transaction that had input count != 1!"); @@ -1477,8 +1436,6 @@ impl Channel { } } else { None }; - self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); - self.their_dust_limit_satoshis = msg.dust_limit_satoshis; self.their_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000); self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis; @@ -1495,33 +1452,33 @@ impl Channel { self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey; let obscure_factor = self.get_commitment_transaction_number_obscure_factor(); - self.channel_monitor.set_commitment_obscure_factor(obscure_factor); - self.channel_monitor.set_their_to_self_delay(msg.to_self_delay); + let funding_redeemscript = self.get_funding_redeemscript(); + self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor); self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32; Ok(()) } - fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Transaction, Signature, TxCreationKeys), ChannelError> { + fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, LocalCommitmentTransaction, Signature, TxCreationKeys), ChannelError> { let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; + let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); // They sign the "local" commitment transaction... secp_check!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer"); - // ...and we sign it, allowing us to broadcast the tx if we wish - self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig); + let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()); let remote_keys = self.build_remote_transaction_keys()?; let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); + let remote_signature = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0; // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), local_keys)) + Ok((remote_initial_commitment_tx, localtx, remote_signature, local_keys)) } pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> { @@ -1555,7 +1512,6 @@ impl Channel { // Now that we're past error-generating stuff, update our local state: self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap()); - self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()]; self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new()); self.channel_state = ChannelState::FundingSent as u32; self.channel_id = funding_txo.to_channel_id(); @@ -1586,15 +1542,15 @@ impl Channel { let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; + let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0; let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish. secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer"); - self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature); - self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new()); - self.last_local_commitment_txn = vec![local_initial_commitment_tx]; + self.channel_monitor.provide_latest_local_commitment_tx_info( + LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()), + local_keys, self.feerate_per_kw, Vec::new()); self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32)); self.cur_local_commitment_transaction_number -= 1; @@ -1858,25 +1814,15 @@ impl Channel { return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote")); } - let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 1); - self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature); - new_local_commitment_txn.push(local_commitment_tx.0.clone()); - let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len()); for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() { if let Some(_) = htlc.transaction_output_index { - let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); + let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys); log_trace!(self, "Checking HTLC tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript)); let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer"); - let htlc_sig = if htlc.offered { - let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, &htlc, &local_keys)?; - new_local_commitment_txn.push(htlc_tx); - htlc_sig - } else { - self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1 - }; + let htlc_sig = self.create_htlc_tx_signature(&htlc_tx, &htlc, &local_keys)?.1; htlcs_and_sigs.push((htlc, Some((msg.htlc_signatures[idx], htlc_sig)), source)); } else { htlcs_and_sigs.push((htlc, None, source)); @@ -1901,7 +1847,10 @@ impl Channel { } } - self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs); + + self.channel_monitor.provide_latest_local_commitment_tx_info( + LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()), + local_keys, self.feerate_per_kw, htlcs_and_sigs); for htlc in self.pending_inbound_htlcs.iter_mut() { let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state { @@ -1922,7 +1871,6 @@ impl Channel { } self.cur_local_commitment_transaction_number -= 1; - self.last_local_commitment_txn = new_local_commitment_txn; // Note that if we need_our_commitment & !AwaitingRemoteRevoke we'll call // send_commitment_no_status_check() next which will reset this to RAAFirst. self.resend_order = RAACommitmentOrder::CommitmentFirst; @@ -2664,14 +2612,16 @@ impl Channel { let proposed_total_fee_satoshis = proposed_feerate * tx_weight / 1000; let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false); - let funding_redeemscript = self.get_funding_redeemscript(); - let sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &self.get_funding_redeemscript(), &closing_tx, &self.secp_ctx) + .ok(); + if our_sig.is_none() { return None; } - self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis)); + self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, our_sig.clone().unwrap())); Some(msgs::ClosingSigned { channel_id: self.channel_id, fee_satoshis: total_fee_satoshis, - signature: self.secp_ctx.sign(&sighash, &self.local_keys.funding_key()), + signature: our_sig.unwrap(), }) } @@ -2748,6 +2698,28 @@ impl Channel { Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs)) } + fn build_signed_closing_transaction(&self, tx: &mut Transaction, their_sig: &Signature, our_sig: &Signature) { + if tx.input.len() != 1 { panic!("Tried to sign closing transaction that had input count != 1!"); } + if tx.input[0].witness.len() != 0 { panic!("Tried to re-sign closing transaction"); } + if tx.output.len() > 2 { panic!("Tried to sign bogus closing transaction"); } + + tx.input[0].witness.push(Vec::new()); // First is the multisig dummy + + let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); + let their_funding_key = self.their_funding_pubkey.unwrap().serialize(); + if our_funding_key[..] < their_funding_key[..] { + tx.input[0].witness.push(our_sig.serialize_der().to_vec()); + tx.input[0].witness.push(their_sig.serialize_der().to_vec()); + } else { + tx.input[0].witness.push(their_sig.serialize_der().to_vec()); + tx.input[0].witness.push(our_sig.serialize_der().to_vec()); + } + 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()); + } + pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option, Option), ChannelError> { if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK { return Err(ChannelError::Close("Remote end sent us a closing_signed before both sides provided a shutdown")); @@ -2780,9 +2752,9 @@ impl Channel { }, }; - if let Some((_, last_fee)) = self.last_sent_closing_fee { + if let Some((_, last_fee, our_sig)) = self.last_sent_closing_fee { if last_fee == msg.fee_satoshis { - self.sign_commitment_transaction(&mut closing_tx, &msg.signature); + self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; return Ok((None, Some(closing_tx))); @@ -2793,9 +2765,10 @@ impl Channel { ($new_feerate: expr) => { let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.their_shutdown_scriptpubkey.as_ref().unwrap()); let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate * closing_tx_max_weight / 1000, false); - sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key()); - self.last_sent_closing_fee = Some(($new_feerate, used_total_fee)); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &funding_redeemscript, &closing_tx, &self.secp_ctx) + .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction"))?; + self.last_sent_closing_fee = Some(($new_feerate, used_total_fee, our_sig.clone())); return Ok((Some(msgs::ClosingSigned { channel_id: self.channel_id, fee_satoshis: used_total_fee, @@ -2808,7 +2781,7 @@ impl Channel { if self.channel_outbound { let our_max_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); if proposed_sat_per_kw > our_max_feerate { - if let Some((last_feerate, _)) = self.last_sent_closing_fee { + if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { if our_max_feerate <= last_feerate { return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something higher than our Normal feerate")); } @@ -2818,7 +2791,7 @@ impl Channel { } else { let our_min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); if proposed_sat_per_kw < our_min_feerate { - if let Some((last_feerate, _)) = self.last_sent_closing_fee { + if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { if our_min_feerate >= last_feerate { return Err(ChannelError::Close("Unable to come to consensus about closing feerate, remote wanted something lower than our Background feerate")); } @@ -2827,7 +2800,11 @@ impl Channel { } } - let our_sig = self.sign_commitment_transaction(&mut closing_tx, &msg.signature); + let our_sig = self.local_keys + .sign_closing_transaction(self.channel_value_satoshis, &funding_redeemscript, &closing_tx, &self.secp_ctx) + .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction"))?; + self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig); + self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; @@ -2851,11 +2828,11 @@ impl Channel { } /// May only be called after funding has been initiated (ie is_funding_initiated() is true) - pub fn channel_monitor(&self) -> ChannelMonitor { + pub fn channel_monitor(&mut self) -> &mut ChannelMonitor { if self.channel_state < ChannelState::FundingCreated as u32 { panic!("Can't get a channel monitor until funding has been created"); } - self.channel_monitor.clone() + &mut self.channel_monitor } /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus, @@ -3222,14 +3199,10 @@ impl Channel { /// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created) fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), ChannelError> { - let funding_script = self.get_funding_redeemscript(); - let remote_keys = self.build_remote_transaction_keys()?; let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0; - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]); - - // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()), remote_initial_commitment_tx)) + Ok((self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0, remote_initial_commitment_tx)) } /// Updates channel state with knowledge of the funding transaction's txid/index, and generates @@ -3313,8 +3286,8 @@ impl Channel { excess_data: Vec::new(), }; - let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); - let sig = self.secp_ctx.sign(&msghash, self.local_keys.funding_key()); + let sig = self.local_keys.sign_channel_announcement(&msg, &self.secp_ctx) + .map_err(|_| ChannelError::Ignore("Signer rejected channel_announcement"))?; Ok((msg, sig)) } @@ -3519,8 +3492,6 @@ impl Channel { /// Only fails in case of bad keys. Used for channel_reestablish commitment_signed generation /// when we shouldn't change HTLC/channel state. fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> { - let funding_script = self.get_funding_redeemscript(); - let mut feerate_per_kw = self.feerate_per_kw; if let Some(feerate) = self.pending_update_fee { if self.channel_outbound { @@ -3530,27 +3501,37 @@ impl Channel { let remote_keys = self.build_remote_transaction_keys()?; let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw); - let remote_commitment_txid = remote_commitment_tx.0.txid(); - let remote_sighash = hash_to_message!(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]); - let our_sig = self.secp_ctx.sign(&remote_sighash, self.local_keys.funding_key()); - log_trace!(self, "Signing remote commitment tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&remote_commitment_tx.0), encode::serialize_hex(&funding_script), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize()), log_bytes!(our_sig.serialize_compact()[..])); + let (signature, htlc_signatures); - let mut htlc_sigs = Vec::with_capacity(remote_commitment_tx.1); - for &(ref htlc, _) in remote_commitment_tx.2.iter() { - if let Some(_) = htlc.transaction_output_index { - let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw); - let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys); - let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]); - let our_htlc_key = secp_check!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, self.local_keys.htlc_base_key()), "Derived invalid key, peer is maliciously selecting parameters"); - htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key)); - log_trace!(self, "Signing remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript), log_bytes!(PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).serialize()), log_bytes!(htlc_sigs.last().unwrap().serialize_compact()[..])); + { + let mut htlcs = Vec::with_capacity(remote_commitment_tx.2.len()); + for &(ref htlc, _) in remote_commitment_tx.2.iter() { + htlcs.push(htlc); + } + + let res = self.local_keys.sign_remote_commitment(self.channel_value_satoshis, &self.get_funding_redeemscript(), feerate_per_kw, &remote_commitment_tx.0, &remote_keys, &htlcs, self.our_to_self_delay, &self.secp_ctx) + .map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?; + signature = res.0; + htlc_signatures = res.1; + + log_trace!(self, "Signed remote commitment tx {} with redeemscript {} -> {}", + encode::serialize_hex(&remote_commitment_tx.0), + encode::serialize_hex(&self.get_funding_redeemscript()), + log_bytes!(signature.serialize_compact()[..])); + + for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { + log_trace!(self, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", + encode::serialize_hex(&chan_utils::build_htlc_transaction(&remote_commitment_tx.0.txid(), feerate_per_kw, self.our_to_self_delay, htlc, &remote_keys.a_delayed_payment_key, &remote_keys.revocation_key)), + encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &remote_keys)), + log_bytes!(remote_keys.a_htlc_key.serialize()), + log_bytes!(htlc_sig.serialize_compact()[..])); } } Ok((msgs::CommitmentSigned { channel_id: self.channel_id, - signature: our_sig, - htlc_signatures: htlc_sigs, + signature, + htlc_signatures, }, (remote_commitment_tx.0, remote_commitment_tx.2))) } @@ -3647,9 +3628,7 @@ impl Channel { self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; - let mut res = Vec::new(); - mem::swap(&mut res, &mut self.last_local_commitment_txn); - (res, dropped_outbound_htlcs) + (self.channel_monitor.get_latest_local_commitment_txn(), dropped_outbound_htlcs) } } @@ -3839,21 +3818,12 @@ impl Writeable for Channel { self.channel_update_count.write(writer)?; self.feerate_per_kw.write(writer)?; - (self.last_local_commitment_txn.len() as u64).write(writer)?; - for tx in self.last_local_commitment_txn.iter() { - if let Err(e) = tx.consensus_encode(&mut WriterWriteAdaptor(writer)) { - match e { - encode::Error::Io(e) => return Err(e), - _ => panic!("last_local_commitment_txn must have been well-formed!"), - } - } - } - match self.last_sent_closing_fee { - Some((feerate, fee)) => { + Some((feerate, fee, sig)) => { 1u8.write(writer)?; feerate.write(writer)?; fee.write(writer)?; + sig.write(writer)?; }, None => 0u8.write(writer)?, } @@ -4006,18 +3976,9 @@ impl> ReadableArgs tx, - Err(_) => return Err(DecodeError::InvalidValue), - }); - } - let last_sent_closing_fee = match >::read(reader)? { 0 => None, - 1 => Some((Readable::read(reader)?, Readable::read(reader)?)), + 1 => Some((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)), _ => return Err(DecodeError::InvalidValue), }; @@ -4097,8 +4058,6 @@ impl> ReadableArgs