X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmonitor.rs;h=49168627f5448647f8bc150fdce7aa72a862b738;hb=b9707da1382bcebe066c0c26b15a975991bf81e2;hp=5db9d17141ce28244d005780a304ca5b2a8b0948;hpb=22daecb8e494122af8617f716014cae9dca38b9b;p=rust-lightning diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 5db9d171..49168627 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -1,3 +1,12 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + //! The logic to monitor for on-chain transactions and create the relevant claim responses lives //! here. //! @@ -17,7 +26,6 @@ use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; use bitcoin::consensus::encode; -use bitcoin::util::hash::BitcoinHash; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; @@ -38,11 +46,13 @@ use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys}; use util::logger::Logger; use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48}; use util::{byte_utils, events}; +use util::events::Event; use std::collections::{HashMap, hash_map}; use std::sync::Mutex; use std::{hash,cmp, mem}; use std::ops::Deref; +use std::io::Error; /// An update generated by the underlying Channel itself which contains some new information the /// ChannelMonitor should be made aware of. @@ -139,6 +149,16 @@ pub enum ChannelMonitorUpdateErr { #[derive(Debug)] pub struct MonitorUpdateError(pub &'static str); +/// An event to be processed by the ChannelManager. +#[derive(PartialEq)] +pub enum MonitorEvent { + /// A monitor event containing an HTLCUpdate. + HTLCEvent(HTLCUpdate), + + /// A monitor event that the Channel's commitment transaction was broadcasted. + CommitmentTxBroadcasted(OutPoint), +} + /// Simple structure send back by ManyChannelMonitor in case of HTLC detected onchain from a /// forward channel and from which info are needed to update HTLC in a backward channel. #[derive(Clone, PartialEq)] @@ -149,66 +169,6 @@ pub struct HTLCUpdate { } 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 -/// server(s). -/// -/// In general, you must always have at least one local copy in memory, which must never fail to -/// update (as it is responsible for broadcasting the latest state in case the channel is closed), -/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails -/// to update (eg out-of-memory or some other condition), you must immediately shut down without -/// taking any further action such as writing the current state to disk. This should likely be -/// accomplished via panic!() or abort(). -/// -/// 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! -/// -/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or -/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather -/// than calling these methods directly, the user should register implementors as listeners to the -/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify -/// all registered listeners in one go. -pub trait ManyChannelMonitor: Send + Sync { - /// 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 - /// callbacks with the funding transaction, or any spends of it. - /// - /// Further, the implementer must also ensure that each output returned in - /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about - /// any spends of any of the outputs. - /// - /// 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_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; - - /// Updates 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 - /// callbacks with the funding transaction, or any spends of it. - /// - /// Further, the implementer must also ensure that each output returned in - /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about - /// any spends of any of the outputs. - /// - /// Any spends of outputs which should have been registered which aren't passed to - /// ChannelMonitors via block_connected may result in FUNDS LOSS. - fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>; - - /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated - /// with success or failure. - /// - /// You should probably just call through to - /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return - /// the full list. - fn get_and_clear_pending_htlcs_updated(&self) -> Vec; -} - /// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a /// watchtower or watch our own channels. /// @@ -226,10 +186,8 @@ pub struct SimpleManyChannelMonitor>>, - #[cfg(not(test))] - monitors: Mutex>>, chain_monitor: C, broadcaster: T, logger: L, @@ -243,8 +201,8 @@ impl return Err(MonitorUpdateError("Channel monitor for given key is already present")), hash_map::Entry::Vacant(e) => e, }; - 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); + { + let funding_txo = monitor.get_funding_txo(); + log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(funding_txo.0.to_channel_id()[..])); + self.chain_monitor.install_watch_tx(&funding_txo.0.txid, &funding_txo.1); + self.chain_monitor.install_watch_outpoint((funding_txo.0.txid, funding_txo.0.index as u32), &funding_txo.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); + } } } entry.insert(monitor); @@ -320,12 +281,14 @@ impl ManyChannelMonitor for SimpleManyChannelMonitor +impl ManyChannelMonitor for SimpleManyChannelMonitor where T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, C::Target: ChainWatchInterface, { + type Keys = ChanSigner; + fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { match self.add_monitor_by_key(funding_txo, monitor) { Ok(_) => Ok(()), @@ -340,12 +303,12 @@ impl Vec { - let mut pending_htlcs_updated = Vec::new(); + fn get_and_clear_pending_monitor_events(&self) -> Vec { + let mut pending_monitor_events = Vec::new(); for chan in self.monitors.lock().unwrap().values_mut() { - pending_htlcs_updated.append(&mut chan.get_and_clear_pending_htlcs_updated()); + pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events()); } - pending_htlcs_updated + pending_monitor_events } } @@ -355,7 +318,7 @@ impl Vec { + fn get_and_clear_pending_events(&self) -> Vec { let mut pending_events = Vec::new(); for chan in self.monitors.lock().unwrap().values_mut() { pending_events.append(&mut chan.get_and_clear_pending_events()); @@ -424,7 +387,7 @@ struct LocalSignedTx { b_htlc_key: PublicKey, delayed_payment_key: PublicKey, per_commitment_point: PublicKey, - feerate_per_kw: u64, + feerate_per_kw: u32, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, } @@ -777,7 +740,7 @@ impl Readable for ChannelMonitorUpdateStep { /// information and are actively monitoring the chain. /// /// Pending Events or updated HTLCs which have not yet been read out by -/// get_and_clear_pending_htlcs_updated or get_and_clear_pending_events are serialized to disk and +/// get_and_clear_pending_monitor_events or get_and_clear_pending_events are serialized to disk and /// reloaded at deserialize-time. Thus, you must ensure that, when handling events, all events /// gotten are fully handled before re-serializing the new state. pub struct ChannelMonitor { @@ -832,8 +795,8 @@ pub struct ChannelMonitor { payment_preimages: HashMap, - pending_htlcs_updated: Vec, - pending_events: Vec, + pending_monitor_events: Vec, + pending_events: Vec, // Used to track onchain events, i.e transactions parts of channels confirmed on chain, on which // we have to take actions once they reach enough confs. Key is a block height timer, i.e we enforce @@ -866,10 +829,74 @@ pub struct ChannelMonitor { // (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: BlockHash, + last_block_hash: BlockHash, secp_ctx: Secp256k1, //TODO: dedup this a bit... } +/// 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 +/// server(s). +/// +/// In general, you must always have at least one local copy in memory, which must never fail to +/// update (as it is responsible for broadcasting the latest state in case the channel is closed), +/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails +/// to update (eg out-of-memory or some other condition), you must immediately shut down without +/// taking any further action such as writing the current state to disk. This should likely be +/// accomplished via panic!() or abort(). +/// +/// 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! +/// +/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or +/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather +/// than calling these methods directly, the user should register implementors as listeners to the +/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify +/// all registered listeners in one go. +pub trait ManyChannelMonitor: Send + Sync { + /// The concrete type which signs for transactions and provides access to our channel public + /// keys. + type Keys: ChannelKeys; + + /// 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 + /// callbacks with the funding transaction, or any spends of it. + /// + /// Further, the implementer must also ensure that each output returned in + /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about + /// any spends of any of the outputs. + /// + /// 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_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; + + /// Updates 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 + /// callbacks with the funding transaction, or any spends of it. + /// + /// Further, the implementer must also ensure that each output returned in + /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about + /// any spends of any of the outputs. + /// + /// Any spends of outputs which should have been registered which aren't passed to + /// ChannelMonitors via block_connected may result in FUNDS LOSS. + fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>; + + /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated + /// with success or failure. + /// + /// You should probably just call through to + /// ChannelMonitor::get_and_clear_pending_monitor_events() for each ChannelMonitor and return + /// the full list. + fn get_and_clear_pending_monitor_events(&self) -> Vec; +} + #[cfg(any(test, feature = "fuzztarget"))] /// Used only in testing and fuzztarget to check serialization roundtrips don't change the /// underlying object @@ -898,7 +925,7 @@ impl PartialEq for ChannelMonitor { self.current_local_commitment_number != other.current_local_commitment_number || self.current_local_commitment_tx != other.current_local_commitment_tx || self.payment_preimages != other.payment_preimages || - self.pending_htlcs_updated != other.pending_htlcs_updated || + self.pending_monitor_events != other.pending_monitor_events || self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf || self.outputs_to_watch != other.outputs_to_watch || @@ -920,7 +947,7 @@ impl ChannelMonitor { /// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the /// returned block hash and the the current chain and then reconnecting blocks to get to the /// best chain) upon deserializing the object! - pub fn write_for_disk(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + pub fn write_for_disk(&self, writer: &mut W) -> Result<(), Error> { //TODO: We still write out all the serialization here manually instead of using the fancy //serialization framework we have, we should migrate things over to it. writer.write_all(&[SERIALIZATION_VERSION; 1])?; @@ -1022,7 +1049,7 @@ impl ChannelMonitor { writer.write_all(&$local_tx.delayed_payment_key.serialize())?; writer.write_all(&$local_tx.per_commitment_point.serialize())?; - writer.write_all(&byte_utils::be64_to_array($local_tx.feerate_per_kw))?; + writer.write_all(&byte_utils::be32_to_array($local_tx.feerate_per_kw))?; writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_outputs.len() as u64))?; for &(ref htlc_output, ref sig, ref htlc_source) in $local_tx.htlc_outputs.iter() { serialize_htlc_in_commitment!(htlc_output); @@ -1054,9 +1081,15 @@ impl ChannelMonitor { writer.write_all(&payment_preimage.0[..])?; } - writer.write_all(&byte_utils::be64_to_array(self.pending_htlcs_updated.len() as u64))?; - for data in self.pending_htlcs_updated.iter() { - data.write(writer)?; + writer.write_all(&byte_utils::be64_to_array(self.pending_monitor_events.len() as u64))?; + for event in self.pending_monitor_events.iter() { + match event { + MonitorEvent::HTLCEvent(upd) => { + 0u8.write(writer)?; + upd.write(writer)?; + }, + MonitorEvent::CommitmentTxBroadcasted(_) => 1u8.write(writer)? + } } writer.write_all(&byte_utils::be64_to_array(self.pending_events.len() as u64))?; @@ -1171,7 +1204,7 @@ impl ChannelMonitor { current_local_commitment_number: 0xffff_ffff_ffff - ((((local_tx_sequence & 0xffffff) << 3*8) | (local_tx_locktime as u64 & 0xffffff)) ^ commitment_transaction_number_obscure_factor), payment_preimages: HashMap::new(), - pending_htlcs_updated: Vec::new(), + pending_monitor_events: Vec::new(), pending_events: Vec::new(), onchain_events_waiting_threshold_conf: HashMap::new(), @@ -1335,27 +1368,7 @@ impl ChannelMonitor { for tx in self.get_latest_local_commitment_txn(logger).iter() { broadcaster.broadcast_transaction(tx); } - } - - /// Used in Channel to cheat wrt the update_ids since it plays games, will be removed soon! - pub(super) fn update_monitor_ooo(&mut self, mut updates: ChannelMonitorUpdate, logger: &L) -> Result<(), MonitorUpdateError> where L::Target: Logger { - for update in updates.updates.drain(..) { - match update { - ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, htlc_outputs } => { - if self.lockdown_from_offchain { panic!(); } - self.provide_latest_local_commitment_tx_info(commitment_tx, htlc_outputs)? - }, - ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } => - self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point, logger), - ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => - self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage), - ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => - self.provide_secret(idx, secret)?, - ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {}, - } - } - self.latest_update_id = updates.update_id; - Ok(()) + self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0)); } /// Updates a ChannelMonitor on the basis of some new information provided by the Channel @@ -1402,8 +1415,8 @@ impl ChannelMonitor { } /// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for. - pub fn get_funding_txo(&self) -> OutPoint { - self.funding_info.0 + pub fn get_funding_txo(&self) -> &(OutPoint, Script) { + &self.funding_info } /// Gets a list of txids, with their output scripts (in the order they appear in the @@ -1427,10 +1440,10 @@ impl ChannelMonitor { } /// Get the list of HTLCs who's status has been updated on chain. This should be called by - /// ChannelManager via ManyChannelMonitor::get_and_clear_pending_htlcs_updated(). - pub fn get_and_clear_pending_htlcs_updated(&mut self) -> Vec { + /// ChannelManager via ManyChannelMonitor::get_and_clear_pending_monitor_events(). + pub fn get_and_clear_pending_monitor_events(&mut self) -> Vec { let mut ret = Vec::new(); - mem::swap(&mut ret, &mut self.pending_htlcs_updated); + mem::swap(&mut ret, &mut self.pending_monitor_events); ret } @@ -1440,7 +1453,7 @@ impl ChannelMonitor { /// This is called by ManyChannelMonitor::get_and_clear_pending_events() and is equivalent to /// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do /// no internal locking in ChannelMonitors. - pub fn get_and_clear_pending_events(&mut self) -> Vec { + pub fn get_and_clear_pending_events(&mut self) -> Vec { let mut ret = Vec::new(); mem::swap(&mut ret, &mut self.pending_events); ret @@ -1635,7 +1648,7 @@ impl ChannelMonitor { self.remote_payment_script = { // Note that the Network here is ignored as we immediately drop the address for the // script_pubkey version - let payment_hash160 = WPubkeyHash::hash(&PublicKey::from_secret_key(&self.secp_ctx, &self.keys.payment_key()).serialize()); + let payment_hash160 = WPubkeyHash::hash(&self.keys.pubkeys().payment_point.serialize()); Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script() }; @@ -1831,7 +1844,7 @@ impl ChannelMonitor { /// Unsafe test-only version of get_latest_local_commitment_txn used by our test framework /// to bypass LocalCommitmentTransaction state update lockdown after signature and generate /// revoked commitment transaction. - #[cfg(test)] + #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] pub fn unsafe_get_latest_local_commitment_txn(&mut self, logger: &L) -> Vec where L::Target: Logger { log_trace!(logger, "Getting signed copy of latest local commitment transaction!"); if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(&self.funding_redeemscript) { @@ -1922,7 +1935,9 @@ impl ChannelMonitor { claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { funding_redeemscript: self.funding_redeemscript.clone() }}); } if should_broadcast { + self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0)); if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(&self.funding_redeemscript) { + self.local_tx_signed = true; let (mut new_outpoints, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, &self.current_local_commitment_tx); if !new_outputs.is_empty() { watch_outputs.push((self.current_local_commitment_tx.txid.clone(), new_outputs)); @@ -1935,21 +1950,22 @@ impl ChannelMonitor { match ev { OnchainEvent::HTLCUpdate { htlc_update } => { log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0)); - self.pending_htlcs_updated.push(HTLCUpdate { + self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { payment_hash: htlc_update.1, payment_preimage: None, source: htlc_update.0, - }); + })); }, OnchainEvent::MaturingOutput { descriptor } => { log_trace!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); - self.pending_events.push(events::Event::SpendableOutputs { + self.pending_events.push(Event::SpendableOutputs { outputs: vec![descriptor] }); } } } } + self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger); self.last_block_hash = block_hash.clone(); @@ -1977,7 +1993,7 @@ impl ChannelMonitor { self.last_block_hash = block_hash.clone(); } - pub(super) fn would_broadcast_at_height(&self, height: u32, logger: &L) -> bool where L::Target: Logger { + fn would_broadcast_at_height(&self, height: u32, logger: &L) -> bool where L::Target: Logger { // We need to consider all HTLCs which are: // * in any unrevoked remote commitment transaction, as they could broadcast said // transactions and we'd end up in a race, or @@ -2135,22 +2151,26 @@ impl ChannelMonitor { if let Some((source, payment_hash)) = payment_data { let mut payment_preimage = PaymentPreimage([0; 32]); if accepted_preimage_claim { - if !self.pending_htlcs_updated.iter().any(|update| update.source == source) { + if !self.pending_monitor_events.iter().any( + |update| if let &MonitorEvent::HTLCEvent(ref upd) = update { upd.source == source } else { false }) { payment_preimage.0.copy_from_slice(&input.witness[3]); - self.pending_htlcs_updated.push(HTLCUpdate { + self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { source, payment_preimage: Some(payment_preimage), payment_hash - }); + })); } } else if offered_preimage_claim { - if !self.pending_htlcs_updated.iter().any(|update| update.source == source) { + if !self.pending_monitor_events.iter().any( + |update| if let &MonitorEvent::HTLCEvent(ref upd) = update { + upd.source == source + } else { false }) { payment_preimage.0.copy_from_slice(&input.witness[1]); - self.pending_htlcs_updated.push(HTLCUpdate { + self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { source, payment_preimage: Some(payment_preimage), payment_hash - }); + })); } } else { log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), height + ANTI_REORG_DELAY - 1); @@ -2180,16 +2200,30 @@ impl ChannelMonitor { fn is_paying_spendable_output(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger { let mut spendable_output = None; for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us + if i > ::std::u16::MAX as usize { + // While it is possible that an output exists on chain which is greater than the + // 2^16th output in a given transaction, this is only possible if the output is not + // in a lightning transaction and was instead placed there by some third party who + // wishes to give us money for no reason. + // Namely, any lightning transactions which we pre-sign will never have anywhere + // near 2^16 outputs both because such transactions must have ~2^16 outputs who's + // scripts are not longer than one byte in length and because they are inherently + // non-standard due to their size. + // Thus, it is completely safe to ignore such outputs, and while it may result in + // us ignoring non-lightning fund to us, that is only possible if someone fills + // nearly a full block with garbage just to hit this case. + continue; + } if outp.script_pubkey == self.destination_script { spendable_output = Some(SpendableOutputDescriptor::StaticOutput { - outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, + outpoint: OutPoint { txid: tx.txid(), index: i as u16 }, output: outp.clone(), }); break; } else if let Some(ref broadcasted_local_revokable_script) = self.broadcasted_local_revokable_script { if broadcasted_local_revokable_script.0 == outp.script_pubkey { spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WSH { - outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, + outpoint: OutPoint { txid: tx.txid(), index: i as u16 }, per_commitment_point: broadcasted_local_revokable_script.1, to_self_delay: self.on_local_tx_csv, output: outp.clone(), @@ -2200,14 +2234,14 @@ impl ChannelMonitor { } } else if self.remote_payment_script == outp.script_pubkey { spendable_output = Some(SpendableOutputDescriptor::StaticOutputRemotePayment { - outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, + outpoint: OutPoint { txid: tx.txid(), index: i as u16 }, output: outp.clone(), key_derivation_params: self.keys.key_derivation_params(), }); break; } else if outp.script_pubkey == self.shutdown_script { spendable_output = Some(SpendableOutputDescriptor::StaticOutput { - outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 }, + outpoint: OutPoint { txid: tx.txid(), index: i as u16 }, output: outp.clone(), }); } @@ -2361,7 +2395,7 @@ impl Readable for (BlockHash, ChannelMonitor let b_htlc_key = Readable::read(reader)?; let delayed_payment_key = Readable::read(reader)?; let per_commitment_point = Readable::read(reader)?; - let feerate_per_kw: u64 = Readable::read(reader)?; + let feerate_per_kw: u32 = Readable::read(reader)?; let htlcs_len: u64 = Readable::read(reader)?; let mut htlcs = Vec::with_capacity(cmp::min(htlcs_len as usize, MAX_ALLOC_SIZE / 128)); @@ -2406,14 +2440,19 @@ impl Readable for (BlockHash, ChannelMonitor } } - let pending_htlcs_updated_len: u64 = Readable::read(reader)?; - let mut pending_htlcs_updated = Vec::with_capacity(cmp::min(pending_htlcs_updated_len as usize, MAX_ALLOC_SIZE / (32 + 8*3))); - for _ in 0..pending_htlcs_updated_len { - pending_htlcs_updated.push(Readable::read(reader)?); + let pending_monitor_events_len: u64 = Readable::read(reader)?; + let mut pending_monitor_events = Vec::with_capacity(cmp::min(pending_monitor_events_len as usize, MAX_ALLOC_SIZE / (32 + 8*3))); + for _ in 0..pending_monitor_events_len { + let ev = match ::read(reader)? { + 0 => MonitorEvent::HTLCEvent(Readable::read(reader)?), + 1 => MonitorEvent::CommitmentTxBroadcasted(funding_info.0), + _ => return Err(DecodeError::InvalidValue) + }; + pending_monitor_events.push(ev); } let pending_events_len: u64 = Readable::read(reader)?; - let mut pending_events = Vec::with_capacity(cmp::min(pending_events_len as usize, MAX_ALLOC_SIZE / mem::size_of::())); + let mut pending_events = Vec::with_capacity(cmp::min(pending_events_len as usize, MAX_ALLOC_SIZE / mem::size_of::())); for _ in 0..pending_events_len { if let Some(event) = MaybeReadable::read(reader)? { pending_events.push(event); @@ -2500,7 +2539,7 @@ impl Readable for (BlockHash, ChannelMonitor current_local_commitment_number, payment_preimages, - pending_htlcs_updated, + pending_monitor_events, pending_events, onchain_events_waiting_threshold_conf, @@ -2538,7 +2577,6 @@ mod tests { use util::test_utils::TestLogger; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; - use rand::{thread_rng,Rng}; use std::sync::Arc; use chain::keysinterface::InMemoryChannelKeys; @@ -2552,10 +2590,8 @@ mod tests { let mut preimages = Vec::new(); { - let mut rng = thread_rng(); - for _ in 0..20 { - let mut preimage = PaymentPreimage([0; 32]); - rng.fill_bytes(&mut preimage.0[..]); + for i in 0..20 { + let preimage = PaymentPreimage([i; 32]); let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner()); preimages.push((preimage, hash)); }