Kaynağa Gözat

create specific error type for client

ghassmo 5 yıl önce
ebeveyn
işleme
4a1ecdcbfc
4 değiştirilmiş dosya ile 105 ekleme ve 28 silme
  1. 36 20
      src/client/client.rs
  2. 39 0
      src/client/mod.rs
  3. 9 0
      src/error.rs
  4. 21 8
      src/rpc/adapters/user_adapter.rs

+ 36 - 20
src/client/client.rs

@@ -17,6 +17,8 @@ use crate::state::{state_transition, ProgramState, StateUpdate};
 use crate::wallet::WalletPtr;
 use crate::{tx, Result};
 
+use super::ClientResult;
+
 use async_executor::Executor;
 use bellman::groth16;
 use bls12_381::Bls12;
@@ -135,7 +137,8 @@ impl Client {
             self.gateway.start_subscriber(executor.clone()).await?;
 
         // channels to request transfer from adapter
-        let (publish_tx_send, publish_tx_recv) = async_channel::unbounded::<TransferParams>();
+        let (transfer_req_send, transfer_req_recv) = async_channel::unbounded::<TransferParams>();
+        let (transfer_rep_send, transfer_rep_recv) = async_channel::unbounded::<ClientResult<()>>();
 
         // channels to request deposit from adapter, send DRK key and receive BTC key
         let (deposit_req_send, deposit_req_recv) =
@@ -153,7 +156,7 @@ impl Client {
 
         let adapter = Arc::new(UserAdapter::new(
             wallet.clone(),
-            publish_tx_send.clone(),
+            (transfer_req_send.clone(), transfer_rep_recv.clone()),
             (deposit_req_send.clone(), deposit_rep_recv.clone()),
             (withdraw_req_send.clone(), withdraw_rep_recv.clone()),
         )?);
@@ -171,7 +174,8 @@ impl Client {
             deposit_rep_send.clone(),
             withdraw_req_recv.clone(),
             withdraw_rep_send.clone(),
-            publish_tx_recv.clone(),
+            transfer_req_recv.clone(),
+            transfer_rep_send.clone(),
         )
         .await?;
 
@@ -187,7 +191,8 @@ impl Client {
         deposit_rep: async_channel::Sender<Option<bitcoin::util::address::Address>>,
         withdraw_req: async_channel::Receiver<String>,
         withdraw_rep: async_channel::Sender<Option<jubjub::SubgroupPoint>>,
-        publish_tx_recv: async_channel::Receiver<TransferParams>,
+        transfer_req: async_channel::Receiver<TransferParams>,
+        transfer_rep: async_channel::Sender<ClientResult<()>>,
     ) -> Result<()> {
         loop {
             futures::select! {
@@ -205,22 +210,32 @@ impl Client {
                     let drk_public = cashier_client.withdraw(withdraw_addr?).await?;
                     withdraw_rep.send(drk_public).await?;
                 }
-                transfer_params = publish_tx_recv.recv().fuse() => {
-                    let transfer_params = transfer_params?;
+                transfer_params = transfer_req.recv().fuse() => {
+
+                    let result: ClientResult<()> = {
+
+                        let transfer_params = transfer_params?;
+
+                        let address = bs58::decode(transfer_params.pub_key).into_vec()?;
+                        let address: jubjub::SubgroupPoint = deserialize(&address)?;
+
 
-                    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()
+                        )?;
 
 
-                    let slab_tx = self.prepare_transaction(
-                        address,
-                        transfer_params.amount,
-                        wallet.clone()
-                    )?;
+                        self.gateway.put_slab(slab_tx).await?;
+
+                        Ok(())
+
+                    };
+
+
+                    transfer_rep.send(result).await?;
 
-                    if let Some(slab) = slab_tx {
-                        self.gateway.put_slab(slab).await?;
-                    }
                 }
 
             }
@@ -232,11 +247,12 @@ impl Client {
         address: jubjub::SubgroupPoint,
         amount: f64,
         wallet: WalletPtr,
-    ) -> Result<Option<Slab>> {
+    ) -> super::ClientResult<Slab> {
         // check if there are coins
         let own_coins = wallet.get_own_coins()?;
-        if own_coins.len() < 1 {
-            return Ok(None);
+
+        if own_coins.is_empty() {
+            return Err(super::ClientFailed::NotEnoughValue(0));
         }
 
         let witness = &own_coins[0].3;
@@ -267,7 +283,7 @@ impl Client {
 
         // build slab from the transaction
         let slab = Slab::new(tx_data);
-        return Ok(Some(slab));
+        return Ok(slab);
     }
 }
 

+ 39 - 0
src/client/mod.rs

@@ -1,3 +1,42 @@
 pub mod client;
 
 pub use client::{Client, State};
+
+use std::fmt;
+
+
+#[derive(Debug)]
+pub enum ClientFailed {
+    NotEnoughValue(u64),
+    BadAddress(String),
+    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::ClientError(i) => {
+                write!(f, "ClientError: {}", i)
+            }
+        }
+    }
+}
+
+impl From<super::error::Error> for ClientFailed {
+    fn from(err: super::error::Error) -> ClientFailed {
+        ClientFailed::ClientError(err.to_string())
+    }
+}
+
+pub type ClientResult<T> = std::result::Result<T, ClientFailed>;
+
+

+ 9 - 0
src/error.rs

@@ -2,6 +2,7 @@ use jsonrpc_core::*;
 use std::fmt;
 
 use crate::state;
+use crate::client;
 use crate::vm::ZkVmError;
 
 pub type Result<T> = std::result::Result<T, Error>;
@@ -40,6 +41,7 @@ pub enum Error {
     ServicesError(&'static str),
     ZmqError(String),
     VerifyFailed,
+    ClientFailed(String),
     TryIntoError,
     TryFromError,
     JsonRpcError(String),
@@ -93,6 +95,7 @@ impl fmt::Display for Error {
             Error::ServicesError(ref err) => write!(f, "Services error: {}", err),
             Error::ZmqError(ref err) => write!(f, "ZmqError: {}", err),
             Error::VerifyFailed => f.write_str("Verify failed"),
+            Error::ClientFailed(ref err) => write!(f, "Client failed: {}", err),
             Error::TryIntoError => f.write_str("TryInto error"),
             Error::TryFromError => f.write_str("TryFrom error"),
             Error::RocksdbError(ref err) => write!(f, "Rocksdb Error: {}", err),
@@ -209,6 +212,12 @@ impl From<state::VerifyFailed> for Error {
     }
 }
 
+impl From<client::ClientFailed> for Error {
+    fn from(err: client::ClientFailed) -> Error {
+        Error::ClientFailed(err.to_string())
+    }
+}
+
 impl From<surf::Error> for Error {
     fn from(err: surf::Error) -> Error {
         Error::SurfHttpError(err.to_string())

+ 21 - 8
src/rpc/adapters/user_adapter.rs

@@ -3,17 +3,26 @@ use crate::serial::serialize;
 use crate::service::btc::PubAddress;
 use crate::wallet::WalletDb;
 use crate::{Error, Result};
-use std::string::ToString;
+use crate::client::ClientResult;
+
 
 use log::*;
 
 use async_std::sync::Arc;
+use std::string::ToString;
 
 pub type UserAdapterPtr = Arc<UserAdapter>;
+
+pub type TransferChannel = (
+    async_channel::Sender<TransferParams>,
+    async_channel::Receiver<ClientResult<()>>,
+);
+
 pub type DepositChannel = (
     async_channel::Sender<jubjub::SubgroupPoint>,
     async_channel::Receiver<Option<bitcoin::util::address::Address>>,
 );
+
 pub type WithdrawChannel = (
     async_channel::Sender<String>,
     async_channel::Receiver<Option<jubjub::SubgroupPoint>>,
@@ -21,7 +30,7 @@ pub type WithdrawChannel = (
 
 pub struct UserAdapter {
     pub wallet: Arc<WalletDb>,
-    publish_tx_send: async_channel::Sender<TransferParams>,
+    transfer_channel: TransferChannel,
     deposit_channel: DepositChannel,
     withdraw_channel: WithdrawChannel,
 }
@@ -29,14 +38,14 @@ pub struct UserAdapter {
 impl UserAdapter {
     pub fn new(
         wallet: Arc<WalletDb>,
-        publish_tx_send: async_channel::Sender<TransferParams>,
+        transfer_channel: TransferChannel,
         deposit_channel: DepositChannel,
         withdraw_channel: WithdrawChannel,
     ) -> Result<Self> {
         debug!(target: "ADAPTER", "new() [CREATING NEW WALLET]");
         Ok(Self {
             wallet,
-            publish_tx_send,
+            transfer_channel,
             deposit_channel,
             withdraw_channel,
         })
@@ -44,9 +53,11 @@ impl UserAdapter {
 
     pub fn handle_input(self: Arc<Self>) -> Result<jsonrpc_core::IoHandler> {
         let mut io = jsonrpc_core::IoHandler::new();
+
         io.add_sync_method("say_hello", |_| {
             Ok(jsonrpc_core::Value::String("hello world!".into()))
         });
+
         let self1 = self.clone();
         io.add_method("get_key", move |_| {
             let self2 = self1.clone();
@@ -188,12 +199,13 @@ impl UserAdapter {
         }
     }
 
-    pub async fn transfer(&self, transfer_params: TransferParams) -> Result<()> {
-        self.publish_tx_send.send(transfer_params).await?;
+    async fn transfer(&self, transfer_params: TransferParams) -> Result<()> {
+        self.transfer_channel.0.send(transfer_params).await?;
+        self.transfer_channel.1.recv().await??;
         Ok(())
     }
 
-    pub async fn withdraw(&self, withdraw_params: WithdrawParams) -> Result<()> {
+    async fn withdraw(&self, withdraw_params: WithdrawParams) -> Result<()> {
         debug!(target: "withdraw", "withdraw: START");
         // do the key exchange
         self.withdraw_channel
@@ -205,7 +217,8 @@ impl UserAdapter {
             let mut transfer_params = TransferParams::new();
             transfer_params.pub_key = key.to_string();
             transfer_params.amount = withdraw_params.amount;
-            self.publish_tx_send.send(transfer_params).await?;
+            self.transfer_channel.0.send(transfer_params).await?;
+            self.transfer_channel.1.recv().await??;
         }
         Ok(())
     }