Skip to content

Commit f6c6c4f

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 7f15200 commit f6c6c4f

File tree

4 files changed

+30
-61
lines changed

4 files changed

+30
-61
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};
@@ -3486,11 +3486,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34863486
) -> CommitmentTransaction {
34873487
let channel_parameters =
34883488
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3489-
let keys = TxCreationKeys::from_channel_static_keys(&their_per_commitment_point,
3490-
channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), &self.onchain_tx_handler.secp_ctx);
3491-
3492-
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3493-
to_broadcaster_value, to_countersignatory_value, keys, feerate_per_kw, &mut nondust_htlcs, channel_parameters)
3489+
CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number, their_per_commitment_point,
3490+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, &mut nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
34943491
}
34953492

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

lightning/src/ln/chan_utils.rs

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

1137-
let keys = TxCreationKeys {
1138-
per_commitment_point: dummy_key.clone(),
1139-
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1140-
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1141-
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1142-
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1143-
};
11441137
let channel_pubkeys = ChannelPublicKeys {
11451138
funding_pubkey: dummy_key.clone(),
11461139
revocation_basepoint: RevocationBasepoint::from(dummy_key),
@@ -1161,7 +1154,7 @@ impl HolderCommitmentTransaction {
11611154
for _ in 0..htlcs.len() {
11621155
counterparty_htlc_sigs.push(dummy_sig);
11631156
}
1164-
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
1157+
let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, &dummy_key.clone(), 0, 0, 0, htlcs, &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
11651158
htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
11661159
HolderCommitmentTransaction {
11671160
inner,
@@ -1471,9 +1464,10 @@ impl CommitmentTransaction {
14711464
/// Only include HTLCs that are above the dust limit for the channel.
14721465
///
14731466
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1474-
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 {
1467+
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 {
14751468
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
14761469
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
1470+
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
14771471

14781472
// Sort outputs and populate output indices while keeping track of the auxiliary data
14791473
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters).unwrap();
@@ -1922,8 +1916,8 @@ pub fn get_commitment_transaction_number_obscure_factor(
19221916
mod tests {
19231917
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
19241918
use crate::chain;
1925-
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1926-
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1919+
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1920+
use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1};
19271921
use crate::util::test_utils;
19281922
use crate::sign::{ChannelSigner, SignerProvider};
19291923
use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey};
@@ -1938,11 +1932,12 @@ mod tests {
19381932

19391933
struct TestCommitmentTxBuilder {
19401934
commitment_number: u64,
1941-
keys: TxCreationKeys,
1935+
per_commitment_point: PublicKey,
19421936
feerate_per_kw: u32,
19431937
htlcs_with_aux: Vec<(HTLCOutputInCommitment, ())>,
19441938
channel_parameters: ChannelTransactionParameters,
19451939
counterparty_pubkeys: ChannelPublicKeys,
1940+
secp_ctx: Secp256k1::<secp256k1::All>,
19461941
}
19471942

19481943
impl TestCommitmentTxBuilder {
@@ -1953,13 +1948,10 @@ mod tests {
19531948
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
19541949
let signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(false, 0));
19551950
let counterparty_signer = keys_provider.derive_channel_signer(keys_provider.generate_channel_keys_id(true, 1));
1956-
let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint;
19571951
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
19581952
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
1959-
let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
19601953
let holder_pubkeys = signer.pubkeys();
19611954
let counterparty_pubkeys = counterparty_signer.pubkeys().clone();
1962-
let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
19631955
let channel_parameters = ChannelTransactionParameters {
19641956
holder_pubkeys: holder_pubkeys.clone(),
19651957
holder_selected_contest_delay: 0,
@@ -1973,19 +1965,19 @@ mod tests {
19731965

19741966
Self {
19751967
commitment_number: 0,
1976-
keys,
1968+
per_commitment_point,
19771969
feerate_per_kw: 1,
19781970
htlcs_with_aux,
19791971
channel_parameters,
19801972
counterparty_pubkeys,
1973+
secp_ctx,
19811974
}
19821975
}
19831976

19841977
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
19851978
CommitmentTransaction::new_with_auxiliary_htlc_data(
1986-
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
1987-
self.keys.clone(), self.feerate_per_kw,
1988-
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable()
1979+
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
1980+
&mut self.htlcs_with_aux, &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
19891981
)
19901982
}
19911983
}
@@ -2033,7 +2025,7 @@ mod tests {
20332025
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
20342026
builder.htlcs_with_aux = vec![(received_htlc.clone(), ()), (offered_htlc.clone(), ())];
20352027
let tx = builder.build(3000, 0);
2036-
let keys = &builder.keys.clone();
2028+
let keys = &tx.trust().keys();
20372029
assert_eq!(tx.built.transaction.output.len(), 3);
20382030
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
20392031
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
@@ -3662,12 +3662,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36623662
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
36633663
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
36643664
let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(commitment_number,
3665+
&keys.per_commitment_point,
36653666
value_to_a as u64,
36663667
value_to_b as u64,
3667-
keys.clone(),
36683668
feerate_per_kw,
36693669
&mut included_non_dust_htlcs,
3670-
&channel_parameters
3670+
&channel_parameters,
3671+
&self.secp_ctx,
36713672
);
36723673
let mut htlcs_included = included_non_dust_htlcs;
36733674
// 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();
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();
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();
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();
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)