darkfid.rs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. use async_std::sync::{Arc, Mutex};
  2. use std::collections::HashMap;
  3. use std::convert::TryInto;
  4. use std::path::PathBuf;
  5. use std::str::FromStr;
  6. use async_executor::Executor;
  7. use async_trait::async_trait;
  8. use clap::clap_app;
  9. use easy_parallel::Parallel;
  10. use log::debug;
  11. use num_bigint::BigUint;
  12. use serde_json::{json, Value};
  13. use url::Url;
  14. use drk::{
  15. blockchain::{rocks::columns, Rocks, RocksColumn},
  16. cli::{Config, DarkfidConfig},
  17. client::{Client, State},
  18. crypto::{
  19. load_params, merkle::CommitmentTree, save_params, setup_mint_prover, setup_spend_prover,
  20. },
  21. rpc::{
  22. jsonrpc::{error as jsonerr, request as jsonreq, response as jsonresp, send_raw_request},
  23. jsonrpc::{ErrorCode::*, JsonRequest, JsonResult},
  24. rpcserver::{listen_and_serve, RequestHandler, RpcServerConfig},
  25. },
  26. serial::{deserialize, serialize},
  27. state::ProgramState,
  28. util::{
  29. assign_id, decode_base10, encode_base10, expand_path, join_config_path, DrkTokenList,
  30. NetworkName, TokenList,
  31. },
  32. wallet::WalletDb,
  33. Error, Result,
  34. };
  35. #[derive(Clone, Debug)]
  36. pub struct Cashier {
  37. pub name: String,
  38. pub rpc_url: String,
  39. pub public_key: jubjub::SubgroupPoint,
  40. }
  41. #[async_trait]
  42. impl RequestHandler for Darkfid {
  43. async fn handle_request(&self, req: JsonRequest, _executor: Arc<Executor<'_>>) -> JsonResult {
  44. if req.params.as_array().is_none() {
  45. return JsonResult::Err(jsonerr(InvalidParams, None, req.id));
  46. }
  47. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  48. if self.update_balances().await.is_err() {
  49. return JsonResult::Err(jsonerr(
  50. InternalError,
  51. Some("Unable to update balances".into()),
  52. req.id,
  53. ));
  54. }
  55. match req.method.as_str() {
  56. Some("say_hello") => return self.say_hello(req.id, req.params).await,
  57. Some("create_wallet") => return self.create_wallet(req.id, req.params).await,
  58. Some("key_gen") => return self.key_gen(req.id, req.params).await,
  59. Some("get_key") => return self.get_key(req.id, req.params).await,
  60. Some("get_balances") => return self.get_balances(req.id, req.params).await,
  61. Some("get_token_id") => return self.get_token_id(req.id, req.params).await,
  62. Some("features") => return self.features(req.id, req.params).await,
  63. Some("deposit") => return self.deposit(req.id, req.params).await,
  64. Some("withdraw") => return self.withdraw(req.id, req.params).await,
  65. Some("transfer") => return self.transfer(req.id, req.params).await,
  66. Some(_) | None => return JsonResult::Err(jsonerr(MethodNotFound, None, req.id)),
  67. };
  68. }
  69. }
  70. struct Darkfid {
  71. client: Arc<Mutex<Client>>,
  72. state: Arc<Mutex<State>>,
  73. sol_tokenlist: TokenList,
  74. drk_tokenlist: DrkTokenList,
  75. cashiers: Vec<Cashier>,
  76. }
  77. impl Darkfid {
  78. async fn new(
  79. client: Arc<Mutex<Client>>,
  80. state: Arc<Mutex<State>>,
  81. cashiers: Vec<Cashier>,
  82. ) -> Result<Self> {
  83. let sol_tokenlist = TokenList::new(include_bytes!("../../token/solana_token_list.json"))?;
  84. let drk_tokenlist = DrkTokenList::new(sol_tokenlist.clone())?;
  85. Ok(Self {
  86. client,
  87. state,
  88. sol_tokenlist,
  89. drk_tokenlist,
  90. cashiers,
  91. })
  92. }
  93. async fn start(&mut self, executor: Arc<Executor<'_>>) -> Result<()> {
  94. self.client.lock().await.start().await?;
  95. self.client
  96. .lock()
  97. .await
  98. .connect_to_subscriber(self.state.clone(), executor)
  99. .await?;
  100. Ok(())
  101. }
  102. async fn update_balances(&self) -> Result<()> {
  103. let own_coins = self.client.lock().await.get_own_coins()?;
  104. for own_coin in own_coins.iter() {
  105. let nullifier_exists = self
  106. .state
  107. .lock()
  108. .await
  109. .nullifier_exists(&own_coin.nullifier);
  110. if nullifier_exists {
  111. self.client
  112. .lock()
  113. .await
  114. .confirm_spend_coin(&own_coin.coin)?;
  115. }
  116. }
  117. Ok(())
  118. }
  119. // --> {"method": "say_hello", "params": []}
  120. // <-- {"result": "hello world"}
  121. async fn say_hello(&self, id: Value, _params: Value) -> JsonResult {
  122. JsonResult::Resp(jsonresp(json!("hello world"), id))
  123. }
  124. // --> {"method": "create_wallet", "params": []}
  125. // <-- {"result": true}
  126. async fn create_wallet(&self, id: Value, _params: Value) -> JsonResult {
  127. match self.client.lock().await.init_db().await {
  128. Ok(()) => JsonResult::Resp(jsonresp(json!(true), id)),
  129. Err(e) => JsonResult::Err(jsonerr(ServerError(-32001), Some(e.to_string()), id)),
  130. }
  131. }
  132. // --> {"method": "key_gen", "params": []}
  133. // <-- {"result": true}
  134. async fn key_gen(&self, id: Value, _params: Value) -> JsonResult {
  135. match self.client.lock().await.key_gen() {
  136. Ok(()) => JsonResult::Resp(jsonresp(json!(true), id)),
  137. Err(e) => JsonResult::Err(jsonerr(ServerError(-32002), Some(e.to_string()), id)),
  138. }
  139. }
  140. // --> {"method": "get_key", "params": []}
  141. // <-- {"result": "vdNS7oBj7KvsMWWmo9r96SV4SqATLrGsH2a3PGpCfJC"}
  142. async fn get_key(&self, id: Value, _params: Value) -> JsonResult {
  143. let pk = self.client.lock().await.main_keypair.public;
  144. let b58 = bs58::encode(serialize(&pk)).into_string();
  145. JsonResult::Resp(jsonresp(json!(b58), id))
  146. }
  147. // --> {"method": "get_balances", "params": []}
  148. // <-- {"result": "get_balances": "[ {"btc": (value, network)}, .. ]"}
  149. async fn get_balances(&self, id: Value, _params: Value) -> JsonResult {
  150. let result: Result<HashMap<String, (String, String)>> = async {
  151. let balances = self.client.lock().await.get_balances()?;
  152. let mut symbols: HashMap<String, (String, String)> = HashMap::new();
  153. for balance in balances.list.iter() {
  154. // XXX: this must be changed once cashierd
  155. // supports more than two networks
  156. let mut network = "solana";
  157. if balance.token_id.to_string()
  158. == "0x01300f9bce0f9ba7168dc001a67bcbda3a5bf4bdb4c56ae900fe4698cee9a7bd"
  159. {
  160. network = "bitcoin"
  161. }
  162. if let Some(symbol) = self.drk_tokenlist.symbol_from_id(balance.token_id)? {
  163. let amount = encode_base10(BigUint::from(balance.value), 8);
  164. symbols.insert(symbol, (amount, network.to_string()));
  165. }
  166. }
  167. Ok(symbols)
  168. }
  169. .await;
  170. match result {
  171. Ok(res) => JsonResult::Resp(jsonresp(json!(res), id)),
  172. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  173. }
  174. }
  175. // --> {"method": "get_token_id", "params": [network, token]}
  176. // <-- {"result": "Ht5G1RhkcKnpLVLMhqJc5aqZ4wYUEbxbtZwGCVbgU7DL"}
  177. async fn get_token_id(&self, id: Value, params: Value) -> JsonResult {
  178. let args = params.as_array();
  179. if args.is_none() {
  180. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  181. }
  182. let args = args.unwrap();
  183. if args.len() != 2 {
  184. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  185. }
  186. let network: &str;
  187. let symbol: &str;
  188. match (args[0].as_str(), args[1].as_str()) {
  189. (Some(net), Some(sym)) => {
  190. network = net;
  191. symbol = sym;
  192. }
  193. (None, _) => {
  194. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id));
  195. }
  196. (_, None) => {
  197. return JsonResult::Err(jsonerr(InvalidSymbolParam, None, id));
  198. }
  199. }
  200. let result: Result<Value> = async {
  201. let network = NetworkName::from_str(network)?;
  202. match network {
  203. #[cfg(feature = "sol")]
  204. NetworkName::Solana => {
  205. let token_id = self.sol_tokenlist.search_id(symbol)?;
  206. Ok(json!(token_id))
  207. }
  208. #[cfg(feature = "btc")]
  209. NetworkName::Bitcoin => {
  210. //hardcoded genesis coinbase address
  211. let token_id = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa".to_string();
  212. Ok(json!(token_id))
  213. }
  214. _ => Err(Error::NotSupportedNetwork),
  215. }
  216. }
  217. .await;
  218. match result {
  219. Ok(res) => JsonResult::Resp(jsonresp(json!(res), id)),
  220. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  221. }
  222. }
  223. // --> {""method": "features", "params": []}
  224. // <-- {"result": { "network": ["btc", "sol"] } }
  225. async fn features(&self, id: Value, _params: Value) -> JsonResult {
  226. let req = jsonreq(json!("features"), json!([]));
  227. let rep: JsonResult;
  228. // NOTE: this just selects the first cashier in the list
  229. match send_raw_request(&self.cashiers[0].rpc_url, json!(req)).await {
  230. Ok(v) => rep = v,
  231. Err(e) => {
  232. return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id))
  233. }
  234. }
  235. match rep {
  236. JsonResult::Resp(r) => JsonResult::Resp(r),
  237. JsonResult::Err(e) => JsonResult::Err(e),
  238. JsonResult::Notif(_) => JsonResult::Err(jsonerr(InternalError, None, id)),
  239. }
  240. }
  241. // --> {"method": "deposit", "params": [network, token, publickey]}
  242. // The publickey sent here is used so the cashier can know where to send
  243. // tokens once the deposit is received.
  244. // <-- {"result": "Ht5G1RhkcKnpLVLMhqJc5aqZ4wYUEbxbtZwGCVbgU7DL"}
  245. async fn deposit(&self, id: Value, params: Value) -> JsonResult {
  246. let args = params.as_array();
  247. if args.is_none() {
  248. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  249. }
  250. let args = args.unwrap();
  251. if args.len() != 2 {
  252. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  253. }
  254. let network: &str;
  255. let token: &str;
  256. match (args[0].as_str(), args[1].as_str()) {
  257. (Some(net), Some(tkn)) => {
  258. network = net;
  259. token = tkn;
  260. }
  261. (None, _) => {
  262. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id));
  263. }
  264. (_, None) => {
  265. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id));
  266. }
  267. }
  268. let token_id = match assign_id(network, token, &self.sol_tokenlist) {
  269. Ok(t) => t,
  270. Err(e) => {
  271. return JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id));
  272. }
  273. };
  274. // TODO: Optional sanity checking here, but cashier *must* do so too.
  275. let pk = self.client.lock().await.main_keypair.public;
  276. let pubkey = bs58::encode(serialize(&pk)).into_string();
  277. // Send request to cashier. If the cashier supports the requested network
  278. // (and token), it shall return a valid address where tokens can be deposited.
  279. // If not, an error is returned, and forwarded to the method caller.
  280. let req = jsonreq(json!("deposit"), json!([network, token_id, pubkey]));
  281. let rep: JsonResult;
  282. match send_raw_request(&self.cashiers[0].rpc_url, json!(req)).await {
  283. Ok(v) => rep = v,
  284. Err(e) => {
  285. debug!(target: "DARKFID", "REQUEST IS ERR");
  286. return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id));
  287. }
  288. }
  289. match rep {
  290. JsonResult::Resp(r) => JsonResult::Resp(r),
  291. JsonResult::Err(e) => JsonResult::Err(e),
  292. JsonResult::Notif(_n) => JsonResult::Err(jsonerr(InternalError, None, id)),
  293. }
  294. }
  295. // --> {"method": "withdraw", "params": [network, token, publickey, amount]}
  296. // The publickey sent here is the address where the caller wants to receive
  297. // the tokens they plan to withdraw.
  298. // On request, send request to cashier to get deposit address, and then transfer
  299. // dark tokens to the cashier's wallet. Following that, the cashier should return
  300. // a transaction ID of them sending the funds that are requested for withdrawal.
  301. // <-- {"result": "txID"}
  302. async fn withdraw(&self, id: Value, params: Value) -> JsonResult {
  303. let args = params.as_array();
  304. if args.is_none() {
  305. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  306. }
  307. let args = args.unwrap();
  308. if args.len() != 4 {
  309. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  310. }
  311. let network: &str;
  312. let token: &str;
  313. let address: &str;
  314. let amount: &str;
  315. match (
  316. args[0].as_str(),
  317. args[1].as_str(),
  318. args[2].as_str(),
  319. args[3].as_str(),
  320. ) {
  321. (Some(net), Some(tkn), Some(addr), Some(val)) => {
  322. network = net;
  323. token = tkn;
  324. address = addr;
  325. amount = val;
  326. }
  327. (None, _, _, _) => {
  328. return JsonResult::Err(jsonerr(InvalidNetworkParam, None, id));
  329. }
  330. (_, None, _, _) => {
  331. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id));
  332. }
  333. (_, _, None, _) => {
  334. return JsonResult::Err(jsonerr(InvalidAddressParam, None, id));
  335. }
  336. (_, _, _, None) => {
  337. return JsonResult::Err(jsonerr(InvalidAmountParam, None, id));
  338. }
  339. }
  340. let amount_in_apo = match decode_base10(amount, 8, true) {
  341. Ok(a) => a,
  342. Err(e) => {
  343. return JsonResult::Err(jsonerr(InvalidAmountParam, Some(e.to_string()), id));
  344. }
  345. };
  346. let token_id = match assign_id(network, token, &self.sol_tokenlist) {
  347. Ok(t) => t,
  348. Err(e) => {
  349. return JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id));
  350. }
  351. };
  352. let req = jsonreq(
  353. json!("withdraw"),
  354. json!([network, token_id, address, amount_in_apo]),
  355. );
  356. let mut rep: JsonResult;
  357. match send_raw_request(&self.cashiers[0].rpc_url, json!(req)).await {
  358. Ok(v) => rep = v,
  359. Err(e) => {
  360. return JsonResult::Err(jsonerr(ServerError(-32004), Some(e.to_string()), id));
  361. }
  362. }
  363. let token_id: &jubjub::Fr;
  364. // get the id for the token
  365. if let Some(tk_id) = self.drk_tokenlist.tokens.get(&token.to_uppercase()) {
  366. token_id = tk_id;
  367. } else {
  368. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  369. }
  370. // send drk to cashier_public
  371. if let JsonResult::Resp(cashier_public) = &rep {
  372. let result: Result<()> = async {
  373. let cashier_public = cashier_public.result.as_str().unwrap();
  374. let cashier_public: jubjub::SubgroupPoint =
  375. deserialize(&bs58::decode(cashier_public).into_vec()?)?;
  376. self.client
  377. .lock()
  378. .await
  379. .transfer(
  380. *token_id,
  381. cashier_public,
  382. amount_in_apo.try_into()?,
  383. self.state.clone(),
  384. )
  385. .await?;
  386. Ok(())
  387. }
  388. .await;
  389. match result {
  390. Err(e) => {
  391. rep = JsonResult::Err(jsonerr(InternalError, Some(e.to_string()), id.clone()))
  392. }
  393. Ok(_) => {
  394. rep = JsonResult::Resp(jsonresp(
  395. json!(format!(
  396. "Sent request to withdraw {} amount of {}",
  397. amount, token_id
  398. )),
  399. id.clone(),
  400. ))
  401. }
  402. }
  403. };
  404. match rep {
  405. JsonResult::Resp(r) => JsonResult::Resp(r),
  406. JsonResult::Err(e) => JsonResult::Err(e),
  407. JsonResult::Notif(_n) => JsonResult::Err(jsonerr(InternalError, None, id)),
  408. }
  409. }
  410. // --> {"method": "transfer", [dToken, address, amount]}
  411. // <-- {"result": "txID"}
  412. async fn transfer(&self, id: Value, params: Value) -> JsonResult {
  413. let args = params.as_array();
  414. if args.is_none() {
  415. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  416. }
  417. let args = args.unwrap();
  418. if args.len() != 3 {
  419. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  420. }
  421. let token: &str;
  422. let address: &str;
  423. let amount: &str;
  424. match (args[0].as_str(), args[1].as_str(), args[2].as_str()) {
  425. (Some(tkn), Some(addr), Some(val)) => {
  426. token = tkn;
  427. address = addr;
  428. amount = val;
  429. }
  430. (None, _, _) => {
  431. return JsonResult::Err(jsonerr(InvalidTokenIdParam, None, id));
  432. }
  433. (_, None, _) => {
  434. return JsonResult::Err(jsonerr(InvalidAddressParam, None, id));
  435. }
  436. (_, _, None) => {
  437. return JsonResult::Err(jsonerr(InvalidAmountParam, None, id));
  438. }
  439. }
  440. let token_id: &jubjub::Fr;
  441. // get the id for the token
  442. if let Some(tk_id) = self.drk_tokenlist.tokens.get(&token.to_uppercase()) {
  443. token_id = tk_id;
  444. } else {
  445. return JsonResult::Err(jsonerr(InvalidParams, None, id));
  446. }
  447. let result: Result<()> = async {
  448. let drk_address = bs58::decode(&address).into_vec()?;
  449. let drk_address: jubjub::SubgroupPoint = deserialize(&drk_address)?;
  450. let decimals: usize = 8;
  451. let amount = decode_base10(amount, decimals, true)?;
  452. self.client
  453. .lock()
  454. .await
  455. .transfer(
  456. *token_id,
  457. drk_address,
  458. amount.try_into()?,
  459. self.state.clone(),
  460. )
  461. .await?;
  462. Ok(())
  463. }
  464. .await;
  465. match result {
  466. Ok(_) => JsonResult::Resp(jsonresp(json!("Success"), id)),
  467. Err(err) => JsonResult::Err(jsonerr(InternalError, Some(err.to_string()), json!(id))),
  468. }
  469. }
  470. }
  471. async fn start(
  472. executor: Arc<Executor<'_>>,
  473. local_cashier: Option<&str>,
  474. config: &DarkfidConfig,
  475. ) -> Result<()> {
  476. let wallet = WalletDb::new(
  477. expand_path(&config.wallet_path)?.as_path(),
  478. config.wallet_password.clone(),
  479. )?;
  480. let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
  481. let mut cashiers = Vec::new();
  482. let mut cashier_keys = Vec::new();
  483. if let Some(cpub) = local_cashier {
  484. let cashier_public: jubjub::SubgroupPoint = deserialize(&bs58::decode(cpub).into_vec()?)?;
  485. cashiers.push(Cashier {
  486. name: "localCashier".into(),
  487. rpc_url: "tcp://127.0.0.1:9000".into(),
  488. public_key: cashier_public,
  489. });
  490. cashier_keys.push(cashier_public);
  491. } else {
  492. for cashier in config.clone().cashiers {
  493. if cashier.public_key.is_empty() {
  494. return Err(Error::CashierKeysNotFound);
  495. }
  496. let cashier_public: jubjub::SubgroupPoint =
  497. deserialize(&bs58::decode(cashier.public_key).into_vec()?)?;
  498. cashiers.push(Cashier {
  499. name: cashier.name,
  500. rpc_url: cashier.rpc_url,
  501. public_key: cashier_public,
  502. });
  503. cashier_keys.push(cashier_public);
  504. }
  505. }
  506. // Load trusted setup parameters
  507. let params_paths = (
  508. expand_path(&config.mint_params_path.clone())?,
  509. expand_path(&config.spend_params_path.clone())?,
  510. );
  511. let mint_params_path = params_paths.0.to_str().unwrap_or("mint.params");
  512. let spend_params_path = params_paths.1.to_str().unwrap_or("spend.params");
  513. // Auto create trusted ceremony parameters if they don't exist
  514. if !params_paths.0.exists() {
  515. let params = setup_mint_prover();
  516. save_params(mint_params_path, &params)?;
  517. }
  518. if !params_paths.1.exists() {
  519. let params = setup_spend_prover();
  520. save_params(spend_params_path, &params)?;
  521. }
  522. let (mint_params, mint_pvk) = load_params(mint_params_path)?;
  523. let (spend_params, spend_pvk) = load_params(spend_params_path)?;
  524. let client = Client::new(
  525. rocks.clone(),
  526. (
  527. Url::parse(&config.gateway_protocol_url)?,
  528. Url::parse(&config.gateway_publisher_url)?,
  529. ),
  530. wallet.clone(),
  531. mint_params,
  532. spend_params,
  533. )
  534. .await?;
  535. let client = Arc::new(Mutex::new(client));
  536. let merkle_roots = RocksColumn::<columns::MerkleRoots>::new(rocks.clone());
  537. let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
  538. let state = Arc::new(Mutex::new(State {
  539. tree: CommitmentTree::empty(),
  540. merkle_roots,
  541. nullifiers,
  542. mint_pvk,
  543. spend_pvk,
  544. public_keys: cashier_keys,
  545. }));
  546. let mut darkfid = Darkfid::new(client, state, cashiers).await?;
  547. let server_config = RpcServerConfig {
  548. socket_addr: config.rpc_listen_address,
  549. use_tls: config.serve_tls,
  550. identity_path: expand_path(&config.tls_identity_path.clone())?,
  551. identity_pass: config.tls_identity_password.clone(),
  552. };
  553. darkfid.start(executor.clone()).await?;
  554. listen_and_serve(server_config, Arc::new(darkfid), executor).await
  555. }
  556. #[async_std::main]
  557. async fn main() -> Result<()> {
  558. let args = clap_app!(darkfid =>
  559. (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
  560. (@arg verbose: -v --verbose "Increase verbosity")
  561. (@arg refresh: -r --refresh "Refresh the wallet and slabstore")
  562. (@arg cashier: --cashier +takes_value "Local cashier public key")
  563. )
  564. .get_matches();
  565. let config_path = if args.is_present("CONFIG") {
  566. expand_path(args.value_of("CONFIG").unwrap())?
  567. } else {
  568. join_config_path(&PathBuf::from("darkfid.toml"))?
  569. };
  570. let loglevel = if args.is_present("verbose") {
  571. log::Level::Debug
  572. } else {
  573. log::Level::Info
  574. };
  575. simple_logger::init_with_level(loglevel)?;
  576. let config: DarkfidConfig = Config::<DarkfidConfig>::load(config_path)?;
  577. if args.is_present("refresh") {
  578. debug!(target: "DARKFI DAEMON", "Refresh the wallet and the database");
  579. let wallet = WalletDb::new(
  580. expand_path(&config.wallet_path)?.as_path(),
  581. config.wallet_password.clone(),
  582. )?;
  583. wallet.remove_own_coins()?;
  584. if let Some(path) = expand_path(&config.database_path)?.to_str() {
  585. debug!(target: "DARKFI DAEMON", "Remove database: {}", path);
  586. std::fs::remove_dir_all(path)?;
  587. }
  588. println!("Wallet got updated successfully.");
  589. return Ok(());
  590. }
  591. let mut local_cashier: Option<&str> = None;
  592. if args.is_present("cashier") {
  593. local_cashier = Some(args.value_of("cashier").unwrap())
  594. }
  595. let ex = Arc::new(Executor::new());
  596. let (signal, shutdown) = async_channel::unbounded::<()>();
  597. let ex2 = ex.clone();
  598. let nthreads = num_cpus::get();
  599. debug!(target: "DARKFI DAEMON", "Run {} executor threads", nthreads);
  600. let (_, result) = Parallel::new()
  601. .each(0..nthreads, |_| {
  602. smol::future::block_on(ex.run(shutdown.recv()))
  603. })
  604. // Run the main future on the current thread.
  605. .finish(|| {
  606. smol::future::block_on(async move {
  607. start(ex2, local_cashier, &config).await?;
  608. drop(signal);
  609. Ok::<(), drk::Error>(())
  610. })
  611. });
  612. result
  613. }