Convert boost::optional to std::optional for distributed work generation.

This commit is contained in:
Colin LeMahieu 2024-03-06 15:39:50 +00:00
commit 76ebe9afa8
No known key found for this signature in database
GPG key ID: 43708520C8DFB938
13 changed files with 78 additions and 74 deletions

View file

@ -18,10 +18,10 @@ TEST (distributed_work, no_peers)
nano::test::system system (1);
auto node (system.nodes[0]);
nano::block_hash hash{ 1 };
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
std::atomic<bool> done{ false };
auto callback = [&work, &done] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&work, &done] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a;
done = true;
};
@ -54,8 +54,8 @@ TEST (distributed_work, no_peers_cancel)
auto & node = *system.add_node (node_config);
nano::block_hash hash{ 1 };
bool done{ false };
auto callback_to_cancel = [&done] (boost::optional<uint64_t> work_a) {
ASSERT_FALSE (work_a.is_initialized ());
auto callback_to_cancel = [&done] (std::optional<uint64_t> work_a) {
ASSERT_FALSE (work_a.has_value ());
done = true;
};
ASSERT_FALSE (node.distributed_work.make (nano::work_version::work_1, hash, node.config.work_peers, nano::difficulty::from_multiplier (1e6, node.network_params.work.base), callback_to_cancel));
@ -83,8 +83,8 @@ TEST (distributed_work, no_peers_multi)
nano::block_hash hash{ 1 };
unsigned total{ 10 };
std::atomic<unsigned> count{ 0 };
auto callback = [&count] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&count] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
++count;
};
// Test many works for the same root
@ -125,10 +125,10 @@ TEST (distributed_work, peer)
auto node (system.add_node (node_config));
ASSERT_FALSE (node->local_work_generation_enabled ());
nano::block_hash hash{ 1 };
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
std::atomic<bool> done{ false };
auto callback = [&work, &done] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&work, &done] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a;
done = true;
};
@ -151,10 +151,10 @@ TEST (distributed_work, peer_malicious)
auto node (system.nodes[0]);
ASSERT_TRUE (node->local_work_generation_enabled ());
nano::block_hash hash{ 1 };
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
std::atomic<bool> done{ false };
auto callback = [&work, &done] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&work, &done] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a;
done = true;
};
@ -194,10 +194,10 @@ TEST (distributed_work, DISABLED_peer_multi)
auto node (system.nodes[0]);
ASSERT_TRUE (node->local_work_generation_enabled ());
nano::block_hash hash{ 1 };
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
std::atomic<bool> done{ false };
auto callback = [&work, &done] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&work, &done] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a;
done = true;
};
@ -233,10 +233,10 @@ TEST (distributed_work, fail_resolve)
nano::test::system system (1);
auto node (system.nodes[0]);
nano::block_hash hash{ 1 };
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
std::atomic<bool> done{ false };
auto callback = [&work, &done] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
auto callback = [&work, &done] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a;
done = true;
};

View file

@ -48,19 +48,19 @@ TEST (node, work_generate)
{
auto difficulty = nano::difficulty::from_multiplier (1.5, node.network_params.work.base);
auto work = node.work_generate_blocking (version, root, difficulty);
ASSERT_TRUE (work.is_initialized ());
ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, *work), difficulty);
ASSERT_TRUE (work.has_value ());
ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, work.value ()), difficulty);
}
{
auto difficulty = nano::difficulty::from_multiplier (0.5, node.network_params.work.base);
boost::optional<uint64_t> work;
std::optional<uint64_t> work;
do
{
work = node.work_generate_blocking (version, root, difficulty);
} while (nano::dev::network_params.work.difficulty (version, root, *work) >= node.network_params.work.base);
ASSERT_TRUE (work.is_initialized ());
ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, *work), difficulty);
ASSERT_FALSE (nano::dev::network_params.work.difficulty (version, root, *work) >= node.network_params.work.base);
} while (nano::dev::network_params.work.difficulty (version, root, work.value ()) >= node.network_params.work.base);
ASSERT_TRUE (work.has_value ());
ASSERT_GE (nano::dev::network_params.work.difficulty (version, root, work.value ()), difficulty);
ASSERT_FALSE (nano::dev::network_params.work.difficulty (version, root, work.value ()) >= node.network_params.work.base);
}
}

View file

@ -796,7 +796,7 @@ TEST (websocket, work)
// Generate work
nano::block_hash hash{ 1 };
auto work (node1->work_generate_blocking (hash));
ASSERT_TRUE (work.is_initialized ());
ASSERT_TRUE (work.has_value ());
// Wait for the work notification
ASSERT_TIMELY_EQ (5s, future.wait_for (0s), std::future_status::ready);
@ -827,7 +827,7 @@ TEST (websocket, work)
nano::from_string_hex (result.get<std::string> ("difficulty"), result_difficulty);
ASSERT_GE (result_difficulty, node1->default_difficulty (nano::work_version::work_1));
ASSERT_NEAR (result.get<double> ("multiplier"), nano::difficulty::to_multiplier (result_difficulty, node1->default_difficulty (nano::work_version::work_1)), 1e-6);
ASSERT_EQ (result.get<std::string> ("work"), nano::to_string_hex (work.get ()));
ASSERT_EQ (result.get<std::string> ("work"), nano::to_string_hex (work.value ()));
ASSERT_EQ (1, contents.count ("bad_peers"));
auto & bad_peers = contents.get_child ("bad_peers");

View file

@ -68,7 +68,7 @@ void nano::distributed_work::start ()
else if (need_resolve.empty () && request.callback)
{
status = work_generation_status::failure_local;
request.callback (boost::none);
request.callback (std::nullopt);
}
for (auto const & peer : need_resolve)
{
@ -117,7 +117,7 @@ void nano::distributed_work::start_local ()
this_l->status = work_generation_status::failure_local;
if (this_l->request.callback)
{
this_l->request.callback (boost::none);
this_l->request.callback (std::nullopt);
}
}
this_l->stop_once (false);
@ -143,9 +143,9 @@ void nano::distributed_work::do_request (nano::tcp_endpoint const & endpoint_a)
rpc_request.put ("action", "work_generate");
rpc_request.put ("hash", this_l->request.root.to_string ());
rpc_request.put ("difficulty", nano::to_string_hex (this_l->request.difficulty));
if (this_l->request.account.is_initialized ())
if (this_l->request.account.has_value ())
{
rpc_request.put ("account", this_l->request.account.get ().to_account ());
rpc_request.put ("account", this_l->request.account.value ().to_account ());
}
std::stringstream ostream;
boost::property_tree::write_json (ostream, rpc_request);
@ -373,7 +373,7 @@ void nano::distributed_work::cancel ()
status = work_generation_status::cancelled;
if (request.callback)
{
request.callback (boost::none);
request.callback (std::nullopt);
}
stop_once (true);
}
@ -411,7 +411,7 @@ void nano::distributed_work::handle_failure ()
}
if (error_l && request_l.callback)
{
request_l.callback (boost::none);
request_l.callback (std::nullopt);
}
});
}

View file

@ -9,6 +9,8 @@
#include <nano/lib/work.hpp>
#include <nano/node/common.hpp>
#include <optional>
using request_type = boost::beast::http::request<boost::beast::http::string_body>;
namespace boost
@ -28,8 +30,8 @@ struct work_request final
nano::work_version version;
nano::root root;
uint64_t difficulty;
boost::optional<nano::account> const account;
std::function<void (boost::optional<uint64_t>)> callback;
std::optional<nano::account> const account;
std::function<void (std::optional<uint64_t>)> callback;
std::vector<std::pair<std::string, uint16_t>> const peers;
};
@ -107,4 +109,4 @@ private:
std::atomic<bool> stopped{ false };
std::atomic<bool> local_generation_started{ false };
};
}
}

View file

@ -12,7 +12,7 @@ nano::distributed_work_factory::~distributed_work_factory ()
stop ();
}
bool nano::distributed_work_factory::make (nano::work_version const version_a, nano::root const & root_a, std::vector<std::pair<std::string, uint16_t>> const & peers_a, uint64_t difficulty_a, std::function<void (boost::optional<uint64_t>)> const & callback_a, boost::optional<nano::account> const & account_a)
bool nano::distributed_work_factory::make (nano::work_version const version_a, nano::root const & root_a, std::vector<std::pair<std::string, uint16_t>> const & peers_a, uint64_t difficulty_a, std::function<void (std::optional<uint64_t>)> const & callback_a, std::optional<nano::account> const & account_a)
{
return make (std::chrono::seconds (1), nano::work_request{ version_a, root_a, difficulty_a, account_a, callback_a, peers_a });
}

View file

@ -4,6 +4,7 @@
#include <atomic>
#include <functional>
#include <optional>
#include <unordered_map>
#include <vector>
@ -20,7 +21,7 @@ class distributed_work_factory final
public:
distributed_work_factory (nano::node &);
~distributed_work_factory ();
bool make (nano::work_version const, nano::root const &, std::vector<std::pair<std::string, uint16_t>> const &, uint64_t, std::function<void (boost::optional<uint64_t>)> const &, boost::optional<nano::account> const & = boost::none);
bool make (nano::work_version const, nano::root const &, std::vector<std::pair<std::string, uint16_t>> const &, uint64_t, std::function<void (std::optional<uint64_t>)> const &, std::optional<nano::account> const & = std::nullopt);
bool make (std::chrono::seconds const &, nano::work_request const &);
void cancel (nano::root const &);
void cleanup_finished ();

View file

@ -1613,10 +1613,10 @@ void nano::json_handler::block_create ()
// Wrapper from argument to lambda capture, to extend the block's scope
auto get_callback_l = [rpc_l, block_response_put_l] (std::shared_ptr<nano::block> const & block_a) {
// Callback upon work generation success or failure
return [block_a, rpc_l, block_response_put_l] (boost::optional<uint64_t> const & work_a) {
return [block_a, rpc_l, block_response_put_l] (std::optional<uint64_t> const & work_a) {
if (block_a != nullptr)
{
if (work_a.is_initialized ())
if (work_a.has_value ())
{
block_a->block_work_set (*work_a);
block_response_put_l (*block_a);
@ -4994,7 +4994,7 @@ void nano::json_handler::wallet_work_get ()
void nano::json_handler::work_generate ()
{
boost::optional<nano::account> account;
std::optional<nano::account> account;
auto account_opt (request.get_optional<std::string> ("account"));
// Default to work_1 if not specified
auto work_version (work_version_optional_impl (nano::work_version::work_1));
@ -5046,7 +5046,7 @@ void nano::json_handler::work_generate ()
{
auto use_peers (request.get<bool> ("use_peers", false));
auto rpc_l (shared_from_this ());
auto callback = [rpc_l, hash, work_version, this] (boost::optional<uint64_t> const & work_a) {
auto callback = [rpc_l, hash, work_version, this] (std::optional<uint64_t> const & work_a) {
if (work_a)
{
boost::property_tree::ptree response_l;

View file

@ -1078,50 +1078,50 @@ bool nano::node::work_generation_enabled (std::vector<std::pair<std::string, uin
return !peers_a.empty () || local_work_generation_enabled ();
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a)
std::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a)
{
auto opt_work_l (work_generate_blocking (block_a.work_version (), block_a.root (), difficulty_a, block_a.account ()));
if (opt_work_l.is_initialized ())
if (opt_work_l.has_value ())
{
block_a.block_work_set (*opt_work_l);
block_a.block_work_set (opt_work_l.value ());
}
return opt_work_l;
}
void nano::node::work_generate (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::function<void (boost::optional<uint64_t>)> callback_a, boost::optional<nano::account> const & account_a, bool secondary_work_peers_a)
void nano::node::work_generate (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::function<void (std::optional<uint64_t>)> callback_a, std::optional<nano::account> const & account_a, bool secondary_work_peers_a)
{
auto const & peers_l (secondary_work_peers_a ? config.secondary_work_peers : config.work_peers);
if (distributed_work.make (version_a, root_a, peers_l, difficulty_a, callback_a, account_a))
{
// Error in creating the job (either stopped or work generation is not possible)
callback_a (boost::none);
callback_a (std::nullopt);
}
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, boost::optional<nano::account> const & account_a)
std::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::optional<nano::account> const & account_a)
{
std::promise<boost::optional<uint64_t>> promise;
std::promise<std::optional<uint64_t>> promise;
work_generate (
version_a, root_a, difficulty_a, [&promise] (boost::optional<uint64_t> opt_work_a) {
version_a, root_a, difficulty_a, [&promise] (std::optional<uint64_t> opt_work_a) {
promise.set_value (opt_work_a);
},
account_a);
return promise.get_future ().get ();
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a)
std::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a)
{
debug_assert (network_params.network.is_dev_network ());
return work_generate_blocking (block_a, default_difficulty (nano::work_version::work_1));
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a)
std::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a)
{
debug_assert (network_params.network.is_dev_network ());
return work_generate_blocking (root_a, default_difficulty (nano::work_version::work_1));
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a)
std::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a)
{
debug_assert (network_params.network.is_dev_network ());
return work_generate_blocking (nano::work_version::work_1, root_a, difficulty_a);

View file

@ -43,6 +43,7 @@
#include <atomic>
#include <memory>
#include <optional>
#include <vector>
namespace nano
@ -111,9 +112,9 @@ public:
bool local_work_generation_enabled () const;
bool work_generation_enabled () const;
bool work_generation_enabled (std::vector<std::pair<std::string, uint16_t>> const &) const;
boost::optional<uint64_t> work_generate_blocking (nano::block &, uint64_t);
boost::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::root const &, uint64_t, boost::optional<nano::account> const & = boost::none);
void work_generate (nano::work_version const, nano::root const &, uint64_t, std::function<void (boost::optional<uint64_t>)>, boost::optional<nano::account> const & = boost::none, bool const = false);
std::optional<uint64_t> work_generate_blocking (nano::block &, uint64_t);
std::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::root const &, uint64_t, std::optional<nano::account> const & = std::nullopt);
void work_generate (nano::work_version const, nano::root const &, uint64_t, std::function<void (std::optional<uint64_t>)>, std::optional<nano::account> const & = std::nullopt, bool const = false);
void add_initial_peers ();
void start_election (std::shared_ptr<nano::block> const & block);
bool block_confirmed (nano::block_hash const &);
@ -199,11 +200,11 @@ public:
// For tests only
unsigned node_seq;
// For tests only
boost::optional<uint64_t> work_generate_blocking (nano::block &);
std::optional<uint64_t> work_generate_blocking (nano::block &);
// For tests only
boost::optional<uint64_t> work_generate_blocking (nano::root const &, uint64_t);
std::optional<uint64_t> work_generate_blocking (nano::root const &, uint64_t);
// For tests only
boost::optional<uint64_t> work_generate_blocking (nano::root const &);
std::optional<uint64_t> work_generate_blocking (nano::root const &);
public: // Testing convenience functions
/**

View file

@ -1050,7 +1050,7 @@ bool nano::wallet::action_complete (std::shared_ptr<nano::block> const & block_a
account_a.to_account ());
debug_assert (required_difficulty <= wallets.node.max_work_generate_difficulty (block_a->work_version ()));
error = !wallets.node.work_generate_blocking (*block_a, required_difficulty).is_initialized ();
error = !wallets.node.work_generate_blocking (*block_a, required_difficulty).has_value ();
}
if (!error)
{
@ -1298,12 +1298,12 @@ void nano::wallet::work_cache_blocking (nano::account const & account_a, nano::r
{
auto difficulty (wallets.node.default_difficulty (nano::work_version::work_1));
auto opt_work_l (wallets.node.work_generate_blocking (nano::work_version::work_1, root_a, difficulty, account_a));
if (opt_work_l.is_initialized ())
if (opt_work_l.has_value ())
{
auto transaction_l (wallets.tx_begin_write ());
if (live () && store.exists (transaction_l, account_a))
{
work_update (transaction_l, account_a, root_a, *opt_work_l);
work_update (transaction_l, account_a, root_a, opt_work_l.value ());
}
}
else if (!wallets.node.stopped)

View file

@ -2253,7 +2253,7 @@ void nano_qt::block_creation::create_send ()
details.is_send = true;
details.epoch = info.epoch ();
auto const required_difficulty{ wallet.node.network_params.work.threshold (send.work_version (), details) };
if (wallet.node.work_generate_blocking (send, required_difficulty).is_initialized ())
if (wallet.node.work_generate_blocking (send, required_difficulty).has_value ())
{
std::string block_l;
send.serialize_json (block_l);
@ -2337,7 +2337,7 @@ void nano_qt::block_creation::create_receive ()
details.is_receive = true;
details.epoch = std::max (info.epoch (), pending.epoch);
auto required_difficulty{ wallet.node.network_params.work.threshold (receive.work_version (), details) };
if (wallet.node.work_generate_blocking (receive, required_difficulty).is_initialized ())
if (wallet.node.work_generate_blocking (receive, required_difficulty).has_value ())
{
std::string block_l;
receive.serialize_json (block_l);
@ -2420,7 +2420,7 @@ void nano_qt::block_creation::create_change ()
nano::block_details details;
details.epoch = info.epoch ();
auto const required_difficulty{ wallet.node.network_params.work.threshold (change.work_version (), details) };
if (wallet.node.work_generate_blocking (change, required_difficulty).is_initialized ())
if (wallet.node.work_generate_blocking (change, required_difficulty).has_value ())
{
std::string block_l;
change.serialize_json (block_l);
@ -2502,7 +2502,7 @@ void nano_qt::block_creation::create_open ()
details.is_receive = true;
details.epoch = pending.epoch;
auto const required_difficulty{ wallet.node.network_params.work.threshold (open.work_version (), details) };
if (wallet.node.work_generate_blocking (open, required_difficulty).is_initialized ())
if (wallet.node.work_generate_blocking (open, required_difficulty).has_value ())
{
std::string block_l;
open.serialize_json (block_l);

View file

@ -2088,9 +2088,9 @@ TEST (rpc, work_peer_bad)
auto const rpc_ctx = add_rpc (system, node1);
nano::block_hash hash1 (1);
std::atomic<uint64_t> work (0);
node2.work_generate (nano::work_version::work_1, hash1, node2.network_params.work.base, [&work] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
work = *work_a;
node2.work_generate (nano::work_version::work_1, hash1, node2.network_params.work.base, [&work] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a.value ();
});
ASSERT_TIMELY (5s, nano::dev::network_params.work.difficulty (nano::work_version::work_1, hash1, work) >= nano::dev::network_params.work.threshold_base (nano::work_version::work_1));
}
@ -2107,9 +2107,9 @@ TEST (rpc, DISABLED_work_peer_one)
node2.config.work_peers.emplace_back (node1->network.endpoint ().address ().to_string (), rpc_ctx.rpc->listening_port ());
nano::keypair key1;
std::atomic<uint64_t> work (0);
node2.work_generate (nano::work_version::work_1, key1.pub, node1->network_params.work.base, [&work] (boost::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.is_initialized ());
work = *work_a;
node2.work_generate (nano::work_version::work_1, key1.pub, node1->network_params.work.base, [&work] (std::optional<uint64_t> work_a) {
ASSERT_TRUE (work_a.has_value ());
work = work_a.value ();
});
ASSERT_TIMELY (5s, nano::dev::network_params.work.difficulty (nano::work_version::work_1, key1.pub, work) >= nano::dev::network_params.work.threshold_base (nano::work_version::work_1));
}
@ -2138,7 +2138,7 @@ TEST (rpc, DISABLED_work_peer_many)
for (auto & work : works)
{
nano::keypair key1;
node1.work_generate (nano::work_version::work_1, key1.pub, node1.network_params.work.base, [&work] (boost::optional<uint64_t> work_a) {
node1.work_generate (nano::work_version::work_1, key1.pub, node1.network_params.work.base, [&work] (std::optional<uint64_t> work_a) {
work = *work_a;
});
while (nano::dev::network_params.work.difficulty (nano::work_version::work_1, key1.pub, work) < nano::dev::network_params.work.threshold_base (nano::work_version::work_1))