Skip to content

Commit 458bde0

Browse files
committed
Cache HTLC per_commitment_point in descriptor
1 parent 07b0db3 commit 458bde0

File tree

5 files changed

+102
-110
lines changed

5 files changed

+102
-110
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::util::logger::Logger;
5050
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
5151
use crate::util::byte_utils;
5252
use crate::events::Event;
53-
use crate::events::bump_transaction::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent};
53+
use crate::events::bump_transaction::{ChannelDerivationParameters, AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent};
5454

5555
use crate::prelude::*;
5656
use core::{cmp, mem};
@@ -2550,8 +2550,11 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
25502550
commitment_tx,
25512551
commitment_tx_fee_satoshis,
25522552
anchor_descriptor: AnchorDescriptor {
2553-
channel_keys_id: self.channel_keys_id,
2554-
channel_value_satoshis: self.channel_value_satoshis,
2553+
channel_derivation_parameters: ChannelDerivationParameters {
2554+
keys_id: self.channel_keys_id,
2555+
value_satoshis: self.channel_value_satoshis,
2556+
transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
2557+
},
25552558
outpoint: BitcoinOutPoint {
25562559
txid: commitment_txid,
25572560
vout: anchor_output_idx,
@@ -2566,11 +2569,16 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
25662569
let mut htlc_descriptors = Vec::with_capacity(htlcs.len());
25672570
for htlc in htlcs {
25682571
htlc_descriptors.push(HTLCDescriptor {
2569-
channel_keys_id: self.channel_keys_id,
2570-
channel_value_satoshis: self.channel_value_satoshis,
2571-
channel_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
2572+
channel_derivation_parameters: ChannelDerivationParameters {
2573+
keys_id: self.channel_keys_id,
2574+
value_satoshis: self.channel_value_satoshis,
2575+
transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(),
2576+
},
25722577
commitment_txid: htlc.commitment_txid,
25732578
per_commitment_number: htlc.per_commitment_number,
2579+
per_commitment_point: self.onchain_tx_handler.signer.get_per_commitment_point(
2580+
htlc.per_commitment_number, &self.onchain_tx_handler.secp_ctx,
2581+
),
25742582
htlc: htlc.htlc,
25752583
preimage: htlc.preimage,
25762584
counterparty_sig: htlc.counterparty_sig,

lightning/src/events/bump_transaction.rs

Lines changed: 74 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
//! Utitilies for bumping transactions originating from [`super::Event`]s.
1111
12+
use alloc::collections::BTreeMap;
1213
use core::convert::TryInto;
1314
use core::ops::Deref;
1415

@@ -48,49 +49,57 @@ const fn fee_for_weight(feerate_sat_per_1000_weight: u32, weight: u64) -> u64 {
4849
((feerate_sat_per_1000_weight as u64 * weight) + 1000 - 1) / 1000
4950
}
5051

52+
/// The parameters required to derive a channel signer via [`SignerProvider`].
53+
#[derive(Clone, Debug, PartialEq, Eq)]
54+
pub struct ChannelDerivationParameters {
55+
/// The value in satoshis of the channel we're attempting to spend the anchor output of.
56+
pub value_satoshis: u64,
57+
/// The unique identifier to re-derive the signer for the associated channel.
58+
pub keys_id: [u8; 32],
59+
/// The necessary channel parameters that need to be provided to the re-derived signer through
60+
/// [`ChannelSigner::provide_channel_parameters`].
61+
///
62+
/// [`ChannelSigner::provide_channel_parameters`]: crate::sign::ChannelSigner::provide_channel_parameters
63+
pub transaction_parameters: ChannelTransactionParameters,
64+
}
65+
5166
/// A descriptor used to sign for a commitment transaction's anchor output.
5267
#[derive(Clone, Debug, PartialEq, Eq)]
5368
pub struct AnchorDescriptor {
54-
/// A unique identifier used along with `channel_value_satoshis` to re-derive the
55-
/// [`InMemorySigner`] required to sign `input`.
56-
///
57-
/// [`InMemorySigner`]: crate::sign::InMemorySigner
58-
pub channel_keys_id: [u8; 32],
59-
/// The value in satoshis of the channel we're attempting to spend the anchor output of. This is
60-
/// used along with `channel_keys_id` to re-derive the [`InMemorySigner`] required to sign
61-
/// `input`.
62-
///
63-
/// [`InMemorySigner`]: crate::sign::InMemorySigner
64-
pub channel_value_satoshis: u64,
69+
/// The parameters required to derive the signer for the anchor input.
70+
pub channel_derivation_parameters: ChannelDerivationParameters,
6571
/// The transaction input's outpoint corresponding to the commitment transaction's anchor
6672
/// output.
6773
pub outpoint: OutPoint,
6874
}
6975

76+
impl AnchorDescriptor {
77+
/// Derives the channel signer required to sign the anchor input.
78+
pub fn derive_channel_signer<SP: Deref>(&self, signer_provider: &SP) -> <SP::Target as SignerProvider>::Signer
79+
where
80+
SP::Target: SignerProvider
81+
{
82+
let mut signer = signer_provider.derive_channel_signer(
83+
self.channel_derivation_parameters.value_satoshis,
84+
self.channel_derivation_parameters.keys_id,
85+
);
86+
signer.provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters);
87+
signer
88+
}
89+
}
90+
7091
/// A descriptor used to sign for a commitment transaction's HTLC output.
7192
#[derive(Clone, Debug, PartialEq, Eq)]
7293
pub struct HTLCDescriptor {
73-
/// A unique identifier used along with `channel_value_satoshis` to re-derive the
74-
/// [`InMemorySigner`] required to sign `input`.
75-
///
76-
/// [`InMemorySigner`]: crate::sign::InMemorySigner
77-
pub channel_keys_id: [u8; 32],
78-
/// The value in satoshis of the channel we're attempting to spend the anchor output of. This is
79-
/// used along with `channel_keys_id` to re-derive the [`InMemorySigner`] required to sign
80-
/// `input`.
81-
///
82-
/// [`InMemorySigner`]: crate::sign::InMemorySigner
83-
pub channel_value_satoshis: u64,
84-
/// The necessary channel parameters that need to be provided to the re-derived
85-
/// [`InMemorySigner`] through [`ChannelSigner::provide_channel_parameters`].
86-
///
87-
/// [`InMemorySigner`]: crate::sign::InMemorySigner
88-
/// [`ChannelSigner::provide_channel_parameters`]: crate::sign::ChannelSigner::provide_channel_parameters
89-
pub channel_parameters: ChannelTransactionParameters,
94+
/// The parameters required to derive the signer for the HTLC input.
95+
pub channel_derivation_parameters: ChannelDerivationParameters,
9096
/// The txid of the commitment transaction in which the HTLC output lives.
9197
pub commitment_txid: Txid,
9298
/// The number of the commitment transaction in which the HTLC output lives.
9399
pub per_commitment_number: u64,
100+
/// The public key corresponding to the number of the commitment transaction in which the HTLC
101+
/// output lives.
102+
pub per_commitment_point: PublicKey,
94103
/// The details of the HTLC as it appears in the commitment transaction.
95104
pub htlc: HTLCOutputInCommitment,
96105
/// The preimage, if `Some`, to claim the HTLC output with. If `None`, the timeout path must be
@@ -109,17 +118,15 @@ impl HTLCDescriptor {
109118

110119
/// Returns the delayed output created as a result of spending the HTLC output in the commitment
111120
/// transaction.
112-
pub fn tx_output<C: secp256k1::Signing + secp256k1::Verification>(
113-
&self, per_commitment_point: &PublicKey, secp: &Secp256k1<C>
114-
) -> TxOut {
115-
let channel_params = self.channel_parameters.as_holder_broadcastable();
121+
pub fn tx_output<C: secp256k1::Signing + secp256k1::Verification>(&self, secp: &Secp256k1<C>) -> TxOut {
122+
let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable();
116123
let broadcaster_keys = channel_params.broadcaster_pubkeys();
117124
let counterparty_keys = channel_params.countersignatory_pubkeys();
118125
let broadcaster_delayed_key = chan_utils::derive_public_key(
119-
secp, per_commitment_point, &broadcaster_keys.delayed_payment_basepoint
126+
secp, &self.per_commitment_point, &broadcaster_keys.delayed_payment_basepoint
120127
);
121128
let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
122-
secp, per_commitment_point, &counterparty_keys.revocation_basepoint
129+
secp, &self.per_commitment_point, &counterparty_keys.revocation_basepoint
123130
);
124131
chan_utils::build_htlc_output(
125132
0 /* feerate_per_kw */, channel_params.contest_delay(), &self.htlc,
@@ -128,20 +135,18 @@ impl HTLCDescriptor {
128135
}
129136

130137
/// Returns the witness script of the HTLC output in the commitment transaction.
131-
pub fn witness_script<C: secp256k1::Signing + secp256k1::Verification>(
132-
&self, per_commitment_point: &PublicKey, secp: &Secp256k1<C>
133-
) -> Script {
134-
let channel_params = self.channel_parameters.as_holder_broadcastable();
138+
pub fn witness_script<C: secp256k1::Signing + secp256k1::Verification>(&self, secp: &Secp256k1<C>) -> Script {
139+
let channel_params = self.channel_derivation_parameters.transaction_parameters.as_holder_broadcastable();
135140
let broadcaster_keys = channel_params.broadcaster_pubkeys();
136141
let counterparty_keys = channel_params.countersignatory_pubkeys();
137142
let broadcaster_htlc_key = chan_utils::derive_public_key(
138-
secp, per_commitment_point, &broadcaster_keys.htlc_basepoint
143+
secp, &self.per_commitment_point, &broadcaster_keys.htlc_basepoint
139144
);
140145
let counterparty_htlc_key = chan_utils::derive_public_key(
141-
secp, per_commitment_point, &counterparty_keys.htlc_basepoint
146+
secp, &self.per_commitment_point, &counterparty_keys.htlc_basepoint
142147
);
143148
let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
144-
secp, per_commitment_point, &counterparty_keys.revocation_basepoint
149+
secp, &self.per_commitment_point, &counterparty_keys.revocation_basepoint
145150
);
146151
chan_utils::get_htlc_redeemscript_with_explicit_keys(
147152
&self.htlc, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(), &broadcaster_htlc_key, &counterparty_htlc_key,
@@ -156,6 +161,19 @@ impl HTLCDescriptor {
156161
signature, &self.counterparty_sig, &self.preimage, witness_script, &ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies() /* opt_anchors */
157162
)
158163
}
164+
165+
/// Derives the channel signer required to sign the HTLC input.
166+
pub fn derive_channel_signer<SP: Deref>(&self, signer_provider: &SP) -> <SP::Target as SignerProvider>::Signer
167+
where
168+
SP::Target: SignerProvider
169+
{
170+
let mut signer = signer_provider.derive_channel_signer(
171+
self.channel_derivation_parameters.value_satoshis,
172+
self.channel_derivation_parameters.keys_id,
173+
);
174+
signer.provide_channel_parameters(&self.channel_derivation_parameters.transaction_parameters);
175+
signer
176+
}
159177
}
160178

161179
/// Represents the different types of transactions, originating from LDK, to be bumped.
@@ -662,9 +680,7 @@ where
662680
debug_assert_eq!(anchor_tx.output.len(), 1);
663681

664682
self.utxo_source.sign_tx(&mut anchor_tx)?;
665-
let signer = self.signer_provider.derive_channel_signer(
666-
anchor_descriptor.channel_value_satoshis, anchor_descriptor.channel_keys_id,
667-
);
683+
let signer = anchor_descriptor.derive_channel_signer(&self.signer_provider);
668684
let anchor_sig = signer.sign_holder_anchor_input(&anchor_tx, 0, &self.secp)?;
669685
anchor_tx.input[0].witness =
670686
chan_utils::build_anchor_input_witness(&signer.pubkeys().funding_pubkey, &anchor_sig);
@@ -678,7 +694,7 @@ where
678694
fn build_htlc_tx(
679695
&self, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32,
680696
htlc_descriptors: &[HTLCDescriptor], tx_lock_time: PackedLockTime,
681-
) -> Result<(Transaction, HashMap<[u8; 32], <SP::Target as SignerProvider>::Signer>), ()> {
697+
) -> Result<Transaction, ()> {
682698
let mut tx = Transaction {
683699
version: 2,
684700
lock_time: tx_lock_time,
@@ -687,19 +703,8 @@ where
687703
};
688704
// Unfortunately, we need to derive the signer for each HTLC ahead of time to obtain its
689705
// input.
690-
let mut signers = HashMap::new();
691706
let mut must_spend = Vec::with_capacity(htlc_descriptors.len());
692707
for htlc_descriptor in htlc_descriptors {
693-
let signer = signers.entry(htlc_descriptor.channel_keys_id)
694-
.or_insert_with(||
695-
self.signer_provider.derive_channel_signer(
696-
htlc_descriptor.channel_value_satoshis, htlc_descriptor.channel_keys_id,
697-
)
698-
);
699-
let per_commitment_point = signer.get_per_commitment_point(
700-
htlc_descriptor.per_commitment_number, &self.secp
701-
);
702-
703708
let htlc_input = htlc_descriptor.unsigned_tx_input();
704709
must_spend.push(Input {
705710
outpoint: htlc_input.previous_output.clone(),
@@ -710,15 +715,15 @@ where
710715
},
711716
});
712717
tx.input.push(htlc_input);
713-
let htlc_output = htlc_descriptor.tx_output(&per_commitment_point, &self.secp);
718+
let htlc_output = htlc_descriptor.tx_output(&self.secp);
714719
tx.output.push(htlc_output);
715720
}
716721

717722
let coin_selection = self.utxo_source.select_confirmed_utxos(
718723
claim_id, &must_spend, &tx.output, target_feerate_sat_per_1000_weight,
719724
)?;
720725
self.process_coin_selection(&mut tx, coin_selection);
721-
Ok((tx, signers))
726+
Ok(tx)
722727
}
723728

724729
/// Handles a [`BumpTransactionEvent::HTLCResolution`] event variant by producing a
@@ -727,20 +732,22 @@ where
727732
&self, claim_id: ClaimId, target_feerate_sat_per_1000_weight: u32,
728733
htlc_descriptors: &[HTLCDescriptor], tx_lock_time: PackedLockTime,
729734
) -> Result<(), ()> {
730-
let (mut htlc_tx, signers) = self.build_htlc_tx(
735+
let mut htlc_tx = self.build_htlc_tx(
731736
claim_id, target_feerate_sat_per_1000_weight, htlc_descriptors, tx_lock_time,
732737
)?;
733738

734739
self.utxo_source.sign_tx(&mut htlc_tx)?;
740+
let mut signers = BTreeMap::new();
735741
for (idx, htlc_descriptor) in htlc_descriptors.iter().enumerate() {
736-
let signer = signers.get(&htlc_descriptor.channel_keys_id).unwrap();
737-
let htlc_sig = signer.sign_holder_htlc_transaction(
738-
&htlc_tx, idx, htlc_descriptor, &self.secp
739-
)?;
740-
let per_commitment_point = signer.get_per_commitment_point(
741-
htlc_descriptor.per_commitment_number, &self.secp
742-
);
743-
let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &self.secp);
742+
let signer = if let Some(signer) = signers.get(&htlc_descriptor.channel_derivation_parameters.keys_id) {
743+
signer
744+
} else {
745+
let signer = htlc_descriptor.derive_channel_signer(&self.signer_provider);
746+
signers.insert(htlc_descriptor.channel_derivation_parameters.keys_id, signer);
747+
signers.get(&htlc_descriptor.channel_derivation_parameters.keys_id).expect("Signer was just added")
748+
};
749+
let htlc_sig = signer.sign_holder_htlc_transaction(&htlc_tx, idx, htlc_descriptor, &self.secp)?;
750+
let witness_script = htlc_descriptor.witness_script(&self.secp);
744751
htlc_tx.input[idx].witness = htlc_descriptor.tx_input_witness(&htlc_sig, &witness_script);
745752
}
746753

lightning/src/ln/monitor_tests.rs

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,15 +1778,10 @@ fn do_test_monitor_rebroadcast_pending_claims(anchors: bool) {
17781778
// feerate for the test, we just want to make sure the feerates we receive from
17791779
// the events never decrease.
17801780
tx.input.push(descriptor.unsigned_tx_input());
1781-
let signer = nodes[0].keys_manager.derive_channel_keys(
1782-
descriptor.channel_value_satoshis, &descriptor.channel_keys_id,
1783-
);
1784-
let per_commitment_point = signer.get_per_commitment_point(
1785-
descriptor.per_commitment_number, &secp
1786-
);
1787-
tx.output.push(descriptor.tx_output(&per_commitment_point, &secp));
1781+
tx.output.push(descriptor.tx_output(&secp));
1782+
let signer = descriptor.derive_channel_signer(&nodes[0].keys_manager);
17881783
let our_sig = signer.sign_holder_htlc_transaction(&mut tx, 0, &descriptor, &secp).unwrap();
1789-
let witness_script = descriptor.witness_script(&per_commitment_point, &secp);
1784+
let witness_script = descriptor.witness_script(&secp);
17901785
tx.input[0].witness = descriptor.tx_input_witness(&our_sig, &witness_script);
17911786
target_feerate_sat_per_1000_weight as u64
17921787
} else { panic!("unexpected event"); };
@@ -1910,9 +1905,7 @@ fn test_yield_anchors_events() {
19101905
script_pubkey: Script::new_op_return(&[]),
19111906
}],
19121907
};
1913-
let signer = nodes[0].keys_manager.derive_channel_keys(
1914-
anchor_descriptor.channel_value_satoshis, &anchor_descriptor.channel_keys_id,
1915-
);
1908+
let signer = anchor_descriptor.derive_channel_signer(&nodes[0].keys_manager);
19161909
let funding_sig = signer.sign_holder_anchor_input(&mut anchor_tx, 0, &secp).unwrap();
19171910
anchor_tx.input[0].witness = chan_utils::build_anchor_input_witness(
19181911
&signer.pubkeys().funding_pubkey, &funding_sig
@@ -1943,10 +1936,6 @@ fn test_yield_anchors_events() {
19431936
Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { htlc_descriptors, tx_lock_time, .. }) => {
19441937
assert_eq!(htlc_descriptors.len(), 1);
19451938
let htlc_descriptor = &htlc_descriptors[0];
1946-
let signer = nodes[0].keys_manager.derive_channel_keys(
1947-
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
1948-
);
1949-
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
19501939
let mut htlc_tx = Transaction {
19511940
version: 2,
19521941
lock_time: tx_lock_time,
@@ -1955,15 +1944,16 @@ fn test_yield_anchors_events() {
19551944
TxIn { ..Default::default() } // Fee input
19561945
],
19571946
output: vec![
1958-
htlc_descriptor.tx_output(&per_commitment_point, &secp), // HTLC output
1947+
htlc_descriptor.tx_output(&secp), // HTLC output
19591948
TxOut { // Fee input change
19601949
value: Amount::ONE_BTC.to_sat(),
19611950
script_pubkey: Script::new_op_return(&[]),
19621951
}
19631952
]
19641953
};
1954+
let signer = htlc_descriptor.derive_channel_signer(&nodes[0].keys_manager);
19651955
let our_sig = signer.sign_holder_htlc_transaction(&mut htlc_tx, 0, htlc_descriptor, &secp).unwrap();
1966-
let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &secp);
1956+
let witness_script = htlc_descriptor.witness_script(&secp);
19671957
htlc_tx.input[0].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script);
19681958
htlc_txs.push(htlc_tx);
19691959
},
@@ -2122,9 +2112,7 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
21222112
previous_output: anchor_descriptor.outpoint,
21232113
..Default::default()
21242114
});
2125-
let signer = nodes[1].keys_manager.derive_channel_keys(
2126-
anchor_descriptor.channel_value_satoshis, &anchor_descriptor.channel_keys_id,
2127-
);
2115+
let signer = anchor_descriptor.derive_channel_signer(&nodes[1].keys_manager);
21282116
signers.push(signer);
21292117
},
21302118
_ => panic!("Unexpected event"),
@@ -2227,12 +2215,8 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
22272215
assert_eq!(htlc_descriptors.len(), 2);
22282216
for htlc_descriptor in &htlc_descriptors {
22292217
assert!(!htlc_descriptor.htlc.offered);
2230-
let signer = nodes[1].keys_manager.derive_channel_keys(
2231-
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
2232-
);
2233-
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
22342218
htlc_tx.input.push(htlc_descriptor.unsigned_tx_input());
2235-
htlc_tx.output.push(htlc_descriptor.tx_output(&per_commitment_point, &secp));
2219+
htlc_tx.output.push(htlc_descriptor.tx_output(&secp));
22362220
}
22372221
descriptors.append(&mut htlc_descriptors);
22382222
htlc_tx.lock_time = tx_lock_time;
@@ -2242,12 +2226,9 @@ fn test_anchors_aggregated_revoked_htlc_tx() {
22422226
}
22432227
for (idx, htlc_descriptor) in descriptors.into_iter().enumerate() {
22442228
let htlc_input_idx = idx + 1;
2245-
let signer = nodes[1].keys_manager.derive_channel_keys(
2246-
htlc_descriptor.channel_value_satoshis, &htlc_descriptor.channel_keys_id
2247-
);
2229+
let signer = htlc_descriptor.derive_channel_signer(&nodes[1].keys_manager);
22482230
let our_sig = signer.sign_holder_htlc_transaction(&htlc_tx, htlc_input_idx, &htlc_descriptor, &secp).unwrap();
2249-
let per_commitment_point = signer.get_per_commitment_point(htlc_descriptor.per_commitment_number, &secp);
2250-
let witness_script = htlc_descriptor.witness_script(&per_commitment_point, &secp);
2231+
let witness_script = htlc_descriptor.witness_script(&secp);
22512232
htlc_tx.input[htlc_input_idx].witness = htlc_descriptor.tx_input_witness(&our_sig, &witness_script);
22522233
}
22532234
let fee_utxo_sig = {

0 commit comments

Comments
 (0)