darkfid.rs 27 KB

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