btc.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
  2. use crate::serial::{serialize, Decodable, Encodable};
  3. use crate::{Error, Result};
  4. use async_trait::async_trait;
  5. use bitcoin::blockdata::script::Script;
  6. use bitcoin::hash_types::{PubkeyHash as BtcPubKeyHash, Txid};
  7. use bitcoin::network::constants::Network;
  8. use bitcoin::util::address::Address;
  9. use bitcoin::util::ecdsa::{PrivateKey as BtcPrivKey, PublicKey as BtcPubKey};
  10. use electrum_client::{Client as ElectrumClient, ElectrumApi};
  11. use log::*;
  12. use secp256k1::key::{PublicKey, SecretKey};
  13. use secp256k1::{rand::rngs::OsRng, Secp256k1};
  14. use async_std::sync::Arc;
  15. use std::str::FromStr;
  16. // Swap out these types for any future non bitcoin-rs types
  17. pub type PubAddress = Address;
  18. pub type PubKey = BtcPubKey;
  19. pub type PrivKey = BtcPrivKey;
  20. pub struct BitcoinKeys {
  21. secret_key: SecretKey,
  22. public_key: PublicKey,
  23. _context: Secp256k1<secp256k1::All>,
  24. btc_privkey: BtcPrivKey,
  25. pub btc_pubkey: BtcPubKey,
  26. pub network: Network,
  27. }
  28. impl BitcoinKeys {
  29. pub fn new(network: Network) -> Result<Arc<BitcoinKeys>> {
  30. let secp = Secp256k1::new();
  31. let mut rng = OsRng::new().expect("OsRng");
  32. let (secret_key, public_key) = secp.generate_keypair(&mut rng);
  33. let btc_privkey = BtcPrivKey::new(secret_key, network);
  34. let btc_pubkey = btc_privkey.public_key(&secp);
  35. Ok(Arc::new(BitcoinKeys {
  36. secret_key,
  37. public_key,
  38. _context: secp,
  39. btc_privkey,
  40. btc_pubkey,
  41. network,
  42. }))
  43. }
  44. pub fn pubkey(&self) -> &PublicKey {
  45. &self.public_key
  46. }
  47. pub fn btc_privkey(&self) -> &BtcPrivKey {
  48. &self.btc_privkey
  49. }
  50. pub fn btc_pubkey(&self) -> &BtcPubKey {
  51. &self.btc_pubkey
  52. }
  53. pub fn btc_pubkey_hash(&self) -> BtcPubKeyHash {
  54. self.btc_pubkey.pubkey_hash()
  55. }
  56. pub fn derive_btc_address(btc_pubkey: BtcPubKey, network: Network) -> Address {
  57. Address::p2pkh(&btc_pubkey, network)
  58. }
  59. pub fn derive_script(btc_pubkey_hash: BtcPubKeyHash) -> Script {
  60. Script::new_p2pkh(&btc_pubkey_hash)
  61. }
  62. }
  63. pub struct BtcClient {
  64. client: Arc<ElectrumClient>,
  65. network: Network,
  66. keypair: BitcoinKeys,
  67. }
  68. impl BtcClient {
  69. pub fn new(network: &str, keypair: BitcoinKeys) -> Result<Arc<Self>> {
  70. let (network, url) = match network {
  71. "mainnet" => (Network::Bitcoin, "ssl://electrum.blockstream.info:50002"),
  72. "testnet" => (Network::Testnet, "ssl://electrum.blockstream.info:60002"),
  73. _ => return Err(Error::NotSupportedNetwork),
  74. };
  75. let electrum_client = ElectrumClient::new(&url)
  76. .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
  77. Ok(Arc::new(Self {
  78. client: Arc::new(electrum_client),
  79. network,
  80. keypair,
  81. }))
  82. }
  83. async fn handle_subscribe_request(
  84. self: Arc<Self>,
  85. keypair: Arc<BitcoinKeys>,
  86. ) -> BtcResult<(Txid, u64)> {
  87. debug!(
  88. target: "BTC BRIDGE",
  89. "Handle subscribe request"
  90. );
  91. let client = &self.client;
  92. // p2pkh script
  93. let script = BitcoinKeys::derive_script(keypair.btc_pubkey_hash());
  94. if let Some(status_start) = client.script_subscribe(&script)? {
  95. loop {
  96. match client.script_pop(&script)? {
  97. Some(status) => {
  98. // Script has a notification update
  99. if status != status_start {
  100. let balance = client.script_get_balance(&script)?;
  101. if balance.confirmed > 0 {
  102. debug!(target: "BTC CLIENT", "BTC Balance: Confirmed!");
  103. let history = client.script_get_history(&script)?;
  104. //return tx_hash of latest tx that created balance
  105. return Ok((history[0].tx_hash, balance.confirmed));
  106. } else {
  107. debug!(target: "BTC CLIENT", "BTC Balance: Unconfirmed!");
  108. continue;
  109. }
  110. } else {
  111. debug!(target: "BTC CLIENT", "ScriptPubKey status has not changed");
  112. continue;
  113. }
  114. }
  115. None => {
  116. debug!(target: "BTC CLIENT", "Scriptpubkey does not yet exist in script notifications!");
  117. continue;
  118. }
  119. };
  120. } // Endloop
  121. } else {
  122. return Err(BtcFailed::ElectrumError(
  123. "Did not subscribe to scriptpubkey".to_string(),
  124. ));
  125. }
  126. //let keypair = serialize(&keypair);
  127. //Ok(())
  128. }
  129. }
  130. #[async_trait]
  131. impl NetworkClient for BtcClient {
  132. async fn subscribe(
  133. self: Arc<Self>,
  134. _drk_pub_key: jubjub::SubgroupPoint,
  135. _mint: Option<String>,
  136. ) -> Result<TokenSubscribtion> {
  137. // Generate bitcoin keys
  138. let btc_keys = BitcoinKeys::new(self.network)?;
  139. let btc_privkey = btc_keys.clone();
  140. let btc_privkey = btc_privkey.btc_privkey();
  141. let btc_pubkey = btc_keys.clone();
  142. let btc_pubkey = btc_pubkey.btc_pubkey();
  143. // start scheduler for checking balance
  144. debug!(target: "BRIDGE BITCOIN", "Subscribing for deposit");
  145. //let (_txid, _balance) = btc_keys.start_subscribe().await?;
  146. smol::spawn(self.handle_subscribe_request(btc_keys)).detach();
  147. Ok(TokenSubscribtion {
  148. secret_key: serialize(&btc_privkey.to_bytes()),
  149. public_key: btc_pubkey.to_string(),
  150. })
  151. }
  152. async fn subscribe_with_keypair(
  153. self: Arc<Self>,
  154. _private_key: Vec<u8>,
  155. _public_key: Vec<u8>,
  156. _drk_pub_key: jubjub::SubgroupPoint,
  157. _mint: Option<String>,
  158. ) -> Result<String> {
  159. // TODO this not implemented yet
  160. Ok(String::new())
  161. }
  162. async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>> {
  163. // TODO this not implemented yet
  164. let (_, notifier) = async_channel::unbounded();
  165. Ok(notifier)
  166. }
  167. async fn send(self: Arc<Self>, _address: Vec<u8>, _amount: u64) -> Result<()> {
  168. // TODO this not implemented yet
  169. Ok(())
  170. }
  171. }
  172. impl Encodable for bitcoin::Address {
  173. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  174. let addr = self.to_string();
  175. let len = addr.encode(s)?;
  176. Ok(len)
  177. }
  178. }
  179. impl Decodable for bitcoin::Address {
  180. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  181. let addr: String = Decodable::decode(&mut d)?;
  182. let addr = bitcoin::Address::from_str(&addr)
  183. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  184. Ok(addr)
  185. }
  186. }
  187. impl Encodable for bitcoin::PublicKey {
  188. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  189. let key = self.to_bytes();
  190. let len = key.encode(s)?;
  191. Ok(len)
  192. }
  193. }
  194. impl Decodable for bitcoin::PublicKey {
  195. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  196. let key: Vec<u8> = Decodable::decode(&mut d)?;
  197. let key = bitcoin::PublicKey::from_slice(&key)
  198. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  199. Ok(key)
  200. }
  201. }
  202. impl Encodable for bitcoin::PrivateKey {
  203. fn encode<S: std::io::Write>(&self, s: S) -> Result<usize> {
  204. let key: String = self.to_string();
  205. let len = key.encode(s)?;
  206. Ok(len)
  207. }
  208. }
  209. impl Decodable for bitcoin::PrivateKey {
  210. fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
  211. let key: String = Decodable::decode(&mut d)?;
  212. let key = bitcoin::PrivateKey::from_str(&key)
  213. .map_err(|err| crate::Error::from(BtcFailed::from(err)))?;
  214. Ok(key)
  215. }
  216. }
  217. #[derive(Debug)]
  218. pub enum BtcFailed {
  219. NotEnoughValue(u64),
  220. BadBtcAddress(String),
  221. ElectrumError(String),
  222. BtcError(String),
  223. DecodeAndEncodeError(String),
  224. }
  225. impl std::error::Error for BtcFailed {}
  226. impl std::fmt::Display for BtcFailed {
  227. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  228. match self {
  229. BtcFailed::NotEnoughValue(i) => {
  230. write!(f, "There is no enough value {}", i)
  231. }
  232. BtcFailed::BadBtcAddress(ref err) => {
  233. write!(f, "Unable to create Electrum Client: {}", err)
  234. }
  235. BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
  236. BtcFailed::DecodeAndEncodeError(ref err) => {
  237. write!(f, "Decode and decode keys error: {}", err)
  238. }
  239. BtcFailed::BtcError(i) => {
  240. write!(f, "BtcFailed: {}", i)
  241. }
  242. }
  243. }
  244. }
  245. impl From<crate::error::Error> for BtcFailed {
  246. fn from(err: crate::error::Error) -> BtcFailed {
  247. BtcFailed::BtcError(err.to_string())
  248. }
  249. }
  250. impl From<bitcoin::util::address::Error> for BtcFailed {
  251. fn from(err: bitcoin::util::address::Error) -> BtcFailed {
  252. BtcFailed::BadBtcAddress(err.to_string())
  253. }
  254. }
  255. impl From<electrum_client::Error> for BtcFailed {
  256. fn from(err: electrum_client::Error) -> BtcFailed {
  257. BtcFailed::ElectrumError(err.to_string())
  258. }
  259. }
  260. impl From<bitcoin::util::key::Error> for BtcFailed {
  261. fn from(err: bitcoin::util::key::Error) -> BtcFailed {
  262. BtcFailed::DecodeAndEncodeError(err.to_string())
  263. }
  264. }
  265. pub type BtcResult<T> = std::result::Result<T, BtcFailed>;
  266. #[cfg(test)]
  267. mod tests {
  268. use crate::serial::{deserialize, serialize};
  269. use std::str::FromStr;
  270. #[test]
  271. pub fn test_serialize_btc_address() -> super::BtcResult<()> {
  272. let btc_addr =
  273. bitcoin::Address::from_str(&String::from("mxVFsFW5N4mu1HPkxPttorvocvzeZ7KZyk"))?;
  274. let btc_ser = serialize(&btc_addr);
  275. let btc_dser = deserialize(&btc_ser)?;
  276. assert_eq!(btc_addr, btc_dser);
  277. Ok(())
  278. }
  279. }