X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=eead5bf62301d3ff2b85180e691138ebeeffbe32;hb=315589076609d574c4367046d7270f18957cad1b;hp=b9a81f6ebc0465cf34396eb44073b790fd7c3925;hpb=af89de3d86356285b863bc3c4309b2853c981c96;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index b9a81f6e..eead5bf6 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -2,11 +2,9 @@ use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::script::{Script,Builder}; use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType}; use bitcoin::blockdata::opcodes; -use bitcoin::util::hash::{Sha256dHash, Hash160}; +use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160}; use bitcoin::util::bip143; -use bitcoin::network; -use bitcoin::network::serialize::{BitcoinHash, RawDecoder, RawEncoder}; -use bitcoin::network::encodable::{ConsensusEncodable, ConsensusDecodable}; +use bitcoin::consensus::encode::{self, Encodable, Decodable}; use secp256k1::key::{PublicKey,SecretKey}; use secp256k1::{Secp256k1,Message,Signature}; @@ -357,8 +355,9 @@ const UNCONF_THRESHOLD: u32 = 6; const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO? /// The amount of time we're willing to wait to claim money back to us const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 14; -const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; -const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; +/// Exposing these two constants for use in test in ChannelMonitor +pub const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; +pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4 const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?) /// Maximmum `funding_satoshis` value, according to the BOLT #2 specification @@ -438,7 +437,7 @@ impl Channel { let secp_ctx = Secp256k1::new(); let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key, - &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT, + &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), BREAKDOWN_TIMEOUT, keys_provider.get_destination_script(), logger.clone()); Ok(Channel { @@ -626,9 +625,10 @@ 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, BREAKDOWN_TIMEOUT, + &chan_keys.htlc_base_key, &chan_keys.payment_base_key, &keys_provider.get_shutdown_pubkey(), BREAKDOWN_TIMEOUT, keys_provider.get_destination_script(), logger.clone()); channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); + channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER, msg.first_per_commitment_point))); channel_monitor.set_their_to_self_delay(msg.to_self_delay); let mut chan = Channel { @@ -1122,8 +1122,9 @@ impl Channel { Ok(our_sig) } - /// May return an IgnoreError, but should not, and will always return Ok(_) when - /// debug_assertions are turned on + /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. + /// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return + /// Ok(_) if debug assertions are turned on and preconditions are met. fn get_update_fulfill_htlc(&mut self, htlc_id_arg: u64, payment_preimage_arg: [u8; 32]) -> Result<(Option, Option), HandleError> { // Either ChannelFunded got set (which means it wont bet unset) or there is no way any // caller thought we could have something claimed (cause we wouldn't have accepted in an @@ -1175,7 +1176,9 @@ impl Channel { &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { debug_assert!(false, "Tried to fulfill an HTLC we already had a holding-cell failure on"); - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)}); + // Return the new channel monitor in a last-ditch effort to hit the + // chain and claim the funds + return Ok((None, Some(self.channel_monitor.clone()))); } }, _ => {} @@ -1215,8 +1218,9 @@ impl Channel { } } - /// May return an IgnoreError, but should not, and will always return Ok(_) when - /// debug_assertions are turned on + /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. + /// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return + /// Ok(_) if debug assertions are turned on and preconditions are met. pub fn get_update_fail_htlc(&mut self, htlc_id_arg: u64, err_packet: msgs::OnionErrorPacket) -> Result, HandleError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { panic!("Was asked to fail an HTLC when channel was not in an operational state"); @@ -1349,6 +1353,7 @@ impl Channel { } self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); + self.channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER, msg.first_per_commitment_point))); 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); @@ -1373,22 +1378,25 @@ impl Channel { Ok(()) } - fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Signature), HandleError> { + fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Transaction, Signature, TxCreationKeys), HandleError> { let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - 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 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_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap(); - // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish. + // They sign the "local" commitment transaction... secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer", self.channel_id()); + // ...and we sign it, allowing us to broadcast the tx if we wish + self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig); + 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 = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap(); // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish. - Ok((remote_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key))) + Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), local_keys)) } pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), HandleError> { @@ -1411,7 +1419,7 @@ impl Channel { let funding_txo_script = self.get_funding_redeemscript().to_v0_p2wsh(); self.channel_monitor.set_funding_info((funding_txo, funding_txo_script)); - let (remote_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature) { + let (remote_initial_commitment_tx, local_initial_commitment_tx, our_signature, local_keys) = match self.funding_created_signature(&msg.signature) { Ok(res) => res, Err(e) => { self.channel_monitor.unset_funding_info(); @@ -1422,6 +1430,8 @@ 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.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(); self.cur_remote_commitment_transaction_number -= 1; @@ -1491,6 +1501,7 @@ impl Channel { return Err(ChannelError::Close("Peer sent a funding_locked at a strange time")); } + self.channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER - 1 , msg.next_per_commitment_point))); self.their_prev_commitment_point = self.their_cur_commitment_point; self.their_cur_commitment_point = Some(msg.next_per_commitment_point); Ok(()) @@ -1653,7 +1664,9 @@ impl Channel { let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; + let mut update_fee = false; let feerate_per_kw = if !self.channel_outbound && self.pending_update_fee.is_some() { + update_fee = true; self.pending_update_fee.unwrap() } else { self.feerate_per_kw @@ -1664,6 +1677,16 @@ impl Channel { let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap(); secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer", self.channel_id()); + //If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction + if update_fee { + let num_htlcs = local_commitment_tx.1.len(); + let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + + if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + self.their_channel_reserve_satoshis { + return Err(HandleError { err: "Funding remote cannot afford proposed new fee", action: Some(ErrorAction::DisconnectPeer { msg: None }) }); + } + } + if msg.htlc_signatures.len() != local_commitment_tx.1.len() { return Err(HandleError{err: "Got wrong number of HTLC signatures from remote", action: None}); } @@ -1677,7 +1700,7 @@ impl Channel { let mut 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); let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap(); - secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx siganture from peer", self.channel_id()); + secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer", self.channel_id()); 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); @@ -1705,6 +1728,7 @@ impl Channel { } } } + if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { // This is a response to our post-monitor-failed unfreeze messages, so we can clear the // monitor_pending_order requirement as we won't re-send the monitor_pending messages. @@ -1870,7 +1894,9 @@ impl Channel { return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", action: None}); } } - self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret, Some((self.cur_remote_commitment_transaction_number - 1, msg.next_per_commitment_point)))?; + self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret) + .map_err(|e| HandleError{err: e.0, action: None})?; + self.channel_monitor.provide_their_next_revocation_point(Some((self.cur_remote_commitment_transaction_number - 1, msg.next_per_commitment_point))); // Update state now that we've passed all the can-fail calls... // (note that we may still fail to generate the new commitment_signed message, but that's @@ -2188,7 +2214,6 @@ impl Channel { return Err(ChannelError::Close("Peer sent update_fee when we needed a channel_reestablish")); } Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; - self.pending_update_fee = Some(msg.feerate_per_kw as u64); self.channel_update_count += 1; Ok(()) @@ -2823,6 +2848,16 @@ impl Channel { self.channel_update_count += 1; return Err(HandleError{err: "funding tx had wrong script/value", action: Some(ErrorAction::DisconnectPeer{msg: None})}); } else { + if self.channel_outbound { + for input in tx.input.iter() { + if input.witness.is_empty() { + // We generated a malleable funding transaction, implying we've + // just exposed ourselves to funds loss to our counterparty. + #[cfg(not(feature = "fuzztarget"))] + panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); + } + } + } self.funding_tx_confirmations = 1; self.short_channel_id = Some(((height as u64) << (5*8)) | ((*index_in_block as u64) << (2*8)) | @@ -3511,9 +3546,9 @@ impl Writeable for Channel { (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 RawEncoder::new(WriterWriteAdaptor(writer))) { + if let Err(e) = tx.consensus_encode(&mut WriterWriteAdaptor(writer)) { match e { - network::serialize::Error::Io(e) => return Err(e), + encode::Error::Io(e) => return Err(e), _ => panic!("last_local_commitment_txn must have been well-formed!"), } } @@ -3690,7 +3725,7 @@ impl ReadableArgs> for Channel { let last_local_commitment_txn_count: u64 = Readable::read(reader)?; let mut last_local_commitment_txn = Vec::with_capacity(cmp::min(last_local_commitment_txn_count as usize, OUR_MAX_HTLCS as usize*2 + 1)); for _ in 0..last_local_commitment_txn_count { - last_local_commitment_txn.push(match Transaction::consensus_decode(&mut RawDecoder::new(reader.by_ref())) { + last_local_commitment_txn.push(match Transaction::consensus_decode(reader.by_ref()) { Ok(tx) => tx, Err(_) => return Err(DecodeError::InvalidValue), }); @@ -3818,7 +3853,7 @@ impl ReadableArgs> for Channel { mod tests { use bitcoin::util::hash::{Sha256dHash, Hash160}; use bitcoin::util::bip143; - use bitcoin::network::serialize::serialize; + use bitcoin::consensus::encode::serialize; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::opcodes; @@ -3940,7 +3975,7 @@ mod tests { chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature); - assert_eq!(serialize(&unsigned_tx.0).unwrap()[..], + assert_eq!(serialize(&unsigned_tx.0)[..], hex::decode($tx_hex).unwrap()[..]); }; } @@ -3973,7 +4008,7 @@ mod tests { } chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap(); - assert_eq!(serialize(&htlc_tx).unwrap()[..], + assert_eq!(serialize(&htlc_tx)[..], hex::decode($tx_hex).unwrap()[..]); }; }