cashierd.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. use std::{path::PathBuf, str::FromStr};
  2. use async_executor::Executor;
  3. use async_std::sync::{Arc, Mutex};
  4. use async_trait::async_trait;
  5. use clap::clap_app;
  6. use easy_parallel::Parallel;
  7. use incrementalmerkletree::bridgetree::BridgeTree;
  8. use log::{debug, info};
  9. use pasta_curves::pallas;
  10. use serde_json::{json, Value};
  11. use drk::{
  12. blockchain::{rocks::columns, Rocks, RocksColumn},
  13. circuit::{MintContract, SpendContract},
  14. cli::{CashierdConfig, Config},
  15. client::Client,
  16. crypto::{merkle_node::MerkleNode, proof::VerifyingKey, schnorr},
  17. rpc::{
  18. jsonrpc::{error as jsonerr, response as jsonresp, ErrorCode::*, JsonRequest, JsonResult},
  19. rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
  20. },
  21. serial::{deserialize, serialize},
  22. service::{bridge, bridge::Bridge},
  23. state::State,
  24. types::DrkTokenId,
  25. util::{expand_path, generate_id, join_config_path, parse::truncate, NetworkName},
  26. wallet::{cashierdb::TokenKey, CashierDb, WalletDb},
  27. Error, Result,
  28. };
  29. fn handle_bridge_error(error_code: u32) -> Result<()> {
  30. match error_code {
  31. 1 => Err(Error::BridgeError("Not Supported Client".into())),
  32. 2 => Err(Error::BridgeError("Unable to watch the deposit address".into())),
  33. 3 => Err(Error::BridgeError("Unable to send the token".into())),
  34. _ => Err(Error::BridgeError("Unknown error_code".into())),
  35. }
  36. }
  37. #[derive(Clone, Debug)]
  38. pub struct Network {
  39. pub name: NetworkName,
  40. pub blockchain: String,
  41. pub keypair: String,
  42. }
  43. struct Cashierd {
  44. bridge: Arc<Bridge>,
  45. cashier_wallet: Arc<CashierDb>,
  46. networks: Vec<Network>,
  47. public_key: String,
  48. config: CashierdConfig,
  49. }
  50. #[async_trait]
  51. impl RequestHandler for Cashierd {
  52. async fn handle_request(&self, req: JsonRequest, executor: Arc<Executor<'_>>) -> JsonResult {
  53. if req.params.as_array().is_none() {
  54. return JsonResult::Err(jsonerr(InvalidParams, None, req.id))
  55. }
  56. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  57. match req.method.as_str() {
  58. Some("deposit") => return self.deposit(req.id, req.params, executor).await,
  59. Some("withdraw") => return self.withdraw(req.id, req.params).await,
  60. Some("features") => return self.features(req.id, req.params).await,
  61. Some(_) => {}
  62. None => {}
  63. };
  64. return JsonResult::Err(jsonerr(MethodNotFound, None, req.id))
  65. }
  66. }
  67. impl Cashierd {
  68. async fn new(config: CashierdConfig) -> Result<Self> {
  69. debug!(target: "CASHIER DAEMON", "Initialize");
  70. let cashier_wallet = CashierDb::new(
  71. expand_path(&config.cashier_wallet_path)?.as_path(),
  72. config.cashier_wallet_password.clone(),
  73. )?;
  74. let mut networks = Vec::new();
  75. let cfg = config.clone();
  76. for network in cfg.networks {
  77. networks.push(Network {
  78. name: NetworkName::from_str(&network.name)?,
  79. blockchain: network.blockchain,
  80. keypair: network.keypair,
  81. });
  82. }
  83. let bridge = bridge::Bridge::new();
  84. Ok(Self { bridge, cashier_wallet, networks, public_key: String::from(""), config })
  85. }
  86. async fn listen_for_receiving_coins(
  87. bridge: Arc<Bridge>,
  88. cashier_wallet: Arc<CashierDb>,
  89. recv_coin: async_channel::Receiver<(pallas::Point, u64)>,
  90. executor: Arc<Executor<'_>>,
  91. ) -> Result<()> {
  92. // received drk coin
  93. let (drk_pub_key, amount) = recv_coin.recv().await?;
  94. debug!(target: "CASHIER DAEMON", "Receive coin with amount: {}", amount);
  95. // get public key, and token_id of the token
  96. let token =
  97. cashier_wallet.get_withdraw_token_public_key_by_dkey_public(&drk_pub_key).await?;
  98. // send a request to bridge to send equivalent amount of
  99. // received drk coin to token publickey
  100. if let Some(withdraw_token) = token {
  101. let bridge_subscribtion = bridge
  102. .subscribe(drk_pub_key, Some(withdraw_token.mint_address), executor.clone())
  103. .await;
  104. // send a request to the bridge to send amount of token
  105. // equivalent to the received drk
  106. bridge_subscribtion
  107. .sender
  108. .send(bridge::BridgeRequests {
  109. network: withdraw_token.network.clone(),
  110. payload: bridge::BridgeRequestsPayload::Send(
  111. withdraw_token.token_public_key.clone(),
  112. amount,
  113. ),
  114. })
  115. .await?;
  116. // receive a response
  117. let res = bridge_subscribtion.receiver.recv().await?;
  118. // check the response's error
  119. let error_code = res.error as u32;
  120. if error_code != 0 {
  121. return handle_bridge_error(error_code)
  122. }
  123. match res.payload {
  124. bridge::BridgeResponsePayload::Send => {
  125. cashier_wallet
  126. .confirm_withdraw_key_record(
  127. &withdraw_token.token_public_key,
  128. &withdraw_token.network,
  129. )
  130. .await?;
  131. }
  132. _ => {
  133. return Err(Error::BridgeError("Receive unknown value from Subscription".into()))
  134. }
  135. }
  136. }
  137. Ok(())
  138. }
  139. async fn deposit(&self, id: Value, params: Value, executor: Arc<Executor<'_>>) -> JsonResult {
  140. debug!(target: "CASHIER DAEMON", "RECEIVED DEPOSIT REQUEST");
  141. let args: &Vec<serde_json::Value> = params.as_array().unwrap();
  142. if args.len() != 3 {
  143. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  144. }
  145. let network: NetworkName;
  146. let mut mint_address: &str;
  147. let drk_pub_key: &str;
  148. match (args[0].as_str(), args[1].as_str(), args[2].as_str()) {
  149. (Some(n), Some(m), Some(d)) => {
  150. if NetworkName::from_str(n).is_err() {
  151. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  152. }
  153. network = NetworkName::from_str(n).unwrap();
  154. mint_address = m;
  155. drk_pub_key = d;
  156. }
  157. (None, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  158. (_, None, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  159. (_, _, None) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  160. }
  161. // Check if the features list contains this network
  162. if !self.networks.iter().any(|net| net.name == network) {
  163. return JsonResult::Err(jsonerr(
  164. InvalidParams,
  165. Some(format!("Cashier doesn't support this network: {}", network)),
  166. id,
  167. ))
  168. }
  169. let result: Result<String> = async {
  170. let token_id = generate_id(mint_address, &network)?;
  171. let mint_address_opt = Self::check_token_id(&network, mint_address)?;
  172. if mint_address_opt.is_none() {
  173. mint_address = "";
  174. }
  175. let drk_pub_key = bs58::decode(&drk_pub_key).into_vec()?;
  176. let drk_pub_key: pallas::Point = deserialize(&drk_pub_key)?;
  177. // check if the drk public key already exist
  178. let check = self
  179. .cashier_wallet
  180. .get_deposit_token_keys_by_dkey_public(&drk_pub_key, &network)
  181. .await?;
  182. // start new subscription from the bridge and then cashierd will
  183. // send a request to the bridge to generate keypair for the desired token
  184. // and start watch this token's keypair
  185. // once a bridge receive an update for this token's address
  186. // cashierd will get notification from bridge.listen() function
  187. //
  188. // The "if statement" check from the cashierdb if the node's drk_pub_key already exist
  189. // in this case it will not generate new keypair but it will
  190. // retrieve the old generated keypair
  191. //
  192. // Once receive a response from the bridge, the cashierd then save a deposit
  193. // record in cashierdb with the network name and token id
  194. let bridge = self.bridge.clone();
  195. let bridge_subscribtion =
  196. bridge.subscribe(drk_pub_key, mint_address_opt, executor).await;
  197. if check.is_empty() {
  198. bridge_subscribtion
  199. .sender
  200. .send(bridge::BridgeRequests {
  201. network: network.clone(),
  202. payload: bridge::BridgeRequestsPayload::Watch(None),
  203. })
  204. .await?;
  205. } else {
  206. let keypair = check[0].clone();
  207. bridge_subscribtion
  208. .sender
  209. .send(bridge::BridgeRequests {
  210. network: network.clone(),
  211. payload: bridge::BridgeRequestsPayload::Watch(Some(keypair)),
  212. })
  213. .await?;
  214. }
  215. let bridge_res = bridge_subscribtion.receiver.recv().await?;
  216. let error_code = bridge_res.error as u32;
  217. if error_code != 0 {
  218. return handle_bridge_error(error_code).map(|_| String::new())
  219. }
  220. match bridge_res.payload {
  221. bridge::BridgeResponsePayload::Watch(token_key) => {
  222. // add pairings to db
  223. self.cashier_wallet
  224. .put_deposit_keys(
  225. &drk_pub_key,
  226. &token_key.private_key,
  227. &serialize(&token_key.public_key),
  228. &network,
  229. &token_id,
  230. mint_address.into(),
  231. )
  232. .await?;
  233. Ok(token_key.public_key)
  234. }
  235. bridge::BridgeResponsePayload::Address(token_pub) => Ok(token_pub),
  236. _ => Err(Error::BridgeError("Receive unknown value from Subscription".into())),
  237. }
  238. }
  239. .await;
  240. match result {
  241. Ok(res) => JsonResult::Resp(jsonresp(json!(res), json!(id))),
  242. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  243. }
  244. }
  245. async fn withdraw(&self, id: Value, params: Value) -> JsonResult {
  246. debug!(target: "CASHIER DAEMON", "RECEIVED WITHDRAW REQUEST");
  247. let args: &Vec<serde_json::Value> = params.as_array().unwrap();
  248. if args.len() != 4 {
  249. return JsonResult::Err(jsonerr(InvalidParams, None, id))
  250. }
  251. let network: NetworkName;
  252. let mut mint_address: &str;
  253. let address: &str;
  254. match (args[0].as_str(), args[1].as_str(), args[2].as_str()) {
  255. (Some(n), Some(m), Some(a)) => {
  256. if NetworkName::from_str(n).is_err() {
  257. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id))
  258. }
  259. network = NetworkName::from_str(n).unwrap();
  260. mint_address = m;
  261. address = a;
  262. }
  263. (None, _, _) => return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id)),
  264. (_, None, _) => return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id)),
  265. (_, _, None) => return JsonResult::Err(jsonerr(InvalidAddressParam, None, id)),
  266. }
  267. // Check if the features list contains this network
  268. if !self.networks.iter().any(|net| net.name == network) {
  269. return JsonResult::Err(jsonerr(
  270. InvalidParams,
  271. Some(format!("Cashier doesn't support this network: {}", network)),
  272. id,
  273. ))
  274. }
  275. let result: Result<String> = async {
  276. let token_id: DrkTokenId = generate_id(mint_address, &network)?;
  277. let mint_address_opt = Self::check_token_id(&network, mint_address)?;
  278. if mint_address_opt.is_none() {
  279. // empty string
  280. mint_address = "";
  281. }
  282. let address = serialize(&address.to_string());
  283. let cashier_public: pallas::Point;
  284. if let Some(addr) = self
  285. .cashier_wallet
  286. .get_withdraw_keys_by_token_public_key(&address, &network)
  287. .await?
  288. {
  289. cashier_public = addr.public;
  290. } else {
  291. let cashier_secret = schnorr::SecretKey::random();
  292. cashier_public = cashier_secret.public_key().inner();
  293. self.cashier_wallet
  294. .put_withdraw_keys(
  295. &address,
  296. &cashier_public,
  297. &cashier_secret.inner(),
  298. &network,
  299. &token_id,
  300. mint_address.into(),
  301. )
  302. .await?;
  303. }
  304. let cashier_public_str = bs58::encode(serialize(&cashier_public)).into_string();
  305. Ok(cashier_public_str)
  306. }
  307. .await;
  308. match result {
  309. Ok(res) => JsonResult::Resp(jsonresp(json!(res), json!(id))),
  310. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  311. }
  312. }
  313. async fn features(&self, id: Value, _params: Value) -> JsonResult {
  314. let tcp_port: Option<u16>;
  315. let tls_port: Option<u16>;
  316. let onionaddr: Option<String>;
  317. let dnsaddr: Option<String>;
  318. if self.config.serve_tls {
  319. tls_port = Some(self.config.rpc_listen_address.port());
  320. tcp_port = None;
  321. } else {
  322. tcp_port = Some(self.config.rpc_listen_address.port());
  323. tls_port = None;
  324. }
  325. if self.config.dns_addr.ends_with(".onion") {
  326. onionaddr = Some(self.config.dns_addr.clone());
  327. dnsaddr = None;
  328. } else {
  329. dnsaddr = Some(self.config.dns_addr.clone());
  330. onionaddr = None;
  331. }
  332. let mut resp: serde_json::Value = json!(
  333. {
  334. "server_version": env!("CARGO_PKG_VERSION"),
  335. "protocol_version": "1.0",
  336. "public_key": self.public_key,
  337. "networks": [],
  338. "hosts": {
  339. "tcp_port": tcp_port,
  340. "tls_port": tls_port,
  341. "onion_addr": onionaddr,
  342. "dns_addr": dnsaddr,
  343. }
  344. }
  345. );
  346. for network in self.networks.iter() {
  347. resp.as_object_mut().unwrap()["networks"].as_array_mut().unwrap().push(json!(
  348. {
  349. network.name.to_string().to_lowercase():
  350. {"chain": network.blockchain.to_lowercase()}
  351. }
  352. ));
  353. }
  354. JsonResult::Resp(jsonresp(resp, id))
  355. }
  356. fn check_token_id(network: &NetworkName, _token_id: &str) -> Result<Option<String>> {
  357. match network {
  358. #[cfg(feature = "sol")]
  359. NetworkName::Solana => {
  360. use drk::service::sol::SOL_NATIVE_TOKEN_ID;
  361. if _token_id != SOL_NATIVE_TOKEN_ID {
  362. return Ok(Some(_token_id.to_string()))
  363. }
  364. Ok(None)
  365. }
  366. #[cfg(feature = "eth")]
  367. NetworkName::Ethereum => {
  368. use drk::service::eth::ETH_NATIVE_TOKEN_ID;
  369. if _token_id != ETH_NATIVE_TOKEN_ID {
  370. return Ok(Some(_token_id.to_string()))
  371. }
  372. Ok(None)
  373. }
  374. #[cfg(feature = "btc")]
  375. NetworkName::Bitcoin => Ok(None),
  376. _ => Err(Error::NotSupportedNetwork),
  377. }
  378. }
  379. async fn start(
  380. &mut self,
  381. mut client: Client,
  382. state: Arc<Mutex<State>>,
  383. executor: Arc<Executor<'_>>,
  384. ) -> Result<(smol::Task<Result<()>>, smol::Task<Result<()>>)> {
  385. self.cashier_wallet.init_db().await?;
  386. for network in self.networks.iter() {
  387. match network.name {
  388. #[cfg(feature = "sol")]
  389. NetworkName::Solana => {
  390. debug!(target: "CASHIER DAEMON", "Add sol network");
  391. use drk::service::{sol::SolFailed, SolClient};
  392. use solana_sdk::{signature::Signer, signer::keypair::Keypair};
  393. let bridge2 = self.bridge.clone();
  394. let main_keypair: Keypair;
  395. let main_keypairs =
  396. self.cashier_wallet.get_main_keys(&NetworkName::Solana).await?;
  397. if network.keypair.is_empty() {
  398. if main_keypairs.is_empty() {
  399. main_keypair = Keypair::new();
  400. self.cashier_wallet
  401. .put_main_keys(
  402. &TokenKey {
  403. private_key: serialize(&main_keypair),
  404. public_key: serialize(&main_keypair.pubkey()),
  405. },
  406. &NetworkName::Solana,
  407. )
  408. .await?;
  409. } else {
  410. main_keypair =
  411. deserialize(&main_keypairs[main_keypairs.len() - 1].private_key)?;
  412. }
  413. } else {
  414. let keypair_str = drk::cli::cli_config::load_keypair_to_str(expand_path(
  415. &network.keypair.clone(),
  416. )?)?;
  417. let keypair_bytes: Vec<u8> = serde_json::from_str(&keypair_str)?;
  418. main_keypair = Keypair::from_bytes(&keypair_bytes)
  419. .map_err(|e| SolFailed::Signature(e.to_string()))?;
  420. }
  421. let sol_client = SolClient::new(main_keypair, &network.blockchain).await?;
  422. bridge2.add_clients(NetworkName::Solana, sol_client).await?;
  423. }
  424. #[cfg(feature = "eth")]
  425. NetworkName::Ethereum => {
  426. debug!(target: "CASHIER DAEMON", "Add eth network");
  427. use drk::service::{
  428. eth::{generate_privkey, Keypair},
  429. EthClient,
  430. };
  431. let bridge2 = self.bridge.clone();
  432. let main_keypair: Keypair;
  433. let main_keypairs =
  434. self.cashier_wallet.get_main_keys(&NetworkName::Ethereum).await?;
  435. let passphrase = self.config.geth_passphrase.clone();
  436. let mut eth_client = EthClient::new(
  437. expand_path(&self.config.geth_socket)?.to_str().unwrap().into(),
  438. passphrase.clone(),
  439. );
  440. if main_keypairs.is_empty() {
  441. let main_private_key = generate_privkey();
  442. let main_public_key = eth_client
  443. .import_privkey(&main_private_key, &passphrase)
  444. .await?
  445. .as_str()
  446. .unwrap()
  447. .to_string();
  448. self.cashier_wallet
  449. .put_main_keys(
  450. &TokenKey {
  451. private_key: serialize(&main_private_key),
  452. public_key: serialize(&main_public_key),
  453. },
  454. &NetworkName::Ethereum,
  455. )
  456. .await?;
  457. main_keypair =
  458. Keypair { private_key: main_private_key, public_key: main_public_key };
  459. } else {
  460. let last_keypair = &main_keypairs[main_keypairs.len() - 1];
  461. main_keypair = Keypair {
  462. private_key: deserialize(&last_keypair.private_key)?,
  463. public_key: deserialize(&last_keypair.public_key)?,
  464. }
  465. }
  466. eth_client.set_main_keypair(&main_keypair);
  467. bridge2.add_clients(NetworkName::Ethereum, Arc::new(eth_client)).await?;
  468. }
  469. #[cfg(feature = "btc")]
  470. NetworkName::Bitcoin => {
  471. debug!(target: "CASHIER DAEMON", "Add btc network");
  472. use drk::service::btc::{BtcClient, BtcFailed, Keypair};
  473. let bridge2 = self.bridge.clone();
  474. let main_keypair: Keypair;
  475. let main_keypairs =
  476. self.cashier_wallet.get_main_keys(&NetworkName::Bitcoin).await?;
  477. if network.keypair.is_empty() {
  478. if main_keypairs.is_empty() {
  479. main_keypair = Keypair::new();
  480. self.cashier_wallet
  481. .put_main_keys(
  482. &TokenKey {
  483. private_key: serialize(&main_keypair),
  484. public_key: serialize(&main_keypair.pubkey()),
  485. },
  486. &NetworkName::Bitcoin,
  487. )
  488. .await?;
  489. } else {
  490. main_keypair =
  491. deserialize(&main_keypairs[main_keypairs.len() - 1].private_key)?;
  492. }
  493. } else {
  494. let keypair_str = drk::cli::cli_config::load_keypair_to_str(expand_path(
  495. &network.keypair.clone(),
  496. )?)?;
  497. let keypair_bytes: Vec<u8> = serde_json::from_str(&keypair_str)?;
  498. main_keypair = Keypair::from_bytes(&keypair_bytes)
  499. .map_err(|e| BtcFailed::DecodeAndEncodeError(e.to_string()))?;
  500. }
  501. let btc_client = BtcClient::new(main_keypair, &network.blockchain).await?;
  502. bridge2.add_clients(NetworkName::Bitcoin, btc_client).await?;
  503. }
  504. _ => {}
  505. }
  506. }
  507. client.start().await?;
  508. let (notify, recv_coin) = async_channel::unbounded::<(pallas::Point, u64)>();
  509. client
  510. .connect_to_subscriber_from_cashier(
  511. state.clone(),
  512. self.cashier_wallet.clone(),
  513. notify.clone(),
  514. executor.clone(),
  515. )
  516. .await?;
  517. let cashier_wallet = self.cashier_wallet.clone();
  518. let bridge = self.bridge.clone();
  519. let ex = executor.clone();
  520. let listen_for_receiving_coins_task: smol::Task<Result<()>> = executor.spawn(async move {
  521. let ex2 = ex.clone();
  522. loop {
  523. Self::listen_for_receiving_coins(
  524. bridge.clone(),
  525. cashier_wallet.clone(),
  526. recv_coin.clone(),
  527. ex2.clone(),
  528. )
  529. .await?;
  530. }
  531. });
  532. let bridge2 = self.bridge.clone();
  533. let listen_for_notification_from_bridge_task: smol::Task<Result<()>> =
  534. executor.spawn(async move {
  535. while let Some(token_notification) = bridge2.clone().listen().await {
  536. debug!(target: "CASHIER DAEMON", "Notification from birdge");
  537. let token_notification = token_notification?;
  538. let received_balance = truncate(
  539. token_notification.received_balance,
  540. 8,
  541. token_notification.decimals,
  542. )?;
  543. client
  544. .send(
  545. token_notification.drk_pub_key,
  546. received_balance,
  547. token_notification.token_id,
  548. true,
  549. state.clone(),
  550. )
  551. .await?;
  552. }
  553. Ok(())
  554. });
  555. Ok((listen_for_receiving_coins_task, listen_for_notification_from_bridge_task))
  556. }
  557. }
  558. async fn start(
  559. executor: Arc<Executor<'_>>,
  560. config: &CashierdConfig,
  561. get_address_flag: bool,
  562. ) -> Result<()> {
  563. let mut cashierd = Cashierd::new(config.clone()).await?;
  564. let client_wallet = WalletDb::new(
  565. expand_path(&config.client_wallet_path.clone())?.as_path(),
  566. config.client_wallet_password.clone(),
  567. )?;
  568. let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
  569. /*
  570. let mint_pk = ProvingKey::build(11, MintContract::default());
  571. let spend_pk = ProvingKey::build(11, SpendContract::default());
  572. */
  573. info!("Building verifying key for the mint contract...");
  574. let mint_vk = VerifyingKey::build(11, MintContract::default());
  575. info!("Building verifying key for the spend contract...");
  576. let spend_vk = VerifyingKey::build(11, SpendContract::default());
  577. let client = Client::new(
  578. rocks.clone(),
  579. (config.gateway_protocol_url.parse()?, config.gateway_publisher_url.parse()?),
  580. client_wallet.clone(),
  581. )
  582. .await?;
  583. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  584. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  585. let cashier_public = client.main_keypair.public;
  586. let cashier_public_str = bs58::encode(&serialize(&cashier_public)).into_string();
  587. cashierd.public_key = cashier_public_str.clone();
  588. let cashier_public_keys = vec![cashier_public];
  589. let state = Arc::new(Mutex::new(State {
  590. tree: BridgeTree::<MerkleNode, 32>::new(100),
  591. merkle_roots,
  592. nullifiers,
  593. mint_vk,
  594. spend_vk,
  595. public_keys: cashier_public_keys,
  596. }));
  597. if get_address_flag {
  598. info!("Public Key: {}", cashier_public_str);
  599. return Ok(())
  600. };
  601. let cfg = RpcServerConfig {
  602. socket_addr: config.rpc_listen_address,
  603. use_tls: config.serve_tls,
  604. identity_path: expand_path(&config.clone().tls_identity_path)?,
  605. identity_pass: config.tls_identity_password.clone(),
  606. };
  607. let (t1, t2) = cashierd.start(client, state, executor.clone()).await?;
  608. listen_and_serve(cfg, Arc::new(cashierd), executor).await?;
  609. t1.cancel().await;
  610. t2.cancel().await;
  611. Ok(())
  612. }
  613. #[async_std::main]
  614. async fn main() -> Result<()> {
  615. let args = clap_app!(cashierd =>
  616. (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
  617. (@arg ADDRESS: -a --address "Get Cashier Public key")
  618. (@arg verbose: -v --verbose "Increase verbosity")
  619. (@arg refresh: -r --refresh "Refresh the wallet and slabstore")
  620. )
  621. .get_matches();
  622. let config_path = if args.is_present("CONFIG") {
  623. expand_path(args.value_of("CONFIG").unwrap())?
  624. } else {
  625. join_config_path(&PathBuf::from("cashierd.toml"))?
  626. };
  627. let loglevel = if args.is_present("verbose") { log::Level::Debug } else { log::Level::Info };
  628. simple_logger::init_with_level(loglevel)?;
  629. let config: CashierdConfig = Config::<CashierdConfig>::load(config_path)?;
  630. if args.is_present("refresh") {
  631. debug!(target: "CASHIER DAEMON", "Refresh the wallet and the database");
  632. let client_wallet = WalletDb::new(
  633. expand_path(&config.client_wallet_path)?.as_path(),
  634. config.client_wallet_password.clone(),
  635. )?;
  636. client_wallet.remove_own_coins().await?;
  637. let wallet = CashierDb::new(
  638. expand_path(&config.cashier_wallet_path)?.as_path(),
  639. config.cashier_wallet_password.clone(),
  640. )?;
  641. wallet.remove_withdraw_and_deposit_keys().await?;
  642. if let Some(path) = expand_path(&config.database_path)?.to_str() {
  643. debug!(target: "CASHIER DAEMON", "Remove database: {}", path);
  644. std::fs::remove_dir_all(path)?;
  645. }
  646. info!("Wallet got updated successfully.");
  647. return Ok(())
  648. }
  649. let ex = Arc::new(Executor::new());
  650. let (signal, shutdown) = async_channel::unbounded::<()>();
  651. let ex2 = ex.clone();
  652. let get_address_flag = args.is_present("ADDRESS");
  653. let nthreads = num_cpus::get();
  654. debug!(target: "CASHIER DAEMON", "Run {} executor threads", nthreads);
  655. let (_, result) = Parallel::new()
  656. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  657. // Run the main future on the current thread.
  658. .finish(|| {
  659. smol::future::block_on(async move {
  660. start(ex2, &config, get_address_flag).await?;
  661. drop(signal);
  662. Ok::<(), drk::Error>(())
  663. })
  664. });
  665. result
  666. }
  667. // async fn resume_watch_deposit_keys(
  668. // bridge: Arc<Bridge>,
  669. // cashier_wallet: Arc<CashierDb>,
  670. // networks: Vec<Network>,
  671. // executor: Arc<Executor<'_>>,
  672. // ) -> Result<()> {
  673. // debug!(target: "CASHIER DAEMON", "Resume watch deposit keys");
  674. // for network in networks.iter() {
  675. // let keypairs_to_watch =
  676. // cashier_wallet.get_deposit_token_keys_by_network(&network.name)?;
  677. // for deposit_token in keypairs_to_watch {
  678. // let bridge = bridge.clone();
  679. // let bridge_subscribtion = bridge
  680. // .subscribe(
  681. // deposit_token.drk_public_key,
  682. // Some(deposit_token.mint_address),
  683. // executor.clone(),
  684. // )
  685. // .await;
  686. // bridge_subscribtion
  687. // .sender
  688. // .send(bridge::BridgeRequests {
  689. // network: network.name.clone(),
  690. // payload: bridge::BridgeRequestsPayload::Watch(Some(
  691. // deposit_token.token_key,
  692. // )),
  693. // })
  694. // .await?;
  695. // }
  696. // }
  697. // Ok(())
  698. // }