X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=28b6da4722a7b4e3820541b30c89047d1e8e5cfe;hb=refs%2Fheads%2F2021-03-check-tx;hp=aa9150aec7797027f75e329eeb602d90cb1475a1;hpb=7c8e740b6e82feeb60938083dcf677ea7e21f7bd;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index aa9150ae..28b6da47 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -19,8 +19,6 @@ //! ChannelMonitors should do so). Thus, if you're building rust-lightning into an HSM or other //! security-domain-separated system design, you should consider having multiple paths for //! ChannelMonitors to get out of the HSM and onto monitoring devices. -//! -//! [`chain::Watch`]: ../trait.Watch.html use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::blockdata::transaction::{TxOut,Transaction}; @@ -45,6 +43,7 @@ use chain; use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface}; +use chain::Filter; use util::logger::Logger; use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48}; use util::byte_utils; @@ -74,8 +73,6 @@ pub struct ChannelMonitorUpdate { /// The only instance where update_id values are not strictly increasing is the case where we /// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See /// its docs for more details. - /// - /// [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html pub update_id: u64, } @@ -192,8 +189,6 @@ pub enum MonitorEvent { /// Simple structure sent back by `chain::Watch` when an HTLC from a forward channel is detected on /// chain. Used to update the corresponding HTLC in the backward channel. Failing to pass the /// preimage claim backward will lead to loss of funds. -/// -/// [`chain::Watch`]: ../trait.Watch.html #[derive(Clone, PartialEq)] pub struct HTLCUpdate { pub(crate) payment_hash: PaymentHash, @@ -620,7 +615,7 @@ impl Readable for ChannelMonitorUpdateStep { /// reloaded at deserialize-time. Thus, you must ensure that, when handling events, all events /// gotten are fully handled before re-serializing the new state. /// -/// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which +/// Note that the deserializer is only implemented for (BlockHash, ChannelMonitor), which /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along /// 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 @@ -980,7 +975,8 @@ impl ChannelMonitor { channel_parameters: &ChannelTransactionParameters, funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64, - initial_holder_commitment_tx: HolderCommitmentTransaction) -> ChannelMonitor { + initial_holder_commitment_tx: HolderCommitmentTransaction, + last_block_hash: BlockHash) -> ChannelMonitor { assert!(commitment_transaction_number_obscure_factor <= (1 << 48)); let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize()); @@ -1067,7 +1063,7 @@ impl ChannelMonitor { lockdown_from_offchain: false, holder_tx_signed: false, - last_block_hash: Default::default(), + last_block_hash, secp_ctx, }), } @@ -1164,16 +1160,27 @@ impl ChannelMonitor { /// Gets a list of txids, with their output scripts (in the order they appear in the /// transaction), which we must learn about spends of via block_connected(). - /// - /// (C-not exported) because we have no HashMap bindings - pub fn get_outputs_to_watch(&self) -> HashMap> { - self.inner.lock().unwrap().get_outputs_to_watch().clone() + pub fn get_outputs_to_watch(&self) -> Vec<(Txid, Vec<(u32, Script)>)> { + self.inner.lock().unwrap().get_outputs_to_watch() + .iter().map(|(txid, outputs)| (*txid, outputs.clone())).collect() + } + + /// Loads the funding txo and outputs to watch into the given `chain::Filter` by repeatedly + /// calling `chain::Filter::register_output` and `chain::Filter::register_tx` until all outputs + /// have been registered. + pub fn load_outputs_to_watch(&self, filter: &F) where F::Target: chain::Filter { + let lock = self.inner.lock().unwrap(); + filter.register_tx(&lock.get_funding_txo().0.txid, &lock.get_funding_txo().1); + for (txid, outputs) in lock.get_outputs_to_watch().iter() { + for (index, script_pubkey) in outputs.iter() { + assert!(*index <= u16::max_value() as u32); + filter.register_output(&OutPoint { txid: *txid, index: *index as u16 }, script_pubkey); + } + } } /// Get the list of HTLCs who's status has been updated on chain. This should be called by /// ChannelManager via [`chain::Watch::release_pending_monitor_events`]. - /// - /// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events pub fn get_and_clear_pending_monitor_events(&self) -> Vec { self.inner.lock().unwrap().get_and_clear_pending_monitor_events() } @@ -1494,8 +1501,13 @@ impl ChannelMonitorImpl { self.lockdown_from_offchain = true; if *should_broadcast { self.broadcast_latest_holder_commitment_txn(broadcaster, logger); - } else { + } else if !self.holder_tx_signed { log_error!(logger, "You have a toxic holder commitment transaction avaible in channel monitor, read comment in ChannelMonitor::get_latest_holder_commitment_txn to be informed of manual action to take"); + } else { + // If we generated a MonitorEvent::CommitmentTxBroadcasted, the ChannelManager + // will still give us a ChannelForceClosed event with !should_broadcast, but we + // shouldn't print the scary warning above. + log_info!(logger, "Channel off-chain state closed after we broadcasted our latest commitment transaction."); } } } @@ -2089,8 +2101,7 @@ impl ChannelMonitorImpl { F::Target: FeeEstimator, L::Target: Logger, { - let block_hash = header.block_hash(); - log_trace!(logger, "Block {} at height {} disconnected", block_hash, height); + log_trace!(logger, "Block {} at height {} disconnected", header.block_hash(), height); if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) { //We may discard: @@ -2100,7 +2111,7 @@ impl ChannelMonitorImpl { self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger); - self.last_block_hash = block_hash; + self.last_block_hash = header.prev_blockhash; } /// Filters a block's `txdata` for transactions spending watched outputs or for any child @@ -2436,11 +2447,8 @@ pub trait Persist: Send + Sync { /// stored channel data). Note that you **must** persist every new monitor to /// disk. See the `Persist` trait documentation for more details. /// - /// See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + /// See [`ChannelMonitor::write`] for writing out a `ChannelMonitor`, /// and [`ChannelMonitorUpdateErr`] for requirements when returning errors. - /// - /// [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk - /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html fn persist_new_channel(&self, id: OutPoint, data: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; /// Update one channel's data. The provided `ChannelMonitor` has already @@ -2462,14 +2470,9 @@ pub trait Persist: Send + Sync { /// them in batches. The size of each monitor grows `O(number of state updates)` /// whereas updates are small and `O(1)`. /// - /// See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + /// See [`ChannelMonitor::write`] for writing out a `ChannelMonitor`, /// [`ChannelMonitorUpdate::write`] for writing out an update, and /// [`ChannelMonitorUpdateErr`] for requirements when returning errors. - /// - /// [`ChannelMonitor::update_monitor`]: struct.ChannelMonitor.html#impl-1 - /// [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk - /// [`ChannelMonitorUpdate::write`]: struct.ChannelMonitorUpdate.html#method.write - /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html fn update_persisted_channel(&self, id: OutPoint, update: &ChannelMonitorUpdate, data: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; } @@ -2492,7 +2495,7 @@ where const MAX_ALLOC_SIZE: usize = 64*1024; impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> - for (Option, ChannelMonitor) { + for (BlockHash, ChannelMonitor) { fn read(reader: &mut R, keys_manager: &'a K) -> Result { macro_rules! unwrap_obj { ($key: expr) => { @@ -2735,13 +2738,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes()); - let last_seen_block_hash = if last_block_hash == Default::default() { - None - } else { - Some(last_block_hash) - }; - - Ok((last_seen_block_hash, ChannelMonitor { + Ok((last_block_hash.clone(), ChannelMonitor { inner: Mutex::new(ChannelMonitorImpl { latest_update_id, commitment_transaction_number_obscure_factor, @@ -2795,6 +2792,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> #[cfg(test)] mod tests { + use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType}; @@ -2804,6 +2802,7 @@ mod tests { use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::hex::FromHex; use bitcoin::hash_types::Txid; + use bitcoin::network::constants::Network; use hex; use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; @@ -2903,12 +2902,13 @@ mod tests { }; // Prune with one old state and a holder commitment tx holding a few overlaps with the // old state. + let last_block_hash = genesis_block(Network::Testnet).block_hash(); let monitor = ChannelMonitor::new(Secp256k1::new(), keys, &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(), (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), &channel_parameters, Script::new(), 46, 0, - HolderCommitmentTransaction::dummy()); + HolderCommitmentTransaction::dummy(), last_block_hash); monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); let dummy_txid = dummy_tx.txid();