Skip to content

Commit 5ae1430

Browse files
committed
Remove explicit per-commitment key derivations from channel objects
Channel objects should not impose a particular per-commitment derivation scheme on the builders of commitment transactions. This will make it easier to enable custom derivations in the future. Instead of building `TxCreationKeys` explicitly, the function `TrustedCommitmentTransaction::keys` should be used when the keys of the commitment transaction are needed. We do that in this commit.
1 parent c89b6ae commit 5ae1430

File tree

1 file changed

+21
-59
lines changed

1 file changed

+21
-59
lines changed

lightning/src/ln/channel.rs

Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::ln::script::{self, ShutdownScript};
4141
use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails};
4242
use crate::ln::channelmanager::{self, OpenChannelMessage, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentClaimDetails, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
4343
use crate::ln::chan_utils::{
44-
CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight,
44+
CounterpartyCommitmentSecrets, HTLCOutputInCommitment, htlc_success_tx_weight,
4545
htlc_timeout_tx_weight, ChannelPublicKeys, CommitmentTransaction,
4646
HolderCommitmentTransaction, ChannelTransactionParameters,
4747
CounterpartyChannelTransactionParameters, MAX_HTLCS,
@@ -2036,8 +2036,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20362036
) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
20372037
let funding_script = self.funding().get_funding_redeemscript();
20382038

2039-
let keys = self.context().build_holder_transaction_keys(&self.funding(), holder_commitment_point.current_point());
2040-
let initial_commitment_tx = self.context().build_commitment_transaction(self.funding(), holder_commitment_point.transaction_number(), &keys, true, false, logger).tx;
2039+
let initial_commitment_tx = self.context().build_commitment_transaction(self.funding(), holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger).tx;
20412040
let trusted_tx = initial_commitment_tx.trust();
20422041
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
20432042
let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().get_value_satoshis());
@@ -2074,8 +2073,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20742073
}
20752074
};
20762075
let context = self.context();
2077-
let counterparty_keys = context.build_remote_transaction_keys(self.funding());
2078-
let counterparty_initial_commitment_tx = context.build_commitment_transaction(self.funding(), context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
2076+
let counterparty_initial_commitment_tx = context.build_commitment_transaction(self.funding(), context.cur_counterparty_commitment_transaction_number, &context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
20792077
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
20802078
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
20812079

@@ -3459,9 +3457,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34593457
{
34603458
let funding_script = funding.get_funding_redeemscript();
34613459

3462-
let keys = self.build_holder_transaction_keys(funding, holder_commitment_point.current_point());
3463-
3464-
let commitment_stats = self.build_commitment_transaction(funding, holder_commitment_point.transaction_number(), &keys, true, false, logger);
3460+
let commitment_stats = self.build_commitment_transaction(funding, holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger);
34653461
let commitment_txid = {
34663462
let trusted_tx = commitment_stats.tx.trust();
34673463
let bitcoin_tx = trusted_tx.built_transaction();
@@ -3529,19 +3525,20 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35293525

35303526
let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
35313527
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
3528+
let holder_keys = commitment_stats.tx.trust().keys();
35323529
for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
35333530
if let Some(_) = htlc.transaction_output_index {
35343531
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
35353532
funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.channel_type,
3536-
&keys.broadcaster_delayed_payment_key, &keys.revocation_key);
3533+
&holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key);
35373534

3538-
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.channel_type, &keys);
3535+
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.channel_type, &holder_keys);
35393536
let htlc_sighashtype = if self.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
35403537
let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
35413538
log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
3542-
log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
3539+
log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(holder_keys.countersignatory_htlc_key.to_public_key().serialize()),
35433540
encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.channel_id());
3544-
if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
3541+
if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &holder_keys.countersignatory_htlc_key.to_public_key()) {
35453542
return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned()));
35463543
}
35473544
if !separate_nondust_htlc_sources {
@@ -3590,7 +3587,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35903587
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
35913588
/// which peer generated this transaction and "to whom" this transaction flows.
35923589
#[inline]
3593-
fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats
3590+
fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats
35943591
where L::Target: Logger
35953592
{
35963593
let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
@@ -3792,7 +3789,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
37923789
if local { funding.channel_transaction_parameters.as_holder_broadcastable() }
37933790
else { funding.channel_transaction_parameters.as_counterparty_broadcastable() };
37943791
let tx = CommitmentTransaction::new(commitment_number,
3795-
&keys.per_commitment_point,
3792+
&per_commitment_point,
37963793
value_to_a as u64,
37973794
value_to_b as u64,
37983795
feerate_per_kw,
@@ -3818,32 +3815,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38183815
}
38193816
}
38203817

3821-
#[inline]
3822-
/// Creates a set of keys for build_commitment_transaction to generate a transaction which our
3823-
/// counterparty will sign (ie DO NOT send signatures over a transaction created by this to
3824-
/// our counterparty!)
3825-
/// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction)
3826-
/// TODO Some magic rust shit to compile-time check this?
3827-
fn build_holder_transaction_keys(&self, funding: &FundingScope, per_commitment_point: PublicKey) -> TxCreationKeys {
3828-
let delayed_payment_base = &funding.get_holder_pubkeys().delayed_payment_basepoint;
3829-
let htlc_basepoint = &funding.get_holder_pubkeys().htlc_basepoint;
3830-
let counterparty_pubkeys = funding.get_counterparty_pubkeys();
3831-
3832-
TxCreationKeys::derive_new(&self.secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint)
3833-
}
3834-
3835-
#[inline]
3836-
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
3837-
/// will sign and send to our counterparty.
3838-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
3839-
fn build_remote_transaction_keys(&self, funding: &FundingScope) -> TxCreationKeys {
3840-
let revocation_basepoint = &funding.get_holder_pubkeys().revocation_basepoint;
3841-
let htlc_basepoint = &funding.get_holder_pubkeys().htlc_basepoint;
3842-
let counterparty_pubkeys = funding.get_counterparty_pubkeys();
3843-
3844-
TxCreationKeys::derive_new(&self.secp_ctx, &self.counterparty_cur_commitment_point.unwrap(), &counterparty_pubkeys.delayed_payment_basepoint, &counterparty_pubkeys.htlc_basepoint, revocation_basepoint, htlc_basepoint)
3845-
}
3846-
38473818
pub fn get_feerate_sat_per_1000_weight(&self) -> u32 {
38483819
self.feerate_per_kw
38493820
}
@@ -4627,9 +4598,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
46274598
SP::Target: SignerProvider,
46284599
L::Target: Logger
46294600
{
4630-
let counterparty_keys = self.build_remote_transaction_keys(funding);
46314601
let counterparty_initial_commitment_tx = self.build_commitment_transaction(
4632-
funding, self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
4602+
funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
46334603
match self.holder_signer {
46344604
// TODO (taproot|arik): move match into calling method for Taproot
46354605
ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -6296,8 +6266,7 @@ impl<SP: Deref> FundedChannel<SP> where
62966266
// Before proposing a feerate update, check that we can actually afford the new fee.
62976267
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
62986268
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
6299-
let keys = self.context.build_holder_transaction_keys(&self.funding, self.holder_commitment_point.current_point());
6300-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &keys, true, true, logger);
6269+
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, true, logger);
63016270
let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
63026271
let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
63036272
if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
@@ -6610,8 +6579,7 @@ impl<SP: Deref> FundedChannel<SP> where
66106579
self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
66116580
}
66126581
let funding_signed = if self.context.signer_pending_funding && !self.funding.is_outbound() {
6613-
let counterparty_keys = self.context.build_remote_transaction_keys(&self.funding);
6614-
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number + 1, &counterparty_keys, false, false, logger).tx;
6582+
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number + 1, &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
66156583
self.context.get_funding_signed_msg(&self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx)
66166584
} else { None };
66176585
// Provide a `channel_ready` message if we need to, but only if we're _not_ still pending
@@ -8551,8 +8519,7 @@ impl<SP: Deref> FundedChannel<SP> where
85518519
-> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
85528520
where L::Target: Logger
85538521
{
8554-
let counterparty_keys = self.context.build_remote_transaction_keys(&self.funding);
8555-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
8522+
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
85568523
let counterparty_commitment_tx = commitment_stats.tx;
85578524

85588525
#[cfg(any(test, fuzzing))]
@@ -8583,8 +8550,7 @@ impl<SP: Deref> FundedChannel<SP> where
85838550
#[cfg(any(test, fuzzing))]
85848551
self.build_commitment_no_state_update(logger);
85858552

8586-
let counterparty_keys = self.context.build_remote_transaction_keys(&self.funding);
8587-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
8553+
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
85888554
let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
85898555

85908556
match &self.context.holder_signer {
@@ -8612,6 +8578,7 @@ impl<SP: Deref> FundedChannel<SP> where
86128578
&counterparty_commitment_txid, encode::serialize_hex(&self.funding.get_funding_redeemscript()),
86138579
log_bytes!(signature.serialize_compact()[..]), &self.context.channel_id());
86148580

8581+
let counterparty_keys = commitment_stats.tx.trust().keys();
86158582
for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) {
86168583
log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}",
86178584
encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.funding.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)),
@@ -9069,8 +9036,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
90699036

90709037
/// Only allowed after [`FundingScope::channel_transaction_parameters`] is set.
90719038
fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
9072-
let counterparty_keys = self.context.build_remote_transaction_keys(&self.funding);
9073-
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
9039+
let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
90749040
let signature = match &self.context.holder_signer {
90759041
// TODO (taproot|arik): move match into calling method for Taproot
90769042
ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11596,7 +11562,7 @@ mod tests {
1159611562
use bitcoin::secp256k1::Message;
1159711563
use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ecdsa::EcdsaChannelSigner};
1159811564
use crate::types::payment::PaymentPreimage;
11599-
use crate::ln::channel::{HTLCOutputInCommitment ,TxCreationKeys};
11565+
use crate::ln::channel::HTLCOutputInCommitment;
1160011566
use crate::ln::channel_keys::{DelayedPaymentBasepoint, HtlcBasepoint};
1160111567
use crate::ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters};
1160211568
use crate::util::logger::Logger;
@@ -11664,11 +11630,6 @@ mod tests {
1166411630
// build_commitment_transaction.
1166511631
let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
1166611632
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
11667-
let directed_params = chan.funding.channel_transaction_parameters.as_holder_broadcastable();
11668-
let keys = TxCreationKeys::from_channel_static_keys(
11669-
&per_commitment_point, directed_params.broadcaster_pubkeys(),
11670-
directed_params.countersignatory_pubkeys(), &secp_ctx,
11671-
);
1167211633

1167311634
macro_rules! test_commitment {
1167411635
( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $($remain:tt)* ) => {
@@ -11689,7 +11650,7 @@ mod tests {
1168911650
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
1169011651
} ) => { {
1169111652
let (commitment_tx, htlcs): (_, Vec<HTLCOutputInCommitment>) = {
11692-
let mut commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &keys, true, false, &logger);
11653+
let mut commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
1169311654

1169411655
let htlcs = commitment_stats.htlcs_included.drain(..)
1169511656
.filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })
@@ -11737,6 +11698,7 @@ mod tests {
1173711698
let remote_signature = Signature::from_der(&<Vec<u8>>::from_hex($counterparty_htlc_sig_hex).unwrap()[..]).unwrap();
1173811699

1173911700
let ref htlc = htlcs[$htlc_idx];
11701+
let keys = commitment_tx.trust().keys();
1174011702
let mut htlc_tx = chan_utils::build_htlc_transaction(&unsigned_tx.txid, chan.context.feerate_per_kw,
1174111703
chan.funding.get_counterparty_selected_contest_delay().unwrap(),
1174211704
&htlc, $opt_anchors, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);

0 commit comments

Comments
 (0)