X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmonitor.rs;h=b18a49e0107709e886576ca0c704518929674625;hb=676e15910c1a681e5ff2019bc7e53540119ceee5;hp=4a89f5002e175a969a6435fc7aacdab3c368844a;hpb=080afeb6ea5746ac076658c723492e3d6d257ceb;p=rust-lightning diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 4a89f500..b18a49e0 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -19,14 +19,13 @@ use bitcoin::blockdata::opcodes; use bitcoin::consensus::encode; use bitcoin::util::hash::BitcoinHash; -use bitcoin_hashes::Hash; -use bitcoin_hashes::sha256::Hash as Sha256; -use bitcoin_hashes::hash160::Hash as Hash160; -use bitcoin_hashes::sha256d::Hash as Sha256dHash; +use bitcoin::hashes::Hash; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; -use secp256k1::{Secp256k1,Signature}; -use secp256k1::key::{SecretKey,PublicKey}; -use secp256k1; +use bitcoin::secp256k1::{Secp256k1,Signature}; +use bitcoin::secp256k1::key::{SecretKey,PublicKey}; +use bitcoin::secp256k1; use ln::msgs::DecodeError; use ln::chan_utils; @@ -37,11 +36,11 @@ use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInter use chain::transaction::OutPoint; use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys}; use util::logger::Logger; -use util::ser::{ReadableArgs, Readable, MaybeReadable, Writer, Writeable, U48}; +use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48}; use util::{byte_utils, events}; use std::collections::{HashMap, hash_map}; -use std::sync::{Arc,Mutex}; +use std::sync::{Mutex, MutexGuard}; use std::{hash,cmp, mem}; use std::ops::Deref; @@ -210,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. /// @@ -221,31 +241,35 @@ pub trait ManyChannelMonitor: Send + Sync { /// /// If you're using this for local monitoring of your own channels, you probably want to use /// `OutPoint` as the key, which will give you a ManyChannelMonitor implementation. -pub struct SimpleManyChannelMonitor +pub struct SimpleManyChannelMonitor where T::Target: BroadcasterInterface, - F::Target: FeeEstimator + F::Target: FeeEstimator, + L::Target: Logger, + C::Target: ChainWatchInterface, { #[cfg(test)] // Used in ChannelManager tests to manipulate channels directly pub monitors: Mutex>>, #[cfg(not(test))] monitors: Mutex>>, - chain_monitor: Arc, + chain_monitor: C, broadcaster: T, - logger: Arc, + logger: L, fee_estimator: F } -impl<'a, Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send> - ChainListener for SimpleManyChannelMonitor +impl + ChainListener for SimpleManyChannelMonitor where T::Target: BroadcasterInterface, - F::Target: FeeEstimator + F::Target: FeeEstimator, + L::Target: Logger, + C::Target: ChainWatchInterface, { fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) { let block_hash = header.bitcoin_hash(); { let mut monitors = self.monitors.lock().unwrap(); for monitor in monitors.values_mut() { - let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator); + let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger); for (ref txid, ref outputs) in txn_outputs { for (idx, output) in outputs.iter().enumerate() { @@ -260,18 +284,20 @@ impl<'a, Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + let block_hash = header.bitcoin_hash(); let mut monitors = self.monitors.lock().unwrap(); for monitor in monitors.values_mut() { - monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator); + monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger); } } } -impl SimpleManyChannelMonitor +impl SimpleManyChannelMonitor where T::Target: BroadcasterInterface, - F::Target: FeeEstimator + F::Target: FeeEstimator, + L::Target: Logger, + C::Target: ChainWatchInterface, { /// Creates a new object which can be used to monitor several channels given the chain /// interface with which to register to receive notifications. - pub fn new(chain_monitor: Arc, broadcaster: T, logger: Arc, feeest: F) -> SimpleManyChannelMonitor { + pub fn new(chain_monitor: C, broadcaster: T, logger: L, feeest: F) -> SimpleManyChannelMonitor { let res = SimpleManyChannelMonitor { monitors: Mutex::new(HashMap::new()), chain_monitor, @@ -290,16 +316,9 @@ impl return Err(MonitorUpdateError("Channel monitor for given key is already present")), hash_map::Entry::Vacant(e) => e, }; - match monitor.onchain_detection.funding_info { - None => { - return Err(MonitorUpdateError("Try to update a useless monitor without funding_txo !")); - }, - Some((ref outpoint, ref script)) => { - log_trace!(self, "Got new Channel Monitor for channel {}", log_bytes!(outpoint.to_channel_id()[..])); - self.chain_monitor.install_watch_tx(&outpoint.txid, script); - self.chain_monitor.install_watch_outpoint((outpoint.txid, outpoint.index as u32), script); - }, - } + log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(monitor.funding_info.0.to_channel_id()[..])); + self.chain_monitor.install_watch_tx(&monitor.funding_info.0.txid, &monitor.funding_info.1); + self.chain_monitor.install_watch_outpoint((monitor.funding_info.0.txid, monitor.funding_info.0.index as u32), &monitor.funding_info.1); for (txid, outputs) in monitor.get_outputs_to_watch().iter() { for (idx, script) in outputs.iter().enumerate() { self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script); @@ -314,17 +333,50 @@ impl { - log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor.onchain_detection)); - orig_monitor.update_monitor(update, &self.broadcaster) + log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor)); + orig_monitor.update_monitor(update, &self.broadcaster, &self.logger) }, 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> { + // 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 +impl ManyChannelMonitor for SimpleManyChannelMonitor where T::Target: BroadcasterInterface, - F::Target: FeeEstimator + F::Target: FeeEstimator, + L::Target: Logger, + C::Target: ChainWatchInterface, { fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { match self.add_monitor_by_key(funding_txo, monitor) { @@ -349,9 +401,11 @@ impl Ma } } -impl events::EventsProvider for SimpleManyChannelMonitor +impl events::EventsProvider for SimpleManyChannelMonitor where T::Target: BroadcasterInterface, - F::Target: FeeEstimator + F::Target: FeeEstimator, + L::Target: Logger, + C::Target: ChainWatchInterface, { fn get_and_clear_pending_events(&self) -> Vec { let mut pending_events = Vec::new(); @@ -390,26 +444,33 @@ pub(crate) const LATENCY_GRACE_PERIOD_BLOCKS: u32 = 3; /// solved by a previous claim tx. What we want to avoid is reorg evicting our claim tx and us not /// keeping bumping another claim tx to solve the outpoint. pub(crate) const ANTI_REORG_DELAY: u32 = 6; - -struct OnchainDetection { - keys: ChanSigner, - funding_info: Option<(OutPoint, Script)>, - current_remote_commitment_txid: Option, - prev_remote_commitment_txid: Option, -} - -#[cfg(any(test, feature = "fuzztarget"))] -impl PartialEq for OnchainDetection { - fn eq(&self, other: &Self) -> bool { - self.keys.pubkeys() == other.keys.pubkeys() - } -} +/// Number of blocks before confirmation at which we fail back an un-relayed HTLC or at which we +/// refuse to accept a new HTLC. +/// +/// This is used for a few separate purposes: +/// 1) if we've received an MPP HTLC to us and it expires within this many blocks and we are +/// waiting on additional parts (or waiting on the preimage for any HTLC from the user), we will +/// fail this HTLC, +/// 2) if we receive an HTLC within this many blocks of its expiry (plus one to avoid a race +/// condition with the above), we will fail this HTLC without telling the user we received it, +/// 3) if we are waiting on a connection or a channel state update to send an HTLC to a peer, and +/// that HTLC expires within this many blocks, we will simply fail the HTLC instead. +/// +/// (1) is all about protecting us - we need enough time to update the channel state before we hit +/// CLTV_CLAIM_BUFFER, at which point we'd go on chain to claim the HTLC with the preimage. +/// +/// (2) is the same, but with an additional buffer to avoid accepting an HTLC which is immediately +/// in a race condition between the user connecting a block (which would fail it) and the user +/// providing us the preimage (which would claim it). +/// +/// (3) is about our counterparty - we don't want to relay an HTLC to a counterparty when they may +/// end up force-closing the channel on us to claim it. +pub(crate) const HTLC_FAIL_BACK_BUFFER: u32 = CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS; #[derive(Clone, PartialEq)] struct LocalSignedTx { /// txid of the transaction in tx, just used to make comparison faster - txid: Sha256dHash, - tx: LocalCommitmentTransaction, + txid: Txid, revocation_key: PublicKey, a_htlc_key: PublicKey, b_htlc_key: PublicKey, @@ -439,13 +500,11 @@ pub(crate) enum InputMaterial { locktime: u32, }, LocalHTLC { - witness_script: Script, - sigs: (Signature, Signature), preimage: Option, amount: u64, }, Funding { - channel_value: u64, + funding_redeemscript: Script, } } @@ -468,17 +527,14 @@ impl Writeable for InputMaterial { writer.write_all(&byte_utils::be64_to_array(*amount))?; writer.write_all(&byte_utils::be32_to_array(*locktime))?; }, - &InputMaterial::LocalHTLC { ref witness_script, ref sigs, ref preimage, ref amount } => { + &InputMaterial::LocalHTLC { ref preimage, ref amount } => { writer.write_all(&[2; 1])?; - witness_script.write(writer)?; - sigs.0.write(writer)?; - sigs.1.write(writer)?; preimage.write(writer)?; writer.write_all(&byte_utils::be64_to_array(*amount))?; }, - &InputMaterial::Funding { ref channel_value } => { + &InputMaterial::Funding { ref funding_redeemscript } => { writer.write_all(&[3; 1])?; - channel_value.write(writer)?; + funding_redeemscript.write(writer)?; } } Ok(()) @@ -517,22 +573,16 @@ impl Readable for InputMaterial { } }, 2 => { - let witness_script = Readable::read(reader)?; - let their_sig = Readable::read(reader)?; - let our_sig = Readable::read(reader)?; let preimage = Readable::read(reader)?; let amount = Readable::read(reader)?; InputMaterial::LocalHTLC { - witness_script, - sigs: (their_sig, our_sig), preimage, - amount + amount, } }, 3 => { - let channel_value = Readable::read(reader)?; InputMaterial::Funding { - channel_value + funding_redeemscript: Readable::read(reader)?, } } _ => return Err(DecodeError::InvalidValue), @@ -585,12 +635,7 @@ const MIN_SERIALIZATION_VERSION: u8 = 1; #[derive(Clone)] pub(super) enum ChannelMonitorUpdateStep { LatestLocalCommitmentTXInfo { - // TODO: We really need to not be generating a fully-signed transaction in Channel and - // passing it here, we need to hold off so that the ChanSigner can enforce a - // only-sign-local-state-for-broadcast once invariant: commitment_tx: LocalCommitmentTransaction, - local_keys: chan_utils::TxCreationKeys, - feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, }, LatestRemoteCommitmentTXInfo { @@ -606,11 +651,6 @@ pub(super) enum ChannelMonitorUpdateStep { idx: u64, secret: [u8; 32], }, - /// Indicates our channel is likely a stale version, we're closing, but this update should - /// allow us to spend what is ours if our counterparty broadcasts their latest state. - RescueRemoteCommitmentTXInfo { - their_current_per_commitment_point: PublicKey, - }, /// Used to indicate that the no future updates will occur, and likely that the latest local /// commitment transaction(s) should be broadcast, as the channel has been force-closed. ChannelForceClosed { @@ -623,11 +663,9 @@ pub(super) enum ChannelMonitorUpdateStep { impl Writeable for ChannelMonitorUpdateStep { fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { match self { - &ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { ref commitment_tx, ref local_keys, ref feerate_per_kw, ref htlc_outputs } => { + &ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { ref commitment_tx, ref htlc_outputs } => { 0u8.write(w)?; commitment_tx.write(w)?; - local_keys.write(w)?; - feerate_per_kw.write(w)?; (htlc_outputs.len() as u64).write(w)?; for &(ref output, ref signature, ref source) in htlc_outputs.iter() { output.write(w)?; @@ -655,12 +693,8 @@ impl Writeable for ChannelMonitorUpdateStep { idx.write(w)?; secret.write(w)?; }, - &ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { ref their_current_per_commitment_point } => { - 4u8.write(w)?; - their_current_per_commitment_point.write(w)?; - }, &ChannelMonitorUpdateStep::ChannelForceClosed { ref should_broadcast } => { - 5u8.write(w)?; + 4u8.write(w)?; should_broadcast.write(w)?; }, } @@ -673,8 +707,6 @@ impl Readable for ChannelMonitorUpdateStep { 0u8 => { Ok(ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx: Readable::read(r)?, - local_keys: Readable::read(r)?, - feerate_per_kw: Readable::read(r)?, htlc_outputs: { let len: u64 = Readable::read(r)?; let mut res = Vec::new(); @@ -712,11 +744,6 @@ impl Readable for ChannelMonitorUpdateStep { }) }, 4u8 => { - Ok(ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { - their_current_per_commitment_point: Readable::read(r)?, - }) - }, - 5u8 => { Ok(ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast: Readable::read(r)? }) @@ -742,28 +769,32 @@ pub struct ChannelMonitor { destination_script: Script, broadcasted_local_revokable_script: Option<(Script, SecretKey, Script)>, - broadcasted_remote_payment_script: Option<(Script, SecretKey)>, + remote_payment_script: Script, shutdown_script: Script, - onchain_detection: OnchainDetection, - their_htlc_base_key: Option, - their_delayed_payment_base_key: Option, - funding_redeemscript: Option