1use std::str::FromStr;
24
25use bip39::Mnemonic;
26use bip85_extended;
27use bitcoin::bip32::{DerivationPath, Fingerprint, Xpriv, Xpub};
28use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
29use bitcoin::hex::{DisplayHex, FromHex};
30use bitcoin::key::rand::{rngs::OsRng, RngCore};
31use bitcoin::secp256k1::{Keypair, Secp256k1};
32use elements::secp256k1_zkp::{Keypair as ZKKeyPair, Secp256k1 as ZKSecp256k1};
33use lightning_invoice::Bolt11Invoice;
34use serde::{Deserialize, Serialize};
35
36use crate::error::Error;
37use crate::network::Network;
38
39const MNEMONIC_BIP85_INDEX: u32 = 26589;
40const SWAP_KEY_DERIVATION_PATH: &str = "m/44/0/0/0";
41
42#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
53pub struct SwapMasterKey {
54 pub mnemonic: Mnemonic,
56 pub xprv: Xpriv,
58 pub fingerprint: Fingerprint,
60 pub network: Network,
62}
63
64impl SwapMasterKey {
65 pub fn new(
79 wallet_mnemonic: &str,
80 wallet_passphrase: Option<&str>,
81 network: Network,
82 ) -> Result<SwapMasterKey, Error> {
83 let secp = Secp256k1::new();
84 let root = Self::derive_root_xpriv(wallet_mnemonic, wallet_passphrase, network)?;
85 let swap_mnemonic =
86 bip85_extended::mnemonic::to_mnemonic(&secp, &root, 12, MNEMONIC_BIP85_INDEX)?;
87 Self::from_mnemonic(&swap_mnemonic.to_string(), None, network)
88 }
89
90 pub fn from_mnemonic(
103 mnemonic: &str,
104 passphrase: Option<&str>,
105 network: Network,
106 ) -> Result<SwapMasterKey, Error> {
107 let secp = Secp256k1::new();
108 let root = Self::derive_root_xpriv(mnemonic, passphrase, network)?;
109 let fingerprint = root.fingerprint(&secp);
110
111 let master_path = DerivationPath::from_str(SWAP_KEY_DERIVATION_PATH)?;
112 let xprv = root.derive_priv(&secp, &master_path)?;
113
114 let mnemonic_struct = Mnemonic::from_str(mnemonic)?;
115
116 Ok(SwapMasterKey {
117 mnemonic: mnemonic_struct,
118 xprv,
119 fingerprint,
120 network,
121 })
122 }
123 pub fn derive_swapkey(&self, index: u64) -> Result<Keypair, Error> {
134 let secp = Secp256k1::new();
135 let child_path = DerivationPath::from_str(&format!("m/{index}"))?;
136 let child_xprv = self.xprv.derive_priv(&secp, &child_path)?;
137 let key_pair = Keypair::from_secret_key(&secp, &child_xprv.private_key);
138 Ok(key_pair)
139 }
140
141 pub fn derive_liquid_swapkey(&self, index: u64) -> Result<ZKKeyPair, Error> {
152 let keypair = self.derive_swapkey(index)?;
153 let secp = ZKSecp256k1::new();
154 let zk_keypair = ZKKeyPair::from_seckey_str(&secp, &keypair.display_secret().to_string())?;
155 Ok(zk_keypair)
156 }
157
158 pub fn get_master_xpub(&self) -> Xpub {
165 let secp = Secp256k1::new();
166 Xpub::from_priv(&secp, &self.xprv)
167 }
168
169 fn derive_root_xpriv(
170 mnemonic: &str,
171 passphrase: Option<&str>,
172 network: Network,
173 ) -> Result<Xpriv, Error> {
174 let mnemonic_struct = Mnemonic::from_str(mnemonic)?;
175 let seed = mnemonic_struct.to_seed(passphrase.unwrap_or(""));
176 let root = Xpriv::new_master(bitcoin::Network::from(network), &seed)?;
177 Ok(root)
178 }
179}
180
181pub(crate) fn rng_32b() -> [u8; 32] {
187 let mut bytes = [0u8; 32];
188 OsRng.fill_bytes(&mut bytes);
189 bytes
190}
191
192#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
194pub struct Preimage {
195 pub bytes: Option<[u8; 32]>,
196 pub sha256: sha256::Hash,
197 pub hash160: hash160::Hash,
198}
199
200impl FromStr for Preimage {
201 type Err = Error;
202
203 fn from_str(preimage: &str) -> Result<Self, Self::Err> {
205 Self::from_vec(Vec::from_hex(preimage)?)
206 }
207}
208
209impl Default for Preimage {
210 fn default() -> Self {
211 Preimage::random()
212 }
213}
214
215impl Preimage {
216 pub fn random() -> Preimage {
220 let preimage = rng_32b();
221 let sha256 = sha256::Hash::hash(&preimage);
222 let hash160 = hash160::Hash::hash(&preimage);
223
224 Preimage {
225 sha256,
226 hash160,
227 bytes: Some(preimage),
228 }
229 }
230
231 pub fn from_vec(preimage: Vec<u8>) -> Result<Preimage, Error> {
233 let preimage: [u8; 32] = preimage
235 .try_into()
236 .map_err(|_| Error::Protocol("Decoded Preimage input is not 32 bytes".to_string()))?;
237 let sha256 = sha256::Hash::hash(&preimage);
238 let hash160 = hash160::Hash::hash(&preimage);
239 Ok(Preimage {
240 sha256,
241 hash160,
242 bytes: Some(preimage),
243 })
244 }
245
246 pub fn from_sha256_str(preimage_sha256: &str) -> Result<Preimage, Error> {
249 Self::from_sha256_vec(Vec::from_hex(preimage_sha256)?)
250 }
251
252 pub fn from_sha256_vec(preimage_sha256: Vec<u8>) -> Result<Preimage, Error> {
255 let sha256 = sha256::Hash::from_slice(preimage_sha256.as_slice())?;
256 let hash160 = hash160::Hash::from_slice(
257 ripemd160::Hash::hash(sha256.as_byte_array()).as_byte_array(),
258 )?;
259 Ok(Preimage {
261 sha256,
262 hash160,
263 bytes: None,
264 })
265 }
266
267 pub fn from_invoice_str(invoice_str: &str) -> Result<Preimage, Error> {
270 let invoice = Bolt11Invoice::from_str(invoice_str)?;
271 Preimage::from_sha256_str(&invoice.payment_hash().to_string())
272 }
273
274 pub fn to_string(&self) -> Option<String> {
276 self.bytes.map(|res| res.to_lower_hex_string())
277 }
278
279 pub fn from_swap_key(keypair: &Keypair) -> Preimage {
283 let private_key_bytes = keypair.secret_key().secret_bytes();
284 let preimage = sha256::Hash::hash(&private_key_bytes);
285 let preimage_bytes: [u8; 32] = *preimage.as_byte_array();
286 let sha256 = sha256::Hash::hash(&preimage_bytes);
287 let hash160 = hash160::Hash::hash(&preimage_bytes);
288
289 Preimage {
290 bytes: Some(preimage_bytes),
291 sha256,
292 hash160,
293 }
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300 use elements::pset::serialize::Serialize;
301
302 #[macros::test_all]
303 fn test_derivation() {
304 let mnemonic: &str = "bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon";
305 let index = 0_u64; let swap_master_key =
307 SwapMasterKey::from_mnemonic(mnemonic, None, Network::Mainnet).unwrap();
308 let keypair = swap_master_key.derive_swapkey(index).unwrap();
309 let secp = ZKSecp256k1::new();
310 let zk_keypair =
311 ZKKeyPair::from_seckey_str(&secp, &keypair.display_secret().to_string()).unwrap();
312 assert_eq!(keypair.public_key(), zk_keypair.public_key());
313 }
314
315 #[macros::test_all]
316 fn test_preimage_from_str() {
317 let preimage = Preimage::random();
318 assert_eq!(
319 Preimage::from_str(&hex::encode(preimage.bytes.unwrap()).to_string()).unwrap(),
320 preimage
321 );
322 }
323
324 #[macros::test_all]
325 fn test_preimage_from_vec() {
326 let preimage = Preimage::random();
327 assert_eq!(
328 Preimage::from_vec(Vec::from(preimage.bytes.unwrap())).unwrap(),
329 preimage
330 );
331 }
332
333 #[macros::test_all]
334 fn test_preimage_from_vec_invalid_length() {
335 let mut bytes = [0u8; 33];
336 OsRng.fill_bytes(&mut bytes);
337 assert_eq!(
338 Preimage::from_vec(Vec::from(bytes))
339 .err()
340 .unwrap()
341 .message(),
342 "Decoded Preimage input is not 32 bytes".to_string()
343 );
344 }
345
346 #[macros::test_all]
347 fn test_preimage_from_sha256_str() {
348 let preimage = Preimage::random();
349 let compare = Preimage::from_sha256_str(preimage.sha256.to_string().as_str()).unwrap();
350
351 assert_eq!(compare.bytes, None);
352 assert_eq!(compare.sha256, preimage.sha256);
353 assert_eq!(compare.hash160, preimage.hash160);
354 }
355
356 #[macros::test_all]
357 fn test_preimage_from_sha256_vec() {
358 let preimage = Preimage::random();
359 let compare = Preimage::from_sha256_vec(preimage.sha256.serialize()).unwrap();
360
361 assert_eq!(compare.bytes, None);
362 assert_eq!(compare.sha256, preimage.sha256);
363 assert_eq!(compare.hash160, preimage.hash160);
364 }
365
366 #[macros::test_all]
367 fn test_swap_master_key() -> Result<(), Error> {
368 let wallet_mnemonic = "bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon bacon";
369 let wallet_passphrase = None;
370 let network = Network::Mainnet;
371
372 let swap_master_key = SwapMasterKey::new(wallet_mnemonic, wallet_passphrase, network)?;
373
374 assert_eq!(
375 swap_master_key.mnemonic.to_string(),
376 "velvet engage shaft effort clarify annual protect client only surround sock gain"
377 .to_string(),
378 "BIP85 extended method should produce the same mnemonic as raw derivation"
379 );
380
381 assert_eq!(
382 swap_master_key.xprv.to_string(),
383 "xprvA2Cw2wgWLdz9ppAYGVYpfVT6zjdVpQg9MPh9vuFQj3CMDguEv1reAdHiaSPyjqmk7sb7BA9X8T29snJGMtLBWKmATtdPaQijCbc5bbViDsH",
384 "xpriv should match expected value"
385 );
386
387 let master_xpub = swap_master_key.get_master_xpub();
388 assert_eq!(
389 master_xpub.to_string(),
390 "xpub6FCHSTDQB1YT3JF1NX5q2dPqYmTzDsPzicckjHf2HNjL6VEPTZAtiRcCRixiSpfKinRfWGFQ5b1yw74jzsBd1hkm25864ZpH8uND7rjKjiV",
391 "xpub should match expected value"
392 );
393
394 let swap_key_at_index_0 = swap_master_key.derive_swapkey(0)?;
395
396 let xprv_str = "xprvA44z2P7u7pXcG23soQ32XV9jUgbnQukETR1sNT2HKu681zaNU7iPEo3qQ6tMrAzNK8kQmFqEqFURCxXEZpEuVLK4KdXH8atNQpxrqYGjq17";
397 let swap_xprv = Xpriv::from_str(xprv_str)?;
398 let secp = Secp256k1::new();
399
400 let keypair_from_xprv = Keypair::from_secret_key(&secp, &swap_xprv.private_key);
401
402 assert_eq!(
403 swap_key_at_index_0.public_key(),
404 keypair_from_xprv.public_key(),
405 "Swap key at index 0 should match KeyPair derived from xprv"
406 );
407 assert_eq!(
408 swap_key_at_index_0.secret_key(),
409 keypair_from_xprv.secret_key(),
410 "Swap key secret at index 0 should match KeyPair secret derived from xprv"
411 );
412
413 let preimage = Preimage::from_swap_key(&swap_key_at_index_0);
414 assert_eq!(
415 preimage.bytes.unwrap().to_lower_hex_string(),
416 "f19d42c70bf00267b6c5dcfe6e1094386f8c72389f1ced91e0132d1502bbd244".to_string(),
417 );
418
419 Ok(())
420 }
421}