Skip to content

Commit 2e96e75

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`, let `CommitmentTransaction` derive the `TxCreationKeys` it will use to build the raw commitment transaction that it will cache. 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 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 02ea7b5 commit 2e96e75

File tree

4 files changed

+30
-63
lines changed

4 files changed

+30
-63
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};
@@ -3492,11 +3492,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34923492
) -> CommitmentTransaction {
34933493
let channel_parameters =
34943494
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3495-
let keys = TxCreationKeys::from_channel_static_keys(&their_per_commitment_point,
3496-
channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), &self.onchain_tx_handler.secp_ctx);
3497-
3498-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3499-
to_broadcaster_value, to_countersignatory_value, keys, feerate_per_kw, &mut nondust_htlcs, channel_parameters)
3495+
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3496+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
35003497
}
35013498

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

1153-
let keys = TxCreationKeys {
1154-
per_commitment_point: dummy_key.clone(),
1155-
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1156-
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1157-
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1158-
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1159-
};
11601153
let channel_pubkeys = ChannelPublicKeys {
11611154
funding_pubkey: dummy_key.clone(),
11621155
revocation_basepoint: RevocationBasepoint::from(dummy_key),
@@ -1178,7 +1171,7 @@ impl HolderCommitmentTransaction {
11781171
for _ in 0..htlcs.len() {
11791172
counterparty_htlc_sigs.push(dummy_sig);
11801173
}
1181-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
1174+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key.clone(), 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
11821175
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
11831176
HolderCommitmentTransaction {
11841177
inner,
@@ -1488,9 +1481,10 @@ impl CommitmentTransaction {
14881481
/// Only include HTLCs that are above the dust limit for the channel.
14891482
///
14901483
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1491-
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 {
1484+
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 {
14921485
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
14931486
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
1487+
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
14941488

14951489
// Sort outputs and populate output indices while keeping track of the auxiliary data
14961490
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
@@ -1939,8 +1933,8 @@ pub fn get_commitment_transaction_number_obscure_factor(
19391933
mod tests {
19401934
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
19411935
use crate::chain;
1942-
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1943-
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1936+
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1937+
use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1};
19441938
use crate::util::test_utils;
19451939
use crate::sign::{ChannelSigner, SignerProvider};
19461940
use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey};
@@ -1955,11 +1949,12 @@ mod tests {
19551949

19561950
struct TestCommitmentTxBuilder {
19571951
commitment_number: u64,
1958-
keys: TxCreationKeys,
1952+
per_commitment_point: PublicKey,
19591953
feerate_per_kw: u32,
19601954
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
19611955
channel_parameters: ChannelTransactionParameters,
19621956
counterparty_pubkeys: ChannelPublicKeys,
1957+
secp_ctx: Secp256k1::<secp256k1::All>,
19631958
}
19641959

19651960
impl TestCommitmentTxBuilder {
@@ -1984,28 +1979,23 @@ mod tests {
19841979
channel_type_features: ChannelTypeFeatures::only_static_remote_key(),
19851980
channel_value_satoshis: 3000,
19861981
};
1987-
let directed_parameters = channel_parameters.as_holder_broadcastable();
1988-
let keys = TxCreationKeys::from_channel_static_keys(
1989-
&per_commitment_point, directed_parameters.broadcaster_pubkeys(),
1990-
directed_parameters.countersignatory_pubkeys(), &secp_ctx,
1991-
);
19921982
let htlcs_with_aux = Vec::new();
19931983

19941984
Self {
19951985
commitment_number: 0,
1996-
keys,
1986+
per_commitment_point,
19971987
feerate_per_kw: 1,
19981988
htlcs_with_aux,
19991989
channel_parameters,
20001990
counterparty_pubkeys,
1991+
secp_ctx,
20011992
}
20021993
}
20031994

20041995
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
20051996
CommitmentTransaction::new_with_auxiliary_htlc_data(
2006-
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
2007-
self.keys.clone(), self.feerate_per_kw,
2008-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable()
1997+
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
1998+
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
20091999
)
20102000
}
20112001
}
@@ -2053,7 +2043,7 @@ mod tests {
20532043
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
20542044
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
20552045
let tx = builder.build(3000, 0);
2056-
let keys = &builder.keys.clone();
2046+
let keys = &tx.trust().keys();
20572047
assert_eq!(tx.built.transaction.output.len(), 3);
20582048
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
20592049
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
@@ -3792,12 +3792,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
37923792
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
37933793
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
37943794
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3795+
&keys.per_commitment_point,
37953796
value_to_a as u64,
37963797
value_to_b as u64,
3797-
keys.clone(),
37983798
feerate_per_kw,
37993799
&mut included_non_dust_htlcs,
3800-
&channel_parameters
3800+
&channel_parameters,
3801+
&self.secp_ctx,
38013802
);
38023803
let mut htlcs_included = included_non_dust_htlcs;
38033804
// 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 & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -732,29 +732,14 @@ pub fn test_update_fee_that_funder_cannot_afford() {
732732

733733
// Get the TestChannelSigner for each channel, which will be used to (1) get the keys
734734
// 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) = {
735+
let remote_point = {
744736
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
745737
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
746738
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
747739
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-
)
740+
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
752741
};
753742

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-
758743
let res = {
759744
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
760745
let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
@@ -763,12 +748,13 @@ pub fn test_update_fee_that_funder_cannot_afford() {
763748
let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![];
764749
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
765750
INITIAL_COMMITMENT_NUMBER - 1,
751+
&remote_point,
766752
push_sats,
767753
channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
768-
commit_tx_keys.clone(),
769754
non_buffer_feerate + 4,
770755
&mut htlcs,
771-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
756+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
757+
&secp_ctx,
772758
);
773759
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
774760
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),
@@ -1458,33 +1444,25 @@ pub fn test_fee_spike_violation_fails_htlc() {
14581444

14591445
// Get the TestChannelSigner for each channel, which will be used to (1) get the keys
14601446
// 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) = {
1447+
let (local_secret, next_local_point) = {
14621448
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
14631449
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
14641450
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14651451
let chan_signer = local_chan.get_signer();
14661452
// Make the signer believe we validated another commitment, so we can release the secret
14671453
chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1;
14681454

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(),
1455+
(chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
14721456
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap())
14731457
};
1474-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point) = {
1458+
let remote_point = {
14751459
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
14761460
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
14771461
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14781462
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())
1463+
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx).unwrap()
14821464
};
14831465

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-
14881466
// Build the remote commitment transaction so we can sign it, and then later use the
14891467
// signature for the commitment_signed message.
14901468
let local_chan_balance = 1313;
@@ -1506,12 +1484,13 @@ pub fn test_fee_spike_violation_fails_htlc() {
15061484
let local_chan_signer = local_chan.get_signer();
15071485
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
15081486
commitment_number,
1487+
&remote_point,
15091488
95000,
15101489
local_chan_balance,
1511-
commit_tx_keys.clone(),
15121490
feerate_per_kw,
15131491
&mut vec![(accepted_htlc_info, ())],
1514-
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable()
1492+
&local_chan.funding.channel_transaction_parameters.as_counterparty_broadcastable(),
1493+
&secp_ctx,
15151494
);
15161495
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(
15171496
&local_chan.funding.channel_transaction_parameters, &commitment_tx, Vec::new(),

0 commit comments

Comments
 (0)