Make `get_outputs_to_watch` return a `Vec` instead of a `HashMap`
[rust-lightning] / lightning / src / chain / channelmonitor.rs
index 034854810c6c0c885364091bb2b4ce0d96ca62e5..c2c791c4b172b8335c43117ff191e93320c3cddc 100644 (file)
@@ -45,6 +45,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;
@@ -620,7 +621,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 +981,8 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                          channel_parameters: &ChannelTransactionParameters,
                          funding_redeemscript: Script, channel_value_satoshis: u64,
                          commitment_transaction_number_obscure_factor: u64,
-                         initial_holder_commitment_tx: HolderCommitmentTransaction) -> ChannelMonitor<Signer> {
+                         initial_holder_commitment_tx: HolderCommitmentTransaction,
+                         last_block_hash: BlockHash) -> ChannelMonitor<Signer> {
 
                assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
                let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize());
@@ -1067,7 +1069,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                                lockdown_from_offchain: false,
                                holder_tx_signed: false,
 
-                               last_block_hash: Default::default(),
+                               last_block_hash,
                                secp_ctx,
                        }),
                }
@@ -1164,10 +1166,23 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
 
        /// 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<Txid, Vec<(u32, Script)>> {
-               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<F: Deref>(&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
@@ -2089,8 +2104,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                      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 +2114,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 
                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
@@ -2789,6 +2803,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> 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};
@@ -2798,6 +2813,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;
@@ -2897,12 +2913,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();