Skip to content

Commit a50d32d

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 2a82a1f commit a50d32d

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};
@@ -3472,11 +3472,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34723472
) -> CommitmentTransaction {
34733473
let channel_parameters =
34743474
&self.onchain_tx_handler.channel_transaction_parameters.as_counterparty_broadcastable();
3475-
let keys = TxCreationKeys::from_channel_static_keys(&their_per_commitment_point,
3476-
channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), &self.onchain_tx_handler.secp_ctx);
3477-
3478-
CommitmentTransaction::new(commitment_number,
3479-
to_broadcaster_value, to_countersignatory_value, keys, feerate_per_kw, nondust_htlcs, channel_parameters)
3475+
CommitmentTransaction::new(commitment_number, their_per_commitment_point,
3476+
to_broadcaster_value, to_countersignatory_value, feerate_per_kw, nondust_htlcs, channel_parameters, &self.onchain_tx_handler.secp_ctx)
34803477
}
34813478

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

1113-
let keys = TxCreationKeys {
1114-
per_commitment_point: dummy_key.clone(),
1115-
revocation_key: RevocationKey::from_basepoint(&secp_ctx, &RevocationBasepoint::from(dummy_key), &dummy_key),
1116-
broadcaster_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1117-
countersignatory_htlc_key: HtlcKey::from_basepoint(&secp_ctx, &HtlcBasepoint::from(dummy_key), &dummy_key),
1118-
broadcaster_delayed_payment_key: DelayedPaymentKey::from_basepoint(&secp_ctx, &DelayedPaymentBasepoint::from(dummy_key), &dummy_key),
1119-
};
11201113
let channel_pubkeys = ChannelPublicKeys {
11211114
funding_pubkey: dummy_key.clone(),
11221115
revocation_basepoint: RevocationBasepoint::from(dummy_key),
@@ -1136,7 +1129,7 @@ impl HolderCommitmentTransaction {
11361129
for _ in 0..nondust_htlcs.len() {
11371130
counterparty_htlc_sigs.push(dummy_sig);
11381131
}
1139-
let inner = CommitmentTransaction::new(0, 0, 0, keys, 0, nondust_htlcs.iter_mut(), &channel_parameters.as_counterparty_broadcastable());
1132+
let inner = CommitmentTransaction::new(0, &dummy_key.clone(), 0, 0, 0, nondust_htlcs.iter_mut(), &channel_parameters.as_counterparty_broadcastable(), &secp_ctx);
11401133
nondust_htlcs.sort_by_key(|htlc| htlc.transaction_output_index);
11411134
HolderCommitmentTransaction {
11421135
inner,
@@ -1443,9 +1436,10 @@ impl CommitmentTransaction {
14431436
/// Only include HTLCs that are above the dust limit for the channel.
14441437
///
14451438
/// This is not exported to bindings users due to the generic though we likely should expose a version without
1446-
pub fn new<'a>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, keys: TxCreationKeys, feerate_per_kw: u32, nondust_htlcs: impl Iterator<Item = &'a mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
1439+
pub fn new<'a>(commitment_number: u64, per_commitment_point: &PublicKey, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, feerate_per_kw: u32, nondust_htlcs: impl Iterator<Item = &'a mut HTLCOutputInCommitment>, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>) -> CommitmentTransaction {
14471440
let to_broadcaster_value_sat = Amount::from_sat(to_broadcaster_value_sat);
14481441
let to_countersignatory_value_sat = Amount::from_sat(to_countersignatory_value_sat);
1442+
let keys = TxCreationKeys::from_channel_static_keys(per_commitment_point, channel_parameters.broadcaster_pubkeys(), channel_parameters.countersignatory_pubkeys(), secp_ctx);
14491443

14501444
// Sort outputs and populate output indices while keeping track of the auxiliary data
14511445
let (outputs, nondust_htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, nondust_htlcs, channel_parameters).unwrap();
@@ -1896,8 +1890,8 @@ pub fn get_commitment_transaction_number_obscure_factor(
18961890
mod tests {
18971891
use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys};
18981892
use crate::chain;
1899-
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1900-
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
1893+
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
1894+
use bitcoin::secp256k1::{self, PublicKey, SecretKey, Secp256k1};
19011895
use crate::util::test_utils;
19021896
use crate::sign::{ChannelSigner, SignerProvider};
19031897
use bitcoin::{Network, Txid, ScriptBuf, CompressedPublicKey};
@@ -1912,11 +1906,12 @@ mod tests {
19121906

19131907
struct TestCommitmentTxBuilder {
19141908
commitment_number: u64,
1915-
keys: TxCreationKeys,
1909+
per_commitment_point: PublicKey,
19161910
feerate_per_kw: u32,
19171911
nondust_htlcs: Vec<HTLCOutputInCommitment>,
19181912
channel_parameters: ChannelTransactionParameters,
19191913
counterparty_pubkeys: ChannelPublicKeys,
1914+
secp_ctx: Secp256k1::<secp256k1::All>,
19201915
}
19211916

19221917
impl TestCommitmentTxBuilder {
@@ -1927,13 +1922,10 @@ mod tests {
19271922
let keys_provider = test_utils::TestKeysInterface::new(&seed, network);
19281923
let signer = keys_provider.derive_channel_signer(3000, keys_provider.generate_channel_keys_id(false, 1_000_000, 0));
19291924
let counterparty_signer = keys_provider.derive_channel_signer(3000, keys_provider.generate_channel_keys_id(true, 1_000_000, 1));
1930-
let delayed_payment_base = &signer.pubkeys().delayed_payment_basepoint;
19311925
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
19321926
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
1933-
let htlc_basepoint = &signer.pubkeys().htlc_basepoint;
19341927
let holder_pubkeys = signer.pubkeys();
19351928
let counterparty_pubkeys = counterparty_signer.pubkeys().clone();
1936-
let keys = TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint);
19371929
let channel_parameters = ChannelTransactionParameters {
19381930
holder_pubkeys: holder_pubkeys.clone(),
19391931
holder_selected_contest_delay: 0,
@@ -1946,19 +1938,19 @@ mod tests {
19461938

19471939
Self {
19481940
commitment_number: 0,
1949-
keys,
1941+
per_commitment_point,
19501942
feerate_per_kw: 1,
19511943
nondust_htlcs,
19521944
channel_parameters,
19531945
counterparty_pubkeys,
1946+
secp_ctx,
19541947
}
19551948
}
19561949

19571950
fn build(&mut self, to_broadcaster_sats: u64, to_countersignatory_sats: u64) -> CommitmentTransaction {
19581951
CommitmentTransaction::new(
1959-
self.commitment_number, to_broadcaster_sats, to_countersignatory_sats,
1960-
self.keys.clone(), self.feerate_per_kw,
1961-
self.nondust_htlcs.iter_mut(), &self.channel_parameters.as_holder_broadcastable()
1952+
self.commitment_number, &self.per_commitment_point, to_broadcaster_sats, to_countersignatory_sats, self.feerate_per_kw,
1953+
self.nondust_htlcs.iter_mut(), &self.channel_parameters.as_holder_broadcastable(), &self.secp_ctx
19621954
)
19631955
}
19641956
}
@@ -2006,7 +1998,7 @@ mod tests {
20061998
builder.channel_parameters.channel_type_features = ChannelTypeFeatures::only_static_remote_key();
20071999
builder.nondust_htlcs = vec![received_htlc.clone(), offered_htlc.clone()];
20082000
let tx = builder.build(3000, 0);
2009-
let keys = &builder.keys.clone();
2001+
let keys = &tx.trust().keys();
20102002
assert_eq!(tx.built.transaction.output.len(), 3);
20112003
assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, &ChannelTypeFeatures::only_static_remote_key(), &keys).to_p2wsh());
20122004
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
@@ -3614,12 +3614,13 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36143614
if local { self.channel_transaction_parameters.as_holder_broadcastable() }
36153615
else { self.channel_transaction_parameters.as_counterparty_broadcastable() };
36163616
let tx = CommitmentTransaction::new(commitment_number,
3617+
&keys.per_commitment_point,
36173618
value_to_a as u64,
36183619
value_to_b as u64,
3619-
keys.clone(),
36203620
feerate_per_kw,
36213621
included_non_dust_htlcs.iter_mut().map(|(htlc, _)| htlc),
3622-
&channel_parameters
3622+
&channel_parameters,
3623+
&self.secp_ctx,
36233624
);
36243625
let mut htlcs_included = included_non_dust_htlcs;
36253626
// 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
@@ -731,29 +731,14 @@ fn test_update_fee_that_funder_cannot_afford() {
731731

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

753-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
754-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
755-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
756-
757742
let res = {
758743
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
759744
let local_chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
@@ -762,12 +747,13 @@ fn test_update_fee_that_funder_cannot_afford() {
762747
let mut htlcs: Vec<HTLCOutputInCommitment> = vec![];
763748
let commitment_tx = CommitmentTransaction::new(
764749
INITIAL_COMMITMENT_NUMBER - 1,
750+
&remote_point,
765751
push_sats,
766752
channel_value - push_sats - commit_tx_fee_msat(non_buffer_feerate + 4, 0, &channel_type_features) / 1000,
767-
commit_tx_keys.clone(),
768753
non_buffer_feerate + 4,
769754
htlcs.iter_mut(),
770-
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
755+
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable(),
756+
&secp_ctx,
771757
);
772758
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
773759
};
@@ -1454,33 +1440,25 @@ fn test_fee_spike_violation_fails_htlc() {
14541440

14551441
// Get the TestChannelSigner for each channel, which will be used to (1) get the keys
14561442
// needed to sign the new commitment tx and (2) sign the new commitment tx.
1457-
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point) = {
1443+
let (local_secret, next_local_point) = {
14581444
let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
14591445
let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
14601446
let local_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14611447
let chan_signer = local_chan.get_signer();
14621448
// Make the signer believe we validated another commitment, so we can release the secret
14631449
chan_signer.as_ecdsa().unwrap().get_enforcement_state().last_holder_commitment -= 1;
14641450

1465-
let pubkeys = chan_signer.as_ref().pubkeys();
1466-
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
1467-
chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
1451+
(chan_signer.as_ref().release_commitment_secret(INITIAL_COMMITMENT_NUMBER).unwrap(),
14681452
chan_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx).unwrap())
14691453
};
1470-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_point) = {
1454+
let remote_point = {
14711455
let per_peer_state = nodes[1].node.per_peer_state.read().unwrap();
14721456
let chan_lock = per_peer_state.get(&nodes[0].node.get_our_node_id()).unwrap().lock().unwrap();
14731457
let remote_chan = chan_lock.channel_by_id.get(&chan.2).and_then(Channel::as_funded).unwrap();
14741458
let chan_signer = remote_chan.get_signer();
1475-
let pubkeys = chan_signer.as_ref().pubkeys();
1476-
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1477-
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()
14781460
};
14791461

1480-
// Assemble the set of keys we can use for signatures for our commitment_signed message.
1481-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
1482-
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint);
1483-
14841462
// Build the remote commitment transaction so we can sign it, and then later use the
14851463
// signature for the commitment_signed message.
14861464
let local_chan_balance = 1313;
@@ -1502,12 +1480,13 @@ fn test_fee_spike_violation_fails_htlc() {
15021480
let local_chan_signer = local_chan.get_signer();
15031481
let commitment_tx = CommitmentTransaction::new(
15041482
commitment_number,
1483+
&remote_point,
15051484
95000,
15061485
local_chan_balance,
1507-
commit_tx_keys.clone(),
15081486
feerate_per_kw,
15091487
vec![accepted_htlc_info].iter_mut(),
1510-
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable()
1488+
&local_chan.context.channel_transaction_parameters.as_counterparty_broadcastable(),
1489+
&secp_ctx,
15111490
);
15121491
local_chan_signer.as_ecdsa().unwrap().sign_counterparty_commitment(&commitment_tx, Vec::new(), Vec::new(), &secp_ctx).unwrap()
15131492
};

0 commit comments

Comments
 (0)