get_block_hash, get_block_template IPC + deprecated RPC
This commit is contained in:
parent
26f7c3d5a9
commit
c7d27d4979
|
@ -57,6 +57,25 @@ namespace
|
|||
}
|
||||
return check_core_busy();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// equivalent of strstr, but with arbitrary bytes (ie, NULs)
|
||||
// This does not differentiate between "not found" and "found at offset 0"
|
||||
// (taken straight from core_rpc_server.cpp)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
namespace IPC
|
||||
|
@ -483,5 +502,89 @@ namespace IPC
|
|||
p2p->set_save_graph(false);
|
||||
wap_proto_set_status(message, STATUS_OK);
|
||||
}
|
||||
|
||||
void get_block_hash(wap_proto_t *message) {
|
||||
if (!check_core_busy())
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||
return;
|
||||
}
|
||||
uint64_t height = wap_proto_height(message);
|
||||
if (core->get_current_blockchain_height() <= height)
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_HEIGHT_TOO_BIG);
|
||||
return;
|
||||
}
|
||||
std::string hash = string_tools::pod_to_hex(core->get_block_id_by_height(height));
|
||||
zchunk_t *hash_chunk = zchunk_new((void*)(hash.c_str()), hash.length());
|
||||
wap_proto_set_hash(message, &hash_chunk);
|
||||
wap_proto_set_status(message, STATUS_OK);
|
||||
}
|
||||
|
||||
void get_block_template(wap_proto_t *message) {
|
||||
if (!check_core_ready())
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_CORE_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t reserve_size = wap_proto_reserve_size(message);
|
||||
if (reserve_size > 255)
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_RESERVE_SIZE_TOO_BIG);
|
||||
return;
|
||||
}
|
||||
|
||||
cryptonote::account_public_address acc = AUTO_VAL_INIT(acc);
|
||||
|
||||
zchunk_t *address_chunk = wap_proto_address(message);
|
||||
std::string address((char*)zchunk_data(address_chunk), zchunk_size(address_chunk));
|
||||
if (!address.size() || !cryptonote::get_account_address_from_str(acc, testnet, address))
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_WRONG_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
cryptonote::block b = AUTO_VAL_INIT(b);
|
||||
cryptonote::blobdata blob_reserve;
|
||||
blob_reserve.resize(reserve_size, 0);
|
||||
uint64_t difficulty = wap_proto_difficulty(message);
|
||||
uint64_t height;
|
||||
if (!core->get_block_template(b, acc, difficulty, height, blob_reserve))
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
uint64_t reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key));
|
||||
if (!reserved_offset)
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
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())
|
||||
{
|
||||
wap_proto_set_status(message, STATUS_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
wap_proto_set_height(message, height);
|
||||
wap_proto_set_difficulty(message, difficulty);
|
||||
wap_proto_set_reserved_offset(message, reserved_offset);
|
||||
std::string prev_hash = string_tools::pod_to_hex(b.prev_id);
|
||||
zchunk_t *prev_hash_chunk = zchunk_new((void*)prev_hash.c_str(), prev_hash.length());
|
||||
wap_proto_set_prev_hash(message, &prev_hash_chunk);
|
||||
|
||||
cryptonote::blobdata blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
||||
zchunk_t *blob_chunk = zchunk_new((void*)blocktemplate_blob.c_str(), blocktemplate_blob.length());
|
||||
wap_proto_set_block_template_blob(message, &blob_chunk);
|
||||
wap_proto_set_status(message, STATUS_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,8 +66,10 @@ namespace IPC
|
|||
const uint64_t STATUS_RANDOM_OUTS_FAILED = 9;
|
||||
const uint64_t STATUS_MINING_NOT_STOPPED = 10;
|
||||
const uint64_t STATUS_NOT_MINING = 11;
|
||||
const uint64_t STATUS_INVALID_LOG_LEVEL = 11;
|
||||
const uint64_t STATUS_ERROR_STORING_BLOCKCHAIN = 11;
|
||||
const uint64_t STATUS_INVALID_LOG_LEVEL = 12;
|
||||
const uint64_t STATUS_ERROR_STORING_BLOCKCHAIN = 13;
|
||||
const uint64_t STATUS_HEIGHT_TOO_BIG = 13;
|
||||
const uint64_t STATUS_RESERVE_SIZE_TOO_BIG = 14;
|
||||
namespace Daemon
|
||||
{
|
||||
void start_mining(wap_proto_t *message);
|
||||
|
@ -85,6 +87,8 @@ namespace IPC
|
|||
void set_log_level(wap_proto_t *message);
|
||||
void start_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_template(wap_proto_t *message);
|
||||
void init(cryptonote::core &p_core,
|
||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> > &p_p2p,
|
||||
bool p_testnet);
|
||||
|
|
|
@ -147,6 +147,16 @@ WAP_EXPORT int
|
|||
WAP_EXPORT int
|
||||
wap_client_stop_save_graph (wap_client_t *self);
|
||||
|
||||
// Get block hash
|
||||
// Returns >= 0 if successful, -1 if interrupted.
|
||||
WAP_EXPORT int
|
||||
wap_client_get_block_hash (wap_client_t *self, uint64_t height);
|
||||
|
||||
// Get block template
|
||||
// Returns >= 0 if successful, -1 if interrupted.
|
||||
WAP_EXPORT int
|
||||
wap_client_get_block_template (wap_client_t *self, uint64_t reserve_size, zchunk_t **address_p);
|
||||
|
||||
// Return last received status
|
||||
WAP_EXPORT int
|
||||
wap_client_status (wap_client_t *self);
|
||||
|
@ -243,6 +253,22 @@ WAP_EXPORT uint64_t
|
|||
WAP_EXPORT zchunk_t *
|
||||
wap_client_address (wap_client_t *self);
|
||||
|
||||
// Return last received hash
|
||||
WAP_EXPORT zchunk_t *
|
||||
wap_client_hash (wap_client_t *self);
|
||||
|
||||
// Return last received reserved_offset
|
||||
WAP_EXPORT uint64_t
|
||||
wap_client_reserved_offset (wap_client_t *self);
|
||||
|
||||
// Return last received prev_hash
|
||||
WAP_EXPORT zchunk_t *
|
||||
wap_client_prev_hash (wap_client_t *self);
|
||||
|
||||
// Return last received block_template_blob
|
||||
WAP_EXPORT zchunk_t *
|
||||
wap_client_block_template_blob (wap_client_t *self);
|
||||
|
||||
// Self test of this class
|
||||
WAP_EXPORT void
|
||||
wap_client_test (bool verbose);
|
||||
|
|
|
@ -40,10 +40,12 @@ typedef enum {
|
|||
expect_set_log_level_ok_state = 17,
|
||||
expect_start_save_graph_ok_state = 18,
|
||||
expect_stop_save_graph_ok_state = 19,
|
||||
expect_close_ok_state = 20,
|
||||
defaults_state = 21,
|
||||
have_error_state = 22,
|
||||
reexpect_open_ok_state = 23
|
||||
expect_get_block_hash_ok_state = 20,
|
||||
expect_get_block_template_ok_state = 21,
|
||||
expect_close_ok_state = 22,
|
||||
defaults_state = 23,
|
||||
have_error_state = 24,
|
||||
reexpect_open_ok_state = 25
|
||||
} state_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -68,29 +70,33 @@ typedef enum {
|
|||
set_log_level_event = 18,
|
||||
start_save_graph_event = 19,
|
||||
stop_save_graph_event = 20,
|
||||
destructor_event = 21,
|
||||
blocks_ok_event = 22,
|
||||
get_ok_event = 23,
|
||||
put_ok_event = 24,
|
||||
save_bc_ok_event = 25,
|
||||
start_ok_event = 26,
|
||||
stop_ok_event = 27,
|
||||
output_indexes_ok_event = 28,
|
||||
random_outs_ok_event = 29,
|
||||
get_height_ok_event = 30,
|
||||
get_info_ok_event = 31,
|
||||
get_peer_list_ok_event = 32,
|
||||
get_mining_status_ok_event = 33,
|
||||
set_log_hash_rate_ok_event = 34,
|
||||
set_log_level_ok_event = 35,
|
||||
start_save_graph_ok_event = 36,
|
||||
stop_save_graph_ok_event = 37,
|
||||
close_ok_event = 38,
|
||||
ping_ok_event = 39,
|
||||
error_event = 40,
|
||||
exception_event = 41,
|
||||
command_invalid_event = 42,
|
||||
other_event = 43
|
||||
get_block_hash_event = 21,
|
||||
get_block_template_event = 22,
|
||||
destructor_event = 23,
|
||||
blocks_ok_event = 24,
|
||||
get_ok_event = 25,
|
||||
put_ok_event = 26,
|
||||
save_bc_ok_event = 27,
|
||||
start_ok_event = 28,
|
||||
stop_ok_event = 29,
|
||||
output_indexes_ok_event = 30,
|
||||
random_outs_ok_event = 31,
|
||||
get_height_ok_event = 32,
|
||||
get_info_ok_event = 33,
|
||||
get_peer_list_ok_event = 34,
|
||||
get_mining_status_ok_event = 35,
|
||||
set_log_hash_rate_ok_event = 36,
|
||||
set_log_level_ok_event = 37,
|
||||
start_save_graph_ok_event = 38,
|
||||
stop_save_graph_ok_event = 39,
|
||||
get_block_hash_ok_event = 40,
|
||||
get_block_template_ok_event = 41,
|
||||
close_ok_event = 42,
|
||||
ping_ok_event = 43,
|
||||
error_event = 44,
|
||||
exception_event = 45,
|
||||
command_invalid_event = 46,
|
||||
other_event = 47
|
||||
} event_t;
|
||||
|
||||
// Names for state machine logging and error reporting
|
||||
|
@ -116,6 +122,8 @@ s_state_name [] = {
|
|||
"expect set log level ok",
|
||||
"expect start save graph ok",
|
||||
"expect stop save graph ok",
|
||||
"expect get block hash ok",
|
||||
"expect get block template ok",
|
||||
"expect close ok",
|
||||
"defaults",
|
||||
"have error",
|
||||
|
@ -145,6 +153,8 @@ s_event_name [] = {
|
|||
"SET_LOG_LEVEL",
|
||||
"START_SAVE_GRAPH",
|
||||
"STOP_SAVE_GRAPH",
|
||||
"GET_BLOCK_HASH",
|
||||
"GET_BLOCK_TEMPLATE",
|
||||
"destructor",
|
||||
"BLOCKS_OK",
|
||||
"GET_OK",
|
||||
|
@ -162,6 +172,8 @@ s_event_name [] = {
|
|||
"SET_LOG_LEVEL_OK",
|
||||
"START_SAVE_GRAPH_OK",
|
||||
"STOP_SAVE_GRAPH_OK",
|
||||
"GET_BLOCK_HASH_OK",
|
||||
"GET_BLOCK_TEMPLATE_OK",
|
||||
"CLOSE_OK",
|
||||
"PING_OK",
|
||||
"ERROR",
|
||||
|
@ -191,6 +203,8 @@ struct _client_args_t {
|
|||
uint64_t thread_count;
|
||||
uint8_t visible;
|
||||
uint8_t level;
|
||||
uint64_t height;
|
||||
uint64_t reserve_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -258,6 +272,10 @@ static void
|
|||
prepare_set_log_hash_rate_command (client_t *self);
|
||||
static void
|
||||
prepare_set_log_level_command (client_t *self);
|
||||
static void
|
||||
prepare_get_block_hash_command (client_t *self);
|
||||
static void
|
||||
prepare_get_block_template_command (client_t *self);
|
||||
static void
|
||||
check_if_connection_is_dead (client_t *self);
|
||||
static void
|
||||
|
@ -292,6 +310,10 @@ static void
|
|||
signal_have_start_save_graph_ok (client_t *self);
|
||||
static void
|
||||
signal_have_stop_save_graph_ok (client_t *self);
|
||||
static void
|
||||
signal_have_get_block_hash_ok (client_t *self);
|
||||
static void
|
||||
signal_have_get_block_template_ok (client_t *self);
|
||||
static void
|
||||
signal_failure (client_t *self);
|
||||
static void
|
||||
|
@ -577,6 +599,18 @@ s_protocol_event (s_client_t *self, wap_proto_t *message)
|
|||
case WAP_PROTO_STOP_SAVE_GRAPH_OK:
|
||||
return stop_save_graph_ok_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
return get_block_hash_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
return get_block_hash_ok_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
return get_block_template_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
return get_block_template_ok_event;
|
||||
break;
|
||||
case WAP_PROTO_STOP:
|
||||
return stop_event;
|
||||
break;
|
||||
|
@ -983,6 +1017,42 @@ s_client_execute (s_client_t *self, event_t event)
|
|||
self->state = expect_stop_save_graph_ok_state;
|
||||
}
|
||||
else
|
||||
if (self->event == get_block_hash_event) {
|
||||
if (!self->exception) {
|
||||
// prepare get block hash command
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ prepare get block hash command");
|
||||
prepare_get_block_hash_command (&self->client);
|
||||
}
|
||||
if (!self->exception) {
|
||||
// send GET_BLOCK_HASH
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ send GET_BLOCK_HASH");
|
||||
wap_proto_set_id (self->message, WAP_PROTO_GET_BLOCK_HASH);
|
||||
wap_proto_send (self->message, self->dealer);
|
||||
}
|
||||
if (!self->exception)
|
||||
self->state = expect_get_block_hash_ok_state;
|
||||
}
|
||||
else
|
||||
if (self->event == get_block_template_event) {
|
||||
if (!self->exception) {
|
||||
// prepare get block template command
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ prepare get block template command");
|
||||
prepare_get_block_template_command (&self->client);
|
||||
}
|
||||
if (!self->exception) {
|
||||
// send GET_BLOCK_TEMPLATE
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ send GET_BLOCK_TEMPLATE");
|
||||
wap_proto_set_id (self->message, WAP_PROTO_GET_BLOCK_TEMPLATE);
|
||||
wap_proto_send (self->message, self->dealer);
|
||||
}
|
||||
if (!self->exception)
|
||||
self->state = expect_get_block_template_ok_state;
|
||||
}
|
||||
else
|
||||
if (self->event == destructor_event) {
|
||||
if (!self->exception) {
|
||||
// send CLOSE
|
||||
|
@ -1764,6 +1834,96 @@ s_client_execute (s_client_t *self, event_t event)
|
|||
}
|
||||
break;
|
||||
|
||||
case expect_get_block_hash_ok_state:
|
||||
if (self->event == get_block_hash_ok_event) {
|
||||
if (!self->exception) {
|
||||
// signal have get block hash ok
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ signal have get block hash ok");
|
||||
signal_have_get_block_hash_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_block_template_ok_state:
|
||||
if (self->event == get_block_template_ok_event) {
|
||||
if (!self->exception) {
|
||||
// signal have get block template ok
|
||||
if (wap_client_verbose)
|
||||
zsys_debug ("wap_client: $ signal have get block template ok");
|
||||
signal_have_get_block_template_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) {
|
||||
|
@ -2093,6 +2253,17 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument)
|
|||
if (streq (method, "STOP SAVE GRAPH")) {
|
||||
s_client_execute (self, stop_save_graph_event);
|
||||
}
|
||||
else
|
||||
if (streq (method, "GET BLOCK HASH")) {
|
||||
zsock_recv (self->cmdpipe, "8", &self->args.height);
|
||||
s_client_execute (self, get_block_hash_event);
|
||||
}
|
||||
else
|
||||
if (streq (method, "GET BLOCK TEMPLATE")) {
|
||||
zchunk_destroy (&self->args.address);
|
||||
zsock_recv (self->cmdpipe, "8p", &self->args.reserve_size, &self->args.address);
|
||||
s_client_execute (self, get_block_template_event);
|
||||
}
|
||||
// Cleanup pipe if any argument frames are still waiting to be eaten
|
||||
if (zsock_rcvmore (self->cmdpipe)) {
|
||||
zsys_error ("wap_client: trailing API command frames (%s)", method);
|
||||
|
@ -2229,6 +2400,10 @@ struct _wap_client_t {
|
|||
uint64_t speed; // Returned by actor reply
|
||||
uint64_t thread_count; // Returned by actor reply
|
||||
zchunk_t *address; // Returned by actor reply
|
||||
zchunk_t *hash; // Returned by actor reply
|
||||
uint64_t reserved_offset; // Returned by actor reply
|
||||
zchunk_t *prev_hash; // Returned by actor reply
|
||||
zchunk_t *block_template_blob; // Returned by actor reply
|
||||
};
|
||||
|
||||
|
||||
|
@ -2284,6 +2459,9 @@ wap_client_destroy (wap_client_t **self_p)
|
|||
zframe_destroy (&self->white_list);
|
||||
zframe_destroy (&self->gray_list);
|
||||
zchunk_destroy (&self->address);
|
||||
zchunk_destroy (&self->hash);
|
||||
zchunk_destroy (&self->prev_hash);
|
||||
zchunk_destroy (&self->block_template_blob);
|
||||
free (self);
|
||||
*self_p = NULL;
|
||||
}
|
||||
|
@ -2432,6 +2610,17 @@ s_accept_reply (wap_client_t *self, ...)
|
|||
if (streq (reply, "STOP SAVE GRAPH OK")) {
|
||||
zsock_recv (self->actor, "8", &self->status);
|
||||
}
|
||||
else
|
||||
if (streq (reply, "GET BLOCK HASH OK")) {
|
||||
zchunk_destroy (&self->hash);
|
||||
zsock_recv (self->actor, "8p", &self->status, &self->hash);
|
||||
}
|
||||
else
|
||||
if (streq (reply, "GET BLOCK TEMPLATE OK")) {
|
||||
zchunk_destroy (&self->prev_hash);
|
||||
zchunk_destroy (&self->block_template_blob);
|
||||
zsock_recv (self->actor, "8888pp", &self->status, &self->reserved_offset, &self->height, &self->difficulty, &self->prev_hash, &self->block_template_blob);
|
||||
}
|
||||
break;
|
||||
}
|
||||
filter = va_arg (args, char *);
|
||||
|
@ -2745,6 +2934,39 @@ wap_client_stop_save_graph (wap_client_t *self)
|
|||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Get block hash
|
||||
// Returns >= 0 if successful, -1 if interrupted.
|
||||
|
||||
int
|
||||
wap_client_get_block_hash (wap_client_t *self, uint64_t height)
|
||||
{
|
||||
assert (self);
|
||||
|
||||
zsock_send (self->actor, "s8", "GET BLOCK HASH", height);
|
||||
if (s_accept_reply (self, "GET BLOCK HASH OK", "FAILURE", NULL))
|
||||
return -1; // Interrupted or timed-out
|
||||
return self->status;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Get block template
|
||||
// Returns >= 0 if successful, -1 if interrupted.
|
||||
|
||||
int
|
||||
wap_client_get_block_template (wap_client_t *self, uint64_t reserve_size, zchunk_t **address_p)
|
||||
{
|
||||
assert (self);
|
||||
|
||||
zsock_send (self->actor, "s8p", "GET BLOCK TEMPLATE", reserve_size, *address_p);
|
||||
*address_p = NULL; // Take ownership of address
|
||||
if (s_accept_reply (self, "GET BLOCK TEMPLATE OK", "FAILURE", NULL))
|
||||
return -1; // Interrupted or timed-out
|
||||
return self->status;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Return last received status
|
||||
|
||||
|
@ -3007,3 +3229,47 @@ wap_client_address (wap_client_t *self)
|
|||
assert (self);
|
||||
return self->address;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Return last received hash
|
||||
|
||||
zchunk_t *
|
||||
wap_client_hash (wap_client_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->hash;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Return last received reserved_offset
|
||||
|
||||
uint64_t
|
||||
wap_client_reserved_offset (wap_client_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->reserved_offset;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Return last received prev_hash
|
||||
|
||||
zchunk_t *
|
||||
wap_client_prev_hash (wap_client_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->prev_hash;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Return last received block_template_blob
|
||||
|
||||
zchunk_t *
|
||||
wap_client_block_template_blob (wap_client_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->block_template_blob;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,25 @@ ERROR.
|
|||
STOP_SAVE_GRAPH_OK - This is a codec for a Bitcoin Wallet Access Protocol (RFC tbd)
|
||||
status number 8 Status
|
||||
|
||||
GET_BLOCK_HASH - get_block_hash IPC
|
||||
height number 8 Height
|
||||
|
||||
GET_BLOCK_HASH_OK - This is a codec for a Bitcoin Wallet Access Protocol (RFC tbd)
|
||||
status number 8 Status
|
||||
hash chunk Hash
|
||||
|
||||
GET_BLOCK_TEMPLATE - get_block_template IPC
|
||||
reserve_size number 8 Reserve size
|
||||
address chunk Address
|
||||
|
||||
GET_BLOCK_TEMPLATE_OK - This is a codec for a Bitcoin Wallet Access Protocol (RFC tbd)
|
||||
status number 8 Status
|
||||
reserved_offset number 8 Rservered Offset
|
||||
height number 8 Height
|
||||
difficulty number 8 Difficulty
|
||||
prev_hash chunk Previous Hash
|
||||
block_template_blob chunk Block template blob
|
||||
|
||||
STOP - Wallet asks daemon to start mining. Daemon replies with STOP-OK, or
|
||||
ERROR.
|
||||
|
||||
|
@ -205,13 +224,17 @@ Daemon will reply with CLOSE-OK or ERROR.
|
|||
#define WAP_PROTO_START_SAVE_GRAPH_OK 30
|
||||
#define WAP_PROTO_STOP_SAVE_GRAPH 31
|
||||
#define WAP_PROTO_STOP_SAVE_GRAPH_OK 32
|
||||
#define WAP_PROTO_STOP 33
|
||||
#define WAP_PROTO_STOP_OK 34
|
||||
#define WAP_PROTO_CLOSE 35
|
||||
#define WAP_PROTO_CLOSE_OK 36
|
||||
#define WAP_PROTO_PING 37
|
||||
#define WAP_PROTO_PING_OK 38
|
||||
#define WAP_PROTO_ERROR 39
|
||||
#define WAP_PROTO_GET_BLOCK_HASH 33
|
||||
#define WAP_PROTO_GET_BLOCK_HASH_OK 34
|
||||
#define WAP_PROTO_GET_BLOCK_TEMPLATE 35
|
||||
#define WAP_PROTO_GET_BLOCK_TEMPLATE_OK 36
|
||||
#define WAP_PROTO_STOP 37
|
||||
#define WAP_PROTO_STOP_OK 38
|
||||
#define WAP_PROTO_CLOSE 39
|
||||
#define WAP_PROTO_CLOSE_OK 40
|
||||
#define WAP_PROTO_PING 41
|
||||
#define WAP_PROTO_PING_OK 42
|
||||
#define WAP_PROTO_ERROR 43
|
||||
|
||||
#include <czmq.h>
|
||||
|
||||
|
@ -491,6 +514,48 @@ byte
|
|||
void
|
||||
wap_proto_set_level (wap_proto_t *self, byte level);
|
||||
|
||||
// Get a copy of the hash field
|
||||
zchunk_t *
|
||||
wap_proto_hash (wap_proto_t *self);
|
||||
// Get the hash field and transfer ownership to caller
|
||||
zchunk_t *
|
||||
wap_proto_get_hash (wap_proto_t *self);
|
||||
// Set the hash field, transferring ownership from caller
|
||||
void
|
||||
wap_proto_set_hash (wap_proto_t *self, zchunk_t **chunk_p);
|
||||
|
||||
// Get/set the reserve_size field
|
||||
uint64_t
|
||||
wap_proto_reserve_size (wap_proto_t *self);
|
||||
void
|
||||
wap_proto_set_reserve_size (wap_proto_t *self, uint64_t reserve_size);
|
||||
|
||||
// Get/set the reserved_offset field
|
||||
uint64_t
|
||||
wap_proto_reserved_offset (wap_proto_t *self);
|
||||
void
|
||||
wap_proto_set_reserved_offset (wap_proto_t *self, uint64_t reserved_offset);
|
||||
|
||||
// Get a copy of the prev_hash field
|
||||
zchunk_t *
|
||||
wap_proto_prev_hash (wap_proto_t *self);
|
||||
// Get the prev_hash field and transfer ownership to caller
|
||||
zchunk_t *
|
||||
wap_proto_get_prev_hash (wap_proto_t *self);
|
||||
// Set the prev_hash field, transferring ownership from caller
|
||||
void
|
||||
wap_proto_set_prev_hash (wap_proto_t *self, zchunk_t **chunk_p);
|
||||
|
||||
// Get a copy of the block_template_blob field
|
||||
zchunk_t *
|
||||
wap_proto_block_template_blob (wap_proto_t *self);
|
||||
// Get the block_template_blob field and transfer ownership to caller
|
||||
zchunk_t *
|
||||
wap_proto_get_block_template_blob (wap_proto_t *self);
|
||||
// Set the block_template_blob field, transferring ownership from caller
|
||||
void
|
||||
wap_proto_set_block_template_blob (wap_proto_t *self, zchunk_t **chunk_p);
|
||||
|
||||
// Get/set the reason field
|
||||
const char *
|
||||
wap_proto_reason (wap_proto_t *self);
|
||||
|
|
|
@ -47,11 +47,13 @@ typedef enum {
|
|||
set_log_level_event = 16,
|
||||
start_save_graph_event = 17,
|
||||
stop_save_graph_event = 18,
|
||||
close_event = 19,
|
||||
ping_event = 20,
|
||||
expired_event = 21,
|
||||
exception_event = 22,
|
||||
settled_event = 23
|
||||
get_block_hash_event = 19,
|
||||
get_block_template_event = 20,
|
||||
close_event = 21,
|
||||
ping_event = 22,
|
||||
expired_event = 23,
|
||||
exception_event = 24,
|
||||
settled_event = 25
|
||||
} event_t;
|
||||
|
||||
// Names for state machine logging and error reporting
|
||||
|
@ -85,6 +87,8 @@ s_event_name [] = {
|
|||
"SET_LOG_LEVEL",
|
||||
"START_SAVE_GRAPH",
|
||||
"STOP_SAVE_GRAPH",
|
||||
"GET_BLOCK_HASH",
|
||||
"GET_BLOCK_TEMPLATE",
|
||||
"CLOSE",
|
||||
"PING",
|
||||
"expired",
|
||||
|
@ -186,6 +190,10 @@ static void
|
|||
start_save_graph (client_t *self);
|
||||
static void
|
||||
stop_save_graph (client_t *self);
|
||||
static void
|
||||
get_block_hash (client_t *self);
|
||||
static void
|
||||
get_block_template (client_t *self);
|
||||
static void
|
||||
deregister_wallet (client_t *self);
|
||||
static void
|
||||
|
@ -418,6 +426,12 @@ s_protocol_event (wap_proto_t *message)
|
|||
case WAP_PROTO_STOP_SAVE_GRAPH:
|
||||
return stop_save_graph_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
return get_block_hash_event;
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
return get_block_template_event;
|
||||
break;
|
||||
case WAP_PROTO_STOP:
|
||||
return stop_event;
|
||||
break;
|
||||
|
@ -924,6 +938,42 @@ s_client_execute (s_client_t *self, event_t event)
|
|||
}
|
||||
}
|
||||
else
|
||||
if (self->event == get_block_hash_event) {
|
||||
if (!self->exception) {
|
||||
// get block hash
|
||||
if (self->server->verbose)
|
||||
zsys_debug ("%s: $ get block hash", self->log_prefix);
|
||||
get_block_hash (&self->client);
|
||||
}
|
||||
if (!self->exception) {
|
||||
// send GET_BLOCK_HASH_OK
|
||||
if (self->server->verbose)
|
||||
zsys_debug ("%s: $ send GET_BLOCK_HASH_OK",
|
||||
self->log_prefix);
|
||||
wap_proto_set_id (self->server->message, WAP_PROTO_GET_BLOCK_HASH_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_block_template_event) {
|
||||
if (!self->exception) {
|
||||
// get block template
|
||||
if (self->server->verbose)
|
||||
zsys_debug ("%s: $ get block template", self->log_prefix);
|
||||
get_block_template (&self->client);
|
||||
}
|
||||
if (!self->exception) {
|
||||
// send GET_BLOCK_TEMPLATE_OK
|
||||
if (self->server->verbose)
|
||||
zsys_debug ("%s: $ send GET_BLOCK_TEMPLATE_OK",
|
||||
self->log_prefix);
|
||||
wap_proto_set_id (self->server->message, WAP_PROTO_GET_BLOCK_TEMPLATE_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
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
*/
|
||||
|
||||
#include "wap_classes.h"
|
||||
// TODO: Change these to match your project's needs
|
||||
#include "../include/wap_proto.h"
|
||||
#include "../include/wap_client.h"
|
||||
|
||||
// Forward reference to method arguments structure
|
||||
typedef struct _client_args_t client_args_t;
|
||||
|
@ -98,6 +95,7 @@ use_connect_timeout (client_t *self)
|
|||
engine_set_timeout (self, self->args->timeout);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// client_is_connected
|
||||
//
|
||||
|
@ -110,6 +108,7 @@ client_is_connected (client_t *self)
|
|||
engine_set_timeout (self, self->heartbeat_timer);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// check_if_connection_is_dead
|
||||
//
|
||||
|
@ -125,17 +124,6 @@ check_if_connection_is_dead (client_t *self)
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// use_heartbeat_timer
|
||||
//
|
||||
|
||||
static void
|
||||
use_heartbeat_timer (client_t *self)
|
||||
{
|
||||
engine_set_timeout (self, self->heartbeat_timer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_blocks_command
|
||||
|
@ -148,15 +136,6 @@ prepare_blocks_command (client_t *self)
|
|||
wap_proto_set_start_height (self->message, self->args->start_height);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_get_output_indexes_command
|
||||
//
|
||||
|
||||
static void
|
||||
prepare_get_output_indexes_command (client_t *self)
|
||||
{
|
||||
wap_proto_set_tx_id (self->message, &self->args->tx_id);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_blocks_ok
|
||||
|
@ -165,10 +144,13 @@ prepare_get_output_indexes_command (client_t *self)
|
|||
static void
|
||||
signal_have_blocks_ok (client_t *self)
|
||||
{
|
||||
zmsg_t *msg = wap_proto_get_block_data (self->message);
|
||||
assert(msg != 0);
|
||||
printf("%p <--\n", (void*)msg);
|
||||
zsock_send (self->cmdpipe, "s888p", "BLOCKS OK", wap_proto_status(self->message),
|
||||
wap_proto_start_height (self->message),
|
||||
wap_proto_curr_height (self->message),
|
||||
wap_proto_get_block_data (self->message));
|
||||
msg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,8 +183,8 @@ prepare_put_command (client_t *self)
|
|||
static void
|
||||
signal_have_put_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8s", "PUT OK", wap_proto_status(self->message),
|
||||
wap_proto_tx_id (self->message));
|
||||
zsock_send (self->cmdpipe, "s8", "PUT OK",
|
||||
wap_proto_status (self->message));
|
||||
}
|
||||
|
||||
|
||||
|
@ -224,10 +206,21 @@ prepare_get_command (client_t *self)
|
|||
static void
|
||||
signal_have_get_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8p", "GET OK", 0,
|
||||
zsock_send (self->cmdpipe, "sip", "GET OK", 0,
|
||||
wap_proto_get_tx_data (self->message));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 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_save_ok
|
||||
|
@ -258,31 +251,9 @@ signal_have_start_ok (client_t *self)
|
|||
static void
|
||||
signal_have_stop_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8", "STOP OK", 0);
|
||||
zsock_send (self->cmdpipe, "si", "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
|
||||
//
|
||||
|
||||
static void
|
||||
signal_have_output_indexes_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8p", "OUTPUT INDEXES OK",
|
||||
wap_proto_status (self->message),
|
||||
wap_proto_get_o_indexes (self->message));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_success
|
||||
|
@ -352,6 +323,37 @@ signal_server_not_present (client_t *self)
|
|||
zsock_send (self->cmdpipe, "sis", "FAILURE", -1, "Server is not reachable");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_get_output_indexes_command
|
||||
//
|
||||
|
||||
static void
|
||||
prepare_get_output_indexes_command (client_t *self)
|
||||
{
|
||||
wap_proto_set_tx_id (self->message, &self->args->tx_id);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_output_indexes_ok
|
||||
//
|
||||
|
||||
static void
|
||||
signal_have_output_indexes_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8p", "OUTPUT INDEXES OK",
|
||||
wap_proto_status (self->message),
|
||||
wap_proto_get_o_indexes (self->message));
|
||||
}
|
||||
|
||||
void wap_client_test(bool verbose) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_get_random_outs_command
|
||||
//
|
||||
|
@ -359,7 +361,6 @@ signal_server_not_present (client_t *self)
|
|||
static void
|
||||
prepare_get_random_outs_command (client_t *self)
|
||||
{
|
||||
wap_proto_set_outs_count(self->message, self->args->outs_count);
|
||||
wap_proto_set_amounts (self->message, &self->args->amounts);
|
||||
}
|
||||
|
||||
|
@ -376,6 +377,8 @@ signal_have_random_outs_ok (client_t *self)
|
|||
wap_proto_get_random_outputs (self->message));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_get_info_ok
|
||||
//
|
||||
|
@ -397,8 +400,9 @@ signal_have_get_info_ok (client_t *self)
|
|||
wap_proto_grey_peerlist_size (self->message));
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_get_get_peer_list_ok
|
||||
// signal_have_get_peer_list_ok
|
||||
//
|
||||
|
||||
static void
|
||||
|
@ -488,3 +492,52 @@ signal_have_stop_save_graph_ok (client_t *self)
|
|||
zsock_send (self->cmdpipe, "s8", "STOP SAVE GRAPH OK",
|
||||
wap_proto_status (self->message));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_get_block_hash_command
|
||||
//
|
||||
|
||||
static void
|
||||
prepare_get_block_hash_command (client_t *self)
|
||||
{
|
||||
wap_proto_set_height (self->message, self->args->height);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_get_block_hash_ok
|
||||
//
|
||||
|
||||
static void
|
||||
signal_have_get_block_hash_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8p", "GET BLOCK HASH OK",
|
||||
wap_proto_status (self->message), wap_proto_get_hash (self->message));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// prepare_get_block_template_command
|
||||
//
|
||||
|
||||
static void
|
||||
prepare_get_block_template_command (client_t *self)
|
||||
{
|
||||
wap_proto_set_reserve_size (self->message, self->args->reserve_size);
|
||||
wap_proto_set_address (self->message, &self->args->address);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// signal_have_get_block_template_ok
|
||||
//
|
||||
|
||||
static void
|
||||
signal_have_get_block_template_ok (client_t *self)
|
||||
{
|
||||
zsock_send (self->cmdpipe, "s8888pp", "GET BLOCK TEMPLATE OK",
|
||||
wap_proto_status (self->message),
|
||||
wap_proto_reserved_offset (self->message),
|
||||
wap_proto_height (self->message),
|
||||
wap_proto_difficulty (self->message),
|
||||
wap_proto_get_prev_hash (self->message),
|
||||
wap_proto_get_block_template_blob (self->message));
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,11 @@ struct _wap_proto_t {
|
|||
uint64_t speed; // Speed
|
||||
byte visible; // Visible
|
||||
byte level; // Level
|
||||
zchunk_t *hash; // Hash
|
||||
uint64_t reserve_size; // Reserve size
|
||||
uint64_t reserved_offset; // Rservered Offset
|
||||
zchunk_t *prev_hash; // Previous Hash
|
||||
zchunk_t *block_template_blob; // Block template blob
|
||||
char reason [256]; // Printable explanation
|
||||
};
|
||||
|
||||
|
@ -253,6 +258,9 @@ wap_proto_destroy (wap_proto_t **self_p)
|
|||
zchunk_destroy (&self->address);
|
||||
zframe_destroy (&self->white_list);
|
||||
zframe_destroy (&self->gray_list);
|
||||
zchunk_destroy (&self->hash);
|
||||
zchunk_destroy (&self->prev_hash);
|
||||
zchunk_destroy (&self->block_template_blob);
|
||||
|
||||
// Free object itself
|
||||
free (self);
|
||||
|
@ -568,6 +576,69 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input)
|
|||
GET_NUMBER8 (self->status);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
GET_NUMBER8 (self->height);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
GET_NUMBER8 (self->status);
|
||||
{
|
||||
size_t chunk_size;
|
||||
GET_NUMBER4 (chunk_size);
|
||||
if (self->needle + chunk_size > (self->ceiling)) {
|
||||
zsys_warning ("wap_proto: hash is missing data");
|
||||
goto malformed;
|
||||
}
|
||||
zchunk_destroy (&self->hash);
|
||||
self->hash = zchunk_new (self->needle, chunk_size);
|
||||
self->needle += chunk_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
GET_NUMBER8 (self->reserve_size);
|
||||
{
|
||||
size_t chunk_size;
|
||||
GET_NUMBER4 (chunk_size);
|
||||
if (self->needle + chunk_size > (self->ceiling)) {
|
||||
zsys_warning ("wap_proto: address is missing data");
|
||||
goto malformed;
|
||||
}
|
||||
zchunk_destroy (&self->address);
|
||||
self->address = zchunk_new (self->needle, chunk_size);
|
||||
self->needle += chunk_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
GET_NUMBER8 (self->status);
|
||||
GET_NUMBER8 (self->reserved_offset);
|
||||
GET_NUMBER8 (self->height);
|
||||
GET_NUMBER8 (self->difficulty);
|
||||
{
|
||||
size_t chunk_size;
|
||||
GET_NUMBER4 (chunk_size);
|
||||
if (self->needle + chunk_size > (self->ceiling)) {
|
||||
zsys_warning ("wap_proto: prev_hash is missing data");
|
||||
goto malformed;
|
||||
}
|
||||
zchunk_destroy (&self->prev_hash);
|
||||
self->prev_hash = zchunk_new (self->needle, chunk_size);
|
||||
self->needle += chunk_size;
|
||||
}
|
||||
{
|
||||
size_t chunk_size;
|
||||
GET_NUMBER4 (chunk_size);
|
||||
if (self->needle + chunk_size > (self->ceiling)) {
|
||||
zsys_warning ("wap_proto: block_template_blob is missing data");
|
||||
goto malformed;
|
||||
}
|
||||
zchunk_destroy (&self->block_template_blob);
|
||||
self->block_template_blob = zchunk_new (self->needle, chunk_size);
|
||||
self->needle += chunk_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case WAP_PROTO_STOP:
|
||||
break;
|
||||
|
||||
|
@ -734,6 +805,33 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
|
|||
case WAP_PROTO_STOP_SAVE_GRAPH_OK:
|
||||
frame_size += 8; // status
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
frame_size += 8; // height
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
frame_size += 8; // status
|
||||
frame_size += 4; // Size is 4 octets
|
||||
if (self->hash)
|
||||
frame_size += zchunk_size (self->hash);
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
frame_size += 8; // reserve_size
|
||||
frame_size += 4; // Size is 4 octets
|
||||
if (self->address)
|
||||
frame_size += zchunk_size (self->address);
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
frame_size += 8; // status
|
||||
frame_size += 8; // reserved_offset
|
||||
frame_size += 8; // height
|
||||
frame_size += 8; // difficulty
|
||||
frame_size += 4; // Size is 4 octets
|
||||
if (self->prev_hash)
|
||||
frame_size += zchunk_size (self->prev_hash);
|
||||
frame_size += 4; // Size is 4 octets
|
||||
if (self->block_template_blob)
|
||||
frame_size += zchunk_size (self->block_template_blob);
|
||||
break;
|
||||
case WAP_PROTO_ERROR:
|
||||
frame_size += 2; // status
|
||||
frame_size += 1 + strlen (self->reason);
|
||||
|
@ -930,6 +1028,61 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
|
|||
PUT_NUMBER8 (self->status);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
PUT_NUMBER8 (self->height);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
PUT_NUMBER8 (self->status);
|
||||
if (self->hash) {
|
||||
PUT_NUMBER4 (zchunk_size (self->hash));
|
||||
memcpy (self->needle,
|
||||
zchunk_data (self->hash),
|
||||
zchunk_size (self->hash));
|
||||
self->needle += zchunk_size (self->hash);
|
||||
}
|
||||
else
|
||||
PUT_NUMBER4 (0); // Empty chunk
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
PUT_NUMBER8 (self->reserve_size);
|
||||
if (self->address) {
|
||||
PUT_NUMBER4 (zchunk_size (self->address));
|
||||
memcpy (self->needle,
|
||||
zchunk_data (self->address),
|
||||
zchunk_size (self->address));
|
||||
self->needle += zchunk_size (self->address);
|
||||
}
|
||||
else
|
||||
PUT_NUMBER4 (0); // Empty chunk
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
PUT_NUMBER8 (self->status);
|
||||
PUT_NUMBER8 (self->reserved_offset);
|
||||
PUT_NUMBER8 (self->height);
|
||||
PUT_NUMBER8 (self->difficulty);
|
||||
if (self->prev_hash) {
|
||||
PUT_NUMBER4 (zchunk_size (self->prev_hash));
|
||||
memcpy (self->needle,
|
||||
zchunk_data (self->prev_hash),
|
||||
zchunk_size (self->prev_hash));
|
||||
self->needle += zchunk_size (self->prev_hash);
|
||||
}
|
||||
else
|
||||
PUT_NUMBER4 (0); // Empty chunk
|
||||
if (self->block_template_blob) {
|
||||
PUT_NUMBER4 (zchunk_size (self->block_template_blob));
|
||||
memcpy (self->needle,
|
||||
zchunk_data (self->block_template_blob),
|
||||
zchunk_size (self->block_template_blob));
|
||||
self->needle += zchunk_size (self->block_template_blob);
|
||||
}
|
||||
else
|
||||
PUT_NUMBER4 (0); // Empty chunk
|
||||
break;
|
||||
|
||||
case WAP_PROTO_ERROR:
|
||||
PUT_NUMBER2 (self->status);
|
||||
PUT_STRING (self->reason);
|
||||
|
@ -1210,6 +1363,33 @@ wap_proto_print (wap_proto_t *self)
|
|||
zsys_debug (" status=%ld", (long) self->status);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
zsys_debug ("WAP_PROTO_GET_BLOCK_HASH:");
|
||||
zsys_debug (" height=%ld", (long) self->height);
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
zsys_debug ("WAP_PROTO_GET_BLOCK_HASH_OK:");
|
||||
zsys_debug (" status=%ld", (long) self->status);
|
||||
zsys_debug (" hash=[ ... ]");
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
zsys_debug ("WAP_PROTO_GET_BLOCK_TEMPLATE:");
|
||||
zsys_debug (" reserve_size=%ld", (long) self->reserve_size);
|
||||
zsys_debug (" address=[ ... ]");
|
||||
break;
|
||||
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
zsys_debug ("WAP_PROTO_GET_BLOCK_TEMPLATE_OK:");
|
||||
zsys_debug (" status=%ld", (long) self->status);
|
||||
zsys_debug (" reserved_offset=%ld", (long) self->reserved_offset);
|
||||
zsys_debug (" height=%ld", (long) self->height);
|
||||
zsys_debug (" difficulty=%ld", (long) self->difficulty);
|
||||
zsys_debug (" prev_hash=[ ... ]");
|
||||
zsys_debug (" block_template_blob=[ ... ]");
|
||||
break;
|
||||
|
||||
case WAP_PROTO_STOP:
|
||||
zsys_debug ("WAP_PROTO_STOP:");
|
||||
break;
|
||||
|
@ -1383,6 +1563,18 @@ wap_proto_command (wap_proto_t *self)
|
|||
case WAP_PROTO_STOP_SAVE_GRAPH_OK:
|
||||
return ("STOP_SAVE_GRAPH_OK");
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH:
|
||||
return ("GET_BLOCK_HASH");
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_HASH_OK:
|
||||
return ("GET_BLOCK_HASH_OK");
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE:
|
||||
return ("GET_BLOCK_TEMPLATE");
|
||||
break;
|
||||
case WAP_PROTO_GET_BLOCK_TEMPLATE_OK:
|
||||
return ("GET_BLOCK_TEMPLATE_OK");
|
||||
break;
|
||||
case WAP_PROTO_STOP:
|
||||
return ("STOP");
|
||||
break;
|
||||
|
@ -2137,6 +2329,141 @@ wap_proto_set_level (wap_proto_t *self, byte level)
|
|||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get the hash field without transferring ownership
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_hash (wap_proto_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->hash;
|
||||
}
|
||||
|
||||
// Get the hash field and transfer ownership to caller
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_get_hash (wap_proto_t *self)
|
||||
{
|
||||
zchunk_t *hash = self->hash;
|
||||
self->hash = NULL;
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Set the hash field, transferring ownership from caller
|
||||
|
||||
void
|
||||
wap_proto_set_hash (wap_proto_t *self, zchunk_t **chunk_p)
|
||||
{
|
||||
assert (self);
|
||||
assert (chunk_p);
|
||||
zchunk_destroy (&self->hash);
|
||||
self->hash = *chunk_p;
|
||||
*chunk_p = NULL;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get/set the reserve_size field
|
||||
|
||||
uint64_t
|
||||
wap_proto_reserve_size (wap_proto_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->reserve_size;
|
||||
}
|
||||
|
||||
void
|
||||
wap_proto_set_reserve_size (wap_proto_t *self, uint64_t reserve_size)
|
||||
{
|
||||
assert (self);
|
||||
self->reserve_size = reserve_size;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get/set the reserved_offset field
|
||||
|
||||
uint64_t
|
||||
wap_proto_reserved_offset (wap_proto_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->reserved_offset;
|
||||
}
|
||||
|
||||
void
|
||||
wap_proto_set_reserved_offset (wap_proto_t *self, uint64_t reserved_offset)
|
||||
{
|
||||
assert (self);
|
||||
self->reserved_offset = reserved_offset;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get the prev_hash field without transferring ownership
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_prev_hash (wap_proto_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->prev_hash;
|
||||
}
|
||||
|
||||
// Get the prev_hash field and transfer ownership to caller
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_get_prev_hash (wap_proto_t *self)
|
||||
{
|
||||
zchunk_t *prev_hash = self->prev_hash;
|
||||
self->prev_hash = NULL;
|
||||
return prev_hash;
|
||||
}
|
||||
|
||||
// Set the prev_hash field, transferring ownership from caller
|
||||
|
||||
void
|
||||
wap_proto_set_prev_hash (wap_proto_t *self, zchunk_t **chunk_p)
|
||||
{
|
||||
assert (self);
|
||||
assert (chunk_p);
|
||||
zchunk_destroy (&self->prev_hash);
|
||||
self->prev_hash = *chunk_p;
|
||||
*chunk_p = NULL;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get the block_template_blob field without transferring ownership
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_block_template_blob (wap_proto_t *self)
|
||||
{
|
||||
assert (self);
|
||||
return self->block_template_blob;
|
||||
}
|
||||
|
||||
// Get the block_template_blob field and transfer ownership to caller
|
||||
|
||||
zchunk_t *
|
||||
wap_proto_get_block_template_blob (wap_proto_t *self)
|
||||
{
|
||||
zchunk_t *block_template_blob = self->block_template_blob;
|
||||
self->block_template_blob = NULL;
|
||||
return block_template_blob;
|
||||
}
|
||||
|
||||
// Set the block_template_blob field, transferring ownership from caller
|
||||
|
||||
void
|
||||
wap_proto_set_block_template_blob (wap_proto_t *self, zchunk_t **chunk_p)
|
||||
{
|
||||
assert (self);
|
||||
assert (chunk_p);
|
||||
zchunk_destroy (&self->block_template_blob);
|
||||
self->block_template_blob = *chunk_p;
|
||||
*chunk_p = NULL;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Get/set the reason field
|
||||
|
||||
|
@ -2646,6 +2973,76 @@ 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_BLOCK_HASH);
|
||||
|
||||
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_height (self) == 123);
|
||||
}
|
||||
wap_proto_set_id (self, WAP_PROTO_GET_BLOCK_HASH_OK);
|
||||
|
||||
wap_proto_set_status (self, 123);
|
||||
zchunk_t *get_block_hash_ok_hash = zchunk_new ("Captcha Diem", 12);
|
||||
wap_proto_set_hash (self, &get_block_hash_ok_hash);
|
||||
// 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 (memcmp (zchunk_data (wap_proto_hash (self)), "Captcha Diem", 12) == 0);
|
||||
zchunk_destroy (&get_block_hash_ok_hash);
|
||||
}
|
||||
wap_proto_set_id (self, WAP_PROTO_GET_BLOCK_TEMPLATE);
|
||||
|
||||
wap_proto_set_reserve_size (self, 123);
|
||||
zchunk_t *get_block_template_address = zchunk_new ("Captcha Diem", 12);
|
||||
wap_proto_set_address (self, &get_block_template_address);
|
||||
// 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_reserve_size (self) == 123);
|
||||
assert (memcmp (zchunk_data (wap_proto_address (self)), "Captcha Diem", 12) == 0);
|
||||
zchunk_destroy (&get_block_template_address);
|
||||
}
|
||||
wap_proto_set_id (self, WAP_PROTO_GET_BLOCK_TEMPLATE_OK);
|
||||
|
||||
wap_proto_set_status (self, 123);
|
||||
wap_proto_set_reserved_offset (self, 123);
|
||||
wap_proto_set_height (self, 123);
|
||||
wap_proto_set_difficulty (self, 123);
|
||||
zchunk_t *get_block_template_ok_prev_hash = zchunk_new ("Captcha Diem", 12);
|
||||
wap_proto_set_prev_hash (self, &get_block_template_ok_prev_hash);
|
||||
zchunk_t *get_block_template_ok_block_template_blob = zchunk_new ("Captcha Diem", 12);
|
||||
wap_proto_set_block_template_blob (self, &get_block_template_ok_block_template_blob);
|
||||
// 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_reserved_offset (self) == 123);
|
||||
assert (wap_proto_height (self) == 123);
|
||||
assert (wap_proto_difficulty (self) == 123);
|
||||
assert (memcmp (zchunk_data (wap_proto_prev_hash (self)), "Captcha Diem", 12) == 0);
|
||||
zchunk_destroy (&get_block_template_ok_prev_hash);
|
||||
assert (memcmp (zchunk_data (wap_proto_block_template_blob (self)), "Captcha Diem", 12) == 0);
|
||||
zchunk_destroy (&get_block_template_ok_block_template_blob);
|
||||
}
|
||||
wap_proto_set_id (self, WAP_PROTO_STOP);
|
||||
|
||||
// Send twice
|
||||
|
|
|
@ -362,3 +362,23 @@ stop_save_graph (client_t *self)
|
|||
{
|
||||
IPC::Daemon::stop_save_graph(self->message);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// get_block_hash
|
||||
//
|
||||
|
||||
static void
|
||||
get_block_hash (client_t *self)
|
||||
{
|
||||
IPC::Daemon::get_block_hash(self->message);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// get_block_template
|
||||
//
|
||||
|
||||
static void
|
||||
get_block_template (client_t *self)
|
||||
{
|
||||
IPC::Daemon::get_block_template(self->message);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
// Trivial and error responses may be returned with ns_create_rpc_reply and ns_create_rpc_error
|
||||
// respectively.
|
||||
|
||||
// TODO: Add core busy checks to all methods here
|
||||
|
||||
#include "daemon_deprecated_rpc.h"
|
||||
#include <stdexcept>
|
||||
|
||||
|
@ -26,6 +28,7 @@
|
|||
*/
|
||||
namespace
|
||||
{
|
||||
// TODO: put right error codes here
|
||||
int daemon_connection_error = -326701;
|
||||
int parse_error = -32700;
|
||||
int invalid_request = -32600;
|
||||
|
@ -43,26 +46,21 @@ namespace
|
|||
return ipc_client && wap_client_connected(ipc_client);
|
||||
}
|
||||
|
||||
void connect_to_daemon() {
|
||||
bool connect_to_daemon() {
|
||||
if (check_connection_to_daemon()) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
ipc_client = wap_client_new();
|
||||
wap_client_connect(ipc_client, "ipc://@/monero", 200, "wallet identity");
|
||||
return check_connection_to_daemon();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a response string given a result JSON object.
|
||||
*
|
||||
* It also adds boilerplate properties like id, method.
|
||||
* \brief Initializes a rapidjson response object
|
||||
* \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.
|
||||
* \param response_json net_skeleton request object to fill
|
||||
*/
|
||||
void construct_response_string(struct ns_rpc_request *req, rapidjson::Value &result_json,
|
||||
rapidjson::Document &response_json, std::string &response)
|
||||
{
|
||||
void init_response_object(struct ns_rpc_request *req, rapidjson::Document &response_json) {
|
||||
response_json.SetObject();
|
||||
response_json.AddMember("jsonrpc", "2.0" , response_json.GetAllocator());
|
||||
rapidjson::Value string_value(rapidjson::kStringType);
|
||||
|
@ -78,6 +76,21 @@ namespace
|
|||
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());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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)
|
||||
{
|
||||
init_response_object(req, response_json);
|
||||
response_json.AddMember("result", result_json, response_json.GetAllocator());
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
@ -85,6 +98,30 @@ namespace
|
|||
// Write string to `response`.
|
||||
response = buffer.GetString();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a response string given a result string.
|
||||
*
|
||||
* It also adds boilerplate properties like id, method.
|
||||
* \param req net_skeleton request object
|
||||
* \param result 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, const std::string &result,
|
||||
rapidjson::Document &response_json, std::string &response)
|
||||
{
|
||||
init_response_object(req, response_json);
|
||||
rapidjson::Value string_value(rapidjson::kStringType);
|
||||
string_value.SetString(result.c_str(), result.length());
|
||||
response_json.AddMember("result", string_value, response_json.GetAllocator());
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> 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.
|
||||
|
@ -94,12 +131,20 @@ namespace
|
|||
*/
|
||||
int getheight(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't 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 status = wap_client_status(ipc_client);
|
||||
if (status == IPC::STATUS_CORE_BUSY) {
|
||||
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||
"Core busy.", "{}");
|
||||
}
|
||||
uint64_t height = wap_client_height(ipc_client);
|
||||
rapidjson::Document response_json;
|
||||
rapidjson::Value result_json;
|
||||
|
@ -122,7 +167,10 @@ namespace
|
|||
*/
|
||||
int startmining(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
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,
|
||||
|
@ -160,7 +208,10 @@ namespace
|
|||
"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_WRONG_ADDRESS)
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
|
@ -183,12 +234,20 @@ namespace
|
|||
*/
|
||||
int stopmining(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't 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.", "{}");
|
||||
}
|
||||
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 (wap_client_status(ipc_client) != IPC::STATUS_OK)
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_request,
|
||||
|
@ -206,13 +265,21 @@ namespace
|
|||
*/
|
||||
int getinfo(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't 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)
|
||||
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_OK)
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_request,
|
||||
"Failed to get info", "{}");
|
||||
|
@ -257,7 +324,10 @@ namespace
|
|||
*/
|
||||
int getpeerlist(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
int rc = wap_client_get_peer_list(ipc_client);
|
||||
if (rc < 0) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
|
@ -309,13 +379,20 @@ namespace
|
|||
*/
|
||||
int getminingstatus(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
int rc = wap_client_get_mining_status(ipc_client);
|
||||
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.", "{}");
|
||||
}
|
||||
rapidjson::Document response_json;
|
||||
rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator();
|
||||
rapidjson::Value result_json;
|
||||
|
@ -346,7 +423,10 @@ namespace
|
|||
*/
|
||||
int setloghashrate(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
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,
|
||||
|
@ -376,8 +456,12 @@ namespace
|
|||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
|
||||
if (wap_client_status(ipc_client) == IPC::STATUS_NOT_MINING) {
|
||||
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_NOT_MINING) {
|
||||
return ns_rpc_create_error(buf, len, req, not_mining_error,
|
||||
"Not mining", "{}");
|
||||
}
|
||||
|
@ -394,7 +478,10 @@ namespace
|
|||
*/
|
||||
int setloglevel(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
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,
|
||||
|
@ -423,8 +510,12 @@ namespace
|
|||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
|
||||
if (wap_client_status(ipc_client) == IPC::STATUS_INVALID_LOG_LEVEL) {
|
||||
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_INVALID_LOG_LEVEL) {
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Invalid log level", "{}");
|
||||
}
|
||||
|
@ -441,12 +532,20 @@ namespace
|
|||
*/
|
||||
int getblockcount(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't 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 status = wap_client_status(ipc_client);
|
||||
if (status == IPC::STATUS_CORE_BUSY) {
|
||||
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||
"Core busy.", "{}");
|
||||
}
|
||||
uint64_t count = wap_client_height(ipc_client);
|
||||
rapidjson::Document response_json;
|
||||
rapidjson::Value result_json;
|
||||
|
@ -469,7 +568,10 @@ namespace
|
|||
*/
|
||||
int startsavegraph(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
int rc = wap_client_start_save_graph(ipc_client);
|
||||
if (rc < 0) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
|
@ -487,7 +589,10 @@ namespace
|
|||
*/
|
||||
int stopsavegraph(char *buf, int len, struct ns_rpc_request *req)
|
||||
{
|
||||
connect_to_daemon();
|
||||
if (!connect_to_daemon()) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
"Couldn't connect to daemon.", "{}");
|
||||
}
|
||||
int rc = wap_client_stop_save_graph(ipc_client);
|
||||
if (rc < 0) {
|
||||
return ns_rpc_create_error(buf, len, req, daemon_connection_error,
|
||||
|
@ -495,6 +600,152 @@ namespace
|
|||
}
|
||||
return ns_rpc_create_reply(buf, len, req, "{s:s}", "status", STATUS_OK);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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)
|
||||
{
|
||||
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.IsArray() || request_json.Size() < 1 || !request_json[(unsigned int)0].IsNumber())
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Incorrect 'height' field", "{}");
|
||||
}
|
||||
|
||||
|
||||
int height = request_json[(unsigned int)0].GetUint();
|
||||
int rc = wap_client_get_block_hash(ipc_client, height);
|
||||
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_HEIGHT_TOO_BIG) {
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Height too big.", "{}");
|
||||
}
|
||||
zchunk_t *hash_chunk = wap_client_hash(ipc_client);
|
||||
std::string hash((char*)zchunk_data(hash_chunk), zchunk_size(hash_chunk));
|
||||
std::string response;
|
||||
rapidjson::Document response_json;
|
||||
construct_response_string(req, hash, 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)
|
||||
{
|
||||
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("reserve_size") || !request_json["reserve_size"].IsNumber())
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Incorrect 'reserve_size' field", "{}");
|
||||
}
|
||||
if (!request_json.HasMember("wallet_address") || !request_json["wallet_address"].IsString())
|
||||
{
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Incorrect 'wallet_address' field", "{}");
|
||||
}
|
||||
|
||||
uint64_t reserve_size = request_json["reserve_size"].GetUint();
|
||||
std::string wallet_address = request_json["wallet_address"].GetString();
|
||||
zchunk_t *address_chunk = zchunk_new((void*)wallet_address.c_str(), wallet_address.length());
|
||||
int rc = wap_client_get_block_template(ipc_client, reserve_size, &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_CORE_BUSY) {
|
||||
return ns_rpc_create_error(buf, len, req, internal_error,
|
||||
"Core busy.", "{}");
|
||||
}
|
||||
if (status == IPC::STATUS_RESERVE_SIZE_TOO_BIG) {
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Reserve size too big.", "{}");
|
||||
}
|
||||
if (status == IPC::STATUS_WRONG_ADDRESS) {
|
||||
return ns_rpc_create_error(buf, len, req, invalid_params,
|
||||
"Wrong address.", "{}");
|
||||
}
|
||||
|
||||
rapidjson::Document response_json;
|
||||
rapidjson::Document::AllocatorType &allocator = response_json.GetAllocator();
|
||||
rapidjson::Value result_json;
|
||||
result_json.SetObject();
|
||||
result_json.AddMember("difficulty", wap_client_difficulty(ipc_client), allocator);
|
||||
result_json.AddMember("height", wap_client_height(ipc_client), allocator);
|
||||
result_json.AddMember("reserved_offset", wap_client_reserved_offset(ipc_client), allocator);
|
||||
zchunk_t *prev_hash_chunk = wap_client_prev_hash(ipc_client);
|
||||
rapidjson::Value string_value(rapidjson::kStringType);
|
||||
string_value.SetString((char*)zchunk_data(prev_hash_chunk), zchunk_size(prev_hash_chunk));
|
||||
result_json.AddMember("prev_hash", string_value, allocator);
|
||||
zchunk_t *block_template_chunk = wap_client_prev_hash(ipc_client);
|
||||
string_value.SetString((char*)zchunk_data(block_template_chunk), zchunk_size(block_template_chunk));
|
||||
result_json.AddMember("blocktemplate_blob", string_value, 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.
|
||||
const char *method_names[] = {
|
||||
"getheight",
|
||||
|
@ -508,6 +759,8 @@ namespace
|
|||
"getblockcount",
|
||||
"startsavegraph",
|
||||
"stopsavegraph",
|
||||
"getblockhash",
|
||||
"getblocktemplate",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -524,6 +777,8 @@ namespace
|
|||
getblockcount,
|
||||
startsavegraph,
|
||||
stopsavegraph,
|
||||
getblockhash,
|
||||
getblocktemplate,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue