Use rust-bitcoin's new SigHashCache instead of SignatureHashComp's
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index b08bfddbfce7c27a02e70b4c9d05273a81c74c68..4ba7eb2d2d00e1f6b5ce3b0dad168d8de436c594 100644 (file)
@@ -26,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;
@@ -47,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.
@@ -201,7 +202,7 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync
         C::Target: ChainWatchInterface,
 {
        fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[usize]) {
-               let block_hash = header.bitcoin_hash();
+               let block_hash = header.block_hash();
                {
                        let mut monitors = self.monitors.lock().unwrap();
                        for monitor in monitors.values_mut() {
@@ -217,7 +218,7 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync
        }
 
        fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) {
-               let block_hash = header.bitcoin_hash();
+               let block_hash = header.block_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, &*self.logger);
@@ -317,7 +318,7 @@ impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: De
              L::Target: Logger,
         C::Target: ChainWatchInterface,
 {
-       fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
+       fn get_and_clear_pending_events(&self) -> Vec<Event> {
                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());
@@ -795,7 +796,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
        payment_preimages: HashMap<PaymentHash, PaymentPreimage>,
 
        pending_monitor_events: Vec<MonitorEvent>,
-       pending_events: Vec<events::Event>,
+       pending_events: Vec<Event>,
 
        // 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
@@ -828,7 +829,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
        // (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<secp256k1::All>, //TODO: dedup this a bit...
 }
 
@@ -946,7 +947,7 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
        /// 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<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+       pub fn write_for_disk<W: Writer>(&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])?;
@@ -1370,27 +1371,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0));
        }
 
-       /// Used in Channel to cheat wrt the update_ids since it plays games, will be removed soon!
-       pub(super) fn update_monitor_ooo<L: Deref>(&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(())
-       }
-
        /// Updates a ChannelMonitor on the basis of some new information provided by the Channel
        /// itself.
        ///
@@ -1473,7 +1453,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        /// 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<events::Event> {
+       pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
                let mut ret = Vec::new();
                mem::swap(&mut ret, &mut self.pending_events);
                ret
@@ -1978,7 +1958,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                        },
                                        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]
                                                });
                                        }
@@ -2220,16 +2200,30 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        fn is_paying_spendable_output<L: Deref>(&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(),
@@ -2240,14 +2234,14 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                }
                        } 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(),
                                });
                        }
@@ -2458,7 +2452,7 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for (BlockHash, ChannelMonitor
                }
 
                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::<events::Event>()));
+               let mut pending_events = Vec::with_capacity(cmp::min(pending_events_len as usize, MAX_ALLOC_SIZE / mem::size_of::<Event>()));
                for _ in 0..pending_events_len {
                        if let Some(event) = MaybeReadable::read(reader)? {
                                pending_events.push(event);
@@ -2711,33 +2705,33 @@ mod tests {
                let mut sum_actual_sigs = 0;
 
                macro_rules! sign_input {
-                       ($sighash_parts: expr, $input: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
+                       ($sighash_parts: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
                                let htlc = HTLCOutputInCommitment {
                                        offered: if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::OfferedHTLC { true } else { false },
                                        amount_msat: 0,
                                        cltv_expiry: 2 << 16,
                                        payment_hash: PaymentHash([1; 32]),
-                                       transaction_output_index: Some($idx),
+                                       transaction_output_index: Some($idx as u32),
                                };
                                let redeem_script = if *$input_type == InputDescriptors::RevokedOutput { chan_utils::get_revokeable_redeemscript(&pubkey, 256, &pubkey) } else { chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &pubkey, &pubkey, &pubkey) };
-                               let sighash = hash_to_message!(&$sighash_parts.sighash_all(&$input, &redeem_script, $amount)[..]);
+                               let sighash = hash_to_message!(&$sighash_parts.signature_hash($idx, &redeem_script, $amount, SigHashType::All)[..]);
                                let sig = secp_ctx.sign(&sighash, &privkey);
-                               $input.witness.push(sig.serialize_der().to_vec());
-                               $input.witness[0].push(SigHashType::All as u8);
-                               sum_actual_sigs += $input.witness[0].len();
+                               $sighash_parts.access_witness($idx).push(sig.serialize_der().to_vec());
+                               $sighash_parts.access_witness($idx)[0].push(SigHashType::All as u8);
+                               sum_actual_sigs += $sighash_parts.access_witness($idx)[0].len();
                                if *$input_type == InputDescriptors::RevokedOutput {
-                                       $input.witness.push(vec!(1));
+                                       $sighash_parts.access_witness($idx).push(vec!(1));
                                } else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
-                                       $input.witness.push(pubkey.clone().serialize().to_vec());
+                                       $sighash_parts.access_witness($idx).push(pubkey.clone().serialize().to_vec());
                                } else if *$input_type == InputDescriptors::ReceivedHTLC {
-                                       $input.witness.push(vec![0]);
+                                       $sighash_parts.access_witness($idx).push(vec![0]);
                                } else {
-                                       $input.witness.push(PaymentPreimage([1; 32]).0.to_vec());
+                                       $sighash_parts.access_witness($idx).push(PaymentPreimage([1; 32]).0.to_vec());
                                }
-                               $input.witness.push(redeem_script.into_bytes());
-                               println!("witness[0] {}", $input.witness[0].len());
-                               println!("witness[1] {}", $input.witness[1].len());
-                               println!("witness[2] {}", $input.witness[2].len());
+                               $sighash_parts.access_witness($idx).push(redeem_script.into_bytes());
+                               println!("witness[0] {}", $sighash_parts.access_witness($idx)[0].len());
+                               println!("witness[1] {}", $sighash_parts.access_witness($idx)[1].len());
+                               println!("witness[2] {}", $sighash_parts.access_witness($idx)[2].len());
                        }
                }
 
@@ -2762,10 +2756,12 @@ mod tests {
                        value: 0,
                });
                let base_weight = claim_tx.get_weight();
-               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
                let inputs_des = vec![InputDescriptors::RevokedOutput, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedOfferedHTLC, InputDescriptors::RevokedReceivedHTLC];
-               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
-                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               {
+                       let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+                       for (idx, inp) in inputs_des.iter().enumerate() {
+                               sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                       }
                }
                assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
 
@@ -2784,10 +2780,12 @@ mod tests {
                        });
                }
                let base_weight = claim_tx.get_weight();
-               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
                let inputs_des = vec![InputDescriptors::OfferedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC, InputDescriptors::ReceivedHTLC];
-               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
-                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               {
+                       let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+                       for (idx, inp) in inputs_des.iter().enumerate() {
+                               sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                       }
                }
                assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
 
@@ -2804,10 +2802,12 @@ mod tests {
                        witness: Vec::new(),
                });
                let base_weight = claim_tx.get_weight();
-               let sighash_parts = bip143::SighashComponents::new(&claim_tx);
                let inputs_des = vec![InputDescriptors::RevokedOutput];
-               for (idx, inp) in claim_tx.input.iter_mut().zip(inputs_des.iter()).enumerate() {
-                       sign_input!(sighash_parts, inp.0, idx as u32, 0, inp.1, sum_actual_sigs);
+               {
+                       let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+                       for (idx, inp) in inputs_des.iter().enumerate() {
+                               sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs);
+                       }
                }
                assert_eq!(base_weight + OnchainTxHandler::<InMemoryChannelKeys>::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() - sum_actual_sigs));
        }