Work multiplier format and RPC work_validate fix for lower difficulties (#1984)
* Format multipliers using fixed and max precision rather than scientific * Fix RPC work_validate returning invalid for difficulty lower than threshold * Move nano::to/from_string_hex to lib/numbers.hpp * Parameter can be const in nano::to_string_hex * Extract nano::to_string method for converting double with fixed and custom precision. Use std streams rather than boost * Fix intermitent failure of rpc.work_generate test * Prevent crash in debug if given difficulty is 0
This commit is contained in:
parent
2174fd737b
commit
e822707d90
7 changed files with 62 additions and 47 deletions
|
|
@ -16,43 +16,6 @@ bool blocks_equal (T const & first, nano::block const & second)
|
|||
}
|
||||
}
|
||||
|
||||
std::string nano::to_string_hex (uint64_t value_a)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << std::noshowbase << std::setw (16) << std::setfill ('0');
|
||||
stream << value_a;
|
||||
return stream.str ();
|
||||
}
|
||||
|
||||
bool nano::from_string_hex (std::string const & value_a, uint64_t & target_a)
|
||||
{
|
||||
auto error (value_a.empty ());
|
||||
if (!error)
|
||||
{
|
||||
error = value_a.size () > 16;
|
||||
if (!error)
|
||||
{
|
||||
std::stringstream stream (value_a);
|
||||
stream << std::hex << std::noshowbase;
|
||||
try
|
||||
{
|
||||
uint64_t number_l;
|
||||
stream >> number_l;
|
||||
target_a = number_l;
|
||||
if (!stream.eof ())
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error &)
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
std::string nano::block::to_json () const
|
||||
{
|
||||
std::string result;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
namespace nano
|
||||
{
|
||||
std::string to_string_hex (uint64_t);
|
||||
bool from_string_hex (std::string const &, uint64_t &);
|
||||
// We operate on streams of uint8_t by convention
|
||||
using stream = std::basic_streambuf<uint8_t>;
|
||||
// Read a raw byte stream the size of `T' and fill value.
|
||||
|
|
|
|||
|
|
@ -774,6 +774,51 @@ std::string nano::uint128_union::to_string_dec () const
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string nano::to_string_hex (uint64_t const value_a)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << std::noshowbase << std::setw (16) << std::setfill ('0');
|
||||
stream << value_a;
|
||||
return stream.str ();
|
||||
}
|
||||
|
||||
bool nano::from_string_hex (std::string const & value_a, uint64_t & target_a)
|
||||
{
|
||||
auto error (value_a.empty ());
|
||||
if (!error)
|
||||
{
|
||||
error = value_a.size () > 16;
|
||||
if (!error)
|
||||
{
|
||||
std::stringstream stream (value_a);
|
||||
stream << std::hex << std::noshowbase;
|
||||
try
|
||||
{
|
||||
uint64_t number_l;
|
||||
stream >> number_l;
|
||||
target_a = number_l;
|
||||
if (!stream.eof ())
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
catch (std::runtime_error &)
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
std::string nano::to_string (double const value_a, int const precision_a)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::setprecision (precision_a) << std::fixed;
|
||||
stream << value_a;
|
||||
return stream.str ();
|
||||
}
|
||||
|
||||
uint64_t nano::difficulty::from_multiplier (double const multiplier_a, uint64_t const base_difficulty_a)
|
||||
{
|
||||
assert (multiplier_a > 0.);
|
||||
|
|
|
|||
|
|
@ -127,6 +127,16 @@ bool validate_message_batch (const unsigned char **, size_t *, const unsigned ch
|
|||
void deterministic_key (nano::uint256_union const &, uint32_t, nano::uint256_union &);
|
||||
nano::public_key pub_key (nano::private_key const &);
|
||||
|
||||
/* Conversion methods */
|
||||
std::string to_string_hex (uint64_t const);
|
||||
bool from_string_hex (std::string const &, uint64_t &);
|
||||
|
||||
/**
|
||||
* Convert a double to string in fixed format
|
||||
* @param precision_a (optional) use a specific precision (default is the maximum)
|
||||
*/
|
||||
std::string to_string (double const, int const precision_a = std::numeric_limits<double>::digits10);
|
||||
|
||||
namespace difficulty
|
||||
{
|
||||
uint64_t from_multiplier (double const, uint64_t const);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void nano::work_pool::loop (uint64_t thread)
|
|||
{
|
||||
// If the ticket matches what we started with, we're the ones that found the solution
|
||||
assert (output >= current_l.difficulty);
|
||||
assert (work_value (current_l.item, work) == output);
|
||||
assert (current_l.difficulty == 0 || work_value (current_l.item, work) == output);
|
||||
// Signal other threads to stop their work next time they check ticket
|
||||
++ticket;
|
||||
pending.pop_front ();
|
||||
|
|
|
|||
|
|
@ -839,7 +839,7 @@ void nano::json_handler::active_difficulty ()
|
|||
auto difficulty_active = node.active.active_difficulty ();
|
||||
response_l.put ("difficulty_active", nano::to_string_hex (difficulty_active));
|
||||
auto multiplier = nano::difficulty::to_multiplier (difficulty_active, node.network_params.network.publish_threshold);
|
||||
response_l.put ("multiplier", std::to_string (multiplier));
|
||||
response_l.put ("multiplier", nano::to_string (multiplier));
|
||||
response_errors ();
|
||||
}
|
||||
|
||||
|
|
@ -4363,7 +4363,7 @@ void nano::json_handler::work_generate ()
|
|||
nano::work_validate (hash, work_a.value (), &result_difficulty);
|
||||
response_l.put ("difficulty", nano::to_string_hex (result_difficulty));
|
||||
auto multiplier = nano::difficulty::to_multiplier (result_difficulty, this->node.network_params.network.publish_threshold);
|
||||
response_l.put ("multiplier", multiplier);
|
||||
response_l.put ("multiplier", nano::to_string (multiplier));
|
||||
boost::property_tree::write_json (ostream, response_l);
|
||||
rpc_l->response (ostream.str ());
|
||||
}
|
||||
|
|
@ -4451,12 +4451,11 @@ void nano::json_handler::work_validate ()
|
|||
if (!ec)
|
||||
{
|
||||
uint64_t result_difficulty (0);
|
||||
bool invalid (nano::work_validate (hash, work, &result_difficulty));
|
||||
bool valid (!invalid && result_difficulty >= difficulty);
|
||||
response_l.put ("valid", valid ? "1" : "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", multiplier);
|
||||
response_l.put ("multiplier", nano::to_string (multiplier));
|
||||
}
|
||||
response_errors ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2462,7 +2462,7 @@ TEST (rpc, work_generate)
|
|||
ASSERT_FALSE (nano::from_string_hex (response_difficulty_text, response_difficulty));
|
||||
ASSERT_EQ (result_difficulty, response_difficulty);
|
||||
auto multiplier = response.json.get<double> ("multiplier");
|
||||
ASSERT_EQ (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_threshold), multiplier);
|
||||
ASSERT_NEAR (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_threshold), multiplier, 1e-6);
|
||||
}
|
||||
|
||||
TEST (rpc, work_generate_difficulty)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue