rachel-rose 5 лет назад
Родитель
Сommit
e8a400def2
6 измененных файлов с 181 добавлено и 0 удалено
  1. 2 0
      src/rpc/__init__.py
  2. 2 0
      src/rpc/adapter.rs
  3. 53 0
      src/rpc/jsonclient.py
  4. 118 0
      src/rpc/jsonserver.rs
  5. 3 0
      src/rpc/mod.rs
  6. 3 0
      src/rpc/test.rs

+ 2 - 0
src/rpc/__init__.py

@@ -0,0 +1,2 @@
+from rpc import jsonclient
+from .jsonclient import RpcClient

+ 2 - 0
src/rpc/adapter.rs

@@ -0,0 +1,2 @@
+// Adapter class goes here
+//

+ 53 - 0
src/rpc/jsonclient.py

@@ -0,0 +1,53 @@
+import requests
+
+# TODO: generate random ID (4 byte unsigned int) (rand range 0 - max size uint32)
+# TODO: make functions async
+# TODO: parse json replies into something more legible
+
+class RpcClient:
+    def __init__(self):
+        self.url = "http://localhost:8000/"
+        self.payload = {
+            "method": [],
+            "params": [],
+            "jsonrpc": [],
+            "id": [],
+        }
+
+    def key_gen(self, payload):
+        payload['method'] = "key_gen"
+        payload['jsonrpc'] = "2.0"
+        payload['id'] = "0"
+        key = self.__request(payload)
+        print(key)
+
+    def get_info(self, payload):
+        payload['method'] = "get_info"
+        payload['jsonrpc'] = "2.0"
+        payload['id'] = "0"
+        info = self.__request(payload)
+        print(info)
+
+    def stop(self, payload):
+        payload['method'] = "stop"
+        payload['jsonrpc'] = "2.0"
+        payload['id'] = "0"
+        stop = self.__request(payload)
+        print(stop)
+
+    def say_hello(self, payload):
+        payload['method'] = "say_hello"
+        payload['jsonrpc'] = "2.0"
+        payload['id'] = "0"
+        hello = self.__request(payload)
+        print(hello)
+
+    def __request(self, payload):
+        response = requests.post(self.url, json=payload).json()
+        print(response)
+        assert response["jsonrpc"]
+
+    
+if __name__ == "__main__":
+    client = RpcClient()
+

+ 118 - 0
src/rpc/jsonserver.rs

@@ -0,0 +1,118 @@
+#[macro_use] extern crate clap;
+use async_executor::Executor;
+use async_native_tls::TlsAcceptor;
+use async_std::sync::Mutex;
+use easy_parallel::Parallel;
+use ff::Field;
+use http_types::{Request, Response, StatusCode};
+use log::*;
+use rand::rngs::OsRng;
+use sapvi::serial;
+use serde_json::json;
+use smol::Async;
+use std::fs::File;
+use std::io::prelude::*;
+use std::io::BufReader;
+use std::net::SocketAddr;
+use std::net::TcpListener;
+use std::sync::Arc;
+use rusqlite::Connection;
+
+use sapvi::{net, Result, Error};
+// json RPC server goes here
+struct RpcInterface {
+    p2p: Arc<net::P2p>,
+    started: Mutex<bool>,
+    stop_send: async_channel::Sender<()>,
+    stop_recv: async_channel::Receiver<()>,
+}
+
+impl RpcInterface {
+    fn new(p2p: Arc<net::P2p>) -> Arc<Self> {
+        let (stop_send, stop_recv) = async_channel::unbounded::<()>();
+
+        Arc::new(Self {
+            p2p,
+            started: Mutex::new(false),
+            stop_send,
+            stop_recv,
+        })
+    }
+
+    async fn db_connect() -> Connection {
+        let path = dirs::home_dir()
+            .expect("Cannot find home directory.")
+            .as_path()
+            .join(".config/darkfi/wallet.db");
+        let connector = Connection::open(&path);
+        connector.expect("Failed to connect to database.")
+    }
+
+    async fn generate_key() -> (Vec<u8>, Vec<u8>) {
+        let secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
+        let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
+        let pubkey = serial::serialize(&public);
+        let privkey = serial::serialize(&secret);
+        (privkey, pubkey)
+    }
+
+    // TODO: fix this
+    async fn store_key(conn: &Connection, pubkey: Vec<u8>, privkey: Vec<u8>) -> Result<()> {
+        let mut db_file = File::open("wallet.sql")?;
+        let mut contents = String::new();
+        db_file.read_to_string(&mut contents)?;
+        Ok(conn.execute_batch(&mut contents)?)
+    }
+
+    // add new methods to handle wallet commands
+    async fn serve(self: Arc<Self>, mut req: Request) -> http_types::Result<Response> {
+        info!("RPC serving {}", req.url());
+
+        let request = req.body_string().await?;
+
+        let mut io = jsonrpc_core::IoHandler::new();
+        io.add_sync_method("say_hello", |_| {
+            Ok(jsonrpc_core::Value::String("Hello World!".into()))
+        });
+
+        let self2 = self.clone();
+        io.add_method("get_info", move |_| {
+            let self2 = self2.clone();
+            async move {
+                Ok(json!({
+                    "started": *self2.started.lock().await,
+                    "connections": self2.p2p.connections_count().await
+                }))
+            }
+        });
+
+        let stop_send = self.stop_send.clone();
+        io.add_method("stop", move |_| {
+            let stop_send = stop_send.clone();
+            async move {
+                let _ = stop_send.send(()).await;
+                Ok(jsonrpc_core::Value::Null)
+            }
+        });
+        io.add_method("key_gen", move |_| async move {
+            RpcInterface::db_connect().await;
+            let (pubkey, privkey) = RpcInterface::generate_key().await;
+            //println!("{}", pubkey, "{}", privkey);
+            Ok(jsonrpc_core::Value::Null)
+        });
+
+        let response = io
+            .handle_request_sync(&request)
+            .ok_or(sapvi::Error::BadOperationType)?;
+
+        let mut res = Response::new(StatusCode::Ok);
+        res.insert_header("Content-Type", "text/plain");
+        res.set_body(response);
+        Ok(res)
+    }
+
+    async fn wait_for_quit(self: Arc<Self>) -> Result<()> {
+        Ok(self.stop_recv.recv().await?)
+    }
+}
+

+ 3 - 0
src/rpc/mod.rs

@@ -0,0 +1,3 @@
+pub mod test;
+pub mod jsonserver;
+

+ 3 - 0
src/rpc/test.rs

@@ -0,0 +1,3 @@
+fn foo() {
+}
+