Implement struct wrappers for channel key types to avoid confusion.
[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!("Generate ", $KeyName, " using per_commitment_point"),
54             pub fn from_basepoint<T: secp256k1::Signing>(
55                 secp_ctx: &Secp256k1<T>,
56                 basepoint: &$BasepointT,
57                 per_commitment_point: &PublicKey,
58             ) -> Self {
59                 Self(derive_public_key(secp_ctx, per_commitment_point, &basepoint.0))
60             }
61         }
62         
63         doc_comment! {
64             concat!("Generate ", $KeyName, " from privkey"),
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 /// Master key used in conjunction with per_commitment_point to generate [`local_delayedpubkey`](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
96 /// A watcher can be given a [DelayedPaymentBasepoint] to generate per commitment [DelayedPaymentKey] to create justice transactions.
97 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
98 pub struct DelayedPaymentBasepoint(pub PublicKey);
99 basepoint_impl!(DelayedPaymentBasepoint);
100 key_read_write!(DelayedPaymentBasepoint);
101
102 /// [delayedpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
103 /// To allow a counterparty to contest a channel state published by a node, Lightning protocol sets delays for some of the outputs, before can be spend.
104 /// For example a commitment transaction has to_local output encumbered by a delay, negotiated at the channel establishment flow.
105 /// To spend from such output a node has to generate a script using, among others, a local delayed payment key.
106 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
107 pub struct DelayedPaymentKey(pub PublicKey);
108
109 impl DelayedPaymentKey {
110     key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
111 }
112 key_read_write!(DelayedPaymentKey);
113
114 /// Master key used in conjunction with per_commitment_point to generate a [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
115 /// Also used to generate a commitment number in a commitment transaction or as a Payment Key for a remote node (not us) in an anchor output if `option_static_remotekey` is enabled.
116 /// Shared by both nodes in a channel establishment message flow.
117 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
118 pub struct PaymentBasepoint(pub PublicKey);
119 basepoint_impl!(PaymentBasepoint);
120 key_read_write!(PaymentBasepoint);
121
122
123 /// [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a payment basepoint,
124 /// that enables a secure hash-lock for off-chain payments without risk of funds getting stuck or stolen. A payment key is normally shared with a counterparty so that it can generate 
125 /// a commitment transaction's to_remote ouput, which our node can claim in case the counterparty force closes the channel.
126 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
127 pub struct PaymentKey(pub PublicKey);
128
129 impl PaymentKey {
130     key_impl!(PaymentBasepoint, "localpubkey");
131 }
132 key_read_write!(PaymentKey);
133
134 /// 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.
135 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
136 pub struct HtlcBasepoint(pub PublicKey);
137 basepoint_impl!(HtlcBasepoint);
138 key_read_write!(HtlcBasepoint);
139
140
141 /// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of an htlc basepoint,
142 /// that enables secure routing of payments in onion scheme without a risk of them getting stuck or diverted. It is used to claim the funds in successful or timed out htlc outputs.
143 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
144 pub struct HtlcKey(pub PublicKey);
145
146 impl HtlcKey {
147     key_impl!(HtlcBasepoint, "htlcpubkey");
148 }
149 key_read_write!(HtlcKey);
150
151 /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
152 /// from the base point and the per_commitment_key. This is the public equivalent of
153 /// derive_private_key - using only public keys to derive a public key instead of private keys.
154 fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> PublicKey {
155         let mut sha = Sha256::engine();
156         sha.input(&per_commitment_point.serialize());
157         sha.input(&base_point.serialize());
158         let res = Sha256::from_engine(sha).to_byte_array();
159     
160
161         let hashkey = PublicKey::from_secret_key(&secp_ctx,
162                 &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
163         base_point.combine(&hashkey)
164                 .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.")
165 }
166
167 /// 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.
168 /// A watcher can be given a [RevocationBasepoint] to generate per commitment [RevocationKey] to create justice transactions.
169 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
170 pub struct RevocationBasepoint(pub PublicKey);
171 basepoint_impl!(RevocationBasepoint);
172 key_read_write!(RevocationBasepoint);
173
174
175 /// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a revocation basepoint,
176 /// that enables a node to create a justice transaction punishing a counterparty for an attempt to steal funds. Used to in generation of commitment and htlc outputs.
177 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
178 pub struct RevocationKey(pub PublicKey);
179
180 impl RevocationKey {
181     /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
182     /// the public equivalend of derive_private_revocation_key - using only public keys to derive a
183     /// public key instead of private keys.
184     ///
185     /// Only the cheating participant owns a valid witness to propagate a revoked
186     /// commitment transaction, thus per_commitment_point always come from cheater
187     /// and revocation_base_point always come from punisher, which is the broadcaster
188     /// of the transaction spending with this key knowledge.
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     pub fn from_basepoint<T: secp256k1::Verification>(
193         secp_ctx: &Secp256k1<T>,
194         basepoint: &RevocationBasepoint,
195         per_commitment_point: &PublicKey,
196     ) -> Self {
197         let rev_append_commit_hash_key = {
198             let mut sha = Sha256::engine();
199             sha.input(&basepoint.to_public_key().serialize());
200             sha.input(&per_commitment_point.serialize());
201     
202             Sha256::from_engine(sha).to_byte_array()
203         };
204         let commit_append_rev_hash_key = {
205             let mut sha = Sha256::engine();
206             sha.input(&per_commitment_point.serialize());
207             sha.input(&basepoint.to_public_key().serialize());
208     
209             Sha256::from_engine(sha).to_byte_array()
210         };
211     
212         let countersignatory_contrib = basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
213             .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
214         let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
215             .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
216         let pk = countersignatory_contrib.combine(&broadcaster_contrib)
217             .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
218         Self(pk)
219     }
220
221     /// Get inner Public Key
222     pub fn to_public_key(&self) -> PublicKey {
223         self.0
224     }
225 }
226 key_read_write!(RevocationKey);
227
228
229
230 #[cfg(test)]
231 mod test {
232     use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
233     use bitcoin::hashes::hex::FromHex;
234     use super::derive_public_key;
235
236     #[test]
237         fn test_key_derivation() {
238                 // Test vectors from BOLT 3 Appendix E:
239                 let secp_ctx = Secp256k1::new();
240
241                 let base_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
242                 let per_commitment_secret = SecretKey::from_slice(&<Vec<u8>>::from_hex("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
243
244                 let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret);
245                 assert_eq!(base_point.serialize()[..], <Vec<u8>>::from_hex("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]);
246
247                 let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
248                 assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
249
250                 assert_eq!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
251                                 <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
252         }
253 }