Merge pull request #535 from TheBlueMatt/2020-03-462-nits
[rust-lightning] / lightning / src / ln / channelmonitor.rs
index a8fdb32aa3f7c1cda9ac20299cc48f839e4251be..205f4b011ac0fb32d62304f5bf1e3ceadbbf2ca1 100644 (file)
@@ -451,21 +451,21 @@ struct LocalSignedTx {
 #[derive(Clone, PartialEq)]
 pub(crate) enum InputMaterial {
        Revoked {
-               script: Script,
+               witness_script: Script,
                pubkey: Option<PublicKey>,
                key: SecretKey,
                is_htlc: bool,
                amount: u64,
        },
        RemoteHTLC {
-               script: Script,
+               witness_script: Script,
                key: SecretKey,
                preimage: Option<PaymentPreimage>,
                amount: u64,
                locktime: u32,
        },
        LocalHTLC {
-               script: Script,
+               witness_script: Script,
                sigs: (Signature, Signature),
                preimage: Option<PaymentPreimage>,
                amount: u64,
@@ -475,25 +475,25 @@ pub(crate) enum InputMaterial {
 impl Writeable for InputMaterial  {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
                match self {
-                       &InputMaterial::Revoked { ref script, ref pubkey, ref key, ref is_htlc, ref amount} => {
+                       &InputMaterial::Revoked { ref witness_script, ref pubkey, ref key, ref is_htlc, ref amount} => {
                                writer.write_all(&[0; 1])?;
-                               script.write(writer)?;
+                               witness_script.write(writer)?;
                                pubkey.write(writer)?;
                                writer.write_all(&key[..])?;
                                is_htlc.write(writer)?;
                                writer.write_all(&byte_utils::be64_to_array(*amount))?;
                        },
-                       &InputMaterial::RemoteHTLC { ref script, ref key, ref preimage, ref amount, ref locktime } => {
+                       &InputMaterial::RemoteHTLC { ref witness_script, ref key, ref preimage, ref amount, ref locktime } => {
                                writer.write_all(&[1; 1])?;
-                               script.write(writer)?;
+                               witness_script.write(writer)?;
                                key.write(writer)?;
                                preimage.write(writer)?;
                                writer.write_all(&byte_utils::be64_to_array(*amount))?;
                                writer.write_all(&byte_utils::be32_to_array(*locktime))?;
                        },
-                       &InputMaterial::LocalHTLC { ref script, ref sigs, ref preimage, ref amount } => {
+                       &InputMaterial::LocalHTLC { ref witness_script, ref sigs, ref preimage, ref amount } => {
                                writer.write_all(&[2; 1])?;
-                               script.write(writer)?;
+                               witness_script.write(writer)?;
                                sigs.0.write(writer)?;
                                sigs.1.write(writer)?;
                                preimage.write(writer)?;
@@ -508,13 +508,13 @@ impl Readable for InputMaterial {
        fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
                let input_material = match <u8 as Readable>::read(reader)? {
                        0 => {
-                               let script = Readable::read(reader)?;
+                               let witness_script = Readable::read(reader)?;
                                let pubkey = Readable::read(reader)?;
                                let key = Readable::read(reader)?;
                                let is_htlc = Readable::read(reader)?;
                                let amount = Readable::read(reader)?;
                                InputMaterial::Revoked {
-                                       script,
+                                       witness_script,
                                        pubkey,
                                        key,
                                        is_htlc,
@@ -522,13 +522,13 @@ impl Readable for InputMaterial {
                                }
                        },
                        1 => {
-                               let script = Readable::read(reader)?;
+                               let witness_script = Readable::read(reader)?;
                                let key = Readable::read(reader)?;
                                let preimage = Readable::read(reader)?;
                                let amount = Readable::read(reader)?;
                                let locktime = Readable::read(reader)?;
                                InputMaterial::RemoteHTLC {
-                                       script,
+                                       witness_script,
                                        key,
                                        preimage,
                                        amount,
@@ -536,13 +536,13 @@ impl Readable for InputMaterial {
                                }
                        },
                        2 => {
-                               let script = Readable::read(reader)?;
+                               let witness_script = Readable::read(reader)?;
                                let their_sig = Readable::read(reader)?;
                                let our_sig = Readable::read(reader)?;
                                let preimage = Readable::read(reader)?;
                                let amount = Readable::read(reader)?;
                                InputMaterial::LocalHTLC {
-                                       script,
+                                       witness_script,
                                        sigs: (their_sig, our_sig),
                                        preimage,
                                        amount
@@ -554,6 +554,28 @@ impl Readable for InputMaterial {
        }
 }
 
+/// ClaimRequest is a descriptor structure to communicate between detection
+/// and reaction module. They are generated by ChannelMonitor while parsing
+/// onchain txn leaked from a channel and handed over to OnchainTxHandler which
+/// is responsible for opportunistic aggregation, selecting and enforcing
+/// bumping logic, building and signing transactions.
+pub(crate) struct ClaimRequest {
+       // Block height before which claiming is exclusive to one party,
+       // after reaching it, claiming may be contentious.
+       pub(crate) absolute_timelock: u32,
+       // Timeout tx must have nLocktime set which means aggregating multiple
+       // ones must take the higher nLocktime among them to satisfy all of them.
+       // Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
+       // of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
+       // Do simplify we mark them as non-aggregable.
+       pub(crate) aggregable: bool,
+       // Basic bitcoin outpoint (txid, vout)
+       pub(crate) outpoint: BitcoinOutPoint,
+       // Following outpoint type, set of data needed to generate transaction digest
+       // and satisfy witness program.
+       pub(crate) witness_data: InputMaterial
+}
+
 /// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
 /// once they mature to enough confirmations (ANTI_REORG_DELAY)
 #[derive(Clone, PartialEq)]
@@ -1385,7 +1407,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        /// HTLC-Success/HTLC-Timeout transactions.
        /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
        /// revoked remote commitment tx
-       fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<(u32, bool, BitcoinOutPoint, InputMaterial)>, (Sha256dHash, Vec<TxOut>), Vec<SpendableOutputDescriptor>) {
+       fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Sha256dHash, Vec<TxOut>), Vec<SpendableOutputDescriptor>) {
                // Most secp and related errors trying to create keys means we have no hope of constructing
                // a spend transaction...so we return no transactions to broadcast
                let mut claimable_outpoints = Vec::new();
@@ -1439,7 +1461,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                        // First, process non-htlc outputs (to_local & to_remote)
                        for (idx, outp) in tx.output.iter().enumerate() {
                                if outp.script_pubkey == revokeable_p2wsh {
-                                       claimable_outpoints.push((height + self.our_to_self_delay as u32, true, BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 }, InputMaterial::Revoked { script: revokeable_redeemscript.clone(), pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: false, amount: outp.value }));
+                                       let witness_data = InputMaterial::Revoked { witness_script: revokeable_redeemscript.clone(), pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: false, amount: outp.value };
+                                       claimable_outpoints.push(ClaimRequest { absolute_timelock: height + self.our_to_self_delay as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 }, witness_data});
                                } else if Some(&outp.script_pubkey) == local_payment_p2wpkh.as_ref() {
                                        spendable_outputs.push(SpendableOutputDescriptor::DynamicOutputP2WPKH {
                                                outpoint: BitcoinOutPoint { txid: commitment_txid, vout: idx as u32 },
@@ -1459,7 +1482,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                                                tx.output[transaction_output_index as usize].script_pubkey != expected_script.to_v0_p2wsh() {
                                                        return (claimable_outpoints, (commitment_txid, watch_outputs), spendable_outputs); // Corrupted per_commitment_data, fuck this user
                                                }
-                                               claimable_outpoints.push((htlc.cltv_expiry, true, BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, InputMaterial::Revoked { script: expected_script, pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: true, amount: tx.output[transaction_output_index as usize].value }));
+                                               let witness_data = InputMaterial::Revoked { witness_script: expected_script, pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: true, amount: tx.output[transaction_output_index as usize].value };
+                                               claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable: true, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
                                        }
                                }
                        }
@@ -1622,7 +1646,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                                        let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None };
                                                        let aggregable = if !htlc.offered { false } else { true };
                                                        if preimage.is_some() || !htlc.offered {
-                                                               claimable_outpoints.push((htlc.cltv_expiry, aggregable, BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, InputMaterial::RemoteHTLC { script: expected_script, key: htlc_privkey, preimage, amount: htlc.amount_msat / 1000, locktime: htlc.cltv_expiry }));
+                                                               let witness_data = InputMaterial::RemoteHTLC { witness_script: expected_script, key: htlc_privkey, preimage, amount: htlc.amount_msat / 1000, locktime: htlc.cltv_expiry };
+                                                               claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data });
                                                        }
                                                }
                                        }
@@ -1643,7 +1668,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
        }
 
        /// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
-       fn check_spend_remote_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32) -> Vec<(u32, bool, BitcoinOutPoint, InputMaterial)> {
+       fn check_spend_remote_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32) -> Vec<ClaimRequest> {
                //TODO: send back new outputs to guarantee pending_claim_request consistency
                if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 {
                        return Vec::new()
@@ -1676,7 +1701,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                let htlc_txid = tx.txid(); //TODO: This is gonna be a performance bottleneck for watchtowers!
 
                log_trace!(self, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
-               let claimable_outpoints = vec!((height + self.our_to_self_delay as u32, true, BitcoinOutPoint { txid: htlc_txid, vout: 0}, InputMaterial::Revoked { script: redeemscript, pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: false, amount: tx.output[0].value }));
+               let witness_data = InputMaterial::Revoked { witness_script: redeemscript, pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: false, amount: tx.output[0].value };
+               let claimable_outpoints = vec!(ClaimRequest { absolute_timelock: height + self.our_to_self_delay as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0}, witness_data });
                claimable_outpoints
        }
 
@@ -1723,7 +1749,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
 
                                                        add_dynamic_output!(htlc_timeout_tx, 0);
                                                        let mut per_input_material = HashMap::with_capacity(1);
-                                                       per_input_material.insert(htlc_timeout_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, our_sig), preimage: None, amount: htlc.amount_msat / 1000});
+                                                       per_input_material.insert(htlc_timeout_tx.input[0].previous_output, InputMaterial::LocalHTLC { witness_script: htlc_script, sigs: (*their_sig, our_sig), preimage: None, amount: htlc.amount_msat / 1000});
                                                        //TODO: with option_simplified_commitment track outpoint too
                                                        log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_timeout_tx.input[0].previous_output.vout, htlc_timeout_tx.input[0].previous_output.txid);
                                                        res.push(htlc_timeout_tx);
@@ -1739,7 +1765,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
 
                                                                add_dynamic_output!(htlc_success_tx, 0);
                                                                let mut per_input_material = HashMap::with_capacity(1);
-                                                               per_input_material.insert(htlc_success_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, our_sig), preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000});
+                                                               per_input_material.insert(htlc_success_tx.input[0].previous_output, InputMaterial::LocalHTLC { witness_script: htlc_script, sigs: (*their_sig, our_sig), preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000});
                                                                //TODO: with option_simplified_commitment track outpoint too
                                                                log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_success_tx.input[0].previous_output.vout, htlc_success_tx.input[0].previous_output.txid);
                                                                res.push(htlc_success_tx);
@@ -1984,7 +2010,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                                                watch_outputs.push(new_outputs);
                                                        }
                                                }
-                                               claimable_outpoints.push(new_outpoints);
+                                               claimable_outpoints.append(&mut new_outpoints);
                                        }
                                        if !funding_txo.is_none() && claimable_outpoints.is_empty() {
                                                if let Some(spendable_output) = self.check_spend_closing_transaction(&tx) {
@@ -1994,7 +2020,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                } else {
                                        if let Some(&(commitment_number, _)) = self.remote_commitment_txn_on_chain.get(&prevout.txid) {
                                                let mut new_outpoints = self.check_spend_remote_htlc(&tx, commitment_number, height);
-                                               claimable_outpoints.push(new_outpoints);
+                                               claimable_outpoints.append(&mut new_outpoints);
                                        }
                                }
                        }
@@ -2050,7 +2076,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                }
                        }
                }
-               let mut spendable_output = self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, broadcaster, &*fee_estimator);
+               let mut spendable_output = self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator);
                spendable_outputs.append(&mut spendable_output);
 
                self.last_block_hash = block_hash.clone();