X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmonitor.rs;h=b18a49e0107709e886576ca0c704518929674625;hb=676e15910c1a681e5ff2019bc7e53540119ceee5;hp=ff0b6e9eb8903a0ab3d2c03a7cba8f892026f623;hpb=d4ad57b7e65f206bc40989eaef7ce2efe9428935;p=rust-lightning diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index ff0b6e9e..b18a49e0 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -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: Send + Sync { fn get_and_clear_pending_htlcs_updated(&self) -> Vec; } +/// 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>>, + monitor: &'a ChannelMonitor, +} +impl<'a, Key, ChanSigner: ChannelKeys> ::std::ops::Deref for ManyChannelMonitorLock<'a, Key, ChanSigner> { + type Target = ChannelMonitor; + fn deref(&self) -> &ChannelMonitor { + 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 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> { + // 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>> = 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 ManyChannelMonitor for SimpleManyChannelMonitor @@ -1797,12 +1849,17 @@ impl ChannelMonitor { 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(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec)> + /// Called when a new block has been connected to the best chain by ::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(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec)> where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -1901,7 +1958,14 @@ impl ChannelMonitor { watch_outputs } - fn block_disconnected(&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 ::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(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger,