Browse Source

bridge: pass mint_address when subscribe

ghassmo 4 years ago
parent
commit
ff8c900ec2
5 changed files with 90 additions and 60 deletions
  1. 40 37
      src/bin/cashierd.rs
  2. 2 2
      src/bin/sol-test.rs
  3. 15 5
      src/service/bridge.rs
  4. 2 1
      src/service/btc.rs
  5. 31 15
      src/service/sol.rs

+ 40 - 37
src/bin/cashierd.rs

@@ -90,7 +90,8 @@ impl Cashierd {
                 expand_path(&config.spend_params_path.clone())?,
                 expand_path(&config.spend_params_path.clone())?,
             ),
             ),
             client_wallet.clone(),
             client_wallet.clone(),
-        ).await?;
+        )
+        .await?;
 
 
         let client = Arc::new(Mutex::new(client));
         let client = Arc::new(Mutex::new(client));
 
 
@@ -119,14 +120,19 @@ impl Cashierd {
         for (network, _) in features.iter() {
         for (network, _) in features.iter() {
             let keypairs_to_watch = cashier_wallet.get_deposit_token_keys_by_network(&network)?;
             let keypairs_to_watch = cashier_wallet.get_deposit_token_keys_by_network(&network)?;
 
 
-            for keypair in keypairs_to_watch {
+            for (private_key, public_key, _token_id, mint_address) in keypairs_to_watch {
                 let bridge = bridge.clone();
                 let bridge = bridge.clone();
-                let bridge_subscribtion = bridge.subscribe().await;
+
+                let bridge_subscribtion = bridge.subscribe(Some(mint_address)).await;
+
                 bridge_subscribtion
                 bridge_subscribtion
                     .sender
                     .sender
                     .send(bridge::BridgeRequests {
                     .send(bridge::BridgeRequests {
                         network: network.clone(),
                         network: network.clone(),
-                        payload: bridge::BridgeRequestsPayload::Watch(Some((keypair.0, keypair.1))),
+                        payload: bridge::BridgeRequestsPayload::Watch(Some((
+                            private_key,
+                            public_key,
+                        ))),
                     })
                     })
                     .await?;
                     .await?;
             }
             }
@@ -139,20 +145,21 @@ impl Cashierd {
         cashier_wallet: Arc<CashierDb>,
         cashier_wallet: Arc<CashierDb>,
         recv_coin: async_channel::Receiver<(jubjub::SubgroupPoint, u64)>,
         recv_coin: async_channel::Receiver<(jubjub::SubgroupPoint, u64)>,
     ) -> Result<()> {
     ) -> Result<()> {
-        let bridge_subscribtion = bridge.subscribe().await;
-
         // received drk coin
         // received drk coin
         let (drk_pub_key, amount) = recv_coin.recv().await?;
         let (drk_pub_key, amount) = recv_coin.recv().await?;
 
 
         debug!(target: "CASHIER DAEMON", "Receive coin with following address and amount: {}, {}"
         debug!(target: "CASHIER DAEMON", "Receive coin with following address and amount: {}, {}"
             , drk_pub_key, amount);
             , drk_pub_key, amount);
 
 
-        // get public key, and asset_id of the token
+        // get public key, and token_id of the token
         let token = cashier_wallet.get_withdraw_token_public_key_by_dkey_public(&drk_pub_key)?;
         let token = cashier_wallet.get_withdraw_token_public_key_by_dkey_public(&drk_pub_key)?;
 
 
         // send a request to bridge to send equivalent amount of
         // send a request to bridge to send equivalent amount of
         // received drk coin to token publickey
         // received drk coin to token publickey
-        if let Some((addr, network, _asset_id)) = token {
+        if let Some((addr, network, _token_id, mint_address)) = token {
+
+            let bridge_subscribtion = bridge.subscribe(Some(mint_address)).await;
+
             bridge_subscribtion
             bridge_subscribtion
                 .sender
                 .sender
                 .send(bridge::BridgeRequests {
                 .send(bridge::BridgeRequests {
@@ -191,7 +198,7 @@ impl Cashierd {
         }
         }
 
 
         let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
         let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
-        let token_id = &args[1].as_str().unwrap();
+        let mut mint_address: String = args[1].as_str().unwrap().to_string();
         let drk_pub_key = &args[2].as_str().unwrap();
         let drk_pub_key = &args[2].as_str().unwrap();
 
 
         if !self.features.contains_key(&network.clone()) {
         if !self.features.contains_key(&network.clone()) {
@@ -203,9 +210,13 @@ impl Cashierd {
         }
         }
 
 
         let result: Result<String> = async {
         let result: Result<String> = async {
-            Self::check_token_id(&network, token_id)?;
+            let token_id = generate_id(&mint_address)?;
 
 
-            let asset_id = generate_id(token_id)?;
+            let mint_address_opt = Self::check_token_id(&network, &mint_address)?;
+
+            if mint_address_opt.is_none() {
+                mint_address = String::new();
+            }
 
 
             let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
             let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
             let drk_pub_key: jubjub::SubgroupPoint = deserialize(&drk_pub_key)?;
             let drk_pub_key: jubjub::SubgroupPoint = deserialize(&drk_pub_key)?;
@@ -216,7 +227,7 @@ impl Cashierd {
                 .get_deposit_token_keys_by_dkey_public(&drk_pub_key, &network)?;
                 .get_deposit_token_keys_by_dkey_public(&drk_pub_key, &network)?;
 
 
             let bridge = self.bridge.clone();
             let bridge = self.bridge.clone();
-            let bridge_subscribtion = bridge.subscribe().await;
+            let bridge_subscribtion = bridge.subscribe(mint_address_opt).await;
 
 
             if check.is_empty() {
             if check.is_empty() {
                 bridge_subscribtion
                 bridge_subscribtion
@@ -253,7 +264,8 @@ impl Cashierd {
                         &token_priv,
                         &token_priv,
                         &serialize(&token_pub),
                         &serialize(&token_pub),
                         &network,
                         &network,
-                        &asset_id,
+                        &token_id,
+                        &mint_address,
                     )?;
                     )?;
 
 
                     return Ok(token_pub);
                     return Ok(token_pub);
@@ -284,7 +296,7 @@ impl Cashierd {
         }
         }
 
 
         let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
         let network = NetworkName::from_str(args[0].as_str().unwrap()).unwrap();
-        let token = &args[1].as_str().unwrap();
+        let mut mint_address: String = args[1].as_str().unwrap().to_string();
         let address = &args[2].as_str().unwrap();
         let address = &args[2].as_str().unwrap();
         let _amount = &args[3];
         let _amount = &args[3];
 
 
@@ -297,9 +309,15 @@ impl Cashierd {
         }
         }
 
 
         let result: Result<String> = async {
         let result: Result<String> = async {
-            Self::check_token_id(&network, token)?;
+            let token_id = generate_id(&mint_address)?;
+
+            let mint_address_opt = Self::check_token_id(&network, &mint_address)?;
+
+            if mint_address_opt.is_none() {
+                // empty string
+                mint_address = String::new();
+            }
 
 
-            let asset_id = generate_id(&token)?;
             let address = serialize(&address.to_string());
             let address = serialize(&address.to_string());
 
 
             let cashier_public: jubjub::SubgroupPoint;
             let cashier_public: jubjub::SubgroupPoint;
@@ -319,7 +337,8 @@ impl Cashierd {
                     &cashier_public,
                     &cashier_public,
                     &cashier_secret,
                     &cashier_secret,
                     &network,
                     &network,
-                    &asset_id,
+                    &token_id,
+                    &mint_address,
                 )?;
                 )?;
             }
             }
 
 
@@ -345,37 +364,21 @@ impl Cashierd {
         ))
         ))
     }
     }
 
 
-    fn check_token_id(network: &NetworkName, token_id: &str) -> Result<()> {
+    fn check_token_id(network: &NetworkName, token_id: &str) -> Result<Option<String>> {
         match network {
         match network {
             #[cfg(feature = "sol")]
             #[cfg(feature = "sol")]
             NetworkName::Solana => {
             NetworkName::Solana => {
                 if token_id != "So11111111111111111111111111111111111111112" {
                 if token_id != "So11111111111111111111111111111111111111112" {
-                    // This is supposed to be a token mint account now
-                    use drk::service::sol::account_is_initialized_mint;
-                    use drk::service::sol::SolFailed::BadSolAddress;
-                    use solana_client::rpc_client::RpcClient;
-                    use solana_sdk::pubkey::Pubkey;
-
-                    let pubkey = match Pubkey::from_str(token_id) {
-                        Ok(v) => v,
-                        Err(e) => return Err(Error::from(BadSolAddress(e.to_string()))),
-                    };
-
-                    // FIXME: Use network name from variable
-                    let rpc = RpcClient::new("https://api.devnet.solana.com".to_string());
-                    if !account_is_initialized_mint(&rpc, &pubkey) {
-                        return Err(Error::CashierInvalidTokenId(
-                            "Given address is not a valid token mint".into(),
-                        ));
-                    }
+                    return Ok(Some(token_id.to_string()));
                 }
                 }
+                return Ok(None);
             }
             }
             #[cfg(feature = "btc")]
             #[cfg(feature = "btc")]
             NetworkName::Bitcoin => {
             NetworkName::Bitcoin => {
                 // Handle bitcoin address here if needed
                 // Handle bitcoin address here if needed
+                Ok(None)
             }
             }
         }
         }
-        Ok(())
     }
     }
 
 
     async fn start(&self, executor: Arc<Executor<'static>>) -> Result<()> {
     async fn start(&self, executor: Arc<Executor<'static>>) -> Result<()> {

+ 2 - 2
src/bin/sol-test.rs

@@ -32,7 +32,7 @@ async fn run() -> Result<()> {
         .await?;
         .await?;
 
 
     let bridge2 = bridge.clone();
     let bridge2 = bridge.clone();
-    let bridge_subscribtion = bridge2.subscribe().await;
+    let bridge_subscribtion = bridge2.subscribe(None).await;
 
 
     bridge_subscribtion
     bridge_subscribtion
         .sender
         .sender
@@ -51,7 +51,7 @@ async fn run() -> Result<()> {
         _ => {}
         _ => {}
     }
     }
 
 
-    let bridge_subscribtion = bridge.subscribe().await;
+    let bridge_subscribtion = bridge.subscribe(None).await;
 
 
     bridge_subscribtion
     bridge_subscribtion
         .sender
         .sender

+ 15 - 5
src/service/bridge.rs

@@ -93,12 +93,12 @@ impl Bridge {
             .map(|o| o.map_err(Error::from))
             .map(|o| o.map_err(Error::from))
     }
     }
 
 
-    pub async fn subscribe(self: Arc<Self>) -> BridgeSubscribtion {
+    pub async fn subscribe(self: Arc<Self>, mint: Option<String>) -> BridgeSubscribtion {
         debug!(target: "BRIDGE", "Start new subscription");
         debug!(target: "BRIDGE", "Start new subscription");
         let (sender, req) = async_channel::unbounded();
         let (sender, req) = async_channel::unbounded();
         let (rep, receiver) = async_channel::unbounded();
         let (rep, receiver) = async_channel::unbounded();
 
 
-        smol::spawn(self.listen_for_new_subscription(req, rep)).detach();
+        smol::spawn(self.listen_for_new_subscription(req, rep, mint)).detach();
 
 
         BridgeSubscribtion { sender, receiver }
         BridgeSubscribtion { sender, receiver }
     }
     }
@@ -107,6 +107,7 @@ impl Bridge {
         self: Arc<Self>,
         self: Arc<Self>,
         req: async_channel::Receiver<BridgeRequests>,
         req: async_channel::Receiver<BridgeRequests>,
         rep: async_channel::Sender<BridgeResponse>,
         rep: async_channel::Sender<BridgeResponse>,
+        mint: Option<String>,
     ) -> Result<()> {
     ) -> Result<()> {
         debug!(target: "BRIDGE", "Listen for new subscription");
         debug!(target: "BRIDGE", "Listen for new subscription");
         let req = req.recv().await?;
         let req = req.recv().await?;
@@ -122,6 +123,14 @@ impl Bridge {
             return Ok(());
             return Ok(());
         }
         }
 
 
+        let mut mint_address: Option<String> = mint.clone();
+
+        if mint.is_some() {
+            if mint.unwrap().is_empty() {
+                mint_address = None;
+            }
+        }
+
         let client: Arc<dyn NetworkClient + Send + Sync>;
         let client: Arc<dyn NetworkClient + Send + Sync>;
         // avoid deadlock
         // avoid deadlock
         {
         {
@@ -133,7 +142,7 @@ impl Bridge {
             BridgeRequestsPayload::Watch(val) => match val {
             BridgeRequestsPayload::Watch(val) => match val {
                 Some((private_key, public_key)) => {
                 Some((private_key, public_key)) => {
                     let pub_key = client
                     let pub_key = client
-                        .subscribe_with_keypair(private_key, public_key)
+                        .subscribe_with_keypair(private_key, public_key, mint_address)
                         .await?;
                         .await?;
                     let res = BridgeResponse {
                     let res = BridgeResponse {
                         error: BridgeResponseError::NoError,
                         error: BridgeResponseError::NoError,
@@ -142,7 +151,7 @@ impl Bridge {
                     rep.send(res).await?;
                     rep.send(res).await?;
                 }
                 }
                 None => {
                 None => {
-                    let sub = client.subscribe().await?;
+                    let sub = client.subscribe(mint_address).await?;
                     let res = BridgeResponse {
                     let res = BridgeResponse {
                         error: BridgeResponseError::NoError,
                         error: BridgeResponseError::NoError,
                         payload: BridgeResponsePayload::Watch(sub.secret_key, sub.public_key),
                         payload: BridgeResponsePayload::Watch(sub.secret_key, sub.public_key),
@@ -166,13 +175,14 @@ impl Bridge {
 
 
 #[async_trait]
 #[async_trait]
 pub trait NetworkClient {
 pub trait NetworkClient {
-    async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion>;
+    async fn subscribe(self: Arc<Self>, mint: Option<String>) -> Result<TokenSubscribtion>;
 
 
     // should check if the keypair in not already subscribed
     // should check if the keypair in not already subscribed
     async fn subscribe_with_keypair(
     async fn subscribe_with_keypair(
         self: Arc<Self>,
         self: Arc<Self>,
         private_key: Vec<u8>,
         private_key: Vec<u8>,
         public_key: Vec<u8>,
         public_key: Vec<u8>,
+        mint: Option<String>,
     ) -> Result<String>;
     ) -> Result<String>;
 
 
     async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>>;
     async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>>;

+ 2 - 1
src/service/btc.rs

@@ -149,7 +149,7 @@ impl BtcClient {
 
 
 #[async_trait]
 #[async_trait]
 impl NetworkClient for BtcClient {
 impl NetworkClient for BtcClient {
-    async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion> {
+    async fn subscribe(self: Arc<Self>, _mint: Option<String>) -> Result<TokenSubscribtion> {
         // Generate bitcoin keys
         // Generate bitcoin keys
         let btc_keys = BitcoinKeys::new(self.network)?;
         let btc_keys = BitcoinKeys::new(self.network)?;
         let btc_privkey = btc_keys.clone();
         let btc_privkey = btc_keys.clone();
@@ -174,6 +174,7 @@ impl NetworkClient for BtcClient {
         self: Arc<Self>,
         self: Arc<Self>,
         _private_key: Vec<u8>,
         _private_key: Vec<u8>,
         _public_key: Vec<u8>,
         _public_key: Vec<u8>,
+        _mint: Option<String>,
     ) -> Result<String> {
     ) -> Result<String> {
         // TODO this not implemented yet
         // TODO this not implemented yet
         Ok(String::new())
         Ok(String::new())

+ 31 - 15
src/service/sol.rs

@@ -223,10 +223,6 @@ impl SolClient {
         debug!(target: "SOL BRIDGE", "Sending {} {:?} tokens to main wallet",
         debug!(target: "SOL BRIDGE", "Sending {} {:?} tokens to main wallet",
                 amount / u64::pow(10, decimals as u32), mint);
                 amount / u64::pow(10, decimals as u32), mint);
 
 
-        if !account_is_initialized_mint(rpc, mint) {
-            return Err(SolFailed::MintIsNotValid(mint.to_string()));
-        }
-
         // The token account from our main wallet
         // The token account from our main wallet
         let main_tok_pk = get_associated_token_address(&self.main_keypair.pubkey(), mint);
         let main_tok_pk = get_associated_token_address(&self.main_keypair.pubkey(), mint);
         // The token account from the deposit wallet
         // The token account from the deposit wallet
@@ -302,27 +298,46 @@ impl SolClient {
     ) -> SolResult<Signature> {
     ) -> SolResult<Signature> {
         debug!(target: "SOL BRIDGE", "Sending {} SOL to main wallet", lamports_to_sol(amount));
         debug!(target: "SOL BRIDGE", "Sending {} SOL to main wallet", lamports_to_sol(amount));
 
 
-        let ix = system_instruction::transfer(&keypair.pubkey(), &self.main_keypair.pubkey(), amount);
+        let ix =
+            system_instruction::transfer(&keypair.pubkey(), &self.main_keypair.pubkey(), amount);
         let tx = Transaction::new_with_payer(&[ix], Some(&self.main_keypair.pubkey()));
         let tx = Transaction::new_with_payer(&[ix], Some(&self.main_keypair.pubkey()));
         let signature = sign_and_send_transaction(&rpc, tx, vec![&self.main_keypair, keypair])?;
         let signature = sign_and_send_transaction(&rpc, tx, vec![&self.main_keypair, keypair])?;
 
 
         debug!(target: "SOL BRIDGE", "Sent SOL to main wallet: {}", signature);
         debug!(target: "SOL BRIDGE", "Sent SOL to main wallet: {}", signature);
         Ok(signature)
         Ok(signature)
     }
     }
+
+    fn check_mint_address(&self, mint_address: Option<String>) -> SolResult<Option<Pubkey>> {
+        if let Some(mint_addr) = mint_address {
+            let pubkey = match Pubkey::from_str(&mint_addr) {
+                Ok(v) => v,
+                Err(e) => return Err(SolFailed::BadSolAddress(e.to_string())),
+            };
+
+            let rpc = RpcClient::new(self.rpc_server.to_string());
+
+            if !account_is_initialized_mint(&rpc, &pubkey) {
+                return Err(SolFailed::MintIsNotValid(mint_addr.to_string()));
+            }
+
+            return Ok(Some(pubkey));
+        } else {
+            return Ok(None);
+        }
+    }
 }
 }
 
 
 #[async_trait]
 #[async_trait]
 impl NetworkClient for SolClient {
 impl NetworkClient for SolClient {
-    async fn subscribe(self: Arc<Self>) -> Result<TokenSubscribtion> {
+    async fn subscribe(self: Arc<Self>, mint_address: Option<String>) -> Result<TokenSubscribtion> {
         let keypair = Keypair::generate(&mut OsRng);
         let keypair = Keypair::generate(&mut OsRng);
 
 
         let public_key = keypair.pubkey().to_string();
         let public_key = keypair.pubkey().to_string();
         let secret_key = serialize(&keypair);
         let secret_key = serialize(&keypair);
 
 
-        // TODO: Option<Pubkey> for 2nd arg representing Token Mint account
-        let mint = Pubkey::from_str("F4wkXLN5n1ckejfnJoahGpgW3ffRsrvS9GGVME6ckxS9").unwrap();
-        smol::spawn(self.handle_subscribe_request(keypair, Some(mint))).detach();
-        //smol::spawn(self.handle_subscribe_request(keypair, None)).detach();
+        let mint = self.check_mint_address(mint_address)?;
+
+        smol::spawn(self.handle_subscribe_request(keypair, mint)).detach();
 
 
         Ok(TokenSubscribtion {
         Ok(TokenSubscribtion {
             secret_key,
             secret_key,
@@ -335,15 +350,15 @@ impl NetworkClient for SolClient {
         self: Arc<Self>,
         self: Arc<Self>,
         private_key: Vec<u8>,
         private_key: Vec<u8>,
         _public_key: Vec<u8>,
         _public_key: Vec<u8>,
+        mint_address: Option<String>,
     ) -> Result<String> {
     ) -> Result<String> {
         let keypair: Keypair = deserialize(&private_key)?;
         let keypair: Keypair = deserialize(&private_key)?;
 
 
         let public_key = keypair.pubkey().to_string();
         let public_key = keypair.pubkey().to_string();
 
 
-        // TODO: Option<Pubkey> for 2nd arg representing Token Mint account
-        let mint = Pubkey::from_str("F4wkXLN5n1ckejfnJoahGpgW3ffRsrvS9GGVME6ckxS9").unwrap();
-        smol::spawn(self.handle_subscribe_request(keypair, Some(mint))).detach();
-        //smol::spawn(self.handle_subscribe_request(keypair, None)).detach();
+        let mint = self.check_mint_address(mint_address)?;
+
+        smol::spawn(self.handle_subscribe_request(keypair, mint)).detach();
 
 
         Ok(public_key)
         Ok(public_key)
     }
     }
@@ -355,7 +370,8 @@ impl NetworkClient for SolClient {
     async fn send(self: Arc<Self>, address: Vec<u8>, amount: u64) -> Result<()> {
     async fn send(self: Arc<Self>, address: Vec<u8>, amount: u64) -> Result<()> {
         let rpc = RpcClient::new(self.rpc_server.to_string());
         let rpc = RpcClient::new(self.rpc_server.to_string());
         let address: Pubkey = deserialize(&address)?;
         let address: Pubkey = deserialize(&address)?;
-        let instruction = system_instruction::transfer(&self.main_keypair.pubkey(), &address, amount);
+        let instruction =
+            system_instruction::transfer(&self.main_keypair.pubkey(), &address, amount);
 
 
         let mut tx = Transaction::new_with_payer(&[instruction], Some(&self.main_keypair.pubkey()));
         let mut tx = Transaction::new_with_payer(&[instruction], Some(&self.main_keypair.pubkey()));
         let bhq = BlockhashQuery::default();
         let bhq = BlockhashQuery::default();