Moving nano::block::difficulty on to nano::work_thresholds. This moves the responsibility of determining difficulty fully on to work_thresholds rather than splitting this responsibliity with nano::block.

This commit is contained in:
clemahieu 2021-08-09 15:47:33 +01:00
commit c3ac780af2
No known key found for this signature in database
GPG key ID: 43708520C8DFB938
16 changed files with 42 additions and 43 deletions

View file

@ -312,7 +312,7 @@ TEST (block, publish_req_serialization)
TEST (block, difficulty)
{
nano::send_block block (0, 1, 2, nano::keypair ().prv, 4, 5);
ASSERT_EQ (block.difficulty (), nano::dev::network_params.network.publish_thresholds.difficulty (block.work_version (), block.root (), block.block_work ()));
ASSERT_EQ (nano::dev::network_params.network.publish_thresholds.difficulty (block), nano::dev::network_params.network.publish_thresholds.difficulty (block.work_version (), block.root (), block.block_work ()));
}
TEST (state_block, serialization)

View file

@ -2895,7 +2895,7 @@ TEST (ledger, work_validation)
auto process_block = [&store, &ledger, &pool] (nano::block & block_a, nano::block_details const details_a) {
auto threshold = nano::dev::network_params.network.publish_thresholds.threshold (block_a.work_version (), details_a);
// Rarely failed with random work, so modify until it doesn't have enough difficulty
while (block_a.difficulty () >= threshold)
while (nano::dev::network_params.network.publish_thresholds.difficulty (block_a) >= threshold)
{
block_a.block_work_set (block_a.block_work () + 1);
}

View file

@ -4550,7 +4550,7 @@ TEST (node, deferred_dependent_elections)
ASSERT_TIMELY (2s, node2.block (send2->hash ()));
// Re-processing older blocks with updated work also does not start an election
node.work_generate_blocking (*open, open->difficulty () + 1);
node.work_generate_blocking (*open, nano::dev::network_params.network.publish_thresholds.difficulty (*open) + 1);
node.process_local (open);
node.block_processor.flush ();
node.scheduler.flush ();
@ -4563,7 +4563,7 @@ TEST (node, deferred_dependent_elections)
ASSERT_FALSE (node.active.active (open->qualified_root ()));
/// The election was dropped but it's still not possible to restart it
node.work_generate_blocking (*open, open->difficulty () + 1);
node.work_generate_blocking (*open, nano::dev::network_params.network.publish_thresholds.difficulty (*open) + 1);
ASSERT_FALSE (node.active.active (open->qualified_root ()));
node.process_local (open);
node.block_processor.flush ();

View file

@ -822,7 +822,7 @@ TEST (wallet, no_work)
auto block (system.wallet (0)->send_action (nano::dev::genesis_key.pub, key2.pub, std::numeric_limits<nano::uint128_t>::max (), false));
ASSERT_NE (nullptr, block);
ASSERT_NE (0, block->block_work ());
ASSERT_GE (block->difficulty (), nano::dev::network_params.network.publish_thresholds.threshold (block->work_version (), block->sideband ().details));
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (*block), nano::dev::network_params.network.publish_thresholds.threshold (block->work_version (), block->sideband ().details));
auto transaction (system.wallet (0)->wallets.tx_begin_read ());
uint64_t cached_work (0);
system.wallet (0)->store.work_get (transaction, nano::dev::genesis_key.pub, cached_work);
@ -1022,9 +1022,9 @@ TEST (wallet, epoch_2_validation)
auto receive = wallet.receive_action (send->hash (), nano::dev::genesis_key.pub, amount, send->link ().as_account (), 1);
ASSERT_NE (nullptr, receive);
if (receive->difficulty () < node.network_params.network.publish_thresholds.base)
if (nano::dev::network_params.network.publish_thresholds.difficulty (*receive) < node.network_params.network.publish_thresholds.base)
{
ASSERT_GE (receive->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (*receive), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, receive->sideband ().details.epoch);
ASSERT_EQ (nano::epoch::epoch_2, receive->sideband ().source_epoch);
break;
@ -1074,9 +1074,9 @@ TEST (wallet, epoch_2_receive_propagation)
auto receive2 = wallet.receive_action (send2->hash (), key.pub, amount, send2->link ().as_account (), 1);
ASSERT_NE (nullptr, receive2);
if (receive2->difficulty () < node.network_params.network.publish_thresholds.base)
if (nano::dev::network_params.network.publish_thresholds.difficulty (*receive2) < node.network_params.network.publish_thresholds.base)
{
ASSERT_GE (receive2->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (*receive2), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, node.store.block.version (node.store.tx_begin_read (), receive2->hash ()));
ASSERT_EQ (nano::epoch::epoch_2, receive2->sideband ().source_epoch);
break;
@ -1119,9 +1119,9 @@ TEST (wallet, epoch_2_receive_unopened)
auto receive1 = wallet.receive_action (send1->hash (), key.pub, amount, send1->link ().as_account (), 1);
ASSERT_NE (nullptr, receive1);
if (receive1->difficulty () < node.network_params.network.publish_thresholds.base)
if (nano::dev::network_params.network.publish_thresholds.difficulty (*receive1) < node.network_params.network.publish_thresholds.base)
{
ASSERT_GE (receive1->difficulty (), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (*receive1), node.network_params.network.publish_thresholds.epoch_2_receive);
ASSERT_EQ (nano::epoch::epoch_2, node.store.block.version (node.store.tx_begin_read (), receive1->hash ()));
ASSERT_EQ (nano::epoch::epoch_1, receive1->sideband ().source_epoch);
break;

View file

@ -19,7 +19,7 @@ TEST (work, one)
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
nano::change_block block (1, 1, nano::keypair ().prv, 3, 4);
block.block_work_set (*pool.generate (block.root ()));
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.threshold_base (block.work_version ()), block.difficulty ());
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.threshold_base (block.work_version ()), nano::dev::network_params.network.publish_thresholds.difficulty (block));
}
TEST (work, disabled)
@ -33,9 +33,9 @@ TEST (work, validate)
{
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
nano::send_block send_block (1, 1, 2, nano::keypair ().prv, 4, 6);
ASSERT_LT (send_block.difficulty (), nano::dev::network_params.network.publish_thresholds.threshold_base (send_block.work_version ()));
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.difficulty (send_block), nano::dev::network_params.network.publish_thresholds.threshold_base (send_block.work_version ()));
send_block.block_work_set (*pool.generate (send_block.root ()));
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.threshold_base (send_block.work_version ()), send_block.difficulty ());
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.threshold_base (send_block.work_version ()), nano::dev::network_params.network.publish_thresholds.difficulty (send_block));
}
TEST (work, cancel)

View file

@ -83,12 +83,6 @@ nano::work_version nano::block::work_version () const
return nano::work_version::work_1;
}
uint64_t nano::block::difficulty () const
{
static nano::network_constants constants;
return constants.publish_thresholds.difficulty (this->work_version (), this->root (), this->block_work ());
}
nano::block_hash nano::block::generate_hash () const
{
nano::block_hash result;

View file

@ -113,7 +113,6 @@ public:
virtual bool valid_predecessor (nano::block const &) const = 0;
static size_t size (nano::block_type);
virtual nano::work_version work_version () const;
uint64_t difficulty () const;
// If there are any changes to the hashables, call this to update the cached hash
void refresh ();

View file

@ -193,6 +193,11 @@ uint64_t nano::work_thresholds::difficulty (nano::work_version const version_a,
return result;
}
uint64_t nano::work_thresholds::difficulty (nano::block const & block_a) const
{
return difficulty (block_a.work_version (), block_a.root (), block_a.block_work ());
}
bool nano::work_thresholds::validate_entry (nano::work_version const version_a, nano::root const & root_a, uint64_t const work_a) const
{
return difficulty (version_a, root_a, work_a) < threshold_entry (version_a, nano::block_type::state);
@ -200,7 +205,7 @@ bool nano::work_thresholds::validate_entry (nano::work_version const version_a,
bool nano::work_thresholds::validate_entry (nano::block const & block_a) const
{
return block_a.difficulty () < threshold_entry (block_a.work_version (), block_a.type ());
return difficulty (block_a) < threshold_entry (block_a.work_version (), block_a.type ());
}
namespace nano

View file

@ -120,6 +120,7 @@ public:
double normalized_multiplier (double const, uint64_t const) const;
double denormalized_multiplier (double const, uint64_t const) const;
uint64_t difficulty (nano::work_version const, nano::root const &, uint64_t const) const;
uint64_t difficulty (nano::block const & block_a) const;
bool validate_entry (nano::work_version const, nano::root const &, uint64_t const) const;
bool validate_entry (nano::block const &) const;

View file

@ -1567,7 +1567,7 @@ int main (int argc, char * const * argv)
}
}
// Check if block work value is correct
if (block->difficulty () < node->network_params.network.publish_thresholds.threshold (block->work_version (), block->sideband ().details))
if (node->network_params.network.publish_thresholds.difficulty (*block) < node->network_params.network.publish_thresholds.threshold (block->work_version (), block->sideband ().details))
{
print_error_message (boost::str (boost::format ("Invalid work for block %1% value: %2%\n") % hash.to_string () % nano::to_string_hex (block->block_work ())));
}

View file

@ -501,7 +501,7 @@ nano::process_return nano::block_processor::process_one (nano::write_transaction
{
if (node.config.logging.ledger_logging ())
{
node.logger.try_log (boost::str (boost::format ("Insufficient work for %1% : %2% (difficulty %3%)") % hash.to_string () % nano::to_string_hex (block->block_work ()) % nano::to_string_hex (block->difficulty ())));
node.logger.try_log (boost::str (boost::format ("Insufficient work for %1% : %2% (difficulty %3%)") % hash.to_string () % nano::to_string_hex (block->block_work ()) % nano::to_string_hex (node.network_params.network.publish_thresholds.difficulty (*block))));
}
break;
}

View file

@ -1481,7 +1481,7 @@ void nano::json_handler::block_create ()
auto block_response_put_l = [rpc_l, this] (nano::block const & block_a) {
boost::property_tree::ptree response_l;
response_l.put ("hash", block_a.hash ().to_string ());
response_l.put ("difficulty", nano::to_string_hex (block_a.difficulty ()));
response_l.put ("difficulty", nano::to_string_hex (rpc_l->node.network_params.network.publish_thresholds.difficulty (block_a)));
bool json_block_l = request.get<bool> ("json_block", false);
if (json_block_l)
{
@ -4901,7 +4901,7 @@ void nano::json_handler::work_generate ()
difficulty = difficulty_ledger (*block);
}
// If optional block difficulty is higher than requested difficulty, send error
if (!ec && block->difficulty () >= difficulty)
if (!ec && node.network_params.network.publish_thresholds.difficulty (*block) >= difficulty)
{
ec = nano::error_rpc::block_work_enough;
}

View file

@ -1460,7 +1460,7 @@ void nano::node::epoch_upgrader_impl (nano::raw_key const & prv_a, nano::epoch e
auto upgrader_process = [] (nano::node & node_a, std::atomic<uint64_t> & counter, std::shared_ptr<nano::block> const & epoch, uint64_t difficulty, nano::public_key const & signer_a, nano::root const & root_a, nano::account const & account_a) {
epoch->block_work_set (node_a.work_generate_blocking (nano::work_version::work_1, root_a, difficulty).value_or (0));
bool valid_signature (!nano::validate_message (signer_a, epoch->hash (), epoch->block_signature ()));
bool valid_work (epoch->difficulty () >= difficulty);
bool valid_work (node_a.network_params.network.publish_thresholds.difficulty (*epoch) >= difficulty);
nano::process_result result (nano::process_result::old);
if (valid_signature && valid_work)
{

View file

@ -1044,7 +1044,7 @@ bool nano::wallet::action_complete (std::shared_ptr<nano::block> const & block_a
if (block_a != nullptr)
{
auto required_difficulty{ wallets.node.network_params.network.publish_thresholds.threshold (block_a->work_version (), details_a) };
if (block_a->difficulty () < required_difficulty)
if (wallets.node.network_params.network.publish_thresholds.difficulty (*block_a) < required_difficulty)
{
wallets.node.logger.try_log (boost::str (boost::format ("Cached or provided work for block %1% account %2% is invalid, regenerating") % block_a->hash ().to_string () % account_a.to_account ()));
debug_assert (required_difficulty <= wallets.node.max_work_generate_difficulty (block_a->work_version ()));

View file

@ -1641,8 +1641,8 @@ TEST (rpc, process_ledger_insufficient_work)
auto min_difficulty = node->network_params.network.publish_thresholds.entry;
auto max_difficulty = node->network_params.network.publish_thresholds.epoch_1;
nano::state_block send (nano::dev::genesis->account (), latest, nano::dev::genesis->account (), nano::dev::constants.genesis_amount - nano::Gxrb_ratio, nano::dev::genesis_key.pub, nano::dev::genesis_key.prv, nano::dev::genesis_key.pub, system.work_generate_limited (latest, min_difficulty, max_difficulty));
ASSERT_LT (send.difficulty (), max_difficulty);
ASSERT_GE (send.difficulty (), min_difficulty);
ASSERT_LT (nano::dev::network_params.network.publish_thresholds.difficulty (send), max_difficulty);
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (send), min_difficulty);
boost::property_tree::ptree request;
request.put ("action", "process");
std::string json;
@ -2087,7 +2087,7 @@ TEST (rpc, work_generate_block_low)
auto threshold (node->default_difficulty (block.work_version ()));
block.block_work_set (system.work_generate_limited (block.root ().as_block_hash (), threshold, nano::difficulty::from_multiplier (node->config.max_work_generate_multiplier / 10, threshold)));
nano::block_hash hash (block.root ().as_block_hash ());
auto block_difficulty (block.difficulty ());
auto block_difficulty (nano::dev::network_params.network.publish_thresholds.difficulty (block));
boost::property_tree::ptree request;
request.put ("action", "work_generate");
request.put ("hash", hash.to_string ());
@ -4228,7 +4228,7 @@ TEST (rpc, block_create)
std::string send_hash (response.get<std::string> ("hash"));
ASSERT_EQ (send.hash ().to_string (), send_hash);
std::string send_difficulty (response.get<std::string> ("difficulty"));
ASSERT_EQ (nano::to_string_hex (send.difficulty ()), send_difficulty);
ASSERT_EQ (nano::to_string_hex (nano::dev::network_params.network.publish_thresholds.difficulty (send)), send_difficulty);
auto send_text (response.get<std::string> ("block"));
boost::property_tree::ptree block_l;
std::stringstream block_stream (send_text);
@ -4360,7 +4360,7 @@ TEST (rpc, block_create_state_open)
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
auto difficulty (nano::dev::network_params.network.publish_thresholds.difficulty (*state_block));
ASSERT_GT (difficulty, nano::dev::network_params.network.publish_thresholds.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_0, false, true, false)));
ASSERT_TRUE (node->latest (key.pub).is_zero ());
rpc_ctx->io_scope->reset ();
@ -4406,7 +4406,7 @@ TEST (rpc, block_create_state_request_work)
boost::property_tree::read_json (block_stream, block_l);
auto block (nano::deserialize_block_json (block_l));
ASSERT_NE (nullptr, block);
ASSERT_GE (block->difficulty (), node->default_difficulty (nano::work_version::work_1));
ASSERT_GE (nano::dev::network_params.network.publish_thresholds.difficulty (*block), node->default_difficulty (nano::work_version::work_1));
}
}
@ -4440,7 +4440,7 @@ TEST (rpc, block_create_open_epoch_v2)
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
auto difficulty (nano::dev::network_params.network.publish_thresholds.difficulty (*state_block));
ASSERT_GT (difficulty, nano::dev::network_params.network.publish_thresholds.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false)));
ASSERT_TRUE (node->latest (key.pub).is_zero ());
rpc_ctx->io_scope->reset ();
@ -4484,7 +4484,7 @@ TEST (rpc, block_create_receive_epoch_v2)
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
auto difficulty (nano::dev::network_params.network.publish_thresholds.difficulty (*state_block));
ASSERT_GT (difficulty, nano::dev::network_params.network.publish_thresholds.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, false, true, false)));
rpc_ctx->io_scope->reset ();
auto process_result (node->process (*state_block));
@ -4526,7 +4526,7 @@ TEST (rpc, block_create_send_epoch_v2)
ASSERT_NE (nullptr, state_block);
ASSERT_EQ (nano::block_type::state, state_block->type ());
ASSERT_EQ (state_hash, state_block->hash ().to_string ());
auto difficulty (state_block->difficulty ());
auto difficulty (nano::dev::network_params.network.publish_thresholds.difficulty (*state_block));
ASSERT_GT (difficulty, nano::dev::network_params.network.publish_thresholds.threshold (state_block->work_version (), nano::block_details (nano::epoch::epoch_2, true, false, false)));
rpc_ctx->io_scope->reset ();
auto process_result (node->process (*state_block));

View file

@ -346,7 +346,7 @@ void ledger_processor::state_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (epoch, is_send, is_receive, false);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::state_block);
@ -446,7 +446,7 @@ void ledger_processor::epoch_block_impl (nano::state_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (epoch, false, false, true);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
ledger.stats.inc (nano::stat::type::ledger, nano::stat::detail::epoch_block);
@ -498,7 +498,7 @@ void ledger_processor::change_block (nano::change_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
debug_assert (!validate_message (account, hash, block_a.signature));
@ -547,7 +547,7 @@ void ledger_processor::send_block (nano::send_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
debug_assert (!validate_message (account, hash, block_a.signature));
@ -624,7 +624,7 @@ void ledger_processor::receive_block (nano::receive_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
auto new_balance (info.balance.number () + pending.amount.number ());
@ -697,7 +697,7 @@ void ledger_processor::open_block (nano::open_block & block_a)
if (result.code == nano::process_result::progress)
{
nano::block_details block_details (nano::epoch::epoch_0, false /* unused */, false /* unused */, false /* unused */);
result.code = block_a.difficulty () >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
result.code = ledger.constants.work.difficulty (block_a) >= ledger.constants.work.threshold (block_a.work_version (), block_details) ? nano::process_result::progress : nano::process_result::insufficient_work; // Does this block have sufficient work? (Malformed)
if (result.code == nano::process_result::progress)
{
#ifdef NDEBUG