Add an fn to get a ChannelMonitor reference from a ManyChannelMonitor
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index ff0b6e9eb8903a0ab3d2c03a7cba8f892026f623..b18a49e0107709e886576ca0c704518929674625 100644 (file)
@@ -40,7 +40,7 @@ use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48};
 use util::{byte_utils, events};
 
 use std::collections::{HashMap, hash_map};
-use std::sync::Mutex;
+use std::sync::{Mutex, MutexGuard};
 use std::{hash,cmp, mem};
 use std::ops::Deref;
 
@@ -209,6 +209,27 @@ pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
        fn get_and_clear_pending_htlcs_updated(&self) -> Vec<HTLCUpdate>;
 }
 
+/// A lock held on a specific ManyChannelMonitor that includes a reference to the current version
+/// of a ChannelMonitor contained within.
+pub struct ManyChannelMonitorLock<'a, Key, ChanSigner: ChannelKeys> {
+       lock_ptr: *mut MutexGuard<'a, HashMap<Key, ChannelMonitor<ChanSigner>>>,
+       monitor: &'a ChannelMonitor<ChanSigner>,
+}
+impl<'a, Key, ChanSigner: ChannelKeys> ::std::ops::Deref for ManyChannelMonitorLock<'a, Key, ChanSigner> {
+       type Target = ChannelMonitor<ChanSigner>;
+       fn deref(&self) -> &ChannelMonitor<ChanSigner> {
+               self.monitor
+       }
+}
+impl<'a, Key, ChanSigner: ChannelKeys> Drop for ManyChannelMonitorLock<'a, Key, ChanSigner> {
+       fn drop(&mut self) {
+               // Dereferencing the lock_ptr is trivially safe here - it is created when this object is
+               // created, is never null, and is not modified at any point other than creation.
+               let _ = unsafe { Box::from_raw(self.lock_ptr) };
+               // Drop the box, freeing the lock
+       }
+}
+
 /// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
 /// watchtower or watch our own channels.
 ///
@@ -318,6 +339,37 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: De
                        None => Err(MonitorUpdateError("No such monitor registered"))
                }
        }
+
+       /// Gets a reference to the latest copy of a given ChannelMonitor given a &Key, if any has been
+       /// registered.
+       ///
+       /// The returned value contains a lock on this object, and other calls into this object will
+       /// almost certainly block until the returned value is dropped!
+       pub fn get_monitor_ref_by_key<'a>(&'a self, key: &Key) -> Option<ManyChannelMonitorLock<'a, Key, ChanSigner>> {
+               // Rust doesn't natively allow self-referential structs, and the only way to return a
+               // reference to something inside our Mutex is to return a struct that contains the lock and
+               // a reference to something pulled out of said lock.
+               // To avoid this, we have to fall back to some use of unsafe, but luckily its incredibly
+               // trivial - we simply Box up the MutexGuard and Box::leak() it, ensuring that its sitting
+               // in our heap without Rust having any reference to drop it.
+               // Then, we do a map lookup against the raw pointer, either returning a
+               // ManyChannelMonitorMonRef (which will drop the lock by recreating the Box when it gets
+               // dropped), or we will recreate the Box immediately and drop the lock before returning
+               // None.
+               //
+               // The returned ManyChannelMonitorMonRef is templated by a lifetime for which &self is
+               // valid, ensuring this object cannot be dropped until after the returned value is.
+               let lock = Box::new(self.monitors.lock().unwrap());
+               let lock_ptr: *mut MutexGuard<HashMap<Key, ChannelMonitor<ChanSigner>>> = Box::leak(lock);
+               let mon = unsafe { (*lock_ptr).get(key) };
+               if let Some(monitor) = mon {
+                       Some(ManyChannelMonitorLock { lock_ptr, monitor })
+               } else {
+                       let _ = unsafe { Box::from_raw(lock_ptr) };
+                       // Drop the lock again
+                       None
+               }
+       }
 }
 
 impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
@@ -1797,12 +1849,17 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                Vec::new()
        }
 
-       /// Called by SimpleManyChannelMonitor::block_connected, which implements
-       /// ChainListener::block_connected.
-       /// Eventually this should be pub and, roughly, implement ChainListener, however this requires
-       /// &mut self, as well as returns new spendable outputs and outpoints to watch for spending of
-       /// on-chain.
-       fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
+       /// Called when a new block has been connected to the best chain by <SimpleManyChannelMonitor
+       /// as ChainListener>::block_connected, and should thus generally not be called during normal
+       /// operation. It is exposed both for users who wish to use ChannelMonitors directly and to
+       /// simplify rescans that occur at load-time.
+       ///
+       /// This is very similar to ChainListener::block_connected itself, but requires an &mut self,
+       /// and an explicit reference to a transaction broadcaster and fee estimator.
+       ///
+       /// Returns a list of new (txid, outputs) pairs which spends of must be watched for. Note that
+       /// after this call these are also available via get_outputs_to_watch().
+       pub fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
                where B::Target: BroadcasterInterface,
                      F::Target: FeeEstimator,
                                        L::Target: Logger,
@@ -1901,7 +1958,14 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                watch_outputs
        }
 
-       fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)
+       /// Called when a block has been disconnected from the best chain by <SimpleManyChannelMonitor
+       /// as ChainListener>::block_disconnected, and should thus generally not be called during
+       /// normal operation. It is exposed both for users who wish to use ChannelMonitors directly and
+       /// to simplify rescans that occur at load-time.
+       ///
+       /// This is very similar to ChainListener::block_disconnected itself, but requires an &mut self,
+       /// and an explicit reference to a transaction broadcaster and fee estimator.
+       pub fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)
                where B::Target: BroadcasterInterface,
                      F::Target: FeeEstimator,
                      L::Target: Logger,