Forráskód Böngészése

darkfid return ClientResult with a proper message instead of panic and crash

ghassmo 5 éve
szülő
commit
fff6827343

+ 59 - 37
src/client/client.rs

@@ -17,7 +17,7 @@ use crate::state::{state_transition, ProgramState, StateUpdate};
 use crate::wallet::WalletPtr;
 use crate::{tx, Result};
 
-use super::ClientResult;
+use super::{ClientFailed, ClientResult};
 
 use async_executor::Executor;
 use bellman::groth16;
@@ -144,12 +144,12 @@ impl Client {
         let (deposit_req_send, deposit_req_recv) =
             async_channel::unbounded::<jubjub::SubgroupPoint>();
         let (deposit_rep_send, deposit_rep_recv) =
-            async_channel::unbounded::<Option<bitcoin::util::address::Address>>();
+            async_channel::unbounded::<ClientResult<bitcoin::util::address::Address>>();
 
         // channel to request withdraw from adapter, send BTC key and receive DRK key
         let (withdraw_req_send, withdraw_req_recv) = async_channel::unbounded::<String>();
         let (withdraw_rep_send, withdraw_rep_recv) =
-            async_channel::unbounded::<Option<jubjub::SubgroupPoint>>();
+            async_channel::unbounded::<ClientResult<jubjub::SubgroupPoint>>();
 
         // start cashier_client
         cashier_client.start().await?;
@@ -188,9 +188,9 @@ impl Client {
         wallet: WalletPtr,
         gateway_slabs_sub: async_channel::Receiver<Slab>,
         deposit_req: async_channel::Receiver<jubjub::SubgroupPoint>,
-        deposit_rep: async_channel::Sender<Option<bitcoin::util::address::Address>>,
+        deposit_rep: async_channel::Sender<ClientResult<bitcoin::util::address::Address>>,
         withdraw_req: async_channel::Receiver<String>,
-        withdraw_rep: async_channel::Sender<Option<jubjub::SubgroupPoint>>,
+        withdraw_rep: async_channel::Sender<ClientResult<jubjub::SubgroupPoint>>,
         transfer_req: async_channel::Receiver<TransferParams>,
         transfer_rep: async_channel::Sender<ClientResult<()>>,
     ) -> Result<()> {
@@ -203,56 +203,75 @@ impl Client {
                     self.state.apply(update, wallet.clone()).await?;
                 }
                 deposit_addr = deposit_req.recv().fuse() => {
-                    let btc_public = cashier_client.get_address(deposit_addr?).await?;
-                    deposit_rep.send(btc_public).await?;
+                    let btc_public = cashier_client.get_address(deposit_addr?).await.map_err(|err| {ClientFailed::from(err)});
+
+                    if let Err(err) = btc_public {
+                        deposit_rep.send(Err(err)).await?;
+                    } else {
+                        if let Some(btc_addr) = btc_public? {
+                            deposit_rep.send(Ok(btc_addr)).await?;
+                        }else {
+                            deposit_rep.send(Err(ClientFailed::UnableToGetDepositAddress)).await?;
+                        }
+                    }
                 }
                 withdraw_addr = withdraw_req.recv().fuse() => {
-                    let drk_public = cashier_client.withdraw(withdraw_addr?).await?;
-                    withdraw_rep.send(drk_public).await?;
+                    let drk_public = cashier_client.withdraw(withdraw_addr?).await.map_err(|err| {ClientFailed::from(err)});
+
+                    if let Err(err) = drk_public {
+                        withdraw_rep.send(Err(err)).await?;
+                    } else {
+                        if let Some(drk_addr) = drk_public? {
+                            withdraw_rep.send(Ok(drk_addr)).await?;
+                        }else {
+                            withdraw_rep.send(Err(ClientFailed::UnableToGetDepositAddress)).await?;
+                        }
+                    }
                 }
                 transfer_params = transfer_req.recv().fuse() => {
 
-                    let result: ClientResult<()> = {
+                    let result = self.transfer(
+                        transfer_params?,
+                        wallet.clone()
+                    ).await;
 
-                        let transfer_params = transfer_params?;
+                    if let Err(err) = result {
+                        transfer_rep.send(Err(err)).await?;
+                    } else {
+                        transfer_rep.send(Ok(())).await?;
+                    }
 
-                        let address = bs58::decode(transfer_params.pub_key).into_vec()?;
-                        let address: jubjub::SubgroupPoint = deserialize(&address)?;
-
-
-                        let slab_tx = self.prepare_transaction(
-                            address,
-                            transfer_params.amount,
-                            wallet.clone()
-                        )?;
-
-
-                        self.gateway.put_slab(slab_tx).await?;
+                }
 
-                        Ok(())
+            }
+        }
+    }
 
-                    };
+    pub async fn transfer(
+        &mut self,
+        transfer_params: TransferParams,
+        wallet: WalletPtr,
+    ) -> ClientResult<()> {
+        let pub_key = transfer_params.pub_key;
 
+        let address = bs58::decode(pub_key.clone())
+            .into_vec()
+            .map_err(|_| ClientFailed::UnvalidAddress(pub_key.clone()))?;
 
-                    transfer_rep.send(result).await?;
+        let address: jubjub::SubgroupPoint =
+            deserialize(&address).map_err(|_| ClientFailed::UnvalidAddress(pub_key))?;
 
-                }
+        let amount = transfer_params.amount;
 
-            }
+        if amount <= 0.0 {
+            return Err(ClientFailed::UnvalidAmount(amount as u64));
         }
-    }
 
-    pub fn prepare_transaction(
-        &self,
-        address: jubjub::SubgroupPoint,
-        amount: f64,
-        wallet: WalletPtr,
-    ) -> super::ClientResult<Slab> {
         // check if there are coins
         let own_coins = wallet.get_own_coins()?;
 
         if own_coins.is_empty() {
-            return Err(super::ClientFailed::NotEnoughValue(0));
+            return Err(ClientFailed::NotEnoughValue(0));
         }
 
         let witness = &own_coins[0].3;
@@ -283,7 +302,10 @@ impl Client {
 
         // build slab from the transaction
         let slab = Slab::new(tx_data);
-        return Ok(slab);
+
+        self.gateway.put_slab(slab).await?;
+
+        Ok(())
     }
 }
 

+ 19 - 7
src/client/mod.rs

@@ -4,25 +4,39 @@ pub use client::{Client, State};
 
 use std::fmt;
 
-
 #[derive(Debug)]
 pub enum ClientFailed {
     NotEnoughValue(u64),
-    BadAddress(String),
+    UnvalidAddress(String),
+    UnvalidAmount(u64),
+    UnableToGetDepositAddress,
+    UnableToGetWithdrawAddress,
+    EmptyPassword,
     ClientError(String),
 }
 
 impl std::error::Error for ClientFailed {}
 
-
 impl fmt::Display for ClientFailed {
     fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
         match self {
             ClientFailed::NotEnoughValue(i) => {
                 write!(f, "There is no enough value {}", i)
             }
-            ClientFailed::BadAddress(i) => {
-                write!(f, "Bad Address {}", i)
+            ClientFailed::UnvalidAddress(i) => {
+                write!(f, "Unvalid Address {}", i)
+            }            
+            ClientFailed::UnvalidAmount(i) => {
+                write!(f, "Unvalid Amount {}", i)
+            }
+            ClientFailed::UnableToGetDepositAddress => {
+                f.write_str("Unable to get deposit address")
+            }
+            ClientFailed::UnableToGetWithdrawAddress => {
+                f.write_str("Unable to get withdraw address")
+            }
+            ClientFailed::EmptyPassword => {
+                f.write_str("Password is empty. Cannot create database")
             }
             ClientFailed::ClientError(i) => {
                 write!(f, "ClientError: {}", i)
@@ -38,5 +52,3 @@ impl From<super::error::Error> for ClientFailed {
 }
 
 pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
-
-

+ 0 - 3
src/error.rs

@@ -49,7 +49,6 @@ pub enum Error {
     TreeFull,
     SerdeJsonError(String),
     SurfHttpError(String),
-    EmptyPassword,
     TomlDeserializeError(String),
     TomlSerializeError(String),
     CashierNoReply,
@@ -83,7 +82,6 @@ impl fmt::Display for Error {
             Error::Groth16Error => f.write_str("Groth16 error"),
             Error::RusqliteError(ref err) => write!(f, "Rusqlite error {}", err),
             Error::OperationFailed => f.write_str("Operation failed"),
-
             Error::ConnectFailed => f.write_str("Connection failed"),
             Error::ConnectTimeout => f.write_str("Connection timed out"),
             Error::ChannelStopped => f.write_str("Channel stopped"),
@@ -103,7 +101,6 @@ impl fmt::Display for Error {
             Error::TreeFull => f.write_str("MerkleTree is full"),
             Error::SerdeJsonError(ref err) => write!(f, "Json serialization error: {}", err),
             Error::SurfHttpError(ref err) => write!(f, "Surf Http error: {}", err),
-            Error::EmptyPassword => f.write_str("Password is empty. Cannot create database"),
             Error::TomlDeserializeError(ref err) => write!(f, "Toml parsing error: {}", err),
             Error::TomlSerializeError(ref err) => write!(f, "Toml parsing error: {}", err),
             Error::Base58EncodeError(ref err) => write!(f, "bs58 encode error: {}", err),

+ 20 - 12
src/rpc/adapters/user_adapter.rs

@@ -1,10 +1,9 @@
 use crate::cli::{TransferParams, WithdrawParams};
+use crate::client::ClientResult;
 use crate::serial::serialize;
 use crate::service::btc::PubAddress;
 use crate::wallet::WalletDb;
 use crate::{Error, Result};
-use crate::client::ClientResult;
-
 
 use log::*;
 
@@ -20,12 +19,12 @@ pub type TransferChannel = (
 
 pub type DepositChannel = (
     async_channel::Sender<jubjub::SubgroupPoint>,
-    async_channel::Receiver<Option<bitcoin::util::address::Address>>,
+    async_channel::Receiver<ClientResult<bitcoin::util::address::Address>>,
 );
 
 pub type WithdrawChannel = (
     async_channel::Sender<String>,
-    async_channel::Receiver<Option<jubjub::SubgroupPoint>>,
+    async_channel::Receiver<ClientResult<jubjub::SubgroupPoint>>,
 );
 
 pub struct UserAdapter {
@@ -193,16 +192,21 @@ impl UserAdapter {
         self.wallet.put_keypair(public, private)?;
         let dkey = self.wallet.get_public()?;
         self.deposit_channel.0.send(dkey).await?;
-        match self.deposit_channel.1.recv().await? {
-            Some(key) => Ok(key),
-            None => Err(Error::CashierNoReply),
-        }
+        self.deposit_channel
+            .1
+            .recv()
+            .await?
+            .map_err(|err| Error::from(err))
     }
 
     async fn transfer(&self, transfer_params: TransferParams) -> Result<()> {
         self.transfer_channel.0.send(transfer_params).await?;
-        self.transfer_channel.1.recv().await??;
-        Ok(())
+
+        self.transfer_channel
+            .1
+            .recv()
+            .await?
+            .map_err(|err| Error::from(err))
     }
 
     async fn withdraw(&self, withdraw_params: WithdrawParams) -> Result<()> {
@@ -213,12 +217,16 @@ impl UserAdapter {
             .send(withdraw_params.pub_key)
             .await?;
         // send the drk
-        if let Some(key) = self.withdraw_channel.1.recv().await? {
+        if let Ok(key) = self.withdraw_channel.1.recv().await? {
             let mut transfer_params = TransferParams::new();
             transfer_params.pub_key = key.to_string();
             transfer_params.amount = withdraw_params.amount;
             self.transfer_channel.0.send(transfer_params).await?;
-            self.transfer_channel.1.recv().await??;
+            self.transfer_channel
+                .1
+                .recv()
+                .await?
+                .map_err(|err| Error::from(err))?;
         }
         Ok(())
     }

+ 2 - 2
src/service/cashier.rs

@@ -268,7 +268,7 @@ impl CashierClient {
 
         if let Some(key) = rep {
             let address = deserialize(&key)?;
-            return Ok(Some(address));
+            return Ok(address);
         }
         Ok(None)
     }
@@ -288,7 +288,7 @@ impl CashierClient {
             .await?;
 
         if let Some(key) = rep {
-            let address = BitcoinKeys::address_from_slice(&key).unwrap();
+            let address = BitcoinKeys::address_from_slice(&key)?;
             return Ok(Some(address));
         }
         Ok(None)

+ 2 - 1
src/wallet/cashierdb.rs

@@ -3,6 +3,7 @@ use crate::serial::{deserialize, serialize, Decodable, Encodable};
 use crate::service::btc::{PrivKey, PubKey};
 use crate::util::join_config_path;
 use crate::{Error, Result};
+use crate::client::ClientFailed;
 
 use async_std::sync::Arc;
 use ff::Field;
@@ -45,7 +46,7 @@ impl CashierDb {
         } else {
             println!("Password is empty. You must set a password to use the wallet.");
             println!("Current password: {}", self.password);
-            return Err(Error::EmptyPassword);
+            return Err(Error::from(ClientFailed::EmptyPassword));
         }
         Ok(())
     }

+ 2 - 1
src/wallet/walletdb.rs

@@ -4,6 +4,7 @@ use crate::crypto::{
 use crate::serial;
 use crate::serial::{deserialize, serialize, Decodable, Encodable};
 use crate::{Error, Result};
+use crate::client::ClientFailed;
 
 use async_std::sync::{Arc, Mutex};
 use ff::Field;
@@ -61,7 +62,7 @@ impl WalletDb {
         } else {
             info!("Password is empty. You must set a password to use the wallet.");
             info!("Current password: {}", self.password);
-            return Err(Error::EmptyPassword);
+            return Err(Error::from(ClientFailed::EmptyPassword));
         }
         Ok(())
     }