X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannelmonitor.rs;h=8d6d23ad00a160b6342eade2dce0fffbf33ca06c;hb=41f1e1680553d1416d1b2bc2e4fb284cbe1a130f;hp=acd63da79e1bd63b511bfc7ec49ed29bb3dbcebb;hpb=92ff499bdbc115fbb897e5aa8bf758fc66987e95;p=rust-lightning diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index acd63da7..8d6d23ad 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -1,8 +1,10 @@ //! The logic to monitor for on-chain transactions and create the relevant claim responses lives //! here. +//! //! ChannelMonitor objects are generated by ChannelManager in response to relevant //! messages/actions, and MUST be persisted to disk (and, preferably, remotely) before progress can //! be made in responding to certain messages, see ManyChannelMonitor for more. +//! //! Note that ChannelMonitors are an important part of the lightning trust model and a copy of the //! latest ChannelMonitor must always be actively monitoring for chain updates (and no out-of-date //! ChannelMonitors should do so). Thus, if you're building rust-lightning into an HSM or other @@ -40,6 +42,7 @@ use std::{hash,cmp}; pub enum ChannelMonitorUpdateErr { /// Used to indicate a temporary failure (eg connection to a watchtower failed, but is expected /// to succeed at some point in the future). + /// /// Such a failure will "freeze" a channel, preventing us from revoking old states or /// submitting new commitment transactions to the remote party. /// ChannelManager::test_restore_channel_monitor can be used to retry the update(s) and restore @@ -55,12 +58,14 @@ pub enum ChannelMonitorUpdateErr { /// 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 /// server(s). +/// /// Note that any updates to a channel's monitor *must* be applied to each instance of the /// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If /// an update occurs and a remote watchtower is left with old state, it may broadcast transactions /// which we have revoked, allowing our counterparty to claim all funds in the channel! pub trait ManyChannelMonitor: Send + Sync { /// Adds or updates a monitor for the given `funding_txo`. + /// /// Implementor must also ensure that the funding_txo outpoint is registered with any relevant /// ChainWatchInterfaces such that the provided monitor receives block_connected callbacks with /// any spends of it. @@ -69,10 +74,13 @@ pub trait ManyChannelMonitor: Send + Sync { /// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a /// watchtower or watch our own channels. +/// /// Note that you must provide your own key by which to refer to channels. +/// /// If you're accepting remote monitors (ie are implementing a watchtower), you must verify that /// users cannot overwrite a given channel by providing a duplicate key. ie you should probably /// index by a PublicKey which is required to sign any updates. +/// /// 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 { @@ -180,6 +188,7 @@ const MIN_SERIALIZATION_VERSION: u8 = 1; /// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates /// on-chain transactions to ensure no loss of funds occurs. +/// /// You MUST ensure that no ChannelMonitors for a given channel anywhere contain out-of-date /// information and are actively monitoring the chain. pub struct ChannelMonitor { @@ -750,7 +759,7 @@ impl ChannelMonitor { ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &htlc_base_key))) }, }; - let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.delayed_payment_base_key)); + let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key.unwrap())); let a_htlc_key = match self.their_htlc_base_key { None => return (txn_to_broadcast, (commitment_txid, watch_outputs)), Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &their_htlc_base_key)), @@ -847,7 +856,7 @@ impl ChannelMonitor { }; let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx); sign_input!(sighash_parts, single_htlc_tx.input[0], Some(idx), htlc.amount_msat / 1000); - txn_to_broadcast.push(single_htlc_tx); // TODO: This is not yet tested in ChannelManager! + txn_to_broadcast.push(single_htlc_tx); } } } @@ -1002,7 +1011,9 @@ impl ChannelMonitor { /// Attempst to claim a remote HTLC-Success/HTLC-Timeout s outputs using the revocation key fn check_spend_remote_htlc(&self, tx: &Transaction, commitment_number: u64) -> Option { - let htlc_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers! + if tx.input.len() != 1 || tx.output.len() != 1 { + return None; + } macro_rules! ignore_error { ( $thing : expr ) => { @@ -1030,6 +1041,7 @@ impl ChannelMonitor { }; let redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.their_to_self_delay.unwrap(), &delayed_key); let revokeable_p2wsh = redeemscript.to_v0_p2wsh(); + let htlc_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers! let mut inputs = Vec::new(); let mut amount = 0;