Rm ChannelMonitor merge capabilities in favor of explicit add/update
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index 373f811e9ae4ea8ec77f104edff12fef1c0bca08..113e007abead2b6c647cab3db68ffe7363cf0217 100644 (file)
@@ -131,9 +131,9 @@ pub enum ChannelMonitorUpdateErr {
 }
 
 /// General Err type for ChannelMonitor actions. Generally, this implies that the data provided is
-/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::insert_combine this
-/// means you tried to merge two monitors for different channels or for a channel which was
-/// restored from a backup and then generated new commitment updates.
+/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this
+/// means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was
+/// corrupted.
 /// Contains a human-readable error message.
 #[derive(Debug)]
 pub struct MonitorUpdateError(pub &'static str);
@@ -150,7 +150,7 @@ impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
 
 /// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
 /// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
-/// events to it, while also taking any add_update_monitor events and passing them to some remote
+/// events to it, while also taking any add/update_monitor events and passing them to some remote
 /// server(s).
 ///
 /// Note that any updates to a channel's monitor *must* be applied to each instance of the
@@ -164,7 +164,7 @@ impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
 /// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
 /// all registered listeners in one go.
 pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
-       /// Adds or updates a monitor for the given `funding_txo`.
+       /// Adds a monitor for the given `funding_txo`.
        ///
        /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
        /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
@@ -176,7 +176,7 @@ pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
        ///
        /// Any spends of outputs which should have been registered which aren't passed to
        /// ChannelMonitors via block_connected may result in FUNDS LOSS.
-       fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
+       fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
 
        /// Updates a monitor for the given `funding_txo`.
        ///
@@ -279,14 +279,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
        }
 
        /// Adds or updates the monitor which monitors the channel referred to by the given key.
-       pub fn add_update_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
+       pub fn add_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
                let mut monitors = self.monitors.lock().unwrap();
-               match monitors.get_mut(&key) {
-                       Some(orig_monitor) => {
-                               log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(monitor.key_storage));
-                               return orig_monitor.insert_combine(monitor);
-                       },
-                       None => {}
+               let entry = match monitors.entry(key) {
+                       hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
+                       hash_map::Entry::Vacant(e) => e,
                };
                match monitor.key_storage {
                        Storage::Local { ref funding_info, .. } => {
@@ -310,7 +307,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
                                self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
                        }
                }
-               monitors.insert(key, monitor);
+               entry.insert(monitor);
                Ok(())
        }
 
@@ -330,8 +327,8 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
 impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T>
        where T::Target: BroadcasterInterface
 {
-       fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
-               match self.add_update_monitor_by_key(funding_txo, monitor) {
+       fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
+               match self.add_monitor_by_key(funding_txo, monitor) {
                        Ok(_) => Ok(()),
                        Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
                }
@@ -879,7 +876,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
 
        // We simply modify last_block_hash in Channel's block_connected so that serialization is
        // consistent but hopefully the users' copy handles block_connected in a consistent way.
-       // (we do *not*, however, update them in insert_combine to ensure any local user copies keep
+       // (we do *not*, however, update them in update_monitor to ensure any local user copies keep
        // their last_block_hash from its state and not based on updated copies that didn't run through
        // the full block_connected).
        pub(crate) last_block_hash: Sha256dHash,
@@ -1215,31 +1212,43 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
 }
 
 impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
-       pub(super) fn new(keys: ChanSigner, funding_key: &SecretKey, revocation_base_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey, payment_base_key: &SecretKey, shutdown_pubkey: &PublicKey, our_to_self_delay: u16, destination_script: Script, logger: Arc<Logger>) -> ChannelMonitor<ChanSigner> {
+       pub(super) fn new(keys: ChanSigner, shutdown_pubkey: &PublicKey,
+                       our_to_self_delay: u16, destination_script: &Script, funding_info: (OutPoint, Script),
+                       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,
+                       logger: Arc<Logger>) -> ChannelMonitor<ChanSigner> {
+
+               assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
+               let funding_key = keys.funding_key().clone();
+               let revocation_base_key = keys.revocation_base_key().clone();
+               let htlc_base_key = keys.htlc_base_key().clone();
+               let delayed_payment_base_key = keys.delayed_payment_base_key().clone();
+               let payment_base_key = keys.payment_base_key().clone();
                ChannelMonitor {
                        latest_update_id: 0,
-                       commitment_transaction_number_obscure_factor: 0,
+                       commitment_transaction_number_obscure_factor,
 
                        key_storage: Storage::Local {
                                keys,
-                               funding_key: funding_key.clone(),
-                               revocation_base_key: revocation_base_key.clone(),
-                               htlc_base_key: htlc_base_key.clone(),
-                               delayed_payment_base_key: delayed_payment_base_key.clone(),
-                               payment_base_key: payment_base_key.clone(),
+                               funding_key,
+                               revocation_base_key,
+                               htlc_base_key,
+                               delayed_payment_base_key,
+                               payment_base_key,
                                shutdown_pubkey: shutdown_pubkey.clone(),
-                               funding_info: None,
+                               funding_info: Some(funding_info),
                                current_remote_commitment_txid: None,
                                prev_remote_commitment_txid: None,
                        },
-                       their_htlc_base_key: None,
-                       their_delayed_payment_base_key: None,
-                       funding_redeemscript: None,
-                       channel_value_satoshis: None,
+                       their_htlc_base_key: Some(their_htlc_base_key.clone()),
+                       their_delayed_payment_base_key: Some(their_delayed_payment_base_key.clone()),
+                       funding_redeemscript: Some(funding_redeemscript),
+                       channel_value_satoshis: Some(channel_value_satoshis),
                        their_cur_revocation_points: None,
 
                        our_to_self_delay: our_to_self_delay,
-                       their_to_self_delay: None,
+                       their_to_self_delay: Some(their_to_self_delay),
 
                        commitment_secrets: CounterpartyCommitmentSecrets::new(),
                        remote_claimable_outpoints: HashMap::new(),
@@ -1253,7 +1262,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        payment_preimages: HashMap::new(),
                        pending_htlcs_updated: Vec::new(),
 
-                       destination_script: destination_script,
+                       destination_script: destination_script.clone(),
                        to_remote_rescue: None,
 
                        pending_claim_requests: HashMap::new(),
@@ -1497,97 +1506,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                Ok(())
        }
 
-       /// Combines this ChannelMonitor with the information contained in the other ChannelMonitor.
-       /// After a successful call this ChannelMonitor is up-to-date and is safe to use to monitor the
-       /// chain for new blocks/transactions.
-       pub fn insert_combine(&mut self, mut other: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
-               match self.key_storage {
-                       Storage::Local { ref funding_info, .. } => {
-                               if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
-                               let our_funding_info = funding_info;
-                               if let Storage::Local { ref funding_info, .. } = other.key_storage {
-                                       if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
-                                       // We should be able to compare the entire funding_txo, but in fuzztarget it's trivially
-                                       // easy to collide the funding_txo hash and have a different scriptPubKey.
-                                       if funding_info.as_ref().unwrap().0 != our_funding_info.as_ref().unwrap().0 {
-                                               return Err(MonitorUpdateError("Funding transaction outputs are not identical!"));
-                                       }
-                               } else {
-                                       return Err(MonitorUpdateError("Try to combine a Local monitor with a Watchtower one !"));
-                               }
-                       },
-                       Storage::Watchtower { .. } => {
-                               if let Storage::Watchtower { .. } = other.key_storage {
-                                       unimplemented!();
-                               } else {
-                                       return Err(MonitorUpdateError("Try to combine a Watchtower monitor with a Local one !"));
-                               }
-                       },
-               }
-               let other_min_secret = other.get_min_seen_secret();
-               let our_min_secret = self.get_min_seen_secret();
-               if our_min_secret > other_min_secret {
-                       self.provide_secret(other_min_secret, other.get_secret(other_min_secret).unwrap())?;
-               }
-               if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
-                       if let Some(ref other_local_tx) = other.current_local_signed_commitment_tx {
-                               let our_commitment_number = 0xffffffffffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
-                               let other_commitment_number = 0xffffffffffff - ((((other_local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ other.commitment_transaction_number_obscure_factor);
-                               if our_commitment_number >= other_commitment_number {
-                                       self.key_storage = other.key_storage;
-                               }
-                       }
-               }
-               // TODO: We should use current_remote_commitment_number and the commitment number out of
-               // local transactions to decide how to merge
-               if our_min_secret >= other_min_secret {
-                       self.their_cur_revocation_points = other.their_cur_revocation_points;
-                       for (txid, htlcs) in other.remote_claimable_outpoints.drain() {
-                               self.remote_claimable_outpoints.insert(txid, htlcs);
-                       }
-                       if let Some(local_tx) = other.prev_local_signed_commitment_tx {
-                               self.prev_local_signed_commitment_tx = Some(local_tx);
-                       }
-                       if let Some(local_tx) = other.current_local_signed_commitment_tx {
-                               self.current_local_signed_commitment_tx = Some(local_tx);
-                       }
-                       self.payment_preimages = other.payment_preimages;
-                       self.to_remote_rescue = other.to_remote_rescue;
-               }
-
-               self.current_remote_commitment_number = cmp::min(self.current_remote_commitment_number, other.current_remote_commitment_number);
-               Ok(())
-       }
-
-       /// 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 on a monitor you wish to send to a watchtower as it provides slightly better
-       /// privacy.
-       /// It's the responsibility of the caller to register outpoint and script with passing the former
-       /// value as key to add_update_monitor.
-       pub(super) fn set_funding_info(&mut self, new_funding_info: (OutPoint, Script)) {
-               match self.key_storage {
-                       Storage::Local { ref mut funding_info, .. } => {
-                               *funding_info = Some(new_funding_info);
-                       },
-                       Storage::Watchtower { .. } => {
-                               panic!("Channel somehow ended up with its internal ChannelMonitor being in Watchtower mode?");
-                       }
-               }
-       }
-
-       /// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
-       /// 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());
-               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;
-       }
-
        /// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
        /// ChannelMonitor.
        pub fn get_latest_update_id(&self) -> u64 {
@@ -3571,6 +3489,7 @@ mod tests {
        use bitcoin_hashes::sha256d::Hash as Sha256dHash;
        use bitcoin_hashes::hex::FromHex;
        use hex;
+       use chain::transaction::OutPoint;
        use ln::channelmanager::{PaymentPreimage, PaymentHash};
        use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
        use ln::chan_utils;
@@ -3663,7 +3582,13 @@ 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(keys, &SecretKey::from_slice(&[41; 32]).unwrap(), &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());
+               let mut monitor = ChannelMonitor::new(keys,
+                       &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(),
+                       (OutPoint { txid: Sha256dHash::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
+                       &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[44; 32]).unwrap()),
+                       &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()),
+                       0, Script::new(), 46, 0, logger.clone());
+
                monitor.their_to_self_delay = Some(10);
 
                monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10])).unwrap();