Skip to content

Commit

Permalink
Add RPC call for getting snode register command
Browse files Browse the repository at this point in the history
  • Loading branch information
Doy-lee authored and jcktm committed Aug 3, 2018
1 parent bffd7c2 commit 5435e33
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 149 deletions.
40 changes: 5 additions & 35 deletions src/cryptonote_core/cryptonote_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1739,47 +1739,17 @@ namespace cryptonote
return m_service_node;
}
//-----------------------------------------------------------------------------------------------
std::string core::prepare_registration(const std::vector<std::string>& args)
{
std::vector<cryptonote::account_public_address> addresses;
std::vector<uint32_t> portions;
bool r = service_nodes::convert_registration_args(m_nettype, args, addresses, portions);
CHECK_AND_ASSERT_MES(r, "", tr("Failed to convert registration args"));
assert(addresses.size() == portions.size());
uint64_t exp_timestamp = time(nullptr) + STAKING_AUTHORIZATION_EXPIRATION_WINDOW;
crypto::hash hash;
r = cryptonote::get_registration_hash(addresses, portions, exp_timestamp, hash);
CHECK_AND_ASSERT_MES(r, "", tr("Failed to get the registration hash"));
crypto::signature signature;
crypto::generate_signature(hash, m_service_node_pubkey, m_service_node_key, signature);
std::stringstream ss;
ss << tr("Run this command in the wallet that will fund this registration:\n\n");
ss << "register_service_node ";
ss << std::setprecision(17);
for (size_t i = 0; i < addresses.size(); i++)
ss << get_account_address_as_str(m_nettype, false, addresses[i]) << " " << (portions[i]/(double)STAKING_PORTIONS) << " ";
ss << exp_timestamp << " " << epee::string_tools::pod_to_hex(m_service_node_pubkey) << " " << epee::string_tools::pod_to_hex(signature) << "\n\n";
time_t tt = exp_timestamp;
struct tm tm;
#ifdef WIN32
gmtime_s(&tm, &tt);
#else
gmtime_r(&tt, &tm);
#endif
char buffer[128];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M:%S %p", &tm);
ss << tr("This registration expires at ") << buffer << tr(". This should be in about 2 weeks. If it isn't, check this computer's clock") << std::endl;
ss << tr("Please submit your registration into the blockchain before this time or it will be invalid.");
return ss.str();
}
//-----------------------------------------------------------------------------------------------
bool core::cmd_prepare_registration(const boost::program_options::variables_map& vm, const std::vector<std::string>& args)
{
bool r = handle_command_line(vm);
CHECK_AND_ASSERT_MES(r, false, "Unable to parse command line arguments");

r = init_service_node_key();
CHECK_AND_ASSERT_MES(r, false, "Failed to create or load service node key");
std::string registration = prepare_registration(args);

std::string registration;
r = service_nodes::make_registration_cmd(get_nettype(), args, m_service_node_pubkey, m_service_node_key, registration, true /*make_friendly*/);
CHECK_AND_ASSERT_MES(r, "", tr("Failed to make registration command"));
std::cout << registration << std::endl;
return true;
}
Expand Down
14 changes: 2 additions & 12 deletions src/cryptonote_core/cryptonote_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,12 +753,12 @@ namespace cryptonote
* @return the number of blocks to sync in one go
*/
std::pair<uint64_t, uint64_t> get_coinbase_tx_sum(const uint64_t start_offset, const size_t count);

/**
* @brief get the network type we're on
*
* @return which network are we on?
*/
*/
network_type get_nettype() const { return m_nettype; };

/**
Expand Down Expand Up @@ -1016,16 +1016,6 @@ namespace cryptonote
*/
bool init_service_node_key();

/**
* @brief Prepare a registration tx using the service node keys for this
* daemon.
*
* @param args The arguments, as a string. <address1> <fraction1> [<address2> <fraction2> [...]]
*
* @return whether or not the command was able to prepare the registration.
*/
std::string prepare_registration(const std::vector<std::string>& args);

bool m_test_drop_download = true; //!< whether or not to drop incoming blocks (for testing)

uint64_t m_test_drop_download_height = 0; //!< height under which to drop incoming blocks, if doing so
Expand Down
63 changes: 63 additions & 0 deletions src/cryptonote_core/service_node_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,69 @@ namespace service_nodes
MERROR(tr("If it looks correct, this may be because of rounding. Try reducing one of the portionholders portions by a very tiny amount"));
return false;
}

return true;
}

bool make_registration_cmd(cryptonote::network_type nettype, const std::vector<std::string> args, const crypto::public_key& service_node_pubkey,
const crypto::secret_key service_node_key, std::string &cmd, bool make_friendly)
{

std::vector<cryptonote::account_public_address> addresses;
std::vector<uint32_t> shares;
if (!convert_registration_args(nettype, args, addresses, shares))
{
MERROR(tr("Could not convert registration args"));
return false;
}

uint64_t exp_timestamp = time(nullptr) + STAKING_AUTHORIZATION_EXPIRATION_WINDOW;

crypto::hash hash;
bool hashed = cryptonote::get_registration_hash(addresses, shares, exp_timestamp, hash);
if (!hashed)
{
MERROR(tr("Could not make registration hash from addresses and shares"));
return false;
}

crypto::signature signature;
crypto::generate_signature(hash, service_node_pubkey, service_node_key, signature);

std::stringstream stream;
if (make_friendly)
{
stream << tr("Run this command in the wallet that will fund this registration:\n\n");
}

stream << "register_service_node";
for (size_t i = 0; i < args.size(); ++i)
{
stream << " " << args[i];
}

stream << " " << exp_timestamp << " ";
stream << epee::string_tools::pod_to_hex(service_node_pubkey) << " ";
stream << epee::string_tools::pod_to_hex(signature);

if (make_friendly)
{
stream << "\n\n";
time_t tt = exp_timestamp;
struct tm tm;
#ifdef WIN32
gmtime_s(&tm, &tt);
#else
gmtime_r(&tt, &tm);
#endif

char buffer[128];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M:%S %p", &tm);
stream << tr("This registration expires at ") << buffer << tr(". This should be in about 2 weeks. If it isn't, check this computer's clock") << std::endl;
stream << tr("Please submit your registration into the blockchain before this time or it will be invalid.");
}

cmd = stream.str();
return true;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/cryptonote_core/service_node_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ namespace service_nodes
};

bool convert_registration_args(cryptonote::network_type nettype, const std::vector<std::string>& args, std::vector<cryptonote::account_public_address>& addresses, std::vector<uint32_t>& portions);
bool make_registration_cmd(cryptonote::network_type nettype, const std::vector<std::string> args, const crypto::public_key& service_node_pubkey,
const crypto::secret_key service_node_key, std::string &cmd, bool make_friendly);

const static cryptonote::account_public_address null_address{ crypto::null_pkey, crypto::null_pkey };
}
11 changes: 11 additions & 0 deletions src/daemon/command_parser_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,17 @@ bool t_command_parser_executor::print_quorum_state(const std::vector<std::string
return m_executor.print_quorum_state(height);
}

bool t_command_parser_executor::get_service_node_registration_cmd(const std::vector<std::string>& args)
{
if (args.empty() || args.size() % 2 != 0)
{
std::cout << "Invalid number of arguments received, expected an even number of arguments and > 0, received: " << args.size() << std::endl;
return false;
}

bool result = m_executor.get_service_node_registration_cmd(args);
return result;
}

bool t_command_parser_executor::set_log_level(const std::vector<std::string>& args)
{
Expand Down
2 changes: 2 additions & 0 deletions src/daemon/command_parser_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class t_command_parser_executor final

bool print_quorum_state(const std::vector<std::string>& args);

bool get_service_node_registration_cmd(const std::vector<std::string>& args);

bool set_log_level(const std::vector<std::string>& args);

bool set_log_categories(const std::vector<std::string>& args);
Expand Down
6 changes: 6 additions & 0 deletions src/daemon/command_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ t_command_server::t_command_server(
, "print_quorum_state <height>"
, "Print the quorum state for the block height."
);
m_command_lookup.set_handler(
"get_service_node_registration_cmd"
, std::bind(&t_command_parser_executor::get_service_node_registration_cmd, &m_parser, p::_1)
, "get_service_node_registration_cmd <address1> <shares1> [<address2> <shares2> [...]]"
, "Generate the required registration command"
);
m_command_lookup.set_handler(
"is_key_image_spent"
, std::bind(&t_command_parser_executor::is_key_image_spent, &m_parser, p::_1)
Expand Down
29 changes: 29 additions & 0 deletions src/daemon/rpc_command_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1963,4 +1963,33 @@ bool t_rpc_command_executor::sync_info()
return true;
}

bool t_rpc_command_executor::get_service_node_registration_cmd(const std::vector<std::string> &args)
{
cryptonote::COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::request req;
cryptonote::COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::response res;
std::string fail_message = "Unsuccessful";
epee::json_rpc::error error_resp;

req.args = args;
req.make_friendly = !m_is_rpc;
if (m_is_rpc)
{
if (!m_rpc_client->json_rpc_request(req, res, "get_service_node_registration_cmd", fail_message.c_str()))
{
tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
else
{
if (!m_rpc_server->on_get_service_node_registration_cmd(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << make_error(fail_message, error_resp.message);
return true;
}
}

tools::success_msg_writer() << res.registration_cmd;
return true;
}
}// namespace daemonize
2 changes: 2 additions & 0 deletions src/daemon/rpc_command_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ class t_rpc_command_executor final {
bool relay_tx(const std::string &txid);

bool sync_info();

bool get_service_node_registration_cmd(const std::vector<std::string> &args);
};

} // namespace daemonize
75 changes: 26 additions & 49 deletions src/rpc/core_rpc_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2025,55 +2025,6 @@ namespace cryptonote
return r;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_submit_deregister_vote(const COMMAND_RPC_SEND_DEREGISTER_VOTE::request& req, COMMAND_RPC_SEND_DEREGISTER_VOTE::response &resp)
{
PERF_TIMER(on_submit_deregister_vote);

vote_verification_context vvc = {};
if(!m_core.add_deregister_vote(req.vote, vvc))
{
resp.status = "Failed";
resp.reason = "";

if ((resp.invalid_block_height = vvc.m_invalid_block_height))
add_reason(resp.reason, "could not get quorum for block height");

if ((resp.voters_quorum_index_out_of_bounds = vvc.m_voters_quorum_index_out_of_bounds))
add_reason(resp.reason, "quorum index was not in bounds of quorum");

if ((resp.service_node_index_out_of_bounds = vvc.m_service_node_index_out_of_bounds))
add_reason(resp.reason, "service node index was not in bounds of the service node list");

if ((resp.signature_not_valid = vvc.m_signature_not_valid))
add_reason(resp.reason, "signature could not be verified with the voter's key");

const std::string punctuation = resp.reason.empty() ? "" : ": ";

if (vvc.m_verification_failed)
{
LOG_PRINT_L0("[on_submit_deregister_vote]: deregister vote verification failed" << punctuation << resp.reason);
}
else
{
LOG_PRINT_L0("[on_submit_deregister_vote]: Failed to process deregister vote" << punctuation << resp.reason);
}

return true;
}

if (vvc.m_added_to_pool)
{
NOTIFY_NEW_DEREGISTER_VOTE::request r;
r.votes.push_back(req.vote);

cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context);
m_core.get_protocol()->relay_deregister_votes(r, fake_context);
}

resp.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp)
{
PERF_TIMER(on_relay_tx);
Expand Down Expand Up @@ -2286,6 +2237,32 @@ namespace cryptonote
return r;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_service_node_registration_cmd(const COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::request& req,
COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::response& res,
epee::json_rpc::error& error_resp)
{
PERF_TIMER(on_get_service_node_registration_cmd);

crypto::public_key service_node_pubkey;
crypto::secret_key service_node_key;
if (!m_core.get_service_node_keys(service_node_pubkey, service_node_key))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
error_resp.message = "Daemon has not been started in service node mode, please relaunch with --service-node flag.";
return false;
}

if (!service_nodes::make_registration_cmd(m_core.get_nettype(), req.args, service_node_pubkey, service_node_key, res.registration_cmd, req.make_friendly))
{
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
error_resp.message = "Failed to make registration command";
return false;
}

res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------


const command_line::arg_descriptor<std::string, false, true, 2> core_rpc_server::arg_rpc_bind_port = {
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/core_rpc_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ namespace cryptonote
MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted)
MAP_URI_AUTO_JON2("/get_quorum_state", on_get_quorum_state, COMMAND_RPC_GET_QUORUM_STATE)
MAP_URI_AUTO_JON2("/submit_deregister_vote", on_submit_deregister_vote, COMMAND_RPC_SEND_DEREGISTER_VOTE)
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
Expand Down Expand Up @@ -157,6 +156,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG)
MAP_JON_RPC_WE("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
MAP_JON_RPC_WE("get_quorum_state", on_get_quorum_state_json, COMMAND_RPC_GET_QUORUM_STATE)
MAP_JON_RPC_WE("get_service_node_registration_cmd", on_get_service_node_registration_cmd, COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD)
END_JSON_RPC_MAP()
END_URI_MAP2()

Expand Down Expand Up @@ -194,7 +194,6 @@ namespace cryptonote
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res);
bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res);
bool on_get_quorum_state(const COMMAND_RPC_GET_QUORUM_STATE::request& req, COMMAND_RPC_GET_QUORUM_STATE::response& res);
bool on_submit_deregister_vote(const COMMAND_RPC_SEND_DEREGISTER_VOTE::request& req, COMMAND_RPC_SEND_DEREGISTER_VOTE::response& resp);

//json_rpc
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res);
Expand Down Expand Up @@ -222,6 +221,7 @@ namespace cryptonote
bool on_get_txpool_backlog(const COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::response& res, epee::json_rpc::error& error_resp);
bool on_get_output_distribution(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res, epee::json_rpc::error& error_resp);
bool on_get_quorum_state_json(const COMMAND_RPC_GET_QUORUM_STATE::request& req, COMMAND_RPC_GET_QUORUM_STATE::response& res, epee::json_rpc::error& error_resp);
bool on_get_service_node_registration_cmd(const COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::request& req, COMMAND_RPC_GET_SERVICE_NODE_REGISTRATION_CMD::response& res, epee::json_rpc::error& error_resp);
//-----------------------

private:
Expand Down
Loading

0 comments on commit 5435e33

Please sign in to comment.