Set basic channel info in chanmon all at once, add a bit more info
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index 154d8ccf70d29ccd641c85f9105b54b9783c707e..fef352ce4d4039a15633b496c68b4a31a3379248 100644 (file)
@@ -41,7 +41,7 @@ use util::logger::Logger;
 use util::ser::{ReadableArgs, Readable, Writer, Writeable, WriterWriteAdaptor, U48};
 use util::{byte_utils, events};
 
-use std::collections::{HashMap, hash_map};
+use std::collections::{HashMap, hash_map, HashSet};
 use std::sync::{Arc,Mutex};
 use std::{hash,cmp, mem};
 
@@ -513,7 +513,7 @@ enum OnchainEvent {
 
 /// Higher-level cache structure needed to re-generate bumped claim txn if needed
 #[derive(Clone, PartialEq)]
-struct ClaimTxBumpMaterial {
+pub struct ClaimTxBumpMaterial {
        // At every block tick, used to check if pending claiming tx is taking too
        // much time for confirmation and we need to bump it.
        height_timer: u32,
@@ -571,6 +571,8 @@ pub struct ChannelMonitor {
        key_storage: Storage,
        their_htlc_base_key: Option<PublicKey>,
        their_delayed_payment_base_key: Option<PublicKey>,
+       funding_redeemscript: Option<Script>,
+       channel_value_satoshis: Option<u64>,
        // first is the idx of the first of the two revocation points
        their_cur_revocation_points: Option<(u64, PublicKey, Option<PublicKey>)>,
 
@@ -621,6 +623,9 @@ pub struct ChannelMonitor {
        // Key is identifier of the pending claim request, i.e the txid of the initial claiming transaction generated by
        // us and is immutable until all outpoint of the claimable set are post-anti-reorg-delay solved.
        // Entry is cache of elements need to generate a bumped claiming transaction (see ClaimTxBumpMaterial)
+       #[cfg(test)] // Used in functional_test to verify sanitization
+       pub pending_claim_requests: HashMap<Sha256dHash, ClaimTxBumpMaterial>,
+       #[cfg(not(test))]
        pending_claim_requests: HashMap<Sha256dHash, ClaimTxBumpMaterial>,
 
        // Used to link outpoints claimed in a connected block to a pending claim request.
@@ -629,6 +634,9 @@ pub struct ChannelMonitor {
        // is txid of the initial claiming transaction and is immutable until outpoint is
        // post-anti-reorg-delay solved, confirmaiton_block is used to erase entry if
        // block with output gets disconnected.
+       #[cfg(test)] // Used in functional_test to verify sanitization
+       pub claimable_outpoints: HashMap<BitcoinOutPoint, (Sha256dHash, u32)>,
+       #[cfg(not(test))]
        claimable_outpoints: HashMap<BitcoinOutPoint, (Sha256dHash, u32)>,
 
        // Used to track onchain events, i.e transactions parts of channels confirmed on chain, on which
@@ -690,6 +698,8 @@ impl PartialEq for ChannelMonitor {
                        self.key_storage != other.key_storage ||
                        self.their_htlc_base_key != other.their_htlc_base_key ||
                        self.their_delayed_payment_base_key != other.their_delayed_payment_base_key ||
+                       self.funding_redeemscript != other.funding_redeemscript ||
+                       self.channel_value_satoshis != other.channel_value_satoshis ||
                        self.their_cur_revocation_points != other.their_cur_revocation_points ||
                        self.our_to_self_delay != other.our_to_self_delay ||
                        self.their_to_self_delay != other.their_to_self_delay ||
@@ -737,6 +747,8 @@ impl ChannelMonitor {
                        },
                        their_htlc_base_key: None,
                        their_delayed_payment_base_key: None,
+                       funding_redeemscript: None,
+                       channel_value_satoshis: None,
                        their_cur_revocation_points: None,
 
                        our_to_self_delay: our_to_self_delay,
@@ -1046,12 +1058,6 @@ impl ChannelMonitor {
                Ok(())
        }
 
-       /// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
-       pub(super) fn set_commitment_obscure_factor(&mut self, commitment_transaction_number_obscure_factor: u64) {
-               assert!(commitment_transaction_number_obscure_factor < (1 << 48));
-               self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
-       }
-
        /// Allows this monitor to scan only for transactions which are applicable. Note that this is
        /// optional, without it this monitor cannot be used in an SPV client, but you may wish to
        /// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
@@ -1070,13 +1076,15 @@ impl ChannelMonitor {
        }
 
        /// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
-       pub(super) fn set_their_base_keys(&mut self, their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey) {
+       /// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
+       pub(super) fn set_basic_channel_info(&mut self, their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey, their_to_self_delay: u16, funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64) {
                self.their_htlc_base_key = Some(their_htlc_base_key.clone());
                self.their_delayed_payment_base_key = Some(their_delayed_payment_base_key.clone());
-       }
-
-       pub(super) fn set_their_to_self_delay(&mut self, their_to_self_delay: u16) {
                self.their_to_self_delay = Some(their_to_self_delay);
+               self.funding_redeemscript = Some(funding_redeemscript);
+               self.channel_value_satoshis = Some(channel_value_satoshis);
+               assert!(commitment_transaction_number_obscure_factor < (1 << 48));
+               self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
        }
 
        pub(super) fn unset_funding_info(&mut self) {
@@ -1169,6 +1177,8 @@ impl ChannelMonitor {
 
                writer.write_all(&self.their_htlc_base_key.as_ref().unwrap().serialize())?;
                writer.write_all(&self.their_delayed_payment_base_key.as_ref().unwrap().serialize())?;
+               self.funding_redeemscript.as_ref().unwrap().write(writer)?;
+               self.channel_value_satoshis.unwrap().write(writer)?;
 
                match self.their_cur_revocation_points {
                        Some((idx, pubkey, second_option)) => {
@@ -2310,6 +2320,7 @@ impl ChannelMonitor {
        /// out-of-band the other node operator to coordinate with him if option is available to you.
        /// In any-case, choice is up to the user.
        pub fn get_latest_local_commitment_txn(&self) -> Vec<Transaction> {
+               log_trace!(self, "Getting signed latest local commitment transaction!");
                if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
                        let mut res = vec![local_tx.tx.clone()];
                        match self.key_storage {
@@ -2331,7 +2342,7 @@ impl ChannelMonitor {
                let mut watch_outputs = Vec::new();
                let mut spendable_outputs = Vec::new();
                let mut htlc_updated = Vec::new();
-               let mut bump_candidates = HashMap::new();
+               let mut bump_candidates = HashSet::new();
                for tx in txn_matched {
                        if tx.input.len() == 1 {
                                // Assuming our keys were not leaked (in which case we're screwed no matter what),
@@ -2397,9 +2408,9 @@ impl ChannelMonitor {
                        // Scan all input to verify is one of the outpoint spent is of interest for us
                        let mut claimed_outputs_material = Vec::new();
                        for inp in &tx.input {
-                               if let Some(ancestor_claimable_txid) = self.claimable_outpoints.get(&inp.previous_output) {
+                               if let Some(first_claim_txid_height) = self.claimable_outpoints.get(&inp.previous_output) {
                                        // If outpoint has claim request pending on it...
-                                       if let Some(claim_material) = self.pending_claim_requests.get_mut(&ancestor_claimable_txid.0) {
+                                       if let Some(claim_material) = self.pending_claim_requests.get_mut(&first_claim_txid_height.0) {
                                                //... we need to verify equality between transaction outpoints and claim request
                                                // outpoints to know if transaction is the original claim or a bumped one issued
                                                // by us.
@@ -2416,7 +2427,7 @@ impl ChannelMonitor {
 
                                                macro_rules! clean_claim_request_after_safety_delay {
                                                        () => {
-                                                               let new_event = OnchainEvent::Claim { claim_request: ancestor_claimable_txid.0.clone() };
+                                                               let new_event = OnchainEvent::Claim { claim_request: first_claim_txid_height.0.clone() };
                                                                match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
                                                                        hash_map::Entry::Occupied(mut entry) => {
                                                                                if !entry.get().contains(&new_event) {
@@ -2446,7 +2457,7 @@ impl ChannelMonitor {
                                                                }
                                                        }
                                                        //TODO: recompute soonest_timelock to avoid wasting a bit on fees
-                                                       bump_candidates.insert(ancestor_claimable_txid.0.clone(), claim_material.clone());
+                                                       bump_candidates.insert(first_claim_txid_height.0.clone());
                                                }
                                                break; //No need to iterate further, either tx is our or their
                                        } else {
@@ -2520,23 +2531,26 @@ impl ChannelMonitor {
                                }
                        }
                }
-               for (ancestor_claim_txid, ref mut cached_claim_datas) in self.pending_claim_requests.iter_mut() {
+               for (first_claim_txid, ref mut cached_claim_datas) in self.pending_claim_requests.iter_mut() {
                        if cached_claim_datas.height_timer == height {
-                               if let hash_map::Entry::Vacant(entry) = bump_candidates.entry(ancestor_claim_txid.clone()) {
-                                       entry.insert(cached_claim_datas.clone());
-                               }
+                               bump_candidates.insert(first_claim_txid.clone());
                        }
                }
-               for ref mut cached_claim_datas in bump_candidates.values_mut() {
-                       if let Some((new_timer, new_feerate, bump_tx)) = self.bump_claim_tx(height, &cached_claim_datas, fee_estimator) {
-                               cached_claim_datas.height_timer = new_timer;
-                               cached_claim_datas.feerate_previous = new_feerate;
-                               broadcaster.broadcast_transaction(&bump_tx);
+               for first_claim_txid in bump_candidates.iter() {
+                       if let Some((new_timer, new_feerate)) = {
+                               if let Some(claim_material) = self.pending_claim_requests.get(first_claim_txid) {
+                                       if let Some((new_timer, new_feerate, bump_tx)) = self.bump_claim_tx(height, &claim_material, fee_estimator) {
+                                               broadcaster.broadcast_transaction(&bump_tx);
+                                               Some((new_timer, new_feerate))
+                                       } else { None }
+                               } else { unreachable!(); }
+                       } {
+                               if let Some(claim_material) = self.pending_claim_requests.get_mut(first_claim_txid) {
+                                       claim_material.height_timer = new_timer;
+                                       claim_material.feerate_previous = new_feerate;
+                               } else { unreachable!(); }
                        }
                }
-               for (ancestor_claim_txid, cached_claim_datas) in bump_candidates.drain() {
-                       self.pending_claim_requests.insert(ancestor_claim_txid, cached_claim_datas);
-               }
                self.last_block_hash = block_hash.clone();
                (watch_outputs, spendable_outputs, htlc_updated)
        }
@@ -2984,6 +2998,8 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
 
                let their_htlc_base_key = Some(Readable::read(reader)?);
                let their_delayed_payment_base_key = Some(Readable::read(reader)?);
+               let funding_redeemscript = Some(Readable::read(reader)?);
+               let channel_value_satoshis = Some(Readable::read(reader)?);
 
                let their_cur_revocation_points = {
                        let first_idx = <U48 as Readable<R>>::read(reader)?.0;
@@ -3204,6 +3220,8 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
                        key_storage,
                        their_htlc_base_key,
                        their_delayed_payment_base_key,
+                       funding_redeemscript,
+                       channel_value_satoshis,
                        their_cur_revocation_points,
 
                        our_to_self_delay,
@@ -3685,7 +3703,7 @@ mod tests {
                // Prune with one old state and a local commitment tx holding a few overlaps with the
                // old state.
                let mut monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
-               monitor.set_their_to_self_delay(10);
+               monitor.their_to_self_delay = Some(10);
 
                monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]));
                monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key);