rpc.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use async_trait::async_trait;
  19. use log::debug;
  20. use serde_json::{json, Value};
  21. use darkfi::{
  22. net,
  23. rpc::{
  24. jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
  25. server::RequestHandler,
  26. },
  27. util::time::Timestamp,
  28. };
  29. use crate::Darkfid;
  30. #[async_trait]
  31. impl RequestHandler for Darkfid {
  32. async fn handle_request(&self, req: JsonRequest) -> JsonResult {
  33. if req.params.as_array().is_none() {
  34. return JsonError::new(ErrorCode::InvalidRequest, None, req.id).into()
  35. }
  36. let params = req.params.as_array().unwrap();
  37. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  38. match req.method.as_str() {
  39. // =====================
  40. // Miscellaneous methods
  41. // =====================
  42. Some("ping") => return self.pong(req.id, params).await,
  43. Some("clock") => return self.clock(req.id, params).await,
  44. Some("sync_dnet_switch") => return self.sync_dnet_switch(req.id, params).await,
  45. Some("sync_dnet_info") => return self.sync_dnet_info(req.id, params).await,
  46. Some("consensus_dnet_switch") => {
  47. return self.consensus_dnet_switch(req.id, params).await
  48. }
  49. Some("consensus_dnet_info") => return self.consensus_dnet_info(req.id, params).await,
  50. // ==================
  51. // Blockchain methods
  52. // ==================
  53. Some("blockchain.get_slot") => return self.blockchain_get_slot(req.id, params).await,
  54. Some("blockchain.get_tx") => return self.blockchain_get_tx(req.id, params).await,
  55. Some("blockchain.last_known_slot") => {
  56. return self.blockchain_last_known_slot(req.id, params).await
  57. }
  58. Some("blockchain.lookup_zkas") => {
  59. return self.blockchain_lookup_zkas(req.id, params).await
  60. }
  61. // ===================
  62. // Transaction methods
  63. // ===================
  64. Some("tx.simulate") => return self.tx_simulate(req.id, params).await,
  65. Some("tx.broadcast") => return self.tx_broadcast(req.id, params).await,
  66. // ==============
  67. // Invalid method
  68. // ==============
  69. Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
  70. }
  71. }
  72. }
  73. impl Darkfid {
  74. // RPCAPI:
  75. // Replies to a ping method.
  76. // --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
  77. // <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
  78. async fn pong(&self, id: Value, _params: &[Value]) -> JsonResult {
  79. JsonResponse::new(json!("pong"), id).into()
  80. }
  81. // RPCAPI:
  82. // Returns current system clock in `Timestamp` format.
  83. //
  84. // --> {"jsonrpc": "2.0", "method": "clock", "params": [], "id": 1}
  85. // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
  86. async fn clock(&self, id: Value, _params: &[Value]) -> JsonResult {
  87. JsonResponse::new(json!(Timestamp::current_time()), id).into()
  88. }
  89. // RPCAPI:
  90. // Activate or deactivate dnet in the sync P2P stack.
  91. // By sending `true`, dnet will be activated, and by sending `false` dnet
  92. // will be deactivated. Returns `true` on success.
  93. //
  94. // --> {"jsonrpc": "2.0", "method": "sync_dnet_switch", "params": [true], "id": 42}
  95. // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
  96. async fn sync_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
  97. if params.len() != 1 && params[0].as_bool().is_none() {
  98. return JsonError::new(ErrorCode::InvalidParams, None, id).into()
  99. }
  100. if params[0].as_bool().unwrap() {
  101. self.sync_p2p.dnet_enable().await;
  102. } else {
  103. self.sync_p2p.dnet_disable().await;
  104. }
  105. JsonResponse::new(json!(true), id).into()
  106. }
  107. // RPCAPI:
  108. // Retrieves sync P2P network information.
  109. //
  110. // --> {"jsonrpc": "2.0", "method": "sync_dnet_info", "params": [], "id": 42}
  111. // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
  112. async fn sync_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
  113. let dnet_info = self.sync_p2p.dnet_info().await;
  114. JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
  115. }
  116. // RPCAPI:
  117. // Activate or deactivate dnet in the consensus P2P stack.
  118. // By sending `true`, dnet will be activated, and by sending `false` dnet
  119. // will be deactivated. Returns `true` on success.
  120. //
  121. // --> {"jsonrpc": "2.0", "method": "consensus_dnet_switch", "params": [true], "id": 42}
  122. // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
  123. async fn consensus_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
  124. if params.len() != 1 && params[0].as_bool().is_none() {
  125. return JsonError::new(ErrorCode::InvalidParams, None, id).into()
  126. }
  127. if self.consensus_p2p.is_some() {
  128. if params[0].as_bool().unwrap() {
  129. self.consensus_p2p.clone().unwrap().dnet_enable().await;
  130. } else {
  131. self.consensus_p2p.clone().unwrap().dnet_disable().await;
  132. }
  133. }
  134. JsonResponse::new(json!(true), id).into()
  135. }
  136. // RPCAPI:
  137. // Retrieves consensus P2P network information.
  138. //
  139. // --> {"jsonrpc": "2.0", "method": "consensus_dnet_info", "params": [], "id": 42}
  140. // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
  141. async fn consensus_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
  142. let dnet_info = if self.consensus_p2p.is_some() {
  143. self.consensus_p2p.clone().unwrap().dnet_info().await
  144. } else {
  145. vec![]
  146. };
  147. JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
  148. }
  149. }