Skip to content

Commit 42d7738

Browse files
devrandomTheBlueMatt
authored andcommitted
Provide remote channel public keys to signer
1 parent 09d2a71 commit 42d7738

File tree

7 files changed

+97
-26
lines changed

7 files changed

+97
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/target/
2+
/hfuzz_target/
23
/net-tokio/target/
34
**/*.rs.bk
45
Cargo.lock

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl KeysInterface for KeyProvider {
158158
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(),
159159
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(),
160160
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id],
161-
remote_funding_pubkey: None,
161+
remote_channel_pubkeys: None,
162162
})
163163
}
164164

fuzz/src/full_stack.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ impl KeysInterface for KeyProvider {
257257
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ctr]).unwrap(),
258258
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, ctr]).unwrap(),
259259
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr],
260-
remote_funding_pubkey: None,
260+
remote_channel_pubkeys: None,
261261
}
262262
} else {
263263
InMemoryChannelKeys {
@@ -267,7 +267,7 @@ impl KeysInterface for KeyProvider {
267267
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, ctr]).unwrap(),
268268
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, ctr]).unwrap(),
269269
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr],
270-
remote_funding_pubkey: None,
270+
remote_channel_pubkeys: None,
271271
}
272272
})
273273
}

lightning/src/chain/keysinterface.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use util::logger::Logger;
2424
use util::ser::Writeable;
2525

2626
use ln::chan_utils;
27-
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript};
27+
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys};
2828
use ln::msgs;
2929

3030
use std::sync::Arc;
@@ -142,7 +142,7 @@ pub trait ChannelKeys : Send {
142142
/// TODO: Document the things someone using this interface should enforce before signing.
143143
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
144144
/// making the callee generate it via some util function we expose)!
145-
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
145+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
146146

147147
/// Create a signature for a (proposed) closing transaction.
148148
///
@@ -158,11 +158,11 @@ pub trait ChannelKeys : Send {
158158
/// protocol.
159159
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
160160

161-
/// Set the remote funding key. This is done immediately on incoming channels
161+
/// Set the remote channel basepoints. This is done immediately on incoming channels
162162
/// and as soon as the channel is accepted on outgoing channels.
163163
///
164164
/// Will be called before any signatures are applied.
165-
fn set_remote_funding_pubkey(&mut self, key: &PublicKey);
165+
fn set_remote_channel_pubkeys(&mut self, channel_points: &ChannelPublicKeys);
166166
}
167167

168168
#[derive(Clone)]
@@ -181,7 +181,7 @@ pub struct InMemoryChannelKeys {
181181
/// Commitment seed
182182
pub commitment_seed: [u8; 32],
183183
/// Remote funding pubkey
184-
pub remote_funding_pubkey: Option<PublicKey>,
184+
pub remote_channel_pubkeys: Option<ChannelPublicKeys>,
185185
}
186186

187187
impl ChannelKeys for InMemoryChannelKeys {
@@ -192,12 +192,12 @@ impl ChannelKeys for InMemoryChannelKeys {
192192
fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
193193
fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
194194

195-
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
195+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
196196
if commitment_tx.input.len() != 1 { return Err(()); }
197197

198198
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
199-
let remote_funding_pubkey = self.remote_funding_pubkey.as_ref().expect("must set remote funding key before signing");
200-
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, remote_funding_pubkey);
199+
let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
200+
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
201201

202202
let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, channel_value_satoshis)[..]);
203203
let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
@@ -236,9 +236,9 @@ impl ChannelKeys for InMemoryChannelKeys {
236236
Ok(secp_ctx.sign(&msghash, &self.funding_key))
237237
}
238238

239-
fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
240-
assert!(self.remote_funding_pubkey.is_none(), "Already set remote funding key");
241-
self.remote_funding_pubkey = Some(*key);
239+
fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
240+
assert!(self.remote_channel_pubkeys.is_none(), "Already set remote channel pubkeys");
241+
self.remote_channel_pubkeys = Some(channel_pubkeys.clone());
242242
}
243243
}
244244

@@ -249,7 +249,7 @@ impl_writeable!(InMemoryChannelKeys, 0, {
249249
delayed_payment_base_key,
250250
htlc_base_key,
251251
commitment_seed,
252-
remote_funding_pubkey
252+
remote_channel_pubkeys
253253
});
254254

255255
/// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
@@ -398,7 +398,7 @@ impl KeysInterface for KeysManager {
398398
delayed_payment_base_key,
399399
htlc_base_key,
400400
commitment_seed,
401-
remote_funding_pubkey: None,
401+
remote_channel_pubkeys: None,
402402
}
403403
}
404404

lightning/src/ln/chan_utils.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub(super) fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx:
118118

119119
/// The set of public keys which are used in the creation of one commitment transaction.
120120
/// These are derived from the channel base keys and per-commitment data.
121+
#[derive(PartialEq)]
121122
pub struct TxCreationKeys {
122123
/// The per-commitment public key which was used to derive the other keys.
123124
pub per_commitment_point: PublicKey,
@@ -134,8 +135,40 @@ pub struct TxCreationKeys {
134135
pub b_payment_key: PublicKey,
135136
}
136137

138+
/// One counterparty's public keys which do not change over the life of a channel.
139+
#[derive(Clone)]
140+
pub struct ChannelPublicKeys {
141+
/// The public key which is used to sign all commitment transactions, as it appears in the
142+
/// on-chain channel lock-in 2-of-2 multisig output.
143+
pub funding_pubkey: PublicKey,
144+
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
145+
/// revocation keys. The per-commitment revocation private key is then revealed by the owner of
146+
/// a commitment transaction so that their counterparty can claim all available funds if they
147+
/// broadcast an old state.
148+
pub revocation_basepoint: PublicKey,
149+
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
150+
/// public key which receives immediately-spendable non-HTLC-encumbered funds.
151+
pub payment_basepoint: PublicKey,
152+
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
153+
/// public key which receives non-HTLC-encumbered funds which are only available for spending
154+
/// after some delay (or can be claimed via the revocation path).
155+
pub delayed_payment_basepoint: PublicKey,
156+
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
157+
/// which is used to encumber HTLC-in-flight outputs.
158+
pub htlc_basepoint: PublicKey,
159+
}
160+
161+
impl_writeable!(ChannelPublicKeys, 33*5, {
162+
funding_pubkey,
163+
revocation_basepoint,
164+
payment_basepoint,
165+
delayed_payment_basepoint,
166+
htlc_basepoint
167+
});
168+
169+
137170
impl TxCreationKeys {
138-
pub(super) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
171+
pub(crate) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
139172
Ok(TxCreationKeys {
140173
per_commitment_point: per_commitment_point.clone(),
141174
revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)?,

lightning/src/ln/channel.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use ln::msgs;
2020
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
2121
use ln::channelmonitor::ChannelMonitor;
2222
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
23-
use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript};
23+
use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys};
2424
use ln::chan_utils;
2525
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
2626
use chain::transaction::OutPoint;
@@ -546,7 +546,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
546546
/// Assumes chain_hash has already been checked and corresponds with what we expect!
547547
pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface<ChanKeySigner = ChanSigner>>, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, ChannelError> {
548548
let mut chan_keys = keys_provider.get_channel_keys(true);
549-
chan_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
549+
let channel_pubkeys = ChannelPublicKeys {
550+
funding_pubkey: msg.funding_pubkey,
551+
revocation_basepoint: msg.revocation_basepoint,
552+
payment_basepoint: msg.payment_basepoint,
553+
delayed_payment_basepoint: msg.delayed_payment_basepoint,
554+
htlc_basepoint: msg.htlc_basepoint
555+
};
556+
chan_keys.set_remote_channel_pubkeys(&channel_pubkeys);
550557
let mut local_config = (*config).channel_options.clone();
551558

552559
if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
@@ -1401,7 +1408,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
14011408
self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor);
14021409

14031410
self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
1404-
self.local_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
1411+
let channel_pubkeys = ChannelPublicKeys {
1412+
funding_pubkey: msg.funding_pubkey,
1413+
revocation_basepoint: msg.revocation_basepoint,
1414+
payment_basepoint: msg.payment_basepoint,
1415+
delayed_payment_basepoint: msg.delayed_payment_basepoint,
1416+
htlc_basepoint: msg.htlc_basepoint
1417+
};
1418+
self.local_keys.set_remote_channel_pubkeys(&channel_pubkeys);
14051419

14061420
Ok(())
14071421
}
@@ -4127,7 +4141,7 @@ mod tests {
41274141
// These aren't set in the test vectors:
41284142
revocation_base_key: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
41294143
commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
4130-
remote_funding_pubkey: None,
4144+
remote_channel_pubkeys: None,
41314145
};
41324146
assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
41334147
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);

lightning/src/util/enforcing_trait_impls.rs

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

@@ -27,6 +27,27 @@ impl EnforcingChannelKeys {
2727
}
2828
}
2929
}
30+
31+
impl EnforcingChannelKeys {
32+
fn check_keys<T: secp256k1::Signing + secp256k1::Verification>(&self, secp_ctx: &Secp256k1<T>,
33+
keys: &TxCreationKeys) {
34+
let revocation_base = PublicKey::from_secret_key(secp_ctx, &self.inner.revocation_base_key);
35+
let payment_base = PublicKey::from_secret_key(secp_ctx, &self.inner.payment_base_key);
36+
let htlc_base = PublicKey::from_secret_key(secp_ctx, &self.inner.htlc_base_key);
37+
38+
let remote_points = self.inner.remote_channel_pubkeys.as_ref().unwrap();
39+
40+
let keys_expected = TxCreationKeys::new(secp_ctx,
41+
&keys.per_commitment_point,
42+
&remote_points.delayed_payment_basepoint,
43+
&remote_points.htlc_basepoint,
44+
&revocation_base,
45+
&payment_base,
46+
&htlc_base).unwrap();
47+
if keys != &keys_expected { panic!("derived different per-tx keys") }
48+
}
49+
}
50+
3051
impl ChannelKeys for EnforcingChannelKeys {
3152
fn funding_key(&self) -> &SecretKey { self.inner.funding_key() }
3253
fn revocation_base_key(&self) -> &SecretKey { self.inner.revocation_base_key() }
@@ -35,8 +56,9 @@ impl ChannelKeys for EnforcingChannelKeys {
3556
fn htlc_base_key(&self) -> &SecretKey { self.inner.htlc_base_key() }
3657
fn commitment_seed(&self) -> &[u8; 32] { self.inner.commitment_seed() }
3758

38-
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
39-
if commitment_tx.input.len() != 1 { panic!(); }
59+
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
60+
if commitment_tx.input.len() != 1 { panic!("lightning commitment transactions have a single input"); }
61+
self.check_keys(secp_ctx, keys);
4062
let obscured_commitment_transaction_number = (commitment_tx.lock_time & 0xffffff) as u64 | ((commitment_tx.input[0].sequence as u64 & 0xffffff) << 3*8);
4163

4264
{
@@ -60,11 +82,12 @@ impl ChannelKeys for EnforcingChannelKeys {
6082
self.inner.sign_channel_announcement(msg, secp_ctx)
6183
}
6284

63-
fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
64-
self.inner.set_remote_funding_pubkey(key)
85+
fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
86+
self.inner.set_remote_channel_pubkeys(channel_pubkeys)
6587
}
6688
}
6789

90+
6891
impl_writeable!(EnforcingChannelKeys, 0, {
6992
inner,
7093
commitment_number_obscure_and_last

0 commit comments

Comments
 (0)