Răsfoiți Sursa

darkfid2: Update to new RPC dependencies.

parazyd 3 ani în urmă
părinte
comite
f85d0d6c46

+ 2 - 2
bin/darkfid/src/rpc_blockchain.rs

@@ -90,10 +90,10 @@ impl Darkfid {
     //
     // **Returns:**
     // * Serialized [`Transaction`](https://darkrenaissance.github.io/darkfi/development/darkfi/tx/struct.Transaction.html)
-    //   object
+    //   object encoded with base64
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.get_tx", "params": ["TxHash"], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
+    // <-- {"jsonrpc": "2.0", "result": "ABCD...", "id": 1}
     pub async fn blockchain_get_tx(&self, id: u16, params: JsonValue) -> JsonResult {
         let params = params.get::<Vec<JsonValue>>().unwrap();
         if params.len() != 1 || !params[0].is_string() {

+ 1 - 1
bin/darkfid2/Cargo.toml

@@ -25,7 +25,7 @@ sled = "0.34.7"
 
 # JSON-RPC
 async-trait = "0.1.73"
-serde_json = "1.0.105"
+tinyjson = "2.5.1"
 url = "2.4.0"
 
 # Daemon

+ 3 - 5
bin/darkfid2/src/error.rs

@@ -16,8 +16,6 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use serde_json::Value;
-
 use darkfi::rpc::jsonrpc::{ErrorCode::ServerError, JsonError, JsonResult};
 
 /// Custom RPC errors available for darkfid.
@@ -38,7 +36,7 @@ pub enum RpcError {
     ContractZkasDbNotFound = -32200,
 }
 
-fn to_tuple(e: RpcError) -> (i64, String) {
+fn to_tuple(e: RpcError) -> (i32, String) {
     let msg = match e {
         // Transaction-related errors
         RpcError::TxSimulationFail => "Failed simulating transaction state change",
@@ -52,10 +50,10 @@ fn to_tuple(e: RpcError) -> (i64, String) {
         RpcError::ContractZkasDbNotFound => "zkas database not found for given contract",
     };
 
-    (e as i64, msg.to_string())
+    (e as i32, msg.to_string())
 }
 
-pub fn server_error(e: RpcError, id: Value, msg: Option<&str>) -> JsonResult {
+pub fn server_error(e: RpcError, id: u16, msg: Option<&str>) -> JsonResult {
     let (code, default_msg) = to_tuple(e);
 
     if let Some(message) = msg {

+ 6 - 7
bin/darkfid2/src/main.rs

@@ -28,7 +28,7 @@ use darkfi::{
     blockchain::BlockInfo,
     cli_desc,
     net::{settings::SettingsOpt, P2pPtr},
-    rpc::{jsonrpc::MethodSubscriber, server::listen_and_serve},
+    rpc::{jsonrpc::JsonSubscriber, server::listen_and_serve},
     util::time::TimeKeeper,
     validator::{Validator, ValidatorConfig, ValidatorPtr},
     Result,
@@ -110,7 +110,7 @@ pub struct Darkfid {
     /// Validator(node) pointer
     validator: ValidatorPtr,
     /// A map of various subscribers exporting live info from the blockchain
-    subscribers: HashMap<&'static str, MethodSubscriber>,
+    subscribers: HashMap<&'static str, JsonSubscriber>,
 }
 
 impl Darkfid {
@@ -118,7 +118,7 @@ impl Darkfid {
         sync_p2p: P2pPtr,
         consensus_p2p: Option<P2pPtr>,
         validator: ValidatorPtr,
-        subscribers: HashMap<&'static str, MethodSubscriber>,
+        subscribers: HashMap<&'static str, JsonSubscriber>,
     ) -> Self {
         Self { sync_p2p, consensus_p2p, validator, subscribers }
     }
@@ -157,11 +157,10 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'_>>) -> Result<()> {
 
     // Here we initialize various subscribers that can export live blockchain/consensus data.
     let mut subscribers = HashMap::new();
-    subscribers.insert("blocks", MethodSubscriber::new("blockchain.subscribe_blocks".into()));
-    subscribers.insert("txs", MethodSubscriber::new("blockchain.subscribe_txs".into()));
+    subscribers.insert("blocks", JsonSubscriber::new("blockchain.subscribe_blocks"));
+    subscribers.insert("txs", JsonSubscriber::new("blockchain.subscribe_txs"));
     if args.consensus {
-        subscribers
-            .insert("proposals", MethodSubscriber::new("blockchain.subscribe_proposals".into()));
+        subscribers.insert("proposals", JsonSubscriber::new("blockchain.subscribe_proposals"));
     }
 
     // Initialize syncing P2P network

+ 4 - 4
bin/darkfid2/src/proto/protocol_block.rs

@@ -29,7 +29,7 @@ use darkfi::{
         ChannelPtr, Message, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
         ProtocolJobsManager, ProtocolJobsManagerPtr,
     },
-    rpc::jsonrpc::MethodSubscriber,
+    rpc::jsonrpc::JsonSubscriber,
     validator::ValidatorPtr,
     Result,
 };
@@ -53,7 +53,7 @@ pub struct ProtocolBlock {
     validator: ValidatorPtr,
     p2p: P2pPtr,
     channel_address: Url,
-    subscriber: MethodSubscriber,
+    subscriber: JsonSubscriber,
 }
 
 impl ProtocolBlock {
@@ -61,7 +61,7 @@ impl ProtocolBlock {
         channel: ChannelPtr,
         validator: ValidatorPtr,
         p2p: P2pPtr,
-        subscriber: MethodSubscriber,
+        subscriber: JsonSubscriber,
     ) -> Result<ProtocolBasePtr> {
         debug!(
             target: "validator::protocol_block::init",
@@ -124,7 +124,7 @@ impl ProtocolBlock {
             match self.validator.write().await.append_block(&block_copy.0).await {
                 Ok(()) => {
                     self.p2p.broadcast_with_exclude(&block_copy, &exclude_list).await;
-                    self.subscriber.notify(&block_copy).await;
+                    self.subscriber.notify(&[block_copy]).await;
                 }
                 Err(e) => {
                     debug!(

+ 4 - 4
bin/darkfid2/src/proto/protocol_proposal.rs

@@ -28,7 +28,7 @@ use darkfi::{
         ChannelPtr, Message, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
         ProtocolJobsManager, ProtocolJobsManagerPtr,
     },
-    rpc::jsonrpc::MethodSubscriber,
+    rpc::jsonrpc::JsonSubscriber,
     validator::{consensus::Proposal, ValidatorPtr},
     Result,
 };
@@ -46,7 +46,7 @@ pub struct ProtocolProposal {
     validator: ValidatorPtr,
     p2p: P2pPtr,
     channel_address: Url,
-    subscriber: MethodSubscriber,
+    subscriber: JsonSubscriber,
 }
 
 impl ProtocolProposal {
@@ -54,7 +54,7 @@ impl ProtocolProposal {
         channel: ChannelPtr,
         validator: ValidatorPtr,
         p2p: P2pPtr,
-        subscriber: MethodSubscriber,
+        subscriber: JsonSubscriber,
     ) -> Result<ProtocolBasePtr> {
         debug!(
             target: "validator::protocol_proposal::init",
@@ -114,7 +114,7 @@ impl ProtocolProposal {
             match self.validator.write().await.consensus.append_proposal(&proposal_copy.0).await {
                 Ok(()) => {
                     self.p2p.broadcast_with_exclude(&proposal_copy, &exclude_list).await;
-                    self.subscriber.notify(&proposal_copy).await;
+                    self.subscriber.notify(&[proposal_copy]).await;
                 }
                 Err(e) => {
                     debug!(

+ 4 - 4
bin/darkfid2/src/proto/protocol_tx.rs

@@ -28,7 +28,7 @@ use darkfi::{
         ChannelPtr, Message, MessageSubscription, P2pPtr, ProtocolBase, ProtocolBasePtr,
         ProtocolJobsManager, ProtocolJobsManagerPtr,
     },
-    rpc::jsonrpc::MethodSubscriber,
+    rpc::jsonrpc::JsonSubscriber,
     tx::Transaction,
     validator::ValidatorPtr,
     Result,
@@ -47,7 +47,7 @@ pub struct ProtocolTx {
     validator: ValidatorPtr,
     p2p: P2pPtr,
     channel_address: Url,
-    subscriber: MethodSubscriber,
+    subscriber: JsonSubscriber,
 }
 
 impl ProtocolTx {
@@ -55,7 +55,7 @@ impl ProtocolTx {
         channel: ChannelPtr,
         validator: ValidatorPtr,
         p2p: P2pPtr,
-        subscriber: MethodSubscriber,
+        subscriber: JsonSubscriber,
     ) -> Result<ProtocolBasePtr> {
         debug!(
             target: "validator::protocol_tx::init",
@@ -110,7 +110,7 @@ impl ProtocolTx {
             match self.validator.write().await.append_tx(&tx_copy.0).await {
                 Ok(()) => {
                     self.p2p.broadcast_with_exclude(&tx_copy, &exclude_list).await;
-                    self.subscriber.notify(&tx_copy).await;
+                    self.subscriber.notify(&[tx_copy]).await;
                 }
                 Err(e) => {
                     debug!(

+ 40 - 78
bin/darkfid2/src/rpc.rs

@@ -18,10 +18,9 @@
 
 use async_trait::async_trait;
 use log::debug;
-use serde_json::{json, Value};
+use tinyjson::JsonValue;
 
 use darkfi::{
-    net,
     rpc::{
         jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
         server::RequestHandler,
@@ -34,80 +33,62 @@ use crate::Darkfid;
 #[async_trait]
 impl RequestHandler for Darkfid {
     async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        if req.params.as_array().is_none() {
-            return JsonError::new(ErrorCode::InvalidRequest, None, req.id).into()
-        }
-
-        let params = req.params.as_array().unwrap();
-
-        debug!(target: "darkfid::rpc", "--> {}", serde_json::to_string(&req).unwrap());
+        debug!(target: "darkfid::rpc", "--> {}", req.stringify().unwrap());
 
         match req.method.as_str() {
             // =====================
             // Miscellaneous methods
             // =====================
-            Some("ping") => return self.pong(req.id, params).await,
-            Some("clock") => return self.clock(req.id, params).await,
-            Some("sync_dnet_switch") => return self.sync_dnet_switch(req.id, params).await,
-            Some("sync_dnet_info") => return self.sync_dnet_info(req.id, params).await,
-            Some("consensus_dnet_switch") => {
-                return self.consensus_dnet_switch(req.id, params).await
-            }
-            Some("consensus_dnet_info") => return self.consensus_dnet_info(req.id, params).await,
+            "ping" => return self.pong(req.id, req.params).await,
+            "clock" => return self.clock(req.id, req.params).await,
+            "sync_dnet_switch" => return self.sync_dnet_switch(req.id, req.params).await,
+            "consensus_dnet_switch" => return self.consensus_dnet_switch(req.id, req.params).await,
 
             // ==================
             // Blockchain methods
             // ==================
-            Some("blockchain.get_slot") => return self.blockchain_get_slot(req.id, params).await,
-            Some("blockchain.get_tx") => return self.blockchain_get_tx(req.id, params).await,
-            Some("blockchain.last_known_slot") => {
-                return self.blockchain_last_known_slot(req.id, params).await
+            "blockchain.get_slot" => return self.blockchain_get_slot(req.id, req.params).await,
+            "blockchain.get_tx" => return self.blockchain_get_tx(req.id, req.params).await,
+            "blockchain.last_known_slot" => {
+                return self.blockchain_last_known_slot(req.id, req.params).await
             }
-            Some("blockchain.lookup_zkas") => {
-                return self.blockchain_lookup_zkas(req.id, params).await
+            "blockchain.lookup_zkas" => {
+                return self.blockchain_lookup_zkas(req.id, req.params).await
             }
-            Some("blockchain.subscribe_blocks") => {
-                return self.blockchain_subscribe_blocks(req.id, params).await
+            "blockchain.subscribe_blocks" => {
+                return self.blockchain_subscribe_blocks(req.id, req.params).await
             }
-            Some("blockchain.subscribe_txs") => {
-                return self.blockchain_subscribe_txs(req.id, params).await
+            "blockchain.subscribe_txs" => {
+                return self.blockchain_subscribe_txs(req.id, req.params).await
             }
-            Some("blockchain.subscribe_proposals") => {
-                return self.blockchain_subscribe_proposals(req.id, params).await
+            "blockchain.subscribe_proposals" => {
+                return self.blockchain_subscribe_proposals(req.id, req.params).await
             }
 
             // ===================
             // Transaction methods
             // ===================
-            Some("tx.simulate") => return self.tx_simulate(req.id, params).await,
-            Some("tx.broadcast") => return self.tx_broadcast(req.id, params).await,
-            Some("tx.pending") => return self.tx_pending(req.id, params).await,
-            Some("tx.clean_pending") => return self.tx_pending(req.id, params).await,
+            "tx.simulate" => return self.tx_simulate(req.id, req.params).await,
+            "tx.broadcast" => return self.tx_broadcast(req.id, req.params).await,
+            "tx.pending" => return self.tx_pending(req.id, req.params).await,
+            "tx.clean_pending" => return self.tx_pending(req.id, req.params).await,
 
             // ==============
             // Invalid method
             // ==============
-            Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
+            _ => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
         }
     }
 }
 
 impl Darkfid {
     // RPCAPI:
-    // Replies to a ping method.
-    // --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
-    async fn pong(&self, id: Value, _params: &[Value]) -> JsonResult {
-        JsonResponse::new(json!("pong"), id).into()
-    }
-
-    // RPCAPI:
-    // Returns current system clock in `Timestamp` format.
+    // Returns current system clock as `u64` (String) timestamp.
     //
     // --> {"jsonrpc": "2.0", "method": "clock", "params": [], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    async fn clock(&self, id: Value, _params: &[Value]) -> JsonResult {
-        JsonResponse::new(json!(Timestamp::current_time()), id).into()
+    // <-- {"jsonrpc": "2.0", "result": "1234", "id": 1}
+    async fn clock(&self, id: u16, _params: JsonValue) -> JsonResult {
+        JsonResponse::new(JsonValue::String(Timestamp::current_time().0.to_string()), id).into()
     }
 
     // RPCAPI:
@@ -117,28 +98,21 @@ impl Darkfid {
     //
     // --> {"jsonrpc": "2.0", "method": "sync_dnet_switch", "params": [true], "id": 42}
     // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
-    async fn sync_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
-        if params.len() != 1 && params[0].as_bool().is_none() {
+    async fn sync_dnet_switch(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
+        if params.len() != 1 || !params[0].is_bool() {
             return JsonError::new(ErrorCode::InvalidParams, None, id).into()
         }
 
-        if params[0].as_bool().unwrap() {
+        let switch = params[0].get::<bool>().unwrap();
+
+        if *switch {
             self.sync_p2p.dnet_enable().await;
         } else {
             self.sync_p2p.dnet_disable().await;
         }
 
-        JsonResponse::new(json!(true), id).into()
-    }
-
-    // RPCAPI:
-    // Retrieves sync P2P network information.
-    //
-    // --> {"jsonrpc": "2.0", "method": "sync_dnet_info", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
-    async fn sync_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let dnet_info = self.sync_p2p.dnet_info().await;
-        JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
+        JsonResponse::new(JsonValue::Boolean(true), id).into()
     }
 
     // RPCAPI:
@@ -148,33 +122,21 @@ impl Darkfid {
     //
     // --> {"jsonrpc": "2.0", "method": "consensus_dnet_switch", "params": [true], "id": 42}
     // <-- {"jsonrpc": "2.0", "result": true, "id": 42}
-    async fn consensus_dnet_switch(&self, id: Value, params: &[Value]) -> JsonResult {
-        if params.len() != 1 && params[0].as_bool().is_none() {
+    async fn consensus_dnet_switch(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
+        if params.len() != 1 || !params[0].is_bool() {
             return JsonError::new(ErrorCode::InvalidParams, None, id).into()
         }
 
         if self.consensus_p2p.is_some() {
-            if params[0].as_bool().unwrap() {
+            let switch = params[0].get::<bool>().unwrap();
+            if *switch {
                 self.consensus_p2p.clone().unwrap().dnet_enable().await;
             } else {
                 self.consensus_p2p.clone().unwrap().dnet_disable().await;
             }
         }
 
-        JsonResponse::new(json!(true), id).into()
-    }
-
-    // RPCAPI:
-    // Retrieves consensus P2P network information.
-    //
-    // --> {"jsonrpc": "2.0", "method": "consensus_dnet_info", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
-    async fn consensus_dnet_info(&self, id: Value, _params: &[Value]) -> JsonResult {
-        let dnet_info = if self.consensus_p2p.is_some() {
-            self.consensus_p2p.clone().unwrap().dnet_info().await
-        } else {
-            vec![]
-        };
-        JsonResponse::new(net::P2p::map_dnet_info(dnet_info), id).into()
+        JsonResponse::new(JsonValue::Boolean(true), id).into()
     }
 }

+ 51 - 49
bin/darkfid2/src/rpc_blockchain.rs

@@ -21,14 +21,15 @@ use std::str::FromStr;
 use darkfi_sdk::crypto::ContractId;
 use darkfi_serial::{deserialize, serialize};
 use log::{debug, error};
-use serde_json::{json, Value};
+use tinyjson::JsonValue;
 
 use darkfi::{
     rpc::jsonrpc::{
         ErrorCode::{InternalError, InvalidParams, ParseError},
-        JsonError, JsonResponse, JsonResult, JsonSubscriber,
+        JsonError, JsonResponse, JsonResult,
     },
     runtime::vm_runtime::SMART_CONTRACT_ZKAS_DB_NAME,
+    util::encoding::base64,
 };
 
 use crate::{server_error, Darkfid, RpcError};
@@ -39,20 +40,24 @@ impl Darkfid {
     // Returns a readable block upon success.
     //
     // **Params:**
-    // * `array[0]`: `u64` slot ID
+    // * `array[0]`: `u64` slot ID (as string)
     //
     // **Returns:**
     // * [`BlockInfo`](https://darkrenaissance.github.io/darkfi/development/darkfi/consensus/block/struct.BlockInfo.html)
-    //   struct as a JSON object
+    //   struct serialized into base64.
     //
-    // --> {"jsonrpc": "2.0", "method": "blockchain.get_slot", "params": [0], "id": 1}
+    // --> {"jsonrpc": "2.0", "method": "blockchain.get_slot", "params": ["0"], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    pub async fn blockchain_get_slot(&self, id: Value, params: &[Value]) -> JsonResult {
-        if params.len() != 1 || !params[0].is_u64() {
+    pub async fn blockchain_get_slot(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
+        if params.len() != 1 || !params[0].is_string() {
             return JsonError::new(InvalidParams, None, id).into()
         }
 
-        let slot = params[0].as_u64().unwrap();
+        let slot = match u64::from_str_radix(params[0].get::<String>().unwrap(), 10) {
+            Ok(v) => v,
+            Err(_) => return JsonError::new(ParseError, None, id).into(),
+        };
 
         let blocks = match self.validator.read().await.blockchain.get_blocks_by_slot(&[slot]) {
             Ok(v) => v,
@@ -66,7 +71,8 @@ impl Darkfid {
             return server_error(RpcError::UnknownSlot, id, None)
         }
 
-        JsonResponse::new(json!(serialize(&blocks[0])), id).into()
+        let block = base64::encode(&serialize(&blocks[0]));
+        JsonResponse::new(JsonValue::String(block), id).into()
     }
 
     // RPCAPI:
@@ -78,25 +84,20 @@ impl Darkfid {
     //
     // **Returns:**
     // * Serialized [`Transaction`](https://darkrenaissance.github.io/darkfi/development/darkfi/tx/struct.Transaction.html)
-    //   object
+    //   object encoded with base64
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.get_tx", "params": ["TxHash"], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    pub async fn blockchain_get_tx(&self, id: Value, params: &[Value]) -> JsonResult {
+    // <-- {"jsonrpc": "2.0", "result": "ABCD...", "id": 1}
+    pub async fn blockchain_get_tx(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if params.len() != 1 {
             return JsonError::new(InvalidParams, None, id).into()
         }
 
-        let tx_hash_str = if let Some(tx_hash_str) = params[0].as_str() {
-            tx_hash_str
-        } else {
-            return JsonError::new(InvalidParams, None, id).into()
-        };
-
-        let tx_hash = if let Ok(tx_hash) = blake3::Hash::from_hex(tx_hash_str) {
-            tx_hash
-        } else {
-            return JsonError::new(ParseError, None, id).into()
+        let tx_hash = params[0].get::<String>().unwrap();
+        let tx_hash = match blake3::Hash::from_hex(tx_hash) {
+            Ok(v) => v,
+            Err(_) => return JsonError::new(ParseError, None, id).into(),
         };
 
         let txs = match self.validator.read().await.blockchain.transactions.get(&[tx_hash], true) {
@@ -111,7 +112,8 @@ impl Darkfid {
         // and strict was used during .get()
         let tx = txs[0].as_ref().unwrap();
 
-        JsonResponse::new(json!(serialize(tx)), id).into()
+        let tx_enc = base64::encode(&serialize(tx));
+        JsonResponse::new(JsonValue::String(tx_enc), id).into()
     }
 
     // RPCAPI:
@@ -121,11 +123,12 @@ impl Darkfid {
     // * `None`
     //
     // **Returns:**
-    // * `u64` ID of the last known slot
+    // * `u64` ID of the last known slot, as string
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.last_known_slot", "params": [], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": 1234, "id": 1}
-    pub async fn blockchain_last_known_slot(&self, id: Value, params: &[Value]) -> JsonResult {
+    // <-- {"jsonrpc": "2.0", "result": "1234", "id": 1}
+    pub async fn blockchain_last_known_slot(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -135,7 +138,7 @@ impl Darkfid {
             return JsonError::new(InternalError, None, id).into()
         };
 
-        JsonResponse::new(json!(last_slot.0), id).into()
+        JsonResponse::new(JsonValue::String(last_slot.0.to_string()), id).into()
     }
 
     // RPCAPI:
@@ -145,14 +148,13 @@ impl Darkfid {
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_blocks", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_blocks", "params": [`blockinfo`]}
-    pub async fn blockchain_subscribe_blocks(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn blockchain_subscribe_blocks(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
 
-        let blocks_subscriber = self.subscribers.get("blocks").unwrap().clone();
-
-        JsonSubscriber::new(blocks_subscriber).into()
+        self.subscribers.get("blocks").unwrap().clone().into()
     }
 
     // RPCAPI:
@@ -162,14 +164,13 @@ impl Darkfid {
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_txs", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_txs", "params": [`tx_hash`]}
-    pub async fn blockchain_subscribe_txs(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn blockchain_subscribe_txs(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
 
-        let txs_subscriber = self.subscribers.get("txs").unwrap().clone();
-
-        JsonSubscriber::new(txs_subscriber).into()
+        self.subscribers.get("txs").unwrap().clone().into()
     }
 
     // RPCAPI:
@@ -179,7 +180,8 @@ impl Darkfid {
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_proposals", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_proposals", "params": [`blockinfo`]}
-    pub async fn blockchain_subscribe_proposals(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn blockchain_subscribe_proposals(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -192,7 +194,7 @@ impl Darkfid {
             return JsonError::new(InternalError, None, id).into()
         }
 
-        JsonSubscriber::new(proposals_subscriber.unwrap().clone()).into()
+        proposals_subscriber.unwrap().clone().into()
     }
 
     // RPCAPI:
@@ -208,13 +210,15 @@ impl Darkfid {
     //   object
     //
     // --> {"jsonrpc": "2.0", "method": "blockchain.lookup_zkas", "params": ["6Ef42L1KLZXBoxBuCDto7coi9DA2D2SRtegNqNU4sd74"], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": [["Foo", [...]], ["Bar", [...]]], "id": 1}
-    pub async fn blockchain_lookup_zkas(&self, id: Value, params: &[Value]) -> JsonResult {
+    // <-- {"jsonrpc": "2.0", "result": [["Foo", "ABCD..."], ["Bar", "EFGH..."]], "id": 1}
+    pub async fn blockchain_lookup_zkas(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if params.len() != 1 || !params[0].is_string() {
             return JsonError::new(InvalidParams, None, id).into()
         }
 
-        let contract_id = match ContractId::from_str(params[0].as_str().unwrap()) {
+        let contract_id = params[0].get::<String>().unwrap();
+        let contract_id = match ContractId::from_str(contract_id) {
             Ok(v) => v,
             Err(e) => {
                 error!(target: "darkfid::rpc::blockchain_lookup_zkas", "Error decoding string to ContractId: {}", e);
@@ -236,7 +240,7 @@ impl Darkfid {
             return server_error(RpcError::ContractZkasDbNotFound, id, None)
         };
 
-        let mut ret: Vec<(String, Vec<u8>)> = vec![];
+        let mut ret = vec![];
 
         for i in zkas_db.iter() {
             debug!(target: "darkfid::rpc::blockchain_lookup_zkas", "Iterating over zkas db");
@@ -249,15 +253,13 @@ impl Darkfid {
                 return JsonError::new(InternalError, None, id).into()
             };
 
-            let Ok((zkas_bincode, _)): Result<(Vec<u8>, Vec<u8>), std::io::Error> =
-                deserialize(&zkas_bytes)
-            else {
-                return JsonError::new(InternalError, None, id).into()
-            };
-
-            ret.push((zkas_ns, zkas_bincode.to_vec()));
+            let zkas_bincode = base64::encode(&zkas_bytes);
+            ret.push(JsonValue::Array(vec![
+                JsonValue::String(zkas_ns),
+                JsonValue::String(zkas_bincode),
+            ]));
         }
 
-        JsonResponse::new(json!(ret), id).into()
+        JsonResponse::new(JsonValue::Array(ret), id).into()
     }
 }

+ 35 - 23
bin/darkfid2/src/rpc_tx.rs

@@ -18,7 +18,7 @@
 
 use darkfi_serial::deserialize;
 use log::error;
-use serde_json::{json, Value};
+use tinyjson::JsonValue;
 
 use darkfi::{
     rpc::jsonrpc::{
@@ -26,6 +26,7 @@ use darkfi::{
         JsonError, JsonResponse, JsonResult,
     },
     tx::Transaction,
+    util::encoding::base64,
 };
 
 use super::Darkfid;
@@ -37,9 +38,10 @@ impl Darkfid {
     // Returns `true` if the transaction is valid, otherwise, a corresponding
     // error.
     //
-    // --> {"jsonrpc": "2.0", "method": "tx.simulate", "params": ["base58encodedTX"], "id": 1}
+    // --> {"jsonrpc": "2.0", "method": "tx.simulate", "params": ["base64encodedTX"], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": true, "id": 1}
-    pub async fn tx_simulate(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn tx_simulate(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if params.len() != 1 || !params[0].is_string() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -50,10 +52,11 @@ impl Darkfid {
         }
 
         // Try to deserialize the transaction
-        let tx_bytes = match bs58::decode(params[0].as_str().unwrap().trim()).into_vec() {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "darkfid::rpc::tx_simulate", "Failed decoding base58 transaction: {}", e);
+        let tx_enc = params[0].get::<String>().unwrap().trim();
+        let tx_bytes = match base64::decode(tx_enc) {
+            Some(v) => v,
+            None => {
+                error!(target: "darkfid::rpc::tx_simulate", "Failed decoding base64 transaction");
                 return server_error(RpcError::ParseError, id, None)
             }
         };
@@ -78,7 +81,7 @@ impl Darkfid {
             return server_error(RpcError::TxSimulationFail, id, None)
         };
 
-        JsonResponse::new(json!(true), id).into()
+        JsonResponse::new(JsonValue::Boolean(true), id).into()
     }
 
     // RPCAPI:
@@ -87,9 +90,10 @@ impl Darkfid {
     // if the transaction is actually valid, and in turn it will return an
     // error if this is the case. Otherwise, a transaction ID will be returned.
     //
-    // --> {"jsonrpc": "2.0", "method": "tx.broadcast", "params": ["base58encodedTX"], "id": 1}
+    // --> {"jsonrpc": "2.0", "method": "tx.broadcast", "params": ["base64encodedTX"], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": "txID...", "id": 1}
-    pub async fn tx_broadcast(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn tx_broadcast(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if params.len() != 1 || !params[0].is_string() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -100,10 +104,11 @@ impl Darkfid {
         }
 
         // Try to deserialize the transaction
-        let tx_bytes = match bs58::decode(params[0].as_str().unwrap().trim()).into_vec() {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "darkfid::rpc::tx_broadcast", "Failed decoding base58 transaction: {}", e);
+        let tx_enc = params[0].get::<String>().unwrap().trim();
+        let tx_bytes = match base64::decode(tx_enc) {
+            Some(v) => v,
+            None => {
+                error!(target: "darkfid::rpc::tx_broadcast", "Failed decoding base64 transaction");
                 return server_error(RpcError::ParseError, id, None)
             }
         };
@@ -145,16 +150,17 @@ impl Darkfid {
         }
 
         let tx_hash = tx.hash().to_string();
-        JsonResponse::new(json!(tx_hash), id).into()
+        JsonResponse::new(JsonValue::String(tx_hash), id).into()
     }
 
     // RPCAPI:
     // Queries the node pending transactions store to retrieve all transactions.
-    // Returns a vector of serialized `Transaction` objects.
+    // Returns a vector of hex-encoded transaction hashes.
     //
     // --> {"jsonrpc": "2.0", "method": "tx.pending", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": "[TxHash,...]", "id": 1}
-    pub async fn tx_pending(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn tx_pending(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -171,17 +177,21 @@ impl Darkfid {
                 return JsonError::new(InternalError, None, id).into()
             }
         };
-        let pending_txs: Vec<String> = pending_txs.iter().map(|x| x.hash().to_string()).collect();
-        JsonResponse::new(json!(pending_txs), id).into()
+
+        let pending_txs: Vec<JsonValue> =
+            pending_txs.iter().map(|x| JsonValue::String(x.hash().to_string())).collect();
+
+        JsonResponse::new(JsonValue::Array(pending_txs), id).into()
     }
 
     // RPCAPI:
     // Queries the node pending transactions store to remove all transactions.
-    // Returns a vector of serialized `Transaction` objects.
+    // Returns a vector of hex-encoded transaction hashes.
     //
     // --> {"jsonrpc": "2.0", "method": "tx.clean_pending", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": "[TxHash,...]", "id": 1}
-    pub async fn tx_clean_pending(&self, id: Value, params: &[Value]) -> JsonResult {
+    pub async fn tx_clean_pending(&self, id: u16, params: JsonValue) -> JsonResult {
+        let params = params.get::<Vec<JsonValue>>().unwrap();
         if !params.is_empty() {
             return JsonError::new(InvalidParams, None, id).into()
         }
@@ -204,7 +214,9 @@ impl Darkfid {
             return JsonError::new(InternalError, None, id).into()
         };
 
-        let pending_txs: Vec<String> = pending_txs.iter().map(|x| x.hash().to_string()).collect();
-        JsonResponse::new(json!(pending_txs), id).into()
+        let pending_txs: Vec<JsonValue> =
+            pending_txs.iter().map(|x| JsonValue::String(x.hash().to_string())).collect();
+
+        JsonResponse::new(JsonValue::Array(pending_txs), id).into()
     }
 }

+ 1 - 1
bin/darkfid2/src/task/sync.rs

@@ -70,7 +70,7 @@ pub async fn sync_task(node: &Darkfid) -> Result<()> {
 
         // Notify subscriber
         for block in &response.blocks {
-            notif_sub.notify(block).await;
+            notif_sub.notify(&[block.clone()]).await;
         }
 
         let last_received = node.validator.read().await.blockchain.last()?;

+ 3 - 3
bin/darkfid2/src/utils.rs

@@ -23,7 +23,7 @@ use log::info;
 use darkfi::{
     error::TxVerifyFailed,
     net::{P2p, P2pPtr, Settings, SESSION_ALL},
-    rpc::jsonrpc::MethodSubscriber,
+    rpc::jsonrpc::JsonSubscriber,
     tx::Transaction,
     validator::ValidatorPtr,
     Result,
@@ -75,7 +75,7 @@ pub fn genesis_txs_total(txs: &[Transaction]) -> Result<u64> {
 pub async fn spawn_sync_p2p(
     settings: &Settings,
     validator: &ValidatorPtr,
-    subscribers: &HashMap<&'static str, MethodSubscriber>,
+    subscribers: &HashMap<&'static str, JsonSubscriber>,
 ) -> P2pPtr {
     info!(target: "darkfid", "Registering sync network P2P protocols...");
     let p2p = P2p::new(settings.clone()).await;
@@ -116,7 +116,7 @@ pub async fn spawn_sync_p2p(
 pub async fn spawn_consensus_p2p(
     settings: &Settings,
     validator: &ValidatorPtr,
-    subscribers: &HashMap<&'static str, MethodSubscriber>,
+    subscribers: &HashMap<&'static str, JsonSubscriber>,
 ) -> P2pPtr {
     info!(target: "darkfid", "Registering consensus network P2P protocols...");
     let p2p = P2p::new(settings.clone()).await;