Skip to content

Commit d60cfda

Browse files
committed
Begin removing 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. To get us started, we remove most instances of `TxCreationKeys` in channel. The last two instances are 1) checking a counterparty's htlc signatures 2) logging the keys we used to create htlc signatures for a counterparty Both of these cases will be abstracted away from channel in the future.
1 parent a50d32d commit d60cfda

File tree

1 file changed

+19
-53
lines changed

1 file changed

+19
-53
lines changed

lightning/src/ln/channel.rs

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,8 +1968,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
19681968
) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
19691969
let funding_script = self.context().get_funding_redeemscript();
19701970

1971-
let keys = self.context().build_holder_transaction_keys(holder_commitment_point.current_point());
1972-
let initial_commitment_tx = self.context().build_commitment_transaction(self.funding(), holder_commitment_point.transaction_number(), &keys, true, false, logger).tx;
1971+
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;
19731972
let trusted_tx = initial_commitment_tx.trust();
19741973
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
19751974
let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().channel_value_satoshis);
@@ -2006,8 +2005,7 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20062005
}
20072006
};
20082007
let context = self.context();
2009-
let counterparty_keys = context.build_remote_transaction_keys();
2010-
let counterparty_initial_commitment_tx = context.build_commitment_transaction(self.funding(), context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
2008+
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;
20112009
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
20122010
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
20132011

@@ -3412,7 +3410,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34123410
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
34133411
/// which peer generated this transaction and "to whom" this transaction flows.
34143412
#[inline]
3415-
fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats
3413+
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
34163414
where L::Target: Logger
34173415
{
34183416
let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
@@ -3614,7 +3612,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36143612
if local { self.channel_transaction_parameters.as_holder_broadcastable() }
36153613
else { self.channel_transaction_parameters.as_counterparty_broadcastable() };
36163614
let tx = CommitmentTransaction::new(commitment_number,
3617-
&keys.per_commitment_point,
3615+
&per_commitment_point,
36183616
value_to_a as u64,
36193617
value_to_b as u64,
36203618
feerate_per_kw,
@@ -3640,32 +3638,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36403638
}
36413639
}
36423640

3643-
#[inline]
3644-
/// Creates a set of keys for build_commitment_transaction to generate a transaction which our
3645-
/// counterparty will sign (ie DO NOT send signatures over a transaction created by this to
3646-
/// our counterparty!)
3647-
/// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction)
3648-
/// TODO Some magic rust shit to compile-time check this?
3649-
fn build_holder_transaction_keys(&self, per_commitment_point: PublicKey) -> TxCreationKeys {
3650-
let delayed_payment_base = &self.get_holder_pubkeys().delayed_payment_basepoint;
3651-
let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint;
3652-
let counterparty_pubkeys = self.get_counterparty_pubkeys();
3653-
3654-
TxCreationKeys::derive_new(&self.secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &counterparty_pubkeys.revocation_basepoint, &counterparty_pubkeys.htlc_basepoint)
3655-
}
3656-
3657-
#[inline]
3658-
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
3659-
/// will sign and send to our counterparty.
3660-
/// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
3661-
fn build_remote_transaction_keys(&self) -> TxCreationKeys {
3662-
let revocation_basepoint = &self.get_holder_pubkeys().revocation_basepoint;
3663-
let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint;
3664-
let counterparty_pubkeys = self.get_counterparty_pubkeys();
3665-
3666-
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)
3667-
}
3668-
36693641
/// Gets the redeemscript for the funding transaction output (ie the funding transaction output
36703642
/// pays to get_funding_redeemscript().to_p2wsh()).
36713643
/// Panics if called before accept_channel/InboundV1Channel::new
@@ -4459,9 +4431,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
44594431
SP::Target: SignerProvider,
44604432
L::Target: Logger
44614433
{
4462-
let counterparty_keys = self.build_remote_transaction_keys();
44634434
let counterparty_initial_commitment_tx = self.build_commitment_transaction(
4464-
funding, self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).tx;
4435+
funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
44654436
match self.holder_signer {
44664437
// TODO (taproot|arik): move match into calling method for Taproot
44674438
ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -5454,9 +5425,7 @@ impl<SP: Deref> FundedChannel<SP> where
54545425

54555426
let funding_script = self.context.get_funding_redeemscript();
54565427

5457-
let keys = self.context.build_holder_transaction_keys(self.holder_commitment_point.current_point());
5458-
5459-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &keys, true, false, logger);
5428+
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, false, logger);
54605429
let commitment_txid = {
54615430
let trusted_tx = commitment_stats.tx.trust();
54625431
let bitcoin_tx = trusted_tx.built_transaction();
@@ -5524,19 +5493,20 @@ impl<SP: Deref> FundedChannel<SP> where
55245493

55255494
let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
55265495
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
5496+
let holder_keys = TxCreationKeys::from_channel_static_keys(&self.holder_commitment_point.current_point(), self.context.get_holder_pubkeys(), self.context.get_counterparty_pubkeys(), &self.context.secp_ctx);
55275497
for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
55285498
if let Some(_) = htlc.transaction_output_index {
55295499
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
55305500
self.context.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.context.channel_type,
5531-
&keys.broadcaster_delayed_payment_key, &keys.revocation_key);
5501+
&holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key);
55325502

5533-
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys);
5503+
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &holder_keys);
55345504
let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
55355505
let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
55365506
log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
5537-
log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
5507+
log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(holder_keys.countersignatory_htlc_key.to_public_key().serialize()),
55385508
encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
5539-
if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
5509+
if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &holder_keys.countersignatory_htlc_key.to_public_key()) {
55405510
return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned()));
55415511
}
55425512
if !separate_nondust_htlc_sources {
@@ -6218,8 +6188,7 @@ impl<SP: Deref> FundedChannel<SP> where
62186188
// Before proposing a feerate update, check that we can actually afford the new fee.
62196189
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
62206190
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
6221-
let keys = self.context.build_holder_transaction_keys(self.holder_commitment_point.current_point());
6222-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &keys, true, true, logger);
6191+
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);
62236192
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;
62246193
let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
62256194
if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
@@ -6532,8 +6501,7 @@ impl<SP: Deref> FundedChannel<SP> where
65326501
self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
65336502
}
65346503
let funding_signed = if self.context.signer_pending_funding && !self.context.is_outbound() {
6535-
let counterparty_keys = self.context.build_remote_transaction_keys();
6536-
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;
6504+
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;
65376505
self.context.get_funding_signed_msg(logger, counterparty_initial_commitment_tx)
65386506
} else { None };
65396507
// Provide a `channel_ready` message if we need to, but only if we're _not_ still pending
@@ -8469,8 +8437,7 @@ impl<SP: Deref> FundedChannel<SP> where
84698437
-> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
84708438
where L::Target: Logger
84718439
{
8472-
let counterparty_keys = self.context.build_remote_transaction_keys();
8473-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
8440+
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);
84748441
let counterparty_commitment_tx = commitment_stats.tx;
84758442

84768443
#[cfg(any(test, fuzzing))]
@@ -8501,8 +8468,7 @@ impl<SP: Deref> FundedChannel<SP> where
85018468
#[cfg(any(test, fuzzing))]
85028469
self.build_commitment_no_state_update(logger);
85038470

8504-
let counterparty_keys = self.context.build_remote_transaction_keys();
8505-
let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
8471+
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);
85068472
let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
85078473

85088474
match &self.context.holder_signer {
@@ -8528,7 +8494,8 @@ impl<SP: Deref> FundedChannel<SP> where
85288494
encode::serialize_hex(&commitment_stats.tx.trust().built_transaction().transaction),
85298495
&counterparty_commitment_txid, encode::serialize_hex(&self.context.get_funding_redeemscript()),
85308496
log_bytes!(signature.serialize_compact()[..]), &self.context.channel_id());
8531-
8497+
8498+
let counterparty_keys = TxCreationKeys::from_channel_static_keys(&self.context.counterparty_cur_commitment_point.unwrap(), self.context.get_counterparty_pubkeys(), self.context.get_holder_pubkeys(), &self.context.secp_ctx);
85328499
for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) {
85338500
log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}",
85348501
encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.feerate_per_kw, self.context.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)),
@@ -8980,8 +8947,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
89808947

89818948
/// Only allowed after [`ChannelContext::channel_transaction_parameters`] is set.
89828949
fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
8983-
let counterparty_keys = self.context.build_remote_transaction_keys();
8984-
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;
8950+
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;
89858951
let signature = match &self.context.holder_signer {
89868952
// TODO (taproot|arik): move match into calling method for Taproot
89878953
ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11633,7 +11599,7 @@ mod tests {
1163311599
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
1163411600
} ) => { {
1163511601
let (commitment_tx, htlcs): (_, Vec<HTLCOutputInCommitment>) = {
11636-
let mut commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &keys, true, false, &logger);
11602+
let mut commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
1163711603

1163811604
let htlcs = commitment_stats.htlcs_included.drain(..)
1163911605
.filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })

0 commit comments

Comments
 (0)