X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=c34fc6a38c28e5ae89a5cd98e094ee7a5348781a;hb=4e82003261e11ece5d5fb3b13f686c9f7a0d2aaf;hp=dd9170b47e7d8541d88597a358eb7ffa138045a2;hpb=0f6b0004c490855ad88ce1bb545268eb6561fdc2;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index dd9170b4..c34fc6a3 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -25,12 +25,12 @@ use bitcoin::secp256k1; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER}; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use ln::chan_utils::{CounterpartyCommitmentSecrets, HolderCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, PreCalculatedTxCreationKeys}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; -use chain::transaction::OutPoint; +use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER}; +use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::transaction_utils; use util::ser::{Readable, Writeable, Writer}; @@ -487,14 +487,14 @@ impl Channel { let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); Ok(Channel { - user_id: user_id, + user_id, config: config.channel_options.clone(), channel_id: keys_provider.get_secure_random_bytes(), channel_state: ChannelState::OurInitSent as u32, channel_outbound: true, secp_ctx: Secp256k1::new(), - channel_value_satoshis: channel_value_satoshis, + channel_value_satoshis, latest_monitor_update_id: 0, @@ -715,7 +715,7 @@ impl Channel { } else { None }; let chan = Channel { - user_id: user_id, + user_id, config: local_config, channel_id: msg.temporary_channel_id, @@ -766,7 +766,7 @@ impl Channel { feerate_per_kw: msg.feerate_per_kw, channel_value_satoshis: msg.funding_satoshis, counterparty_dust_limit_satoshis: msg.dust_limit_satoshis, - holder_dust_limit_satoshis: holder_dust_limit_satoshis, + holder_dust_limit_satoshis, counterparty_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), counterparty_selected_channel_reserve_satoshis: msg.channel_reserve_satoshis, counterparty_htlc_minimum_msat: msg.htlc_minimum_msat, @@ -1054,8 +1054,30 @@ impl Channel { } #[inline] - fn get_closing_transaction_weight(a_scriptpubkey: &Script, b_scriptpubkey: &Script) -> u64 { - (4 + 1 + 36 + 4 + 1 + 1 + 2*(8+1) + 4 + a_scriptpubkey.len() as u64 + b_scriptpubkey.len() as u64)*4 + 2 + 1 + 1 + 2*(1 + 72) + fn get_closing_transaction_weight(&self, a_scriptpubkey: Option<&Script>, b_scriptpubkey: Option<&Script>) -> u64 { + let mut ret = + (4 + // version + 1 + // input count + 36 + // prevout + 1 + // script length (0) + 4 + // sequence + 1 + // output count + 4 // lock time + )*4 + // * 4 for non-witness parts + 2 + // witness marker and flag + 1 + // witness element count + 4 + // 4 element lengths (2 sigs, multisig dummy, and witness script) + self.get_funding_redeemscript().len() as u64 + // funding witness script + 2*(1 + 71); // two signatures + sighash type flags + if let Some(spk) = a_scriptpubkey { + ret += ((8+1) + // output values and script length + spk.len() as u64) * 4; // scriptpubkey and witness multiplier + } + if let Some(spk) = b_scriptpubkey { + ret += ((8+1) + // output values and script length + spk.len() as u64) * 4; // scriptpubkey and witness multiplier + } + ret } #[inline] @@ -1557,7 +1579,7 @@ impl Channel { Ok((msgs::FundingSigned { channel_id: self.channel_id, - signature: signature + signature }, channel_monitor)) } @@ -2113,8 +2135,8 @@ impl Channel { Ok((msgs::RevokeAndACK { channel_id: self.channel_id, - per_commitment_secret: per_commitment_secret, - next_per_commitment_point: next_per_commitment_point, + per_commitment_secret, + next_per_commitment_point, }, commitment_signed, closing_signed, monitor_update)) } @@ -2218,7 +2240,7 @@ impl Channel { update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs: Vec::new(), - update_fee: update_fee, + update_fee, commitment_signed, }, monitor_update)), htlcs_to_fail)) } else { @@ -2475,7 +2497,7 @@ impl Channel { Some(msgs::UpdateFee { channel_id: self.channel_id, - feerate_per_kw: feerate_per_kw, + feerate_per_kw, }) } @@ -2601,7 +2623,7 @@ impl Channel { let next_per_commitment_point = self.holder_keys.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); Some(msgs::FundingLocked { channel_id: self.channel_id(), - next_per_commitment_point: next_per_commitment_point, + next_per_commitment_point, }) } else { None }; @@ -2776,7 +2798,7 @@ impl Channel { let next_per_commitment_point = self.holder_keys.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id(), - next_per_commitment_point: next_per_commitment_point, + next_per_commitment_point, }), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg)); } @@ -2806,7 +2828,7 @@ impl Channel { let next_per_commitment_point = self.holder_keys.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); Some(msgs::FundingLocked { channel_id: self.channel_id(), - next_per_commitment_point: next_per_commitment_point, + next_per_commitment_point, }) } else { None }; @@ -2880,13 +2902,14 @@ impl Channel { if self.feerate_per_kw > proposed_feerate { proposed_feerate = self.feerate_per_kw; } - let tx_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()); + let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap())); let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000; let (closing_tx, total_fee_satoshis) = self.build_closing_transaction(proposed_total_fee_satoshis, false); let sig = self.holder_keys .sign_closing_transaction(&closing_tx, &self.secp_ctx) .ok(); + assert!(closing_tx.get_weight() as u64 <= tx_weight); if sig.is_none() { return None; } self.last_sent_closing_fee = Some((proposed_feerate, total_fee_satoshis, sig.clone().unwrap())); @@ -3007,7 +3030,7 @@ impl Channel { if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() { return Err(ChannelError::Close("Remote end sent us a closing_signed while there were still pending HTLCs".to_owned())); } - if msg.fee_satoshis > 21000000 * 10000000 { //this is required to stop potential overflow in build_closing_transaction + if msg.fee_satoshis > 21_000_000 * 1_0000_0000 { //this is required to stop potential overflow in build_closing_transaction return Err(ChannelError::Close("Remote tried to send us a closing tx with > 21 million BTC fee".to_owned())); } @@ -3031,9 +3054,14 @@ impl Channel { }, }; + let closing_tx_max_weight = self.get_closing_transaction_weight( + if let Some(oup) = closing_tx.output.get(0) { Some(&oup.script_pubkey) } else { None }, + if let Some(oup) = closing_tx.output.get(1) { Some(&oup.script_pubkey) } else { None }); if let Some((_, last_fee, sig)) = self.last_sent_closing_fee { if last_fee == msg.fee_satoshis { self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); + assert!(closing_tx.get_weight() as u64 <= closing_tx_max_weight); + debug_assert!(closing_tx.get_weight() as u64 >= closing_tx_max_weight - 2); self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; return Ok((None, Some(closing_tx))); @@ -3042,11 +3070,12 @@ impl Channel { macro_rules! propose_new_feerate { ($new_feerate: expr) => { - let closing_tx_max_weight = Self::get_closing_transaction_weight(&self.get_closing_scriptpubkey(), self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()); - let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * closing_tx_max_weight / 1000, false); + let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap())); + let (closing_tx, used_total_fee) = self.build_closing_transaction($new_feerate as u64 * tx_weight / 1000, false); let sig = self.holder_keys .sign_closing_transaction(&closing_tx, &self.secp_ctx) .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; + assert!(closing_tx.get_weight() as u64 <= tx_weight); self.last_sent_closing_fee = Some(($new_feerate, used_total_fee, sig.clone())); return Ok((Some(msgs::ClosingSigned { channel_id: self.channel_id, @@ -3056,10 +3085,10 @@ impl Channel { } } - let proposed_sat_per_kw = msg.fee_satoshis * 1000 / closing_tx.get_weight() as u64; + let mut min_feerate = 253; if self.channel_outbound { let max_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); - if (proposed_sat_per_kw as u32) > max_feerate { + if (msg.fee_satoshis as u64) > max_feerate as u64 * closing_tx_max_weight / 1000 { if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { if max_feerate <= last_feerate { return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wanted something higher ({}) than our Normal feerate ({})", last_feerate, max_feerate))); @@ -3068,21 +3097,23 @@ impl Channel { propose_new_feerate!(max_feerate); } } else { - let min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); - if (proposed_sat_per_kw as u32) < min_feerate { - if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { - if min_feerate >= last_feerate { - return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wanted something lower ({}) than our Background feerate ({}).", last_feerate, min_feerate))); - } + min_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background); + } + if (msg.fee_satoshis as u64) < min_feerate as u64 * closing_tx_max_weight / 1000 { + if let Some((last_feerate, _, _)) = self.last_sent_closing_fee { + if min_feerate >= last_feerate { + return Err(ChannelError::Close(format!("Unable to come to consensus about closing feerate, remote wanted something lower ({}) than our Background feerate ({}).", last_feerate, min_feerate))); } - propose_new_feerate!(min_feerate); } + propose_new_feerate!(min_feerate); } let sig = self.holder_keys .sign_closing_transaction(&closing_tx, &self.secp_ctx) .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?; self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig); + assert!(closing_tx.get_weight() as u64 <= closing_tx_max_weight); + debug_assert!(closing_tx.get_weight() as u64 >= closing_tx_max_weight - 2); self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; @@ -3315,7 +3346,7 @@ impl Channel { /// /// May return some HTLCs (and their payment_hash) which have timed out and should be failed /// back. - pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[usize]) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> { + pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32) -> Result<(Option, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> { let mut timed_out_htlcs = Vec::new(); self.holding_cell_htlc_updates.retain(|htlc_update| { match htlc_update { @@ -3335,7 +3366,7 @@ impl Channel { } } if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { - for (ref tx, index_in_block) in txn_matched.iter().zip(indexes_of_txn_matched) { + for &(index_in_block, tx) in txdata.iter() { if tx.txid() == self.funding_txo.unwrap().txid { let txo_idx = self.funding_txo.unwrap().index as usize; if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() || @@ -3366,14 +3397,14 @@ impl Channel { } } } - if height > 0xff_ff_ff || (*index_in_block) > 0xff_ff_ff { + if height > 0xff_ff_ff || (index_in_block) > 0xff_ff_ff { panic!("Block was bogus - either height 16 million or had > 16 million transactions"); } assert!(txo_idx <= 0xffff); // txo_idx is a (u16 as usize), so this is just listed here for completeness self.funding_tx_confirmations = 1; - self.short_channel_id = Some(((height as u64) << (5*8)) | - ((*index_in_block as u64) << (2*8)) | - ((txo_idx as u64) << (0*8))); + self.short_channel_id = Some(((height as u64) << (5*8)) | + ((index_in_block as u64) << (2*8)) | + ((txo_idx as u64) << (0*8))); } } } @@ -3412,7 +3443,7 @@ impl Channel { let next_per_commitment_point = self.holder_keys.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx); return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id, - next_per_commitment_point: next_per_commitment_point, + next_per_commitment_point, }), timed_out_htlcs)); } else { self.monitor_pending_funding_locked = true; @@ -3461,7 +3492,7 @@ impl Channel { let keys = self.holder_keys.pubkeys(); msgs::OpenChannel { - chain_hash: chain_hash, + chain_hash, temporary_channel_id: self.channel_id, funding_satoshis: self.channel_value_satoshis, push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat, @@ -3566,7 +3597,7 @@ impl Channel { temporary_channel_id, funding_txid: funding_txo.txid, funding_output_index: funding_txo.index, - signature: signature + signature }) } @@ -3593,7 +3624,7 @@ impl Channel { let msg = msgs::UnsignedChannelAnnouncement { features: ChannelFeatures::known(), - chain_hash: chain_hash, + chain_hash, short_channel_id: self.get_short_channel_id().unwrap(), node_id_1: if were_node_one { node_id } else { self.get_counterparty_node_id() }, node_id_2: if were_node_one { self.get_counterparty_node_id() } else { node_id }, @@ -3986,12 +4017,6 @@ impl Channel { } } - for _htlc in self.pending_outbound_htlcs.drain(..) { - //TODO: Do something with the remaining HTLCs - //(we need to have the ChannelManager monitor them so we can claim the inbound HTLCs - //which correspond) - } - self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; self.latest_monitor_update_id += 1;