Przeglądaj źródła

btc: Issue a new keypair if old key has been used

Janus 4 lat temu
rodzic
commit
baea27c543
4 zmienionych plików z 52 dodań i 39 usunięć
  1. 6 2
      src/bin/cashierd.rs
  2. 44 35
      src/service/btc.rs
  3. 1 1
      src/service/mod.rs
  4. 1 1
      todo.md

+ 6 - 2
src/bin/cashierd.rs

@@ -510,7 +510,7 @@ impl Cashierd {
                 #[cfg(feature = "btc")]
                 #[cfg(feature = "btc")]
                 NetworkName::Bitcoin => {
                 NetworkName::Bitcoin => {
                     debug!(target: "CASHIER DAEMON", "Add btc network");
                     debug!(target: "CASHIER DAEMON", "Add btc network");
-                    use drk::service::btc::{BtcClient, BtcFailed, Keypair};
+                    use drk::service::btc::{used_key, BtcClient, BtcFailed, Keypair};
 
 
                     let bridge2 = self.bridge.clone();
                     let bridge2 = self.bridge.clone();
 
 
@@ -519,7 +519,11 @@ impl Cashierd {
                     let main_keypairs = self.cashier_wallet.get_main_keys(&NetworkName::Bitcoin)?;
                     let main_keypairs = self.cashier_wallet.get_main_keys(&NetworkName::Bitcoin)?;
 
 
                     if network.keypair.is_empty() {
                     if network.keypair.is_empty() {
-                        if main_keypairs.is_empty() {
+                        //TODO: There needs to be a better way to flag completed txs
+                        if main_keypairs.is_empty() || used_key(
+                            &main_keypairs[main_keypairs.len() - 1].private_key,
+                            &network.blockchain,
+                        )? {
                             main_keypair = Keypair::new();
                             main_keypair = Keypair::new();
                             self.cashier_wallet.put_main_keys(
                             self.cashier_wallet.put_main_keys(
                                 &TokenKey {
                                 &TokenKey {

+ 44 - 35
src/service/btc.rs

@@ -203,23 +203,50 @@ fn print_status_change(
 ) -> ScriptStatus {
 ) -> ScriptStatus {
     match (old, new) {
     match (old, new) {
         (None, new_status) => {
         (None, new_status) => {
-            debug!(target: "BTC BRIDGE", "Found relevant Bitcoin transaction: {:?} {:?}", script, new_status);
+            debug!(target: "BTC BRIDGE", "Found relevant script: {:?}, Status: {:?}", script, new_status);
         }
         }
         (Some(old_status), new_status) if old_status != new_status => {
         (Some(old_status), new_status) if old_status != new_status => {
-            debug!(target: "BTC BRIDGE", "Bitcoin transaction status changed: {:?} {} {}", script, new_status, old_status);
+            debug!(target: "BTC BRIDGE", "Script status changed: {:?}, to {} from {}", script, new_status, old_status);
         }
         }
         _ => {}
         _ => {}
     }
     }
 
 
     new
     new
 }
 }
+pub fn used_key(keys: &Vec<u8>, network: &str) -> Result<bool> {
+    let keypair: Keypair = deserialize(keys)?;
 
 
+    //TODO: Don't create an electrum client just to check address status
+    let (network, url) = match network {
+        "mainnet" => (Network::Bitcoin, "ssl://electrum.blockstream.info:50002"),
+        "testnet" => (Network::Testnet, "ssl://electrum.blockstream.info:60002"),
+        _ => return Err(Error::NotSupportedNetwork),
+    };
+    let btc_keys = Account::new(&keypair, network);
+    let script = btc_keys.script_pubkey;
+
+    let electrum =
+        ElectrumClient::new(url).map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
+
+    let history = electrum
+        .script_get_history(&script)
+        .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
+    let balance = electrum
+        .script_get_balance(&script)
+        .map_err(|err| crate::Error::from(super::BtcFailed::from(err)))?;
+
+    if !history.is_empty() && balance.confirmed == 0 {
+        Ok(true)
+    } else {
+        Ok(false)
+    }
+}
 fn sync_interval(avg_block_time: Duration) -> Duration {
 fn sync_interval(avg_block_time: Duration) -> Duration {
     max(avg_block_time / 10, Duration::from_secs(1))
     max(avg_block_time / 10, Duration::from_secs(1))
 }
 }
 pub struct Client {
 pub struct Client {
     electrum: ElectrumClient,
     electrum: ElectrumClient,
-    subscriptions: Arc<Mutex<Vec<Script>>>,
+    subscriptions: Vec<Script>,
     latest_block_height: BlockHeight,
     latest_block_height: BlockHeight,
     last_sync: Instant,
     last_sync: Instant,
     sync_interval: Duration,
     sync_interval: Duration,
@@ -242,7 +269,7 @@ impl Client {
 
 
         Ok(Self {
         Ok(Self {
             electrum,
             electrum,
-            subscriptions: Arc::new(Mutex::new(Vec::new())),
+            subscriptions: Vec::new(),
             latest_block_height: BlockHeight::try_from(latest_block)
             latest_block_height: BlockHeight::try_from(latest_block)
                 .map_err(|_| crate::Error::TryFromError)?,
                 .map_err(|_| crate::Error::TryFromError)?,
             last_sync: Instant::now(),
             last_sync: Instant::now(),
@@ -361,25 +388,15 @@ impl BtcClient {
         btc_keys: Account,
         btc_keys: Account,
         drk_pub_key: jubjub::SubgroupPoint,
         drk_pub_key: jubjub::SubgroupPoint,
     ) -> BtcResult<()> {
     ) -> BtcResult<()> {
-        debug!(
-            target: "BTC BRIDGE",
-            "Handle subscribe request"
-        );
         let client = self.client.clone();
         let client = self.client.clone();
-        debug!(
-            target: "BTC BRIDGE",
-            "electrum lock"
-        );
+
         let keys_clone = btc_keys.clone();
         let keys_clone = btc_keys.clone();
         let script = keys_clone.script_pubkey;
         let script = keys_clone.script_pubkey;
 
 
-        //Check if we're already subscribed
         if client
         if client
             .lock()
             .lock()
             .await
             .await
             .subscriptions
             .subscriptions
-            .lock()
-            .await
             .contains(&script)
             .contains(&script)
         {
         {
             return Ok(());
             return Ok(());
@@ -388,16 +405,8 @@ impl BtcClient {
                 .lock()
                 .lock()
                 .await
                 .await
                 .subscriptions
                 .subscriptions
-                .lock()
-                .await
                 .push(script.clone());
                 .push(script.clone());
         }
         }
-
-        debug!(
-            target: "BTC BRIDGE",
-            "subscriptions"
-        );
-
         //Fetch any current balance
         //Fetch any current balance
         let prev_balance = client.lock().await.electrum.script_get_balance(&script)?;
         let prev_balance = client.lock().await.electrum.script_get_balance(&script)?;
         let cur_balance: GetBalanceRes;
         let cur_balance: GetBalanceRes;
@@ -419,27 +428,28 @@ impl BtcClient {
 
 
             match new_status {
             match new_status {
                 ScriptStatus::Unseen => continue,
                 ScriptStatus::Unseen => continue,
-                ScriptStatus::InMempool => continue,
+                ScriptStatus::InMempool => {
+                    break;
+                },
                 ScriptStatus::Confirmed(inner) => {
                 ScriptStatus::Confirmed(inner) => {
                     let confirmations = inner.confirmations();
                     let confirmations = inner.confirmations();
-                    if confirmations > 0 {
-                        break;
-                    }
+                    //if confirmations < 1 {
+                    break;
+                    //}
                 }
                 }
             }
             }
         }
         }
 
 
-        let client2 = client.lock().await;
-        let mut subscriptions = client2.subscriptions.lock().await;
-        let index = subscriptions.iter().position(|p| p == &script);
+        let index = &mut client.lock().await.subscriptions.iter().position(|p| p == &script);
+
         if let Some(ind) = index {
         if let Some(ind) = index {
-            debug!("Removing subscription from list");
-            subscriptions.remove(ind);
+            debug!(target: "BTC BRIDGE", "Removing subscription from list");
+            let _ = &mut client.lock().await.subscriptions.remove(*ind);
         }
         }
+
         cur_balance = client.lock().await.electrum.script_get_balance(&script)?;
         cur_balance = client.lock().await.electrum.script_get_balance(&script)?;
 
 
         let send_notification = self.notify_channel.0.clone();
         let send_notification = self.notify_channel.0.clone();
-
         if cur_balance.confirmed < prev_balance.confirmed {
         if cur_balance.confirmed < prev_balance.confirmed {
             return Err(BtcFailed::Notification(
             return Err(BtcFailed::Notification(
                 "New balance is less than previous balance".into(),
                 "New balance is less than previous balance".into(),
@@ -448,7 +458,6 @@ impl BtcClient {
 
 
         let amnt = cur_balance.confirmed - prev_balance.confirmed;
         let amnt = cur_balance.confirmed - prev_balance.confirmed;
         let ui_amnt = amnt;
         let ui_amnt = amnt;
-
         send_notification
         send_notification
             .send(TokenNotification {
             .send(TokenNotification {
                 network: NetworkName::Bitcoin,
                 network: NetworkName::Bitcoin,
@@ -517,7 +526,7 @@ impl BtcClient {
             output: vec![TxOut {
             output: vec![TxOut {
                 script_pubkey: main_script_pubkey,
                 script_pubkey: main_script_pubkey,
                 // TODO: calculate fee properly above
                 // TODO: calculate fee properly above
-                value: amounts - 300,
+                value: amounts - 400,
             }],
             }],
             lock_time: 0,
             lock_time: 0,
             version: 2,
             version: 2,

+ 1 - 1
src/service/mod.rs

@@ -6,7 +6,7 @@ pub mod reqrep;
 #[cfg(feature = "btc")]
 #[cfg(feature = "btc")]
 pub mod btc;
 pub mod btc;
 #[cfg(feature = "btc")]
 #[cfg(feature = "btc")]
-pub use btc::{Account, BtcFailed, BtcResult, Keypair, PubAddress};
+pub use btc::{Account, BtcFailed, BtcResult, Keypair, PubAddress, used_key};
 
 
 #[cfg(feature = "sol")]
 #[cfg(feature = "sol")]
 pub mod sol;
 pub mod sol;

+ 1 - 1
todo.md

@@ -10,7 +10,7 @@
 - [x] add genesis btc coinbase addr as token id
 - [x] add genesis btc coinbase addr as token id
 - [x] serialize/encode btc keypairs
 - [x] serialize/encode btc keypairs
 - [x] fix electrum rpc error: sendrawtransaction: TX decode failed
 - [x] fix electrum rpc error: sendrawtransaction: TX decode failed
-- [ ] fix unsubscribe generating errors from electrum rpc
+- [x] fix unsubscribe generating errors from electrum rpc
 - [x] start hosting cashierd and gatewayd
 - [x] start hosting cashierd and gatewayd
 - [x] add cashierd public key to darkfid.toml defaults
 - [x] add cashierd public key to darkfid.toml defaults