mirror of
https://github.com/monero-project/monero.git
synced 2025-01-28 18:56:31 +02:00
get_blocks deprecated RPC (buffer overflow for large responses), comments
This commit is contained in:
parent
c7d27d4979
commit
4b2c2cc3e9
@ -28,19 +28,36 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file daemon_ipc_handlers.cpp
|
||||||
|
* \brief Implementation of Daemon IPC handlers
|
||||||
|
*
|
||||||
|
* Most of this code is borrowed from core_rpc_server.cpp but changed to use 0MQ objects.
|
||||||
|
*/
|
||||||
|
|
||||||
//TODO: Recheck memory leaks
|
//TODO: Recheck memory leaks
|
||||||
|
|
||||||
#include "daemon_ipc_handlers.h"
|
#include "daemon_ipc_handlers.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace IPC
|
||||||
|
* \brief Anonymous namepsace to keep things in the scope of this file
|
||||||
|
*/
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
cryptonote::core *core; /*!< Pointer to the core */
|
cryptonote::core *core; /*!< Pointer to the core */
|
||||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > *p2p;
|
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > *p2p;
|
||||||
/*!< Pointer to p2p node server */
|
/*!< Pointer to p2p node server */
|
||||||
zactor_t *server;
|
zactor_t *server; /*!< 0MQ server */
|
||||||
bool testnet;
|
bool testnet; /*!< testnet mode or not */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if core is busy
|
||||||
|
*
|
||||||
|
* \return true if core is busy
|
||||||
|
*/
|
||||||
bool check_core_busy()
|
bool check_core_busy()
|
||||||
{
|
{
|
||||||
if (p2p->get_payload_object().get_core().get_blockchain_storage().is_storing_blockchain())
|
if (p2p->get_payload_object().get_core().get_blockchain_storage().is_storing_blockchain())
|
||||||
@ -49,6 +66,12 @@ namespace
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if core is ready
|
||||||
|
*
|
||||||
|
* \return true if core is ready
|
||||||
|
*/
|
||||||
bool check_core_ready()
|
bool check_core_ready()
|
||||||
{
|
{
|
||||||
if (p2p->get_payload_object().is_synchronized())
|
if (p2p->get_payload_object().is_synchronized())
|
||||||
@ -58,10 +81,11 @@ namespace
|
|||||||
return check_core_busy();
|
return check_core_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
/*!
|
||||||
// equivalent of strstr, but with arbitrary bytes (ie, NULs)
|
* \brief equivalent of strstr, but with arbitrary bytes (ie, NULs)
|
||||||
// This does not differentiate between "not found" and "found at offset 0"
|
* This does not differentiate between "not found" and "found at offset 0"
|
||||||
// (taken straight from core_rpc_server.cpp)
|
* (taken straight from core_rpc_server.cpp)
|
||||||
|
*/
|
||||||
uint64_t slow_memmem(const void *start_buff, size_t buflen, const void *pat, size_t patlen)
|
uint64_t slow_memmem(const void *start_buff, size_t buflen, const void *pat, size_t patlen)
|
||||||
{
|
{
|
||||||
const void *buf = start_buff;
|
const void *buf = start_buff;
|
||||||
@ -78,10 +102,26 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace IPC
|
||||||
|
* \brief Namespace pertaining to IPC.
|
||||||
|
*/
|
||||||
namespace IPC
|
namespace IPC
|
||||||
{
|
{
|
||||||
|
/*!
|
||||||
|
* \namespace Daemon
|
||||||
|
* \brief Namespace pertaining to Daemon IPC.
|
||||||
|
*/
|
||||||
namespace Daemon
|
namespace Daemon
|
||||||
{
|
{
|
||||||
|
/*!
|
||||||
|
* \brief initializes it with objects necessary to handle IPC requests and starts
|
||||||
|
* IPC server
|
||||||
|
*
|
||||||
|
* \param p_core cryptonote core object
|
||||||
|
* \param p_p2p p2p object
|
||||||
|
* \param p_testnet testnet mode or not
|
||||||
|
*/
|
||||||
void init(cryptonote::core &p_core,
|
void init(cryptonote::core &p_core,
|
||||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > &p_p2p,
|
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > &p_p2p,
|
||||||
bool p_testnet)
|
bool p_testnet)
|
||||||
@ -94,10 +134,22 @@ namespace IPC
|
|||||||
zsock_send (server, "sss", "SET", "server/timeout", "5000");
|
zsock_send (server, "sss", "SET", "server/timeout", "5000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief stops the IPC server
|
||||||
|
*
|
||||||
|
* \param p_core cryptonote core object
|
||||||
|
* \param p_p2p p2p object
|
||||||
|
* \param p_testnet testnet mode or not
|
||||||
|
*/
|
||||||
void stop() {
|
void stop() {
|
||||||
zactor_destroy(&server);
|
zactor_destroy(&server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief start_mining IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void start_mining(wap_proto_t *message)
|
void start_mining(wap_proto_t *message)
|
||||||
{
|
{
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
@ -127,6 +179,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief stop_mining IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void stop_mining(wap_proto_t *message)
|
void stop_mining(wap_proto_t *message)
|
||||||
{
|
{
|
||||||
if (!core->get_miner().stop())
|
if (!core->get_miner().stop())
|
||||||
@ -137,6 +194,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_blocks IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void retrieve_blocks(wap_proto_t *message)
|
void retrieve_blocks(wap_proto_t *message)
|
||||||
{
|
{
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
@ -165,6 +227,11 @@ namespace IPC
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We are using JSON to encode blocks. The JSON string will sit in a
|
||||||
|
// 0MQ frame which gets sent in a zmsg_t object. One could put each block
|
||||||
|
// a different frame too.
|
||||||
|
|
||||||
|
// First create a rapidjson object and then stringify it.
|
||||||
rapidjson::Document result_json;
|
rapidjson::Document result_json;
|
||||||
result_json.SetObject();
|
result_json.SetObject();
|
||||||
rapidjson::Document::AllocatorType &allocator = result_json.GetAllocator();
|
rapidjson::Document::AllocatorType &allocator = result_json.GetAllocator();
|
||||||
@ -196,6 +263,7 @@ namespace IPC
|
|||||||
result_json.Accept(writer);
|
result_json.Accept(writer);
|
||||||
std::string block_string = buffer.GetString();
|
std::string block_string = buffer.GetString();
|
||||||
zmsg_t *block_data = zmsg_new();
|
zmsg_t *block_data = zmsg_new();
|
||||||
|
// Put the JSON string in a frame.
|
||||||
zframe_t *frame = zframe_new(block_string.c_str(), block_string.length());
|
zframe_t *frame = zframe_new(block_string.c_str(), block_string.length());
|
||||||
zmsg_prepend(block_data, &frame);
|
zmsg_prepend(block_data, &frame);
|
||||||
wap_proto_set_start_height(message, result_start_height);
|
wap_proto_set_start_height(message, result_start_height);
|
||||||
@ -205,6 +273,11 @@ namespace IPC
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief send_raw_transaction IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void send_raw_transaction(wap_proto_t *message)
|
void send_raw_transaction(wap_proto_t *message)
|
||||||
{
|
{
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
@ -248,10 +321,15 @@ namespace IPC
|
|||||||
cryptonote::NOTIFY_NEW_TRANSACTIONS::request r;
|
cryptonote::NOTIFY_NEW_TRANSACTIONS::request r;
|
||||||
r.txs.push_back(tx_blob);
|
r.txs.push_back(tx_blob);
|
||||||
core->get_protocol()->relay_transactions(r, fake_context);
|
core->get_protocol()->relay_transactions(r, fake_context);
|
||||||
//TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes
|
// TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes
|
||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_output_indexes IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_output_indexes(wap_proto_t *message)
|
void get_output_indexes(wap_proto_t *message)
|
||||||
{
|
{
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
@ -276,6 +354,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_random_outputs IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_random_outs(wap_proto_t *message) {
|
void get_random_outs(wap_proto_t *message) {
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||||
@ -299,7 +382,7 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_RANDOM_OUTS_FAILED);
|
wap_proto_set_status(message, STATUS_RANDOM_OUTS_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to convert the result into a JSON string.
|
// We convert the result into a JSON string and put it into a 0MQ frame.
|
||||||
rapidjson::Document result_json;
|
rapidjson::Document result_json;
|
||||||
result_json.SetObject();
|
result_json.SetObject();
|
||||||
rapidjson::Document::AllocatorType &allocator = result_json.GetAllocator();
|
rapidjson::Document::AllocatorType &allocator = result_json.GetAllocator();
|
||||||
@ -350,6 +433,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_height IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_height(wap_proto_t *message) {
|
void get_height(wap_proto_t *message) {
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||||
@ -359,6 +447,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief save_bc IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void save_bc(wap_proto_t *message) {
|
void save_bc(wap_proto_t *message) {
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||||
@ -371,6 +464,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_info IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_info(wap_proto_t *message) {
|
void get_info(wap_proto_t *message) {
|
||||||
if (!check_core_busy()) {
|
if (!check_core_busy()) {
|
||||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||||
@ -392,17 +490,27 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_peer_list IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_peer_list(wap_proto_t *message) {
|
void get_peer_list(wap_proto_t *message) {
|
||||||
std::list<nodetool::peerlist_entry> white_list;
|
std::list<nodetool::peerlist_entry> white_list;
|
||||||
std::list<nodetool::peerlist_entry> gray_list;
|
std::list<nodetool::peerlist_entry> gray_list;
|
||||||
p2p->get_peerlist_manager().get_peerlist_full(white_list, gray_list);
|
p2p->get_peerlist_manager().get_peerlist_full(white_list, gray_list);
|
||||||
|
|
||||||
|
// The response is of non-trivial type and so is encoded as JSON.
|
||||||
|
// Each peer list is going to look like this:
|
||||||
|
// {"peers": [{"id": ....}, ...]}
|
||||||
|
|
||||||
rapidjson::Document white_list_json;
|
rapidjson::Document white_list_json;
|
||||||
white_list_json.SetObject();
|
white_list_json.SetObject();
|
||||||
rapidjson::Document::AllocatorType &white_list_allocator = white_list_json.GetAllocator();
|
rapidjson::Document::AllocatorType &white_list_allocator = white_list_json.GetAllocator();
|
||||||
rapidjson::Value white_peers(rapidjson::kArrayType);
|
rapidjson::Value white_peers(rapidjson::kArrayType);
|
||||||
|
|
||||||
for (auto & entry : white_list) {
|
for (auto & entry : white_list) {
|
||||||
|
// Each peer object is encoded as JSON
|
||||||
rapidjson::Value output(rapidjson::kObjectType);
|
rapidjson::Value output(rapidjson::kObjectType);
|
||||||
output.AddMember("id", entry.id, white_list_allocator);
|
output.AddMember("id", entry.id, white_list_allocator);
|
||||||
output.AddMember("ip", entry.adr.ip, white_list_allocator);
|
output.AddMember("ip", entry.adr.ip, white_list_allocator);
|
||||||
@ -418,6 +526,7 @@ namespace IPC
|
|||||||
rapidjson::Value gray_peers(rapidjson::kArrayType);
|
rapidjson::Value gray_peers(rapidjson::kArrayType);
|
||||||
|
|
||||||
for (auto & entry : gray_list) {
|
for (auto & entry : gray_list) {
|
||||||
|
// Each peer object is encoded as JSON
|
||||||
rapidjson::Value output(rapidjson::kObjectType);
|
rapidjson::Value output(rapidjson::kObjectType);
|
||||||
output.AddMember("id", entry.id, gray_list_allocator);
|
output.AddMember("id", entry.id, gray_list_allocator);
|
||||||
output.AddMember("ip", entry.adr.ip, gray_list_allocator);
|
output.AddMember("ip", entry.adr.ip, gray_list_allocator);
|
||||||
@ -444,6 +553,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_mining_status IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_mining_status(wap_proto_t *message) {
|
void get_mining_status(wap_proto_t *message) {
|
||||||
if (!check_core_ready()) {
|
if (!check_core_ready()) {
|
||||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||||
@ -464,6 +578,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief set_log_hash_rate IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void set_log_hash_rate(wap_proto_t *message) {
|
void set_log_hash_rate(wap_proto_t *message) {
|
||||||
if (core->get_miner().is_mining())
|
if (core->get_miner().is_mining())
|
||||||
{
|
{
|
||||||
@ -476,6 +595,11 @@ namespace IPC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief set_log_hash_rate IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void set_log_level(wap_proto_t *message) {
|
void set_log_level(wap_proto_t *message) {
|
||||||
// zproto supports only unsigned integers afaik. so the log level is sent as
|
// zproto supports only unsigned integers afaik. so the log level is sent as
|
||||||
// one and casted to signed int here.
|
// one and casted to signed int here.
|
||||||
@ -493,16 +617,31 @@ namespace IPC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief start_save_graph IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void start_save_graph(wap_proto_t *message) {
|
void start_save_graph(wap_proto_t *message) {
|
||||||
p2p->set_save_graph(true);
|
p2p->set_save_graph(true);
|
||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief stop_save_graph IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void stop_save_graph(wap_proto_t *message) {
|
void stop_save_graph(wap_proto_t *message) {
|
||||||
p2p->set_save_graph(false);
|
p2p->set_save_graph(false);
|
||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_block_hash IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_block_hash(wap_proto_t *message) {
|
void get_block_hash(wap_proto_t *message) {
|
||||||
if (!check_core_busy())
|
if (!check_core_busy())
|
||||||
{
|
{
|
||||||
@ -521,6 +660,11 @@ namespace IPC
|
|||||||
wap_proto_set_status(message, STATUS_OK);
|
wap_proto_set_status(message, STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief get_block_template IPC
|
||||||
|
*
|
||||||
|
* \param message 0MQ response object to populate
|
||||||
|
*/
|
||||||
void get_block_template(wap_proto_t *message) {
|
void get_block_template(wap_proto_t *message) {
|
||||||
if (!check_core_ready())
|
if (!check_core_ready())
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,11 @@
|
|||||||
//
|
//
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file daemon_ipc_handlers.h
|
||||||
|
* \brief Header for Daemon IPC handlers
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef DAEMON_IPC_HANDLERS_H
|
#ifndef DAEMON_IPC_HANDLERS_H
|
||||||
#define DAEMON_IPC_HANDLERS_H
|
#define DAEMON_IPC_HANDLERS_H
|
||||||
|
|
||||||
@ -52,8 +57,13 @@ using namespace epee;
|
|||||||
#include "rapidjson/writer.h"
|
#include "rapidjson/writer.h"
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \namespace IPC
|
||||||
|
* \brief Namespace pertaining to IPC.
|
||||||
|
*/
|
||||||
namespace IPC
|
namespace IPC
|
||||||
{
|
{
|
||||||
|
// A bunch of response statuses and error codes
|
||||||
const uint64_t STATUS_OK = 0;
|
const uint64_t STATUS_OK = 0;
|
||||||
const uint64_t STATUS_CORE_BUSY = 1;
|
const uint64_t STATUS_CORE_BUSY = 1;
|
||||||
const uint64_t STATUS_WRONG_ADDRESS = 2;
|
const uint64_t STATUS_WRONG_ADDRESS = 2;
|
||||||
@ -70,16 +80,15 @@ namespace IPC
|
|||||||
const uint64_t STATUS_ERROR_STORING_BLOCKCHAIN = 13;
|
const uint64_t STATUS_ERROR_STORING_BLOCKCHAIN = 13;
|
||||||
const uint64_t STATUS_HEIGHT_TOO_BIG = 13;
|
const uint64_t STATUS_HEIGHT_TOO_BIG = 13;
|
||||||
const uint64_t STATUS_RESERVE_SIZE_TOO_BIG = 14;
|
const uint64_t STATUS_RESERVE_SIZE_TOO_BIG = 14;
|
||||||
|
/*!
|
||||||
|
* \namespace Daemon
|
||||||
|
* \brief Namespace pertaining to Daemon IPC.
|
||||||
|
*/
|
||||||
namespace Daemon
|
namespace Daemon
|
||||||
{
|
{
|
||||||
|
void get_height(wap_proto_t *message);
|
||||||
void start_mining(wap_proto_t *message);
|
void start_mining(wap_proto_t *message);
|
||||||
void stop_mining(wap_proto_t *message);
|
void stop_mining(wap_proto_t *message);
|
||||||
void retrieve_blocks(wap_proto_t *message);
|
|
||||||
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 get_info(wap_proto_t *message);
|
||||||
void get_peer_list(wap_proto_t *message);
|
void get_peer_list(wap_proto_t *message);
|
||||||
void get_mining_status(wap_proto_t *message);
|
void get_mining_status(wap_proto_t *message);
|
||||||
@ -89,9 +98,31 @@ namespace IPC
|
|||||||
void stop_save_graph(wap_proto_t *message);
|
void stop_save_graph(wap_proto_t *message);
|
||||||
void get_block_hash(wap_proto_t *message);
|
void get_block_hash(wap_proto_t *message);
|
||||||
void get_block_template(wap_proto_t *message);
|
void get_block_template(wap_proto_t *message);
|
||||||
|
void retrieve_blocks(wap_proto_t *message);
|
||||||
|
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 save_bc(wap_proto_t *message);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief initializes it with objects necessary to handle IPC requests and starts
|
||||||
|
* IPC server
|
||||||
|
*
|
||||||
|
* \param p_core cryptonote core object
|
||||||
|
* \param p_p2p p2p object
|
||||||
|
* \param p_testnet testnet mode or not
|
||||||
|
*/
|
||||||
void init(cryptonote::core &p_core,
|
void init(cryptonote::core &p_core,
|
||||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > &p_p2p,
|
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > &p_p2p,
|
||||||
bool p_testnet);
|
bool p_testnet);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief stops the IPC server
|
||||||
|
*
|
||||||
|
* \param p_core cryptonote core object
|
||||||
|
* \param p_p2p p2p object
|
||||||
|
* \param p_testnet testnet mode or not
|
||||||
|
*/
|
||||||
void stop();
|
void stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,36 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \file rpc_translator.cpp
|
* \file daemon_deprecated_rpc.cpp
|
||||||
* \brief Implementations of JSON RPC handlers (Daemon)
|
* \brief Implementations of old JSON RPC handlers (Daemon)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
@ -41,11 +71,19 @@ namespace
|
|||||||
|
|
||||||
const char* STATUS_OK = "OK";
|
const char* STATUS_OK = "OK";
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if daemon can be reached via IPC
|
||||||
|
* \return true if daemon can be reached
|
||||||
|
*/
|
||||||
bool check_connection_to_daemon()
|
bool check_connection_to_daemon()
|
||||||
{
|
{
|
||||||
return ipc_client && wap_client_connected(ipc_client);
|
return ipc_client && wap_client_connected(ipc_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if daemon can be reached and if not tries to connect to it.
|
||||||
|
* \return true if daemon is reachable at the end of the function
|
||||||
|
*/
|
||||||
bool connect_to_daemon() {
|
bool connect_to_daemon() {
|
||||||
if (check_connection_to_daemon()) {
|
if (check_connection_to_daemon()) {
|
||||||
return true;
|
return true;
|
||||||
@ -746,6 +784,125 @@ namespace
|
|||||||
return response.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)
|
||||||
|
{
|
||||||
|
if (!connect_to_daemon()) {
|
||||||
|
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||||
|
"Couldn't 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("start_height") || !request_json["start_height"].IsNumber())
|
||||||
|
{
|
||||||
|
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||||
|
"Incorrect 'start_height' field", "{}");
|
||||||
|
}
|
||||||
|
if (!request_json.HasMember("block_ids") || !request_json["block_ids"].IsArray())
|
||||||
|
{
|
||||||
|
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||||
|
"Incorrect 'block_ids' field", "{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t start_height = request_json["start_height"].GetUint();
|
||||||
|
uint64_t block_count = request_json["blocks_ids"].Size();
|
||||||
|
zlist_t *list = zlist_new();
|
||||||
|
for (int i = 0; i < block_count; i++) {
|
||||||
|
if (!request_json["blocks_ids"][i].IsString()) {
|
||||||
|
zlist_destroy(&list);
|
||||||
|
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||||
|
"Incorrect block_id", "{}");
|
||||||
|
}
|
||||||
|
std::string block_id = request_json["blocks_ids"][i].GetString();
|
||||||
|
char *size_prepended_block_id = new char[block_id.length() + 1];
|
||||||
|
size_prepended_block_id[0] = crypto::HASH_SIZE;
|
||||||
|
memcpy(size_prepended_block_id + 1, block_id.c_str(), crypto::HASH_SIZE);
|
||||||
|
zlist_append(list, size_prepended_block_id);
|
||||||
|
}
|
||||||
|
int rc = wap_client_blocks(ipc_client, &list, start_height);
|
||||||
|
zlist_destroy(&list);
|
||||||
|
|
||||||
|
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_CORE_BUSY) {
|
||||||
|
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||||
|
"Core busy.", "{}");
|
||||||
|
}
|
||||||
|
if (status == IPC::STATUS_INTERNAL_ERROR) {
|
||||||
|
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||||
|
"Internal error.", "{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Document response_json;
|
||||||
|
rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator();
|
||||||
|
rapidjson::Value result_json;
|
||||||
|
result_json.SetObject();
|
||||||
|
rapidjson::Value blocks(rapidjson::kArrayType);
|
||||||
|
|
||||||
|
zframe_t *frame = zmsg_first(wap_client_block_data(ipc_client));
|
||||||
|
if (!frame) {
|
||||||
|
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||||
|
"Internal error.", "{}");
|
||||||
|
}
|
||||||
|
size_t size = zframe_size(frame);
|
||||||
|
char *block_data = reinterpret_cast<char*>(zframe_data(frame));
|
||||||
|
|
||||||
|
rapidjson::Document json;
|
||||||
|
if (json.Parse(block_data, size).HasParseError()) {
|
||||||
|
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||||
|
"Internal error.", "{}");
|
||||||
|
}
|
||||||
|
for (rapidjson::SizeType i = 0; i < json["blocks"].Size(); i++) {
|
||||||
|
rapidjson::Value block_entry(rapidjson::kObjectType);
|
||||||
|
std::string block_string(json["blocks"][i]["block"].GetString(), json["blocks"][i]["block"].GetStringLength());
|
||||||
|
rapidjson::Value block_string_json(rapidjson::kStringType);
|
||||||
|
block_string_json.SetString(block_string.c_str(), block_string.length());
|
||||||
|
block_entry.AddMember("block", block_string_json, allocator);
|
||||||
|
rapidjson::Value txs(rapidjson::kArrayType);
|
||||||
|
for (rapidjson::SizeType j = 0; j < json["blocks"][i]["txs"].Size(); j++) {
|
||||||
|
rapidjson::Value txs_json(rapidjson::kStringType);
|
||||||
|
std::string txs_string(json["blocks"][i]["txs"][j].GetString(), json["blocks"][i]["txs"][j].GetStringLength());
|
||||||
|
txs_json.SetString(txs_string.c_str(), txs_string.length());
|
||||||
|
txs.PushBack(txs_json, allocator);
|
||||||
|
}
|
||||||
|
block_entry.AddMember("txs", txs, allocator);
|
||||||
|
blocks.PushBack(block_entry, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_json.AddMember("start_height", wap_client_start_height(ipc_client), allocator);
|
||||||
|
result_json.AddMember("current_height", wap_client_curr_height(ipc_client), allocator);
|
||||||
|
result_json.AddMember("blocks", blocks, 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();
|
||||||
|
}
|
||||||
|
|
||||||
// Contains a list of method names.
|
// Contains a list of method names.
|
||||||
const char *method_names[] = {
|
const char *method_names[] = {
|
||||||
"getheight",
|
"getheight",
|
||||||
@ -761,6 +918,7 @@ namespace
|
|||||||
"stopsavegraph",
|
"stopsavegraph",
|
||||||
"getblockhash",
|
"getblockhash",
|
||||||
"getblocktemplate",
|
"getblocktemplate",
|
||||||
|
"getblocks",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -779,6 +937,7 @@ namespace
|
|||||||
stopsavegraph,
|
stopsavegraph,
|
||||||
getblockhash,
|
getblockhash,
|
||||||
getblocktemplate,
|
getblocktemplate,
|
||||||
|
getblocks,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -816,12 +975,17 @@ namespace
|
|||||||
namespace RPC
|
namespace RPC
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
* \namespace Daemon
|
* \namespace DaemonDeprecated
|
||||||
* \brief RPC relevant to daemon
|
* \brief DaemonDeprecated RPC stuff
|
||||||
*/
|
*/
|
||||||
namespace DaemonDeprecated
|
namespace DaemonDeprecated
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Starts an HTTP server that listens to old style JSON RPC requests
|
||||||
|
* and creates an IPC client to be able to talk to the daemon
|
||||||
|
* \return status code
|
||||||
|
*/
|
||||||
int start() {
|
int start() {
|
||||||
server = new RPC::Json_rpc_http_server("127.0.0.1", "9997", "daemon_json_rpc", &ev_handler);
|
server = new RPC::Json_rpc_http_server("127.0.0.1", "9997", "daemon_json_rpc", &ev_handler);
|
||||||
if (!server->start()) {
|
if (!server->start()) {
|
||||||
@ -836,6 +1000,9 @@ namespace RPC
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Stops the HTTP server and destroys the IPC client
|
||||||
|
*/
|
||||||
void stop() {
|
void stop() {
|
||||||
if (server) {
|
if (server) {
|
||||||
server->stop();
|
server->stop();
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \file daemon_json_rpc_handlers.h
|
* \file daemon_json_rpc_handlers.h
|
||||||
* \brief Header for JSON RPC handlers (Daemon)
|
* \brief Header for JSON RPC handlers (Daemon)
|
||||||
@ -40,7 +70,15 @@ namespace RPC
|
|||||||
const int SUCCESS = 0;
|
const int SUCCESS = 0;
|
||||||
const int FAILURE_DAEMON_NOT_RUNNING = 1;
|
const int FAILURE_DAEMON_NOT_RUNNING = 1;
|
||||||
const int FAILURE_HTTP_SERVER = 2;
|
const int FAILURE_HTTP_SERVER = 2;
|
||||||
|
/*!
|
||||||
|
* \brief Starts an HTTP server that listens to old style JSON RPC requests
|
||||||
|
* and creates an IPC client to be able to talk to the daemon
|
||||||
|
* \return status code
|
||||||
|
*/
|
||||||
int start();
|
int start();
|
||||||
|
/*!
|
||||||
|
* \brief Stops the HTTP server and destroys the IPC client
|
||||||
|
*/
|
||||||
void stop();
|
void stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,44 @@
|
|||||||
|
// Copyright (c) 2014, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \file json_rpc.cpp
|
||||||
|
* \brief Monero RPC deprecated
|
||||||
|
*
|
||||||
|
* Uses net_skeleton (fossa) as the HTTP server to translate JSON RPC requests
|
||||||
|
* into 0MQ IPC requests, sends them to the daemon, translates back 0MQ IPC responses
|
||||||
|
* into JSON RPC responses all as per the old monero JSON RPC API.
|
||||||
|
*
|
||||||
|
* Written for backwards compatiblity purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "daemon_deprecated_rpc.h"
|
#include "daemon_deprecated_rpc.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
Loading…
Reference in New Issue
Block a user