Merge pull request #1503 from valentinewallace/2022-05-onion-msgs
[rust-lightning] / lightning / src / chain / package.rs
index 0d4b4de98cd591d800db077175ad0b03df97faf9..30530303e59b366239e88c96d846f36da77a49ee 100644 (file)
 //! also includes witness weight computation and fee computation methods.
 
 use bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
-use bitcoin::blockdata::transaction::{TxOut,TxIn, Transaction, SigHashType};
+use bitcoin::blockdata::transaction::{TxOut,TxIn, Transaction, EcdsaSighashType};
 use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
 use bitcoin::blockdata::script::Script;
 
 use bitcoin::hash_types::Txid;
 
-use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+use bitcoin::secp256k1::{SecretKey,PublicKey};
 
 use ln::PaymentPreimage;
 use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment};
@@ -36,6 +36,9 @@ use prelude::*;
 use core::cmp;
 use core::mem;
 use core::ops::Deref;
+use bitcoin::Witness;
+
+use super::chaininterface::LowerBoundedFeeEstimator;
 
 const MAX_ALLOC_SIZE: usize = 64*1024;
 
@@ -62,7 +65,7 @@ pub(crate) fn weight_offered_htlc(opt_anchors: bool) -> u64 {
 }
 
 pub(crate) fn weight_received_htlc(opt_anchors: bool) -> u64 {
-       // number_of_witness_elements + sig_length + revocation_sig + pubkey_length + revocationpubkey + witness_script_length + witness_script
+       // number_of_witness_elements + sig_length + counterpartyhtlc_sig + empty_vec_length + empty_vec + witness_script_length + witness_script
        const WEIGHT_RECEIVED_HTLC: u64 = 1 + 1 + 73 + 1 + 1 + 1 + 139;
        const WEIGHT_RECEIVED_HTLC_ANCHORS: u64 = WEIGHT_RECEIVED_HTLC + 3; // + OP_1 + OP_CSV + OP_DROP
        if opt_anchors { WEIGHT_RECEIVED_HTLC_ANCHORS } else { WEIGHT_RECEIVED_HTLC }
@@ -352,8 +355,9 @@ impl PackageSolvingData {
                                        let witness_script = chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, outp.on_counterparty_tx_csv, &chan_keys.broadcaster_delayed_payment_key);
                                        //TODO: should we panic on signer failure ?
                                        if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_output(&bumped_tx, i, outp.amount, &outp.per_commitment_key, &onchain_handler.secp_ctx) {
-                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               let mut ser_sig = sig.serialize_der().to_vec();
+                                               ser_sig.push(EcdsaSighashType::All as u8);
+                                               bumped_tx.input[i].witness.push(ser_sig);
                                                bumped_tx.input[i].witness.push(vec!(1));
                                                bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
                                        } else { return false; }
@@ -364,8 +368,9 @@ impl PackageSolvingData {
                                        let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, onchain_handler.opt_anchors(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
                                        //TODO: should we panic on signer failure ?
                                        if let Ok(sig) = onchain_handler.signer.sign_justice_revoked_htlc(&bumped_tx, i, outp.amount, &outp.per_commitment_key, &outp.htlc, &onchain_handler.secp_ctx) {
-                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               let mut ser_sig = sig.serialize_der().to_vec();
+                                               ser_sig.push(EcdsaSighashType::All as u8);
+                                               bumped_tx.input[i].witness.push(ser_sig);
                                                bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec());
                                                bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
                                        } else { return false; }
@@ -376,8 +381,9 @@ impl PackageSolvingData {
                                        let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&outp.htlc, onchain_handler.opt_anchors(), &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key);
 
                                        if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
-                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               let mut ser_sig = sig.serialize_der().to_vec();
+                                               ser_sig.push(EcdsaSighashType::All as u8);
+                                               bumped_tx.input[i].witness.push(ser_sig);
                                                bumped_tx.input[i].witness.push(outp.preimage.0.to_vec());
                                                bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
                                        }
@@ -389,8 +395,9 @@ impl PackageSolvingData {
 
                                        bumped_tx.lock_time = outp.htlc.cltv_expiry; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation
                                        if let Ok(sig) = onchain_handler.signer.sign_counterparty_htlc_transaction(&bumped_tx, i, &outp.htlc.amount_msat / 1000, &outp.per_commitment_point, &outp.htlc, &onchain_handler.secp_ctx) {
-                                               bumped_tx.input[i].witness.push(sig.serialize_der().to_vec());
-                                               bumped_tx.input[i].witness[0].push(SigHashType::All as u8);
+                                               let mut ser_sig = sig.serialize_der().to_vec();
+                                               ser_sig.push(EcdsaSighashType::All as u8);
+                                               bumped_tx.input[i].witness.push(ser_sig);
                                                // Due to BIP146 (MINIMALIF) this must be a zero-length element to relay.
                                                bumped_tx.input[i].witness.push(vec![]);
                                                bumped_tx.input[i].witness.push(witness_script.clone().into_bytes());
@@ -620,7 +627,7 @@ impl PackageTemplate {
                                                previous_output: *outpoint,
                                                script_sig: Script::new(),
                                                sequence: 0xfffffffd,
-                                               witness: Vec::new(),
+                                               witness: Witness::new(),
                                        });
                                }
                                for (i, (outpoint, out)) in self.inputs.iter().enumerate() {
@@ -660,7 +667,7 @@ impl PackageTemplate {
        /// Returns value in satoshis to be included as package outgoing output amount and feerate
        /// which was used to generate the value. Will not return less than `dust_limit_sats` for the
        /// value.
-       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+       pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
                where F::Target: FeeEstimator,
                      L::Target: Logger,
        {
@@ -767,17 +774,17 @@ impl Readable for PackageTemplate {
 /// If the proposed fee is less than the available spent output's values, we return the proposed
 /// fee and the corresponding updated feerate. If the proposed fee is equal or more than the
 /// available spent output's values, we return nothing
-fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
        where F::Target: FeeEstimator,
              L::Target: Logger,
 {
-       let mut updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64;
+       let mut updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::HighPriority) as u64;
        let mut fee = updated_feerate * (predicted_weight as u64) / 1000;
        if input_amounts <= fee {
-               updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal) as u64;
+               updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Normal) as u64;
                fee = updated_feerate * (predicted_weight as u64) / 1000;
                if input_amounts <= fee {
-                       updated_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u64;
+                       updated_feerate = fee_estimator.bounded_sat_per_1000_weight(ConfirmationTarget::Background) as u64;
                        fee = updated_feerate * (predicted_weight as u64) / 1000;
                        if input_amounts <= fee {
                                log_error!(logger, "Failed to generate an on-chain punishment tx as even low priority fee ({} sat) was more than the entire claim balance ({} sat)",
@@ -803,7 +810,7 @@ fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predic
 /// attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous feerate. We also
 /// verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required adjust
 /// the new fee to meet the RBF policy requirement.
-fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
+fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
        where F::Target: FeeEstimator,
              L::Target: Logger,
 {
@@ -841,7 +848,7 @@ fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64,
 
 #[cfg(test)]
 mod tests {
-       use chain::package::{CounterpartyReceivedHTLCOutput, HolderHTLCOutput, PackageTemplate, PackageSolvingData, RevokedOutput, WEIGHT_REVOKED_OUTPUT};
+       use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderHTLCOutput, PackageTemplate, PackageSolvingData, RevokedOutput, WEIGHT_REVOKED_OUTPUT, weight_offered_htlc, weight_received_htlc};
        use chain::Txid;
        use ln::chan_utils::HTLCOutputInCommitment;
        use ln::{PaymentPreimage, PaymentHash};
@@ -852,7 +859,7 @@ mod tests {
 
        use bitcoin::hashes::hex::FromHex;
 
-       use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+       use bitcoin::secp256k1::{PublicKey,SecretKey};
        use bitcoin::secp256k1::Secp256k1;
 
        macro_rules! dumb_revk_output {
@@ -877,6 +884,19 @@ mod tests {
                }
        }
 
+       macro_rules! dumb_counterparty_offered_output {
+               ($secp_ctx: expr, $amt: expr) => {
+                       {
+                               let dumb_scalar = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
+                               let dumb_point = PublicKey::from_secret_key(&$secp_ctx, &dumb_scalar);
+                               let hash = PaymentHash([1; 32]);
+                               let preimage = PaymentPreimage([2;32]);
+                               let htlc = HTLCOutputInCommitment { offered: false, amount_msat: $amt, cltv_expiry: 1000, payment_hash: hash, transaction_output_index: None };
+                               PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(dumb_point, dumb_point, dumb_point, preimage, htlc))
+                       }
+               }
+       }
+
        macro_rules! dumb_htlc_output {
                () => {
                        {
@@ -1041,13 +1061,32 @@ mod tests {
        fn test_package_weight() {
                let txid = Txid::from_hex("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap();
                let secp_ctx = Secp256k1::new();
-               let revk_outp = dumb_revk_output!(secp_ctx);
 
-               let package = PackageTemplate::build_package(txid, 0, revk_outp, 0, true, 100);
-               // (nVersion (4) + nLocktime (4) + count_tx_in (1) + prevout (36) + sequence (4) + script_length (1) + count_tx_out (1) + value (8) + var_int (1)) * WITNESS_SCALE_FACTOR
-               // + witness marker (2) + WEIGHT_REVOKED_OUTPUT
-               for &opt_anchors in [false, true].iter() {
-                       assert_eq!(package.package_weight(&Script::new(), opt_anchors), (4 + 4 + 1 + 36 + 4 + 1 + 1 + 8 + 1) * WITNESS_SCALE_FACTOR + 2 + WEIGHT_REVOKED_OUTPUT as usize);
+               // (nVersion (4) + nLocktime (4) + count_tx_in (1) + prevout (36) + sequence (4) + script_length (1) + count_tx_out (1) + value (8) + var_int (1)) * WITNESS_SCALE_FACTOR + witness marker (2)
+               let weight_sans_output = (4 + 4 + 1 + 36 + 4 + 1 + 1 + 8 + 1) * WITNESS_SCALE_FACTOR + 2;
+
+               {
+                       let revk_outp = dumb_revk_output!(secp_ctx);
+                       let package = PackageTemplate::build_package(txid, 0, revk_outp, 0, true, 100);
+                       for &opt_anchors in [false, true].iter() {
+                               assert_eq!(package.package_weight(&Script::new(), opt_anchors),  weight_sans_output + WEIGHT_REVOKED_OUTPUT as usize);
+                       }
+               }
+
+               {
+                       let counterparty_outp = dumb_counterparty_output!(secp_ctx, 1_000_000);
+                       let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, true, 100);
+                       for &opt_anchors in [false, true].iter() {
+                               assert_eq!(package.package_weight(&Script::new(), opt_anchors), weight_sans_output + weight_received_htlc(opt_anchors) as usize);
+                       }
+               }
+
+               {
+                       let counterparty_outp = dumb_counterparty_offered_output!(secp_ctx, 1_000_000);
+                       let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, true, 100);
+                       for &opt_anchors in [false, true].iter() {
+                               assert_eq!(package.package_weight(&Script::new(), opt_anchors), weight_sans_output + weight_offered_htlc(opt_anchors) as usize);
+                       }
                }
        }
 }