Wallet seems functional with new IPC

This commit is contained in:
Oran Juice 2015-04-11 23:53:57 +05:30
parent 87a9de9168
commit f5191af24b
No known key found for this signature in database
GPG Key ID: 71C5AF46CCB28124
8 changed files with 113 additions and 79 deletions

View File

@ -216,10 +216,11 @@ namespace IPC
wap_proto_set_status(message, STATUS_CORE_BUSY); wap_proto_set_status(message, STATUS_CORE_BUSY);
return; return;
} }
const char *tx_id = wap_proto_tx_id(message); zchunk_t *tx_id = wap_proto_tx_id(message);
crypto::hash hash; crypto::hash hash;
memcpy(hash.data, tx_id + 1, crypto::HASH_SIZE); memcpy(hash.data, zchunk_data(tx_id), crypto::HASH_SIZE);
std::vector<uint64_t> output_indexes; std::vector<uint64_t> output_indexes;
bool r = core->get_tx_outputs_gindexs(hash, output_indexes); bool r = core->get_tx_outputs_gindexs(hash, output_indexes);
if (!r) if (!r)
{ {
@ -249,6 +250,7 @@ namespace IPC
for (unsigned int i = 0; i < amounts_count; i++) { for (unsigned int i = 0; i < amounts_count; i++) {
req.amounts.push_back(amounts[i]); req.amounts.push_back(amounts[i]);
} }
cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response res; cryptonote::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response res;
if (!core->get_random_outs_for_amounts(req, res)) if (!core->get_random_outs_for_amounts(req, res))
{ {
@ -287,8 +289,6 @@ namespace IPC
result_json.Accept(writer); result_json.Accept(writer);
std::string block_string = buffer.GetString(); std::string block_string = buffer.GetString();
std::cout << block_string << std::endl;
zframe_t *frame = zframe_new(block_string.c_str(), block_string.length()); zframe_t *frame = zframe_new(block_string.c_str(), block_string.length());
wap_proto_set_random_outputs(message, &frame); wap_proto_set_random_outputs(message, &frame);

View File

@ -80,7 +80,7 @@ WAP_EXPORT int
// Request a set of blocks from the server. // Request a set of blocks from the server.
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.
WAP_EXPORT int WAP_EXPORT int
wap_client_get (wap_client_t *self, const char *tx_id); wap_client_get (wap_client_t *self, zchunk_t **tx_id_p);
// Request a set of blocks from the server. // Request a set of blocks from the server.
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.
@ -90,7 +90,7 @@ WAP_EXPORT int
// Ask for tx output indexes. // Ask for tx output indexes.
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.
WAP_EXPORT int WAP_EXPORT int
wap_client_output_indexes (wap_client_t *self, const char *tx_id); wap_client_output_indexes (wap_client_t *self, zchunk_t **tx_id_p);
// Ask for tx output indexes. // Ask for tx output indexes.
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.

View File

@ -136,7 +136,7 @@ struct _client_args_t {
zlist_t *block_ids; zlist_t *block_ids;
uint64_t start_height; uint64_t start_height;
zchunk_t *tx_as_hex; zchunk_t *tx_as_hex;
char *tx_id; zchunk_t *tx_id;
uint64_t outs_count; uint64_t outs_count;
zframe_t *amounts; zframe_t *amounts;
char *address; char *address;
@ -281,7 +281,7 @@ s_client_destroy (s_client_t **self_p)
zstr_free (&self->args.identity); zstr_free (&self->args.identity);
zlist_destroy (&self->args.block_ids); zlist_destroy (&self->args.block_ids);
zchunk_destroy (&self->args.tx_as_hex); zchunk_destroy (&self->args.tx_as_hex);
zstr_free (&self->args.tx_id); zchunk_destroy (&self->args.tx_id);
zframe_destroy (&self->args.amounts); zframe_destroy (&self->args.amounts);
zstr_free (&self->args.address); zstr_free (&self->args.address);
client_terminate (&self->client); client_terminate (&self->client);
@ -1450,8 +1450,8 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument)
} }
else else
if (streq (method, "GET")) { if (streq (method, "GET")) {
zstr_free (&self->args.tx_id); zchunk_destroy (&self->args.tx_id);
zsock_recv (self->cmdpipe, "s", &self->args.tx_id); zsock_recv (self->cmdpipe, "p", &self->args.tx_id);
s_client_execute (self, get_event); s_client_execute (self, get_event);
} }
else else
@ -1460,8 +1460,8 @@ s_client_handle_cmdpipe (zloop_t *loop, zsock_t *reader, void *argument)
} }
else else
if (streq (method, "OUTPUT INDEXES")) { if (streq (method, "OUTPUT INDEXES")) {
zstr_free (&self->args.tx_id); zchunk_destroy (&self->args.tx_id);
zsock_recv (self->cmdpipe, "s", &self->args.tx_id); zsock_recv (self->cmdpipe, "p", &self->args.tx_id);
s_client_execute (self, output_indexes_event); s_client_execute (self, output_indexes_event);
} }
else else
@ -1855,11 +1855,12 @@ wap_client_put (wap_client_t *self, zchunk_t **tx_as_hex_p)
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.
int int
wap_client_get (wap_client_t *self, const char *tx_id) wap_client_get (wap_client_t *self, zchunk_t **tx_id_p)
{ {
assert (self); assert (self);
zsock_send (self->actor, "ss", "GET", tx_id); zsock_send (self->actor, "sp", "GET", *tx_id_p);
*tx_id_p = NULL; // Take ownership of tx_id
if (s_accept_reply (self, "GET OK", "FAILURE", NULL)) if (s_accept_reply (self, "GET OK", "FAILURE", NULL))
return -1; // Interrupted or timed-out return -1; // Interrupted or timed-out
return self->status; return self->status;
@ -1887,11 +1888,12 @@ wap_client_save (wap_client_t *self)
// Returns >= 0 if successful, -1 if interrupted. // Returns >= 0 if successful, -1 if interrupted.
int int
wap_client_output_indexes (wap_client_t *self, const char *tx_id) wap_client_output_indexes (wap_client_t *self, zchunk_t **tx_id_p)
{ {
assert (self); assert (self);
zsock_send (self->actor, "ss", "OUTPUT INDEXES", tx_id); zsock_send (self->actor, "sp", "OUTPUT INDEXES", *tx_id_p);
*tx_id_p = NULL; // Take ownership of tx_id
if (s_accept_reply (self, "OUTPUT INDEXES OK", "FAILURE", NULL)) if (s_accept_reply (self, "OUTPUT INDEXES OK", "FAILURE", NULL))
return -1; // Interrupted or timed-out return -1; // Interrupted or timed-out
return self->status; return self->status;

View File

@ -49,7 +49,7 @@ PUT-OK, or ERROR.
status number 8 Transaction ID status number 8 Transaction ID
OUTPUT_INDEXES - Ask for tx output indexes. OUTPUT_INDEXES - Ask for tx output indexes.
tx_id string Transaction ID tx_id chunk Transaction ID
OUTPUT_INDEXES_OK - Daemon returns tx output indexes. OUTPUT_INDEXES_OK - Daemon returns tx output indexes.
status number 8 Status status number 8 Status
@ -65,7 +65,7 @@ PUT-OK, or ERROR.
GET - Wallet requests transaction data from the daemon. Daemon replies GET - Wallet requests transaction data from the daemon. Daemon replies
with GET-OK, or ERROR. with GET-OK, or ERROR.
tx_id string Transaction ID tx_id chunk Transaction ID
GET_OK - Daemon replies with transaction data. GET_OK - Daemon replies with transaction data.
tx_data chunk Transaction data tx_data chunk Transaction data
@ -239,11 +239,15 @@ zchunk_t *
void void
wap_proto_set_tx_as_hex (wap_proto_t *self, zchunk_t **chunk_p); wap_proto_set_tx_as_hex (wap_proto_t *self, zchunk_t **chunk_p);
// Get/set the tx_id field // Get a copy of the tx_id field
const char * zchunk_t *
wap_proto_tx_id (wap_proto_t *self); wap_proto_tx_id (wap_proto_t *self);
// Get the tx_id field and transfer ownership to caller
zchunk_t *
wap_proto_get_tx_id (wap_proto_t *self);
// Set the tx_id field, transferring ownership from caller
void void
wap_proto_set_tx_id (wap_proto_t *self, const char *value); wap_proto_set_tx_id (wap_proto_t *self, zchunk_t **chunk_p);
// Get a copy of the o_indexes field // Get a copy of the o_indexes field
zframe_t * zframe_t *

View File

@ -155,7 +155,7 @@ prepare_blocks_command (client_t *self)
static void static void
prepare_get_output_indexes_command (client_t *self) prepare_get_output_indexes_command (client_t *self)
{ {
wap_proto_set_tx_id (self->message, self->args->tx_id); wap_proto_set_tx_id (self->message, &self->args->tx_id);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -213,7 +213,7 @@ signal_have_put_ok (client_t *self)
static void static void
prepare_get_command (client_t *self) prepare_get_command (client_t *self)
{ {
wap_proto_set_tx_id (self->message, self->args->tx_id); wap_proto_set_tx_id (self->message, &self->args->tx_id);
} }
@ -359,6 +359,7 @@ signal_server_not_present (client_t *self)
static void static void
prepare_get_random_outs_command (client_t *self) 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); wap_proto_set_amounts (self->message, &self->args->amounts);
} }

View File

@ -49,7 +49,7 @@ struct _wap_proto_t {
// Transaction as hex // Transaction as hex
zchunk_t *tx_as_hex; zchunk_t *tx_as_hex;
// Transaction ID // Transaction ID
char tx_id [256]; zchunk_t *tx_id;
// Output Indexes // Output Indexes
zframe_t *o_indexes; zframe_t *o_indexes;
// Outs count // Outs count
@ -245,6 +245,7 @@ wap_proto_destroy (wap_proto_t **self_p)
zlist_destroy (&self->block_ids); zlist_destroy (&self->block_ids);
zmsg_destroy (&self->block_data); zmsg_destroy (&self->block_data);
zchunk_destroy (&self->tx_as_hex); zchunk_destroy (&self->tx_as_hex);
zchunk_destroy (&self->tx_id);
zframe_destroy (&self->o_indexes); zframe_destroy (&self->o_indexes);
zframe_destroy (&self->amounts); zframe_destroy (&self->amounts);
zframe_destroy (&self->random_outputs); zframe_destroy (&self->random_outputs);
@ -367,7 +368,17 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input)
break; break;
case WAP_PROTO_OUTPUT_INDEXES: case WAP_PROTO_OUTPUT_INDEXES:
GET_STRING (self->tx_id); {
size_t chunk_size;
GET_NUMBER4 (chunk_size);
if (self->needle + chunk_size > (self->ceiling)) {
zsys_warning ("wap_proto: tx_id is missing data");
goto malformed;
}
zchunk_destroy (&self->tx_id);
self->tx_id = zchunk_new (self->needle, chunk_size);
self->needle += chunk_size;
}
break; break;
case WAP_PROTO_OUTPUT_INDEXES_OK: case WAP_PROTO_OUTPUT_INDEXES_OK:
@ -404,7 +415,17 @@ wap_proto_recv (wap_proto_t *self, zsock_t *input)
break; break;
case WAP_PROTO_GET: case WAP_PROTO_GET:
GET_STRING (self->tx_id); {
size_t chunk_size;
GET_NUMBER4 (chunk_size);
if (self->needle + chunk_size > (self->ceiling)) {
zsys_warning ("wap_proto: tx_id is missing data");
goto malformed;
}
zchunk_destroy (&self->tx_id);
self->tx_id = zchunk_new (self->needle, chunk_size);
self->needle += chunk_size;
}
break; break;
case WAP_PROTO_GET_OK: case WAP_PROTO_GET_OK:
@ -520,7 +541,9 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
frame_size += 8; // status frame_size += 8; // status
break; break;
case WAP_PROTO_OUTPUT_INDEXES: case WAP_PROTO_OUTPUT_INDEXES:
frame_size += 1 + strlen (self->tx_id); frame_size += 4; // Size is 4 octets
if (self->tx_id)
frame_size += zchunk_size (self->tx_id);
break; break;
case WAP_PROTO_OUTPUT_INDEXES_OK: case WAP_PROTO_OUTPUT_INDEXES_OK:
frame_size += 8; // status frame_size += 8; // status
@ -532,7 +555,9 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
frame_size += 8; // status frame_size += 8; // status
break; break;
case WAP_PROTO_GET: case WAP_PROTO_GET:
frame_size += 1 + strlen (self->tx_id); frame_size += 4; // Size is 4 octets
if (self->tx_id)
frame_size += zchunk_size (self->tx_id);
break; break;
case WAP_PROTO_GET_OK: case WAP_PROTO_GET_OK:
frame_size += 4; // Size is 4 octets frame_size += 4; // Size is 4 octets
@ -606,7 +631,15 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
break; break;
case WAP_PROTO_OUTPUT_INDEXES: case WAP_PROTO_OUTPUT_INDEXES:
PUT_STRING (self->tx_id); if (self->tx_id) {
PUT_NUMBER4 (zchunk_size (self->tx_id));
memcpy (self->needle,
zchunk_data (self->tx_id),
zchunk_size (self->tx_id));
self->needle += zchunk_size (self->tx_id);
}
else
PUT_NUMBER4 (0); // Empty chunk
break; break;
case WAP_PROTO_OUTPUT_INDEXES_OK: case WAP_PROTO_OUTPUT_INDEXES_OK:
@ -625,7 +658,15 @@ wap_proto_send (wap_proto_t *self, zsock_t *output)
break; break;
case WAP_PROTO_GET: case WAP_PROTO_GET:
PUT_STRING (self->tx_id); if (self->tx_id) {
PUT_NUMBER4 (zchunk_size (self->tx_id));
memcpy (self->needle,
zchunk_data (self->tx_id),
zchunk_size (self->tx_id));
self->needle += zchunk_size (self->tx_id);
}
else
PUT_NUMBER4 (0); // Empty chunk
break; break;
case WAP_PROTO_GET_OK: case WAP_PROTO_GET_OK:
@ -757,10 +798,7 @@ wap_proto_print (wap_proto_t *self)
case WAP_PROTO_OUTPUT_INDEXES: case WAP_PROTO_OUTPUT_INDEXES:
zsys_debug ("WAP_PROTO_OUTPUT_INDEXES:"); zsys_debug ("WAP_PROTO_OUTPUT_INDEXES:");
if (self->tx_id) zsys_debug (" tx_id=[ ... ]");
zsys_debug (" tx_id='%s'", self->tx_id);
else
zsys_debug (" tx_id=");
break; break;
case WAP_PROTO_OUTPUT_INDEXES_OK: case WAP_PROTO_OUTPUT_INDEXES_OK:
@ -795,10 +833,7 @@ wap_proto_print (wap_proto_t *self)
case WAP_PROTO_GET: case WAP_PROTO_GET:
zsys_debug ("WAP_PROTO_GET:"); zsys_debug ("WAP_PROTO_GET:");
if (self->tx_id) zsys_debug (" tx_id=[ ... ]");
zsys_debug (" tx_id='%s'", self->tx_id);
else
zsys_debug (" tx_id=");
break; break;
case WAP_PROTO_GET_OK: case WAP_PROTO_GET_OK:
@ -1159,24 +1194,35 @@ wap_proto_set_tx_as_hex (wap_proto_t *self, zchunk_t **chunk_p)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Get/set the tx_id field // Get the tx_id field without transferring ownership
const char * zchunk_t *
wap_proto_tx_id (wap_proto_t *self) wap_proto_tx_id (wap_proto_t *self)
{ {
assert (self); assert (self);
return self->tx_id; return self->tx_id;
} }
// Get the tx_id field and transfer ownership to caller
zchunk_t *
wap_proto_get_tx_id (wap_proto_t *self)
{
zchunk_t *tx_id = self->tx_id;
self->tx_id = NULL;
return tx_id;
}
// Set the tx_id field, transferring ownership from caller
void void
wap_proto_set_tx_id (wap_proto_t *self, const char *value) wap_proto_set_tx_id (wap_proto_t *self, zchunk_t **chunk_p)
{ {
assert (self); assert (self);
assert (value); assert (chunk_p);
if (value == self->tx_id) zchunk_destroy (&self->tx_id);
return; self->tx_id = *chunk_p;
strncpy (self->tx_id, value, 255); *chunk_p = NULL;
self->tx_id [255] = 0;
} }
@ -1521,7 +1567,8 @@ wap_proto_test (bool verbose)
} }
wap_proto_set_id (self, WAP_PROTO_OUTPUT_INDEXES); wap_proto_set_id (self, WAP_PROTO_OUTPUT_INDEXES);
wap_proto_set_tx_id (self, "Life is short but Now lasts for ever"); zchunk_t *output_indexes_tx_id = zchunk_new ("Captcha Diem", 12);
wap_proto_set_tx_id (self, &output_indexes_tx_id);
// Send twice // Send twice
wap_proto_send (self, output); wap_proto_send (self, output);
wap_proto_send (self, output); wap_proto_send (self, output);
@ -1529,7 +1576,8 @@ wap_proto_test (bool verbose)
for (instance = 0; instance < 2; instance++) { for (instance = 0; instance < 2; instance++) {
wap_proto_recv (self, input); wap_proto_recv (self, input);
assert (wap_proto_routing_id (self)); assert (wap_proto_routing_id (self));
assert (streq (wap_proto_tx_id (self), "Life is short but Now lasts for ever")); assert (memcmp (zchunk_data (wap_proto_tx_id (self)), "Captcha Diem", 12) == 0);
zchunk_destroy (&output_indexes_tx_id);
} }
wap_proto_set_id (self, WAP_PROTO_OUTPUT_INDEXES_OK); wap_proto_set_id (self, WAP_PROTO_OUTPUT_INDEXES_OK);
@ -1581,7 +1629,8 @@ wap_proto_test (bool verbose)
} }
wap_proto_set_id (self, WAP_PROTO_GET); wap_proto_set_id (self, WAP_PROTO_GET);
wap_proto_set_tx_id (self, "Life is short but Now lasts for ever"); zchunk_t *get_tx_id = zchunk_new ("Captcha Diem", 12);
wap_proto_set_tx_id (self, &get_tx_id);
// Send twice // Send twice
wap_proto_send (self, output); wap_proto_send (self, output);
wap_proto_send (self, output); wap_proto_send (self, output);
@ -1589,7 +1638,8 @@ wap_proto_test (bool verbose)
for (instance = 0; instance < 2; instance++) { for (instance = 0; instance < 2; instance++) {
wap_proto_recv (self, input); wap_proto_recv (self, input);
assert (wap_proto_routing_id (self)); assert (wap_proto_routing_id (self));
assert (streq (wap_proto_tx_id (self), "Life is short but Now lasts for ever")); assert (memcmp (zchunk_data (wap_proto_tx_id (self)), "Captcha Diem", 12) == 0);
zchunk_destroy (&get_tx_id);
} }
wap_proto_set_id (self, WAP_PROTO_GET_OK); wap_proto_set_id (self, WAP_PROTO_GET_OK);

View File

@ -185,11 +185,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_
"transactions outputs size=" + std::to_string(tx.vout.size()) + "transactions outputs size=" + std::to_string(tx.vout.size()) +
" not match with COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES response size=" + std::to_string(res.o_indexes.size()));*/ " not match with COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES response size=" + std::to_string(res.o_indexes.size()));*/
char *size_prepended_tx_id = new char[crypto::HASH_SIZE + 1]; zchunk_t *tx_id_chunk = zchunk_new(tx_id.data, crypto::HASH_SIZE);
size_prepended_tx_id[0] = crypto::HASH_SIZE; int rc = wap_client_output_indexes(ipc_client, &tx_id_chunk);
memcpy(size_prepended_tx_id + 1, tx_id.data, crypto::HASH_SIZE);
int rc = wap_client_output_indexes(ipc_client, size_prepended_tx_id);
delete size_prepended_tx_id;
THROW_WALLET_EXCEPTION_IF(rc < 0, error::no_connection_to_daemon, "get_output_indexes"); THROW_WALLET_EXCEPTION_IF(rc < 0, error::no_connection_to_daemon, "get_output_indexes");
uint64_t status = wap_client_status(ipc_client); uint64_t status = wap_client_status(ipc_client);
THROW_WALLET_EXCEPTION_IF(status == IPC::STATUS_CORE_BUSY, error::daemon_busy, "get_output_indexes"); THROW_WALLET_EXCEPTION_IF(status == IPC::STATUS_CORE_BUSY, error::daemon_busy, "get_output_indexes");
@ -1178,7 +1176,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto
// failsafe split attempt counter // failsafe split attempt counter
size_t attempt_count = 0; size_t attempt_count = 0;
std::cout << "a\n";
for(attempt_count = 1; ;attempt_count++) for(attempt_count = 1; ;attempt_count++)
{ {
auto split_values = split_amounts(dsts, attempt_count); auto split_values = split_amounts(dsts, attempt_count);
@ -1198,14 +1195,11 @@ std::cout << "a\n";
cryptonote::transaction tx; cryptonote::transaction tx;
pending_tx ptx; pending_tx ptx;
std::cout << "b\n";
// loop until fee is met without increasing tx size to next KB boundary. // loop until fee is met without increasing tx size to next KB boundary.
uint64_t needed_fee = 0; uint64_t needed_fee = 0;
do do
{ {
std::cout << "c\n";
transfer(dst_vector, fake_outs_count, unlock_time, needed_fee, extra, tx, ptx); transfer(dst_vector, fake_outs_count, unlock_time, needed_fee, extra, tx, ptx);
std::cout << "d\n";
auto txBlob = t_serializable_object_to_blob(ptx.tx); auto txBlob = t_serializable_object_to_blob(ptx.tx);
uint64_t txSize = txBlob.size(); uint64_t txSize = txBlob.size();
uint64_t numKB = txSize / 1024; uint64_t numKB = txSize / 1024;

View File

@ -90,21 +90,6 @@ namespace tools
std::cout << "Couldn't connect to daemon\n\n"; std::cout << "Couldn't connect to daemon\n\n";
// TODO: Daemon not up. // TODO: Daemon not up.
} }
/*zlist_t *list = zlist_new();
char cheese[32];
const char *foo = "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148";
for (int i = 0; i < 63; i += 2) {
std::string x = "";
x += foo[i];
x += foo[i + 1];
cheese[i / 2] = (char)stoi(x, NULL, 16);
}
zlist_append(list, cheese);
uint64_t start_height = 1;
int rc = wap_client_blocks(client, &list, start_height);
// int rc = wap_client_start(client, 25);
// std::cout << "\n\n Response: " << (int)wap_client_curr_height(client) << std::endl;
assert (rc == 0);*/
}; };
struct transfer_details struct transfer_details
{ {
@ -505,16 +490,14 @@ namespace tools
zframe_t *outputs_frame = wap_client_random_outputs(ipc_client); zframe_t *outputs_frame = wap_client_random_outputs(ipc_client);
uint64_t frame_size = zframe_size(outputs_frame); uint64_t frame_size = zframe_size(outputs_frame);
char *frame_data = reinterpret_cast<char*>(zframe_data(outputs_frame)); char *frame_data = reinterpret_cast<char*>(zframe_data(outputs_frame));
std::string tmp(frame_data, frame_size);
std::cout << tmp << std::endl;
rapidjson::Document json; rapidjson::Document json;
THROW_WALLET_EXCEPTION_IF(json.Parse(frame_data, frame_size).HasParseError(), error::get_random_outs_error, "Couldn't JSON parse random outputs."); THROW_WALLET_EXCEPTION_IF(json.Parse(frame_data, frame_size).HasParseError(), error::get_random_outs_error, "Couldn't JSON parse random outputs.");
for (rapidjson::SizeType i = 0; i < json["outputs"].Size(); i++) { for (rapidjson::SizeType i = 0; i < json["outputs"].Size(); i++) {
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount output; COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount output;
output.amount = json["outputs"][i]["amount"].GetInt(); output.amount = json["outputs"][i]["amount"].GetInt64();
for (rapidjson::SizeType j = 0; j < json["outputs"][i]["outs"].Size(); j++) { for (rapidjson::SizeType j = 0; j < json["outputs"][i]["outs"].Size(); j++) {
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry entry; COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry entry;
entry.global_amount_index = json["outputs"][i]["outs"][j]["global_amount_index"].GetInt(); entry.global_amount_index = json["outputs"][i]["outs"][j]["global_amount_index"].GetInt64();
std::string out_key(json["outputs"][i]["outs"][j]["out_key"].GetString(), json["outputs"][i]["outs"][j]["out_key"].GetStringLength()); std::string out_key(json["outputs"][i]["outs"][j]["out_key"].GetString(), json["outputs"][i]["outs"][j]["out_key"].GetStringLength());
memcpy(entry.out_key.data, out_key.c_str(), 32); memcpy(entry.out_key.data, out_key.c_str(), 32);
output.outs.push_back(entry); output.outs.push_back(entry);