Avoid claiming remote received HTLCs with preimage
[rust-lightning] / src / ln / channelmonitor.rs
index 4d54b6412f1050b52cae8db2b3a28c72297bee0a..9deb11073ffc31273d233277070f528c4eca478f 100644 (file)
@@ -488,13 +488,13 @@ macro_rules! subtract_high_prio_fee {
        ($self: ident, $fee_estimator: expr, $value: expr, $predicted_weight: expr, $spent_txid: expr, $used_feerate: expr) => {
                {
                        $used_feerate = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority);
-                       let mut fee = $used_feerate * $predicted_weight / 1000;
+                       let mut fee = $used_feerate * ($predicted_weight as u64) / 1000;
                        if $value <= fee {
                                $used_feerate = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
-                               fee = $used_feerate * $predicted_weight / 1000;
+                               fee = $used_feerate * ($predicted_weight as u64) / 1000;
                                if $value <= fee {
                                        $used_feerate = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
-                                       fee = $used_feerate * $predicted_weight / 1000;
+                                       fee = $used_feerate * ($predicted_weight as u64) / 1000;
                                        if $value <= fee {
                                                log_error!($self, "Failed to generate an on-chain punishment tx spending {} as even low priority fee ({} sat) was more than the entire claim balance ({} sat)",
                                                        $spent_txid, fee, $value);
@@ -602,7 +602,7 @@ impl ChannelMonitor {
                }
        }
 
-       fn get_witnesses_weight(inputs: &[InputDescriptors]) -> u64 {
+       fn get_witnesses_weight(inputs: &[InputDescriptors]) -> usize {
                let mut tx_weight = 2; // count segwit flags
                for inp in inputs {
                        // We use expected weight (and not actual) as signatures and time lock delays may vary
@@ -1643,46 +1643,48 @@ impl ChannelMonitor {
                                                                return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs); // Corrupted per_commitment_data, fuck this user
                                                        }
                                                        if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) {
-                                                               let input = TxIn {
-                                                                       previous_output: BitcoinOutPoint {
-                                                                               txid: commitment_txid,
-                                                                               vout: transaction_output_index,
-                                                                       },
-                                                                       script_sig: Script::new(),
-                                                                       sequence: idx as u32, // reset to 0xfffffffd in sign_input
-                                                                       witness: Vec::new(),
-                                                               };
-                                                               if htlc.cltv_expiry > height + CLTV_SHARED_CLAIM_BUFFER {
-                                                                       inputs.push(input);
-                                                                       inputs_desc.push(if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC });
-                                                                       inputs_info.push((payment_preimage, tx.output[transaction_output_index as usize].value, htlc.cltv_expiry));
-                                                                       total_value += tx.output[transaction_output_index as usize].value;
-                                                               } else {
-                                                                       let mut single_htlc_tx = Transaction {
-                                                                               version: 2,
-                                                                               lock_time: 0,
-                                                                               input: vec![input],
-                                                                               output: vec!(TxOut {
-                                                                                       script_pubkey: self.destination_script.clone(),
-                                                                                       value: htlc.amount_msat / 1000,
-                                                                               }),
+                                                               if htlc.offered {
+                                                                       let input = TxIn {
+                                                                               previous_output: BitcoinOutPoint {
+                                                                                       txid: commitment_txid,
+                                                                                       vout: transaction_output_index,
+                                                                               },
+                                                                               script_sig: Script::new(),
+                                                                               sequence: idx as u32, // reset to 0xfffffffd in sign_input
+                                                                               witness: Vec::new(),
                                                                        };
-                                                                       let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC }]);
-                                                                       let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
-                                                                       let mut used_feerate;
-                                                                       if subtract_high_prio_fee!(self, fee_estimator, single_htlc_tx.output[0].value, predicted_weight, tx.txid(), used_feerate) {
-                                                                               let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
-                                                                               let (redeemscript, htlc_key) = sign_input!(sighash_parts, single_htlc_tx.input[0], htlc.amount_msat / 1000, payment_preimage.0.to_vec());
-                                                                               assert!(predicted_weight >= single_htlc_tx.get_weight());
-                                                                               spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
-                                                                                       outpoint: BitcoinOutPoint { txid: single_htlc_tx.txid(), vout: 0 },
-                                                                                       output: single_htlc_tx.output[0].clone(),
-                                                                               });
-                                                                               match self.our_claim_txn_waiting_first_conf.entry(single_htlc_tx.input[0].previous_output.clone()) {
-                                                                                       hash_map::Entry::Occupied(_) => {},
-                                                                                       hash_map::Entry::Vacant(entry) => { entry.insert((height_timer, TxMaterial::RemoteHTLC { script: redeemscript, key: htlc_key, preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000 }, used_feerate, htlc.cltv_expiry, height)); }
+                                                                       if htlc.cltv_expiry > height + CLTV_SHARED_CLAIM_BUFFER {
+                                                                               inputs.push(input);
+                                                                               inputs_desc.push(if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC });
+                                                                               inputs_info.push((payment_preimage, tx.output[transaction_output_index as usize].value, htlc.cltv_expiry));
+                                                                               total_value += tx.output[transaction_output_index as usize].value;
+                                                                       } else {
+                                                                               let mut single_htlc_tx = Transaction {
+                                                                                       version: 2,
+                                                                                       lock_time: 0,
+                                                                                       input: vec![input],
+                                                                                       output: vec!(TxOut {
+                                                                                               script_pubkey: self.destination_script.clone(),
+                                                                                               value: htlc.amount_msat / 1000,
+                                                                                       }),
+                                                                               };
+                                                                               let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC }]);
+                                                                               let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
+                                                                               let mut used_feerate;
+                                                                               if subtract_high_prio_fee!(self, fee_estimator, single_htlc_tx.output[0].value, predicted_weight, tx.txid(), used_feerate) {
+                                                                                       let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
+                                                                                       let (redeemscript, htlc_key) = sign_input!(sighash_parts, single_htlc_tx.input[0], htlc.amount_msat / 1000, payment_preimage.0.to_vec());
+                                                                                       assert!(predicted_weight >= single_htlc_tx.get_weight());
+                                                                                       spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
+                                                                                               outpoint: BitcoinOutPoint { txid: single_htlc_tx.txid(), vout: 0 },
+                                                                                               output: single_htlc_tx.output[0].clone(),
+                                                                                       });
+                                                                                       match self.our_claim_txn_waiting_first_conf.entry(single_htlc_tx.input[0].previous_output.clone()) {
+                                                                                               hash_map::Entry::Occupied(_) => {},
+                                                                                               hash_map::Entry::Vacant(entry) => { entry.insert((height_timer, TxMaterial::RemoteHTLC { script: redeemscript, key: htlc_key, preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000 }, used_feerate, htlc.cltv_expiry, height)); }
+                                                                                       }
+                                                                                       txn_to_broadcast.push(single_htlc_tx);
                                                                                }
-                                                                               txn_to_broadcast.push(single_htlc_tx);
                                                                        }
                                                                }
                                                        }
@@ -3307,7 +3309,7 @@ mod tests {
                let secp_ctx = Secp256k1::new();
                let privkey = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
                let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey);
-               let mut sum_actual_sigs: u64 = 0;
+               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) => {
@@ -3323,7 +3325,7 @@ mod tests {
                                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() as u64;
+                               sum_actual_sigs += $input.witness[0].len();
                                if *$input_type == InputDescriptors::RevokedOutput {
                                        $input.witness.push(vec!(1));
                                } else if *$input_type == InputDescriptors::RevokedOfferedHTLC || *$input_type == InputDescriptors::RevokedReceivedHTLC {
@@ -3366,7 +3368,7 @@ mod tests {
                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);
                }
-               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
 
                // Claim tx with 1 offered HTLCs, 3 received HTLCs
                claim_tx.input.clear();
@@ -3388,7 +3390,7 @@ mod tests {
                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);
                }
-               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]),  claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_des.len() - sum_actual_sigs));
 
                // Justice tx with 1 revoked HTLC-Success tx output
                claim_tx.input.clear();
@@ -3408,7 +3410,7 @@ mod tests {
                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);
                }
-               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() as u64 - sum_actual_sigs));
+               assert_eq!(base_weight + ChannelMonitor::get_witnesses_weight(&inputs_des[..]), claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_des.len() - sum_actual_sigs));
        }
 
        // Further testing is done in the ChannelManager integration tests.