Update docs on `HTLC` and `DelayedPayment` keys for clarity
[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 bitcoin::hashes::Hash;
14 use bitcoin::hashes::HashEngine;
15 use bitcoin::secp256k1::Scalar;
16 use bitcoin::secp256k1::SecretKey;
17 use bitcoin::secp256k1::Secp256k1;
18 use bitcoin::secp256k1;
19 use crate::ln::msgs::DecodeError;
20 use crate::util::ser::Readable;
21 use crate::io;
22 use crate::util::ser::Writer;
23 use crate::util::ser::Writeable;
24 use bitcoin::secp256k1::PublicKey;
25 use bitcoin::hashes::sha256::Hash as Sha256;
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) => {
35                 impl $BasepointT {
36                         /// Get inner Public Key
37                         pub fn to_public_key(&self) -> PublicKey {
38                                 self.0
39                         }
40                 }
41
42                 impl From<PublicKey> for $BasepointT {
43                         fn from(value: PublicKey) -> Self {
44                                 Self(value)
45                         }
46                 }
47
48         }
49 }
50 macro_rules! key_impl {
51         ($BasepointT:ty, $KeyName:expr) => {
52                 doc_comment! {
53                         concat!("Derive a public ", $KeyName, " using one node's `per_commitment_point` and its countersignatory's `basepoint`"),
54                         pub fn from_basepoint<T: secp256k1::Signing>(
55                                 secp_ctx: &Secp256k1<T>,
56                                 countersignatory_basepoint: &$BasepointT,
57                                 per_commitment_point: &PublicKey,
58                         ) -> Self {
59                                 Self(derive_public_key(secp_ctx, per_commitment_point, &countersignatory_basepoint.0))
60                         }
61                 }
62
63                 doc_comment! {
64                         concat!("Build a ", $KeyName, " directly from an already-derived private key"),
65                         pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
66                                 Self(PublicKey::from_secret_key(&secp_ctx, &sk))
67                         }
68                 }
69
70                 /// Get inner Public Key
71                 pub fn to_public_key(&self) -> PublicKey {
72                         self.0
73                 }
74         }
75 }
76 macro_rules! key_read_write {
77         ($SelfT:ty) => {
78                 impl Writeable for $SelfT {
79                         fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
80                                 self.0.serialize().write(w)
81                         }
82                 }
83
84                 impl Readable for $SelfT {
85                         fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
86                                 let key: PublicKey = Readable::read(r)?;
87                                 Ok(Self(key))
88                         }
89                 }
90         }
91 }
92
93
94
95 /// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
96 ///
97 /// The delayed payment key is used to pay the commitment state broadcaster their
98 /// non-HTLC-encumbered funds after a delay to give their counterparty a chance to punish if the
99 /// state broadcasted was previously revoked.
100 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
101 pub struct DelayedPaymentBasepoint(pub PublicKey);
102 basepoint_impl!(DelayedPaymentBasepoint);
103 key_read_write!(DelayedPaymentBasepoint);
104
105
106 /// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
107 ///
108 /// The delayed payment key is used to pay the commitment state broadcaster their
109 /// non-HTLC-encumbered funds after a delay. This delay gives their counterparty a chance to
110 /// punish and claim all the channel funds if the state broadcasted was previously revoked.
111 ///
112 /// [See the BOLT specs]
113 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
114 /// for more information on key derivation details.
115 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
116 pub struct DelayedPaymentKey(pub PublicKey);
117
118 impl DelayedPaymentKey {
119         key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
120 }
121 key_read_write!(DelayedPaymentKey);
122
123 /// Base key used in conjunction with a `per_commitment_point` to generate an [`HtlcKey`].
124 ///
125 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
126 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
127 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
128 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
129 pub struct HtlcBasepoint(pub PublicKey);
130 basepoint_impl!(HtlcBasepoint);
131 key_read_write!(HtlcBasepoint);
132
133 /// A derived key built from a [`HtlcBasepoint`] and `per_commitment_point`.
134 ///
135 /// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
136 /// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
137 /// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
138 ///
139 /// [See the BOLT specs]
140 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
141 /// for more information on key derivation details.
142 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
143 pub struct HtlcKey(pub PublicKey);
144
145 impl HtlcKey {
146         key_impl!(HtlcBasepoint, "htlcpubkey");
147 }
148 key_read_write!(HtlcKey);
149
150 /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
151 /// from the base point and the per_commitment_key. This is the public equivalent of
152 /// derive_private_key - using only public keys to derive a public key instead of private keys.
153 fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
154         let mut sha = Sha256::engine();
155         sha.input(&per_commitment_point.serialize());
156         sha.input(&base_point.serialize());
157         let res = Sha256::from_engine(sha).to_byte_array();
158
159         let hashkey = PublicKey::from_secret_key(&secp_ctx,
160                 &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
161         base_point.combine(&hashkey)
162                 .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.")
163 }
164
165 /// 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.
166 /// A watcher can be given a [RevocationBasepoint] to generate per commitment [RevocationKey] to create justice transactions.
167 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
168 pub struct RevocationBasepoint(pub PublicKey);
169 basepoint_impl!(RevocationBasepoint);
170 key_read_write!(RevocationBasepoint);
171
172
173 /// The revocation key is used to allow a channel party to revoke their state - giving their
174 /// counterparty the required material to claim all of their funds if they broadcast that state.
175 ///
176 /// Each commitment transaction has a revocation key based on the basepoint and
177 /// per_commitment_point which is used in both commitment and HTLC transactions.
178 ///
179 /// See [the BOLT spec for derivation details]
180 /// (https://github.com/lightning/bolts/blob/master/03-transactions.md#revocationpubkey-derivation)
181 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
182 pub struct RevocationKey(pub PublicKey);
183
184 impl RevocationKey {
185         /// Derives a per-commitment-transaction revocation public key from one party's per-commitment
186         /// point and the other party's [`RevocationBasepoint`]. This is the public equivalent of
187         /// [`chan_utils::derive_private_revocation_key`] - using only public keys to derive a public
188         /// key instead of private keys.
189         ///
190         /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
191         /// generated (ie our own).
192         ///
193         /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
194         pub fn from_basepoint<T: secp256k1::Verification>(
195                 secp_ctx: &Secp256k1<T>,
196                 countersignatory_basepoint: &RevocationBasepoint,
197                 per_commitment_point: &PublicKey,
198         ) -> Self {
199                 let rev_append_commit_hash_key = {
200                         let mut sha = Sha256::engine();
201                         sha.input(&countersignatory_basepoint.to_public_key().serialize());
202                         sha.input(&per_commitment_point.serialize());
203
204                         Sha256::from_engine(sha).to_byte_array()
205                 };
206                 let commit_append_rev_hash_key = {
207                         let mut sha = Sha256::engine();
208                         sha.input(&per_commitment_point.serialize());
209                         sha.input(&countersignatory_basepoint.to_public_key().serialize());
210
211                         Sha256::from_engine(sha).to_byte_array()
212                 };
213
214                 let countersignatory_contrib = countersignatory_basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
215                         .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
216                 let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
217                         .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
218                 let pk = countersignatory_contrib.combine(&broadcaster_contrib)
219                         .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
220                 Self(pk)
221         }
222
223         /// Get inner Public Key
224         pub fn to_public_key(&self) -> PublicKey {
225                 self.0
226         }
227 }
228 key_read_write!(RevocationKey);
229
230
231 #[cfg(test)]
232 mod test {
233         use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
234         use bitcoin::hashes::hex::FromHex;
235         use super::derive_public_key;
236
237         #[test]
238         fn test_key_derivation() {
239                 // Test vectors from BOLT 3 Appendix E:
240                 let secp_ctx = Secp256k1::new();
241
242                 let base_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
243                 let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
244
245                 let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
246                 assert_eq!(base_point.serialize()[..], <Vec<u8>>::from_hex("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]);
247
248                 let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
249                 assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
250
251                 assert_eq!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
252                         <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
253         }
254 }