Skip to content

Commit 09dc44d

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 0d0eede commit 09dc44d

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};
@@ -3436,11 +3436,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34363436
) -> CommitmentTransaction {
34373437
let channel_parameters =
34383438
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3439-
let keys = TxCreationKeys::from_channel_static_keys(their_per_commitment_point,
3440-
channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), &self.onchain_tx_handler.secp_ctx);
3441-
3442-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3443-
to_broadcaster_value, to_countersignatory_value, keys, feerate_per_kw, &mut nondust_htlcs, channel_parameters)
3439+
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3440+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
34443441
}
34453442

34463443
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
@@ -1171,13 +1171,6 @@ impl HolderCommitmentTransaction {
11711171
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
11721172
let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_digest([42; 32]), &SecretKey::from_slice(&[42; 32]).unwrap());
11731173

1174-
let keys = TxCreationKeys {
1175-
per_commitment_point: dummy_key.clone(),
1176-
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1177-
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1178-
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1179-
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1180-
};
11811174
let channel_pubkeys = ChannelPublicKeys {
11821175
funding_pubkey: dummy_key.clone(),
11831176
revocation_basepoint: RevocationBasepoint::from(dummy_key),
@@ -1199,7 +1192,7 @@ impl HolderCommitmentTransaction {
11991192
for _ in 0..htlcs.len() {
12001193
counterparty_htlc_sigs.push(dummy_sig);
12011194
}
1202-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
1195+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key, 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
12031196
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
12041197
HolderCommitmentTransaction {
12051198
inner,
@@ -1509,9 +1502,10 @@ impl CommitmentTransaction {
15091502
/// Only include HTLCs that are above the dust limit for the channel.
15101503
///
15111504
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1512-
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 {
1505+
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 {
15131506
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
15141507
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
1508+
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
15151509

15161510
// Sort outputs and populate output indices while keeping track of the auxiliary data
15171511
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
@@ -1961,8 +1955,8 @@ pub fn get_commitment_transaction_number_obscure_factor(
19611955
mod tests {
19621956
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
19631957
use crate::chain;
1964-
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1965-
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1958+
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1959+
use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1};
19661960
use crate::util::test_utils;
19671961
use crate::sign::{ChannelSigner, SignerProvider};
19681962
use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey};
@@ -1977,11 +1971,12 @@ mod tests {
19771971

19781972
struct TestCommitmentTxBuilder {
19791973
commitment_number: u64,
1980-
keys: TxCreationKeys,
1974+
per_commitment_point: PublicKey,
19811975
feerate_per_kw: u32,
19821976
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
19831977
channel_parameters: ChannelTransactionParameters,
19841978
counterparty_pubkeys: ChannelPublicKeys,
1979+
secp_ctx: Secp256k1::<secp256k1::All>,
19851980
}
19861981

19871982
impl TestCommitmentTxBuilder {
@@ -2006,28 +2001,23 @@ mod tests {
20062001
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
20072002
channel_value_satoshis: 3000,
20082003
};
2009-
let directed_parameters = channel_parameters.as_holder_broadcastable();
2010-
let keys = TxCreationKeys::from_channel_static_keys(
2011-
&per_commitment_point, directed_parameters.broadcaster_pubkeys(),
2012-
directed_parameters.countersignatory_pubkeys(), &secp_ctx,
2013-
);
20142004
let htlcs_with_aux = Vec::new();
20152005

20162006
Self {
20172007
commitment_number: 0,
2018-
keys,
2008+
per_commitment_point,
20192009
feerate_per_kw: 1,
20202010
htlcs_with_aux,
20212011
channel_parameters,
20222012
counterparty_pubkeys,
2013+
secp_ctx,
20232014
}
20242015
}
20252016

20262017
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
20272018
CommitmentTransaction::new_with_auxiliary_htlc_data(
2028-
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
2029-
self.keys.clone(), self.feerate_per_kw,
2030-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable()
2019+
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
2020+
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
20312021
)
20322022
}
20332023
}
@@ -2075,7 +2065,7 @@ mod tests {
20752065
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
20762066
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
20772067
let tx = builder.build(3000, 0);
2078-
let keys = &builder.keys.clone();
2068+
let keys = tx.trust().keys();
20792069
assert_eq!(tx.built.transaction.output.len(), 3);
20802070
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
20812071
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
@@ -3820,12 +3820,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38203820
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
38213821
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
38223822
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3823+
&keys.per_commitment_point,
38233824
value_to_a as u64,
38243825
value_to_b as u64,
3825-
keys.clone(),
38263826
feerate_per_kw,
38273827
&mut included_non_dust_htlcs,
3828-
&channel_parameters
3828+
&channel_parameters,
3829+
&self.secp_ctx,
38293830
);
38303831
let mut htlcs_included = included_non_dust_htlcs;
38313832
// 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
@@ -730,31 +730,14 @@ pub fn test_update_fee_that_funder_cannot_afford() {
730730

731731
const INITIAL_COMMITMENT_NUMBER: u64 = 281474976710654;
732732

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

754-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
755-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
756-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
757-
758741
let res = {
759742
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
760743
let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
@@ -763,12 +746,13 @@ pub fn test_update_fee_that_funder_cannot_afford() {
763746
let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![];
764747
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
765748
INITIAL_COMMITMENT_NUMBER - 1,
749+
&remote_point,
766750
push_sats,
767751
channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
768-
commit_tx_keys.clone(),
769752
non_buffer_feerate + 4,
770753
&mut htlcs,
771-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
754+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
755+
&secp_ctx,
772756
);
773757
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
774758
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),
@@ -1456,35 +1440,25 @@ pub fn test_fee_spike_violation_fails_htlc() {
14561440

14571441
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
14581442

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

1469-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
1470-
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
1471-
chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
1451+
(chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
14721452
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap())
14731453
};
1474-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point) = {
1454+
let remote_point = {
14751455
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
14761456
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
14771457
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14781458
let chan_signer = remote_chan.get_signer();
1479-
let pubkeys = chan_signer.as_ref().pubkeys(None, &secp_ctx);
1480-
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1481-
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap())
1459+
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
14821460
};
14831461

1484-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
1485-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
1486-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
1487-
14881462
// Build the remote commitment transaction so we can sign it, and then later use the
14891463
// signature for the commitment_signed message.
14901464
let local_chan_balance = 1313;
@@ -1506,12 +1480,13 @@ pub fn test_fee_spike_violation_fails_htlc() {
15061480
let local_chan_signer = local_chan.get_signer();
15071481
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
15081482
commitment_number,
1483+
&remote_point,
15091484
95000,
15101485
local_chan_balance,
1511-
commit_tx_keys.clone(),
15121486
feerate_per_kw,
15131487
&mut vec![(accepted_htlc_info, ())],
1514-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
1488+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
1489+
&secp_ctx,
15151490
);
15161491
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
15171492
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),

0 commit comments

Comments
 (0)