X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=a8550932d5ad597e4e16bef4cfdfe7ae68f8df3f;hb=b9a155d75f723f0e99f7bf7faf0abe5c7b492dfd;hp=e71ba9b2c63f151351d60f9f9ce9f46c91620b39;hpb=5ef88cea34b9cf90fa5198b2ff4347e66e49a927;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index e71ba9b2..a8550932 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -14,7 +14,7 @@ use crypto::digest::Digest; use crypto::hkdf::{hkdf_extract,hkdf_expand}; use ln::msgs; -use ln::msgs::{ErrorAction, HandleError, MsgEncodable}; +use ln::msgs::{ErrorAction, HandleError}; use ln::channelmonitor::ChannelMonitor; use ln::channelmanager::{PendingHTLCStatus, HTLCSource, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg}; use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; @@ -22,6 +22,7 @@ use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; use util::{transaction_utils,rng}; +use util::ser::Writeable; use util::sha2::Sha256; use util::logger::Logger; use util::errors::APIError; @@ -203,6 +204,13 @@ enum HTLCUpdateAwaitingACK { }, } +/// There are a few "states" and then a number of flags which can be applied: +/// We first move through init with OurInitSent -> TheirInitSent -> FundingCreated -> FundingSent. +/// TheirFundingLocked and OurFundingLocked then get set on FundingSent, and when both are set we +/// move on to ChannelFunded. +/// Note that PeerDisconnected can be set on both ChannelFunded and FundingSent. +/// ChannelFunded can then get all remaining flags set on it, until we finish shutdown, then we +/// move on to ShutdownComplete, at which point most calls into this channel are disallowed. enum ChannelState { /// Implies we have (or are prepared to) send our open_channel/accept_channel message OurInitSent = (1 << 0), @@ -223,33 +231,39 @@ enum ChannelState { /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded. OurFundingLocked = (1 << 5), ChannelFunded = 64, + /// Flag which is set on ChannelFunded and FundingSent indicating remote side is considered + /// "disconnected" and no updates are allowed until after we've done a channel_reestablish + /// dance. + PeerDisconnected = (1 << 7), /// Flag which implies that we have sent a commitment_signed but are awaiting the responding /// revoke_and_ack message. During this time period, we can't generate new commitment_signed /// messages as then we will be unable to determine which HTLCs they included in their /// revoke_and_ack implicit ACK, so instead we have to hold them away temporarily to be sent /// later. /// Flag is set on ChannelFunded. - AwaitingRemoteRevoke = (1 << 7), + AwaitingRemoteRevoke = (1 << 8), /// Flag which is set on ChannelFunded or FundingSent after receiving a shutdown message from /// the remote end. If set, they may not add any new HTLCs to the channel, and we are expected /// to respond with our own shutdown message when possible. - RemoteShutdownSent = (1 << 8), + RemoteShutdownSent = (1 << 9), /// Flag which is set on ChannelFunded or FundingSent after sending a shutdown message. At this /// point, we may not add any new HTLCs to the channel. /// TODO: Investigate some kind of timeout mechanism by which point the remote end must provide /// us their shutdown. - LocalShutdownSent = (1 << 9), + LocalShutdownSent = (1 << 10), /// We've successfully negotiated a closing_signed dance. At this point ChannelManager is about /// to drop us, but we store this anyway. - ShutdownComplete = (1 << 10), + ShutdownComplete = 2048, } const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32); +const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; + // TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking // has been completed, and then turn into a Channel to get compiler-time enforcement of things like // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. -pub struct Channel { +pub(super) struct Channel { user_id: u64, channel_id: [u8; 32], @@ -271,6 +285,24 @@ pub struct Channel { pending_inbound_htlcs: Vec, pending_outbound_htlcs: Vec, holding_cell_htlc_updates: Vec, + + // pending_update_fee is filled when sending and receiving update_fee + // For outbound channel, feerate_per_kw is updated with the value from + // pending_update_fee when revoke_and_ack is received + // + // For inbound channel, feerate_per_kw is updated when it receives + // commitment_signed and revoke_and_ack is generated + // The pending value is kept when another pair of update_fee and commitment_signed + // is received during AwaitingRemoteRevoke and relieved when the expected + // revoke_and_ack is received and new commitment_signed is generated to be + // sent to the funder. Otherwise, the pending value is removed when receiving + // commitment_signed. + pending_update_fee: Option, + // update_fee() during ChannelState::AwaitingRemoteRevoke is hold in + // holdina_cell_update_fee then moved to pending_udpate_fee when revoke_and_ack + // is received. holding_cell_update_fee is updated when there are additional + // update_fee() during ChannelState::AwaitingRemoteRevoke. + holding_cell_update_fee: Option, next_local_htlc_id: u64, next_remote_htlc_id: u64, channel_update_count: u32, @@ -425,12 +457,14 @@ impl Channel { channel_value_satoshis: channel_value_satoshis, local_keys: chan_keys, - cur_local_commitment_transaction_number: (1 << 48) - 1, - cur_remote_commitment_transaction_number: (1 << 48) - 1, + cur_local_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, + cur_remote_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat: channel_value_satoshis * 1000 - push_msat, pending_inbound_htlcs: Vec::new(), pending_outbound_htlcs: Vec::new(), holding_cell_htlc_updates: Vec::new(), + pending_update_fee: None, + holding_cell_update_fee: None, next_local_htlc_id: 0, next_remote_htlc_id: 0, channel_update_count: 1, @@ -583,12 +617,14 @@ impl Channel { announce_publicly: their_announce, local_keys: chan_keys, - cur_local_commitment_transaction_number: (1 << 48) - 1, - cur_remote_commitment_transaction_number: (1 << 48) - 1, + cur_local_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, + cur_remote_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat: msg.push_msat, pending_inbound_htlcs: Vec::new(), pending_outbound_htlcs: Vec::new(), holding_cell_htlc_updates: Vec::new(), + pending_update_fee: None, + holding_cell_update_fee: None, next_local_htlc_id: 0, next_remote_htlc_id: 0, channel_update_count: 1, @@ -681,8 +717,8 @@ impl Channel { /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both /// which peer generated this transaction and "to whom" this transaction flows. #[inline] - fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool) -> (Transaction, Vec) { - let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (0xffffffffffff - commitment_number); + fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec) { + let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number); let txins = { let mut ins: Vec = Vec::new(); @@ -705,7 +741,7 @@ impl Channel { macro_rules! add_htlc_output { ($htlc: expr, $outbound: expr) => { if $outbound == local { // "offered HTLC output" - if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) { + if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) { let htlc_in_tx = get_htlc_in_commitment!($htlc, true); txouts.push((TxOut { script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(), @@ -713,7 +749,7 @@ impl Channel { }, Some(htlc_in_tx))); } } else { - if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) { + if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) { let htlc_in_tx = get_htlc_in_commitment!($htlc, false); txouts.push((TxOut { // "received HTLC output" script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(), @@ -777,7 +813,8 @@ impl Channel { } } - let total_fee: u64 = self.feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; + + let total_fee: u64 = feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000; let value_to_self: i64 = ((self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset) / 1000 - if self.channel_outbound { total_fee as i64 } else { 0 }; let value_to_remote: i64 = (((self.channel_value_satoshis * 1000 - self.value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset) / 1000) - if self.channel_outbound { 0 } else { total_fee as i64 }; @@ -969,8 +1006,8 @@ impl Channel { /// 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. - fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys) -> Transaction { - chan_utils::build_htlc_transaction(prev_hash, self.feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key) + fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u64) -> Transaction { + chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key) } fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), HandleError> { @@ -1021,6 +1058,8 @@ impl Channel { Ok(our_sig) } + /// May return an IgnoreError, but should not, and will always return Ok(_) when + /// debug_assertions are turned on 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 @@ -1040,14 +1079,17 @@ impl Channel { for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { if htlc.htlc_id == htlc_id_arg { assert_eq!(htlc.payment_hash, payment_hash_calc); - if htlc.state != InboundHTLCState::LocalRemoved { - pending_idx = idx; - break; + if htlc.state != InboundHTLCState::Committed { + debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); + // Don't return in release mode here so that we can update channel_monitor } + pending_idx = idx; + break; } } if pending_idx == std::usize::MAX { - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: None}); + debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); + return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)}); } // Now update local state: @@ -1056,17 +1098,19 @@ impl Channel { // can claim it even if the channel hits the chain before we see their next commitment. self.channel_monitor.provide_payment_preimage(&payment_hash_calc, &payment_preimage_arg); - if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) { + if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32)) != 0 { for pending_update in self.holding_cell_htlc_updates.iter() { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { + debug_assert!(false, "Tried to fulfill an HTLC we already had a pending fulfill for"); return Ok((None, None)); } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: None}); + 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)}); } }, _ => {} @@ -1080,21 +1124,12 @@ impl Channel { { let htlc = &mut self.pending_inbound_htlcs[pending_idx]; - if htlc.state == InboundHTLCState::Committed { - htlc.state = InboundHTLCState::LocalRemoved; - htlc.local_removed_fulfilled = true; - } else if htlc.state == InboundHTLCState::RemoteAnnounced || htlc.state == InboundHTLCState::AwaitingRemoteRevokeToAnnounce || htlc.state == InboundHTLCState::AwaitingAnnouncedRemoteRevoke { - // Theoretically we can hit this if we get the preimage on an HTLC prior to us - // having forwarded it to anyone. This implies that the sender is busted as someone - // else knows the preimage, but handling this case and implementing the logic to - // take their money would be a lot of (never-tested) code to handle a case that - // hopefully never happens. Instead, we make sure we get the preimage into the - // channel_monitor and pretend we didn't just see the preimage. + if htlc.state != InboundHTLCState::Committed { + debug_assert!(false, "Have an inbound HTLC we tried to claim before it was fully committed to"); return Ok((None, Some(self.channel_monitor.clone()))); - } else { - // LocalRemoved handled in the search loop - panic!("Have an inbound HTLC when not awaiting remote revoke that had a garbage state"); } + htlc.state = InboundHTLCState::LocalRemoved; + htlc.local_removed_fulfilled = true; } Ok((Some(msgs::UpdateFulfillHTLC { @@ -1115,23 +1150,42 @@ impl Channel { } } + /// May return an IgnoreError, but should not, and will always return Ok(_) when + /// debug_assertions are turned on 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"); } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); + let mut pending_idx = std::usize::MAX; + for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() { + if htlc.htlc_id == htlc_id_arg { + if htlc.state != InboundHTLCState::Committed { + debug_assert!(false, "Have an inbound HTLC we tried to fail before it was fully committed to"); + return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)}); + } + pending_idx = idx; + } + } + if pending_idx == std::usize::MAX { + debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); + return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)}); + } + // Now update local state: - if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) { + if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32)) != 0 { for pending_update in self.holding_cell_htlc_updates.iter() { match pending_update { &HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: None}); + debug_assert!(false, "Unable to find a pending HTLC which matched the given HTLC ID"); + return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: Some(msgs::ErrorAction::IgnoreError)}); } }, &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, .. } => { if htlc_id_arg == htlc_id { + debug_assert!(false, "Tried to fail an HTLC that we already had a pending failure for"); return Ok(None); } }, @@ -1145,23 +1199,10 @@ impl Channel { return Ok(None); } - let mut htlc_amount_msat = 0; - for htlc in self.pending_inbound_htlcs.iter_mut() { - if htlc.htlc_id == htlc_id_arg { - if htlc.state == InboundHTLCState::Committed { - htlc.state = InboundHTLCState::LocalRemoved; - } else if htlc.state == InboundHTLCState::RemoteAnnounced { - panic!("Somehow forwarded HTLC prior to remote revocation!"); - } else if htlc.state == InboundHTLCState::LocalRemoved { - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: None}); - } else { - panic!("Have an inbound HTLC when not awaiting remote revoke that had a garbage state"); - } - htlc_amount_msat += htlc.amount_msat; - } - } - if htlc_amount_msat == 0 { - return Err(HandleError{err: "Unable to find a pending HTLC which matched the given HTLC ID", action: None}); + { + let htlc = &mut self.pending_inbound_htlcs[pending_idx]; + htlc.state = InboundHTLCState::LocalRemoved; + htlc.local_removed_fulfilled = false; } Ok(Some(msgs::UpdateFailHTLC { @@ -1264,14 +1305,14 @@ impl Channel { 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).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 = 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. secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer", self.channel_id()); 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).0; + 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. @@ -1288,7 +1329,9 @@ impl Channel { // channel. return Err(HandleError{err: "Received funding_created after we got the channel!", action: Some(msgs::ErrorAction::SendErrorMessage {msg: msgs::ErrorMessage {channel_id: self.channel_id, data: "Received funding_created after we got the channel!".to_string()}})}); } - if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 { + if self.channel_monitor.get_min_seen_secret() != (1 << 48) || + self.cur_remote_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || + self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } @@ -1327,14 +1370,16 @@ impl Channel { if self.channel_state != ChannelState::FundingCreated as u32 { return Err(HandleError{err: "Received funding_signed in strange state!", action: None}); } - if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 2 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 { + if self.channel_monitor.get_min_seen_secret() != (1 << 48) || + self.cur_remote_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER - 1 || + self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } 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).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. @@ -1350,12 +1395,24 @@ impl Channel { } pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), HandleError> { + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent funding_locked when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent funding_locked when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK); if non_shutdown_state == ChannelState::FundingSent as u32 { self.channel_state |= ChannelState::TheirFundingLocked as u32; } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) { self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK); self.channel_update_count += 1; + } else if self.channel_state & (ChannelState::ChannelFunded as u32) != 0 && + // Note that funding_signed/funding_created will have decremented both by 1! + self.cur_local_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 && + self.cur_remote_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { + if self.their_cur_commitment_point != Some(msg.next_per_commitment_point) { + return Err(HandleError{err: "Peer sent a reconnect funding_locked with a different point", action: None}); + } + // They probably disconnected/reconnected and re-sent the funding_locked, which is required + return Ok(()); } else { return Err(HandleError{err: "Peer sent a funding_locked at a strange time", action: None}); } @@ -1407,6 +1464,9 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent update_add_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_add_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } if msg.amount_msat > self.channel_value_satoshis * 1000 { return Err(HandleError{err: "Remote side tried to send more than the total value of the channel", action: None}); } @@ -1485,6 +1545,9 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent update_fulfill_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fulfill_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } let mut sha = Sha256::new(); sha.input(&msg.payment_preimage); @@ -1498,6 +1561,9 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent update_fail_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fail_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason)) } @@ -1506,6 +1572,9 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent update_fail_malformed_htlc when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fail_malformed_htlc when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } self.mark_outbound_htlc_removed(msg.htlc_id, None, Some(fail_reason)) } @@ -1514,11 +1583,21 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent commitment_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent commitment_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } let funding_script = self.get_funding_redeemscript(); let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?; - let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false); + + let feerate_per_kw = if !self.channel_outbound && self.pending_update_fee.is_some() { + self.pending_update_fee.unwrap() + } else { + self.feerate_per_kw + }; + + let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw); let local_commitment_txid = local_commitment_tx.0.txid(); 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()); @@ -1533,7 +1612,7 @@ impl Channel { let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len()); for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() { - let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys); + 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()); @@ -1551,9 +1630,22 @@ impl Channel { let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1); // Update state now that we've passed all the can-fail calls... + let mut need_our_commitment = false; + if !self.channel_outbound { + if let Some(fee_update) = self.pending_update_fee { + self.feerate_per_kw = fee_update; + // We later use the presence of pending_update_fee to indicate we should generate a + // commitment_signed upon receipt of revoke_and_ack, so we can only set it to None + // if we're not awaiting a revoke (ie will send a commitment_signed now). + if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) == 0 { + need_our_commitment = true; + self.pending_update_fee = None; + } + } + } + self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs); - let mut need_our_commitment = false; for htlc in self.pending_inbound_htlcs.iter_mut() { if htlc.state == InboundHTLCState::RemoteAnnounced { htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce; @@ -1588,7 +1680,7 @@ impl Channel { /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them /// fulfilling or failing the last pending HTLC) fn free_holding_cell_htlcs(&mut self) -> Result, HandleError> { - if self.holding_cell_htlc_updates.len() != 0 { + if self.holding_cell_htlc_updates.len() != 0 || self.holding_cell_update_fee.is_some() { let mut htlc_updates = Vec::new(); mem::swap(&mut htlc_updates, &mut self.holding_cell_htlc_updates); let mut update_add_htlcs = Vec::with_capacity(htlc_updates.len()); @@ -1617,7 +1709,10 @@ impl Channel { match self.get_update_fulfill_htlc(htlc_id, payment_preimage) { Ok(update_fulfill_msg_option) => update_fulfill_htlcs.push(update_fulfill_msg_option.0.unwrap()), Err(e) => { - err = Some(e); + if let Some(msgs::ErrorAction::IgnoreError) = e.action {} + else { + panic!("Got a non-IgnoreError action trying to fulfill holding cell HTLC"); + } } } }, @@ -1625,7 +1720,10 @@ impl Channel { match self.get_update_fail_htlc(htlc_id, err_packet.clone()) { Ok(update_fail_msg_option) => update_fail_htlcs.push(update_fail_msg_option.unwrap()), Err(e) => { - err = Some(e); + if let Some(msgs::ErrorAction::IgnoreError) = e.action {} + else { + panic!("Got a non-IgnoreError action trying to fail holding cell HTLC"); + } } } }, @@ -1639,12 +1737,28 @@ impl Channel { //fail it back the route, if its a temporary issue we can ignore it... match err { None => { + if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() && self.holding_cell_update_fee.is_none() { + // This should never actually happen and indicates we got some Errs back + // from update_fulfill_htlc/update_fail_htlc, but we handle it anyway in + // case there is some strange way to hit duplicate HTLC removes. + return Ok(None); + } + let update_fee = if let Some(feerate) = self.holding_cell_update_fee { + self.pending_update_fee = self.holding_cell_update_fee.take(); + Some(msgs::UpdateFee { + channel_id: self.channel_id, + feerate_per_kw: feerate as u32, + }) + } else { + None + }; let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?; Ok(Some((msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs: Vec::new(), + update_fee: update_fee, commitment_signed, }, monitor_update))) }, @@ -1664,6 +1778,9 @@ impl Channel { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent revoke_and_ack when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent revoke_and_ack when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } if let Some(their_prev_commitment_point) = self.their_prev_commitment_point { if PublicKey::from_secret_key(&self.secp_ctx, &secp_call!(SecretKey::from_slice(&self.secp_ctx, &msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret", self.channel_id())) != their_prev_commitment_point { return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", action: None}); @@ -1737,6 +1854,24 @@ impl Channel { } self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64; + if self.channel_outbound { + if let Some(feerate) = self.pending_update_fee.take() { + self.feerate_per_kw = feerate; + } + } else { + if let Some(feerate) = self.pending_update_fee { + // Because a node cannot send two commitment_signed's in a row without getting a + // revoke_and_ack from us (as it would otherwise not know the per_commitment_point + // it should use to create keys with) and because a node can't send a + // commitment_signed without changes, checking if the feerate is equal to the + // pending feerate update is sufficient to detect require_commitment. + if feerate == self.feerate_per_kw { + require_commitment = true; + self.pending_update_fee = None; + } + } + } + match self.free_holding_cell_htlcs()? { Some(mut commitment_update) => { commitment_update.0.update_fail_htlcs.reserve(update_fail_htlcs.len()); @@ -1757,6 +1892,7 @@ impl Channel { update_fulfill_htlcs: Vec::new(), update_fail_htlcs, update_fail_malformed_htlcs, + update_fee: None, commitment_signed }), to_forward_infos, revoked_htlcs, monitor_update)) } else { @@ -1764,19 +1900,209 @@ impl Channel { } } } + + } + + /// Adds a pending update to this channel. See the doc for send_htlc for + /// further details on the optionness of the return value. + /// You MUST call send_commitment prior to any other calls on this Channel + fn send_update_fee(&mut self, feerate_per_kw: u64) -> Option { + if !self.channel_outbound { + panic!("Cannot send fee from inbound channel"); + } + + if !self.is_usable() { + panic!("Cannot update fee until channel is fully established and we haven't started shutting down"); + } + + if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) { + self.holding_cell_update_fee = Some(feerate_per_kw); + return None; + } + + debug_assert!(self.pending_update_fee.is_none()); + self.pending_update_fee = Some(feerate_per_kw); + + Some(msgs::UpdateFee { + channel_id: self.channel_id, + feerate_per_kw: feerate_per_kw as u32, + }) + } + + pub fn send_update_fee_and_commit(&mut self, feerate_per_kw: u64) -> Result, HandleError> { + match self.send_update_fee(feerate_per_kw) { + Some(update_fee) => { + let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?; + Ok(Some((update_fee, commitment_signed, monitor_update))) + }, + None => Ok(None) + } + } + + /// Removes any uncommitted HTLCs, to be used on peer disconnection, including any pending + /// HTLCs that we intended to add but haven't as we were waiting on a remote revoke. + /// Returns the set of PendingHTLCStatuses from remote uncommitted HTLCs (which we're + /// implicitly dropping) and the payment_hashes of HTLCs we tried to add but are dropping. + /// No further message handling calls may be made until a channel_reestablish dance has + /// completed. + pub fn remove_uncommitted_htlcs_and_mark_paused(&mut self) -> Vec<(HTLCSource, [u8; 32])> { + let mut outbound_drops = Vec::new(); + + assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); + if self.channel_state < ChannelState::FundingSent as u32 { + self.channel_state = ChannelState::ShutdownComplete as u32; + return outbound_drops; + } + + let mut inbound_drop_count = 0; + self.pending_inbound_htlcs.retain(|htlc| { + match htlc.state { + InboundHTLCState::RemoteAnnounced => { + // They sent us an update_add_htlc but we never got the commitment_signed. + // We'll tell them what commitment_signed we're expecting next and they'll drop + // this HTLC accordingly + inbound_drop_count += 1; + false + }, + InboundHTLCState::AwaitingRemoteRevokeToAnnounce|InboundHTLCState::AwaitingAnnouncedRemoteRevoke => { + // Same goes for AwaitingRemoteRevokeToRemove and AwaitingRemovedRemoteRevoke + // We received a commitment_signed updating this HTLC and (at least hopefully) + // sent a revoke_and_ack (which we can re-transmit) and have heard nothing + // in response to it yet, so don't touch it. + true + }, + InboundHTLCState::Committed => true, + InboundHTLCState::LocalRemoved => { // Same goes for LocalAnnounced + // We (hopefully) sent a commitment_signed updating this HTLC (which we can + // re-transmit if needed) and they may have even sent a revoke_and_ack back + // (that we missed). Keep this around for now and if they tell us they missed + // the commitment_signed we can re-transmit the update then. + true + }, + } + }); + + for htlc in self.pending_outbound_htlcs.iter_mut() { + if htlc.state == OutboundHTLCState::RemoteRemoved { + // They sent us an update to remove this but haven't yet sent the corresponding + // commitment_signed, we need to move it back to Committed and they can re-send + // the update upon reconnection. + htlc.state = OutboundHTLCState::Committed; + } + } + + self.holding_cell_htlc_updates.retain(|htlc_update| { + match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, .. } => { + outbound_drops.push((source.clone(), payment_hash.clone())); + false + }, + &HTLCUpdateAwaitingACK::ClaimHTLC {..} | &HTLCUpdateAwaitingACK::FailHTLC {..} => true, + } + }); + self.channel_state |= ChannelState::PeerDisconnected as u32; + log_debug!(self, "Peer disconnection resulted in {} remote-announced HTLC drops and {} waiting-to-locally-announced HTLC drops on channel {}", outbound_drops.len(), inbound_drop_count, log_bytes!(self.channel_id())); + outbound_drops } pub fn update_fee(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::UpdateFee) -> Result<(), HandleError> { if self.channel_outbound { return Err(HandleError{err: "Non-funding remote tried to update channel fee", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent update_fee when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fee when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } 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; - self.feerate_per_kw = msg.feerate_per_kw as u64; Ok(()) } + /// May panic if some calls other than message-handling calls (which will all Err immediately) + /// have been called between remove_uncommitted_htlcs_and_mark_paused and this call. + pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option, Option, Option, Option), HandleError> { + if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 { + return Err(HandleError{err: "Peer sent a loose channel_reestablish not after reconnect", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent a loose channel_reestablish not after reconnect".to_string(), channel_id: msg.channel_id}})}); + } + + if msg.next_local_commitment_number == 0 || msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || + msg.next_remote_commitment_number == 0 || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER { + return Err(HandleError{err: "Peer send garbage channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer send garbage channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } + + // 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); + + let mut required_revoke = None; + if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { + // Remote isn't waiting on any RevokeAndACK from us! + // Note that if we need to repeat our FundingLocked we'll do that in the next if block. + } else if msg.next_remote_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_local_commitment_transaction_number { + let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number)); + let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 2); + required_revoke = Some(msgs::RevokeAndACK { + channel_id: self.channel_id, + per_commitment_secret, + next_per_commitment_point, + }); + } else { + return Err(HandleError{err: "Peer attempted to reestablish channel with a very old local commitment transaction", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer attempted to reestablish channel with a very old remote commitment transaction".to_string(), channel_id: msg.channel_id}})}); + } + + if msg.next_local_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number { + if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number { + log_debug!(self, "Reconnected channel {} with no lost commitment txn", log_bytes!(self.channel_id())); + if msg.next_local_commitment_number == 1 && msg.next_remote_commitment_number == 1 { + let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); + let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret); + return Ok((Some(msgs::FundingLocked { + channel_id: self.channel_id(), + next_per_commitment_point: next_per_commitment_point, + }), None, None, None)); + } + } + + if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 { + // We're up-to-date and not waiting on a remote revoke (if we are our + // channel_reestablish should result in them sending a revoke_and_ack), but we may + // have received some updates while we were disconnected. Free the holding cell + // now! + match self.free_holding_cell_htlcs() { + Err(e) => { + if let &Some(msgs::ErrorAction::DisconnectPeer{msg: Some(_)}) = &e.action { + } else if let &Some(msgs::ErrorAction::SendErrorMessage{msg: _}) = &e.action { + } else { + panic!("Got non-channel-failing result from free_holding_cell_htlcs"); + } + return Err(e); + }, + Ok(Some((commitment_update, channel_monitor))) => return Ok((None, required_revoke, Some(commitment_update), Some(channel_monitor))), + Ok(None) => return Ok((None, required_revoke, None, None)), + } + } else { + return Ok((None, required_revoke, None, None)); + } + } else if msg.next_local_commitment_number == (INITIAL_COMMITMENT_NUMBER - 1) - self.cur_remote_commitment_transaction_number { + return Ok((None, required_revoke, + Some(msgs::CommitmentUpdate { + update_add_htlcs: Vec::new(), + update_fulfill_htlcs: Vec::new(), + update_fail_htlcs: Vec::new(), + update_fail_malformed_htlcs: Vec::new(), + update_fee: None, + commitment_signed: self.send_commitment_no_state_update().expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0, + }), None)); + } else { + return Err(HandleError{err: "Peer attempted to reestablish channel with a very old remote commitment transaction", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer attempted to reestablish channel with a very old remote commitment transaction".to_string(), channel_id: msg.channel_id}})}); + } + } + pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option, Option, Vec<(HTLCSource, [u8; 32])>), HandleError> { + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent shutdown when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent shutdown when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } if self.channel_state < ChannelState::FundingSent as u32 { self.channel_state = ChannelState::ShutdownComplete as u32; self.channel_update_count += 1; @@ -1797,7 +2123,12 @@ impl Channel { if self.channel_outbound && msg.scriptpubkey.len() > 34 { return Err(HandleError{err: "Got shutdown_scriptpubkey of absurd length from remote peer", action: None}); } - //TODO: Check shutdown_scriptpubkey form as BOLT says we must? WHYYY + + //Check shutdown_scriptpubkey form as BOLT says we must + if !(msg.scriptpubkey.is_p2pkh()) && !(msg.scriptpubkey.is_p2sh()) + && !(msg.scriptpubkey.is_v0_p2wpkh()) && !(msg.scriptpubkey.is_v0_p2wsh()){ + return Err(HandleError{err: "Got an invalid scriptpubkey from remote peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}); + } if self.their_shutdown_scriptpubkey.is_some() { if Some(&msg.scriptpubkey) != self.their_shutdown_scriptpubkey.as_ref() { @@ -1877,10 +2208,13 @@ impl Channel { if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK { return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None}); } + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Peer sent closing_signed when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent closing_signed when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})}); + } if !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() { return Err(HandleError{err: "Remote end sent us a closing_signed while there were still pending HTLCs", action: None}); } - if msg.fee_satoshis > 21000000 * 10000000 { + if msg.fee_satoshis > 21000000 * 10000000 { //this is required to stop potential overflow in build_closing_transaction return Err(HandleError{err: "Remote tried to send us a closing tx with > 21 million BTC fee", action: None}); } @@ -2007,6 +2341,11 @@ impl Channel { self.channel_value_satoshis } + #[cfg(test)] + pub fn get_feerate(&self) -> u64 { + self.feerate_per_kw + } + //TODO: Testing purpose only, should be changed in another way after #81 #[cfg(test)] pub fn get_local_keys(&self) -> &ChannelKeys { @@ -2022,6 +2361,10 @@ impl Channel { self.announce_publicly } + pub fn is_outbound(&self) -> bool { + self.channel_outbound + } + /// Gets the fee we'd want to charge for adding an HTLC output to this Channel /// Allowed in any state (including after shutdown) pub fn get_our_fee_base_msat(&self, fee_estimator: &FeeEstimator) -> u32 { @@ -2042,6 +2385,11 @@ impl Channel { res as u32 } + /// Returns true if we've ever received a message from the remote end for this Channel + pub fn have_received_message(&self) -> bool { + self.channel_state > (ChannelState::OurInitSent as u32) + } + /// Returns true if this channel is fully established and not known to be closing. /// Allowed in any state (including after shutdown) pub fn is_usable(&self) -> bool { @@ -2053,7 +2401,7 @@ impl Channel { /// is_usable() and considers things like the channel being temporarily disabled. /// Allowed in any state (including after shutdown) pub fn is_live(&self) -> bool { - self.is_usable() + self.is_usable() && (self.channel_state & (ChannelState::PeerDisconnected as u32) == 0) } /// Returns true if funding_created was sent/received. @@ -2168,7 +2516,7 @@ impl Channel { // Methods to get unprompted messages to send to the remote end (or where we already returned // something in the handler for the message that prompted this message): - pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result { + pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> msgs::OpenChannel { if !self.channel_outbound { panic!("Tried to open a channel for an inbound channel?"); } @@ -2176,13 +2524,13 @@ impl Channel { panic!("Cannot generate an open_channel after we've moved forward"); } - if self.cur_local_commitment_transaction_number != (1 << 48) - 1 { + if self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Tried to send an open_channel for a channel that has already advanced"); } let local_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); - Ok(msgs::OpenChannel { + msgs::OpenChannel { chain_hash: chain_hash, temporary_channel_id: self.channel_id, funding_satoshis: self.channel_value_satoshis, @@ -2202,7 +2550,7 @@ impl Channel { first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), channel_flags: if self.announce_publicly {1} else {0}, shutdown_scriptpubkey: None, - }) + } } pub fn get_accept_channel(&self) -> msgs::AcceptChannel { @@ -2212,7 +2560,7 @@ impl Channel { if self.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) { panic!("Tried to send accept_channel after channel had moved forward"); } - if self.cur_local_commitment_transaction_number != (1 << 48) - 1 { + if self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Tried to send an accept_channel for a channel that has already advanced"); } @@ -2241,7 +2589,7 @@ impl Channel { 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).0; + 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. @@ -2261,7 +2609,9 @@ impl Channel { if self.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) { panic!("Tried to get a funding_created messsage at a time other than immediately after initial handshake completion (or tried to get funding_created twice)"); } - if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 { + if self.channel_monitor.get_min_seen_secret() != (1 << 48) || + self.cur_remote_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || + self.cur_local_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } @@ -2332,6 +2682,18 @@ impl Channel { Ok((msg, sig)) } + /// May panic if called on a channel that wasn't immediately-previously + /// self.remove_uncommitted_htlcs_and_mark_paused()'d + pub fn get_channel_reestablish(&self) -> msgs::ChannelReestablish { + assert_eq!(self.channel_state & ChannelState::PeerDisconnected as u32, ChannelState::PeerDisconnected as u32); + msgs::ChannelReestablish { + channel_id: self.channel_id(), + next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number, + next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_remote_commitment_transaction_number, + data_loss_protect: None, + } + } + // Send stuff to our remote peers: @@ -2353,6 +2715,16 @@ impl Channel { return Err(HandleError{err: "Cannot send less than their minimum HTLC value", action: None}); } + if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) { + // Note that this should never really happen, if we're !is_live() on receipt of an + // incoming HTLC for relay will result in us rejecting the HTLC and we won't allow + // the user to send directly into a !is_live() channel. However, if we + // disconnected during the time the previous hop was doing the commitment dance we may + // end up getting here after the forwarding delay. In any case, returning an + // IgnoreError will get ChannelManager to do the right thing and fail backwards now. + return Err(HandleError{err: "Cannot send an HTLC while disconnected", action: Some(ErrorAction::IgnoreError)}); + } + let (_, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats(false); if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 { return Err(HandleError{err: "Cannot push more than their max accepted HTLCs", action: None}); @@ -2417,7 +2789,10 @@ impl Channel { if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) { panic!("Cannot create commitment tx until remote revokes their previous commitment"); } - let mut have_updates = false; // TODO initialize with "have we sent a fee update?" + if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) { + panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated"); + } + let mut have_updates = self.pending_update_fee.is_some(); for htlc in self.pending_outbound_htlcs.iter() { if htlc.state == OutboundHTLCState::LocalAnnounced { have_updates = true; @@ -2431,8 +2806,6 @@ impl Channel { } /// Only fails in case of bad keys fn send_commitment_no_status_check(&mut self) -> Result<(msgs::CommitmentSigned, ChannelMonitor), HandleError> { - let funding_script = self.get_funding_redeemscript(); - // We can upgrade the status of some HTLCs that are waiting on a commitment, even if we // fail to generate this, we still are at least at a position where upgrading their status // is acceptable. @@ -2447,8 +2820,31 @@ impl Channel { } } + match self.send_commitment_no_state_update() { + Ok((res, remote_commitment_tx)) => { + // Update state now that we've passed all the can-fail calls... + self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, self.cur_remote_commitment_transaction_number); + self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32; + Ok((res, self.channel_monitor.clone())) + }, + Err(e) => Err(e), + } + } + + /// 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)), HandleError> { + 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 { + feerate_per_kw = feerate; + } + } + 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); + 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 = Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap(); let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key); @@ -2456,22 +2852,18 @@ impl Channel { let mut htlc_sigs = Vec::new(); for ref htlc in remote_commitment_tx.1.iter() { - let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys); + 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 = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap(); let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), self.channel_id()); htlc_sigs.push(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key)); } - // Update state now that we've passed all the can-fail calls... - self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1, self.cur_remote_commitment_transaction_number); - self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32; - Ok((msgs::CommitmentSigned { channel_id: self.channel_id, signature: our_sig, htlc_signatures: htlc_sigs, - }, self.channel_monitor.clone())) + }, remote_commitment_tx)) } /// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction @@ -2500,6 +2892,9 @@ impl Channel { return Err(HandleError{err: "Shutdown already in progress", action: None}); } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); + if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 { + return Err(HandleError{err: "Cannot begin shutdown while peer is disconnected, maybe force-close instead?", action: None}); + } let our_closing_script = self.get_closing_scriptpubkey(); @@ -2659,7 +3054,7 @@ mod tests { macro_rules! test_commitment { ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => { - unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false); + unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw); let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap(); let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap(); secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap(); @@ -2676,7 +3071,7 @@ mod tests { let remote_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap(); let ref htlc = unsigned_tx.1[$htlc_idx]; - let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys); + let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &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_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();