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

Optional "block" given to RPC "work_generate" to infer difficulty #2754

Merged
merged 13 commits into from
May 15, 2020
6 changes: 6 additions & 0 deletions nano/lib/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ std::string nano::error_rpc_messages::message (int ev) const
return "Representative account and previous hash required";
case nano::error_rpc::block_create_requirements_send:
return "Destination account, previous hash, current balance and amount required";
case nano::error_rpc::block_root_mismatch:
return "Root mismatch for block";
case nano::error_rpc::block_work_enough:
return "Provided work is already enough for given difficulty";
case nano::error_rpc::block_work_version_mismatch:
return "Work version mismatch for block";
case nano::error_rpc::confirmation_height_not_processing:
return "There are no blocks currently being processed for adding confirmation height";
case nano::error_rpc::confirmation_not_found:
Expand Down
3 changes: 3 additions & 0 deletions nano/lib/errors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ enum class error_rpc
block_create_requirements_receive,
block_create_requirements_change,
block_create_requirements_send,
block_root_mismatch,
block_work_enough,
block_work_version_mismatch,
confirmation_height_not_processing,
confirmation_not_found,
difficulty_limit,
Expand Down
176 changes: 88 additions & 88 deletions nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,19 +268,27 @@ nano::amount nano::json_handler::amount_impl ()

std::shared_ptr<nano::block> nano::json_handler::block_impl (bool signature_work_required)
{
const bool json_block_l = request.get<bool> ("json_block", false);
std::shared_ptr<nano::block> result{ nullptr };
if (!ec)
{
std::string block_text (request.get<std::string> ("block"));
boost::property_tree::ptree block_l;
std::stringstream block_stream (block_text);
try
if (json_block_l)
{
boost::property_tree::read_json (block_stream, block_l);
block_l = request.get_child ("block");
}
catch (...)
else
{
ec = nano::error_blocks::invalid_block;
std::string block_text (request.get<std::string> ("block"));
std::stringstream block_stream (block_text);
try
{
boost::property_tree::read_json (block_stream, block_l);
}
catch (...)
{
ec = nano::error_blocks::invalid_block;
}
}
if (!ec)
{
Expand All @@ -299,26 +307,6 @@ std::shared_ptr<nano::block> nano::json_handler::block_impl (bool signature_work
return result;
}

std::shared_ptr<nano::block> nano::json_handler::block_json_impl (bool signature_work_required)
{
std::shared_ptr<nano::block> result;
if (!ec)
{
auto block_l (request.get_child ("block"));
if (!signature_work_required)
{
block_l.put ("signature", "0");
block_l.put ("work", "0");
}
result = nano::deserialize_block_json (block_l);
if (result == nullptr)
{
ec = nano::error_blocks::invalid_block;
}
}
return result;
}

nano::block_hash nano::json_handler::hash_impl (std::string search_text)
{
nano::block_hash result (0);
Expand Down Expand Up @@ -375,6 +363,43 @@ uint64_t nano::json_handler::difficulty_optional_impl (nano::work_version const
return difficulty;
}

uint64_t nano::json_handler::difficulty_ledger (nano::block const & block_a)
{
nano::block_details details (nano::epoch::epoch_0, false, false, false);
bool details_found (false);
auto transaction (node.store.tx_begin_read ());
// Previous block find
std::shared_ptr<nano::block> block_previous (nullptr);
auto previous (block_a.previous ());
if (!previous.is_zero ())
{
block_previous = node.store.block_get (transaction, previous);
}
// Send check
if (block_previous != nullptr)
{
details.is_send = node.store.block_balance (transaction, previous) > block_a.balance ().number ();
details_found = true;
}
// Epoch check
if (block_previous != nullptr)
{
details.epoch = block_previous->sideband ().details.epoch;
}
auto link (block_a.link ());
if (!link.is_zero () && !details.is_send)
{
auto block_link (node.store.block_get (transaction, link));
if (block_link != nullptr && node.store.pending_exists (transaction, nano::pending_key (block_a.account (), link)))
{
details.epoch = std::max (details.epoch, block_link->sideband ().details.epoch);
details.is_receive = true;
details_found = true;
}
}
return details_found ? nano::work_threshold (block_a.work_version (), details) : node.default_difficulty (block_a.work_version ());
}

double nano::json_handler::multiplier_optional_impl (nano::work_version const version_a, uint64_t & difficulty)
{
double multiplier (1.);
Expand Down Expand Up @@ -1555,37 +1580,7 @@ void nano::json_handler::block_create ()
// Difficulty calculation
if (request.count ("difficulty") == 0)
{
nano::block_details details (nano::epoch::epoch_0, false, false, false);
bool details_found (false);
auto transaction (node.store.tx_begin_read ());
// Previous block find
std::shared_ptr<nano::block> block_previous (nullptr);
if (!previous.is_zero ())
{
block_previous = node.store.block_get (transaction, previous);
}
// Send check
if (block_previous != nullptr)
{
details.is_send = node.store.block_balance (transaction, previous) > balance.number ();
details_found = true;
}
// Epoch check
if (block_previous != nullptr)
{
details.epoch = block_previous->sideband ().details.epoch;
}
if (!link.is_zero () && !details.is_send)
{
auto block_link (node.store.block_get (transaction, link));
if (block_link != nullptr && node.store.pending_exists (transaction, nano::pending_key (pub, link)))
{
details.epoch = std::max (details.epoch, block_link->sideband ().details.epoch);
details.is_receive = true;
details_found = true;
}
}
difficulty_l = details_found ? nano::work_threshold (work_version, details) : node.default_difficulty (work_version);
difficulty_l = difficulty_ledger (*block_l);
}
node.work_generate (work_version, root_l, difficulty_l, get_callback_l (block_l), nano::account (pub));
}
Expand All @@ -1610,16 +1605,7 @@ void nano::json_handler::block_create ()

void nano::json_handler::block_hash ()
{
const bool json_block_l = request.get<bool> ("json_block", false);
std::shared_ptr<nano::block> block;
if (json_block_l)
{
block = block_json_impl (true);
}
else
{
block = block_impl (true);
}
auto block (block_impl (true));

if (!ec)
{
Expand Down Expand Up @@ -3014,17 +3000,8 @@ void nano::json_handler::payment_wait ()
void nano::json_handler::process ()
{
node.worker.push_task (create_worker_task ([](std::shared_ptr<nano::json_handler> const & rpc_l) {
const bool json_block_l = rpc_l->request.get<bool> ("json_block", false);
const bool watch_work_l = rpc_l->request.get<bool> ("watch_work", true);
std::shared_ptr<nano::block> block;
if (json_block_l)
{
block = rpc_l->block_json_impl (true);
}
else
{
block = rpc_l->block_impl (true);
}
auto block (rpc_l->block_impl (true));

// State blocks subtype check
if (!rpc_l->ec && block->type () == nano::block_type::state)
Expand Down Expand Up @@ -3617,17 +3594,9 @@ void nano::json_handler::sign ()
}
// Retrieving block
std::shared_ptr<nano::block> block;
boost::optional<std::string> block_text (request.get_optional<std::string> ("block"));
if (!ec && block_text.is_initialized ())
if (!ec && request.count ("block"))
{
if (json_block_l)
{
block = block_json_impl (true);
}
else
{
block = block_impl (true);
}
block = block_impl (true);
if (block != nullptr)
{
hash = block->hash ();
Expand Down Expand Up @@ -4785,7 +4754,38 @@ void nano::json_handler::work_generate ()
{
ec = nano::error_rpc::difficulty_limit;
}
if (!ec)
// Retrieving optional block
std::shared_ptr<nano::block> block;
if (!ec && request.count ("block"))
{
block = block_impl (true);
if (block != nullptr)
{
if (hash != block->root ())
{
ec = nano::error_rpc::block_root_mismatch;
}
if (request.count ("version") == 0)
{
work_version = block->work_version ();
}
else if (!ec && work_version != block->work_version ())
{
ec = nano::error_rpc::block_work_version_mismatch;
}
// Difficulty calculation
if (!ec && request.count ("difficulty") == 0 && request.count ("multiplier") == 0)
{
difficulty = difficulty_ledger (*block);
}
// If optional block difficulty is higher than requested difficulty, send error
if (!ec && block->difficulty () >= difficulty)
{
ec = nano::error_rpc::block_work_enough;
}
}
}
if (!ec && response_l.empty ())
{
auto use_peers (request.get<bool> ("use_peers", false));
auto rpc_l (shared_from_this ());
Expand Down
2 changes: 1 addition & 1 deletion nano/node/json_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@ class json_handler : public std::enable_shared_from_this<nano::json_handler>
nano::account_info account_info_impl (nano::transaction const &, nano::account const &);
nano::amount amount_impl ();
std::shared_ptr<nano::block> block_impl (bool = true);
std::shared_ptr<nano::block> block_json_impl (bool = true);
nano::block_hash hash_impl (std::string = "hash");
nano::amount threshold_optional_impl ();
uint64_t work_optional_impl ();
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 (nano::work_version const);
uint64_t difficulty_ledger (nano::block const &);
double multiplier_optional_impl (nano::work_version const, uint64_t &);
nano::work_version work_version_optional_impl (nano::work_version const default_a);
bool enable_sign_hash{ false };
Expand Down
1 change: 1 addition & 0 deletions nano/node/testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ nano::account nano::system::account (nano::transaction const & transaction_a, si

uint64_t nano::system::work_generate_limited (nano::block_hash const & root_a, uint64_t min_a, uint64_t max_a)
{
debug_assert (min_a > 0);
uint64_t result = 0;
do
{
Expand Down
Loading