X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=d3767eb987f469e5e9bf2fe48c9325fd0a1f15a3;hb=6cee9dc9bc8c6e6d4f3bec2839c54d7bcbada44c;hp=164a128acfe1679bc335a35d33ca97b4e49beea1;hpb=db398438aba338f23d458813f756f801d2675c5f;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 164a128a..d3767eb9 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -19,7 +19,7 @@ use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; +use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; @@ -36,6 +36,9 @@ use std::default::Default; use std::{cmp,mem,fmt}; use std::sync::{Arc}; +#[cfg(all(test, feature = "mutation_testing"))] +use mutagen::mutate; + #[cfg(test)] pub struct ChannelValueStat { pub value_to_self_msat: u64, @@ -240,7 +243,10 @@ pub(super) struct Channel { secp_ctx: Secp256k1, channel_value_satoshis: u64, + #[cfg(not(test))] local_keys: ChanSigner, + #[cfg(test)] + pub(super) local_keys: ChanSigner, shutdown_pubkey: PublicKey, // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction @@ -266,7 +272,7 @@ pub(super) struct Channel { monitor_pending_funding_locked: bool, monitor_pending_revoke_and_ack: bool, monitor_pending_commitment_signed: bool, - monitor_pending_forwards: Vec<(PendingForwardHTLCInfo, u64)>, + monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>, monitor_pending_failures: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, // pending_update_fee is filled when sending and receiving update_fee @@ -356,11 +362,18 @@ pub const OUR_MAX_HTLCS: u16 = 50; //TODO /// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't /// really allow for this, so instead we're stuck closing it out at that point. const UNCONF_THRESHOLD: u32 = 6; -/// 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?) + +#[cfg(not(test))] +const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; +#[cfg(test)] +pub const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; +#[cfg(not(test))] +const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; +#[cfg(test)] +pub const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; + /// Maximmum `funding_satoshis` value, according to the BOLT #2 specification /// it's 2^24. pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24); @@ -1619,6 +1632,7 @@ impl Channel { let mut removed_outbound_total_msat = 0; for ref htlc in self.pending_outbound_htlcs.iter() { if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(None) = htlc.state { +debug_assert!(false, "This should be triggerable, and we should add a test case that does so!"); removed_outbound_total_msat += htlc.amount_msat; } else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(None) = htlc.state { removed_outbound_total_msat += htlc.amount_msat; @@ -1974,7 +1988,7 @@ impl Channel { /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail, /// generating an appropriate error *after* the channel state has been updated based on the /// revoke_and_ack message. - pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &FeeEstimator) -> Result<(Option, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option, ChannelMonitor), ChannelError> { + pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &FeeEstimator) -> Result<(Option, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option, ChannelMonitor), ChannelError> { if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) { return Err(ChannelError::Close("Got revoke/ACK message when channel was not in an operational state")); } @@ -1993,6 +2007,17 @@ impl Channel { self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret) .map_err(|e| ChannelError::Close(e.0))?; + if self.channel_state & ChannelState::AwaitingRemoteRevoke as u32 == 0 { + // Our counterparty seems to have burned their coins to us (by revoking a state when we + // haven't given them a new commitment transaction to broadcast). We should probably + // take advantage of this by updating our channel monitor, sending them an error, and + // waiting for them to broadcast their latest (now-revoked claim). But, that would be a + // lot of work, and there's some chance this is all a misunderstanding anyway. + // We have to do *something*, though, since our signer may get mad at us for otherwise + // jumping a remote commitment number, so best to just force-close and move on. + return Err(ChannelError::Close("Got a revoke when we weren't expecting one")); + } + // 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 // OK, we step the channel here and *then* if the new generation fails we can fail the @@ -2194,6 +2219,7 @@ impl Channel { } } + #[cfg_attr(all(test, feature = "mutation_testing"), mutate)] /// 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 @@ -2269,7 +2295,7 @@ impl Channel { /// which failed. The messages which were generated from that call which generated the /// monitor update failure must *not* have been sent to the remote end, and must instead /// have been dropped. They will be regenerated when monitor_updating_restored is called. - pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool, mut pending_forwards: Vec<(PendingForwardHTLCInfo, u64)>, mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>) { + pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>, mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>) { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, 0); self.monitor_pending_revoke_and_ack = resend_raa; self.monitor_pending_commitment_signed = resend_commitment; @@ -2280,10 +2306,11 @@ impl Channel { self.channel_state |= ChannelState::MonitorUpdateFailed as u32; } + #[cfg_attr(all(test, feature = "mutation_testing"), mutate)] /// Indicates that the latest ChannelMonitor update has been committed by the client /// successfully and we should restore normal operation. Returns messages which should be sent /// to the remote side. - pub fn monitor_updating_restored(&mut self) -> (Option, Option, RAACommitmentOrder, Vec<(PendingForwardHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, bool, Option) { + pub fn monitor_updating_restored(&mut self) -> (Option, Option, RAACommitmentOrder, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, bool, Option) { assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32); self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32); @@ -2348,6 +2375,7 @@ impl Channel { Ok(()) } + #[cfg_attr(all(test, feature = "mutation_testing"), mutate)] fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { 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); @@ -2964,12 +2992,24 @@ impl Channel { } /// Called by channelmanager based on chain blocks being connected. - /// Note that we only need to use this to detect funding_signed, anything else is handled by - /// the channel_monitor. + /// We need to use this to detect funding_signed and outgoing HTLC timed out before we were able + /// to commit them on remote commitment tx, anything else is handled by the channel_monitor. /// In case of Err, the channel may have been closed, at which point the standard requirements /// apply - no calls may be made except those explicitly stated to be allowed post-shutdown. /// Only returns an ErrorAction of DisconnectPeer, if Err. - pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result, msgs::ErrorMessage> { + pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<(Option, Vec<(HTLCSource, PaymentHash, u64)>), msgs::ErrorMessage> { + let mut timed_out_htlcs = Vec::new(); + self.holding_cell_htlc_updates.retain(|htlc_update| { + match htlc_update { + &HTLCUpdateAwaitingACK::AddHTLC { ref payment_hash, ref source, ref cltv_expiry, ref amount_msat, .. } => { + if cltv_expiry <= &height { // XXX follow 0a4821b + timed_out_htlcs.push((source.clone(), payment_hash.clone(), *amount_msat)); + false + } else { true } + }, + _ => true + } + }); let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS); if header.bitcoin_hash() != self.last_block_connected { self.last_block_connected = header.bitcoin_hash(); @@ -3005,13 +3045,13 @@ impl Channel { if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) == 0 { 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 { + return Ok((Some(msgs::FundingLocked { channel_id: self.channel_id, next_per_commitment_point: next_per_commitment_point, - })); + }), timed_out_htlcs)); } else { self.monitor_pending_funding_locked = true; - return Ok(None); + return Ok((None, timed_out_htlcs)); } } } @@ -3057,7 +3097,7 @@ impl Channel { } } } - Ok(None) + Ok((None, timed_out_htlcs)) } /// Called by channelmanager based on chain blocks being disconnected. @@ -4101,7 +4141,7 @@ mod tests { PublicKey::from_secret_key(&secp_ctx, &channel_close_key) } - fn get_channel_keys(&self, _inbound: bool, channel_value_satoshis: u64) -> InMemoryChannelKeys { + fn get_channel_keys(&self, _inbound: bool, _channel_value_satoshis: u64) -> InMemoryChannelKeys { self.chan_keys.clone() } fn get_onion_rand(&self) -> (SecretKey, [u8; 32]) { panic!(); }