Browse Source

no need to use Mutex for Client inside cashierd and darkfid & clean up

ghassmo 4 years ago
parent
commit
f112a8abd2
8 changed files with 174 additions and 210 deletions
  1. 61 54
      src/bin/cashierd.rs
  2. 27 58
      src/bin/darkfid.rs
  3. 74 81
      src/client/client.rs
  4. 4 4
      src/client/mod.rs
  5. 1 2
      src/rpc/rpcserver.rs
  6. 1 1
      src/state.rs
  7. 4 5
      src/util/parse.rs
  8. 2 5
      src/wallet/walletdb.rs

+ 61 - 54
src/bin/cashierd.rs

@@ -1,5 +1,5 @@
 use async_executor::Executor;
-use async_std::sync::{Arc, Mutex};
+use async_std::sync::Arc;
 use async_trait::async_trait;
 use clap::clap_app;
 use ff::Field;
@@ -33,13 +33,11 @@ fn handle_bridge_error(error_code: u32) -> Result<()> {
     }
 }
 
-#[derive(Clone)]
 struct Cashierd {
     config: CashierdConfig,
     bridge: Arc<Bridge>,
     cashier_wallet: Arc<CashierDb>,
     features: HashMap<NetworkName, String>,
-    client: Arc<Mutex<Client>>,
 }
 
 #[async_trait]
@@ -72,29 +70,6 @@ impl Cashierd {
             config.cashier_wallet_password.clone(),
         )?;
 
-        let client_wallet = WalletDb::new(
-            expand_path(&config.client_wallet_path.clone())?.as_path(),
-            config.client_wallet_password.clone(),
-        )?;
-
-        let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
-
-        let client = Client::new(
-            rocks,
-            (
-                config.gateway_protocol_url.parse()?,
-                config.gateway_publisher_url.parse()?,
-            ),
-            (
-                expand_path(&config.mint_params_path.clone())?,
-                expand_path(&config.spend_params_path.clone())?,
-            ),
-            client_wallet.clone(),
-        )
-        .await?;
-
-        let client = Arc::new(Mutex::new(client));
-
         let mut features = HashMap::new();
 
         for network in config.clone().networks {
@@ -108,7 +83,6 @@ impl Cashierd {
             bridge,
             cashier_wallet,
             features,
-            client: client.clone(),
         })
     }
 
@@ -379,7 +353,15 @@ impl Cashierd {
         }
     }
 
-    async fn start(&self, executor: Arc<Executor<'static>>) -> Result<()> {
+    async fn start(
+        &mut self,
+        mut client: Client,
+        executor: Arc<Executor<'static>>,
+    ) -> Result<(
+        smol::Task<Result<()>>,
+        smol::Task<Result<()>>,
+        smol::Task<Result<()>>,
+    )> {
         self.cashier_wallet.init_db().await?;
 
         for (feature_name, chain) in self.features.iter() {
@@ -446,16 +428,17 @@ impl Cashierd {
             self.features.clone(),
         ));
 
-        self.client.lock().await.start().await?;
+        client.start().await?;
 
         let (notify, recv_coin) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
-        let cashier_client_subscriber_task =
-            smol::spawn(Client::connect_to_subscriber_from_cashier(
-                self.client.clone(),
-                executor.clone(),
+
+        client
+            .connect_to_subscriber_from_cashier(
                 self.cashier_wallet.clone(),
                 notify.clone(),
-            ));
+                executor.clone(),
+            )
+            .await?;
 
         let cashier_wallet = self.cashier_wallet.clone();
         let bridge = self.bridge.clone();
@@ -471,7 +454,6 @@ impl Cashierd {
         });
 
         let bridge2 = self.bridge.clone();
-        let client2 = self.client.clone();
         let listen_for_notification_from_bridge_task: smol::Task<Result<()>> = smol::spawn(
             async move {
                 loop {
@@ -480,9 +462,7 @@ impl Cashierd {
 
                         debug!(target: "CASHIER DAEMON", "Notification from birdge: {:?}", token_notification);
 
-                        client2
-                            .lock()
-                            .await
+                        client
                             .send(
                                 token_notification.drk_pub_key,
                                 token_notification.received_balance,
@@ -495,20 +475,11 @@ impl Cashierd {
             },
         );
 
-        let cfg = RpcServerConfig {
-            socket_addr: self.config.rpc_listen_address.clone(),
-            use_tls: self.config.serve_tls,
-            identity_path: expand_path(&self.config.clone().tls_identity_path)?,
-            identity_pass: self.config.tls_identity_password.clone(),
-        };
-
-        listen_and_serve(cfg, self.clone()).await?;
-
-        resume_watch_deposit_keys_task.cancel().await;
-        listen_for_receiving_coins_task.cancel().await;
-        listen_for_notification_from_bridge_task.cancel().await;
-        cashier_client_subscriber_task.cancel().await;
-        Ok(())
+        Ok((
+            resume_watch_deposit_keys_task,
+            listen_for_receiving_coins_task,
+            listen_for_notification_from_bridge_task,
+        ))
     }
 }
 
@@ -534,6 +505,42 @@ async fn main() -> Result<()> {
 
     simple_logger::init_with_level(loglevel)?;
     let ex = Arc::new(Executor::new());
-    let cashierd = Cashierd::new(config_path).await?;
-    cashierd.start(ex.clone()).await
+    let mut cashierd = Cashierd::new(config_path).await?;
+
+    let client_wallet = WalletDb::new(
+        expand_path(&cashierd.config.client_wallet_path.clone())?.as_path(),
+        cashierd.config.client_wallet_password.clone(),
+    )?;
+
+    let rocks = Rocks::new(expand_path(&cashierd.config.database_path.clone())?.as_path())?;
+
+    let client = Client::new(
+        rocks,
+        (
+            cashierd.config.gateway_protocol_url.parse()?,
+            cashierd.config.gateway_publisher_url.parse()?,
+        ),
+        (
+            expand_path(&cashierd.config.mint_params_path.clone())?,
+            expand_path(&cashierd.config.spend_params_path.clone())?,
+        ),
+        client_wallet.clone(),
+    )
+    .await?;
+
+    let cfg = RpcServerConfig {
+        socket_addr: cashierd.config.rpc_listen_address.clone(),
+        use_tls: cashierd.config.serve_tls,
+        identity_path: expand_path(&cashierd.config.clone().tls_identity_path)?,
+        identity_pass: cashierd.config.tls_identity_password.clone(),
+    };
+
+    let (t1, t2, t3) = cashierd.start(client, ex.clone()).await?;
+    listen_and_serve(cfg, Arc::new(cashierd)).await?;
+
+    t1.cancel().await;
+    t2.cancel().await;
+    t3.cancel().await;
+    
+    Ok(())
 }

+ 27 - 58
src/bin/darkfid.rs

@@ -1,9 +1,10 @@
+use async_executor::Executor;
 use async_trait::async_trait;
 use clap::clap_app;
 use log::debug;
 use serde_json::{json, Value};
 
-use async_std::sync::{Arc, Mutex};
+use async_std::sync::Arc;
 use std::path::PathBuf;
 //use std::sync::Arc;
 
@@ -16,23 +17,20 @@ use drk::{
         jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
         rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
     },
-    serial::{deserialize, serialize},
+    serial::serialize,
     util::{assign_id, decimals, decode_base10, expand_path, join_config_path, TokenList},
     wallet::WalletDb,
     Result,
 };
 
-#[derive(Clone)]
 struct Darkfid {
     config: DarkfidConfig,
-    wallet: Arc<WalletDb>,
-    client: Arc<Mutex<Client>>,
+    client: Client,
     tokenlist: TokenList,
 }
 
 #[async_trait]
 impl RequestHandler for Darkfid {
-    // TODO: ServerError codes should be part of the lib.
     async fn handle_request(&self, req: JsonRequest) -> JsonResult {
         if req.params.as_array().is_none() {
             return JsonResult::Err(jsonerr(InvalidParams, None, req.id));
@@ -80,18 +78,22 @@ impl Darkfid {
         )
         .await?;
 
-        let client = Arc::new(Mutex::new(client));
-
         let tokenlist = TokenList::new()?;
 
         Ok(Self {
             config,
-            wallet,
             client,
             tokenlist,
         })
     }
 
+    async fn start(&mut self, executor: Arc<Executor<'static>>) -> Result<()> {
+        self.client.start().await?;
+        self.client.connect_to_subscriber(executor).await?;
+
+        Ok(())
+    }
+
     // --> {"method": "say_hello", "params": []}
     // <-- {"result": "hello world"}
     async fn say_hello(&self, id: Value, _params: Value) -> JsonResult {
@@ -101,7 +103,7 @@ impl Darkfid {
     // --> {"method": "create_wallet", "params": []}
     // <-- {"result": true}
     async fn create_wallet(&self, id: Value, _params: Value) -> JsonResult {
-        match self.wallet.init_db().await {
+        match self.client.init_db().await {
             Ok(()) => return JsonResult::Resp(jsonresp(json!(true), id)),
             Err(e) => {
                 return JsonResult::Err(jsonerr(ServerError(-32001), Some(e.to_string()), id))
@@ -112,7 +114,7 @@ impl Darkfid {
     // --> {"method": "key_gen", "params": []}
     // <-- {"result": true}
     async fn key_gen(&self, id: Value, _params: Value) -> JsonResult {
-        match self.wallet.key_gen() {
+        match self.client.key_gen().await {
             Ok(()) => return JsonResult::Resp(jsonresp(json!(true), id)),
             Err(e) => {
                 return JsonResult::Err(jsonerr(ServerError(-32002), Some(e.to_string()), id))
@@ -123,16 +125,9 @@ impl Darkfid {
     // --> {"method": "get_key", "params": []}
     // <-- {"result": "vdNS7oBj7KvsMWWmo9r96SV4SqATLrGsH2a3PGpCfJC"}
     async fn get_key(&self, id: Value, _params: Value) -> JsonResult {
-        match self.wallet.get_keypairs() {
-            Ok(v) => {
-                let pk = v[0].public;
-                let b58 = bs58::encode(serialize(&pk)).into_string();
-                return JsonResult::Resp(jsonresp(json!(b58), id));
-            }
-            Err(e) => {
-                return JsonResult::Err(jsonerr(ServerError(-32003), Some(e.to_string()), id))
-            }
-        }
+        let pk = self.client.main_keypair.public;
+        let b58 = bs58::encode(serialize(&pk)).into_string();
+        return JsonResult::Resp(jsonresp(json!(b58), id));
     }
 
     // --> {"method": "get_token_id", "params": [token]}
@@ -227,17 +222,8 @@ impl Darkfid {
 
         // TODO: Optional sanity checking here, but cashier *must* do so too.
 
-        let pubkey: String;
-        match self.wallet.get_keypairs() {
-            Ok(v) => {
-                let pk = v[0].public;
-                let pk = serialize(&pk);
-                pubkey = bs58::encode(pk).into_string();
-            }
-            Err(e) => {
-                return JsonResult::Err(jsonerr(ServerError(-32003), Some(e.to_string()), id))
-            }
-        }
+        let pk = self.client.main_keypair.public;
+        let pubkey = bs58::encode(serialize(&pk)).into_string();
 
         // Send request to cashier. If the cashier supports the requested network
         // (and token), it shall return a valid address where assets can be deposited.
@@ -296,7 +282,7 @@ impl Darkfid {
 
         let network = network.as_str().unwrap();
 
-        if amount.as_f64().is_none() {
+        if amount.as_str().is_none() {
             return JsonResult::Err(jsonerr(InvalidParams, None, id));
         }
 
@@ -359,19 +345,19 @@ impl Darkfid {
             return JsonResult::Err(jsonerr(InvalidParams, None, id));
         }
 
-        let token = address.as_str().unwrap();
+        let _token = address.as_str().unwrap();
 
         if address.as_str().is_none() {
             return JsonResult::Err(jsonerr(InvalidParams, None, id));
         }
 
-        let address = address.as_str().unwrap();
+        let _address = address.as_str().unwrap();
 
         if amount.as_f64().is_none() {
             return JsonResult::Err(jsonerr(InvalidParams, None, id));
         }
 
-        let amount = amount.as_f64().unwrap();
+        let _amount = amount.as_f64().unwrap();
 
         // TODO: get tokenID from walletdb
         //let result: Result<()> = async {
@@ -421,7 +407,9 @@ async fn main() -> Result<()> {
 
     simple_logger::init_with_level(loglevel)?;
 
-    let darkfid = Darkfid::new(config_path).await?;
+    let ex = Arc::new(Executor::new());
+
+    let mut darkfid = Darkfid::new(config_path).await?;
 
     let server_config = RpcServerConfig {
         socket_addr: darkfid.config.rpc_listen_address.clone(),
@@ -430,25 +418,6 @@ async fn main() -> Result<()> {
         identity_pass: darkfid.config.tls_identity_password.clone(),
     };
 
-    listen_and_serve(server_config, darkfid).await
-}
-
-mod tests {
-
-    //#[test]
-    //fn test_token_parsing() {
-    //    let token = "usdc";
-
-    //    let vec: Vec<char> = token.chars().collect();
-    //    let mut counter = 0;
-    //    for c in vec {
-    //        if c.is_alphabetic() {
-    //            counter += 1;
-    //            println!("Found letter: {}", c)
-    //        }
-    //    }
-    //    if counter == token.len() {
-    //        println!("Every character is a letter");
-    //    }
-    //}
+    darkfid.start(ex.clone()).await?;
+    listen_and_serve(server_config, Arc::new(darkfid)).await
 }

+ 74 - 81
src/client/client.rs

@@ -28,11 +28,11 @@ use std::net::SocketAddr;
 use std::path::PathBuf;
 
 pub struct Client {
-    pub state: State,
+    pub state: Arc<Mutex<State>>,
     mint_params: bellman::groth16::Parameters<Bls12>,
     spend_params: bellman::groth16::Parameters<Bls12>,
     gateway: GatewayClient,
-    pub main_keypair: Keypair
+    pub main_keypair: Keypair,
 }
 
 impl Client {
@@ -49,7 +49,6 @@ impl Client {
         let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
         let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
 
-
         wallet.init_db().await?;
 
         if wallet.get_keypairs()?.len() == 0 {
@@ -72,14 +71,14 @@ impl Client {
         let (mint_params, mint_pvk) = load_params(mint_params_path)?;
         let (spend_params, spend_pvk) = load_params(spend_params_path)?;
 
-        let state = State {
+        let state = Arc::new(Mutex::new(State {
             tree: CommitmentTree::empty(),
             merkle_roots,
             nullifiers,
             mint_pvk,
             spend_pvk,
             wallet,
-        };
+        }));
 
         // create gateway client
         debug!(target: "CLIENT", "Creating GatewayClient");
@@ -99,15 +98,6 @@ impl Client {
         Ok(())
     }
 
-    pub async fn connect_to_cashier(client: Client, executor: Arc<Executor<'_>>) -> Result<()> {
-        let client_mutex = Arc::new(Mutex::new(client));
-
-        // start subscriber
-        Client::connect_to_subscriber(client_mutex.clone(), executor.clone()).await?;
-
-        Ok(())
-    }
-
     pub async fn transfer(
         &mut self,
         asset_id: jubjub::Fr,
@@ -130,14 +120,16 @@ impl Client {
         asset_id: jubjub::Fr,
         clear_input: bool,
     ) -> Result<()> {
-        let slab = self.build_slab_from_tx(pub_key, amount, asset_id, clear_input)?;
+        let slab = self
+            .build_slab_from_tx(pub_key, amount, asset_id, clear_input)
+            .await?;
 
         self.gateway.put_slab(slab).await?;
 
         Ok(())
     }
 
-    fn build_slab_from_tx(
+    async fn build_slab_from_tx(
         &self,
         pub_key: jubjub::SubgroupPoint,
         value: u64,
@@ -157,7 +149,7 @@ impl Client {
             };
             clear_inputs.push(input);
         } else {
-            inputs = self.build_inputs(value, asset_id, &mut outputs)?;
+            inputs = self.build_inputs(value, asset_id, &mut outputs).await?;
         }
 
         outputs.push(tx::TransactionBuilderOutputInfo {
@@ -182,7 +174,7 @@ impl Client {
         Ok(slab)
     }
 
-    fn build_inputs(
+    async fn build_inputs(
         &self,
         amount: u64,
         asset_id: jubjub::Fr,
@@ -191,7 +183,7 @@ impl Client {
         let mut inputs: Vec<tx::TransactionBuilderInputInfo> = vec![];
         let mut inputs_value: u64 = 0;
 
-        let own_coins = self.state.wallet.get_own_coins()?;
+        let own_coins = self.state.lock().await.wallet.get_own_coins()?;
 
         for own_coin in own_coins.iter() {
             if inputs_value >= amount {
@@ -231,82 +223,83 @@ impl Client {
     }
 
     pub async fn connect_to_subscriber_from_cashier(
-        client: Arc<Mutex<Client>>,
-        executor: Arc<Executor<'_>>,
+        &self,
         cashier_wallet: CashierDbPtr,
         notify: async_channel::Sender<(jubjub::SubgroupPoint, u64)>,
+        executor: Arc<Executor<'_>>,
     ) -> Result<()> {
         // start subscribing
         debug!(target: "CLIENT", "Start subscriber");
-        let gateway_slabs_sub: GatewaySlabsSubscriber = client
-            .lock()
-            .await
-            .gateway
-            .start_subscriber(executor.clone())
-            .await?;
+        let gateway_slabs_sub: GatewaySlabsSubscriber =
+            self.gateway.start_subscriber(executor.clone()).await?;
 
-        loop {
-            let slab = gateway_slabs_sub.recv().await?;
-            let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
-            let mut client = client.lock().await;
-            let update = state_transition(&client.state, tx)?;
-            let mut secret_keys: Vec<jubjub::Fr> = client
-                .state
-                .wallet
-                .get_keypairs()?
-                .iter()
-                .map(|k| k.private)
-                .collect();
-            let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys()?;
-            secret_keys.append(&mut withdraw_keys);
-            client
-                .state
-                .apply(update, secret_keys.clone(), notify.clone())
-                .await?;
-        }
+        let secret_key = self.main_keypair.private;
+        let state = self.state.clone();
+
+        let task: smol::Task<Result<()>> = smol::spawn(async move {
+            loop {
+                let slab = gateway_slabs_sub.recv().await?;
+                let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
+
+                let mut state = state.lock().await;
+
+                let update = state_transition(&state, tx)?;
+
+                let mut secret_keys: Vec<jubjub::Fr> = vec![secret_key];
+                let mut withdraw_keys = cashier_wallet.get_withdraw_private_keys()?;
+                secret_keys.append(&mut withdraw_keys);
+
+                state
+                    .apply(update, secret_keys.clone(), notify.clone())
+                    .await?;
+            }
+        });
+
+        task.detach();
+
+        Ok(())
     }
 
-    pub async fn connect_to_subscriber(
-        client: Arc<Mutex<Client>>,
-        executor: Arc<Executor<'_>>,
-    ) -> Result<()> {
+    pub async fn connect_to_subscriber(&self, executor: Arc<Executor<'_>>) -> Result<()> {
         // start subscribing
         debug!(target: "CLIENT", "Start subscriber");
-        let gateway_slabs_sub: GatewaySlabsSubscriber = client
-            .lock()
-            .await
-            .gateway
-            .start_subscriber(executor.clone())
-            .await?;
+        let gateway_slabs_sub: GatewaySlabsSubscriber =
+            self.gateway.start_subscriber(executor.clone()).await?;
 
-        let (notify, recv_queue) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
+        let (notify, _) = async_channel::unbounded::<(jubjub::SubgroupPoint, u64)>();
 
-        executor.spawn(async move {
+
+        let secret_key = self.main_keypair.private;
+        let state = self.state.clone();
+
+        let task: smol::Task<Result<()>> = smol::spawn(async move {
             loop {
-                let (pub_key, amount) = recv_queue.recv().await.expect("Receive Own Coin");
-                debug!(target: "CLIENT", "Receive coin with following address and amount: {}, {}", pub_key, amount);
+                let slab = gateway_slabs_sub.recv().await?;
+                let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
+
+                let mut state = state.lock().await;
+
+                let update = state_transition(&state, tx)?;
+
+                let secret_keys: Vec<jubjub::Fr> = vec![secret_key];
+
+                state
+                    .apply(update, secret_keys.clone(), notify.clone())
+                    .await?;
             }
-        }).detach();
-
-        loop {
-            let slab = gateway_slabs_sub.recv().await?;
-            let tx = tx::Transaction::decode(&slab.get_payload()[..])?;
-            let mut client = client.lock().await;
-            let update = state_transition(&client.state, tx)?;
-
-            let secret_keys: Vec<jubjub::Fr> = client
-                .state
-                .wallet
-                .get_keypairs()?
-                .iter()
-                .map(|k| k.private)
-                .collect();
-
-            client
-                .state
-                .apply(update, secret_keys.clone(), notify.clone())
-                .await?;
-        }
+        });
+
+        task.detach();
+
+        Ok(())
+    }
+
+    pub async fn init_db(&self) -> Result<()> {
+        self.state.lock().await.wallet.init_db().await
+    }
+
+    pub async fn key_gen(&self) -> Result<()> {
+        self.state.lock().await.wallet.key_gen()
     }
 }
 

+ 4 - 4
src/client/mod.rs

@@ -11,8 +11,8 @@ pub enum ClientFailed {
     InvalidAmount(u64),
     UnableToGetDepositAddress,
     UnableToGetWithdrawAddress,
-    DoNotHaveCashierPublicKey,
-    DoNotHaveKeypair,
+    DoesNotHaveCashierPublicKey,
+    DoesNotHaveKeypair,
     EmptyPassword,
     WalletInitialized,
     KeyExists,
@@ -37,8 +37,8 @@ impl fmt::Display for ClientFailed {
             ClientFailed::UnableToGetWithdrawAddress => {
                 f.write_str("Unable to get withdraw address")
             }
-            ClientFailed::DoNotHaveCashierPublicKey => f.write_str("Don't have cashier public key"),
-            ClientFailed::DoNotHaveKeypair => f.write_str("Don't have keypair"),
+            ClientFailed::DoesNotHaveCashierPublicKey => f.write_str("Does not have cashier public key"),
+            ClientFailed::DoesNotHaveKeypair => f.write_str("Does not have keypair"),
             ClientFailed::EmptyPassword => f.write_str("Password is empty. Cannot create database"),
             ClientFailed::WalletInitialized => f.write_str("Wallet already initalized"),
             ClientFailed::KeyExists => f.write_str("Keypair already exists"),

+ 1 - 2
src/rpc/rpcserver.rs

@@ -139,7 +139,7 @@ async fn listen(
 
 pub async fn listen_and_serve(
     cfg: RpcServerConfig,
-    rh: impl RequestHandler + 'static,
+    rh: Arc<impl RequestHandler + 'static>,
 ) -> Result<()> {
     let tls: Option<TlsAcceptor>;
 
@@ -151,7 +151,6 @@ pub async fn listen_and_serve(
         tls = None;
     }
 
-    let rh = Arc::new(rh);
     let listener = listen(Async::<TcpListener>::bind(cfg.socket_addr)?, tls, rh);
     listener.await
 }

+ 1 - 1
src/state.rs

@@ -68,7 +68,7 @@ impl fmt::Display for VerifyFailed {
 }
 
 pub fn state_transition<S: ProgramState>(
-    state: &S,
+    state: &async_std::sync::MutexGuard<S>,
     tx: tx::Transaction,
 ) -> VerifyResult<StateUpdate> {
     // Check deposits are legit

+ 4 - 5
src/util/parse.rs

@@ -12,13 +12,12 @@ use crate::{
 // hash the external token ID and NetworkName param.
 // if fails, change the last 4 bytes and hash it again. keep repeating until it works.
 pub fn generate_id(tkn_str: &str, network: &NetworkName) -> Result<jubjub::Fr> {
+
     let mut id_string = network.to_string();
+
     id_string.push_str(tkn_str);
-    if bs58::decode(id_string.clone()).into_vec().is_err() {
-        // TODO: make this an error
-        debug!(target: "PARSE ID", "COULD NOT DECODE STR");
-    }
-    let mut data = bs58::decode(id_string).into_vec().unwrap();
+
+    let mut data = bs58::decode(serialize(&id_string)).into_vec()?;
 
     let token_id = match deserialize::<jubjub::Fr>(&data) {
         Ok(v) => v,

+ 2 - 5
src/wallet/walletdb.rs

@@ -99,6 +99,7 @@ impl WalletDb {
         )?;
         Ok(())
     }
+
     pub fn get_keypairs(&self) -> Result<Vec<Keypair>> {
         debug!(target: "WALLETDB", "Returning keys...");
         let conn = Connection::open(&self.path)?;
@@ -117,10 +118,6 @@ impl WalletDb {
             keypairs.push(Keypair { public, private });
         }
 
-        if keypairs.is_empty() {
-            return Err(Error::from(ClientFailed::DoNotHaveKeypair));
-        }
-
         Ok(keypairs)
     }
 
@@ -291,7 +288,7 @@ impl WalletDb {
         }
 
         if pub_keys.is_empty() {
-            return Err(Error::from(ClientFailed::DoNotHaveCashierPublicKey));
+            return Err(Error::from(ClientFailed::DoesNotHaveCashierPublicKey));
         }
 
         Ok(pub_keys)