btc.rs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. use async_std::sync::Arc;
  2. use serde_json::json;
  3. use std::convert::From;
  4. use std::str::FromStr;
  5. use std::time::Duration;
  6. use async_trait::async_trait;
  7. use bitcoin::blockdata::{
  8. script::{Builder, Script},
  9. transaction::{OutPoint, SigHashType, Transaction, TxIn, TxOut},
  10. };
  11. use bitcoin::hash_types::PubkeyHash as BtcPubKeyHash;
  12. use bitcoin::network::constants::Network;
  13. use bitcoin::util::psbt::serialize::Serialize;
  14. use bitcoin::util::address::Address;
  15. use bitcoin::util::ecdsa::{PrivateKey as BtcPrivKey, PublicKey as BtcPubKey};
  16. use electrum_client::{Client as ElectrumClient, ElectrumApi, GetBalanceRes};
  17. use futures::{SinkExt, StreamExt};
  18. use log::*;
  19. use secp256k1::{
  20. constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE},
  21. key::{PublicKey, SecretKey},
  22. {rand::rngs::OsRng, Secp256k1},
  23. {All, Message as BtcMessage /*Secp256k1,*/},
  24. };
  25. use tungstenite::Message;
  26. use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
  27. use crate::rpc::{jsonrpc, websockets::WsStream};
  28. use crate::serial::{deserialize, serialize, Decodable, Encodable};
  29. use crate::util::{generate_id, NetworkName};
  30. use crate::{Error, Result};
  31. // Swap out these types for any future non bitcoin-rs types
  32. pub type PubAddress = Address;
  33. pub type PubKey = BtcPubKey;
  34. pub type PrivKey = BtcPrivKey;
  35. const KEYPAIR_LENGTH: usize = SECRET_KEY_SIZE + PUBLIC_KEY_SIZE;
  36. #[derive(Clone)]
  37. pub struct Keypair {
  38. secret: SecretKey,
  39. public: PublicKey,
  40. context: Secp256k1<All>,
  41. }
  42. impl Keypair {
  43. pub fn new() -> Self {
  44. let secp = Secp256k1::new();
  45. let mut rng = OsRng::new().expect("OsRng");
  46. let (secret, public) = secp.generate_keypair(&mut rng);
  47. Self {
  48. secret,
  49. public,
  50. context: secp,
  51. }
  52. }
  53. pub fn to_bytes(&self) -> [u8; KEYPAIR_LENGTH] {
  54. let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH];
  55. bytes[..SECRET_KEY_SIZE].copy_from_slice(self.secret.as_ref());
  56. bytes[SECRET_KEY_SIZE..].copy_from_slice(&self.public.serialize());
  57. bytes
  58. }
  59. pub fn from_bytes(bytes: &[u8]) -> Result<Keypair> {
  60. if bytes.len() != KEYPAIR_LENGTH {
  61. return Err(Error::BtcFailed("Not right size".to_string()));
  62. }
  63. let secp = Secp256k1::new();
  64. //TODO: Map to errors properly, use context for public gen
  65. let secret = SecretKey::from_slice(&bytes[..SECRET_KEY_SIZE]).unwrap();
  66. let public = PublicKey::from_slice(&bytes[SECRET_KEY_SIZE..]).unwrap();
  67. Ok(Keypair {
  68. secret,
  69. public,
  70. context: secp,
  71. })
  72. }
  73. fn secret(&self) -> SecretKey {
  74. self.secret
  75. }
  76. pub fn pubkey(&self) -> PublicKey {
  77. self.public
  78. }
  79. pub fn as_tuple(&self) -> (SecretKey, PublicKey) {
  80. (self.secret, self.public)
  81. }
  82. }
  83. impl Default for Keypair {
  84. fn default() -> Self {
  85. Self::new()
  86. }
  87. }
  88. #[derive(Clone)]
  89. pub struct BtcKeys {
  90. keypair: Arc<Keypair>,
  91. btc_privkey: BtcPrivKey,
  92. pub btc_pubkey: BtcPubKey,
  93. pub address: Address,
  94. pub script_pubkey: Script,
  95. pub network: Network,
  96. }
  97. impl BtcKeys {
  98. pub fn new(keypair: &Keypair, network: Network) -> Self {
  99. let (secret_key, _public_key) = keypair.as_tuple();
  100. let btc_privkey = BtcPrivKey::new(secret_key, network);
  101. let btc_pubkey = btc_privkey.public_key(&keypair.context);
  102. let address = BtcKeys::derive_btc_address(btc_pubkey, network);
  103. let script_pubkey = address.script_pubkey();
  104. Self {
  105. keypair: Arc::new(keypair.clone()),
  106. btc_privkey,
  107. btc_pubkey,
  108. address,
  109. script_pubkey,
  110. network,
  111. }
  112. }
  113. pub fn priv_from_secret(keypair: &Keypair, network: Network) -> BtcPrivKey {
  114. BtcPrivKey::new(keypair.secret(), network)
  115. }
  116. pub fn btcpub_from_keypair(keypair: &Keypair) -> BtcPubKey {
  117. BtcPubKey::new(keypair.public)
  118. }
  119. pub fn btc_privkey(&self) -> &BtcPrivKey {
  120. &self.btc_privkey
  121. }
  122. pub fn btc_pubkey(&self) -> &BtcPubKey {
  123. &self.btc_pubkey
  124. }
  125. pub fn btc_pubkey_hash(&self) -> BtcPubKeyHash {
  126. self.btc_pubkey.pubkey_hash()
  127. }
  128. pub fn derive_btc_script_pubkey(pubkey: PublicKey, network: Network) -> Script {
  129. let btc_pubkey = BtcPubKey::new(pubkey);
  130. let address = Address::p2pkh(&btc_pubkey, network);
  131. address.script_pubkey()
  132. }
  133. pub fn derive_btc_pubkey(pubkey: PublicKey) -> BtcPubKey {
  134. BtcPubKey::new(pubkey)
  135. }
  136. pub fn derive_btc_address(btc_pubkey: BtcPubKey, network: Network) -> Address {
  137. Address::p2pkh(&btc_pubkey, network)
  138. }
  139. pub fn derive_script(btc_pubkey_hash: BtcPubKeyHash) -> Script {
  140. Script::new_p2pkh(&btc_pubkey_hash)
  141. }
  142. }
  143. pub struct BtcClient {
  144. main_account: BtcKeys,
  145. notify_channel: (
  146. async_channel::Sender<TokenNotification>,
  147. async_channel::Receiver<TokenNotification>,
  148. ),
  149. client: Arc<ElectrumClient>,
  150. network: Network,
  151. }
  152. impl BtcClient {
  153. pub async fn new(main_keypair: Vec<u8>, network: &str) -> Result<Arc<Self>> {
  154. let main_keypair: Keypair = deserialize(&main_keypair)?;
  155. let notify_channel = async_channel::unbounded();
  156. let (network, url) = match network {
  157. "mainnet" => (Network::Bitcoin, "ssl://electrum.blockstream.info:50002"),
  158. "testnet" => (Network::Testnet, "ssl://electrum.blockstream.info:60002"),
  159. _ => return Err(Error::NotSupportedNetwork),
  160. };
  161. let main_account = BtcKeys::new(&main_keypair, network);
  162. let electrum_client = ElectrumClient::new(&url)
  163. .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
  164. Ok(Arc::new(Self {
  165. main_account,
  166. notify_channel,
  167. client: Arc::new(electrum_client),
  168. network,
  169. }))
  170. }
  171. async fn handle_subscribe_request(
  172. self: Arc<Self>,
  173. btc_keys: BtcKeys,
  174. drk_pub_key: jubjub::SubgroupPoint,
  175. ) -> BtcResult<()> {
  176. debug!(
  177. target: "BTC BRIDGE",
  178. "Handle subscribe request"
  179. );
  180. let client = &self.client;
  181. let keys_clone = btc_keys.clone();
  182. // p2pkh script
  183. let script = keys_clone.script_pubkey;
  184. //Fetch any current balance
  185. let prev_balance = client.script_get_balance(&script)?;
  186. let cur_balance: GetBalanceRes;
  187. let status = client.script_subscribe(&script)?;
  188. loop {
  189. let current_status = client.script_pop(&script)?;
  190. if current_status == status {
  191. async_std::task::sleep(Duration::from_secs(5)).await;
  192. debug!(
  193. target: "BTC CLIENT",
  194. "ScriptPubKey status has not changed, amtucfd: {}, amtcfd: {}",
  195. client.script_get_balance(&script)?.unconfirmed,
  196. client.script_get_balance(&script)?.confirmed
  197. );
  198. continue;
  199. }
  200. match current_status {
  201. Some(_) => {
  202. // Script has a notification update
  203. debug!(target: "BTC CLIENT", "ScripPubKey notify update");
  204. break;
  205. }
  206. None => {
  207. return Err(BtcFailed::ElectrumError(
  208. "ScriptPubKey was not found".to_string(),
  209. ));
  210. }
  211. };
  212. } // Endloop
  213. cur_balance = client.script_get_balance(&script)?;
  214. let send_notification = self.notify_channel.0.clone();
  215. if cur_balance.unconfirmed < prev_balance.unconfirmed {
  216. return Err(BtcFailed::Notification(
  217. "New balance is less than previous balance".into(),
  218. ));
  219. }
  220. //TODO: Wait until they're confirmed balances above
  221. let amnt = cur_balance.unconfirmed - prev_balance.unconfirmed;
  222. let ui_amnt = amnt;
  223. send_notification
  224. .send(TokenNotification {
  225. network: NetworkName::Bitcoin,
  226. // is btc an acceptable token name?
  227. token_id: generate_id("btc", &NetworkName::Bitcoin)?,
  228. drk_pub_key,
  229. received_balance: amnt as u64,
  230. decimals: 8,
  231. })
  232. .await
  233. .map_err(Error::from)?;
  234. debug!(target: "BTC BRIDGE", "Received {} btc", ui_amnt);
  235. let _ = self.send_btc_to_main_wallet(amnt as u64, btc_keys)?;
  236. Ok(())
  237. }
  238. async fn unsubscribe(
  239. self: Arc<Self>,
  240. write: &mut futures::stream::SplitSink<WsStream, tungstenite::Message>,
  241. pubkey: &PublicKey,
  242. sub_id: &i64,
  243. ) -> Result<()> {
  244. {
  245. let client = &self.client;
  246. let script_pubkey = BtcKeys::derive_btc_script_pubkey(*pubkey, self.network);
  247. let _ = client.script_unsubscribe(&script_pubkey).unwrap();
  248. }
  249. let unsubscription = jsonrpc::request(json!("accountUnsubscribe"), json!([sub_id]));
  250. write
  251. .send(Message::text(serde_json::to_string(&unsubscription)?))
  252. .await?;
  253. Ok(())
  254. }
  255. fn send_btc_to_main_wallet(self: Arc<Self>, amount: u64, btc_keys: BtcKeys) -> BtcResult<()> {
  256. debug!(target: "BTC BRIDGE", "Sending {} BTC to main wallet", amount);
  257. let client = &self.client;
  258. let keys_clone = btc_keys.clone();
  259. let script = keys_clone.script_pubkey;
  260. let utxo = client.script_list_unspent(&script)?;
  261. let mut inputs = Vec::new();
  262. let mut amounts: u64 = 0;
  263. for tx in utxo {
  264. let tx_in = TxIn {
  265. previous_output: OutPoint {
  266. txid: tx.tx_hash,
  267. vout: tx.tx_pos as u32,
  268. },
  269. sequence: 0xffffffff,
  270. witness: Vec::new(),
  271. script_sig: Script::new(),
  272. };
  273. inputs.push(tx_in);
  274. amounts += tx.value;
  275. }
  276. let main_script_pubkey = self.main_account.script_pubkey.clone();
  277. //Estimate fee for getting in 2 blocks ahead
  278. let estimated_fee = client.estimate_fee(2)?;
  279. //TODO: Better handling of fees, don't cast to u64
  280. let value = amounts - estimated_fee as u64;
  281. let transaction = Transaction {
  282. input: inputs,
  283. output: vec![TxOut {
  284. script_pubkey: main_script_pubkey,
  285. value: value,
  286. }],
  287. lock_time: 0,
  288. version: 2,
  289. };
  290. let signed_tx = sign_transaction(
  291. transaction,
  292. script,
  293. btc_keys.keypair.secret,
  294. btc_keys.btc_pubkey,
  295. &btc_keys.keypair.context,
  296. );
  297. let serialized_tx = serialize(&signed_tx);
  298. debug!(target: "BTC BRIDGE", "Signed tx: {:?}",
  299. signed_tx);
  300. //TODO: Replace unwrap with error matching
  301. let _txid = client.transaction_broadcast_raw(&serialized_tx).unwrap();
  302. debug!(target: "BTC BRIDGE", "Sent {} BTC to main wallet", amount);
  303. Ok(())
  304. }
  305. }
  306. #[async_trait]
  307. impl NetworkClient for BtcClient {
  308. async fn subscribe(
  309. self: Arc<Self>,
  310. drk_pub_key: jubjub::SubgroupPoint,
  311. _mint: Option<String>,
  312. ) -> Result<TokenSubscribtion> {
  313. // Generate bitcoin keys
  314. let keypair = Keypair::new();
  315. let btc_keys = BtcKeys::new(&keypair, self.network);
  316. let secret_key = serialize(&keypair);
  317. let public_key = btc_keys.address.to_string();
  318. // start scheduler for checking balance
  319. debug!(target: "BRIDGE BITCOIN", "Subscribing for deposit");
  320. smol::spawn(async move {
  321. let result = self.handle_subscribe_request(btc_keys, drk_pub_key).await;
  322. if let Err(e) = result {
  323. error!(target: "BTC BRIDGE SUBSCRIPTION","{}", e.to_string());
  324. }
  325. })
  326. .detach();
  327. Ok(TokenSubscribtion {
  328. secret_key,
  329. public_key,
  330. })
  331. }
  332. async fn subscribe_with_keypair(
  333. self: Arc<Self>,
  334. private_key: Vec<u8>,
  335. _public_key: Vec<u8>,
  336. drk_pub_key: jubjub::SubgroupPoint,
  337. _mint: Option<String>,
  338. ) -> Result<String> {
  339. let keypair: Keypair = deserialize(&private_key)?;
  340. let btc_keys = BtcKeys::new(&keypair, self.network);
  341. let public_key = keypair.pubkey().to_string();
  342. smol::spawn(async move {
  343. let result = self.handle_subscribe_request(btc_keys, drk_pub_key).await;
  344. if let Err(e) = result {
  345. error!(target: "BTC BRIDGE SUBSCRIPTION","{}", e.to_string());
  346. }
  347. })
  348. .detach();
  349. Ok(public_key)
  350. }
  351. async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>> {
  352. Ok(self.notify_channel.1.clone())
  353. }
  354. async fn send(self: Arc<Self>, address: Vec<u8>, _mint: Option<String>, amount: u64) -> Result<()> {
  355. // address is not a btc address, so derive the btc address
  356. let client = &self.client;
  357. let public_key = deserialize(&address)?;
  358. let script_pubkey = BtcKeys::derive_btc_script_pubkey(public_key, self.network);
  359. let main_script_pubkey = &self.main_account.script_pubkey;
  360. //TODO: Map to errors properly
  361. let main_utxo = client.script_list_unspent(&main_script_pubkey).unwrap();
  362. let transaction = Transaction {
  363. input: vec![TxIn {
  364. previous_output: OutPoint {
  365. txid: main_utxo[0].tx_hash,
  366. vout: main_utxo[0].tx_pos as u32,
  367. },
  368. sequence: 0xffffffff,
  369. witness: Vec::new(),
  370. script_sig: Script::new(),
  371. }],
  372. output: vec![TxOut {
  373. script_pubkey: script_pubkey.clone(),
  374. value: amount,
  375. }],
  376. lock_time: 0,
  377. version: 2,
  378. };
  379. let signed_tx = sign_transaction(
  380. transaction,
  381. script_pubkey,
  382. self.main_account.keypair.secret,
  383. self.main_account.btc_pubkey,
  384. &self.main_account.keypair.context,
  385. );
  386. let serialized_tx = serialize(&signed_tx);
  387. //TODO: Replace unwrap with error matchin
  388. let txid = client.transaction_broadcast_raw(&serialized_tx).unwrap();
  389. debug!(target: "BTC BRIDGE", "Sent {} BTC to main wallet: {}", amount, txid);
  390. Ok(())
  391. }
  392. }
  393. pub fn sign_transaction(
  394. tx: Transaction,
  395. script_pubkey: Script,
  396. priv_key: SecretKey,
  397. pub_key: BtcPubKey,
  398. curve: &Secp256k1<All>,
  399. ) -> Transaction {
  400. let mut signed_inputs: Vec<TxIn> = Vec::new();
  401. for (i, unsigned_input) in tx.input.iter().enumerate() {
  402. let sighash = tx.signature_hash(i, &script_pubkey, SigHashType::All as u32);
  403. //TODO: replace unwrap
  404. let msg = BtcMessage::from_slice(&sighash.as_ref()).unwrap();
  405. let signature = curve.sign(&msg, &priv_key);
  406. let byte_signature = &signature.serialize_der();
  407. let mut with_hashtype = byte_signature.to_vec();
  408. with_hashtype.push(SigHashType::All as u8);
  409. let redeem_script = Builder::new()
  410. .push_slice(with_hashtype.as_slice())
  411. .push_key(&pub_key)
  412. .into_script();
  413. signed_inputs.push(TxIn {
  414. previous_output: unsigned_input.previous_output,
  415. script_sig: redeem_script,
  416. sequence: unsigned_input.sequence,
  417. witness: unsigned_input.witness.clone(),
  418. });
  419. }
  420. Transaction {
  421. version: tx.version,
  422. lock_time: tx.lock_time,
  423. input: signed_inputs,
  424. output: tx.output,
  425. }
  426. }
  427. impl Encodable for bitcoin::Transaction {
  428. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  429. let tx = self.serialize();
  430. let len = tx.encode(s)?;
  431. Ok(len)
  432. }
  433. }
  434. impl Encodable for bitcoin::Address {
  435. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  436. let addr = self.to_string();
  437. let len = addr.encode(s)?;
  438. Ok(len)
  439. }
  440. }
  441. impl Decodable for bitcoin::Address {
  442. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  443. let addr: String = Decodable::decode(&mut d)?;
  444. let addr = bitcoin::Address::from_str(&addr)
  445. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  446. Ok(addr)
  447. }
  448. }
  449. impl Encodable for bitcoin::PublicKey {
  450. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  451. let key = self.to_bytes();
  452. let len = key.encode(s)?;
  453. Ok(len)
  454. }
  455. }
  456. impl Decodable for bitcoin::PublicKey {
  457. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  458. let key: Vec<u8> = Decodable::decode(&mut d)?;
  459. let key = bitcoin::PublicKey::from_slice(&key)
  460. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  461. Ok(key)
  462. }
  463. }
  464. impl Encodable for bitcoin::PrivateKey {
  465. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  466. let key: String = self.to_string();
  467. let len = key.encode(s)?;
  468. Ok(len)
  469. }
  470. }
  471. impl Decodable for bitcoin::PrivateKey {
  472. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  473. let key: String = Decodable::decode(&mut d)?;
  474. let key = bitcoin::PrivateKey::from_str(&key)
  475. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  476. Ok(key)
  477. }
  478. }
  479. impl Encodable for secp256k1::key::PublicKey {
  480. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  481. let key: Vec<u8> = self.serialize().to_vec();
  482. let len = key.encode(s)?;
  483. Ok(len)
  484. }
  485. }
  486. impl Decodable for secp256k1::key::PublicKey {
  487. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  488. let key: Vec<u8> = Decodable::decode(&mut d)?;
  489. let key = secp256k1::key::PublicKey::from_slice(&key)
  490. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  491. Ok(key)
  492. }
  493. }
  494. // TODO: add secret + public keys together for Encodable
  495. impl Encodable for Keypair {
  496. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  497. let key: Vec<u8> = self.to_bytes().to_vec();
  498. let len = key.encode(s)?;
  499. Ok(len)
  500. }
  501. }
  502. impl Decodable for Keypair {
  503. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  504. let key: Vec<u8> = Decodable::decode(&mut d)?;
  505. let key = Keypair::from_bytes(key.as_slice()).map_err(|_| {
  506. crate::Error::from(BtcFailed::DecodeAndEncodeError(
  507. "load keypair from slice".into(),
  508. ))
  509. })?;
  510. Ok(key)
  511. }
  512. }
  513. #[derive(Debug)]
  514. pub enum BtcFailed {
  515. NotEnoughValue(u64),
  516. BadBtcAddress(String),
  517. ElectrumError(String),
  518. BtcError(String),
  519. DecodeAndEncodeError(String),
  520. KeypairError(String),
  521. Notification(String),
  522. }
  523. impl std::error::Error for BtcFailed {}
  524. impl std::fmt::Display for BtcFailed {
  525. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  526. match self {
  527. BtcFailed::NotEnoughValue(i) => {
  528. write!(f, "There is no enough value {}", i)
  529. }
  530. BtcFailed::BadBtcAddress(ref err) => {
  531. write!(f, "Unable to create Electrum Client: {}", err)
  532. }
  533. BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
  534. BtcFailed::DecodeAndEncodeError(ref err) => {
  535. write!(f, "Decode and decode keys error: {}", err)
  536. }
  537. BtcFailed::KeypairError(ref err) => {
  538. write!(f, "Keypair error from Secp256k1: {}", err)
  539. }
  540. BtcFailed::Notification(i) => {
  541. write!(f, "Received Notification Error: {}", i)
  542. }
  543. BtcFailed::BtcError(i) => {
  544. write!(f, "BtcFailed: {}", i)
  545. }
  546. }
  547. }
  548. }
  549. impl From<crate::error::Error> for BtcFailed {
  550. fn from(err: crate::error::Error) -> BtcFailed {
  551. BtcFailed::BtcError(err.to_string())
  552. }
  553. }
  554. impl From<secp256k1::Error> for BtcFailed {
  555. fn from(err: secp256k1::Error) -> BtcFailed {
  556. BtcFailed::KeypairError(err.to_string())
  557. }
  558. }
  559. impl From<bitcoin::util::address::Error> for BtcFailed {
  560. fn from(err: bitcoin::util::address::Error) -> BtcFailed {
  561. BtcFailed::BadBtcAddress(err.to_string())
  562. }
  563. }
  564. impl From<electrum_client::Error> for BtcFailed {
  565. fn from(err: electrum_client::Error) -> BtcFailed {
  566. BtcFailed::ElectrumError(err.to_string())
  567. }
  568. }
  569. impl From<bitcoin::util::key::Error> for BtcFailed {
  570. fn from(err: bitcoin::util::key::Error) -> BtcFailed {
  571. BtcFailed::DecodeAndEncodeError(err.to_string())
  572. }
  573. }
  574. pub type BtcResult<T> = std::result::Result<T, BtcFailed>;
  575. #[cfg(test)]
  576. mod tests {
  577. use crate::serial::{deserialize, serialize};
  578. use std::str::FromStr;
  579. #[test]
  580. pub fn test_serialize_btc_address() -> super::BtcResult<()> {
  581. let btc_addr =
  582. bitcoin::Address::from_str(&String::from("mxVFsFW5N4mu1HPkxPttorvocvzeZ7KZyk"))?;
  583. let btc_ser = serialize(&btc_addr);
  584. let btc_dser = deserialize(&btc_ser)?;
  585. assert_eq!(btc_addr, btc_dser);
  586. Ok(())
  587. }
  588. }