Store anchors option for supported output types
authorWilmer Paulino <wilmer.paulino@gmail.com>
Wed, 14 Sep 2022 19:35:26 +0000 (12:35 -0700)
committerWilmer Paulino <wilmer.paulino@gmail.com>
Tue, 18 Oct 2022 19:22:28 +0000 (12:22 -0700)
As we integrate the support of anchor outputs, we'll want to know if
each input we're working with came from an anchor outputs channel.
Instead of threading through a `opt_anchors` boolean across several
methods on `PackageSolvingData` and `PackageTemplate`, we decide to
store a reference in each `PackageSolvingData` variant instead that
features a change in behavior between channels with and without anchor
outputs.

lightning/src/chain/channelmonitor.rs
lightning/src/chain/onchaintx.rs
lightning/src/chain/package.rs

index 2c3def4889e1c49d5a777602f5521c80d4f64b2c..ae315f9e628e2f4fb68f8d3b8d5c805b894dcbd3 100644 (file)
@@ -2521,13 +2521,13 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                        CounterpartyOfferedHTLCOutput::build(*per_commitment_point,
                                                                self.counterparty_commitment_params.counterparty_delayed_payment_base_key,
                                                                self.counterparty_commitment_params.counterparty_htlc_base_key,
-                                                               preimage.unwrap(), htlc.clone()))
+                                                               preimage.unwrap(), htlc.clone(), self.onchain_tx_handler.opt_anchors()))
                                        } else {
                                                PackageSolvingData::CounterpartyReceivedHTLCOutput(
                                                        CounterpartyReceivedHTLCOutput::build(*per_commitment_point,
                                                                self.counterparty_commitment_params.counterparty_delayed_payment_base_key,
                                                                self.counterparty_commitment_params.counterparty_htlc_base_key,
-                                                               htlc.clone()))
+                                                               htlc.clone(), self.onchain_tx_handler.opt_anchors()))
                                        };
                                        let aggregation = if !htlc.offered { false } else { true };
                                        let counterparty_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, counterparty_htlc_outp, htlc.cltv_expiry,aggregation, 0);
index f14c983b6d5480d2f2b6a47a75292e1758261d58..0d328075c3bcfd5b9f98eb7bef55998f6a13cb2c 100644 (file)
@@ -388,7 +388,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                // didn't receive confirmation of it before, or not enough reorg-safe depth on top of it).
                let new_timer = Some(cached_request.get_height_timer(cur_height));
                if cached_request.is_malleable() {
-                       let predicted_weight = cached_request.package_weight(&self.destination_script, self.channel_transaction_parameters.opt_anchors.is_some());
+                       let predicted_weight = cached_request.package_weight(&self.destination_script);
                        if let Some((output_value, new_feerate)) =
                                        cached_request.compute_package_output(predicted_weight, self.destination_script.dust_value().to_sat(), fee_estimator, logger) {
                                assert!(new_feerate != 0);
index bc5e997b1d46865121c146049845bc73de1a8def..a2922d27d2914add018053cdcb970c3954b9d982 100644 (file)
@@ -177,23 +177,30 @@ pub(crate) struct CounterpartyOfferedHTLCOutput {
        counterparty_delayed_payment_base_key: PublicKey,
        counterparty_htlc_base_key: PublicKey,
        preimage: PaymentPreimage,
-       htlc: HTLCOutputInCommitment
+       htlc: HTLCOutputInCommitment,
+       opt_anchors: Option<()>,
 }
 
 impl CounterpartyOfferedHTLCOutput {
-       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, preimage: PaymentPreimage, htlc: HTLCOutputInCommitment) -> Self {
+       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, preimage: PaymentPreimage, htlc: HTLCOutputInCommitment, opt_anchors: bool) -> Self {
                CounterpartyOfferedHTLCOutput {
                        per_commitment_point,
                        counterparty_delayed_payment_base_key,
                        counterparty_htlc_base_key,
                        preimage,
-                       htlc
+                       htlc,
+                       opt_anchors: if opt_anchors { Some(()) } else { None },
                }
        }
+
+       fn opt_anchors(&self) -> bool {
+               self.opt_anchors.is_some()
+       }
 }
 
 impl_writeable_tlv_based!(CounterpartyOfferedHTLCOutput, {
        (0, per_commitment_point, required),
+       (1, opt_anchors, option),
        (2, counterparty_delayed_payment_base_key, required),
        (4, counterparty_htlc_base_key, required),
        (6, preimage, required),
@@ -209,22 +216,29 @@ pub(crate) struct CounterpartyReceivedHTLCOutput {
        per_commitment_point: PublicKey,
        counterparty_delayed_payment_base_key: PublicKey,
        counterparty_htlc_base_key: PublicKey,
-       htlc: HTLCOutputInCommitment
+       htlc: HTLCOutputInCommitment,
+       opt_anchors: Option<()>,
 }
 
 impl CounterpartyReceivedHTLCOutput {
-       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, htlc: HTLCOutputInCommitment) -> Self {
+       pub(crate) fn build(per_commitment_point: PublicKey, counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, htlc: HTLCOutputInCommitment, opt_anchors: bool) -> Self {
                CounterpartyReceivedHTLCOutput {
                        per_commitment_point,
                        counterparty_delayed_payment_base_key,
                        counterparty_htlc_base_key,
-                       htlc
+                       htlc,
+                       opt_anchors: if opt_anchors { Some(()) } else { None },
                }
        }
+
+       fn opt_anchors(&self) -> bool {
+               self.opt_anchors.is_some()
+       }
 }
 
 impl_writeable_tlv_based!(CounterpartyReceivedHTLCOutput, {
        (0, per_commitment_point, required),
+       (1, opt_anchors, option),
        (2, counterparty_delayed_payment_base_key, required),
        (4, counterparty_htlc_base_key, required),
        (6, htlc, required),
@@ -315,12 +329,12 @@ impl PackageSolvingData {
                };
                amt
        }
-       fn weight(&self, opt_anchors: bool) -> usize {
+       fn weight(&self) -> usize {
                let weight = match self {
                        PackageSolvingData::RevokedOutput(ref outp) => { outp.weight as usize },
                        PackageSolvingData::RevokedHTLCOutput(ref outp) => { outp.weight as usize },
-                       PackageSolvingData::CounterpartyOfferedHTLCOutput(..) => { weight_offered_htlc(opt_anchors) as usize },
-                       PackageSolvingData::CounterpartyReceivedHTLCOutput(..) => { weight_received_htlc(opt_anchors) as usize },
+                       PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { weight_offered_htlc(outp.opt_anchors()) as usize },
+                       PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { weight_received_htlc(outp.opt_anchors()) as usize },
                        // Note: Currently, weights of holder outputs spending witnesses aren't used
                        // as we can't malleate spending package to increase their feerate. This
                        // should change with the remaining anchor output patchset.
@@ -594,13 +608,13 @@ impl PackageTemplate {
                self.inputs.iter().map(|(_, outp)| outp.absolute_tx_timelock(self.height_original))
                        .max().expect("There must always be at least one output to spend in a PackageTemplate")
        }
-       pub(crate) fn package_weight(&self, destination_script: &Script, opt_anchors: bool) -> usize {
+       pub(crate) fn package_weight(&self, destination_script: &Script) -> usize {
                let mut inputs_weight = 0;
                let mut witnesses_weight = 2; // count segwit flags
                for (_, outp) in self.inputs.iter() {
                        // previous_out_point: 36 bytes ; var_int: 1 byte ; sequence: 4 bytes
                        inputs_weight += 41 * WITNESS_SCALE_FACTOR;
-                       witnesses_weight += outp.weight(opt_anchors);
+                       witnesses_weight += outp.weight();
                }
                // version: 4 bytes ; count_tx_in: 1 byte ; count_tx_out: 1 byte ; lock_time: 4 bytes
                let transaction_weight = 10 * WITNESS_SCALE_FACTOR;
@@ -873,26 +887,26 @@ mod tests {
        }
 
        macro_rules! dumb_counterparty_output {
-               ($secp_ctx: expr, $amt: expr) => {
+               ($secp_ctx: expr, $amt: expr, $opt_anchors: 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 htlc = HTLCOutputInCommitment { offered: true, amount_msat: $amt, cltv_expiry: 0, payment_hash: hash, transaction_output_index: None };
-                               PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(dumb_point, dumb_point, dumb_point, htlc))
+                               PackageSolvingData::CounterpartyReceivedHTLCOutput(CounterpartyReceivedHTLCOutput::build(dumb_point, dumb_point, dumb_point, htlc, $opt_anchors))
                        }
                }
        }
 
        macro_rules! dumb_counterparty_offered_output {
-               ($secp_ctx: expr, $amt: expr) => {
+               ($secp_ctx: expr, $amt: expr, $opt_anchors: 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))
+                               PackageSolvingData::CounterpartyOfferedHTLCOutput(CounterpartyOfferedHTLCOutput::build(dumb_point, dumb_point, dumb_point, preimage, htlc, $opt_anchors))
                        }
                }
        }
@@ -987,7 +1001,7 @@ mod tests {
                let txid = Txid::from_hex("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap();
                let secp_ctx = Secp256k1::new();
                let revk_outp = dumb_revk_output!(secp_ctx);
-               let counterparty_outp = dumb_counterparty_output!(secp_ctx, 0);
+               let counterparty_outp = dumb_counterparty_output!(secp_ctx, 0, false);
 
                let mut revoked_package = PackageTemplate::build_package(txid, 0, revk_outp, 1000, true, 100);
                let counterparty_package = PackageTemplate::build_package(txid, 1, counterparty_outp, 1000, true, 100);
@@ -1051,7 +1065,7 @@ mod tests {
        fn test_package_amounts() {
                let txid = Txid::from_hex("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap();
                let secp_ctx = Secp256k1::new();
-               let counterparty_outp = dumb_counterparty_output!(secp_ctx, 1_000_000);
+               let counterparty_outp = dumb_counterparty_output!(secp_ctx, 1_000_000, false);
 
                let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, true, 100);
                assert_eq!(package.package_amount(), 1000);
@@ -1068,24 +1082,22 @@ mod tests {
                {
                        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);
-                       }
+                       assert_eq!(package.package_weight(&Script::new()),  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_output!(secp_ctx, 1_000_000, opt_anchors);
+                               let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, true, 100);
+                               assert_eq!(package.package_weight(&Script::new()), 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);
+                               let counterparty_outp = dumb_counterparty_offered_output!(secp_ctx, 1_000_000, opt_anchors);
+                               let package = PackageTemplate::build_package(txid, 0, counterparty_outp, 1000, true, 100);
+                               assert_eq!(package.package_weight(&Script::new()), weight_sans_output + weight_offered_htlc(opt_anchors) as usize);
                        }
                }
        }