9e839b15e3c40636c72553b32c9eb52f35079f7b
[rust-lightning] / lightning / src / ln / channel_keys.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Keys used to generate commitment transactions.
11 //! See: <https://github.com/lightning/bolts/blob/master/03-transactions.md#keys>
12
13 use crate::io;
14 use crate::ln::msgs::DecodeError;
15 use crate::util::ser::Readable;
16 use crate::util::ser::Writeable;
17 use crate::util::ser::Writer;
18 use bitcoin::hashes::sha256::Hash as Sha256;
19 use bitcoin::hashes::Hash;
20 use bitcoin::hashes::HashEngine;
21 use bitcoin::secp256k1;
22 use bitcoin::secp256k1::PublicKey;
23 use bitcoin::secp256k1::Scalar;
24 use bitcoin::secp256k1::Secp256k1;
25 use bitcoin::secp256k1::SecretKey;
26
27 macro_rules! doc_comment {
28         ($x:expr, $($tt:tt)*) => {
29                 #[doc = $x]
30                 $($tt)*
31         };
32 }
33 macro_rules! basepoint_impl {
34         ($BasepointT:ty $(, $KeyName: expr)?) => {
35                 impl $BasepointT {
36                         /// Get inner Public Key
37                         pub fn to_public_key(&self) -> PublicKey {
38                                 self.0
39                         }
40
41                         $(doc_comment!(
42                                 concat!(
43                                 "Derives the \"tweak\" used in calculate [`", $KeyName, "::from_basepoint`].\n",
44                                 "\n",
45                                 "[`", $KeyName, "::from_basepoint`] calculates a private key as:\n",
46                                 "`privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`\n",
47                                 "\n",
48                                 "This calculates the hash part in the tweak derivation process, which is used to\n",
49                                 "ensure that each key is unique and cannot be guessed by an external party."
50                                 ),
51                                 pub fn derive_add_tweak(&self, per_commitment_point: &PublicKey) -> Sha256 {
52                                         let mut sha = Sha256::engine();
53                                         sha.input(&per_commitment_point.serialize());
54                                         sha.input(&self.to_public_key().serialize());
55                                         Sha256::from_engine(sha)
56                                 });
57                         )?
58                 }
59
60                 impl From<PublicKey> for $BasepointT {
61                         fn from(value: PublicKey) -> Self {
62                                 Self(value)
63                         }
64                 }
65         };
66 }
67 macro_rules! key_impl {
68         ($BasepointT:ty, $KeyName:expr) => {
69                 doc_comment! {
70                         concat!("Derive a public ", $KeyName, " using one node's `per_commitment_point` and its countersignatory's `basepoint`"),
71                         pub fn from_basepoint<T: secp256k1::Signing>(
72                                 secp_ctx: &Secp256k1<T>,
73                                 countersignatory_basepoint: &$BasepointT,
74                                 per_commitment_point: &PublicKey,
75                         ) -> Self {
76                                 Self(derive_public_key(secp_ctx, per_commitment_point, &countersignatory_basepoint.0))
77                         }
78                 }
79
80                 doc_comment! {
81                         concat!("Build a ", $KeyName, " directly from an already-derived private key"),
82                         pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
83                                 Self(PublicKey::from_secret_key(&secp_ctx, &sk))
84                         }
85                 }
86
87                 /// Get inner Public Key
88                 pub fn to_public_key(&self) -> PublicKey {
89                         self.0
90                 }
91         }
92 }
93 macro_rules! key_read_write {
94         ($SelfT:ty) => {
95                 impl Writeable for $SelfT {
96                         fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
97                                 self.0.serialize().write(w)
98                         }
99                 }
100
101                 impl Readable for $SelfT {
102                         fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
103                                 let key: PublicKey = Readable::read(r)?;
104                                 Ok(Self(key))
105                         }
106                 }
107         };
108 }
109
110 /// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
111 ///
112 /// The delayed payment key is used to pay the commitment state broadcaster their
113 /// non-HTLC-encumbered funds after a delay to give their counterparty a chance to punish if the
114 /// state broadcasted was previously revoked.
115 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
116 pub struct DelayedPaymentBasepoint(pub PublicKey);
117 basepoint_impl!(DelayedPaymentBasepoint, "DelayedPaymentKey");
118 key_read_write!(DelayedPaymentBasepoint);
119
120 /// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
121 ///
122 /// The delayed payment key is used to pay the commitment state broadcaster their
123 /// non-HTLC-encumbered funds after a delay. This delay gives their counterparty a chance to
124 /// punish and claim all the channel funds if the state broadcasted was previously revoked.
125 ///
126 /// [See the BOLT specs]
127 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
128 /// for more information on key derivation details.
129 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
130 pub struct DelayedPaymentKey(pub PublicKey);
131
132 impl DelayedPaymentKey {
133         key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
134 }
135 key_read_write!(DelayedPaymentKey);
136
137 /// Base key used in conjunction with a `per_commitment_point` to generate an [`HtlcKey`].
138 ///
139 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
140 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
141 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
142 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
143 pub struct HtlcBasepoint(pub PublicKey);
144 basepoint_impl!(HtlcBasepoint, "HtlcKey");
145 key_read_write!(HtlcBasepoint);
146
147 /// A derived key built from a [`HtlcBasepoint`] and `per_commitment_point`.
148 ///
149 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
150 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
151 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
152 ///
153 /// [See the BOLT specs]
154 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
155 /// for more information on key derivation details.
156 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
157 pub struct HtlcKey(pub PublicKey);
158
159 impl HtlcKey {
160         key_impl!(HtlcBasepoint, "htlcpubkey");
161 }
162 key_read_write!(HtlcKey);
163
164 /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
165 /// from the base point and the per_commitment_key. This is the public equivalent of
166 /// derive_private_key - using only public keys to derive a public key instead of private keys.
167 fn derive_public_key<T: secp256k1::Signing>(
168         secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey,
169 ) -> PublicKey {
170         let mut sha = Sha256::engine();
171         sha.input(&per_commitment_point.serialize());
172         sha.input(&base_point.serialize());
173         let res = Sha256::from_engine(sha);
174
175         add_public_key_tweak(secp_ctx, base_point, &res)
176 }
177
178 /// Adds a tweak to a public key to derive a new public key.
179 ///
180 /// May panic if `tweak` is not the output of a SHA-256 hash.
181 pub fn add_public_key_tweak<T: secp256k1::Signing>(
182         secp_ctx: &Secp256k1<T>, base_point: &PublicKey, tweak: &Sha256,
183 ) -> PublicKey {
184         let hashkey = PublicKey::from_secret_key(
185                 &secp_ctx,
186                 &SecretKey::from_slice(tweak.as_byte_array())
187                         .expect("Hashes should always be valid keys unless SHA-256 is broken"),
188         );
189         base_point.combine(&hashkey)
190                 .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak contains the hash of the key.")
191 }
192
193 /// Master key used in conjunction with per_commitment_point to generate [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
194 /// A watcher can be given a [RevocationBasepoint] to generate per commitment [RevocationKey] to create justice transactions.
195 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
196 pub struct RevocationBasepoint(pub PublicKey);
197 basepoint_impl!(RevocationBasepoint);
198 key_read_write!(RevocationBasepoint);
199
200 /// The revocation key is used to allow a channel party to revoke their state - giving their
201 /// counterparty the required material to claim all of their funds if they broadcast that state.
202 ///
203 /// Each commitment transaction has a revocation key based on the basepoint and
204 /// per_commitment_point which is used in both commitment and HTLC transactions.
205 ///
206 /// See [the BOLT spec for derivation details]
207 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#revocationpubkey-derivation)
208 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
209 pub struct RevocationKey(pub PublicKey);
210
211 impl RevocationKey {
212         /// Derives a per-commitment-transaction revocation public key from one party's per-commitment
213         /// point and the other party's [`RevocationBasepoint`]. This is the public equivalent of
214         /// [`chan_utils::derive_private_revocation_key`] - using only public keys to derive a public
215         /// key instead of private keys.
216         ///
217         /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
218         /// generated (ie our own).
219         ///
220         /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
221         pub fn from_basepoint<T: secp256k1::Verification>(
222                 secp_ctx: &Secp256k1<T>, countersignatory_basepoint: &RevocationBasepoint,
223                 per_commitment_point: &PublicKey,
224         ) -> Self {
225                 let rev_append_commit_hash_key = {
226                         let mut sha = Sha256::engine();
227                         sha.input(&countersignatory_basepoint.to_public_key().serialize());
228                         sha.input(&per_commitment_point.serialize());
229
230                         Sha256::from_engine(sha).to_byte_array()
231                 };
232                 let commit_append_rev_hash_key = {
233                         let mut sha = Sha256::engine();
234                         sha.input(&per_commitment_point.serialize());
235                         sha.input(&countersignatory_basepoint.to_public_key().serialize());
236
237                         Sha256::from_engine(sha).to_byte_array()
238                 };
239
240                 let countersignatory_contrib = countersignatory_basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
241                         .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
242                 let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
243                         .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
244                 let pk = countersignatory_contrib.combine(&broadcaster_contrib)
245                         .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
246                 Self(pk)
247         }
248
249         /// Get inner Public Key
250         pub fn to_public_key(&self) -> PublicKey {
251                 self.0
252         }
253 }
254 key_read_write!(RevocationKey);
255
256 #[cfg(test)]
257 mod test {
258         use super::derive_public_key;
259         use bitcoin::hashes::hex::FromHex;
260         use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
261
262         #[test]
263         fn test_key_derivation() {
264                 // Test vectors from BOLT 3 Appendix E:
265                 let secp_ctx = Secp256k1::new();
266
267                 let base_secret = SecretKey::from_slice(
268                         &<Vec<u8>>::from_hex(
269                                 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
270                         )
271                         .unwrap()[..],
272                 )
273                 .unwrap();
274                 let per_commitment_secret = SecretKey::from_slice(
275                         &<Vec<u8>>::from_hex(
276                                 "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
277                         )
278                         .unwrap()[..],
279                 )
280                 .unwrap();
281
282                 let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
283                 assert_eq!(
284                         base_point.serialize()[..],
285                         <Vec<u8>>::from_hex(
286                                 "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
287                         )
288                         .unwrap()[..]
289                 );
290
291                 let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
292                 assert_eq!(
293                         per_commitment_point.serialize()[..],
294                         <Vec<u8>>::from_hex(
295                                 "025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486"
296                         )
297                         .unwrap()[..]
298                 );
299
300                 assert_eq!(
301                         derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
302                         <Vec<u8>>::from_hex(
303                                 "0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5"
304                         )
305                         .unwrap()[..]
306                 );
307         }
308 }