bridge.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. use async_std::sync::{Arc, Mutex};
  2. use std::collections::HashMap;
  3. use async_trait::async_trait;
  4. use futures::stream::FuturesUnordered;
  5. use futures::stream::StreamExt;
  6. use log::*;
  7. use crate::util::NetworkName;
  8. use crate::{Error, Result};
  9. pub struct BridgeRequests {
  10. pub network: NetworkName,
  11. pub payload: BridgeRequestsPayload,
  12. }
  13. pub struct BridgeResponse {
  14. pub error: BridgeResponseError,
  15. pub payload: BridgeResponsePayload,
  16. }
  17. pub enum BridgeRequestsPayload {
  18. Send(Vec<u8>, u64), // send (address, amount)
  19. Watch(Option<(Vec<u8>, Vec<u8>)>), // if already has a keypair
  20. }
  21. pub enum BridgeResponsePayload {
  22. Watch(Vec<u8>, String),
  23. Address(String),
  24. Send,
  25. Empty,
  26. }
  27. #[repr(u8)]
  28. pub enum BridgeResponseError {
  29. NoError,
  30. NotSupportedClient,
  31. }
  32. pub struct BridgeSubscribtion {
  33. pub sender: async_channel::Sender<BridgeRequests>,
  34. pub receiver: async_channel::Receiver<BridgeResponse>,
  35. }
  36. pub struct TokenSubscribtion {
  37. pub secret_key: Vec<u8>,
  38. pub public_key: String,
  39. }
  40. #[derive(Debug)]
  41. pub struct TokenNotification {
  42. pub network: NetworkName,
  43. pub token_id: jubjub::Fr,
  44. pub drk_pub_key: jubjub::SubgroupPoint,
  45. pub received_balance: u64,
  46. pub decimals: u16
  47. }
  48. pub struct Bridge {
  49. clients: Mutex<HashMap<NetworkName, Arc<dyn NetworkClient + Send + Sync>>>,
  50. notifiers: FuturesUnordered<async_channel::Receiver<TokenNotification>>,
  51. }
  52. impl Bridge {
  53. pub fn new() -> Arc<Self> {
  54. Arc::new(Self {
  55. clients: Mutex::new(HashMap::new()),
  56. notifiers: FuturesUnordered::new(),
  57. })
  58. }
  59. pub async fn add_clients(
  60. self: Arc<Self>,
  61. network: NetworkName,
  62. client: Arc<dyn NetworkClient + Send + Sync>,
  63. ) -> Result<()> {
  64. debug!(target: "BRIDGE", "Add new client");
  65. let client2 = client.clone();
  66. let notifier = client2.get_notifier().await?;
  67. if !notifier.is_closed() {
  68. self.notifiers.push(notifier);
  69. }
  70. self.clients.lock().await.insert(network, client.clone());
  71. Ok(())
  72. }
  73. pub async fn listen(self: Arc<Self>) -> Option<Result<TokenNotification>> {
  74. if !self.notifiers.is_empty() {
  75. debug!(target: "BRIDGE", "Start listening to new notification");
  76. let notification = self
  77. .notifiers
  78. .iter()
  79. .map(|n| n.recv())
  80. .collect::<FuturesUnordered<async_channel::Recv<TokenNotification>>>()
  81. .next()
  82. .await
  83. .map(|o| o.map_err(Error::from));
  84. debug!(target: "BRIDGE", "End listening to new notification");
  85. notification
  86. } else {
  87. None
  88. }
  89. }
  90. pub async fn subscribe(
  91. self: Arc<Self>,
  92. drk_pub_key: jubjub::SubgroupPoint,
  93. mint: Option<String>,
  94. ) -> BridgeSubscribtion {
  95. debug!(target: "BRIDGE", "Start new subscription");
  96. let (sender, req) = async_channel::unbounded();
  97. let (rep, receiver) = async_channel::unbounded();
  98. smol::spawn(self.listen_for_new_subscription(req, rep, drk_pub_key, mint)).detach();
  99. BridgeSubscribtion { sender, receiver }
  100. }
  101. async fn listen_for_new_subscription(
  102. self: Arc<Self>,
  103. req: async_channel::Receiver<BridgeRequests>,
  104. rep: async_channel::Sender<BridgeResponse>,
  105. drk_pub_key: jubjub::SubgroupPoint,
  106. mint: Option<String>,
  107. ) -> Result<()> {
  108. debug!(target: "BRIDGE", "Listen for new subscription");
  109. let req = req.recv().await?;
  110. let network = req.network;
  111. if !self.clients.lock().await.contains_key(&network) {
  112. let res = BridgeResponse {
  113. error: BridgeResponseError::NotSupportedClient,
  114. payload: BridgeResponsePayload::Empty,
  115. };
  116. rep.send(res).await?;
  117. return Ok(());
  118. }
  119. let mut mint_address: Option<String> = mint.clone();
  120. if mint.is_some() && mint.unwrap().is_empty() {
  121. mint_address = None;
  122. }
  123. let client: Arc<dyn NetworkClient + Send + Sync>;
  124. // avoid deadlock
  125. {
  126. let c = &self.clients.lock().await[&network];
  127. client = c.clone();
  128. }
  129. match req.payload {
  130. BridgeRequestsPayload::Watch(val) => match val {
  131. Some((private_key, public_key)) => {
  132. let pub_key = client
  133. .subscribe_with_keypair(private_key, public_key, drk_pub_key, mint_address)
  134. .await?;
  135. let res = BridgeResponse {
  136. error: BridgeResponseError::NoError,
  137. payload: BridgeResponsePayload::Address(pub_key),
  138. };
  139. rep.send(res).await?;
  140. }
  141. None => {
  142. let sub = client.subscribe(drk_pub_key, mint_address).await?;
  143. let res = BridgeResponse {
  144. error: BridgeResponseError::NoError,
  145. payload: BridgeResponsePayload::Watch(sub.secret_key, sub.public_key),
  146. };
  147. rep.send(res).await?;
  148. }
  149. },
  150. BridgeRequestsPayload::Send(addr, amount) => {
  151. client.send(addr, amount).await?;
  152. let res = BridgeResponse {
  153. error: BridgeResponseError::NoError,
  154. payload: BridgeResponsePayload::Send,
  155. };
  156. rep.send(res).await?;
  157. }
  158. }
  159. Ok(())
  160. }
  161. }
  162. #[async_trait]
  163. pub trait NetworkClient {
  164. async fn subscribe(
  165. self: Arc<Self>,
  166. drk_pub_key: jubjub::SubgroupPoint,
  167. mint: Option<String>,
  168. ) -> Result<TokenSubscribtion>;
  169. // should check if the keypair in not already subscribed
  170. async fn subscribe_with_keypair(
  171. self: Arc<Self>,
  172. private_key: Vec<u8>,
  173. public_key: Vec<u8>,
  174. drk_pub_key: jubjub::SubgroupPoint,
  175. mint: Option<String>,
  176. ) -> Result<String>;
  177. async fn get_notifier(self: Arc<Self>) -> Result<async_channel::Receiver<TokenNotification>>;
  178. async fn send(self: Arc<Self>, address: Vec<u8>, amount: u64) -> Result<()>;
  179. }