Skip to content

Commit 0ac188f

Browse files
committed
Let CommitmentTransaction build the TxCreationKeys it will cache
Instead of asking callers to generate the `TxCreationKeys` on every new commitment before constructing a `CommitmentTransaction`, this commit lets `CommitmentTransaction` derive the `TxCreationKeys` it will use to build the raw commitment transaction. This allows a tighter coupling between the per-commitment keys, and the corresponding commitment transaction. As new states are generated, callers now only have to derive new commitment points; `CommitmentTransaction` takes care of deriving the per-commitment keys. This commit also serves to limit the objects in LDK that derive per-commitment keys according to the LN Specification in preparation for enabling custom derivations in the future.
1 parent e58184c commit 0ac188f

File tree

4 files changed

+30
-67
lines changed

4 files changed

+30
-67
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::types::features::ChannelTypeFeatures;
3838
use crate::types::payment::{PaymentHash, PaymentPreimage};
3939
use crate::ln::msgs::DecodeError;
4040
use crate::ln::channel_keys::{DelayedPaymentKey, DelayedPaymentBasepoint, HtlcBasepoint, HtlcKey, RevocationKey, RevocationBasepoint};
41-
use crate::ln::chan_utils::{self,CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction, TxCreationKeys};
41+
use crate::ln::chan_utils::{self,CommitmentTransaction, CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction};
4242
use crate::ln::channelmanager::{HTLCSource, SentHTLCId, PaymentClaimDetails};
4343
use crate::chain;
4444
use crate::chain::{BestBlock, WatchedOutput};
@@ -3507,11 +3507,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35073507
mut nondust_htlcs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>
35083508
) -> CommitmentTransaction {
35093509
let channel_parameters = &self.funding.channel_parameters.as_counterparty_broadcastable();
3510-
let keys = TxCreationKeys::from_channel_static_keys(their_per_commitment_point,
3511-
channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), &self.onchain_tx_handler.secp_ctx);
3512-
3513-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3514-
to_broadcaster_value, to_countersignatory_value, keys, feerate_per_kw, &mut nondust_htlcs, channel_parameters)
3510+
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3511+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
35153512
}
35163513

35173514
fn counterparty_commitment_txs_from_update(&self, update: &ChannelMonitorUpdate) -> Vec<CommitmentTransaction> {

lightning/src/ln/chan_utils.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,13 +1180,6 @@ impl HolderCommitmentTransaction {
11801180
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
11811181
let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap());
11821182

1183-
let keys = TxCreationKeys {
1184-
per_commitment_point: dummy_key.clone(),
1185-
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1186-
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1187-
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1188-
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1189-
};
11901183
let channel_pubkeys = ChannelPublicKeys {
11911184
funding_pubkey: dummy_key.clone(),
11921185
revocation_basepoint: RevocationBasepoint::from(dummy_key),
@@ -1208,7 +1201,7 @@ impl HolderCommitmentTransaction {
12081201
for _ in 0..htlcs.len() {
12091202
counterparty_htlc_sigs.push(dummy_sig);
12101203
}
1211-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
1204+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key, 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
12121205
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
12131206
HolderCommitmentTransaction {
12141207
inner,
@@ -1518,9 +1511,10 @@ impl CommitmentTransaction {
15181511
/// Only include HTLCs that are above the dust limit for the channel.
15191512
///
15201513
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1521-
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
1514+
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>) -> CommitmentTransaction {
15221515
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
15231516
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
1517+
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
15241518

15251519
// Sort outputs and populate output indices while keeping track of the auxiliary data
15261520
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
@@ -1970,8 +1964,8 @@ pub fn get_commitment_transaction_number_obscure_factor(
19701964
mod tests {
19711965
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
19721966
use crate::chain;
1973-
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersigner_keyed_anchor_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1974-
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1967+
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersigner_keyed_anchor_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1968+
use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1};
19751969
use crate::util::test_utils;
19761970
use crate::sign::{ChannelSigner, SignerProvider};
19771971
use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey};
@@ -1986,11 +1980,12 @@ mod tests {
19861980

19871981
struct TestCommitmentTxBuilder {
19881982
commitment_number: u64,
1989-
keys: TxCreationKeys,
1983+
per_commitment_point: PublicKey,
19901984
feerate_per_kw: u32,
19911985
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
19921986
channel_parameters: ChannelTransactionParameters,
19931987
counterparty_pubkeys: ChannelPublicKeys,
1988+
secp_ctx: Secp256k1::<secp256k1::All>,
19941989
}
19951990

19961991
impl TestCommitmentTxBuilder {
@@ -2015,28 +2010,23 @@ mod tests {
20152010
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
20162011
channel_value_satoshis: 3000,
20172012
};
2018-
let directed_parameters = channel_parameters.as_holder_broadcastable();
2019-
let keys = TxCreationKeys::from_channel_static_keys(
2020-
&per_commitment_point, directed_parameters.broadcaster_pubkeys(),
2021-
directed_parameters.countersignatory_pubkeys(), &secp_ctx,
2022-
);
20232013
let htlcs_with_aux = Vec::new();
20242014

20252015
Self {
20262016
commitment_number: 0,
2027-
keys,
2017+
per_commitment_point,
20282018
feerate_per_kw: 1,
20292019
htlcs_with_aux,
20302020
channel_parameters,
20312021
counterparty_pubkeys,
2022+
secp_ctx,
20322023
}
20332024
}
20342025

20352026
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
20362027
CommitmentTransaction::new_with_auxiliary_htlc_data(
2037-
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
2038-
self.keys.clone(), self.feerate_per_kw,
2039-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable()
2028+
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
2029+
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
20402030
)
20412031
}
20422032
}
@@ -2084,7 +2074,7 @@ mod tests {
20842074
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
20852075
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
20862076
let tx = builder.build(3000, 0);
2087-
let keys = &builder.keys.clone();
2077+
let keys = tx.trust().keys();
20882078
assert_eq!(tx.built.transaction.output.len(), 3);
20892079
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
20902080
assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());

lightning/src/ln/channel.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3814,12 +3814,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38143814
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
38153815
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
38163816
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3817+
&keys.per_commitment_point,
38173818
value_to_a as u64,
38183819
value_to_b as u64,
3819-
keys.clone(),
38203820
feerate_per_kw,
38213821
&mut included_non_dust_htlcs,
3822-
&channel_parameters
3822+
&channel_parameters,
3823+
&self.secp_ctx,
38233824
);
38243825
let mut htlcs_included = included_non_dust_htlcs;
38253826
// The unwrap is safe, because all non-dust HTLCs have been assigned an output index

lightning/src/ln/functional_tests.rs

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -732,31 +732,14 @@ pub fn test_update_fee_that_funder_cannot_afford() {
732732

733733
const INITIAL_COMMITMENT_NUMBER: u64 = 281474976710654;
734734

735-
// Get the TestChannelSigner for each channel, which will be used to (1) get the keys
736-
// needed to sign the new commitment tx and (2) sign the new commitment tx.
737-
let (local_revocation_basepoint, local_htlc_basepoint) = {
738-
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
739-
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
740-
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
741-
let chan_signer = local_chan.get_signer();
742-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
743-
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint)
744-
};
745-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point) = {
735+
let remote_point = {
746736
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
747737
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
748738
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
749739
let chan_signer = remote_chan.get_signer();
750-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
751-
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
752-
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap(),
753-
)
740+
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
754741
};
755742

756-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
757-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
758-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
759-
760743
let res = {
761744
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
762745
let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
@@ -765,12 +748,13 @@ pub fn test_update_fee_that_funder_cannot_afford() {
765748
let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![];
766749
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
767750
INITIAL_COMMITMENT_NUMBER - 1,
751+
&remote_point,
768752
push_sats,
769753
channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
770-
commit_tx_keys.clone(),
771754
non_buffer_feerate + 4,
772755
&mut htlcs,
773-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
756+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
757+
&secp_ctx,
774758
);
775759
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
776760
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),
@@ -1458,35 +1442,25 @@ pub fn test_fee_spike_violation_fails_htlc() {
14581442

14591443
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
14601444

1461-
// Get the TestChannelSigner for each channel, which will be used to (1) get the keys
1462-
// needed to sign the new commitment tx and (2) sign the new commitment tx.
1463-
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point) = {
1445+
let (local_secret, next_local_point) = {
14641446
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
14651447
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
14661448
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14671449
let chan_signer = local_chan.get_signer();
14681450
// Make the signer believe we validated another commitment, so we can release the secret
14691451
chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1;
14701452

1471-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
1472-
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
1473-
chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
1453+
(chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
14741454
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap())
14751455
};
1476-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point) = {
1456+
let remote_point = {
14771457
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
14781458
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
14791459
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14801460
let chan_signer = remote_chan.get_signer();
1481-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
1482-
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1483-
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap())
1461+
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
14841462
};
14851463

1486-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
1487-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
1488-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
1489-
14901464
// Build the remote commitment transaction so we can sign it, and then later use the
14911465
// signature for the commitment_signed message.
14921466
let local_chan_balance = 1313;
@@ -1508,12 +1482,13 @@ pub fn test_fee_spike_violation_fails_htlc() {
15081482
let local_chan_signer = local_chan.get_signer();
15091483
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
15101484
commitment_number,
1485+
&remote_point,
15111486
95000,
15121487
local_chan_balance,
1513-
commit_tx_keys.clone(),
15141488
feerate_per_kw,
15151489
&mut vec![(accepted_htlc_info, ())],
1516-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
1490+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
1491+
&secp_ctx,
15171492
);
15181493
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
15191494
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),

0 commit comments

Comments
 (0)