1use crate::io;
14use crate::ln::msgs::DecodeError;
15use crate::util::ser::Readable;
16use crate::util::ser::Writeable;
17use crate::util::ser::Writer;
18use bitcoin::hashes::sha256::Hash as Sha256;
19use bitcoin::hashes::Hash;
20use bitcoin::hashes::HashEngine;
21use bitcoin::secp256k1;
22use bitcoin::secp256k1::PublicKey;
23use bitcoin::secp256k1::Scalar;
24use bitcoin::secp256k1::Secp256k1;
25use bitcoin::secp256k1::SecretKey;
26
27macro_rules! doc_comment {
28 ($x:expr, $($tt:tt)*) => {
29 #[doc = $x]
30 $($tt)*
31 };
32}
33macro_rules! basepoint_impl {
34 ($BasepointT:ty $(, $KeyName: expr)?) => {
35 impl $BasepointT {
36 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}
67macro_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 pub fn to_public_key(&self) -> PublicKey {
89 self.0
90 }
91 }
92}
93macro_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#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
116pub struct DelayedPaymentBasepoint(pub PublicKey);
117basepoint_impl!(DelayedPaymentBasepoint, "DelayedPaymentKey");
118key_read_write!(DelayedPaymentBasepoint);
119
120#[derive(PartialEq, Eq, Clone, Copy, Debug)]
130pub struct DelayedPaymentKey(pub PublicKey);
131
132impl DelayedPaymentKey {
133 key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
134}
135key_read_write!(DelayedPaymentKey);
136
137#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
143pub struct HtlcBasepoint(pub PublicKey);
144basepoint_impl!(HtlcBasepoint, "HtlcKey");
145key_read_write!(HtlcBasepoint);
146
147#[derive(PartialEq, Eq, Clone, Copy, Debug)]
157pub struct HtlcKey(pub PublicKey);
158
159impl HtlcKey {
160 key_impl!(HtlcBasepoint, "htlcpubkey");
161}
162key_read_write!(HtlcKey);
163
164fn 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
178pub 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#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
196pub struct RevocationBasepoint(pub PublicKey);
197basepoint_impl!(RevocationBasepoint);
198key_read_write!(RevocationBasepoint);
199
200#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
209pub struct RevocationKey(pub PublicKey);
210
211impl RevocationKey {
212 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 pub fn to_public_key(&self) -> PublicKey {
251 self.0
252 }
253}
254key_read_write!(RevocationKey);
255
256#[cfg(test)]
257mod test {
258 use super::derive_public_key;
259 use bitcoin::hex::FromHex;
260 use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
261
262 #[test]
263 fn test_key_derivation() {
264 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}