Skip to content

Commit f5b594d

Browse files
committed
Wrap TxCreationKeys in PreCalculatedTxCreationKeys, part 1
This makes it obvious to signer implementers that the pre-derived keys are a local cache and should not be trusted in a validating signer.
1 parent f61ce28 commit f5b594d

File tree

5 files changed

+44
-12
lines changed

5 files changed

+44
-12
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use util::byte_utils;
2323
use util::ser::{Writeable, Writer, Readable};
2424

2525
use ln::chan_utils;
26-
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction};
26+
use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction, PreCalculatedTxCreationKeys};
2727
use ln::msgs;
2828

2929
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -223,7 +223,7 @@ pub trait ChannelKeys : Send+Clone {
223223
// TODO: Document the things someone using this interface should enforce before signing.
224224
// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
225225
// making the callee generate it via some util function we expose)!
226-
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
226+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
227227

228228
/// Create a signature for a local commitment transaction. This will only ever be called with
229229
/// the same local_commitment_tx (or a copy thereof), though there are currently no guarantees
@@ -461,8 +461,9 @@ impl ChannelKeys for InMemoryChannelKeys {
461461
fn pubkeys(&self) -> &ChannelPublicKeys { &self.local_channel_pubkeys }
462462
fn key_derivation_params(&self) -> (u64, u64) { self.key_derivation_params }
463463

464-
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
464+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, pre_keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
465465
if commitment_tx.input.len() != 1 { return Err(()); }
466+
let keys = pre_keys.trust_key_derivation();
466467

467468
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
468469
let accepted_data = self.accepted_channel_data.as_ref().expect("must accept before signing");

lightning/src/ln/chan_utils.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,32 @@ pub struct TxCreationKeys {
284284
impl_writeable!(TxCreationKeys, 33*6,
285285
{ per_commitment_point, revocation_key, a_htlc_key, b_htlc_key, a_delayed_payment_key });
286286

287+
/// The per-commitment point and a set of pre-calculated public keys used for transaction creation
288+
/// in the signer.
289+
/// The pre-calculated keys are an optimization, because ChannelKeys has enough
290+
/// information to re-derive them.
291+
pub struct PreCalculatedTxCreationKeys {
292+
keys: TxCreationKeys
293+
}
294+
295+
impl PreCalculatedTxCreationKeys {
296+
/// Create a new PreCalculatedTxCreationKeys from TxCreationKeys
297+
pub fn new(keys: TxCreationKeys) -> Self {
298+
PreCalculatedTxCreationKeys{ keys }
299+
}
300+
301+
/// The pre-calculated transaction creation public keys.
302+
/// An external validating signer should not trust these keys.
303+
pub fn trust_key_derivation(&self) -> &TxCreationKeys {
304+
&self.keys
305+
}
306+
307+
/// The transaction per-commitment point
308+
pub fn per_comitment_point(&self) -> &PublicKey {
309+
&self.keys.per_commitment_point
310+
}
311+
}
312+
287313
/// One counterparty's public keys which do not change over the life of a channel.
288314
#[derive(Clone, PartialEq)]
289315
pub struct ChannelPublicKeys {

lightning/src/ln/channel.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ln::msgs;
1919
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
2020
use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
2121
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
22-
use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys};
22+
use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, PreCalculatedTxCreationKeys};
2323
use ln::chan_utils;
2424
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
2525
use chain::transaction::OutPoint;
@@ -1484,7 +1484,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
14841484

14851485
let remote_keys = self.build_remote_transaction_keys()?;
14861486
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw, logger).0;
1487-
let remote_signature = self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), &self.secp_ctx)
1487+
let pre_remote_keys = PreCalculatedTxCreationKeys::new(remote_keys);
1488+
let remote_signature = self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &pre_remote_keys, &Vec::new(), &self.secp_ctx)
14881489
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0;
14891490

14901491
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
@@ -3525,7 +3526,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
35253526
fn get_outbound_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
35263527
let remote_keys = self.build_remote_transaction_keys()?;
35273528
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw, logger).0;
3528-
Ok(self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &remote_keys, &Vec::new(), &self.secp_ctx)
3529+
let pre_remote_keys = PreCalculatedTxCreationKeys::new(remote_keys);
3530+
Ok(self.local_keys.sign_remote_commitment(self.feerate_per_kw, &remote_initial_commitment_tx, &pre_remote_keys, &Vec::new(), &self.secp_ctx)
35293531
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
35303532
}
35313533

@@ -3878,7 +3880,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
38783880
htlcs.push(htlc);
38793881
}
38803882

3881-
let res = self.local_keys.sign_remote_commitment(feerate_per_kw, &remote_commitment_tx.0, &remote_keys, &htlcs, &self.secp_ctx)
3883+
let pre_remote_keys = PreCalculatedTxCreationKeys::new(remote_keys.clone());
3884+
let res = self.local_keys.sign_remote_commitment(feerate_per_kw, &remote_commitment_tx.0, &pre_remote_keys, &htlcs, &self.secp_ctx)
38823885
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?;
38833886
signature = res.0;
38843887
htlc_signatures = res.1;

lightning/src/ln/functional_tests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use std::sync::atomic::Ordering;
5252
use std::{mem, io};
5353

5454
use ln::functional_test_utils::*;
55+
use ln::chan_utils::PreCalculatedTxCreationKeys;
5556

5657
#[test]
5758
fn test_insane_channel_opens() {
@@ -1694,7 +1695,8 @@ fn test_fee_spike_violation_fails_htlc() {
16941695
let local_chan_lock = nodes[0].node.channel_state.lock().unwrap();
16951696
let local_chan = local_chan_lock.by_id.get(&chan.2).unwrap();
16961697
let local_chan_keys = local_chan.get_local_keys();
1697-
local_chan_keys.sign_remote_commitment(feerate_per_kw, &commit_tx, &commit_tx_keys, &[&accepted_htlc_info], &secp_ctx).unwrap()
1698+
let pre_commit_tx_keys = PreCalculatedTxCreationKeys::new(commit_tx_keys);
1699+
local_chan_keys.sign_remote_commitment(feerate_per_kw, &commit_tx, &pre_commit_tx_keys, &[&accepted_htlc_info], &secp_ctx).unwrap()
16981700
};
16991701

17001702
let commit_signed_msg = msgs::CommitmentSigned {

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys, LocalCommitmentTransaction};
1+
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys, LocalCommitmentTransaction, PreCalculatedTxCreationKeys};
22
use ln::{chan_utils, msgs};
33
use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys};
44

@@ -60,9 +60,9 @@ impl ChannelKeys for EnforcingChannelKeys {
6060
fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() }
6161
fn key_derivation_params(&self) -> (u64, u64) { self.inner.key_derivation_params() }
6262

63-
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
63+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, pre_keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
6464
if commitment_tx.input.len() != 1 { panic!("lightning commitment transactions have a single input"); }
65-
self.check_keys(secp_ctx, keys);
65+
self.check_keys(secp_ctx, pre_keys.trust_key_derivation());
6666
let obscured_commitment_transaction_number = (commitment_tx.lock_time & 0xffffff) as u64 | ((commitment_tx.input[0].sequence as u64 & 0xffffff) << 3*8);
6767

6868
{
@@ -75,7 +75,7 @@ impl ChannelKeys for EnforcingChannelKeys {
7575
commitment_data.1 = cmp::max(commitment_number, commitment_data.1)
7676
}
7777

78-
Ok(self.inner.sign_remote_commitment(feerate_per_kw, commitment_tx, keys, htlcs, secp_ctx).unwrap())
78+
Ok(self.inner.sign_remote_commitment(feerate_per_kw, commitment_tx, pre_keys, htlcs, secp_ctx).unwrap())
7979
}
8080

8181
fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {

0 commit comments

Comments
 (0)