Skip to content

Commit fd2571d

Browse files
committed
Significantly clarify key derivation and expose methods referenced
1 parent e3f9454 commit fd2571d

File tree

2 files changed

+66
-46
lines changed

2 files changed

+66
-46
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,30 @@ pub enum SpendableOutputDescriptor {
5656
/// <BIP 143 signature> <empty vector> (MINIMALIF standard rule) <provided witnessScript>
5757
///
5858
/// Note that the nSequence field in the spending input must be set to to_self_delay
59-
/// (which means the transaction not being broadcastable until at least to_self_delay
59+
/// (which means the transaction is not broadcastable until at least to_self_delay
6060
/// blocks after the outpoint confirms).
6161
///
6262
/// These are generally the result of a "revocable" output to us, spendable only by us unless
63-
/// it is an output from us having broadcast an old state (which should never happen).
63+
/// it is an output from an old state which we broadcast (which should never happen).
6464
///
65-
/// WitnessScript may be regenerated by passing the revocation_pubkey, to_self_delay and
66-
/// delayed_payment_pubkey to chan_utils::get_revokeable_redeemscript.
65+
/// To derive the delayed_payment key which is used to sign for this input, you must pass the
66+
/// local delayed_payment_base_key (ie the private key which corresponds to the pubkey in
67+
/// ChannelKeys::pubkeys().delayed_payment_basepoint) and the provided per_commitment_point to
68+
/// chan_utils::derive_private_key. The public key can be generated without the secret key
69+
/// using chan_utils::derive_public_key and only the delayed_payment_basepoint which appears in
70+
/// ChannelKeys::pubkeys().
6771
///
68-
/// To derive the delayed_payment key corresponding to the channel state, you must pass the
69-
/// local delayed_payment_base_key and the provided per_commitment_point to
70-
/// chan_utils::derive_private_key. The resulting key should be used to sign the spending
71-
/// transaction.
72-
///
73-
/// To derive the revocation_pubkey corresponding to the channel state, you must pass the
74-
/// remote revocation_basepoint and the provided per_commitment point to
72+
/// To derive the revocation_pubkey which is used in the witness script generation, you must
73+
/// pass the remote revocation_basepoint (which appears in the call to
74+
/// ChannelKeys::set_remote_channel_pubkeys) and the provided per_commitment point to
7575
/// chan_utils::derive_public_revocation_key.
7676
///
77-
/// Both remote revocation_basepoint and local delayed_payment_base_key should be given
78-
/// by ChannelKeys, either default implementation (InMemoryChannelKeys) or custom one.
77+
/// The witness script which is hashed and included in the output script_pubkey may be
78+
/// regenerated by passing the revocation_pubkey (derived as above), our delayed_payment pubkey
79+
/// (derived as above), and the to_self_delay contained here to
80+
/// chan_utils::get_revokeable_redeemscript.
81+
//
82+
// TODO: we need to expose utility methods in KeyManager to do all the relevant derivation.
7983
DynamicOutputP2WSH {
8084
/// The outpoint which is spendable
8185
outpoint: OutPoint,
@@ -92,7 +96,8 @@ pub enum SpendableOutputDescriptor {
9296
/// The remote_revocation_pubkey used to derive witnessScript
9397
remote_revocation_pubkey: PublicKey
9498
},
95-
/// An output to a P2WPKH, spendable exclusively by our payment key.
99+
/// An output to a P2WPKH, spendable exclusively by our payment key (ie the private key which
100+
/// corresponds to the public key in ChannelKeys::pubkeys().payment_point).
96101
/// The witness in the spending input, is, thus, simply:
97102
/// <BIP 143 signature> <payment key>
98103
///
@@ -272,47 +277,47 @@ pub trait ChannelKeys : Send+Clone {
272277
/// return value must contain a signature.
273278
fn sign_local_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()>;
274279

275-
/// Create a signature for a transaction spending an HTLC or commitment transaction output
276-
/// when our counterparty broadcast an old state.
280+
/// Create a signature for the given input in a transaction spending an HTLC or commitment
281+
/// transaction output when our counterparty broadcast an old state.
277282
///
278-
/// Justice transaction may claim multiples outputs at same time if timelock are similar.
283+
/// A justice transaction may claim multiples outputs at same time if timelock are similar,
284+
/// but only a signature for the input at index `input` should be signed for here.
279285
/// It may be called multiples time for same output(s) if a fee-bump is needed with regards
280286
/// to an upcoming timelock expiration.
281287
///
282-
/// Input index is a pointer towards outpoint spent, commited by sigs (BIP 143).
288+
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
283289
///
284-
/// Amount is value of the output spent by this input, committed by sigs (BIP 143).
290+
/// per_commitment_key is revocation secret which was provided by our counterparty when they
291+
/// revoked the state which they eventually broadcast. It's not a _local_ secret key and does
292+
/// not allow the spending of any funds by itself (you need our local revocation_secret to do
293+
/// so).
285294
///
286-
/// Per_commitment key is revocation secret such as provided by remote party while
287-
/// revocating detected onchain transaction. It's not a _local_ secret key, therefore
288-
/// it may cross interfaces, a node compromise won't allow to spend revoked output without
289-
/// also compromissing revocation key.
295+
/// htlc holds HTLC elements (hash, timelock) if the output being spent is a HTLC output, thus
296+
/// changing the format of the witness script (which is committed to in the BIP 143
297+
/// signatures).
290298
///
291-
/// htlc holds HTLC elements (hash, timelock) if output spent is a HTLC one, committed as
292-
/// part of witnessScript by sigs (BIP 143).
293-
///
294-
/// on_remote_tx_csv is the relative lock-time challenge if output spent is on remote
295-
/// balance or 2nd-stage HTLC transactions, committed as part of witnessScript by sigs
296-
/// (BIP 143).
299+
/// on_remote_tx_csv is the relative lock-time that that our counterparty would have to set on
300+
/// their transaction were they to spend the same output. It is included in the witness script
301+
/// and thus committed to in the BIP 143 signature.
297302
fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, on_remote_tx_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
298303

299304
/// Create a signature for a claiming transaction for a HTLC output on a remote commitment
300305
/// transaction, either offered or received.
301306
///
302-
/// HTLC transaction may claim multiples offered outputs at same time if we know preimage
303-
/// for each at detection. It may be called multtiples time for same output(s) if a fee-bump
304-
/// is needed with regards to an upcoming timelock expiration.
307+
/// Such a transaction may claim multiples offered outputs at same time if we know the preimage
308+
/// for each when we create it, but only the input at index `input` should be signed for here.
309+
/// It may be called multiple time for same output(s) if a fee-bump is needed with regards to
310+
/// an upcoming timelock expiration.
305311
///
306312
/// Witness_script is either a offered or received script as defined in BOLT3 for HTLC
307313
/// outputs.
308314
///
309-
/// Input index is a pointer towards outpoint spent, commited by sigs (BIP 143).
310-
///
311-
/// Amount is value of the output spent by this input, committed by sigs (BIP 143).
315+
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
312316
///
313317
/// Per_commitment_point is the dynamic point corresponding to the channel state
314-
/// detected onchain. It has been generated by remote party and is used to derive
315-
/// channel state keys, committed as part of witnessScript by sigs (BIP 143).
318+
/// detected onchain. It has been generated by our counterparty and is used to derive
319+
/// channel state keys, which are then included in the witness script and committed to in the
320+
/// BIP 143 signature.
316321
fn sign_remote_htlc_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
317322

318323
/// Create a signature for a (proposed) closing transaction.

lightning/src/ln/chan_utils.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ impl Readable for CounterpartyCommitmentSecrets {
171171
}
172172
}
173173

174-
/// Derives a per-commitment-transaction private key (eg an htlc key, payment key or delayed_payment
175-
/// key) from the base.
176-
/// private key for that type of key and the per_commitment_point (available in TxCreationKeys)
174+
/// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key)
175+
/// from the base secret and the per_commitment_point.
176+
///
177+
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
178+
/// generated (ie our own).
177179
pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
178180
let mut sha = Sha256::engine();
179181
sha.input(&per_commitment_point.serialize());
@@ -185,7 +187,13 @@ pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_co
185187
Ok(key)
186188
}
187189

188-
pub(crate) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
190+
/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
191+
/// from the base point and the per_commitment_key. This is the public equivalent of
192+
/// derive_private_key - using only public keys to derive a public key instead of private keys.
193+
///
194+
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
195+
/// generated (ie our own).
196+
pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
189197
let mut sha = Sha256::engine();
190198
sha.input(&per_commitment_point.serialize());
191199
sha.input(&base_point.serialize());
@@ -195,7 +203,8 @@ pub(crate) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
195203
base_point.combine(&hashkey)
196204
}
197205

198-
/// Derives a revocation key from its constituent parts.
206+
/// Derives a per-commitment-transaction revocation key from its constituent parts.
207+
///
199208
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
200209
/// generated (ie our own).
201210
pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
@@ -225,7 +234,13 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
225234
Ok(part_a)
226235
}
227236

228-
pub(crate) fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
237+
/// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
238+
/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
239+
/// public key instead of private keys.
240+
///
241+
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
242+
/// generated (ie our own).
243+
pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
229244
let rev_append_commit_hash_key = {
230245
let mut sha = Sha256::engine();
231246
sha.input(&revocation_base_point.serialize());
@@ -274,9 +289,9 @@ pub struct ChannelPublicKeys {
274289
/// on-chain channel lock-in 2-of-2 multisig output.
275290
pub funding_pubkey: PublicKey,
276291
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
277-
/// revocation keys. The per-commitment revocation private key is then revealed by the owner of
278-
/// a commitment transaction so that their counterparty can claim all available funds if they
279-
/// broadcast an old state.
292+
/// revocation keys. This is combined with the per-commitment-secret generated by the
293+
/// counterparty to create a secret which the counterparty can reveal to revoke previous
294+
/// states.
280295
pub revocation_basepoint: PublicKey,
281296
/// The public key which receives our immediately spendable primary channel balance in
282297
/// remote-broadcasted commitment transactions. This key is static across every commitment

0 commit comments

Comments
 (0)