From 44c3ad69b4f36a08448cf8d5d2e0a7be32436991 Mon Sep 17 00:00:00 2001 From: Oran Juice Date: Sun, 24 May 2015 23:10:15 +0530 Subject: [PATCH] monero-rpc-deprecated basic. get_info, save_bc, start, stop mining --- src/daemon/daemon.cpp | 22 +- src/ipc/daemon_ipc_handlers.cpp | 42 + src/ipc/include/daemon_ipc_handlers.h | 4 + src/ipc/include/wap_client.h | 52 +- src/ipc/include/wap_client_engine.inc | 410 +++++++- src/ipc/include/wap_proto.h | 118 ++- src/ipc/include/wap_server_engine.inc | 84 +- src/ipc/wap_client/wap_client.c | 47 +- src/ipc/wap_proto.c | 393 +++++++- src/ipc/wap_server/wap_server.c | 30 + src/rpc/CMakeLists.txt | 24 +- src/rpc/daemon_deprecated_rpc.cpp | 333 +++++++ src/rpc/daemon_deprecated_rpc.h | 48 + src/rpc/daemon_json_rpc_handlers.cpp | 1197 ----------------------- src/rpc/daemon_json_rpc_handlers.h | 75 -- src/rpc/json_rpc.cpp | 26 + src/rpc/json_rpc_http_server.cpp | 9 +- src/rpc/json_rpc_http_server.h | 3 +- src/simplewallet/simplewallet.cpp | 32 +- src/simplewallet/simplewallet.h | 1 - src/wallet/wallet2.cpp | 16 +- src/wallet/wallet2.h | 2 + src/wallet/wallet_json_rpc_handlers.cpp | 12 +- 23 files changed, 1558 insertions(+), 1422 deletions(-) create mode 100644 src/rpc/daemon_deprecated_rpc.cpp create mode 100644 src/rpc/daemon_deprecated_rpc.h delete mode 100644 src/rpc/daemon_json_rpc_handlers.cpp delete mode 100644 src/rpc/daemon_json_rpc_handlers.h create mode 100644 src/rpc/json_rpc.cpp diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index f35f58b80..9e7f2f210 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -34,7 +34,7 @@ #include "daemon/core.h" #include "daemon/p2p.h" #include "daemon/protocol.h" -#include "daemon/rpc.h" +// #include "daemon/rpc.h" #include "daemon/command_server.h" #include "misc_log_ex.h" #include "version.h" @@ -57,7 +57,7 @@ private: public: t_core core; t_p2p p2p; - t_rpc rpc; + // t_rpc rpc; bool testnet_mode; t_internals( @@ -66,7 +66,7 @@ public: : core{vm} , protocol{vm, core} , p2p{vm, protocol} - , rpc{vm, core, p2p} + // , rpc{vm, core, p2p} { // Handle circular dependencies protocol.set_p2p_endpoint(p2p.get()); @@ -79,7 +79,7 @@ void t_daemon::init_options(boost::program_options::options_description & option { t_core::init_options(option_spec); t_p2p::init_options(option_spec); - t_rpc::init_options(option_spec); + // t_rpc::init_options(option_spec); } t_daemon::t_daemon( @@ -122,14 +122,14 @@ bool t_daemon::run(bool interactive) try { mp_internals->core.run(); - mp_internals->rpc.run(); + // mp_internals->rpc.run(); - daemonize::t_command_server* rpc_commands; + // daemonize::t_command_server* rpc_commands; if (interactive) { - rpc_commands = new daemonize::t_command_server(0, 0, false, mp_internals->rpc.get_server()); - rpc_commands->start_handling(); + // rpc_commands = new daemonize::t_command_server(0, 0, false, mp_internals->rpc.get_server()); + // rpc_commands->start_handling(); IPC::Daemon::init(mp_internals->core.get(), mp_internals->p2p.get(), mp_internals->testnet_mode); } @@ -138,11 +138,11 @@ bool t_daemon::run(bool interactive) if (interactive) { - rpc_commands->stop_handling(); + // rpc_commands->stop_handling(); IPC::Daemon::stop(); } - mp_internals->rpc.stop(); + // mp_internals->rpc.stop(); LOG_PRINT("Node stopped.", LOG_LEVEL_0); return true; } @@ -165,7 +165,7 @@ void t_daemon::stop() throw std::runtime_error{"Can't stop stopped daemon"}; } mp_internals->p2p.stop(); - mp_internals->rpc.stop(); + // mp_internals->rpc.stop(); mp_internals.reset(nullptr); // Ensure resources are cleaned up before we return } diff --git a/src/ipc/daemon_ipc_handlers.cpp b/src/ipc/daemon_ipc_handlers.cpp index 90e110cae..4aba57adb 100644 --- a/src/ipc/daemon_ipc_handlers.cpp +++ b/src/ipc/daemon_ipc_handlers.cpp @@ -320,5 +320,47 @@ namespace IPC LOG_PRINT_L2("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: " << ENDL << s); wap_proto_set_status(message, STATUS_OK); } + + void get_height(wap_proto_t *message) { + if (!check_core_busy()) { + wap_proto_set_status(message, STATUS_CORE_BUSY); + return; + } + wap_proto_set_height(message, core->get_current_blockchain_height()); + wap_proto_set_status(message, STATUS_OK); + } + + void save_bc(wap_proto_t *message) { + if (!check_core_busy()) { + wap_proto_set_status(message, STATUS_CORE_BUSY); + return; + } + if (!core->get_blockchain_storage().store_blockchain()) { + wap_proto_set_status(message, STATUS_ERROR_STORING_BLOCKCHAIN); + return; + } + wap_proto_set_status(message, STATUS_OK); + } + + void get_info(wap_proto_t *message) { + if (!check_core_busy()) { + wap_proto_set_status(message, STATUS_CORE_BUSY); + return; + } + uint64_t height = core->get_current_blockchain_height(); + wap_proto_set_height(message, height); + wap_proto_set_target_height(message, core->get_target_blockchain_height()); + wap_proto_set_difficulty(message, core->get_blockchain_storage().get_difficulty_for_next_block()); + wap_proto_set_tx_count(message, core->get_blockchain_storage().get_total_transactions() - height); + wap_proto_set_tx_pool_size(message, core->get_pool_transactions_count()); + wap_proto_set_alt_blocks_count(message, core->get_blockchain_storage().get_alternative_blocks_count()); + uint64_t outgoing_connections_count = p2p->get_outgoing_connections_count(); + wap_proto_set_outgoing_connections_count(message, outgoing_connections_count); + uint64_t total_connections = p2p->get_connections_count(); + wap_proto_set_incoming_connections_count(message, total_connections - outgoing_connections_count); + wap_proto_set_white_peerlist_size(message, p2p->get_peerlist_manager().get_white_peers_count()); + wap_proto_set_grey_peerlist_size(message, p2p->get_peerlist_manager().get_gray_peers_count()); + wap_proto_set_status(message, STATUS_OK); + } } } diff --git a/src/ipc/include/daemon_ipc_handlers.h b/src/ipc/include/daemon_ipc_handlers.h index fe19166ce..eba8b2e03 100644 --- a/src/ipc/include/daemon_ipc_handlers.h +++ b/src/ipc/include/daemon_ipc_handlers.h @@ -65,6 +65,7 @@ namespace IPC const uint64_t STATUS_TX_NOT_RELAYED = 8; const uint64_t STATUS_RANDOM_OUTS_FAILED = 9; const uint64_t STATUS_MINING_NOT_STOPPED = 10; + const uint64_t STATUS_ERROR_STORING_BLOCKCHAIN = 11; namespace Daemon { void start_mining(wap_proto_t *message); @@ -73,6 +74,9 @@ namespace IPC void send_raw_transaction(wap_proto_t *message); void get_output_indexes(wap_proto_t *message); void get_random_outs(wap_proto_t *message); + void get_height(wap_proto_t *message); + void save_bc(wap_proto_t *message); + void get_info(wap_proto_t *message); void init(cryptonote::core &p_core, nodetool::node_server > &p_p2p, bool p_testnet); diff --git a/src/ipc/include/wap_client.h b/src/ipc/include/wap_client.h index 5ef8dfa6b..c4f2a1a76 100644 --- a/src/ipc/include/wap_client.h +++ b/src/ipc/include/wap_client.h @@ -85,7 +85,7 @@ WAP_EXPORT int // Request a set of blocks from the server. // Returns >= 0 if successful, -1 if interrupted. WAP_EXPORT int - wap_client_save (wap_client_t *self); + wap_client_save_bc (wap_client_t *self); // Ask for tx output indexes. // Returns >= 0 if successful, -1 if interrupted. @@ -97,6 +97,16 @@ WAP_EXPORT int WAP_EXPORT int wap_client_random_outs (wap_client_t *self, uint64_t outs_count, zframe_t **amounts_p); +// Ask for height. +// Returns >= 0 if successful, -1 if interrupted. +WAP_EXPORT int + wap_client_get_height (wap_client_t *self); + +// Ask for height. +// Returns >= 0 if successful, -1 if interrupted. +WAP_EXPORT int + wap_client_get_info (wap_client_t *self); + // Send start command to server. // Returns >= 0 if successful, -1 if interrupted. WAP_EXPORT int @@ -139,6 +149,46 @@ WAP_EXPORT zframe_t * WAP_EXPORT zframe_t * wap_client_random_outputs (wap_client_t *self); +// Return last received height +WAP_EXPORT uint64_t + wap_client_height (wap_client_t *self); + +// Return last received target_height +WAP_EXPORT uint64_t + wap_client_target_height (wap_client_t *self); + +// Return last received difficulty +WAP_EXPORT uint64_t + wap_client_difficulty (wap_client_t *self); + +// Return last received tx_count +WAP_EXPORT uint64_t + wap_client_tx_count (wap_client_t *self); + +// Return last received tx_pool_size +WAP_EXPORT uint64_t + wap_client_tx_pool_size (wap_client_t *self); + +// Return last received alt_blocks_count +WAP_EXPORT uint64_t + wap_client_alt_blocks_count (wap_client_t *self); + +// Return last received outgoing_connections_count +WAP_EXPORT uint64_t + wap_client_outgoing_connections_count (wap_client_t *self); + +// Return last received incoming_connections_count +WAP_EXPORT uint64_t + wap_client_incoming_connections_count (wap_client_t *self); + +// Return last received white_peerlist_size +WAP_EXPORT uint64_t + wap_client_white_peerlist_size (wap_client_t *self); + +// Return last received grey_peerlist_size +WAP_EXPORT uint64_t + wap_client_grey_peerlist_size (wap_client_t *self); + // Self test of this class WAP_EXPORT void wap_client_test (bool verbose); diff --git a/src/ipc/include/wap_client_engine.inc b/src/ipc/include/wap_client_engine.inc index 6f10bc0e0..d1fad0938 100644 --- a/src/ipc/include/wap_client_engine.inc +++ b/src/ipc/include/wap_client_engine.inc @@ -27,15 +27,17 @@ typedef enum { expect_blocks_ok_state = 4, expect_get_ok_state = 5, expect_put_ok_state = 6, - expect_save_ok_state = 7, + expect_save_bc_ok_state = 7, expect_start_ok_state = 8, expect_stop_ok_state = 9, expect_output_indexes_ok_state = 10, expect_random_outs_ok_state = 11, - expect_close_ok_state = 12, - defaults_state = 13, - have_error_state = 14, - reexpect_open_ok_state = 15 + expect_get_height_ok_state = 12, + expect_get_info_ok_state = 13, + expect_close_ok_state = 14, + defaults_state = 15, + have_error_state = 16, + reexpect_open_ok_state = 17 } state_t; typedef enum { @@ -47,26 +49,30 @@ typedef enum { blocks_event = 5, get_event = 6, put_event = 7, - save_event = 8, + save_bc_event = 8, start_event = 9, stop_event = 10, output_indexes_event = 11, random_outs_event = 12, - destructor_event = 13, - blocks_ok_event = 14, - get_ok_event = 15, - put_ok_event = 16, - save_ok_event = 17, - start_ok_event = 18, - stop_ok_event = 19, - output_indexes_ok_event = 20, - random_outs_ok_event = 21, - close_ok_event = 22, - ping_ok_event = 23, - error_event = 24, - exception_event = 25, - command_invalid_event = 26, - other_event = 27 + get_height_event = 13, + get_info_event = 14, + destructor_event = 15, + blocks_ok_event = 16, + get_ok_event = 17, + put_ok_event = 18, + save_bc_ok_event = 19, + start_ok_event = 20, + stop_ok_event = 21, + output_indexes_ok_event = 22, + random_outs_ok_event = 23, + get_height_ok_event = 24, + get_info_ok_event = 25, + close_ok_event = 26, + ping_ok_event = 27, + error_event = 28, + exception_event = 29, + command_invalid_event = 30, + other_event = 31 } event_t; // Names for state machine logging and error reporting @@ -79,11 +85,13 @@ s_state_name [] = { "expect blocks ok", "expect get ok", "expect put ok", - "expect save ok", + "expect save bc ok", "expect start ok", "expect stop ok", "expect output indexes ok", "expect random outs ok", + "expect get height ok", + "expect get info ok", "expect close ok", "defaults", "have error", @@ -100,20 +108,24 @@ s_event_name [] = { "BLOCKS", "GET", "PUT", - "SAVE", + "SAVE_BC", "START", "STOP", "OUTPUT_INDEXES", "RANDOM_OUTS", + "GET_HEIGHT", + "GET_INFO", "destructor", "BLOCKS_OK", "GET_OK", "PUT_OK", - "SAVE_OK", + "SAVE_BC_OK", "START_OK", "STOP_OK", "OUTPUT_INDEXES_OK", "RANDOM_OUTS_OK", + "GET_HEIGHT_OK", + "GET_INFO_OK", "CLOSE_OK", "PING_OK", "ERROR", @@ -198,8 +210,6 @@ static void prepare_get_command (client_t *self); static void prepare_put_command (client_t *self); -static void - prepare_save_command (client_t *self); static void prepare_start_command (client_t *self); static void @@ -215,7 +225,7 @@ static void static void signal_have_put_ok (client_t *self); static void - signal_have_save_ok (client_t *self); + signal_have_save_bc_ok (client_t *self); static void signal_have_start_ok (client_t *self); static void @@ -224,6 +234,10 @@ static void signal_have_output_indexes_ok (client_t *self); static void signal_have_random_outs_ok (client_t *self); +static void + signal_have_get_height_ok (client_t *self); +static void + signal_have_get_info_ok (client_t *self); static void signal_failure (client_t *self); static void @@ -443,17 +457,23 @@ s_protocol_event (s_client_t *self, wap_proto_t *message) case WAP_PROTO_RANDOM_OUTS_OK: return random_outs_ok_event; break; + case WAP_PROTO_GET_HEIGHT: + return get_height_event; + break; + case WAP_PROTO_GET_HEIGHT_OK: + return get_height_ok_event; + break; case WAP_PROTO_GET: return get_event; break; case WAP_PROTO_GET_OK: return get_ok_event; break; - case WAP_PROTO_SAVE: - return save_event; + case WAP_PROTO_SAVE_BC: + return save_bc_event; break; - case WAP_PROTO_SAVE_OK: - return save_ok_event; + case WAP_PROTO_SAVE_BC_OK: + return save_bc_ok_event; break; case WAP_PROTO_START: return start_event; @@ -461,6 +481,12 @@ s_protocol_event (s_client_t *self, wap_proto_t *message) case WAP_PROTO_START_OK: return start_ok_event; break; + case WAP_PROTO_GET_INFO: + return get_info_event; + break; + case WAP_PROTO_GET_INFO_OK: + return get_info_ok_event; + break; case WAP_PROTO_STOP: return stop_event; break; @@ -681,22 +707,16 @@ s_client_execute (s_client_t *self, event_t event) self->state = expect_put_ok_state; } else - if (self->event == save_event) { + if (self->event == save_bc_event) { if (!self->exception) { - // prepare save command + // send SAVE_BC if (wap_client_verbose) - zsys_debug ("wap_client: $ prepare save command"); - prepare_save_command (&self->client); - } - if (!self->exception) { - // send SAVE - if (wap_client_verbose) - zsys_debug ("wap_client: $ send SAVE"); - wap_proto_set_id (self->message, WAP_PROTO_SAVE); + zsys_debug ("wap_client: $ send SAVE_BC"); + wap_proto_set_id (self->message, WAP_PROTO_SAVE_BC); wap_proto_send (self->message, self->dealer); } if (!self->exception) - self->state = expect_save_ok_state; + self->state = expect_save_bc_ok_state; } else if (self->event == start_event) { @@ -765,6 +785,30 @@ s_client_execute (s_client_t *self, event_t event) self->state = expect_random_outs_ok_state; } else + if (self->event == get_height_event) { + if (!self->exception) { + // send GET_HEIGHT + if (wap_client_verbose) + zsys_debug ("wap_client: $ send GET_HEIGHT"); + wap_proto_set_id (self->message, WAP_PROTO_GET_HEIGHT); + wap_proto_send (self->message, self->dealer); + } + if (!self->exception) + self->state = expect_get_height_ok_state; + } + else + if (self->event == get_info_event) { + if (!self->exception) { + // send GET_INFO + if (wap_client_verbose) + zsys_debug ("wap_client: $ send GET_INFO"); + wap_proto_set_id (self->message, WAP_PROTO_GET_INFO); + wap_proto_send (self->message, self->dealer); + } + if (!self->exception) + self->state = expect_get_info_ok_state; + } + else if (self->event == destructor_event) { if (!self->exception) { // send CLOSE @@ -961,13 +1005,13 @@ s_client_execute (s_client_t *self, event_t event) } break; - case expect_save_ok_state: - if (self->event == save_ok_event) { + case expect_save_bc_ok_state: + if (self->event == save_bc_ok_event) { if (!self->exception) { - // signal have save ok + // signal have save bc ok if (wap_client_verbose) - zsys_debug ("wap_client: $ signal have save ok"); - signal_have_save_ok (&self->client); + zsys_debug ("wap_client: $ signal have save bc ok"); + signal_have_save_bc_ok (&self->client); } if (!self->exception) self->state = connected_state; @@ -1186,6 +1230,96 @@ s_client_execute (s_client_t *self, event_t event) } break; + case expect_get_height_ok_state: + if (self->event == get_height_ok_event) { + if (!self->exception) { + // signal have get height ok + if (wap_client_verbose) + zsys_debug ("wap_client: $ signal have get height ok"); + signal_have_get_height_ok (&self->client); + } + if (!self->exception) + self->state = connected_state; + } + else + if (self->event == ping_ok_event) { + if (!self->exception) { + // client is connected + if (wap_client_verbose) + zsys_debug ("wap_client: $ client is connected"); + client_is_connected (&self->client); + } + } + else + if (self->event == error_event) { + if (!self->exception) { + // check status code + if (wap_client_verbose) + zsys_debug ("wap_client: $ check status code"); + check_status_code (&self->client); + } + if (!self->exception) + self->state = have_error_state; + } + else + if (self->event == exception_event) { + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ exception"); + } + else { + // Handle unexpected protocol events + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ *"); + } + break; + + case expect_get_info_ok_state: + if (self->event == get_info_ok_event) { + if (!self->exception) { + // signal have get info ok + if (wap_client_verbose) + zsys_debug ("wap_client: $ signal have get info ok"); + signal_have_get_info_ok (&self->client); + } + if (!self->exception) + self->state = connected_state; + } + else + if (self->event == ping_ok_event) { + if (!self->exception) { + // client is connected + if (wap_client_verbose) + zsys_debug ("wap_client: $ client is connected"); + client_is_connected (&self->client); + } + } + else + if (self->event == error_event) { + if (!self->exception) { + // check status code + if (wap_client_verbose) + zsys_debug ("wap_client: $ check status code"); + check_status_code (&self->client); + } + if (!self->exception) + self->state = have_error_state; + } + else + if (self->event == exception_event) { + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ exception"); + } + else { + // Handle unexpected protocol events + // No action - just logging + if (wap_client_verbose) + zsys_debug ("wap_client: $ *"); + } + break; + case expect_close_ok_state: if (self->event == close_ok_event) { if (!self->exception) { @@ -1456,8 +1590,8 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument) s_client_execute (self, get_event); } else - if (streq (method, "SAVE")) { - s_client_execute (self, save_event); + if (streq (method, "SAVE BC")) { + s_client_execute (self, save_bc_event); } else if (streq (method, "OUTPUT INDEXES")) { @@ -1472,6 +1606,14 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument) s_client_execute (self, random_outs_event); } else + if (streq (method, "GET HEIGHT")) { + s_client_execute (self, get_height_event); + } + else + if (streq (method, "GET INFO")) { + s_client_execute (self, get_info_event); + } + else if (streq (method, "START")) { zchunk_destroy (&self->args.address); zsock_recv (self->cmdpipe, "p8", &self->args.address, &self->args.thread_count); @@ -1601,6 +1743,16 @@ struct _wap_client_t { zchunk_t *tx_data; // Returned by actor reply zframe_t *o_indexes; // Returned by actor reply zframe_t *random_outputs; // Returned by actor reply + uint64_t height; // Returned by actor reply + uint64_t target_height; // Returned by actor reply + uint64_t difficulty; // Returned by actor reply + uint64_t tx_count; // Returned by actor reply + uint64_t tx_pool_size; // Returned by actor reply + uint64_t alt_blocks_count; // Returned by actor reply + uint64_t outgoing_connections_count; // Returned by actor reply + uint64_t incoming_connections_count; // Returned by actor reply + uint64_t white_peerlist_size; // Returned by actor reply + uint64_t grey_peerlist_size; // Returned by actor reply }; @@ -1745,8 +1897,8 @@ s_accept_reply (wap_client_t *self, ...) zsock_recv (self->actor, "ip", &self->status, &self->tx_data); } else - if (streq (reply, "SAVE OK")) { - zsock_recv (self->actor, "i", &self->status); + if (streq (reply, "SAVE BC OK")) { + zsock_recv (self->actor, "8", &self->status); } else if (streq (reply, "OUTPUT INDEXES OK")) { @@ -1759,6 +1911,14 @@ s_accept_reply (wap_client_t *self, ...) zsock_recv (self->actor, "8p", &self->status, &self->random_outputs); } else + if (streq (reply, "GET HEIGHT OK")) { + zsock_recv (self->actor, "88", &self->status, &self->height); + } + else + if (streq (reply, "GET INFO OK")) { + zsock_recv (self->actor, "88888888888", &self->status, &self->height, &self->target_height, &self->difficulty, &self->tx_count, &self->tx_pool_size, &self->alt_blocks_count, &self->outgoing_connections_count, &self->incoming_connections_count, &self->white_peerlist_size, &self->grey_peerlist_size); + } + else if (streq (reply, "START OK")) { zsock_recv (self->actor, "8", &self->status); } @@ -1873,12 +2033,12 @@ wap_client_get (wap_client_t *self, zchunk_t **tx_id_p) // Returns >= 0 if successful, -1 if interrupted. int -wap_client_save (wap_client_t *self) +wap_client_save_bc (wap_client_t *self) { assert (self); - zsock_send (self->actor, "s", "SAVE"); - if (s_accept_reply (self, "SAVE OK", "FAILURE", NULL)) + zsock_send (self->actor, "s", "SAVE BC"); + if (s_accept_reply (self, "SAVE BC OK", "FAILURE", NULL)) return -1; // Interrupted or timed-out return self->status; } @@ -1918,6 +2078,38 @@ wap_client_random_outs (wap_client_t *self, uint64_t outs_count, zframe_t **amou } +// --------------------------------------------------------------------------- +// Ask for height. +// Returns >= 0 if successful, -1 if interrupted. + +int +wap_client_get_height (wap_client_t *self) +{ + assert (self); + + zsock_send (self->actor, "s", "GET HEIGHT"); + if (s_accept_reply (self, "GET HEIGHT OK", "FAILURE", NULL)) + return -1; // Interrupted or timed-out + return self->status; +} + + +// --------------------------------------------------------------------------- +// Ask for height. +// Returns >= 0 if successful, -1 if interrupted. + +int +wap_client_get_info (wap_client_t *self) +{ + assert (self); + + zsock_send (self->actor, "s", "GET INFO"); + if (s_accept_reply (self, "GET INFO OK", "FAILURE", NULL)) + return -1; // Interrupted or timed-out + return self->status; +} + + // --------------------------------------------------------------------------- // Send start command to server. // Returns >= 0 if successful, -1 if interrupted. @@ -2037,3 +2229,113 @@ wap_client_random_outputs (wap_client_t *self) assert (self); return self->random_outputs; } + + +// --------------------------------------------------------------------------- +// Return last received height + +uint64_t +wap_client_height (wap_client_t *self) +{ + assert (self); + return self->height; +} + + +// --------------------------------------------------------------------------- +// Return last received target_height + +uint64_t +wap_client_target_height (wap_client_t *self) +{ + assert (self); + return self->target_height; +} + + +// --------------------------------------------------------------------------- +// Return last received difficulty + +uint64_t +wap_client_difficulty (wap_client_t *self) +{ + assert (self); + return self->difficulty; +} + + +// --------------------------------------------------------------------------- +// Return last received tx_count + +uint64_t +wap_client_tx_count (wap_client_t *self) +{ + assert (self); + return self->tx_count; +} + + +// --------------------------------------------------------------------------- +// Return last received tx_pool_size + +uint64_t +wap_client_tx_pool_size (wap_client_t *self) +{ + assert (self); + return self->tx_pool_size; +} + + +// --------------------------------------------------------------------------- +// Return last received alt_blocks_count + +uint64_t +wap_client_alt_blocks_count (wap_client_t *self) +{ + assert (self); + return self->alt_blocks_count; +} + + +// --------------------------------------------------------------------------- +// Return last received outgoing_connections_count + +uint64_t +wap_client_outgoing_connections_count (wap_client_t *self) +{ + assert (self); + return self->outgoing_connections_count; +} + + +// --------------------------------------------------------------------------- +// Return last received incoming_connections_count + +uint64_t +wap_client_incoming_connections_count (wap_client_t *self) +{ + assert (self); + return self->incoming_connections_count; +} + + +// --------------------------------------------------------------------------- +// Return last received white_peerlist_size + +uint64_t +wap_client_white_peerlist_size (wap_client_t *self) +{ + assert (self); + return self->white_peerlist_size; +} + + +// --------------------------------------------------------------------------- +// Return last received grey_peerlist_size + +uint64_t +wap_client_grey_peerlist_size (wap_client_t *self) +{ + assert (self); + return self->grey_peerlist_size; +} diff --git a/src/ipc/include/wap_proto.h b/src/ipc/include/wap_proto.h index edb72ada2..7b7ad0ae1 100644 --- a/src/ipc/include/wap_proto.h +++ b/src/ipc/include/wap_proto.h @@ -63,6 +63,12 @@ PUT-OK, or ERROR. status number 8 Status random_outputs frame Outputs + GET_HEIGHT - Get height. + + GET_HEIGHT_OK - Daemon returns height. + status number 8 Status + height number 8 Height + GET - Wallet requests transaction data from the daemon. Daemon replies with GET-OK, or ERROR. tx_id chunk Transaction ID @@ -70,9 +76,10 @@ with GET-OK, or ERROR. GET_OK - Daemon replies with transaction data. tx_data chunk Transaction data - SAVE - save_bc command. Details tbd. + SAVE_BC - save_bc command. Details tbd. - SAVE_OK - Daemon replies to a save_bc command. + SAVE_BC_OK - Daemon replies to a save_bc command. + status number 8 Status START - Wallet asks daemon to start mining. Daemon replies with START-OK, or ERROR. @@ -82,7 +89,22 @@ ERROR. START_OK - Daemon replies to a start mining request. status number 8 - STOP - Wallet asks daemon to start mining. Daemon replies with START-OK, or + GET_INFO - getinfo IPC + + GET_INFO_OK - This is a codec for a Bitcoin Wallet Access Protocol (RFC tbd) + status number 8 Status + height number 8 Height + target_height number 8 Target Height + difficulty number 8 Difficulty + tx_count number 8 TX Count + tx_pool_size number 8 TX Pool Size + alt_blocks_count number 8 Alt Blocks Count + outgoing_connections_count number 8 Outgoing Connections Count + incoming_connections_count number 8 Incoming Connections Count + white_peerlist_size number 8 White Peerlist Size + grey_peerlist_size number 8 Grey Peerlist Size + + STOP - Wallet asks daemon to start mining. Daemon replies with STOP-OK, or ERROR. STOP_OK - Daemon replies to a stop mining request. @@ -123,19 +145,23 @@ Daemon will reply with CLOSE-OK or ERROR. #define WAP_PROTO_OUTPUT_INDEXES_OK 8 #define WAP_PROTO_RANDOM_OUTS 9 #define WAP_PROTO_RANDOM_OUTS_OK 10 -#define WAP_PROTO_GET 11 -#define WAP_PROTO_GET_OK 12 -#define WAP_PROTO_SAVE 13 -#define WAP_PROTO_SAVE_OK 14 -#define WAP_PROTO_START 15 -#define WAP_PROTO_START_OK 16 -#define WAP_PROTO_STOP 17 -#define WAP_PROTO_STOP_OK 18 -#define WAP_PROTO_CLOSE 19 -#define WAP_PROTO_CLOSE_OK 20 -#define WAP_PROTO_PING 21 -#define WAP_PROTO_PING_OK 22 -#define WAP_PROTO_ERROR 23 +#define WAP_PROTO_GET_HEIGHT 11 +#define WAP_PROTO_GET_HEIGHT_OK 12 +#define WAP_PROTO_GET 13 +#define WAP_PROTO_GET_OK 14 +#define WAP_PROTO_SAVE_BC 15 +#define WAP_PROTO_SAVE_BC_OK 16 +#define WAP_PROTO_START 17 +#define WAP_PROTO_START_OK 18 +#define WAP_PROTO_GET_INFO 19 +#define WAP_PROTO_GET_INFO_OK 20 +#define WAP_PROTO_STOP 21 +#define WAP_PROTO_STOP_OK 22 +#define WAP_PROTO_CLOSE 23 +#define WAP_PROTO_CLOSE_OK 24 +#define WAP_PROTO_PING 25 +#define WAP_PROTO_PING_OK 26 +#define WAP_PROTO_ERROR 27 #include @@ -285,6 +311,12 @@ zframe_t * void wap_proto_set_random_outputs (wap_proto_t *self, zframe_t **frame_p); +// Get/set the height field +uint64_t + wap_proto_height (wap_proto_t *self); +void + wap_proto_set_height (wap_proto_t *self, uint64_t height); + // Get a copy of the tx_data field zchunk_t * wap_proto_tx_data (wap_proto_t *self); @@ -311,6 +343,60 @@ uint64_t void wap_proto_set_thread_count (wap_proto_t *self, uint64_t thread_count); +// Get/set the target_height field +uint64_t + wap_proto_target_height (wap_proto_t *self); +void + wap_proto_set_target_height (wap_proto_t *self, uint64_t target_height); + +// Get/set the difficulty field +uint64_t + wap_proto_difficulty (wap_proto_t *self); +void + wap_proto_set_difficulty (wap_proto_t *self, uint64_t difficulty); + +// Get/set the tx_count field +uint64_t + wap_proto_tx_count (wap_proto_t *self); +void + wap_proto_set_tx_count (wap_proto_t *self, uint64_t tx_count); + +// Get/set the tx_pool_size field +uint64_t + wap_proto_tx_pool_size (wap_proto_t *self); +void + wap_proto_set_tx_pool_size (wap_proto_t *self, uint64_t tx_pool_size); + +// Get/set the alt_blocks_count field +uint64_t + wap_proto_alt_blocks_count (wap_proto_t *self); +void + wap_proto_set_alt_blocks_count (wap_proto_t *self, uint64_t alt_blocks_count); + +// Get/set the outgoing_connections_count field +uint64_t + wap_proto_outgoing_connections_count (wap_proto_t *self); +void + wap_proto_set_outgoing_connections_count (wap_proto_t *self, uint64_t outgoing_connections_count); + +// Get/set the incoming_connections_count field +uint64_t + wap_proto_incoming_connections_count (wap_proto_t *self); +void + wap_proto_set_incoming_connections_count (wap_proto_t *self, uint64_t incoming_connections_count); + +// Get/set the white_peerlist_size field +uint64_t + wap_proto_white_peerlist_size (wap_proto_t *self); +void + wap_proto_set_white_peerlist_size (wap_proto_t *self, uint64_t white_peerlist_size); + +// Get/set the grey_peerlist_size field +uint64_t + wap_proto_grey_peerlist_size (wap_proto_t *self); +void + wap_proto_set_grey_peerlist_size (wap_proto_t *self, uint64_t grey_peerlist_size); + // Get/set the reason field const char * wap_proto_reason (wap_proto_t *self); diff --git a/src/ipc/include/wap_server_engine.inc b/src/ipc/include/wap_server_engine.inc index 91d74a355..cc4a6a1e4 100644 --- a/src/ipc/include/wap_server_engine.inc +++ b/src/ipc/include/wap_server_engine.inc @@ -34,16 +34,18 @@ typedef enum { blocks_event = 3, put_event = 4, get_event = 5, - save_event = 6, + save_bc_event = 6, start_event = 7, stop_event = 8, output_indexes_event = 9, random_outs_event = 10, - close_event = 11, - ping_event = 12, - expired_event = 13, - exception_event = 14, - settled_event = 15 + get_height_event = 11, + get_info_event = 12, + close_event = 13, + ping_event = 14, + expired_event = 15, + exception_event = 16, + settled_event = 17 } event_t; // Names for state machine logging and error reporting @@ -64,11 +66,13 @@ s_event_name [] = { "BLOCKS", "PUT", "GET", - "SAVE", + "SAVE_BC", "START", "STOP", "OUTPUT_INDEXES", "RANDOM_OUTS", + "GET_HEIGHT", + "GET_INFO", "CLOSE", "PING", "expired", @@ -144,6 +148,8 @@ static void send_transaction (client_t *self); static void retrieve_transaction (client_t *self); +static void + save_bc (client_t *self); static void start_mining_process (client_t *self); static void @@ -152,6 +158,10 @@ static void output_indexes (client_t *self); static void random_outs (client_t *self); +static void + height (client_t *self); +static void + getinfo (client_t *self); static void deregister_wallet (client_t *self); static void @@ -351,15 +361,21 @@ s_protocol_event (wap_proto_t *message) case WAP_PROTO_RANDOM_OUTS: return random_outs_event; break; + case WAP_PROTO_GET_HEIGHT: + return get_height_event; + break; case WAP_PROTO_GET: return get_event; break; - case WAP_PROTO_SAVE: - return save_event; + case WAP_PROTO_SAVE_BC: + return save_bc_event; break; case WAP_PROTO_START: return start_event; break; + case WAP_PROTO_GET_INFO: + return get_info_event; + break; case WAP_PROTO_STOP: return stop_event; break; @@ -632,13 +648,19 @@ s_client_execute (s_client_t *self, event_t event) } } else - if (self->event == save_event) { + if (self->event == save_bc_event) { if (!self->exception) { - // send SAVE_OK + // save bc if (self->server->verbose) - zsys_debug ("%s: $ send SAVE_OK", + zsys_debug ("%s: $ save bc", self->log_prefix); + save_bc (&self->client); + } + if (!self->exception) { + // send SAVE_BC_OK + if (self->server->verbose) + zsys_debug ("%s: $ send SAVE_BC_OK", self->log_prefix); - wap_proto_set_id (self->server->message, WAP_PROTO_SAVE_OK); + wap_proto_set_id (self->server->message, WAP_PROTO_SAVE_BC_OK); wap_proto_set_routing_id (self->server->message, self->routing_id); wap_proto_send (self->server->message, self->server->router); } @@ -716,6 +738,42 @@ s_client_execute (s_client_t *self, event_t event) } } else + if (self->event == get_height_event) { + if (!self->exception) { + // height + if (self->server->verbose) + zsys_debug ("%s: $ height", self->log_prefix); + height (&self->client); + } + if (!self->exception) { + // send GET_HEIGHT_OK + if (self->server->verbose) + zsys_debug ("%s: $ send GET_HEIGHT_OK", + self->log_prefix); + wap_proto_set_id (self->server->message, WAP_PROTO_GET_HEIGHT_OK); + wap_proto_set_routing_id (self->server->message, self->routing_id); + wap_proto_send (self->server->message, self->server->router); + } + } + else + if (self->event == get_info_event) { + if (!self->exception) { + // getinfo + if (self->server->verbose) + zsys_debug ("%s: $ getinfo", self->log_prefix); + getinfo (&self->client); + } + if (!self->exception) { + // send GET_INFO_OK + if (self->server->verbose) + zsys_debug ("%s: $ send GET_INFO_OK", + self->log_prefix); + wap_proto_set_id (self->server->message, WAP_PROTO_GET_INFO_OK); + wap_proto_set_routing_id (self->server->message, self->routing_id); + wap_proto_send (self->server->message, self->server->router); + } + } + else if (self->event == close_event) { if (!self->exception) { // send CLOSE_OK diff --git a/src/ipc/wap_client/wap_client.c b/src/ipc/wap_client/wap_client.c index f8bb27197..cb4be741e 100644 --- a/src/ipc/wap_client/wap_client.c +++ b/src/ipc/wap_client/wap_client.c @@ -229,25 +229,14 @@ signal_have_get_ok (client_t *self) } -// --------------------------------------------------------------------------- -// prepare_save_command -// - -static void -prepare_save_command (client_t *self) -{ -} - - - // --------------------------------------------------------------------------- // signal_have_save_ok // static void -signal_have_save_ok (client_t *self) +signal_have_save_bc_ok (client_t *self) { - zsock_send (self->cmdpipe, "s8", "SAVE OK", 0); + zsock_send (self->cmdpipe, "s8", "SAVE BC OK", wap_proto_status(self->message)); } @@ -272,6 +261,17 @@ signal_have_stop_ok (client_t *self) zsock_send (self->cmdpipe, "s8", "STOP OK", 0); } +// --------------------------------------------------------------------------- +// signal_have_get_height_ok +// + +static void +signal_have_get_height_ok (client_t *self) +{ + zsock_send (self->cmdpipe, "si8", "GET HEIGHT OK", 0, + wap_proto_height (self->message)); +} + // --------------------------------------------------------------------------- // signal_have_output_indexes_ok // @@ -375,3 +375,24 @@ signal_have_random_outs_ok (client_t *self) wap_proto_status (self->message), wap_proto_get_random_outputs (self->message)); } + +// --------------------------------------------------------------------------- +// signal_have_get_info_ok +// + +static void +signal_have_get_info_ok (client_t *self) +{ + zsock_send (self->cmdpipe, "s88888888888", "GET INFO OK", + wap_proto_status (self->message), + wap_proto_height (self->message), + wap_proto_target_height (self->message), + wap_proto_difficulty (self->message), + wap_proto_tx_count (self->message), + wap_proto_tx_pool_size (self->message), + wap_proto_alt_blocks_count (self->message), + wap_proto_outgoing_connections_count (self->message), + wap_proto_incoming_connections_count (self->message), + wap_proto_white_peerlist_size (self->message), + wap_proto_grey_peerlist_size (self->message)); +} diff --git a/src/ipc/wap_proto.c b/src/ipc/wap_proto.c index 805a65386..0d4c9c16a 100644 --- a/src/ipc/wap_proto.c +++ b/src/ipc/wap_proto.c @@ -46,9 +46,19 @@ struct _wap_proto_t { uint64_t outs_count; // Outs count zframe_t *amounts; // Amounts zframe_t *random_outputs; // Outputs + uint64_t height; // Height zchunk_t *tx_data; // Transaction data zchunk_t *address; // address uint64_t thread_count; // thread_count + uint64_t target_height; // Target Height + uint64_t difficulty; // Difficulty + uint64_t tx_count; // TX Count + uint64_t tx_pool_size; // TX Pool Size + uint64_t alt_blocks_count; // Alt Blocks Count + uint64_t outgoing_connections_count; // Outgoing Connections Count + uint64_t incoming_connections_count; // Incoming Connections Count + uint64_t white_peerlist_size; // White Peerlist Size + uint64_t grey_peerlist_size; // Grey Peerlist Size char reason [256]; // Printable explanation }; @@ -399,6 +409,14 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input) self->random_outputs = zframe_recv (input); break; + case WAP_PROTO_GET_HEIGHT: + break; + + case WAP_PROTO_GET_HEIGHT_OK: + GET_NUMBER8 (self->status); + GET_NUMBER8 (self->height); + break; + case WAP_PROTO_GET: { size_t chunk_size; @@ -427,10 +445,11 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input) } break; - case WAP_PROTO_SAVE: + case WAP_PROTO_SAVE_BC: break; - case WAP_PROTO_SAVE_OK: + case WAP_PROTO_SAVE_BC_OK: + GET_NUMBER8 (self->status); break; case WAP_PROTO_START: @@ -452,6 +471,23 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input) GET_NUMBER8 (self->status); break; + case WAP_PROTO_GET_INFO: + break; + + case WAP_PROTO_GET_INFO_OK: + GET_NUMBER8 (self->status); + GET_NUMBER8 (self->height); + GET_NUMBER8 (self->target_height); + GET_NUMBER8 (self->difficulty); + GET_NUMBER8 (self->tx_count); + GET_NUMBER8 (self->tx_pool_size); + GET_NUMBER8 (self->alt_blocks_count); + GET_NUMBER8 (self->outgoing_connections_count); + GET_NUMBER8 (self->incoming_connections_count); + GET_NUMBER8 (self->white_peerlist_size); + GET_NUMBER8 (self->grey_peerlist_size); + break; + case WAP_PROTO_STOP: break; @@ -549,6 +585,10 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) case WAP_PROTO_RANDOM_OUTS_OK: frame_size += 8; // status break; + case WAP_PROTO_GET_HEIGHT_OK: + frame_size += 8; // status + frame_size += 8; // height + break; case WAP_PROTO_GET: frame_size += 4; // Size is 4 octets if (self->tx_id) @@ -559,6 +599,9 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) if (self->tx_data) frame_size += zchunk_size (self->tx_data); break; + case WAP_PROTO_SAVE_BC_OK: + frame_size += 8; // status + break; case WAP_PROTO_START: frame_size += 4; // Size is 4 octets if (self->address) @@ -568,6 +611,19 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) case WAP_PROTO_START_OK: frame_size += 8; // status break; + case WAP_PROTO_GET_INFO_OK: + frame_size += 8; // status + frame_size += 8; // height + frame_size += 8; // target_height + frame_size += 8; // difficulty + frame_size += 8; // tx_count + frame_size += 8; // tx_pool_size + frame_size += 8; // alt_blocks_count + frame_size += 8; // outgoing_connections_count + frame_size += 8; // incoming_connections_count + frame_size += 8; // white_peerlist_size + frame_size += 8; // grey_peerlist_size + break; case WAP_PROTO_ERROR: frame_size += 2; // status frame_size += 1 + strlen (self->reason); @@ -654,6 +710,11 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) nbr_frames++; break; + case WAP_PROTO_GET_HEIGHT_OK: + PUT_NUMBER8 (self->status); + PUT_NUMBER8 (self->height); + break; + case WAP_PROTO_GET: if (self->tx_id) { PUT_NUMBER4 (zchunk_size (self->tx_id)); @@ -678,6 +739,10 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) PUT_NUMBER4 (0); // Empty chunk break; + case WAP_PROTO_SAVE_BC_OK: + PUT_NUMBER8 (self->status); + break; + case WAP_PROTO_START: if (self->address) { PUT_NUMBER4 (zchunk_size (self->address)); @@ -695,6 +760,20 @@ wap_proto_send (wap_proto_t *self, zsock_t *output) PUT_NUMBER8 (self->status); break; + case WAP_PROTO_GET_INFO_OK: + PUT_NUMBER8 (self->status); + PUT_NUMBER8 (self->height); + PUT_NUMBER8 (self->target_height); + PUT_NUMBER8 (self->difficulty); + PUT_NUMBER8 (self->tx_count); + PUT_NUMBER8 (self->tx_pool_size); + PUT_NUMBER8 (self->alt_blocks_count); + PUT_NUMBER8 (self->outgoing_connections_count); + PUT_NUMBER8 (self->incoming_connections_count); + PUT_NUMBER8 (self->white_peerlist_size); + PUT_NUMBER8 (self->grey_peerlist_size); + break; + case WAP_PROTO_ERROR: PUT_NUMBER2 (self->status); PUT_STRING (self->reason); @@ -833,6 +912,16 @@ wap_proto_print (wap_proto_t *self) zsys_debug ("(NULL)"); break; + case WAP_PROTO_GET_HEIGHT: + zsys_debug ("WAP_PROTO_GET_HEIGHT:"); + break; + + case WAP_PROTO_GET_HEIGHT_OK: + zsys_debug ("WAP_PROTO_GET_HEIGHT_OK:"); + zsys_debug (" status=%ld", (long) self->status); + zsys_debug (" height=%ld", (long) self->height); + break; + case WAP_PROTO_GET: zsys_debug ("WAP_PROTO_GET:"); zsys_debug (" tx_id=[ ... ]"); @@ -843,12 +932,13 @@ wap_proto_print (wap_proto_t *self) zsys_debug (" tx_data=[ ... ]"); break; - case WAP_PROTO_SAVE: - zsys_debug ("WAP_PROTO_SAVE:"); + case WAP_PROTO_SAVE_BC: + zsys_debug ("WAP_PROTO_SAVE_BC:"); break; - case WAP_PROTO_SAVE_OK: - zsys_debug ("WAP_PROTO_SAVE_OK:"); + case WAP_PROTO_SAVE_BC_OK: + zsys_debug ("WAP_PROTO_SAVE_BC_OK:"); + zsys_debug (" status=%ld", (long) self->status); break; case WAP_PROTO_START: @@ -862,6 +952,25 @@ wap_proto_print (wap_proto_t *self) zsys_debug (" status=%ld", (long) self->status); break; + case WAP_PROTO_GET_INFO: + zsys_debug ("WAP_PROTO_GET_INFO:"); + break; + + case WAP_PROTO_GET_INFO_OK: + zsys_debug ("WAP_PROTO_GET_INFO_OK:"); + zsys_debug (" status=%ld", (long) self->status); + zsys_debug (" height=%ld", (long) self->height); + zsys_debug (" target_height=%ld", (long) self->target_height); + zsys_debug (" difficulty=%ld", (long) self->difficulty); + zsys_debug (" tx_count=%ld", (long) self->tx_count); + zsys_debug (" tx_pool_size=%ld", (long) self->tx_pool_size); + zsys_debug (" alt_blocks_count=%ld", (long) self->alt_blocks_count); + zsys_debug (" outgoing_connections_count=%ld", (long) self->outgoing_connections_count); + zsys_debug (" incoming_connections_count=%ld", (long) self->incoming_connections_count); + zsys_debug (" white_peerlist_size=%ld", (long) self->white_peerlist_size); + zsys_debug (" grey_peerlist_size=%ld", (long) self->grey_peerlist_size); + break; + case WAP_PROTO_STOP: zsys_debug ("WAP_PROTO_STOP:"); break; @@ -969,17 +1078,23 @@ wap_proto_command (wap_proto_t *self) case WAP_PROTO_RANDOM_OUTS_OK: return ("RANDOM_OUTS_OK"); break; + case WAP_PROTO_GET_HEIGHT: + return ("GET_HEIGHT"); + break; + case WAP_PROTO_GET_HEIGHT_OK: + return ("GET_HEIGHT_OK"); + break; case WAP_PROTO_GET: return ("GET"); break; case WAP_PROTO_GET_OK: return ("GET_OK"); break; - case WAP_PROTO_SAVE: - return ("SAVE"); + case WAP_PROTO_SAVE_BC: + return ("SAVE_BC"); break; - case WAP_PROTO_SAVE_OK: - return ("SAVE_OK"); + case WAP_PROTO_SAVE_BC_OK: + return ("SAVE_BC_OK"); break; case WAP_PROTO_START: return ("START"); @@ -987,6 +1102,12 @@ wap_proto_command (wap_proto_t *self) case WAP_PROTO_START_OK: return ("START_OK"); break; + case WAP_PROTO_GET_INFO: + return ("GET_INFO"); + break; + case WAP_PROTO_GET_INFO_OK: + return ("GET_INFO_OK"); + break; case WAP_PROTO_STOP: return ("STOP"); break; @@ -1339,6 +1460,24 @@ wap_proto_set_random_outputs (wap_proto_t *self, zframe_t **frame_p) } +// -------------------------------------------------------------------------- +// Get/set the height field + +uint64_t +wap_proto_height (wap_proto_t *self) +{ + assert (self); + return self->height; +} + +void +wap_proto_set_height (wap_proto_t *self, uint64_t height) +{ + assert (self); + self->height = height; +} + + // -------------------------------------------------------------------------- // Get the tx_data field without transferring ownership @@ -1423,6 +1562,168 @@ wap_proto_set_thread_count (wap_proto_t *self, uint64_t thread_count) } +// -------------------------------------------------------------------------- +// Get/set the target_height field + +uint64_t +wap_proto_target_height (wap_proto_t *self) +{ + assert (self); + return self->target_height; +} + +void +wap_proto_set_target_height (wap_proto_t *self, uint64_t target_height) +{ + assert (self); + self->target_height = target_height; +} + + +// -------------------------------------------------------------------------- +// Get/set the difficulty field + +uint64_t +wap_proto_difficulty (wap_proto_t *self) +{ + assert (self); + return self->difficulty; +} + +void +wap_proto_set_difficulty (wap_proto_t *self, uint64_t difficulty) +{ + assert (self); + self->difficulty = difficulty; +} + + +// -------------------------------------------------------------------------- +// Get/set the tx_count field + +uint64_t +wap_proto_tx_count (wap_proto_t *self) +{ + assert (self); + return self->tx_count; +} + +void +wap_proto_set_tx_count (wap_proto_t *self, uint64_t tx_count) +{ + assert (self); + self->tx_count = tx_count; +} + + +// -------------------------------------------------------------------------- +// Get/set the tx_pool_size field + +uint64_t +wap_proto_tx_pool_size (wap_proto_t *self) +{ + assert (self); + return self->tx_pool_size; +} + +void +wap_proto_set_tx_pool_size (wap_proto_t *self, uint64_t tx_pool_size) +{ + assert (self); + self->tx_pool_size = tx_pool_size; +} + + +// -------------------------------------------------------------------------- +// Get/set the alt_blocks_count field + +uint64_t +wap_proto_alt_blocks_count (wap_proto_t *self) +{ + assert (self); + return self->alt_blocks_count; +} + +void +wap_proto_set_alt_blocks_count (wap_proto_t *self, uint64_t alt_blocks_count) +{ + assert (self); + self->alt_blocks_count = alt_blocks_count; +} + + +// -------------------------------------------------------------------------- +// Get/set the outgoing_connections_count field + +uint64_t +wap_proto_outgoing_connections_count (wap_proto_t *self) +{ + assert (self); + return self->outgoing_connections_count; +} + +void +wap_proto_set_outgoing_connections_count (wap_proto_t *self, uint64_t outgoing_connections_count) +{ + assert (self); + self->outgoing_connections_count = outgoing_connections_count; +} + + +// -------------------------------------------------------------------------- +// Get/set the incoming_connections_count field + +uint64_t +wap_proto_incoming_connections_count (wap_proto_t *self) +{ + assert (self); + return self->incoming_connections_count; +} + +void +wap_proto_set_incoming_connections_count (wap_proto_t *self, uint64_t incoming_connections_count) +{ + assert (self); + self->incoming_connections_count = incoming_connections_count; +} + + +// -------------------------------------------------------------------------- +// Get/set the white_peerlist_size field + +uint64_t +wap_proto_white_peerlist_size (wap_proto_t *self) +{ + assert (self); + return self->white_peerlist_size; +} + +void +wap_proto_set_white_peerlist_size (wap_proto_t *self, uint64_t white_peerlist_size) +{ + assert (self); + self->white_peerlist_size = white_peerlist_size; +} + + +// -------------------------------------------------------------------------- +// Get/set the grey_peerlist_size field + +uint64_t +wap_proto_grey_peerlist_size (wap_proto_t *self) +{ + assert (self); + return self->grey_peerlist_size; +} + +void +wap_proto_set_grey_peerlist_size (wap_proto_t *self, uint64_t grey_peerlist_size) +{ + assert (self); + self->grey_peerlist_size = grey_peerlist_size; +} + + // -------------------------------------------------------------------------- // Get/set the reason field @@ -1634,6 +1935,30 @@ wap_proto_test (bool verbose) assert (zframe_streq (wap_proto_random_outputs (self), "Captcha Diem")); zframe_destroy (&random_outs_ok_random_outputs); } + wap_proto_set_id (self, WAP_PROTO_GET_HEIGHT); + + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + } + wap_proto_set_id (self, WAP_PROTO_GET_HEIGHT_OK); + + wap_proto_set_status (self, 123); + wap_proto_set_height (self, 123); + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + assert (wap_proto_status (self) == 123); + assert (wap_proto_height (self) == 123); + } wap_proto_set_id (self, WAP_PROTO_GET); zchunk_t *get_tx_id = zchunk_new ("Captcha Diem", 12); @@ -1662,7 +1987,7 @@ wap_proto_test (bool verbose) assert (memcmp (zchunk_data (wap_proto_tx_data (self)), "Captcha Diem", 12) == 0); zchunk_destroy (&get_ok_tx_data); } - wap_proto_set_id (self, WAP_PROTO_SAVE); + wap_proto_set_id (self, WAP_PROTO_SAVE_BC); // Send twice wap_proto_send (self, output); @@ -1672,8 +1997,9 @@ wap_proto_test (bool verbose) wap_proto_recv (self, input); assert (wap_proto_routing_id (self)); } - wap_proto_set_id (self, WAP_PROTO_SAVE_OK); + wap_proto_set_id (self, WAP_PROTO_SAVE_BC_OK); + wap_proto_set_status (self, 123); // Send twice wap_proto_send (self, output); wap_proto_send (self, output); @@ -1681,6 +2007,7 @@ wap_proto_test (bool verbose) for (instance = 0; instance < 2; instance++) { wap_proto_recv (self, input); assert (wap_proto_routing_id (self)); + assert (wap_proto_status (self) == 123); } wap_proto_set_id (self, WAP_PROTO_START); @@ -1710,6 +2037,48 @@ wap_proto_test (bool verbose) assert (wap_proto_routing_id (self)); assert (wap_proto_status (self) == 123); } + wap_proto_set_id (self, WAP_PROTO_GET_INFO); + + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + } + wap_proto_set_id (self, WAP_PROTO_GET_INFO_OK); + + wap_proto_set_status (self, 123); + wap_proto_set_height (self, 123); + wap_proto_set_target_height (self, 123); + wap_proto_set_difficulty (self, 123); + wap_proto_set_tx_count (self, 123); + wap_proto_set_tx_pool_size (self, 123); + wap_proto_set_alt_blocks_count (self, 123); + wap_proto_set_outgoing_connections_count (self, 123); + wap_proto_set_incoming_connections_count (self, 123); + wap_proto_set_white_peerlist_size (self, 123); + wap_proto_set_grey_peerlist_size (self, 123); + // Send twice + wap_proto_send (self, output); + wap_proto_send (self, output); + + for (instance = 0; instance < 2; instance++) { + wap_proto_recv (self, input); + assert (wap_proto_routing_id (self)); + assert (wap_proto_status (self) == 123); + assert (wap_proto_height (self) == 123); + assert (wap_proto_target_height (self) == 123); + assert (wap_proto_difficulty (self) == 123); + assert (wap_proto_tx_count (self) == 123); + assert (wap_proto_tx_pool_size (self) == 123); + assert (wap_proto_alt_blocks_count (self) == 123); + assert (wap_proto_outgoing_connections_count (self) == 123); + assert (wap_proto_incoming_connections_count (self) == 123); + assert (wap_proto_white_peerlist_size (self) == 123); + assert (wap_proto_grey_peerlist_size (self) == 123); + } wap_proto_set_id (self, WAP_PROTO_STOP); // Send twice diff --git a/src/ipc/wap_server/wap_server.c b/src/ipc/wap_server/wap_server.c index 7b6520498..9f108763f 100644 --- a/src/ipc/wap_server/wap_server.c +++ b/src/ipc/wap_server/wap_server.c @@ -270,3 +270,33 @@ random_outs (client_t *self) { IPC::Daemon::get_random_outs(self->message); } + +// --------------------------------------------------------------------------- +// height +// + +static void +height (client_t *self) +{ + IPC::Daemon::get_height(self->message); +} + +// --------------------------------------------------------------------------- +// save_bc +// + +static void +save_bc (client_t *self) +{ + IPC::Daemon::save_bc(self->message); +} + +// --------------------------------------------------------------------------- +// getinfo +// + +static void +getinfo (client_t *self) +{ + IPC::Daemon::get_info(self->message); +} diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 6aa90c9ea..ce95d424c 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -28,8 +28,7 @@ set(rpc_sources core_rpc_server.cpp - json_rpc_http_server.cpp - daemon_json_rpc_handlers.cpp) + json_rpc_http_server.cpp) set(rpc_headers) @@ -55,3 +54,24 @@ target_link_libraries(rpc ${EXTRA_LIBRARIES}) add_dependencies(rpc version) + +set(translator_rpc_sources + daemon_deprecated_rpc.cpp + json_rpc_http_server.cpp + json_rpc.cpp) +bitmonero_add_executable(rpc_translator + ${translator_rpc_sources} +) +target_link_libraries(rpc_translator + LINK_PRIVATE + client_ipc + cryptonote_core + cryptonote_protocol + ${EXTRA_LIBRARIES} + ${NET_SKELETON_LIBRARY} + ${ZMQ_LIB} + ${CZMQ_LIB} + ${CMAKE_THREAD_LIBS_INIT}) +set_property(TARGET rpc_translator + PROPERTY + OUTPUT_NAME "monero-rpc-deprecated") diff --git a/src/rpc/daemon_deprecated_rpc.cpp b/src/rpc/daemon_deprecated_rpc.cpp new file mode 100644 index 000000000..a6154c8ac --- /dev/null +++ b/src/rpc/daemon_deprecated_rpc.cpp @@ -0,0 +1,333 @@ +/*! + * \file rpc_translator.cpp + * \brief Implementations of JSON RPC handlers (Daemon) + */ + +// NOTE: +// While this uses net_skeleton (aka fossa) for JSON RPC handling, JSON parsing +// and string conversion are done with rapidjson because it is way easier and better +// suited. +// To add a new method, add the name and function pointer to `method_names` and `handlers`. +// The handler function should have the same signature as the rest of them here. +// It should use rapidjson to parse the request string and the internal objects kept in the +// anonymous namespace to generate the response. The response must eventually get +// stringified using rapidjson. +// Trivial and error responses may be returned with ns_create_rpc_reply and ns_create_rpc_error +// respectively. + +#include "daemon_deprecated_rpc.h" +#include + +#define MAX_RESPONSE_SIZE 2000 + +/*! + * \namespace + * \brief Anonymous namespace to keep things in the scope of this file. + */ +namespace +{ + int daemon_connection_error = -326701; + int parse_error = -32700; + int invalid_request = -32600; + int invalid_params = -32602; + int internal_error = -32603; + + RPC::Json_rpc_http_server *server = NULL; + wap_client_t *ipc_client = NULL; + + const char* STATUS_OK = "OK"; + + bool check_connection_to_daemon() + { + return ipc_client && wap_client_connected(ipc_client); + } + + void connect_to_daemon() { + if (check_connection_to_daemon()) { + return; + } + ipc_client = wap_client_new(); + wap_client_connect(ipc_client, "ipc://@/monero", 200, "wallet identity"); + } + + /*! + * \brief Constructs a response string given a result JSON object. + * + * It also adds boilerplate properties like id, method. + * \param req net_skeleton request object + * \param result_json rapidjson result object + * \param response_json Root rapidjson document that will eventually have the whole response + * \param response Response as a string gets written here. + */ + void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json, + rapidjson::Document &response_json, std::string &response) + { + response_json.SetObject(); + response_json.AddMember("jsonrpc", "2.0" , response_json.GetAllocator()); + rapidjson::Value string_value(rapidjson::kStringType); + // If ID was present in request use it else use "null". + if (req->id != NULL) + { + string_value.SetString(req->id[0].ptr, req->id[0].len); + } + else + { + string_value.SetString("null", 4); + } + response_json.AddMember("id", string_value, response_json.GetAllocator()); + string_value.SetString(req->method[0].ptr, req->method[0].len); + response_json.AddMember("method", string_value, response_json.GetAllocator()); + response_json.AddMember("result", result_json, response_json.GetAllocator()); + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + response_json.Accept(writer); + // Write string to `response`. + response = buffer.GetString(); + } + /*! + * \brief Implementation of 'getheight' method. + * \param buf Buffer to fill in response. + * \param len Max length of response. + * \param req net_skeleton RPC request + * \return Actual response length. + */ + int getheight(char *buf, int len, struct ns_rpc_request *req) + { + connect_to_daemon(); + int rc = wap_client_get_height(ipc_client); + if (rc < 0) { + return ns_rpc_create_error(buf, len, req, daemon_connection_error, + "Couldn't connect to daemon.", "{}"); + } + uint64_t height = wap_client_height(ipc_client); + rapidjson::Document response_json; + rapidjson::Value result_json; + result_json.SetObject(); + result_json.AddMember("height", height, response_json.GetAllocator()); + result_json.AddMember("status", "OK", response_json.GetAllocator()); + std::string response; + construct_response_string(req, result_json, response_json, response); + size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; + strncpy(buf, response.c_str(), copy_length); + return response.length(); + } + + /*! + * \brief Implementation of 'startmining' method. + * \param buf Buffer to fill in response. + * \param len Max length of response. + * \param req net_skeleton RPC request + * \return Actual response length. + */ + int startmining(char *buf, int len, struct ns_rpc_request *req) + { + connect_to_daemon(); + if (req->params == NULL) + { + return ns_rpc_create_error(buf, len, req, invalid_params, + "Parameters missing.", "{}"); + } + rapidjson::Document request_json; + char request_buf[1000]; + strncpy(request_buf, req->params[0].ptr, req->params[0].len); + request_buf[req->params[0].len] = '\0'; + if (request_json.Parse(request_buf).HasParseError()) + { + return ns_rpc_create_error(buf, len, req, parse_error, + "Invalid JSON passed", "{}"); + } + + if (!request_json.HasMember("miner_address") || !request_json["miner_address"].IsString()) + { + return ns_rpc_create_error(buf, len, req, invalid_params, + "Incorrect miner_address", "{}"); + } + if (!request_json.HasMember("threads_count") || !request_json["threads_count"].IsUint64()) + { + return ns_rpc_create_error(buf, len, req, invalid_params, + "Incorrect threads_count", "{}"); + } + + std::string miner_address = request_json["miner_address"].GetString(); + uint64_t threads_count = request_json["threads_count"].GetUint(); + + zchunk_t *address_chunk = zchunk_new((void*)miner_address.c_str(), miner_address.length()); + int rc = wap_client_start(ipc_client, &address_chunk, threads_count); + zchunk_destroy(&address_chunk); + if (rc < 0) { + return ns_rpc_create_error(buf, len, req, daemon_connection_error, + "Couldn't connect to daemon.", "{}"); + } + uint64_t status = wap_client_status(ipc_client); + + if (status == IPC::STATUS_WRONG_ADDRESS) + { + return ns_rpc_create_error(buf, len, req, invalid_params, + "Failed, wrong address", "{}"); + } + if (status == IPC::STATUS_MINING_NOT_STARTED) + { + return ns_rpc_create_error(buf, len, req, invalid_request, + "Failed, mining not started", "{}"); + } + return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", STATUS_OK); + } + + /*! + * \brief Implementation of 'stopmining' method. + * \param buf Buffer to fill in response. + * \param len Max length of response. + * \param req net_skeleton RPC request + * \return Actual response length. + */ + int stopmining(char *buf, int len, struct ns_rpc_request *req) + { + connect_to_daemon(); + int rc = wap_client_stop(ipc_client); + if (rc < 0) { + return ns_rpc_create_error(buf, len, req, daemon_connection_error, + "Couldn't connect to daemon.", "{}"); + } + if (wap_client_status(ipc_client) != IPC::STATUS_OK) + { + return ns_rpc_create_error(buf, len, req, invalid_request, + "Failed, mining not stopped", "{}"); + } + return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", STATUS_OK); + } + + /*! + * \brief Implementation of 'getinfo' method. + * \param buf Buffer to fill in response. + * \param len Max length of response. + * \param req net_skeleton RPC request + * \return Actual response length. + */ + int getinfo(char *buf, int len, struct ns_rpc_request *req) + { + connect_to_daemon(); + int rc = wap_client_get_info(ipc_client); + if (rc < 0) { + return ns_rpc_create_error(buf, len, req, daemon_connection_error, + "Couldn't connect to daemon.", "{}"); + } + if (wap_client_status(ipc_client) != IPC::STATUS_OK) + { + return ns_rpc_create_error(buf, len, req, invalid_request, + "Failed to get info", "{}"); + } + rapidjson::Document response_json; + rapidjson::Value result_json; + result_json.SetObject(); + result_json.AddMember("height", wap_client_height(ipc_client), response_json.GetAllocator()); + result_json.AddMember("target_height", wap_client_target_height(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("difficulty", wap_client_difficulty(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("tx_count", wap_client_tx_count(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("tx_pool_size", wap_client_tx_pool_size(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("alt_blocks_count", wap_client_alt_blocks_count(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("outgoing_connections_count", wap_client_outgoing_connections_count(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("incoming_connections_count", wap_client_incoming_connections_count(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("white_peerlist_size", wap_client_white_peerlist_size(ipc_client), + response_json.GetAllocator()); + result_json.AddMember("grey_peerlist_size", wap_client_grey_peerlist_size(ipc_client), + response_json.GetAllocator()); + + std::string response; + construct_response_string(req, result_json, response_json, response); + size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; + strncpy(buf, response.c_str(), copy_length); + return response.length(); + } + + // Contains a list of method names. + const char *method_names[] = { + "getheight", + "startmining", + "stopmining", + "getinfo", + NULL + }; + + // Contains a list of function pointers. These must map 1-1 by index with `method_names`. + ns_rpc_handler_t handlers[] = { + getheight, + startmining, + stopmining, + getinfo, + NULL + }; + + /*! + * \brief Event handler that is invoked upon net_skeleton network events. + * + * Any change in behavior of RPC should happen from this point. + * \param nc net_skeleton connection + * \param ev Type of event + * \param ev_data Event data + */ + void ev_handler(struct ns_connection *nc, int ev, void *ev_data) + { + struct http_message *hm = (struct http_message *) ev_data; + char buf[MAX_RESPONSE_SIZE]; + switch (ev) { + case NS_HTTP_REQUEST: + ns_rpc_dispatch(hm->body.p, hm->body.len, buf, sizeof(buf), + method_names, handlers); + ns_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n" + "Content-Type: application/json\r\n\r\n%s", + (int) strlen(buf), buf); + nc->flags |= NSF_FINISHED_SENDING_DATA; + break; + default: + break; + } + } +} + +/*! + * \namespace RPC + * \brief RPC related utilities + */ +namespace RPC +{ + /*! + * \namespace Daemon + * \brief RPC relevant to daemon + */ + namespace DaemonDeprecated + { + + int start() { + server = new RPC::Json_rpc_http_server("127.0.0.1", "9997", "daemon_json_rpc", &ev_handler); + if (!server->start()) { + return FAILURE_HTTP_SERVER; + } + std::cout << "Started Daemon server at 127.0.0.1/daemon_json_rpc:9997\n"; + ipc_client = wap_client_new(); + wap_client_connect(ipc_client, "ipc://@/monero", 200, "wallet identity"); + if (!check_connection_to_daemon()) { + return FAILURE_DAEMON_NOT_RUNNING; + } + return SUCCESS; + } + + void stop() { + if (server) { + server->stop(); + delete server; + } + std::cout << "HTTP done\n\n"; + if (ipc_client) { + wap_client_destroy(&ipc_client); + } + std::cout << "IPC done\n\n"; + } + } +} diff --git a/src/rpc/daemon_deprecated_rpc.h b/src/rpc/daemon_deprecated_rpc.h new file mode 100644 index 000000000..6ea1e820c --- /dev/null +++ b/src/rpc/daemon_deprecated_rpc.h @@ -0,0 +1,48 @@ +/*! + * \file daemon_json_rpc_handlers.h + * \brief Header for JSON RPC handlers (Daemon) + */ + +#ifndef DAEMON_JSON_RPC_HANDLERS_H +#define DAEMON_JSON_RPC_HANDLERS_H + +#include "net_skeleton/net_skeleton.h" +#include "json_rpc_http_server.h" +#include "common/command_line.h" +#include "net/http_server_impl_base.h" +#include "cryptonote_core/cryptonote_core.h" +#include "p2p/net_node.h" +#include "cryptonote_protocol/cryptonote_protocol_handler.h" +#include +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include +#include "cryptonote_core/cryptonote_basic.h" +#include "crypto/hash-ops.h" +#include "ipc/include/wallet.h" +#include "ipc/include/daemon_ipc_handlers.h" + +#include + +/*! + * \namespace RPC + * \brief RPC related utilities + */ +namespace RPC +{ + /*! + * \namespace Daemon + * \brief RPC relevant to daemon + */ + namespace DaemonDeprecated + { + const int SUCCESS = 0; + const int FAILURE_DAEMON_NOT_RUNNING = 1; + const int FAILURE_HTTP_SERVER = 2; + int start(); + void stop(); + } +} + +#endif diff --git a/src/rpc/daemon_json_rpc_handlers.cpp b/src/rpc/daemon_json_rpc_handlers.cpp deleted file mode 100644 index bcfacc7bf..000000000 --- a/src/rpc/daemon_json_rpc_handlers.cpp +++ /dev/null @@ -1,1197 +0,0 @@ -/*! - * \file daemon_json_rpc_handlers.cpp - * \brief Implementations of JSON RPC handlers (Daemon) - */ - -// NOTE: -// While this uses net_skeleton (aka fossa) for JSON RPC handling, JSON parsing -// and string conversion are done with rapidjson because it is way easier and better -// suited. -// To add a new method, add the name and function pointer to `method_names` and `handlers`. -// The handler function should have the same signature as the rest of them here. -// It should use rapidjson to parse the request string and the internal objects kept in the -// anonymous namespace to generate the response. The response must eventually get -// stringified using rapidjson. -// Trivial and error responses may be returned with ns_create_rpc_reply and ns_create_rpc_error -// respectively. - -#include "daemon_json_rpc_handlers.h" - -#define CHECK_CORE_BUSY() if (check_core_busy()) { \ - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, \ - CORE_RPC_STATUS_BUSY, "{}"); } - -#define MAX_RESPONSE_SIZE 2000 - -/*! - * \namespace - * \brief Anonymous namespace to keep things in the scope of this file. - */ -namespace -{ - cryptonote::core *core; - nodetool::node_server > *p2p; - bool testnet; - - const command_line::arg_descriptor arg_rpc_bind_ip = { - "rpc-bind-ip", - "IP for RPC server", - "127.0.0.1" - }; - - const command_line::arg_descriptor arg_rpc_bind_port = { - "rpc-bind-port", - "Port for RPC server", - std::to_string(config::RPC_DEFAULT_PORT) - }; - - const command_line::arg_descriptor arg_testnet_rpc_bind_port = { - "testnet-rpc-bind-port", - "Port for testnet RPC server", - std::to_string(config::testnet::RPC_DEFAULT_PORT) - }; - - /*! - * \brief Tells if core is busy - * \return True if core is busy, false otherwise. - */ - bool check_core_busy() - { - if (p2p->get_payload_object().get_core().get_blockchain_storage().is_storing_blockchain()) - { - return true; - } - return false; - } - - /*! - * \brief Constructs a response string given a result JSON object. - * - * It also adds boilerplate properties like id, method. - * \param req net_skeleton request object - * \param result_json rapidjson result object - * \param response_json Root rapidjson document that will eventually have the whole response - * \param response Response as a string gets written here. - */ - void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json, - rapidjson::Document &response_json, std::string &response) - { - response_json.SetObject(); - rapidjson::Value string_value(rapidjson::kStringType); - // If ID was present in request use it else use "null". - if (req->id != NULL) - { - string_value.SetString(req->id[0].ptr, req->id[0].len); - } - else - { - string_value.SetString("null", 4); - } - response_json.AddMember("id", string_value, response_json.GetAllocator()); - string_value.SetString(req->method[0].ptr, req->method[0].len); - response_json.AddMember("method", string_value, response_json.GetAllocator()); - response_json.AddMember("result", result_json, response_json.GetAllocator()); - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - response_json.Accept(writer); - // Write string to `response`. - response = buffer.GetString(); - } - - /*! - * \brief equivalent of strstr, but with arbitrary bytes (ie, NULs) - * - * This does not differentiate between "not found" and "found at offset 0" - * \param start_buff String to search - * \param buflen length of string - * \param pat Pattern to search - * \param patlen Length of pattern - * \return Position of match - */ - uint64_t slow_memmem(const void *start_buff, size_t buflen, const void *pat, size_t patlen) - { - const void *buf = start_buff; - const void *end = (const char*)buf + buflen; - if (patlen > buflen || patlen == 0) - { - return 0; - } - while (buflen > 0 && (buf = memchr(buf,((const char*)pat)[0], buflen - patlen + 1))) - { - if (memcmp(buf,pat,patlen) == 0) - return (const char*)buf - (const char*)start_buff; - buf = (const char*)buf + 1; - buflen = (const char*)end - (const char*)buf; - } - return 0; - } - - uint64_t get_block_reward(const cryptonote::block& blk) - { - uint64_t reward = 0; - BOOST_FOREACH(const cryptonote::tx_out& out, blk.miner_tx.vout) - { - reward += out.amount; - } - return reward; - } - - void fill_block_header_response(const cryptonote::block& blk, bool orphan_status, uint64_t height, - const crypto::hash& hash, rapidjson::Value &header_response, rapidjson::Document &root_doc) - { - rapidjson::Value string_value(rapidjson::kStringType); - header_response.AddMember("major_version", blk.major_version, root_doc.GetAllocator()); - header_response.AddMember("minor_version", blk.minor_version, root_doc.GetAllocator()); - header_response.AddMember("timestamp", blk.timestamp, root_doc.GetAllocator()); - std::string string_prev_hash = epee::string_tools::pod_to_hex(blk.prev_id); - string_value.SetString(string_prev_hash.c_str(), string_prev_hash.length()); - header_response.AddMember("prev_hash", string_value, root_doc.GetAllocator()); - header_response.AddMember("nonce", blk.nonce, root_doc.GetAllocator()); - header_response.AddMember("orphan_status", orphan_status, root_doc.GetAllocator()); - header_response.AddMember("height", height, root_doc.GetAllocator()); - header_response.AddMember("depth", core->get_current_blockchain_height() - height - 1, - root_doc.GetAllocator()); - std::string string_hash = epee::string_tools::pod_to_hex(hash); - string_value.SetString(string_hash.c_str(), string_hash.length()); - header_response.AddMember("hash", string_value, root_doc.GetAllocator()); - header_response.AddMember("difficulty", core->get_blockchain_storage().block_difficulty(height), - root_doc.GetAllocator()); - header_response.AddMember("reward", get_block_reward(blk), root_doc.GetAllocator()); - } - - // The actual RPC method implementations start here. - - /*! - * \brief Implementation of 'getheight' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getheight(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - uint64_t height = core->get_current_blockchain_height(); - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("height", height, response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblocks' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblocks(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - - if (!request_json.HasMember("start_height") || !request_json["start_height"].IsUint64()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect start_height", "{}"); - } - if (!request_json.HasMember("block_ids") || !request_json["block_ids"].IsArray()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect block_ids", "{}"); - } - - uint64_t start_height = request_json["start_height"].GetUint(); - std::list block_ids; - int ii = 0; - for (rapidjson::Value::ConstValueIterator it = request_json["block_ids"].Begin(); - it != request_json["block_ids"].End(); it++, ii++) - { - crypto::hash hash; - if (!it->IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Wrong type in block_ids", "{}"); - } - if (strlen(it->GetString()) > crypto::HASH_SIZE) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Block ID exceeds length.", "{}"); - } - strcpy(hash.data, it->GetString()); - block_ids.push_back(hash); - } - - std::list > > bs; - uint64_t result_current_height = 0; - uint64_t result_start_height = 0; - if (!core->find_blockchain_supplement(start_height, block_ids, bs, result_current_height, - result_start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Failed", "{}"); - } - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - rapidjson::Value block_json(rapidjson::kArrayType); - rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator(); - BOOST_FOREACH(auto &b, bs) - { - rapidjson::Value this_block(rapidjson::kObjectType); - std::string blob = block_to_blob(b.first); - rapidjson::Value string_value(rapidjson::kStringType); - string_value.SetString(blob.c_str(), blob.length()); - this_block.AddMember("block", string_value, allocator); - rapidjson::Value txs_blocks(rapidjson::kArrayType); - BOOST_FOREACH(auto &t, b.second) - { - blob = cryptonote::tx_to_blob(t); - string_value.SetString(blob.c_str(), blob.length()); - txs_blocks.PushBack(string_value.Move(), allocator); - } - this_block.AddMember("txs", txs_blocks, allocator); - block_json.PushBack(this_block, allocator); - } - - result_json.AddMember("start_height", result_start_height, allocator); - result_json.AddMember("current_height", result_current_height, allocator); - result_json.AddMember("status", CORE_RPC_STATUS_OK, allocator); - result_json.AddMember("blocks", block_json, allocator); - - std::string response; - construct_response_string(req, result_json, response_json, response); - - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'gettransactions' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int gettransactions(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - - if (!request_json.HasMember("txs_hashes") || !request_json["txs_hashes"].IsArray()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect txs_hashes", "{}"); - } - - std::list txs_hashes; - for (rapidjson::Value::ConstValueIterator it = request_json["txs_hashes"].Begin(); - it != request_json["txs_hashes"].End(); it++) - { - if (!it->IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Wrong type in txs_hashes", "{}"); - } - txs_hashes.push_back(std::string(it->GetString())); - } - std::vector vh; - BOOST_FOREACH(const auto& tx_hex_str, txs_hashes) - { - cryptonote::blobdata b; - if (!epee::string_tools::parse_hexstr_to_binbuff(tx_hex_str, b)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Failed to parse hex representation of transaction hash", "{}"); - } - if (b.size() != sizeof(crypto::hash)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Failed, size of data mismatch", "{}"); - } - vh.push_back(*reinterpret_cast(b.data())); - } - std::list missed_txs; - std::list txs; - bool r = core->get_transactions(vh, txs, missed_txs); - if (!r) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Failed", "{}"); - } - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator(); - - rapidjson::Value txs_as_hex(rapidjson::kArrayType); - BOOST_FOREACH(auto &tx, txs) - { - cryptonote::blobdata blob = t_serializable_object_to_blob(tx); - std::string string_blob = epee::string_tools::buff_to_hex_nodelimer(blob); - rapidjson::Value string_value(rapidjson::kStringType); - string_value.SetString(string_blob.c_str(), string_blob.length()); - txs_as_hex.PushBack(string_value, allocator); - } - result_json.AddMember("txs_as_hex", txs_as_hex, response_json.GetAllocator()); - - rapidjson::Value missed_tx(rapidjson::kArrayType); - BOOST_FOREACH(const auto &miss_tx, missed_txs) - { - std::string string_blob = epee::string_tools::pod_to_hex(miss_tx); - rapidjson::Value string_value(rapidjson::kStringType); - string_value.SetString(string_blob.c_str(), string_blob.length()); - missed_tx.PushBack(string_value, allocator); - } - result_json.AddMember("missed_tx", missed_tx, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'startmining' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int startmining(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - - if (!request_json.HasMember("miner_address") || !request_json["miner_address"].IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect miner_address", "{}"); - } - if (!request_json.HasMember("threads_count") || !request_json["threads_count"].IsUint64()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect threads_count", "{}"); - } - - std::string miner_address = request_json["miner_address"].GetString(); - uint64_t threads_count = request_json["threads_count"].GetUint(); - - cryptonote::account_public_address adr; - if (!cryptonote::get_account_address_from_str(adr, testnet, miner_address)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Failed, wrong address", "{}"); - } - - boost::thread::attributes attrs; - attrs.set_stack_size(THREAD_STACK_SIZE); - if (!core->get_miner().start(adr, static_cast(threads_count), attrs)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Failed, mining not started", "{}"); - } - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); - } - - /*! - * \brief Implementation of 'stopmining' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int stopmining(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (!core->get_miner().stop()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Failed, mining not stopped", "{}"); - } - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); - } - - /*! - * \brief Implementation of 'miningstatus' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int miningstatus(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - bool active = core->get_miner().is_mining(); - result_json.AddMember("active", active, response_json.GetAllocator()); - - if (active) - { - uint64_t speed = core->get_miner().get_speed(); - uint64_t threads_count = core->get_miner().get_threads_count(); - const cryptonote::account_public_address &mining_address = core->get_miner().get_mining_address(); - std::string address = cryptonote::get_account_address_as_str(testnet, mining_address); - result_json.AddMember("speed", speed, response_json.GetAllocator()); - result_json.AddMember("threads_count", threads_count, response_json.GetAllocator()); - rapidjson::Value string_address(rapidjson::kStringType); - string_address.SetString(address.c_str(), address.length()); - result_json.AddMember("address", string_address, response_json.GetAllocator()); - } - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblockcount' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblockcount(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("count", core->get_current_blockchain_height(), response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblockhash' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblockhash(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - - if (!request_json.HasMember("height") || !request_json["height"].IsUint64()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect height", "{}"); - } - uint64_t height = request_json["height"].GetUint(); - if (core->get_current_blockchain_height() <= height) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Height specified is too big.", "{}"); - } - std::string hash = epee::string_tools::pod_to_hex(core->get_block_id_by_height(height)); - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - rapidjson::Value string_value(rapidjson::kStringType); - string_value.SetString(hash.c_str(), hash.length()); - result_json.AddMember("hash", string_value, response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblocktemplate' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblocktemplate(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - - if (!request_json.HasMember("reserve_size") || !request_json["reserve_size"].IsUint64()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect reserve_size", "{}"); - } - if (!request_json.HasMember("wallet_address") || !request_json["wallet_address"].IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect wallet_address", "{}"); - } - - uint64_t reserve_size = request_json["reserve_size"].GetUint(); - std::string wallet_address = request_json["wallet_address"].GetString(); - - if (reserve_size > 255) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "To big reserved size, maximum 255", "{}"); - } - - cryptonote::account_public_address acc = AUTO_VAL_INIT(acc); - if (!wallet_address.size() || !cryptonote::get_account_address_from_str(acc, testnet, wallet_address)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Failed to parse wallet address", "{}"); - } - - cryptonote::block b = AUTO_VAL_INIT(b); - cryptonote::blobdata blob_reserve; - blob_reserve.resize(reserve_size, 0); - - uint64_t difficulty, height, reserved_offset; - if (!core->get_block_template(b, acc, difficulty, height, blob_reserve)) - { - LOG_ERROR("Failed to create block template"); - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Failed to create block template", "{}"); - } - - cryptonote::blobdata block_blob = t_serializable_object_to_blob(b); - crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx); - if (tx_pub_key == cryptonote::null_pkey) - { - LOG_ERROR("Failed to tx pub key in coinbase extra"); - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Failed to create block template", "{}"); - } - - reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); - if (!reserved_offset) - { - LOG_ERROR("Failed to find tx pub key in blockblob"); - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Internal error: failed to create block template", "{}"); - } - - reserved_offset += sizeof(tx_pub_key) + 3; // 3 bytes: tag for TX_EXTRA_TAG_PUBKEY(1 byte), tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte) - if (reserved_offset + reserve_size > block_blob.size()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Internal error: failed to create block template", "{}"); - } - cryptonote::blobdata blocktemplate_blob = epee::string_tools::buff_to_hex_nodelimer(block_blob); - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("difficulty", difficulty, response_json.GetAllocator()); - result_json.AddMember("height", height, response_json.GetAllocator()); - result_json.AddMember("reserved_offset", reserved_offset, response_json.GetAllocator()); - rapidjson::Value string_value(rapidjson::kStringType); - string_value.SetString(blocktemplate_blob.c_str(), blocktemplate_blob.length()); - result_json.AddMember("blocktemplate_blob", string_value, response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'submitblock' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int submitblock(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - if (!request_json.HasMember("block") || !request_json["block"].IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect block", "{}"); - } - - std::string string_blockblob = request_json["block"].GetString(); - cryptonote::blobdata blockblob; - if (!epee::string_tools::parse_hexstr_to_binbuff(string_blockblob, blockblob)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Incorrect block", "{}"); - } - // Fixing of high orphan issue for most pools - cryptonote::block b = AUTO_VAL_INIT(b); - if (!parse_and_validate_block_from_blob(blockblob, b)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Wrong block blob", "{}"); - } - // Fix from Boolberry neglects to check block - // size, do that with the function below - if (!core->check_incoming_block_size(blockblob)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Block blob size is too big, rejecting block", "{}"); - } - if (!core->handle_block_found(b)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Block not accepted.", "{}"); - } - - return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", CORE_RPC_STATUS_OK); - } - - /*! - * \brief Implementation of 'getlastblockheader' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getlastblockheader(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - uint64_t last_block_height; - crypto::hash last_block_hash; - bool have_last_block_hash = core->get_blockchain_top(last_block_height, last_block_hash); - - if (!have_last_block_hash) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Internal error: can't get last block hash", "{}"); - } - - cryptonote::block last_block; - bool have_last_block = core->get_block_by_hash(last_block_hash, last_block); - if (!have_last_block) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_request, - "Internal error: can't get last block hash", "{}"); - } - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - fill_block_header_response(last_block, false, last_block_height, last_block_hash, - result_json, response_json); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblockheaderbyhash' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblockheaderbyhash(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - if (!request_json.HasMember("hash") || !request_json["hash"].IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect hash", "{}"); - } - - std::string hash = request_json["hash"].GetString(); - crypto::hash block_hash; - bool hash_parsed = parse_hash256(hash, block_hash); - if (!hash_parsed) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - std::string("Failed to parse hex representation of block hash. Hex = " + hash + '.').c_str(), "{}"); - } - - cryptonote::block blk; - bool have_block = core->get_block_by_hash(block_hash, blk); - if (!have_block) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - std::string("Internal error: can't get block by hash. Hash = " + hash + '.').c_str(), "{}"); - } - - if (blk.miner_tx.vin.front().type() != typeid(cryptonote::txin_gen)) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - std::string("Internal error: coinbase transaction in the block has the wrong type").c_str(), "{}"); - } - - uint64_t block_height = boost::get(blk.miner_tx.vin.front()).height; - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - fill_block_header_response(blk, false, block_height, block_hash, result_json, response_json); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getblockheaderbyheight' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getblockheaderbyheight(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - if (!request_json.HasMember("height") || !request_json["height"].IsUint64()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect height", "{}"); - } - - uint64_t height = request_json["height"].GetUint(); - if (core->get_current_blockchain_height() <= height) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - std::string(std::string("To big height: ") + std::to_string(height) + - ", current blockchain height = " + std::to_string(core->get_current_blockchain_height())).c_str(), "{}"); - } - crypto::hash block_hash = core->get_block_id_by_height(height); - cryptonote::block blk; - bool have_block = core->get_block_by_hash(block_hash, blk); - if (!have_block) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - std::string("Internal error: can't get block by height. Height = " + std::to_string(height) + '.').c_str(), "{}"); - } - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - fill_block_header_response(blk, false, height, block_hash, result_json, response_json); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getconnections' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getconnections(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - - std::list connections = p2p->get_payload_object().get_connections(); - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - rapidjson::Value connections_json(rapidjson::kArrayType); - for (std::list::iterator it = connections.begin(); - it != connections.end(); it++) - { - rapidjson::Value connection; - connection.SetObject(); - rapidjson::Value string_value; - connection.AddMember("incoming", it->incoming, response_json.GetAllocator()); - string_value.SetString(it->ip.c_str(), it->ip.length()); - connection.AddMember("ip", string_value, response_json.GetAllocator()); - string_value.SetString(it->port.c_str(), it->port.length()); - connection.AddMember("port", string_value, response_json.GetAllocator()); - string_value.SetString(it->peer_id.c_str(), it->peer_id.length()); - connection.AddMember("peer_id", string_value, response_json.GetAllocator()); - connection.AddMember("recv_count", it->recv_count, response_json.GetAllocator()); - connection.AddMember("recv_idle_time", it->recv_idle_time, response_json.GetAllocator()); - connection.AddMember("send_count", it->send_count, response_json.GetAllocator()); - connection.AddMember("send_idle_time", it->send_idle_time, response_json.GetAllocator()); - string_value.SetString(it->state.c_str(), it->state.length()); - connection.AddMember("state", string_value, response_json.GetAllocator()); - connection.AddMember("live_time", it->live_time, response_json.GetAllocator()); - connections_json.PushBack(connection, response_json.GetAllocator()); - } - result_json.AddMember("connections", connections_json, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getinfo' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getinfo(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - uint64_t height = core->get_current_blockchain_height(); - result_json.AddMember("height", height, response_json.GetAllocator()); - result_json.AddMember("target_height", core->get_target_blockchain_height(), - response_json.GetAllocator()); - result_json.AddMember("difficulty", core->get_blockchain_storage().get_difficulty_for_next_block(), - response_json.GetAllocator()); - result_json.AddMember("tx_count", core->get_blockchain_storage().get_total_transactions() - height, - response_json.GetAllocator()); - result_json.AddMember("tx_pool_size", core->get_pool_transactions_count(), - response_json.GetAllocator()); - result_json.AddMember("alt_blocks_count", (uint64_t)core->get_blockchain_storage().get_alternative_blocks_count(), - response_json.GetAllocator()); - uint64_t total_conn = p2p->get_connections_count(); - uint64_t outgoing_connections_count = p2p->get_outgoing_connections_count(); - result_json.AddMember("outgoing_connections_count", outgoing_connections_count, - response_json.GetAllocator()); - result_json.AddMember("incoming_connections_count", total_conn - outgoing_connections_count, - response_json.GetAllocator()); - result_json.AddMember("white_peerlist_size", p2p->get_peerlist_manager().get_white_peers_count(), - response_json.GetAllocator()); - result_json.AddMember("grey_peerlist_size", p2p->get_peerlist_manager().get_gray_peers_count(), - response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - /*! - * \brief Implementation of 'getindexes' method. - * \param buf Buffer to fill in response. - * \param len Max length of response. - * \param req net_skeleton RPC request - * \return Actual response length. - */ - int getindexes(char *buf, int len, struct ns_rpc_request *req) - { - CHECK_CORE_BUSY(); - if (req->params == NULL) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Parameters missing.", "{}"); - } - rapidjson::Document request_json; - char request_buf[1000]; - strncpy(request_buf, req->params[0].ptr, req->params[0].len); - request_buf[req->params[0].len] = '\0'; - - if (request_json.Parse(request_buf).HasParseError()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::parse_error, - "Invalid JSON passed", "{}"); - } - if (!request_json.HasMember("txid") || !request_json["txid"].IsString()) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "Incorrect txid", "{}"); - } - std::string txid_string = request_json["txid"].GetString(); - if (txid_string.length() < crypto::HASH_SIZE) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::invalid_params, - "txid is not of correct length", "{}"); - } - crypto::hash txid; - strncpy(txid.data, txid_string.c_str(), crypto::HASH_SIZE); - std::vector o_indexes; - - rapidjson::Document response_json; - rapidjson::Value result_json; - result_json.SetObject(); - - rapidjson::Value o_indexes_json(rapidjson::kArrayType); - bool r = core->get_tx_outputs_gindexs(txid, o_indexes); - if (!r) - { - return ns_rpc_create_error(buf, len, req, RPC::Json_rpc_http_server::internal_error, - "Failed", "{}"); - } - for (std::vector::iterator it = o_indexes.begin(); it != o_indexes.end(); it++) - { - o_indexes_json.PushBack(*it, response_json.GetAllocator()); - } - result_json.AddMember("o_indexes", o_indexes_json, response_json.GetAllocator()); - result_json.AddMember("status", CORE_RPC_STATUS_OK, response_json.GetAllocator()); - - std::string response; - construct_response_string(req, result_json, response_json, response); - size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; - strncpy(buf, response.c_str(), copy_length); - return response.length(); - } - - // Contains a list of method names. - const char *method_names[] = { - "getheight", - "getblocks", - "gettransactions", - "startmining", - "stopmining", - "miningstatus", - "getblockcount", - "getblockhash", - "getblocktemplate", - "submitblock", - "getlastblockheader", - "getblockheaderbyhash", - "getblockheaderbyheight", - "getconnections", - "getinfo", - "getindexes", - NULL - }; - - // Contains a list of function pointers. These must map 1-1 by index with `method_names`. - ns_rpc_handler_t handlers[] = { - getheight, - getblocks, - gettransactions, - startmining, - stopmining, - miningstatus, - getblockcount, - getblockhash, - getblocktemplate, - submitblock, - getlastblockheader, - getblockheaderbyhash, - getblockheaderbyheight, - getconnections, - getinfo, - getindexes, - NULL - }; -} - -/*! - * \namespace RPC - * \brief RPC related utilities - */ -namespace RPC -{ - /*! - * \namespace Daemon - * \brief RPC relevant to daemon - */ - namespace Daemon - { - /*! - * \brief initializes module (must call this before handling requests) - * \param p_core Pointer to cryptonote core object - * \param p_p2p Pointer to P2P object - * \param p_testnet True if testnet false otherwise - */ - void init(cryptonote::core *p_core, - nodetool::node_server > *p_p2p, - bool p_testnet) - { - core = p_core; - p2p = p_p2p; - testnet = p_testnet; - } - - /*! - * \Inits certain options used in Daemon CLI. - * \param desc Instance of options description object - */ - void init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_rpc_bind_ip); - command_line::add_arg(desc, arg_rpc_bind_port); - command_line::add_arg(desc, arg_testnet_rpc_bind_port); - } - - /*! - * \brief Gets IP address and port number from variable map - * \param vm Variable map - * \param ip_address IP address - * \param port Port number - */ - void get_address_and_port(const boost::program_options::variables_map& vm, - std::string &ip_address, std::string &port) - { - auto p2p_bind_arg = testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port; - - ip_address = command_line::get_arg(vm, arg_rpc_bind_ip); - port = command_line::get_arg(vm, p2p_bind_arg); - } - - /*! - * \brief Event handler that is invoked upon net_skeleton network events. - * - * Any change in behavior of RPC should happen from this point. - * \param nc net_skeleton connection - * \param ev Type of event - * \param ev_data Event data - */ - void ev_handler(struct ns_connection *nc, int ev, void *ev_data) - { - struct http_message *hm = (struct http_message *) ev_data; - char buf[MAX_RESPONSE_SIZE]; - switch (ev) { - case NS_HTTP_REQUEST: - ns_rpc_dispatch(hm->body.p, hm->body.len, buf, sizeof(buf), - method_names, handlers); - ns_printf(nc, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n" - "Content-Type: application/json\r\n\r\n%s", - (int) strlen(buf), buf); - nc->flags |= NSF_FINISHED_SENDING_DATA; - break; - default: - break; - } - } - } -} diff --git a/src/rpc/daemon_json_rpc_handlers.h b/src/rpc/daemon_json_rpc_handlers.h deleted file mode 100644 index bc9bb3065..000000000 --- a/src/rpc/daemon_json_rpc_handlers.h +++ /dev/null @@ -1,75 +0,0 @@ -/*! - * \file daemon_json_rpc_handlers.h - * \brief Header for JSON RPC handlers (Daemon) - */ - -#ifndef DAEMON_JSON_RPC_HANDLERS_H -#define DAEMON_JSON_RPC_HANDLERS_H - -#include "net_skeleton/net_skeleton.h" -#include "json_rpc_http_server.h" -#include "common/command_line.h" -#include "net/http_server_impl_base.h" -#include "cryptonote_core/cryptonote_core.h" -#include "p2p/net_node.h" -#include "cryptonote_protocol/cryptonote_protocol_handler.h" -#include -#include "rapidjson/document.h" -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" -#include -#include "cryptonote_core/cryptonote_basic.h" -#include "crypto/hash-ops.h" - -#include - -/*! - * \namespace RPC - * \brief RPC related utilities - */ -namespace RPC -{ - /*! - * \namespace Daemon - * \brief RPC relevant to daemon - */ - namespace Daemon - { - /*! - * \brief initializes module (must call this before handling requests) - * \param p_core Pointer to cryptonote core object - * \param p_p2p Pointer to P2P object - * \param p_testnet True if testnet false otherwise - */ - void init(cryptonote::core *p_core, - nodetool::node_server > *p_p2p, - bool p_testnet); - - /*! - * \Inits certain options used in Daemon CLI. - * \param desc Instance of options description object - */ - void init_options(boost::program_options::options_description& desc); - - /*! - * \brief Gets IP address and port number from variable map - * \param vm Variable map - * \param ip_address IP address - * \param port Port number - */ - void get_address_and_port(const boost::program_options::variables_map& vm, - std::string &ip_address, std::string &port); - - /*! - * \brief Event handler that is invoked upon net_skeleton network events. - * - * Any change in behavior of RPC should happen from this point. - * \param nc net_skeleton connection - * \param ev Type of event - * \param ev_data Event data - */ - void ev_handler(struct ns_connection *nc, int ev, void *ev_data); - } -} - -#endif diff --git a/src/rpc/json_rpc.cpp b/src/rpc/json_rpc.cpp new file mode 100644 index 000000000..142cb75c4 --- /dev/null +++ b/src/rpc/json_rpc.cpp @@ -0,0 +1,26 @@ +#include "daemon_deprecated_rpc.h" +#include +#include + +static bool execute = true; +void trap(int signal) { + RPC::DaemonDeprecated::stop(); + execute = false; +} + +int main() { + int res = RPC::DaemonDeprecated::start(); + if (res == RPC::DaemonDeprecated::FAILURE_HTTP_SERVER) { + std::cerr << "Couldn't start HTTP server\n"; + execute = false; + } else if (res == RPC::DaemonDeprecated::FAILURE_DAEMON_NOT_RUNNING) { + std::cerr << "Couldn't connect to daemon\n"; + execute = false; + } + signal(SIGINT, &trap); + while (execute) { + + } + std::cout << "out!\n"; + return 0; +} diff --git a/src/rpc/json_rpc_http_server.cpp b/src/rpc/json_rpc_http_server.cpp index 86edc7d10..3570d058c 100644 --- a/src/rpc/json_rpc_http_server.cpp +++ b/src/rpc/json_rpc_http_server.cpp @@ -13,10 +13,6 @@ */ namespace RPC { - int Json_rpc_http_server::parse_error = -32700; - int Json_rpc_http_server::invalid_request = -32600; - int Json_rpc_http_server::invalid_params = -32602; - int Json_rpc_http_server::internal_error = -32603; /** * \brief Constructor @@ -25,10 +21,11 @@ namespace RPC * \param ev_handler Event handler function pointer */ Json_rpc_http_server::Json_rpc_http_server(const std::string &ip, const std::string &port, - void (*ev_handler)(struct ns_connection *nc, int ev, void *ev_data)) + const std::string &path, void (*ev_handler)(struct ns_connection *nc, int ev, void *ev_data)) { m_ip = ip; m_port = port; + m_path = path; m_is_running = false; m_ev_handler = ev_handler; } @@ -53,7 +50,7 @@ namespace RPC } m_is_running = true; ns_mgr_init(&mgr, NULL); - nc = ns_bind(&mgr, (m_ip + ":" + m_port).c_str(), m_ev_handler); + nc = ns_bind(&mgr, (m_ip + ":" + m_port + "/" + m_path).c_str(), m_ev_handler); if (!nc) { return false; diff --git a/src/rpc/json_rpc_http_server.h b/src/rpc/json_rpc_http_server.h index a262f6061..4cc728313 100644 --- a/src/rpc/json_rpc_http_server.h +++ b/src/rpc/json_rpc_http_server.h @@ -33,6 +33,7 @@ namespace RPC void poll(); std::string m_ip; /*!< IP address where its listening */ std::string m_port; /*!< Port where its listening */ + std::string m_path; /*!< Path */ bool m_is_running; /*!< Whether the server is currently running */ void (*m_ev_handler)(struct ns_connection *nc, int ev, void *ev_data); /*!< Server event handler function pointer */ public: @@ -43,7 +44,7 @@ namespace RPC * \param port Port number to bind * \param ev_handler Event handler function pointer */ - Json_rpc_http_server(const std::string &ip, const std::string &port, + Json_rpc_http_server(const std::string &ip, const std::string &port, const std::string &path, void (*ev_handler)(struct ns_connection *nc, int ev, void *ev_data)); /** diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 05ed03a66..bdb31413a 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -755,7 +755,7 @@ bool simple_wallet::start_mining(const std::vector& args) if (!try_connect_to_daemon()) return true; - COMMAND_RPC_START_MINING::request req; + // COMMAND_RPC_START_MINING::request req; // req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); std::string miner_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); uint64_t threads_count; @@ -822,14 +822,15 @@ bool simple_wallet::save_bc(const std::vector& args) if (!try_connect_to_daemon()) return true; - COMMAND_RPC_SAVE_BC::request req; - COMMAND_RPC_SAVE_BC::response res; - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/save_bc", req, res, m_http_client); - std::string err = interpret_rpc_response(r, res.status); - if (err.empty()) + // COMMAND_RPC_SAVE_BC::request req; + // COMMAND_RPC_SAVE_BC::response res; + // bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/save_bc", req, res, m_http_client); + // std::string err = interpret_rpc_response(r, res.status); + uint64_t status = m_wallet->save_bc(); + if (status == IPC::STATUS_OK) success_msg_writer() << "Blockchain saved"; else - fail_msg_writer() << "Blockchain can't be saved: " << err; + fail_msg_writer() << "Blockchain can't be saved: " << status; return true; } //---------------------------------------------------------------------------------------------------- @@ -1053,11 +1054,18 @@ bool simple_wallet::show_payments(const std::vector &args) //---------------------------------------------------------------------------------------------------- uint64_t simple_wallet::get_daemon_blockchain_height(std::string& err) { - COMMAND_RPC_GET_HEIGHT::request req; - COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized(); - bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client); - err = interpret_rpc_response(r, res.status); - return res.height; + // COMMAND_RPC_GET_HEIGHT::request req; + // COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized(); + // bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/getheight", req, res, m_http_client); + // err = interpret_rpc_response(r, res.status); + uint64_t height; + uint64_t status = m_wallet->get_height(height); + // res has to be true since we have checked before. + if (status != IPC::STATUS_OK) { + // TODO: map proper error messages to codes. + err = "Couldn't get blockchain height."; + } + return height; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_blockchain_height(const std::vector& args) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 9511bb075..a8fe78414 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -207,6 +207,5 @@ namespace cryptonote std::unique_ptr m_wallet; epee::net_utils::http::http_simple_client m_http_client; refresh_progress_reporter_t m_refresh_progress_reporter; - wap_client_t *client; }; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 1801333ba..69b38ee0c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1268,8 +1268,7 @@ void wallet2::stop_ipc_client() { } void wallet2::connect_to_daemon() { - if (ipc_client) { - // TODO: Instead, check if daemon is reachable. + if (check_connection()) { return; } ipc_client = wap_client_new(); @@ -1289,4 +1288,17 @@ uint64_t wallet2::stop_mining() { THROW_WALLET_EXCEPTION_IF(rc < 0, error::no_connection_to_daemon, "stop_mining"); return wap_client_status(ipc_client); } + +uint64_t wallet2::get_height(uint64_t &height) { + int rc = wap_client_get_height(ipc_client); + THROW_WALLET_EXCEPTION_IF(rc < 0, error::no_connection_to_daemon, "get_height"); + height = wap_client_height(ipc_client); + return wap_client_status(ipc_client); +} + +uint64_t wallet2::save_bc() { + int rc = wap_client_save_bc(ipc_client); + THROW_WALLET_EXCEPTION_IF(rc < 0, error::no_connection_to_daemon, "save_bc"); + return wap_client_status(ipc_client); +} } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 202c0c0c9..a1c67ca8d 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -268,6 +268,8 @@ namespace tools uint64_t start_mining(const std::string &address, uint64_t thread_count); uint64_t stop_mining(); + uint64_t get_height(uint64_t &height); + uint64_t save_bc(); private: /*! * \brief Stores wallet information to wallet file. diff --git a/src/wallet/wallet_json_rpc_handlers.cpp b/src/wallet/wallet_json_rpc_handlers.cpp index 5334ebbf7..04986eb8a 100644 --- a/src/wallet/wallet_json_rpc_handlers.cpp +++ b/src/wallet/wallet_json_rpc_handlers.cpp @@ -39,7 +39,7 @@ namespace void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json, rapidjson::Document &response_json, std::string &response) { - response_json.SetObject(); + /*response_json.SetObject(); rapidjson::Value string_value(rapidjson::kStringType); // If ID was present in request use it else use "null". if (req->id != NULL) @@ -58,7 +58,7 @@ namespace rapidjson::Writer writer(buffer); response_json.Accept(writer); // Write string to `response`. - response = buffer.GetString(); + response = buffer.GetString();*/ } /*! @@ -70,7 +70,7 @@ namespace */ int getbalance(char *buf, int len, struct ns_rpc_request *req) { - uint64_t balance, unlocked_balance; + /*uint64_t balance, unlocked_balance; try { balance = wallet->balance(); @@ -91,7 +91,7 @@ namespace construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); - return response.length(); + return response.length();*/ } /*! @@ -103,7 +103,7 @@ namespace */ int getaddress(char *buf, int len, struct ns_rpc_request *req) { - std::string address; + /*std::string address; try { address = wallet->get_account().get_public_address_str(wallet->testnet()); @@ -124,7 +124,7 @@ namespace construct_response_string(req, result_json, response_json, response); size_t copy_length = ((uint32_t)len > response.length()) ? response.length() + 1 : (uint32_t)len; strncpy(buf, response.c_str(), copy_length); - return response.length(); + return response.length();*/ } // Contains a list of method names.