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

Recalculate work from wallet #1895

Merged
merged 25 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
14 changes: 9 additions & 5 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,13 +702,15 @@ TEST (node_config, v16_v17_upgrade)
ASSERT_FALSE (tree.get_optional_child ("pow_sleep_interval"));
ASSERT_FALSE (tree.get_optional_child ("external_address"));
ASSERT_FALSE (tree.get_optional_child ("external_port"));
ASSERT_FALSE (tree.get_optional_child ("work_recalc_interval"));
config.deserialize_json (upgraded, tree);
// The config options should be added after the upgrade
ASSERT_TRUE (!!tree.get_optional_child ("tcp_client_timeout"));
ASSERT_TRUE (!!tree.get_optional_child ("tcp_server_timeout"));
ASSERT_TRUE (!!tree.get_optional_child ("pow_sleep_interval"));
ASSERT_TRUE (!!tree.get_optional_child ("external_address"));
ASSERT_TRUE (!!tree.get_optional_child ("external_port"));
ASSERT_TRUE (!!tree.get_optional_child ("work_recalc_interval"));

ASSERT_TRUE (upgraded);
auto version (tree.get<std::string> ("version"));
Expand All @@ -733,13 +735,15 @@ TEST (node_config, v17_values)
tree.put ("pow_sleep_interval", 0);
tree.put ("external_address", "::1");
tree.put ("external_port", 0);
tree.put ("work_recalc_interval", 4);
config.deserialize_json (upgraded, tree);
ASSERT_FALSE (upgraded);
ASSERT_EQ (config.tcp_client_timeout.count (), 1);
ASSERT_EQ (config.tcp_server_timeout.count (), 0);
ASSERT_EQ (config.pow_sleep_interval.count (), 0);
ASSERT_EQ (config.external_address, boost::asio::ip::address_v6::from_string ("::1"));
ASSERT_EQ (config.external_port, 0);
ASSERT_EQ (config.work_recalc_interval.count (), 4);

// Check config is correct with other values
tree.put ("tcp_client_timeout", std::numeric_limits<unsigned long>::max () - 100);
Expand Down Expand Up @@ -2453,7 +2457,7 @@ TEST (active_difficulty, recalculate_work)
auto & node1 (*system.nodes[0]);
nano::genesis genesis;
nano::keypair key1;
ASSERT_EQ (node1.network_params.network.publish_threshold, node1.active.active_difficulty.load ());
ASSERT_EQ (node1.network_params.network.publish_threshold, node1.active.active_difficulty ());
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send1);
uint64_t difficulty1;
Expand All @@ -2465,9 +2469,9 @@ TEST (active_difficulty, recalculate_work)
{
ASSERT_NO_ERROR (system.poll ());
}
auto sum = std::accumulate (node1.active.difficulty_cb.begin (), node1.active.difficulty_cb.end (), nano::uint128_t (0));
auto sum (std::accumulate (node1.active.difficulty_cb.begin (), node1.active.difficulty_cb.end (), nano::uint128_t (0)));
ASSERT_EQ (node1.active.active_difficulty (), static_cast<uint64_t> (sum / node1.active.difficulty_cb.size ()));
std::unique_lock<std::mutex> lock (node1.active.mutex);
ASSERT_EQ (node1.active.active_difficulty.load (), static_cast<uint64_t> (sum / node1.active.difficulty_cb.size ()));
// Fake history records to force work recalculation
for (auto i (0); i < node1.active.difficulty_cb.size (); i++)
{
Expand All @@ -2477,10 +2481,10 @@ TEST (active_difficulty, recalculate_work)
uint64_t difficulty2;
nano::work_validate (*send1, &difficulty2);
node1.process_active (send1);
node1.active.update_active_difficulty ();
node1.active.update_active_difficulty (lock);
lock.unlock ();
sum = std::accumulate (node1.active.difficulty_cb.begin (), node1.active.difficulty_cb.end (), nano::uint128_t (0));
ASSERT_EQ (node1.active.active_difficulty.load (), static_cast<uint64_t> (sum / node1.active.difficulty_cb.size ()));
ASSERT_EQ (node1.active.active_difficulty (), static_cast<uint64_t> (sum / node1.active.difficulty_cb.size ()));
}

namespace
Expand Down
44 changes: 44 additions & 0 deletions nano/core_test/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,3 +1038,47 @@ TEST (wallet, deterministic_restore)
}
ASSERT_TRUE (wallet->exists (pub));
}

TEST (wallet, update_work_action)
{
nano::system system (24000, 1);
auto & node (*system.nodes[0]);
node.config.enable_voting = false;
auto & wallet (*system.wallet (0));
wallet.insert_adhoc (nano::test_genesis_key.prv);
nano::keypair key;
auto const block (wallet.send_action (nano::test_genesis_key.pub, key.pub, nano::genesis_amount));
node.wallets.queue_work_regeneration (std::chrono::steady_clock::now (), block);
uint64_t difficulty1 (0);
nano::work_validate (*block, &difficulty1);
std::unique_lock<std::mutex> lock (node.active.mutex);
//fill difficulty_cb and update active difficulty;
for (auto i (0); i < node.active.difficulty_cb.size (); i++)
{
node.active.difficulty_cb.push_back (difficulty1 + 10000);
}
node.active.update_active_difficulty (lock);
lock.unlock ();

auto active_difficulty1 (node.active.active_difficulty ());
//active_difficulty1 after filling difficulty_cb with difficulty1 +10000 is greater than difficulty1
ASSERT_GT (active_difficulty1, difficulty1);

system.deadline_set (10s);
auto updated (false);
uint64_t updated_difficulty;
while (!updated)
{
lock.lock ();
auto const existing (node.active.roots.find (block->qualified_root ()));
//if existing is junk the block has been confirmed already
ASSERT_NE (existing, node.active.roots.end ());
updated = existing->difficulty != difficulty1;
updated_difficulty = existing->difficulty;
lock.unlock ();
ASSERT_NO_ERROR (system.poll ());
}
lock.lock ();
ASSERT_GT (updated_difficulty, difficulty1);
lock.unlock ();
}
3 changes: 3 additions & 0 deletions nano/lib/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ namespace thread_role
case nano::thread_role::name::wallet_actions:
thread_role_name_string = "Wallet actions";
break;
case nano::thread_role::name::wallet_work_regen:
thread_role_name_string = "Work regen";
break;
case nano::thread_role::name::bootstrap_initiator:
thread_role_name_string = "Bootstrap init";
break;
Expand Down
3 changes: 2 additions & 1 deletion nano/lib/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ namespace thread_role
voting,
signature_checking,
rpc_request_processor,
rpc_process_container
rpc_process_container,
wallet_work_regen
};
/*
* Get/Set the identifier for the current thread
Expand Down
2 changes: 1 addition & 1 deletion nano/node/json_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ void nano::json_handler::accounts_pending ()
void nano::json_handler::active_difficulty ()
{
response_l.put ("difficulty_threshold", nano::to_string_hex (node.network_params.network.publish_threshold));
response_l.put ("difficulty_active", nano::to_string_hex (node.active.active_difficulty));
response_l.put ("difficulty_active", nano::to_string_hex (node.active.active_difficulty ()));
response_errors ();
}

Expand Down
18 changes: 11 additions & 7 deletions nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3079,7 +3079,6 @@ void nano::active_transactions::request_confirm (std::unique_lock<std::mutex> &
}
roots.erase (*i);
}
update_active_difficulty ();
if (unconfirmed_count > 0)
{
node.logger.try_log (boost::str (boost::format ("%1% blocks have been unconfirmed averaging %2% announcements") % unconfirmed_count % (unconfirmed_announcements / unconfirmed_count)));
Expand All @@ -3098,7 +3097,7 @@ void nano::active_transactions::request_loop ()
while (!stopped)
{
request_confirm (lock);

update_active_difficulty (lock);
// This prevents unnecessary waiting if stopped is set in-between the above check and now
if (stopped)
{
Expand Down Expand Up @@ -3306,9 +3305,8 @@ void nano::active_transactions::adjust_difficulty (nano::block_hash const & hash
}
}

void nano::active_transactions::update_active_difficulty ()
void nano::active_transactions::update_active_difficulty (std::unique_lock<std::mutex> & lock_a)
{
assert (!mutex.try_lock ());
uint64_t difficulty (node.network_params.network.publish_threshold);
if (!roots.empty ())
{
Expand All @@ -3320,10 +3318,16 @@ void nano::active_transactions::update_active_difficulty ()
}
assert (difficulty >= node.network_params.network.publish_threshold);
difficulty_cb.push_front (difficulty);
auto sum = std::accumulate (node.active.difficulty_cb.begin (), node.active.difficulty_cb.end (), uint128_t (0));
auto sum (std::accumulate (node.active.difficulty_cb.begin (), node.active.difficulty_cb.end (), uint128_t (0)));
difficulty = static_cast<uint64_t> (sum / difficulty_cb.size ());
assert (difficulty >= node.network_params.network.publish_threshold);
active_difficulty.store (difficulty);
atomic_active_difficulty.store (difficulty);
}

uint64_t nano::active_transactions::active_difficulty ()
{
std::lock_guard<std::mutex> lock (mutex);
return atomic_active_difficulty.load ();
}

// List of active blocks in elections
Expand Down Expand Up @@ -3373,7 +3377,7 @@ size_t nano::active_transactions::size ()
nano::active_transactions::active_transactions (nano::node & node_a, bool delay_frontier_confirmation_height_updating) :
node (node_a),
difficulty_cb (20, node.network_params.network.publish_threshold),
active_difficulty (node.network_params.network.publish_threshold),
atomic_active_difficulty (node.network_params.network.publish_threshold),
next_frontier_check (std::chrono::steady_clock::now () + (delay_frontier_confirmation_height_updating ? std::chrono::seconds (60) : std::chrono::seconds (0))),
started (false),
stopped (false),
Expand Down
5 changes: 3 additions & 2 deletions nano/node/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class active_transactions final
bool active (nano::block const &);
void update_difficulty (nano::block const &);
void adjust_difficulty (nano::block_hash const &);
void update_active_difficulty ();
void update_active_difficulty (std::unique_lock<std::mutex> &);
uint64_t active_difficulty ();
std::deque<std::shared_ptr<nano::block>> list_blocks (bool = false);
void erase (nano::block const &);
bool empty ();
Expand Down Expand Up @@ -146,7 +147,7 @@ class active_transactions final
static size_t constexpr election_history_size = 2048;
static size_t constexpr max_broadcast_queue = 1000;
boost::circular_buffer<uint64_t> difficulty_cb;
std::atomic<uint64_t> active_difficulty;
std::atomic<uint64_t> atomic_active_difficulty;

private:
// Call action with confirmed block, may be different than what we started with
Expand Down
6 changes: 6 additions & 0 deletions nano/node/nodeconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ nano::error nano::node_config::serialize_json (nano::jsonconfig & json) const
json.put ("pow_sleep_interval", pow_sleep_interval.count ());
json.put ("external_address", external_address.to_string ());
json.put ("external_port", external_port);
json.put ("work_recalc_interval", work_recalc_interval.count ());
nano::jsonconfig websocket_l;
websocket_config.serialize_json (websocket_l);
json.put_child ("websocket", websocket_l);
Expand Down Expand Up @@ -254,6 +255,7 @@ bool nano::node_config::upgrade_json (unsigned version_a, nano::jsonconfig & jso
json.put (pow_sleep_interval_key, pow_sleep_interval.count ());
json.put ("external_address", external_address.to_string ());
json.put ("external_port", external_port);
json.put ("work_recalc_interval", work_recalc_interval.count ());
upgraded = true;
}
case 17:
Expand Down Expand Up @@ -395,6 +397,10 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
json.get (pow_sleep_interval_key, pow_sleep_interval_l);
pow_sleep_interval = std::chrono::nanoseconds (pow_sleep_interval_l);

auto work_recalc_interval_l (work_recalc_interval.count ());
json.get ("work_recalc_interval", work_recalc_interval_l);
work_recalc_interval = std::chrono::seconds (work_recalc_interval_l);

// Validate ranges
if (online_weight_quorum > 100)
{
Expand Down
1 change: 1 addition & 0 deletions nano/node/nodeconfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class node_config
std::chrono::seconds tcp_client_timeout{ std::chrono::seconds (5) };
std::chrono::seconds tcp_server_timeout{ std::chrono::seconds (30) };
std::chrono::nanoseconds pow_sleep_interval{ 0 };
std::chrono::seconds work_recalc_interval{ 4 };
static std::chrono::seconds constexpr keepalive_period = std::chrono::seconds (60);
static std::chrono::seconds constexpr keepalive_cutoff = keepalive_period * 5;
static std::chrono::minutes constexpr wallet_backup_interval = std::chrono::minutes (5);
Expand Down
Loading