btc.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. // TODO: This module needs cleanup related to PublicKey/SecretKey types.
  2. use std::{
  3. cmp::max,
  4. collections::BTreeMap,
  5. convert::{From, TryFrom, TryInto},
  6. fmt,
  7. ops::Add,
  8. str::FromStr,
  9. time::{Duration, Instant},
  10. };
  11. use anyhow::Context;
  12. use async_executor::Executor;
  13. use async_std::sync::{Arc, Mutex};
  14. use async_trait::async_trait;
  15. use bdk::electrum_client::{
  16. Client as ElectrumClient, ElectrumApi, GetBalanceRes, GetHistoryRes, HeaderNotification,
  17. };
  18. use bitcoin::{
  19. blockdata::{
  20. script::{Builder, Script},
  21. transaction::{OutPoint, SigHashType, Transaction, TxIn, TxOut},
  22. },
  23. consensus::encode::serialize_hex,
  24. hash_types::PubkeyHash as BtcPubKeyHash,
  25. network::constants::Network,
  26. util::{
  27. address::Address,
  28. ecdsa::{PrivateKey as BtcPrivKey, PublicKey as BtcPubKey},
  29. psbt::serialize::Serialize,
  30. },
  31. };
  32. use log::*;
  33. use secp256k1::{
  34. constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE},
  35. key::{PublicKey, SecretKey},
  36. rand::rngs::OsRng,
  37. All, Message as BtcMessage, Secp256k1,
  38. };
  39. use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
  40. use crate::{
  41. crypto::keypair::PublicKey as DrkPublicKey,
  42. serial::{deserialize, serialize, Decodable, Encodable},
  43. util::{generate_id2, NetworkName},
  44. Error, Result,
  45. };
  46. // Swap out these types for any future non bitcoin-rs types
  47. pub type PubAddress = Address;
  48. pub type PubKey = BtcPubKey;
  49. pub type PrivKey = BtcPrivKey;
  50. const KEYPAIR_LENGTH: usize = SECRET_KEY_SIZE + PUBLIC_KEY_SIZE;
  51. #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)]
  52. pub struct BlockHeight(u32);
  53. impl From<BlockHeight> for u32 {
  54. fn from(height: BlockHeight) -> Self {
  55. height.0
  56. }
  57. }
  58. impl TryFrom<HeaderNotification> for BlockHeight {
  59. type Error = BtcFailed;
  60. fn try_from(value: HeaderNotification) -> BtcResult<Self> {
  61. Ok(Self(value.height.try_into().context("Failed to fit usize into u32")?))
  62. }
  63. }
  64. impl Add<u32> for BlockHeight {
  65. type Output = BlockHeight;
  66. fn add(self, rhs: u32) -> Self::Output {
  67. BlockHeight(self.0 + rhs)
  68. }
  69. }
  70. #[derive(Debug, Clone, Copy, PartialEq)]
  71. pub enum ExpiredTimelocks {
  72. None,
  73. Cancel,
  74. Punish,
  75. }
  76. #[derive(Clone, Debug, PartialEq)]
  77. pub struct Keypair {
  78. secret: SecretKey,
  79. public: PublicKey,
  80. context: Secp256k1<All>,
  81. }
  82. impl Keypair {
  83. pub fn new() -> Self {
  84. let secp = Secp256k1::new();
  85. let mut rng = OsRng::new().expect("OsRng");
  86. let (secret, public) = secp.generate_keypair(&mut rng);
  87. Self { secret, public, context: secp }
  88. }
  89. pub fn to_bytes(&self) -> [u8; KEYPAIR_LENGTH] {
  90. let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH];
  91. bytes[..SECRET_KEY_SIZE].copy_from_slice(self.secret.as_ref());
  92. bytes[SECRET_KEY_SIZE..].copy_from_slice(&self.public.serialize());
  93. bytes
  94. }
  95. pub fn from_bytes(bytes: &[u8]) -> BtcResult<Keypair> {
  96. if bytes.len() != KEYPAIR_LENGTH {
  97. return Err(BtcFailed::KeypairError("Not right size".to_string()))
  98. }
  99. let secp = Secp256k1::new();
  100. let secret = SecretKey::from_slice(&bytes[..SECRET_KEY_SIZE])?;
  101. let public = PublicKey::from_slice(&bytes[SECRET_KEY_SIZE..])?;
  102. Ok(Keypair { secret, public, context: secp })
  103. }
  104. fn secret(&self) -> SecretKey {
  105. self.secret
  106. }
  107. pub fn pubkey(&self) -> PublicKey {
  108. self.public
  109. }
  110. pub fn as_tuple(&self) -> (SecretKey, PublicKey) {
  111. (self.secret, self.public)
  112. }
  113. }
  114. impl Default for Keypair {
  115. fn default() -> Self {
  116. Self::new()
  117. }
  118. }
  119. #[derive(Clone)]
  120. pub struct Account {
  121. keypair: Arc<Keypair>,
  122. btc_privkey: BtcPrivKey,
  123. pub btc_pubkey: BtcPubKey,
  124. pub address: Address,
  125. pub script_pubkey: Script,
  126. pub network: Network,
  127. }
  128. impl Account {
  129. pub fn new(keypair: &Keypair, network: Network) -> Self {
  130. let (secret_key, _public_key) = keypair.as_tuple();
  131. let btc_privkey = BtcPrivKey::new(secret_key, network);
  132. let btc_pubkey = btc_privkey.public_key(&keypair.context);
  133. let address = Account::derive_btc_address(btc_pubkey, network);
  134. let script_pubkey = address.script_pubkey();
  135. Self {
  136. keypair: Arc::new(keypair.clone()),
  137. btc_privkey,
  138. btc_pubkey,
  139. address,
  140. script_pubkey,
  141. network,
  142. }
  143. }
  144. pub fn priv_from_secret(keypair: &Keypair, network: Network) -> BtcPrivKey {
  145. BtcPrivKey::new(keypair.secret(), network)
  146. }
  147. pub fn btcpub_from_keypair(keypair: &Keypair) -> BtcPubKey {
  148. BtcPubKey::new(keypair.public)
  149. }
  150. pub fn btc_privkey(&self) -> &BtcPrivKey {
  151. &self.btc_privkey
  152. }
  153. pub fn btc_pubkey(&self) -> &BtcPubKey {
  154. &self.btc_pubkey
  155. }
  156. pub fn btc_pubkey_hash(&self) -> BtcPubKeyHash {
  157. self.btc_pubkey.pubkey_hash()
  158. }
  159. pub fn derive_btc_script_pubkey(pubkey: PublicKey, network: Network) -> Script {
  160. let btc_pubkey = BtcPubKey::new(pubkey);
  161. let address = Address::p2pkh(&btc_pubkey, network);
  162. address.script_pubkey()
  163. }
  164. pub fn derive_btc_pubkey(pubkey: PublicKey) -> BtcPubKey {
  165. BtcPubKey::new(pubkey)
  166. }
  167. pub fn derive_btc_address(btc_pubkey: BtcPubKey, network: Network) -> Address {
  168. Address::p2pkh(&btc_pubkey, network)
  169. }
  170. pub fn derive_script(btc_pubkey_hash: BtcPubKeyHash) -> Script {
  171. Script::new_p2pkh(&btc_pubkey_hash)
  172. }
  173. }
  174. fn print_status_change(
  175. script: &Script,
  176. old: Option<ScriptStatus>,
  177. new: ScriptStatus,
  178. ) -> ScriptStatus {
  179. match (old, new) {
  180. (None, new_status) => {
  181. debug!(target: "BTC BRIDGE", "Found relevant script: {:?}, Status: {:?}", script, new_status);
  182. }
  183. (Some(old_status), new_status) if old_status != new_status => {
  184. debug!(target: "BTC BRIDGE", "Script status changed: {:?}, to {} from {}", script, new_status, old_status);
  185. }
  186. _ => {}
  187. }
  188. new
  189. }
  190. fn sync_interval(avg_block_time: Duration) -> Duration {
  191. max(avg_block_time / 10, Duration::from_secs(1))
  192. }
  193. pub struct Client {
  194. electrum: ElectrumClient,
  195. subscriptions: Vec<Script>,
  196. latest_block_height: BlockHeight,
  197. last_sync: Instant,
  198. sync_interval: Duration,
  199. script_history: BTreeMap<Script, Vec<GetHistoryRes>>,
  200. }
  201. impl Client {
  202. pub fn new(electrum_url: &str) -> BtcResult<Self> {
  203. let config = bdk::electrum_client::ConfigBuilder::default().retry(5).build();
  204. let _client = ElectrumClient::from_config(electrum_url, config)?;
  205. let electrum = ElectrumClient::new(electrum_url)
  206. .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
  207. let latest_block = electrum.block_headers_subscribe()?;
  208. //testnet avg block time
  209. let interval = sync_interval(Duration::from_secs(300));
  210. Ok(Self {
  211. electrum,
  212. subscriptions: Vec::new(),
  213. latest_block_height: BlockHeight::try_from(latest_block)
  214. .map_err(|_| crate::Error::TryFromError)?,
  215. last_sync: Instant::now(),
  216. sync_interval: interval,
  217. script_history: Default::default(),
  218. })
  219. }
  220. fn update_state(&mut self) -> Result<()> {
  221. let now = Instant::now();
  222. if now < self.last_sync + self.sync_interval {
  223. return Ok(())
  224. }
  225. self.last_sync = now;
  226. self.update_latest_block()?;
  227. self.update_script_histories()?;
  228. Ok(())
  229. }
  230. fn update_latest_block(&mut self) -> BtcResult<()> {
  231. let latest_block = self.electrum.block_headers_subscribe()?;
  232. let latest_block_height = BlockHeight::try_from(latest_block)?;
  233. if latest_block_height > self.latest_block_height {
  234. debug!( target: "BTC BRIDGE", "{} {}",
  235. u32::from(latest_block_height),
  236. "Got notification for new block"
  237. );
  238. self.latest_block_height = latest_block_height;
  239. }
  240. Ok(())
  241. }
  242. fn update_script_histories(&mut self) -> BtcResult<()> {
  243. let histories = self.electrum.batch_script_get_history(self.script_history.keys())?;
  244. if histories.len() != self.script_history.len() {
  245. debug!(
  246. "Expected {} history entries, received {}",
  247. self.script_history.len(),
  248. histories.len()
  249. );
  250. }
  251. let scripts = self.script_history.keys().cloned();
  252. let histories = histories.into_iter();
  253. self.script_history = scripts.zip(histories).collect::<BTreeMap<_, _>>();
  254. Ok(())
  255. }
  256. pub fn status_of_script(&mut self, script: Script) -> BtcResult<ScriptStatus> {
  257. if !self.script_history.contains_key(&script) {
  258. self.script_history.insert(script.clone(), vec![]);
  259. }
  260. self.update_state()?;
  261. let history = self.script_history.entry(script).or_default();
  262. match history.as_slice() {
  263. [] => Ok(ScriptStatus::Unseen),
  264. [_remaining @ .., last] => {
  265. if last.height <= 0 {
  266. Ok(ScriptStatus::InMempool)
  267. } else {
  268. Ok(ScriptStatus::Confirmed(Confirmed::from_inclusion_and_latest_block(
  269. u32::try_from(last.height).map_err(|_| crate::Error::TryFromError)?,
  270. u32::from(self.latest_block_height),
  271. )))
  272. }
  273. }
  274. }
  275. }
  276. }
  277. pub struct BtcClient {
  278. main_account: Account,
  279. client: Arc<Mutex<Client>>,
  280. notify_channel:
  281. (async_channel::Sender<TokenNotification>, async_channel::Receiver<TokenNotification>),
  282. network: Network,
  283. }
  284. impl BtcClient {
  285. pub async fn new(main_keypair: Keypair, network: &str) -> Result<Arc<Self>> {
  286. let notify_channel = async_channel::unbounded();
  287. let (network, url) = match network {
  288. "mainnet" => (Network::Bitcoin, "ssl://electrum.blockstream.info:50002"),
  289. "testnet" => (Network::Testnet, "ssl://electrum.blockstream.info:60002"),
  290. _ => return Err(Error::NotSupportedNetwork),
  291. };
  292. let main_account = Account::new(&main_keypair, network);
  293. info!(target: "BTC BRIDGE", "Main BTC Address: {}", main_account.address.to_string());
  294. Ok(Arc::new(Self {
  295. main_account,
  296. client: Arc::new(Mutex::new(Client::new(url)?)),
  297. notify_channel,
  298. network,
  299. }))
  300. }
  301. async fn handle_subscribe_request(
  302. self: Arc<Self>,
  303. btc_keys: Account,
  304. drk_pub_key: DrkPublicKey,
  305. ) -> BtcResult<()> {
  306. let client = self.client.clone();
  307. let keys_clone = btc_keys.clone();
  308. let script = keys_clone.script_pubkey;
  309. if client.lock().await.subscriptions.contains(&script) {
  310. return Ok(())
  311. } else {
  312. client.lock().await.subscriptions.push(script.clone());
  313. }
  314. //Fetch any current balance
  315. let prev_balance = client.lock().await.electrum.script_get_balance(&script)?;
  316. let mut last_status = None;
  317. loop {
  318. async_std::task::sleep(Duration::from_secs(5)).await;
  319. let new_status = match client.lock().await.status_of_script(script.clone()) {
  320. Ok(new_status) => new_status,
  321. Err(error) => {
  322. debug!(target: "BTC BRIDGE", "Failed to get status of script: {:#}", error);
  323. return Err(BtcFailed::BtcError("Failed to get status of script".to_string()))
  324. }
  325. };
  326. last_status = Some(print_status_change(&script, last_status, new_status));
  327. match new_status {
  328. ScriptStatus::Unseen => continue,
  329. ScriptStatus::InMempool => break,
  330. ScriptStatus::Confirmed(inner) => {
  331. //Only break when confirmations happen
  332. let confirmations = inner.confirmations();
  333. if confirmations > 1 {
  334. break
  335. }
  336. }
  337. }
  338. }
  339. let index = &mut client.lock().await.subscriptions.iter().position(|p| p == &script);
  340. if let Some(ind) = index {
  341. trace!(target: "BTC BRIDGE", "Removing subscription from list");
  342. let _ = &mut client.lock().await.subscriptions.remove(*ind);
  343. }
  344. let cur_balance: GetBalanceRes =
  345. client.lock().await.electrum.script_get_balance(&script)?;
  346. let send_notification = self.notify_channel.0.clone();
  347. //FIXME: dev
  348. if cur_balance.unconfirmed < prev_balance.unconfirmed {
  349. return Err(BtcFailed::Notification("New balance is less than previous balance".into()))
  350. }
  351. //Just check unconfirmed for now
  352. let amnt = cur_balance.confirmed - prev_balance.confirmed;
  353. let ui_amnt = amnt;
  354. send_notification
  355. .send(TokenNotification {
  356. network: NetworkName::Bitcoin,
  357. // is btc an acceptable token name?
  358. token_id: generate_id2(
  359. "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
  360. &NetworkName::Bitcoin,
  361. )?,
  362. drk_pub_key,
  363. received_balance: amnt as u64,
  364. decimals: 8,
  365. })
  366. .await
  367. .map_err(Error::from)?;
  368. info!(target: "BTC BRIDGE", "Received {} btc", ui_amnt);
  369. let _ = self.send_btc_to_main_wallet(amnt as u64, btc_keys).await;
  370. Ok(())
  371. }
  372. async fn send_btc_to_main_wallet(
  373. self: Arc<Self>,
  374. amount: u64,
  375. btc_keys: Account,
  376. ) -> BtcResult<()> {
  377. info!(target: "BTC BRIDGE", "Sending {} BTC to main wallet", amount);
  378. let client = self.client.lock().await;
  379. let electrum = &client.electrum;
  380. let keys_clone = btc_keys.clone();
  381. let script = keys_clone.script_pubkey;
  382. let utxo = electrum.script_list_unspent(&script)?;
  383. let mut inputs = Vec::new();
  384. let mut amounts: u64 = 0;
  385. for tx in utxo {
  386. let tx_in = TxIn {
  387. previous_output: OutPoint { txid: tx.tx_hash, vout: tx.tx_pos as u32 },
  388. sequence: 0xffffffff,
  389. witness: Vec::new(),
  390. script_sig: Script::new(),
  391. };
  392. inputs.push(tx_in);
  393. amounts += tx.value;
  394. }
  395. let main_script_pubkey = self.main_account.script_pubkey.clone();
  396. //TODO: Change to PSBT
  397. let transaction = Transaction {
  398. input: inputs.clone(),
  399. output: vec![TxOut { script_pubkey: main_script_pubkey.clone(), value: amounts }],
  400. lock_time: 0,
  401. version: 2,
  402. };
  403. let tx_size = transaction.get_size();
  404. let fee_per_kb = electrum.estimate_fee(1)?;
  405. let _fee = tx_size as f64 * fee_per_kb * 100000_f64;
  406. let transaction = Transaction {
  407. input: inputs,
  408. output: vec![TxOut {
  409. script_pubkey: main_script_pubkey,
  410. // TODO: calculate fee properly above
  411. value: amounts - 400,
  412. }],
  413. lock_time: 0,
  414. version: 2,
  415. };
  416. let _txid = transaction.txid();
  417. let signed_tx = sign_transaction(
  418. transaction,
  419. script,
  420. btc_keys.keypair.secret,
  421. btc_keys.btc_pubkey,
  422. &btc_keys.keypair.context,
  423. )?;
  424. let _txid = signed_tx.txid();
  425. let _serialized_tx = serialize(&signed_tx);
  426. info!(target: "BTC BRIDGE", "Signed tx: {:?}",
  427. serialize_hex(&signed_tx));
  428. let txid = electrum.transaction_broadcast_raw(&signed_tx.serialize().to_vec())?;
  429. info!(target: "BTC BRIDGE", "Sent {} satoshi to main wallet, txid: {}", amount, txid);
  430. Ok(())
  431. }
  432. }
  433. #[async_trait]
  434. impl NetworkClient for BtcClient {
  435. async fn subscribe(
  436. self: Arc<Self>,
  437. drk_pub_key: DrkPublicKey,
  438. _mint: Option<String>,
  439. executor: Arc<Executor<'_>>,
  440. ) -> Result<TokenSubscribtion> {
  441. // Generate bitcoin keys
  442. let keypair = Keypair::new();
  443. let btc_keys = Account::new(&keypair, self.network);
  444. let private_key = serialize(&keypair);
  445. let public_key = btc_keys.address.to_string();
  446. // start scheduler for checking balance
  447. trace!(target: "BRIDGE BITCOIN", "Subscribing for deposit");
  448. executor
  449. .spawn(async move {
  450. let result = self.handle_subscribe_request(btc_keys, drk_pub_key).await;
  451. if let Err(e) = result {
  452. error!(target: "BTC BRIDGE SUBSCRIPTION","{}", e.to_string());
  453. }
  454. })
  455. .detach();
  456. Ok(TokenSubscribtion { private_key, public_key })
  457. }
  458. async fn subscribe_with_keypair(
  459. self: Arc<Self>,
  460. private_key: Vec<u8>,
  461. _public_key: Vec<u8>,
  462. drk_pub_key: DrkPublicKey,
  463. _mint: Option<String>,
  464. executor: Arc<Executor<'_>>,
  465. ) -> Result<String> {
  466. let keypair: Keypair = deserialize(&private_key)?;
  467. let btc_keys = Account::new(&keypair, self.network);
  468. let public_key = btc_keys.address.to_string();
  469. executor
  470. .spawn(async move {
  471. let result = self.handle_subscribe_request(btc_keys, drk_pub_key).await;
  472. if let Err(e) = result {
  473. error!(target: "BTC BRIDGE SUBSCRIPTION","{}", e.to_string());
  474. }
  475. })
  476. .detach();
  477. Ok(public_key)
  478. }
  479. async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>> {
  480. Ok(self.notify_channel.1.clone())
  481. }
  482. async fn send(
  483. self: Arc<Self>,
  484. address: Vec<u8>,
  485. _mint: Option<String>,
  486. amount: u64,
  487. ) -> Result<()> {
  488. // address is not a btc address, so derive the btc address
  489. let electrum = &self.client.lock().await.electrum;
  490. let public_key = deserialize(&address)?;
  491. let script_pubkey = Account::derive_btc_script_pubkey(public_key, self.network);
  492. let main_script_pubkey = &self.main_account.script_pubkey;
  493. let main_utxo = electrum
  494. .script_list_unspent(main_script_pubkey)
  495. .map_err(|e| Error::from(BtcFailed::from(e)))?;
  496. let transaction = Transaction {
  497. input: vec![TxIn {
  498. previous_output: OutPoint {
  499. txid: main_utxo[0].tx_hash,
  500. vout: main_utxo[0].tx_pos as u32,
  501. },
  502. sequence: 0xffffffff,
  503. witness: Vec::new(),
  504. script_sig: Script::new(),
  505. }],
  506. output: vec![TxOut {
  507. script_pubkey: script_pubkey.clone(),
  508. // TODO: Calculate fees
  509. value: amount - 300,
  510. }],
  511. lock_time: 0,
  512. version: 2,
  513. };
  514. let signed_tx = sign_transaction(
  515. transaction,
  516. script_pubkey,
  517. self.main_account.keypair.secret,
  518. self.main_account.btc_pubkey,
  519. &self.main_account.keypair.context,
  520. )?;
  521. let txid = electrum
  522. .transaction_broadcast_raw(&signed_tx.serialize().to_vec())
  523. .map_err(|e| Error::from(BtcFailed::from(e)))?;
  524. info!(target: "BTC BRIDGE", "Sent {} satoshi to external wallet, txid: {}", amount, txid);
  525. Ok(())
  526. }
  527. }
  528. pub fn sign_transaction(
  529. tx: Transaction,
  530. script_pubkey: Script,
  531. priv_key: SecretKey,
  532. pub_key: BtcPubKey,
  533. curve: &Secp256k1<All>,
  534. ) -> BtcResult<Transaction> {
  535. let mut signed_inputs: Vec<TxIn> = Vec::new();
  536. for (i, unsigned_input) in tx.input.iter().enumerate() {
  537. let sighash = tx.signature_hash(i, &script_pubkey, SigHashType::All as u32);
  538. let msg = BtcMessage::from_slice(sighash.as_ref())?;
  539. let signature = curve.sign(&msg, &priv_key);
  540. let byte_signature = &signature.serialize_der();
  541. let mut with_hashtype = byte_signature.to_vec();
  542. with_hashtype.push(SigHashType::All as u8);
  543. let redeem_script =
  544. Builder::new().push_slice(with_hashtype.as_slice()).push_key(&pub_key).into_script();
  545. signed_inputs.push(TxIn {
  546. previous_output: unsigned_input.previous_output,
  547. script_sig: redeem_script,
  548. sequence: unsigned_input.sequence,
  549. witness: unsigned_input.witness.clone(),
  550. });
  551. }
  552. Ok(Transaction {
  553. version: tx.version,
  554. lock_time: tx.lock_time,
  555. input: signed_inputs,
  556. output: tx.output,
  557. })
  558. }
  559. #[derive(Debug, Copy, Clone, PartialEq)]
  560. pub enum ScriptStatus {
  561. Unseen,
  562. InMempool,
  563. Confirmed(Confirmed),
  564. }
  565. impl ScriptStatus {
  566. pub fn from_confirmations(confirmations: u32) -> Self {
  567. match confirmations {
  568. 0 => Self::InMempool,
  569. confirmations => Self::Confirmed(Confirmed::new(confirmations - 1)),
  570. }
  571. }
  572. }
  573. #[derive(Debug, Copy, Clone, PartialEq)]
  574. pub struct Confirmed {
  575. depth: u32,
  576. }
  577. impl Confirmed {
  578. pub fn new(depth: u32) -> Self {
  579. Self { depth }
  580. }
  581. pub fn from_inclusion_and_latest_block(inclusion_height: u32, latest_block: u32) -> Self {
  582. let depth = latest_block.saturating_sub(inclusion_height);
  583. Self { depth }
  584. }
  585. pub fn confirmations(&self) -> u32 {
  586. self.depth + 1
  587. }
  588. pub fn meets_target<T>(&self, target: T) -> bool
  589. where
  590. u32: PartialOrd<T>,
  591. {
  592. self.confirmations() >= target
  593. }
  594. }
  595. impl ScriptStatus {
  596. // Check if the script has any confirmations.
  597. pub fn is_confirmed(&self) -> bool {
  598. matches!(self, ScriptStatus::Confirmed(_))
  599. }
  600. // Check if the script has met the given confirmation target.
  601. pub fn is_confirmed_with<T>(&self, target: T) -> bool
  602. where
  603. u32: PartialOrd<T>,
  604. {
  605. match self {
  606. ScriptStatus::Confirmed(inner) => inner.meets_target(target),
  607. _ => false,
  608. }
  609. }
  610. pub fn has_been_seen(&self) -> bool {
  611. matches!(self, ScriptStatus::InMempool | ScriptStatus::Confirmed(_))
  612. }
  613. }
  614. impl fmt::Display for ScriptStatus {
  615. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  616. match self {
  617. ScriptStatus::Unseen => write!(f, "unseen"),
  618. ScriptStatus::InMempool => write!(f, "in mempool"),
  619. ScriptStatus::Confirmed(inner) => {
  620. write!(f, "confirmed with {} blocks", inner.confirmations())
  621. }
  622. }
  623. }
  624. }
  625. impl Encodable for bitcoin::Transaction {
  626. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  627. let tx = self.serialize();
  628. let len = tx.encode(s)?;
  629. Ok(len)
  630. }
  631. }
  632. impl Encodable for bitcoin::Address {
  633. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  634. let addr = self.to_string();
  635. let len = addr.encode(s)?;
  636. Ok(len)
  637. }
  638. }
  639. impl Decodable for bitcoin::Address {
  640. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  641. let addr: String = Decodable::decode(&mut d)?;
  642. let addr = bitcoin::Address::from_str(&addr)
  643. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  644. Ok(addr)
  645. }
  646. }
  647. impl Encodable for bitcoin::PublicKey {
  648. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  649. let key = self.to_bytes();
  650. let len = key.encode(s)?;
  651. Ok(len)
  652. }
  653. }
  654. impl Decodable for bitcoin::PublicKey {
  655. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  656. let key: Vec<u8> = Decodable::decode(&mut d)?;
  657. let key = bitcoin::PublicKey::from_slice(&key)
  658. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  659. Ok(key)
  660. }
  661. }
  662. impl Encodable for bitcoin::PrivateKey {
  663. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  664. let key: String = self.to_string();
  665. let len = key.encode(s)?;
  666. Ok(len)
  667. }
  668. }
  669. impl Decodable for bitcoin::PrivateKey {
  670. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  671. let key: String = Decodable::decode(&mut d)?;
  672. let key = bitcoin::PrivateKey::from_str(&key)
  673. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  674. Ok(key)
  675. }
  676. }
  677. impl Encodable for secp256k1::key::PublicKey {
  678. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  679. let key: Vec<u8> = self.serialize().to_vec();
  680. let len = key.encode(s)?;
  681. Ok(len)
  682. }
  683. }
  684. impl Decodable for secp256k1::key::PublicKey {
  685. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  686. let key: Vec<u8> = Decodable::decode(&mut d)?;
  687. let key = secp256k1::key::PublicKey::from_slice(&key)
  688. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  689. Ok(key)
  690. }
  691. }
  692. // TODO: add secret + public keys together for Encodable
  693. impl Encodable for Keypair {
  694. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  695. let key: Vec<u8> = self.to_bytes().to_vec();
  696. let len = key.encode(s)?;
  697. Ok(len)
  698. }
  699. }
  700. impl Decodable for Keypair {
  701. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  702. let key: Vec<u8> = Decodable::decode(&mut d)?;
  703. let key = Keypair::from_bytes(key.as_slice()).map_err(|_| {
  704. crate::Error::from(BtcFailed::DecodeAndEncodeError("load keypair from slice".into()))
  705. })?;
  706. Ok(key)
  707. }
  708. }
  709. #[derive(Debug, Clone, thiserror::Error)]
  710. pub enum BtcFailed {
  711. #[error("There is no enough value {0}")]
  712. NotEnoughValue(u64),
  713. #[error("could not parse BTC address: {0}")]
  714. BadBtcAddress(String),
  715. #[error("Unable to create Electrum Client: {0}")]
  716. ElectrumError(String),
  717. #[error("BtcFailed: {0}")]
  718. BtcError(String),
  719. #[error("Decode and decode keys error: {0}")]
  720. DecodeAndEncodeError(String),
  721. #[error("Keypair error from Secp256k1: {0}")]
  722. KeypairError(String),
  723. #[error("Received Notification Error: {0}")]
  724. Notification(String),
  725. }
  726. impl From<crate::error::Error> for BtcFailed {
  727. fn from(err: crate::error::Error) -> BtcFailed {
  728. BtcFailed::BtcError(err.to_string())
  729. }
  730. }
  731. impl From<secp256k1::Error> for BtcFailed {
  732. fn from(err: secp256k1::Error) -> BtcFailed {
  733. BtcFailed::KeypairError(err.to_string())
  734. }
  735. }
  736. impl From<bitcoin::util::address::Error> for BtcFailed {
  737. fn from(err: bitcoin::util::address::Error) -> BtcFailed {
  738. BtcFailed::BadBtcAddress(err.to_string())
  739. }
  740. }
  741. impl From<bdk::electrum_client::Error> for BtcFailed {
  742. fn from(err: bdk::electrum_client::Error) -> BtcFailed {
  743. BtcFailed::ElectrumError(err.to_string())
  744. }
  745. }
  746. impl From<bitcoin::util::key::Error> for BtcFailed {
  747. fn from(err: bitcoin::util::key::Error) -> BtcFailed {
  748. BtcFailed::DecodeAndEncodeError(err.to_string())
  749. }
  750. }
  751. impl From<anyhow::Error> for BtcFailed {
  752. fn from(err: anyhow::Error) -> BtcFailed {
  753. BtcFailed::DecodeAndEncodeError(err.to_string())
  754. }
  755. }
  756. pub type BtcResult<T> = std::result::Result<T, BtcFailed>;
  757. #[cfg(test)]
  758. mod tests {
  759. use super::Keypair;
  760. use crate::serial::{deserialize, serialize};
  761. use secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE};
  762. use std::str::FromStr;
  763. const KEYPAIR_LENGTH: usize = SECRET_KEY_SIZE + PUBLIC_KEY_SIZE;
  764. #[test]
  765. pub fn test_serialize_btc_address() -> super::BtcResult<()> {
  766. let btc_addr =
  767. bitcoin::Address::from_str(&String::from("mxVFsFW5N4mu1HPkxPttorvocvzeZ7KZyk"))?;
  768. let btc_ser = serialize(&btc_addr);
  769. let btc_dser = deserialize(&btc_ser)?;
  770. assert_eq!(btc_addr, btc_dser);
  771. Ok(())
  772. }
  773. #[test]
  774. pub fn test_serialize_and_deserialize_keypair() -> super::BtcResult<()> {
  775. let keypair = Keypair::new();
  776. let bytes: [u8; KEYPAIR_LENGTH] = keypair.to_bytes();
  777. let keys = Keypair::from_bytes(&bytes)?;
  778. assert_eq!(keypair, keys);
  779. Ok(())
  780. }
  781. }