Only expose constants exposed for testing in cfg(test)
[rust-lightning] / lightning / src / ln / channel.rs
index c86136d6070a8f2c7909f8f3b39c743689ecd1f9..ff2a28b1fc374d3e527f18501fbb1db566242876 100644 (file)
@@ -240,7 +240,10 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
        secp_ctx: Secp256k1<secp256k1::All>,
        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
@@ -356,11 +359,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);
@@ -1995,6 +2005,17 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                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("Received an unexpected revoke_and_ack"));
+               }
+
                // 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
@@ -2973,49 +2994,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
        pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, msgs::ErrorMessage> {
                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();
-                       self.channel_monitor.last_block_hash = self.last_block_connected;
                        if self.funding_tx_confirmations > 0 {
                                self.funding_tx_confirmations += 1;
-                               if self.funding_tx_confirmations == self.minimum_depth as u64 {
-                                       let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 {
-                                               self.channel_state |= ChannelState::OurFundingLocked as u32;
-                                               true
-                                       } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
-                                               self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
-                                               self.channel_update_count += 1;
-                                               true
-                                       } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
-                                               // We got a reorg but not enough to trigger a force close, just update
-                                               // funding_tx_confirmed_in and return.
-                                               false
-                                       } else if self.channel_state < ChannelState::ChannelFunded as u32 {
-                                               panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state);
-                                       } else {
-                                               // We got a reorg but not enough to trigger a force close, just update
-                                               // funding_tx_confirmed_in and return.
-                                               false
-                                       };
-                                       self.funding_tx_confirmed_in = Some(header.bitcoin_hash());
-
-                                       //TODO: Note that this must be a duplicate of the previous commitment point they sent us,
-                                       //as otherwise we will have a commitment transaction that they can't revoke (well, kinda,
-                                       //they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
-                                       //a protocol oversight, but I assume I'm just missing something.
-                                       if need_commitment_update {
-                                               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 {
-                                                               channel_id: self.channel_id,
-                                                               next_per_commitment_point: next_per_commitment_point,
-                                                       }));
-                                               } else {
-                                                       self.monitor_pending_funding_locked = true;
-                                                       return Ok(None);
-                                               }
-                                       }
-                               }
                        }
                }
                if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
@@ -3058,6 +3038,51 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                                }
                        }
                }
+               if header.bitcoin_hash() != self.last_block_connected {
+                       self.last_block_connected = header.bitcoin_hash();
+                       self.channel_monitor.last_block_hash = self.last_block_connected;
+                       if self.funding_tx_confirmations > 0 {
+                               if self.funding_tx_confirmations == self.minimum_depth as u64 {
+                                       let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 {
+                                               self.channel_state |= ChannelState::OurFundingLocked as u32;
+                                               true
+                                       } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
+                                               self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
+                                               self.channel_update_count += 1;
+                                               true
+                                       } else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
+                                               // We got a reorg but not enough to trigger a force close, just update
+                                               // funding_tx_confirmed_in and return.
+                                               false
+                                       } else if self.channel_state < ChannelState::ChannelFunded as u32 {
+                                               panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state);
+                                       } else {
+                                               // We got a reorg but not enough to trigger a force close, just update
+                                               // funding_tx_confirmed_in and return.
+                                               false
+                                       };
+                                       self.funding_tx_confirmed_in = Some(header.bitcoin_hash());
+
+                                       //TODO: Note that this must be a duplicate of the previous commitment point they sent us,
+                                       //as otherwise we will have a commitment transaction that they can't revoke (well, kinda,
+                                       //they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
+                                       //a protocol oversight, but I assume I'm just missing something.
+                                       if need_commitment_update {
+                                               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 {
+                                                               channel_id: self.channel_id,
+                                                               next_per_commitment_point: next_per_commitment_point,
+                                                       }));
+                                               } else {
+                                                       self.monitor_pending_funding_locked = true;
+                                                       return Ok(None);
+                                               }
+                                       }
+                               }
+                       }
+               }
                Ok(None)
        }
 
@@ -3652,12 +3677,15 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
                }
                (self.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
                for htlc in self.pending_inbound_htlcs.iter() {
+                       if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
+                               continue; // Drop
+                       }
                        htlc.htlc_id.write(writer)?;
                        htlc.amount_msat.write(writer)?;
                        htlc.cltv_expiry.write(writer)?;
                        htlc.payment_hash.write(writer)?;
                        match &htlc.state {
-                               &InboundHTLCState::RemoteAnnounced(_) => {}, // Drop
+                               &InboundHTLCState::RemoteAnnounced(_) => unreachable!(),
                                &InboundHTLCState::AwaitingRemoteRevokeToAnnounce(ref htlc_state) => {
                                        1u8.write(writer)?;
                                        htlc_state.write(writer)?;