rpc.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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: "darkfid::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. Some("blockchain.subscribe_blocks") => {
  62. return self.blockchain_subscribe_blocks(req.id, params).await
  63. }
  64. Some("blockchain.subscribe_txs") => {
  65. return self.blockchain_subscribe_txs(req.id, params).await
  66. }
  67. Some("blockchain.subscribe_proposals") => {
  68. return self.blockchain_subscribe_proposals(req.id, params).await
  69. }
  70. // ===================
  71. // Transaction methods
  72. // ===================
  73. Some("tx.simulate") => return self.tx_simulate(req.id, params).await,
  74. Some("tx.broadcast") => return self.tx_broadcast(req.id, params).await,
  75. Some("tx.pending") => return self.tx_pending(req.id, params).await,
  76. Some("tx.clean_pending") => return self.tx_pending(req.id, params).await,
  77. // ==============
  78. // Invalid method
  79. // ==============
  80. Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
  81. }
  82. }
  83. }
  84. impl Darkfid {
  85. // RPCAPI:
  86. // Replies to a ping method.
  87. // --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
  88. // <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
  89. async fn pong(&self, id: Value, _params: &[Value]) -> JsonResult {
  90. JsonResponse::new(json!("pong"), id).into()
  91. }
  92. // RPCAPI:
  93. // Returns current system clock in `Timestamp` format.
  94. //
  95. // --> {"jsonrpc": "2.0", "method": "clock", "params": [], "id": 1}
  96. // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
  97. async fn clock(&self, id: Value, _params: &[Value]) -> JsonResult {
  98. JsonResponse::new(json!(Timestamp::current_time()), id).into()
  99. }
  100. // RPCAPI:
  101. // Activate or deactivate dnet in the sync P2P stack.
  102. // By sending `true`, dnet will be activated, and by sending `false` dnet
  103. // will be deactivated. Returns `true` on success.
  104. //
  105. // --> {"jsonrpc": "2.0", "method": "sync_dnet_switch", "params": [true], "id": 42}
  106. // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
  107. async fn sync_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
  108. if params.len() != 1 && params[0].as_bool().is_none() {
  109. return JsonError::new(ErrorCode::InvalidParams, None, id).into()
  110. }
  111. if params[0].as_bool().unwrap() {
  112. self.sync_p2p.dnet_enable().await;
  113. } else {
  114. self.sync_p2p.dnet_disable().await;
  115. }
  116. JsonResponse::new(json!(true), id).into()
  117. }
  118. // RPCAPI:
  119. // Retrieves sync P2P network information.
  120. //
  121. // --> {"jsonrpc": "2.0", "method": "sync_dnet_info", "params": [], "id": 42}
  122. // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
  123. async fn sync_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
  124. let dnet_info = self.sync_p2p.dnet_info().await;
  125. JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
  126. }
  127. // RPCAPI:
  128. // Activate or deactivate dnet in the consensus P2P stack.
  129. // By sending `true`, dnet will be activated, and by sending `false` dnet
  130. // will be deactivated. Returns `true` on success.
  131. //
  132. // --> {"jsonrpc": "2.0", "method": "consensus_dnet_switch", "params": [true], "id": 42}
  133. // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
  134. async fn consensus_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
  135. if params.len() != 1 && params[0].as_bool().is_none() {
  136. return JsonError::new(ErrorCode::InvalidParams, None, id).into()
  137. }
  138. if self.consensus_p2p.is_some() {
  139. if params[0].as_bool().unwrap() {
  140. self.consensus_p2p.clone().unwrap().dnet_enable().await;
  141. } else {
  142. self.consensus_p2p.clone().unwrap().dnet_disable().await;
  143. }
  144. }
  145. JsonResponse::new(json!(true), id).into()
  146. }
  147. // RPCAPI:
  148. // Retrieves consensus P2P network information.
  149. //
  150. // --> {"jsonrpc": "2.0", "method": "consensus_dnet_info", "params": [], "id": 42}
  151. // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
  152. async fn consensus_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
  153. let dnet_info = if self.consensus_p2p.is_some() {
  154. self.consensus_p2p.clone().unwrap().dnet_info().await
  155. } else {
  156. vec![]
  157. };
  158. JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
  159. }
  160. }