Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept multiplier in work_generate and work_validate #2151

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nano/lib/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ std::string nano::error_rpc_messages::message (int ev) const
return "Bad key";
case nano::error_rpc::bad_link:
return "Bad link number";
case nano::error_rpc::bad_multiplier_format:
return "Bad multiplier";
case nano::error_rpc::bad_previous:
return "Bad previous";
case nano::error_rpc::bad_representative_number:
Expand Down
1 change: 1 addition & 0 deletions nano/lib/errors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ enum class error_rpc
bad_difficulty_format,
bad_key,
bad_link,
bad_multiplier_format,
bad_previous,
bad_representative_number,
bad_source,
Expand Down
60 changes: 40 additions & 20 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,39 @@ uint64_t nano::json_handler::work_optional_impl ()
return result;
}

uint64_t nano::json_handler::difficulty_optional_impl ()
{
uint64_t difficulty (node.network_params.network.publish_threshold);
boost::optional<std::string> difficulty_text (request.get_optional<std::string> ("difficulty"));
if (!ec && difficulty_text.is_initialized ())
{
if (nano::from_string_hex (difficulty_text.get (), difficulty))
{
ec = nano::error_rpc::bad_difficulty_format;
}
}
return difficulty;
}

double nano::json_handler::multiplier_optional_impl (uint64_t & difficulty)
{
double multiplier (1.);
boost::optional<std::string> multiplier_text (request.get_optional<std::string> ("multiplier"));
if (!ec && multiplier_text.is_initialized ())
{
auto success = boost::conversion::try_lexical_convert<double> (multiplier_text.get (), multiplier);
if (success && multiplier > 0.)
{
difficulty = nano::difficulty::from_multiplier (multiplier, node.network_params.network.publish_threshold);
}
else
{
ec = nano::error_rpc::bad_multiplier_format;
}
}
return multiplier;
}

namespace
{
bool decode_unsigned (std::string const & text, uint64_t & number)
Expand Down Expand Up @@ -4387,15 +4420,8 @@ void nano::json_handler::wallet_work_get ()
void nano::json_handler::work_generate ()
{
auto hash (hash_impl ());
uint64_t difficulty (node.network_params.network.publish_threshold);
boost::optional<std::string> difficulty_text (request.get_optional<std::string> ("difficulty"));
if (!ec && difficulty_text.is_initialized ())
{
if (nano::from_string_hex (difficulty_text.get (), difficulty))
{
ec = nano::error_rpc::bad_difficulty_format;
}
}
auto difficulty (difficulty_optional_impl ());
auto multiplier (multiplier_optional_impl (difficulty));
if (!ec && (difficulty > node_rpc_config.max_work_generate_difficulty || difficulty < node.network_params.network.publish_threshold))
{
ec = nano::error_rpc::difficulty_limit;
Expand Down Expand Up @@ -4491,23 +4517,17 @@ void nano::json_handler::work_validate ()
{
auto hash (hash_impl ());
auto work (work_optional_impl ());
uint64_t difficulty (node.network_params.network.publish_threshold);
boost::optional<std::string> difficulty_text (request.get_optional<std::string> ("difficulty"));
if (!ec && difficulty_text.is_initialized ())
{
if (nano::from_string_hex (difficulty_text.get (), difficulty))
{
ec = nano::error_rpc::bad_difficulty_format;
}
}
auto difficulty (difficulty_optional_impl ());
auto multiplier (multiplier_optional_impl (difficulty));
(void)multiplier;
if (!ec)
{
uint64_t result_difficulty (0);
nano::work_validate (hash, work, &result_difficulty);
response_l.put ("valid", (result_difficulty >= difficulty) ? "1" : "0");
response_l.put ("difficulty", nano::to_string_hex (result_difficulty));
auto multiplier = nano::difficulty::to_multiplier (result_difficulty, node.network_params.network.publish_threshold);
response_l.put ("multiplier", nano::to_string (multiplier));
auto result_multiplier = nano::difficulty::to_multiplier (result_difficulty, node.network_params.network.publish_threshold);
response_l.put ("multiplier", nano::to_string (result_multiplier));
}
response_errors ();
}
Expand Down
2 changes: 2 additions & 0 deletions nano/node/json_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ class json_handler : public std::enable_shared_from_this<nano::json_handler>
uint64_t count_impl ();
uint64_t count_optional_impl (uint64_t = std::numeric_limits<uint64_t>::max ());
uint64_t offset_optional_impl (uint64_t = 0);
uint64_t difficulty_optional_impl ();
double multiplier_optional_impl (uint64_t &);
bool enable_sign_hash{ false };
std::function<void()> stop_callback;
nano::node_rpc_config const & node_rpc_config;
Expand Down
67 changes: 67 additions & 0 deletions nano/rpc_test/rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,73 @@ TEST (rpc, work_generate_difficulty)
}
}

TEST (rpc, work_generate_multiplier)
{
nano::system system (24000, 1);
auto node (system.nodes[0]);
enable_ipc_transport_tcp (node->config.ipc_config.transport_tcp);
nano::node_rpc_config node_rpc_config;
nano::ipc::ipc_server ipc_server (*node, node_rpc_config);
nano::rpc_config rpc_config (true);
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
rpc.start ();
nano::block_hash hash (1);
boost::property_tree::ptree request;
request.put ("action", "work_generate");
request.put ("hash", hash.to_string ());
{
// When both difficulty and multiplier are given, should use multiplier
// Give base difficulty and very high multiplier to test
request.put ("difficulty", nano::to_string_hex (0xff00000000000000));
double multiplier{ 100.0 };
request.put ("multiplier", multiplier);
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (10s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
auto work_text (response.json.get<std::string> ("work"));
uint64_t work;
ASSERT_FALSE (nano::from_string_hex (work_text, work));
uint64_t result_difficulty;
ASSERT_FALSE (nano::work_validate (hash, work, &result_difficulty));
auto response_difficulty_text (response.json.get<std::string> ("difficulty"));
uint64_t response_difficulty;
ASSERT_FALSE (nano::from_string_hex (response_difficulty_text, response_difficulty));
ASSERT_EQ (result_difficulty, response_difficulty);
auto result_multiplier = response.json.get<double> ("multiplier");
ASSERT_GE (result_multiplier, multiplier);
}
{
request.put ("multiplier", -1.5);
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
std::error_code ec (nano::error_rpc::bad_multiplier_format);
ASSERT_EQ (response.json.get<std::string> ("error"), ec.message ());
}
{
double max_multiplier (nano::difficulty::to_multiplier (node_rpc_config.max_work_generate_difficulty, node->network_params.network.publish_threshold));
request.put ("multiplier", max_multiplier + 1);
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
std::error_code ec (nano::error_rpc::difficulty_limit);
ASSERT_EQ (response.json.get<std::string> ("error"), ec.message ());
}
}

TEST (rpc, work_cancel)
{
nano::system system (24000, 1);
Expand Down