Work version concept (#2569)
* Work version concept Adds nano::work_version which is passed to all work_generate and work_validate methods (except for tests, ensured with an assert). The functional changes are quite minimal, as every caller defaults to the only work version available (work_1): - RPC work_generate, work_validate and block_create can receive an optional "work_version" - The work websocket outputs the work version These changes constitute the pipeline necessary for conditional work validation. * Use nano::to_string to match the work version text
This commit is contained in:
parent
e0fe3fca69
commit
eb5febfdf3
34 changed files with 352 additions and 156 deletions
|
|
@ -534,8 +534,8 @@ TEST (active_transactions, update_difficulty)
|
|||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
// Update work with higher difficulty
|
||||
auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1, boost::none);
|
||||
auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1, boost::none);
|
||||
auto work1 = node1.work_generate_blocking (send1->root (), difficulty1 + 1);
|
||||
auto work2 = node1.work_generate_blocking (send2->root (), difficulty2 + 1);
|
||||
|
||||
std::error_code ec;
|
||||
nano::state_block_builder builder;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ TEST (distributed_work, stopped)
|
|||
{
|
||||
nano::system system (1);
|
||||
system.nodes[0]->distributed_work.stop ();
|
||||
ASSERT_TRUE (system.nodes[0]->distributed_work.make (nano::block_hash (), {}, {}, nano::network_constants::publish_test_threshold));
|
||||
ASSERT_TRUE (system.nodes[0]->distributed_work.make (nano::work_version::work_1, nano::block_hash (), {}, {}, nano::network_constants::publish_test_threshold));
|
||||
}
|
||||
|
||||
TEST (distributed_work, no_peers)
|
||||
|
|
@ -25,7 +25,7 @@ TEST (distributed_work, no_peers)
|
|||
work = work_a;
|
||||
done = true;
|
||||
};
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, node->config.work_peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, node->config.work_peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (!done)
|
||||
{
|
||||
|
|
@ -47,7 +47,7 @@ TEST (distributed_work, no_peers_disabled)
|
|||
nano::node_config node_config (nano::get_available_port (), system.logging);
|
||||
node_config.work_threads = 0;
|
||||
auto & node = *system.add_node (node_config);
|
||||
ASSERT_TRUE (node.distributed_work.make (nano::block_hash (), node.config.work_peers, {}, nano::network_constants::publish_test_threshold));
|
||||
ASSERT_TRUE (node.distributed_work.make (nano::work_version::work_1, nano::block_hash (), node.config.work_peers, {}, nano::network_constants::publish_test_threshold));
|
||||
}
|
||||
|
||||
TEST (distributed_work, no_peers_cancel)
|
||||
|
|
@ -63,7 +63,7 @@ TEST (distributed_work, no_peers_cancel)
|
|||
ASSERT_FALSE (work_a.is_initialized ());
|
||||
done = true;
|
||||
};
|
||||
ASSERT_FALSE (node.distributed_work.make (hash, node.config.work_peers, callback_to_cancel, nano::difficulty::from_multiplier (1e6, node.network_params.network.publish_threshold)));
|
||||
ASSERT_FALSE (node.distributed_work.make (nano::work_version::work_1, hash, node.config.work_peers, callback_to_cancel, nano::difficulty::from_multiplier (1e6, node.network_params.network.publish_threshold)));
|
||||
ASSERT_EQ (1, node.distributed_work.items.size ());
|
||||
// cleanup should not cancel or remove an ongoing work
|
||||
node.distributed_work.cleanup_finished ();
|
||||
|
|
@ -79,7 +79,7 @@ TEST (distributed_work, no_peers_cancel)
|
|||
|
||||
// now using observer
|
||||
done = false;
|
||||
ASSERT_FALSE (node.distributed_work.make (hash, node.config.work_peers, callback_to_cancel, nano::difficulty::from_multiplier (1e6, node.network_params.network.publish_threshold)));
|
||||
ASSERT_FALSE (node.distributed_work.make (nano::work_version::work_1, hash, node.config.work_peers, callback_to_cancel, nano::difficulty::from_multiplier (1e6, node.network_params.network.publish_threshold)));
|
||||
ASSERT_EQ (1, node.distributed_work.items.size ());
|
||||
node.observers.work_cancel.notify (hash);
|
||||
system.deadline_set (20s);
|
||||
|
|
@ -103,7 +103,7 @@ TEST (distributed_work, no_peers_multi)
|
|||
// Test many works for the same root
|
||||
for (unsigned i{ 0 }; i < total; ++i)
|
||||
{
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, node->config.work_peers, callback, nano::difficulty::from_multiplier (10, node->network_params.network.publish_threshold)));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, node->config.work_peers, callback, nano::difficulty::from_multiplier (10, node->network_params.network.publish_threshold)));
|
||||
}
|
||||
// 1 root, and _total_ requests for that root are expected, but some may have already finished
|
||||
ASSERT_EQ (1, node->distributed_work.items.size ());
|
||||
|
|
@ -128,7 +128,7 @@ TEST (distributed_work, no_peers_multi)
|
|||
for (unsigned i{ 0 }; i < total; ++i)
|
||||
{
|
||||
nano::block_hash hash_i (i + 1);
|
||||
ASSERT_FALSE (node->distributed_work.make (hash_i, node->config.work_peers, callback, node->network_params.network.publish_threshold));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash_i, node->config.work_peers, callback, node->network_params.network.publish_threshold));
|
||||
}
|
||||
// 10 roots expected with 1 work each, but some may have completed so test for some
|
||||
ASSERT_GT (node->distributed_work.items.size (), 5);
|
||||
|
|
@ -171,7 +171,7 @@ TEST (distributed_work, peer)
|
|||
work_peer->start ();
|
||||
decltype (node->config.work_peers) peers;
|
||||
peers.emplace_back ("::ffff:127.0.0.1", work_peer->port ());
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (!done)
|
||||
{
|
||||
|
|
@ -201,7 +201,7 @@ TEST (distributed_work, peer_malicious)
|
|||
malicious_peer->start ();
|
||||
decltype (node->config.work_peers) peers;
|
||||
peers.emplace_back ("::ffff:127.0.0.1", malicious_peer->port ());
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (!done)
|
||||
{
|
||||
|
|
@ -226,7 +226,7 @@ TEST (distributed_work, peer_malicious)
|
|||
auto malicious_peer2 (std::make_shared<fake_work_peer> (node->work, node->io_ctx, nano::get_available_port (), work_peer_type::malicious));
|
||||
malicious_peer2->start ();
|
||||
peers[0].second = malicious_peer2->port ();
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, peers, nullptr, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, peers, nullptr, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (malicious_peer2->generations_bad < 2)
|
||||
{
|
||||
|
|
@ -259,7 +259,7 @@ TEST (distributed_work, peer_multi)
|
|||
peers.emplace_back ("localhost", malicious_peer->port ());
|
||||
peers.emplace_back ("localhost", slow_peer->port ());
|
||||
peers.emplace_back ("localhost", good_peer->port ());
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (!done)
|
||||
{
|
||||
|
|
@ -298,7 +298,7 @@ TEST (distributed_work, fail_resolve)
|
|||
};
|
||||
decltype (node->config.work_peers) peers;
|
||||
peers.emplace_back ("beeb.boop.123z", 0);
|
||||
ASSERT_FALSE (node->distributed_work.make (hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
ASSERT_FALSE (node->distributed_work.make (nano::work_version::work_1, hash, peers, callback, node->network_params.network.publish_threshold, nano::account ()));
|
||||
system.deadline_set (5s);
|
||||
while (!done)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1190,7 +1190,7 @@ TEST (wallet, work_watcher_generation_disabled)
|
|||
auto block (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - nano::Mxrb_ratio, key.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *pool.generate (genesis.hash ())));
|
||||
uint64_t difficulty (0);
|
||||
ASSERT_FALSE (nano::work_validate (*block, &difficulty));
|
||||
node.wallets.watcher->add (block);
|
||||
node.wallets.watcher->add (block, nano::work_version::work_1);
|
||||
ASSERT_FALSE (node.process_local (block).code != nano::process_result::progress);
|
||||
ASSERT_TRUE (node.wallets.watcher->is_watched (block->qualified_root ()));
|
||||
auto multiplier = nano::difficulty::to_multiplier (difficulty, node.network_params.network.publish_threshold);
|
||||
|
|
|
|||
|
|
@ -677,6 +677,7 @@ TEST (websocket, work)
|
|||
|
||||
ASSERT_EQ (1, contents.count ("request"));
|
||||
auto & request = contents.get_child ("request");
|
||||
ASSERT_EQ (request.get<std::string> ("version"), nano::to_string (nano::work_version::work_1));
|
||||
ASSERT_EQ (request.get<std::string> ("hash"), hash.to_string ());
|
||||
ASSERT_EQ (request.get<std::string> ("difficulty"), nano::to_string_hex (node1->network_params.network.publish_threshold));
|
||||
ASSERT_EQ (request.get<double> ("multiplier"), 1.0);
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ TEST (work, opencl)
|
|||
if (opencl != nullptr)
|
||||
{
|
||||
// 0 threads, should add 1 for managing OpenCL
|
||||
nano::work_pool pool (0, std::chrono::nanoseconds (0), [&opencl](nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
nano::work_pool pool (0, std::chrono::nanoseconds (0), [&opencl](nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
|
||||
return opencl->generate_work (version_a, root_a, difficulty_a);
|
||||
});
|
||||
ASSERT_NE (nullptr, pool.opencl);
|
||||
nano::root root;
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ std::string nano::error_rpc_messages::message (int ev) const
|
|||
return "Bad source";
|
||||
case nano::error_rpc::bad_timeout:
|
||||
return "Bad timeout number";
|
||||
case nano::error_rpc::bad_work_version:
|
||||
return "Bad work version";
|
||||
case nano::error_rpc::block_create_balance_mismatch:
|
||||
return "Balance mismatch for previous block";
|
||||
case nano::error_rpc::block_create_key_required:
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ enum class error_rpc
|
|||
bad_representative_number,
|
||||
bad_source,
|
||||
bad_timeout,
|
||||
bad_work_version,
|
||||
block_create_balance_mismatch,
|
||||
block_create_key_required,
|
||||
block_create_public_key_mismatch,
|
||||
|
|
|
|||
|
|
@ -6,24 +6,65 @@
|
|||
|
||||
#include <future>
|
||||
|
||||
bool nano::work_validate (nano::root const & root_a, uint64_t work_a, uint64_t * difficulty_a)
|
||||
std::string nano::to_string (nano::work_version const version_a)
|
||||
{
|
||||
static nano::network_constants network_constants;
|
||||
auto value (nano::work_value (root_a, work_a));
|
||||
if (difficulty_a != nullptr)
|
||||
std::string result ("invalid");
|
||||
switch (version_a)
|
||||
{
|
||||
*difficulty_a = value;
|
||||
case nano::work_version::work_1:
|
||||
result = "work_1";
|
||||
break;
|
||||
case nano::work_version::unspecified:
|
||||
result = "unspecified";
|
||||
break;
|
||||
}
|
||||
return value < network_constants.publish_threshold;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nano::work_validate (nano::work_version const version_a, nano::block const & block_a, uint64_t * difficulty_a)
|
||||
{
|
||||
return nano::work_validate (version_a, block_a.root (), block_a.block_work (), difficulty_a);
|
||||
}
|
||||
|
||||
bool nano::work_validate (nano::work_version const version_a, nano::root const & root_a, uint64_t const work_a, uint64_t * difficulty_a)
|
||||
{
|
||||
bool invalid (true);
|
||||
switch (version_a)
|
||||
{
|
||||
case nano::work_version::work_1:
|
||||
invalid = nano::work_v1::validate (root_a, work_a, difficulty_a);
|
||||
break;
|
||||
default:
|
||||
assert (false && "Invalid version specified to work_validate");
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
bool nano::work_validate (nano::block const & block_a, uint64_t * difficulty_a)
|
||||
{
|
||||
return work_validate (block_a.root (), block_a.block_work (), difficulty_a);
|
||||
return nano::work_validate (block_a.root (), block_a.block_work (), difficulty_a);
|
||||
}
|
||||
|
||||
bool nano::work_validate (nano::root const & root_a, uint64_t const work_a, uint64_t * difficulty_a)
|
||||
{
|
||||
static nano::network_constants network_constants;
|
||||
assert (network_constants.is_test_network ());
|
||||
return nano::work_validate (nano::work_version::work_1, root_a, work_a, difficulty_a);
|
||||
}
|
||||
|
||||
bool nano::work_v1::validate (nano::root const & root_a, uint64_t work_a, uint64_t * difficulty_a)
|
||||
{
|
||||
static nano::network_constants network_constants;
|
||||
auto work_value (value (root_a, work_a));
|
||||
if (difficulty_a != nullptr)
|
||||
{
|
||||
*difficulty_a = work_value;
|
||||
}
|
||||
return work_value < network_constants.publish_threshold;
|
||||
}
|
||||
|
||||
#ifndef NANO_FUZZER_TEST
|
||||
uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
|
||||
uint64_t nano::work_v1::value (nano::root const & root_a, uint64_t work_a)
|
||||
{
|
||||
uint64_t result;
|
||||
blake2b_state hash;
|
||||
|
|
@ -34,7 +75,7 @@ uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
|
|||
return result;
|
||||
}
|
||||
#else
|
||||
uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
|
||||
uint64_t nano::work_v1::value (nano::root const & root_a, uint64_t work_a)
|
||||
{
|
||||
static nano::network_constants network_constants;
|
||||
if (!network_constants.is_test_network ())
|
||||
|
|
@ -46,7 +87,7 @@ uint64_t nano::work_value (nano::root const & root_a, uint64_t work_a)
|
|||
}
|
||||
#endif
|
||||
|
||||
nano::work_pool::work_pool (unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> opencl_a) :
|
||||
nano::work_pool::work_pool (unsigned max_threads_a, std::chrono::nanoseconds pow_rate_limiter_a, std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> opencl_a) :
|
||||
ticket (0),
|
||||
done (false),
|
||||
pow_rate_limiter (pow_rate_limiter_a),
|
||||
|
|
@ -108,12 +149,12 @@ void nano::work_pool::loop (uint64_t thread)
|
|||
boost::optional<uint64_t> opt_work;
|
||||
if (thread == 0 && opencl)
|
||||
{
|
||||
opt_work = opencl (current_l.item, current_l.difficulty, ticket);
|
||||
opt_work = opencl (current_l.version, current_l.item, current_l.difficulty, ticket);
|
||||
}
|
||||
if (opt_work.is_initialized ())
|
||||
{
|
||||
work = *opt_work;
|
||||
output = work_value (current_l.item, work);
|
||||
output = nano::work_v1::value (current_l.item, work);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -146,7 +187,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 (current_l.difficulty == 0 || work_value (current_l.item, work) == output);
|
||||
assert (current_l.difficulty == 0 || nano::work_v1::value (current_l.item, work) == output);
|
||||
// Signal other threads to stop their work next time they check ticket
|
||||
++ticket;
|
||||
pending.pop_front ();
|
||||
|
|
@ -206,17 +247,27 @@ void nano::work_pool::stop ()
|
|||
|
||||
void nano::work_pool::generate (nano::root const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a)
|
||||
{
|
||||
generate (root_a, callback_a, network_constants.publish_threshold);
|
||||
generate (nano::work_version::work_1, root_a, callback_a);
|
||||
}
|
||||
|
||||
void nano::work_pool::generate (nano::work_version const version_a, nano::root const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a)
|
||||
{
|
||||
generate (version_a, root_a, callback_a, network_constants.publish_threshold);
|
||||
}
|
||||
|
||||
void nano::work_pool::generate (nano::root const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a, uint64_t difficulty_a)
|
||||
{
|
||||
generate (nano::work_version::work_1, root_a, callback_a, difficulty_a);
|
||||
}
|
||||
|
||||
void nano::work_pool::generate (nano::work_version const version_a, nano::root const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a, uint64_t difficulty_a)
|
||||
{
|
||||
assert (!root_a.is_zero ());
|
||||
if (!threads.empty ())
|
||||
{
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
pending.emplace_back (root_a, callback_a, difficulty_a);
|
||||
pending.emplace_back (version_a, root_a, callback_a, difficulty_a);
|
||||
}
|
||||
producer_condition.notify_all ();
|
||||
}
|
||||
|
|
@ -228,10 +279,24 @@ void nano::work_pool::generate (nano::root const & root_a, std::function<void(bo
|
|||
|
||||
boost::optional<uint64_t> nano::work_pool::generate (nano::root const & root_a)
|
||||
{
|
||||
return generate (root_a, network_constants.publish_threshold);
|
||||
static nano::network_constants network_constants;
|
||||
assert (network_constants.is_test_network ());
|
||||
return generate (nano::work_version::work_1, root_a);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::work_pool::generate (nano::work_version const version_a, nano::root const & root_a)
|
||||
{
|
||||
return generate (version_a, root_a, network_constants.publish_threshold);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::work_pool::generate (nano::root const & root_a, uint64_t difficulty_a)
|
||||
{
|
||||
static nano::network_constants network_constants;
|
||||
assert (network_constants.is_test_network ());
|
||||
return generate (nano::work_version::work_1, root_a, difficulty_a);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::work_pool::generate (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a)
|
||||
{
|
||||
boost::optional<uint64_t> result;
|
||||
if (!threads.empty ())
|
||||
|
|
@ -239,7 +304,7 @@ boost::optional<uint64_t> nano::work_pool::generate (nano::root const & root_a,
|
|||
std::promise<boost::optional<uint64_t>> work;
|
||||
std::future<boost::optional<uint64_t>> future = work.get_future ();
|
||||
generate (
|
||||
root_a, [&work](boost::optional<uint64_t> work_a) {
|
||||
version_a, root_a, [&work](boost::optional<uint64_t> work_a) {
|
||||
work.set_value (work_a);
|
||||
},
|
||||
difficulty_a);
|
||||
|
|
|
|||
|
|
@ -13,20 +13,35 @@
|
|||
|
||||
namespace nano
|
||||
{
|
||||
class block;
|
||||
enum class work_version
|
||||
{
|
||||
unspecified,
|
||||
work_1
|
||||
};
|
||||
std::string to_string (nano::work_version const version_a);
|
||||
|
||||
bool work_validate (nano::root const &, uint64_t, uint64_t * = nullptr);
|
||||
class block;
|
||||
bool work_validate (nano::work_version const, nano::block const &, uint64_t * = nullptr);
|
||||
bool work_validate (nano::work_version const, nano::root const &, uint64_t const, uint64_t * = nullptr);
|
||||
// For tests only
|
||||
bool work_validate (nano::block const &, uint64_t * = nullptr);
|
||||
uint64_t work_value (nano::root const &, uint64_t);
|
||||
// For tests only
|
||||
bool work_validate (nano::root const &, uint64_t const, uint64_t * = nullptr);
|
||||
|
||||
namespace work_v1
|
||||
{
|
||||
bool validate (nano::root const &, uint64_t const, uint64_t * = nullptr);
|
||||
uint64_t value (nano::root const &, uint64_t);
|
||||
}
|
||||
class opencl_work;
|
||||
class work_item final
|
||||
{
|
||||
public:
|
||||
work_item (nano::root const & item_a, std::function<void(boost::optional<uint64_t> const &)> const & callback_a, uint64_t difficulty_a) :
|
||||
item (item_a), callback (callback_a), difficulty (difficulty_a)
|
||||
work_item (nano::work_version const version_a, nano::root const & item_a, std::function<void(boost::optional<uint64_t> const &)> const & callback_a, uint64_t difficulty_a) :
|
||||
version (version_a), item (item_a), callback (callback_a), difficulty (difficulty_a)
|
||||
{
|
||||
}
|
||||
|
||||
nano::work_version version;
|
||||
nano::root item;
|
||||
std::function<void(boost::optional<uint64_t> const &)> callback;
|
||||
uint64_t difficulty;
|
||||
|
|
@ -34,12 +49,18 @@ public:
|
|||
class work_pool final
|
||||
{
|
||||
public:
|
||||
work_pool (unsigned, std::chrono::nanoseconds = std::chrono::nanoseconds (0), std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> = nullptr);
|
||||
work_pool (unsigned, std::chrono::nanoseconds = std::chrono::nanoseconds (0), std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> = nullptr);
|
||||
~work_pool ();
|
||||
void loop (uint64_t);
|
||||
void stop ();
|
||||
void cancel (nano::root const &);
|
||||
void generate (nano::work_version const, nano::root const &, std::function<void(boost::optional<uint64_t> const &)>);
|
||||
void generate (nano::work_version const, nano::root const &, std::function<void(boost::optional<uint64_t> const &)>, uint64_t);
|
||||
boost::optional<uint64_t> generate (nano::work_version const, nano::root const &);
|
||||
boost::optional<uint64_t> generate (nano::work_version const, nano::root const &, uint64_t);
|
||||
// For tests only
|
||||
void generate (nano::root const &, std::function<void(boost::optional<uint64_t> const &)>);
|
||||
// For tests only
|
||||
void generate (nano::root const &, std::function<void(boost::optional<uint64_t> const &)>, uint64_t);
|
||||
boost::optional<uint64_t> generate (nano::root const &);
|
||||
boost::optional<uint64_t> generate (nano::root const &, uint64_t);
|
||||
|
|
@ -52,7 +73,7 @@ public:
|
|||
std::mutex mutex;
|
||||
nano::condition_variable producer_condition;
|
||||
std::chrono::nanoseconds pow_rate_limiter;
|
||||
std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> opencl;
|
||||
std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> opencl;
|
||||
nano::observer_set<bool> work_observers;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ void nano_daemon::daemon::run (boost::filesystem::path const & data_path, nano::
|
|||
nano::logger_mt logger{ config.node.logging.min_time_between_log_output };
|
||||
boost::asio::io_context io_ctx;
|
||||
auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, logger));
|
||||
nano::work_pool opencl_work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
|
||||
return opencl->generate_work (root_a, difficulty_a, ticket_a);
|
||||
nano::work_pool opencl_work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> & ticket_a) {
|
||||
return opencl->generate_work (version_a, root_a, difficulty_a, ticket_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
nano::alarm alarm (io_ctx);
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ int main (int argc, char * const * argv)
|
|||
<< "Account: " << rep.pub.to_account () << "\n";
|
||||
}
|
||||
nano::uint128_t balance (std::numeric_limits<nano::uint128_t>::max ());
|
||||
nano::open_block genesis_block (reinterpret_cast<const nano::block_hash &> (genesis.pub), genesis.pub, genesis.pub, genesis.prv, genesis.pub, *work.generate (genesis.pub));
|
||||
nano::open_block genesis_block (reinterpret_cast<const nano::block_hash &> (genesis.pub), genesis.pub, genesis.pub, genesis.prv, genesis.pub, *work.generate (nano::work_version::work_1, genesis.pub));
|
||||
std::cout << genesis_block.to_json ();
|
||||
std::cout.flush ();
|
||||
nano::block_hash previous (genesis_block.hash ());
|
||||
|
|
@ -205,7 +205,7 @@ int main (int argc, char * const * argv)
|
|||
{
|
||||
assert (balance > weekly_distribution);
|
||||
balance = balance < (weekly_distribution * 2) ? 0 : balance - weekly_distribution;
|
||||
nano::send_block send (previous, landing.pub, balance, genesis.prv, genesis.pub, *work.generate (previous));
|
||||
nano::send_block send (previous, landing.pub, balance, genesis.prv, genesis.pub, *work.generate (nano::work_version::work_1, previous));
|
||||
previous = send.hash ();
|
||||
std::cout << send.to_json ();
|
||||
std::cout.flush ();
|
||||
|
|
@ -321,7 +321,7 @@ int main (int argc, char * const * argv)
|
|||
{
|
||||
block.hashables.previous.qwords[0] += 1;
|
||||
auto begin1 (std::chrono::high_resolution_clock::now ());
|
||||
block.block_work_set (*work.generate (block.root ()));
|
||||
block.block_work_set (*work.generate (nano::work_version::work_1, block.root ()));
|
||||
auto end1 (std::chrono::high_resolution_clock::now ());
|
||||
std::cerr << boost::str (boost::format ("%|1$ 12d|\n") % std::chrono::duration_cast<std::chrono::microseconds> (end1 - begin1).count ());
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ int main (int argc, char * const * argv)
|
|||
uint64_t count{ 10000000U }; // 10M
|
||||
for (uint64_t i (0); i < count; ++i)
|
||||
{
|
||||
valid = nano::work_value (hash, i) > difficulty;
|
||||
valid = nano::work_v1::value (hash, i) > difficulty;
|
||||
}
|
||||
std::ostringstream oss (valid ? "true" : "false"); // IO forces compiler to not dismiss the variable
|
||||
auto total_time (std::chrono::duration_cast<std::chrono::nanoseconds> (std::chrono::steady_clock::now () - start).count ());
|
||||
|
|
@ -419,17 +419,17 @@ int main (int argc, char * const * argv)
|
|||
nano::logger_mt logger;
|
||||
nano::opencl_config config (platform, device, threads);
|
||||
auto opencl (nano::opencl_work::create (true, config, logger));
|
||||
nano::work_pool work_pool (std::numeric_limits<unsigned>::max (), std::chrono::nanoseconds (0), opencl ? [&opencl](nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
nano::work_pool work_pool (std::numeric_limits<unsigned>::max (), std::chrono::nanoseconds (0), opencl ? [&opencl](nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
|
||||
return opencl->generate_work (version_a, root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
nano::change_block block (0, 0, nano::keypair ().prv, 0, 0);
|
||||
std::cerr << boost::str (boost::format ("Starting OpenCL generation profiling. Platform: %1%. Device: %2%. Threads: %3%. Difficulty: %4$#x\n") % platform % device % threads % difficulty);
|
||||
for (uint64_t i (0); true; ++i)
|
||||
{
|
||||
block.hashables.previous.qwords[0] += 1;
|
||||
auto begin1 (std::chrono::high_resolution_clock::now ());
|
||||
block.block_work_set (*work_pool.generate (block.root (), difficulty));
|
||||
block.block_work_set (*work_pool.generate (nano::work_version::work_1, block.root (), difficulty));
|
||||
auto end1 (std::chrono::high_resolution_clock::now ());
|
||||
std::cerr << boost::str (boost::format ("%|1$ 12d|\n") % std::chrono::duration_cast<std::chrono::microseconds> (end1 - begin1).count ());
|
||||
}
|
||||
|
|
@ -738,7 +738,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (genesis_balance)
|
||||
.link (keys[i].pub)
|
||||
.sign (test_params.ledger.test_genesis_key.prv, test_params.ledger.test_genesis_key.pub)
|
||||
.work (*work.generate (genesis_latest))
|
||||
.work (*work.generate (nano::work_version::work_1, genesis_latest))
|
||||
.build ();
|
||||
|
||||
genesis_latest = send->hash ();
|
||||
|
|
@ -751,7 +751,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (balances[i])
|
||||
.link (genesis_latest)
|
||||
.sign (keys[i].prv, keys[i].pub)
|
||||
.work (*work.generate (keys[i].pub))
|
||||
.work (*work.generate (nano::work_version::work_1, keys[i].pub))
|
||||
.build ();
|
||||
|
||||
frontiers[i] = open->hash ();
|
||||
|
|
@ -772,7 +772,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (balances[j])
|
||||
.link (keys[other].pub)
|
||||
.sign (keys[j].prv, keys[j].pub)
|
||||
.work (*work.generate (frontiers[j]))
|
||||
.work (*work.generate (nano::work_version::work_1, frontiers[j]))
|
||||
.build ();
|
||||
|
||||
frontiers[j] = send->hash ();
|
||||
|
|
@ -787,7 +787,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (balances[other])
|
||||
.link (static_cast<nano::block_hash const &> (frontiers[j]))
|
||||
.sign (keys[other].prv, keys[other].pub)
|
||||
.work (*work.generate (frontiers[other]))
|
||||
.work (*work.generate (nano::work_version::work_1, frontiers[other]))
|
||||
.build ();
|
||||
|
||||
frontiers[other] = receive->hash ();
|
||||
|
|
@ -859,7 +859,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (genesis_balance)
|
||||
.link (keys[i].pub)
|
||||
.sign (test_params.ledger.test_genesis_key.prv, test_params.ledger.test_genesis_key.pub)
|
||||
.work (*work.generate (genesis_latest))
|
||||
.work (*work.generate (nano::work_version::work_1, genesis_latest))
|
||||
.build ();
|
||||
|
||||
genesis_latest = send->hash ();
|
||||
|
|
@ -872,7 +872,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (balance)
|
||||
.link (genesis_latest)
|
||||
.sign (keys[i].prv, keys[i].pub)
|
||||
.work (*work.generate (keys[i].pub))
|
||||
.work (*work.generate (nano::work_version::work_1, keys[i].pub))
|
||||
.build ();
|
||||
|
||||
node->ledger.process (transaction, *open);
|
||||
|
|
@ -891,7 +891,7 @@ int main (int argc, char * const * argv)
|
|||
.balance (genesis_balance)
|
||||
.link (destination.pub)
|
||||
.sign (test_params.ledger.test_genesis_key.prv, test_params.ledger.test_genesis_key.pub)
|
||||
.work (*work.generate (genesis_latest))
|
||||
.work (*work.generate (nano::work_version::work_1, genesis_latest))
|
||||
.build ();
|
||||
|
||||
genesis_latest = send->hash ();
|
||||
|
|
@ -1104,7 +1104,7 @@ int main (int argc, char * const * argv)
|
|||
std::cerr << boost::str (boost::format ("Incorrect sideband block details for block %1%\n") % hash.to_string ());
|
||||
}
|
||||
// Check if block work value is correct
|
||||
if (nano::work_validate (*block.get ()))
|
||||
if (nano::work_validate (nano::work_version::work_1, *block))
|
||||
{
|
||||
std::cerr << boost::str (boost::format ("Invalid work for block %1% value: %2%\n") % hash.to_string () % nano::to_string_hex (block->block_work ()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ int run_wallet (QApplication & application, int argc, char * const * argv, boost
|
|||
std::shared_ptr<nano_qt::wallet> gui;
|
||||
nano::set_application_icon (application);
|
||||
auto opencl (nano::opencl_work::create (config.opencl_enable, config.opencl, logger));
|
||||
nano::work_pool work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
|
||||
return opencl->generate_work (root_a, difficulty_a);
|
||||
nano::work_pool work (config.node.work_threads, config.node.pow_sleep_interval, opencl ? [&opencl](nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, std::atomic<int> &) {
|
||||
return opencl->generate_work (version_a, root_a, difficulty_a);
|
||||
}
|
||||
: std::function<boost::optional<uint64_t> (nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
: std::function<boost::optional<uint64_t> (nano::work_version const, nano::root const &, uint64_t, std::atomic<int> &)> (nullptr));
|
||||
nano::alarm alarm (io_ctx);
|
||||
node = std::make_shared<nano::node> (io_ctx, data_path, alarm, config.node, work, flags);
|
||||
if (!node->init_error ())
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ std::pair<std::shared_ptr<nano::election>, bool> nano::active_transactions::inse
|
|||
auto hash (block_a->hash ());
|
||||
result.first = nano::make_shared<nano::election> (node, block_a, skip_delay_a, confirmation_action_a);
|
||||
uint64_t difficulty (0);
|
||||
release_assert (!nano::work_validate (*block_a, &difficulty));
|
||||
release_assert (!nano::work_validate (nano::work_version::work_1, *block_a, &difficulty));
|
||||
roots.get<tag_root> ().emplace (nano::conflict_info{ root, difficulty, difficulty, result.first });
|
||||
blocks.emplace (hash, result.first);
|
||||
adjust_difficulty (hash);
|
||||
|
|
@ -680,7 +680,7 @@ void nano::active_transactions::update_difficulty (std::shared_ptr<nano::block>
|
|||
if (existing_election != roots.get<tag_root> ().end ())
|
||||
{
|
||||
uint64_t difficulty;
|
||||
auto error (nano::work_validate (*block_a, &difficulty));
|
||||
auto error (nano::work_validate (nano::work_version::work_1, *block_a, &difficulty));
|
||||
(void)error;
|
||||
assert (!error);
|
||||
if (difficulty > existing_election->difficulty)
|
||||
|
|
@ -714,7 +714,7 @@ void nano::active_transactions::update_difficulty (std::shared_ptr<nano::block>
|
|||
{
|
||||
uint64_t existing_difficulty;
|
||||
uint64_t new_difficulty;
|
||||
if (!nano::work_validate (*block_a, &new_difficulty) && !nano::work_validate (*existing_block, &existing_difficulty))
|
||||
if (!nano::work_validate (nano::work_version::work_1, *block_a, &new_difficulty) && !nano::work_validate (nano::work_version::work_1, *existing_block, &existing_difficulty))
|
||||
{
|
||||
if (new_difficulty > existing_difficulty)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ void nano::block_processor::add (std::shared_ptr<nano::block> block_a, uint64_t
|
|||
|
||||
void nano::block_processor::add (nano::unchecked_info const & info_a)
|
||||
{
|
||||
if (!nano::work_validate (info_a.block->root (), info_a.block->block_work ()))
|
||||
if (!nano::work_validate (nano::work_version::work_1, info_a.block->root (), info_a.block->block_work ()))
|
||||
{
|
||||
{
|
||||
auto hash (info_a.block->hash ());
|
||||
|
|
@ -375,7 +375,7 @@ void nano::block_processor::process_live (nano::block_hash const & hash_a, std::
|
|||
// Add to work watcher to prevent dropping the election
|
||||
if (watch_work_a)
|
||||
{
|
||||
node.wallets.watcher->add (block_a);
|
||||
node.wallets.watcher->add (block_a, nano::work_version::work_1);
|
||||
}
|
||||
|
||||
// Start collecting quorum on block
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code const & e
|
|||
{
|
||||
nano::bufferstream stream (connection->receive_buffer->data (), size_a);
|
||||
std::shared_ptr<nano::block> block (nano::deserialize_block (stream, type_a));
|
||||
if (block != nullptr && !nano::work_validate (*block))
|
||||
if (block != nullptr && !nano::work_validate (nano::work_version::work_1, *block))
|
||||
{
|
||||
auto hash (block->hash ());
|
||||
if (connection->node->config.logging.bulk_pull_logging ())
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ void nano::bulk_push_server::received_block (boost::system::error_code const & e
|
|||
{
|
||||
nano::bufferstream stream (receive_buffer->data (), size_a);
|
||||
auto block (nano::deserialize_block (stream, type_a));
|
||||
if (block != nullptr && !nano::work_validate (*block))
|
||||
if (block != nullptr && !nano::work_validate (nano::work_version::work_1, *block))
|
||||
{
|
||||
connection->node->process_active (std::move (block));
|
||||
throttled_receive ();
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ void nano::message_parser::deserialize_publish (nano::stream & stream_a, nano::m
|
|||
nano::publish incoming (error, stream_a, header_a, &block_uniquer);
|
||||
if (!error && at_end (stream_a))
|
||||
{
|
||||
if (!nano::work_validate (*incoming.block))
|
||||
if (!nano::work_validate (nano::work_version::work_1, *incoming.block))
|
||||
{
|
||||
visitor.publish (incoming);
|
||||
}
|
||||
|
|
@ -439,7 +439,7 @@ void nano::message_parser::deserialize_confirm_req (nano::stream & stream_a, nan
|
|||
nano::confirm_req incoming (error, stream_a, header_a, &block_uniquer);
|
||||
if (!error && at_end (stream_a))
|
||||
{
|
||||
if (incoming.block == nullptr || !nano::work_validate (*incoming.block))
|
||||
if (incoming.block == nullptr || !nano::work_validate (nano::work_version::work_1, *incoming.block))
|
||||
{
|
||||
visitor.confirm_req (incoming);
|
||||
}
|
||||
|
|
@ -465,7 +465,7 @@ void nano::message_parser::deserialize_confirm_ack (nano::stream & stream_a, nan
|
|||
if (!vote_block.which ())
|
||||
{
|
||||
auto block (boost::get<std::shared_ptr<nano::block>> (vote_block));
|
||||
if (nano::work_validate (*block))
|
||||
if (nano::work_validate (nano::work_version::work_1, *block))
|
||||
{
|
||||
status = parse_status::insufficient_work;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -43,15 +43,15 @@ nano::distributed_work::~distributed_work ()
|
|||
nano::websocket::message_builder builder;
|
||||
if (status == work_generation_status::success)
|
||||
{
|
||||
node_l->websocket_server->broadcast (builder.work_generation (request.root, work_result, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), winner, bad_peers));
|
||||
node_l->websocket_server->broadcast (builder.work_generation (request.version, request.root, work_result, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), winner, bad_peers));
|
||||
}
|
||||
else if (status == work_generation_status::cancelled)
|
||||
{
|
||||
node_l->websocket_server->broadcast (builder.work_cancelled (request.root, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), bad_peers));
|
||||
node_l->websocket_server->broadcast (builder.work_cancelled (request.version, request.root, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), bad_peers));
|
||||
}
|
||||
else if (status == work_generation_status::failure_local || status == work_generation_status::failure_peers)
|
||||
{
|
||||
node_l->websocket_server->broadcast (builder.work_failed (request.root, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), bad_peers));
|
||||
node_l->websocket_server->broadcast (builder.work_failed (request.version, request.root, request.difficulty, node_l->network_params.network.publish_threshold, elapsed.value (), bad_peers));
|
||||
}
|
||||
}
|
||||
stop_once (true);
|
||||
|
|
@ -108,7 +108,7 @@ void nano::distributed_work::start_local ()
|
|||
auto this_l (shared_from_this ());
|
||||
local_generation_started = true;
|
||||
node.work.generate (
|
||||
request.root, [this_l](boost::optional<uint64_t> const & work_a) {
|
||||
request.version, request.root, [this_l](boost::optional<uint64_t> const & work_a) {
|
||||
if (work_a.is_initialized ())
|
||||
{
|
||||
this_l->set_once (*work_a);
|
||||
|
|
@ -242,7 +242,7 @@ void nano::distributed_work::success (std::string const & body_a, nano::tcp_endp
|
|||
if (!nano::from_string_hex (work_text, work))
|
||||
{
|
||||
uint64_t result_difficulty (0);
|
||||
if (!nano::work_validate (request.root, work, &result_difficulty) && result_difficulty >= request.difficulty)
|
||||
if (!nano::work_validate (request.version, request.root, work, &result_difficulty) && result_difficulty >= request.difficulty)
|
||||
{
|
||||
error = false;
|
||||
node.unresponsive_work_peers = false;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <nano/boost/beast/http/string_body.hpp>
|
||||
#include <nano/lib/numbers.hpp>
|
||||
#include <nano/lib/timer.hpp>
|
||||
#include <nano/lib/work.hpp>
|
||||
#include <nano/node/common.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
|
@ -28,6 +29,7 @@ class node;
|
|||
|
||||
struct work_request final
|
||||
{
|
||||
nano::work_version version;
|
||||
nano::root root;
|
||||
uint64_t difficulty;
|
||||
boost::optional<nano::account> const account;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ nano::distributed_work_factory::~distributed_work_factory ()
|
|||
stop ();
|
||||
}
|
||||
|
||||
bool nano::distributed_work_factory::make (nano::root const & root_a, std::vector<std::pair<std::string, uint16_t>> const & peers_a, std::function<void(boost::optional<uint64_t>)> const & callback_a, uint64_t difficulty_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, std::function<void(boost::optional<uint64_t>)> const & callback_a, uint64_t difficulty_a, boost::optional<nano::account> const & account_a)
|
||||
{
|
||||
return make (std::chrono::seconds (1), nano::work_request{ root_a, difficulty_a, account_a, callback_a, peers_a });
|
||||
return make (std::chrono::seconds (1), nano::work_request{ version_a, root_a, difficulty_a, account_a, callback_a, peers_a });
|
||||
}
|
||||
|
||||
bool nano::distributed_work_factory::make (std::chrono::seconds const & backoff_a, nano::work_request const & request_a)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class distributed_work_factory final
|
|||
public:
|
||||
distributed_work_factory (nano::node &);
|
||||
~distributed_work_factory ();
|
||||
bool make (nano::root const &, std::vector<std::pair<std::string, uint16_t>> const &, std::function<void(boost::optional<uint64_t>)> const &, uint64_t, 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 &, std::function<void(boost::optional<uint64_t>)> const &, uint64_t, boost::optional<nano::account> const & = boost::none);
|
||||
bool make (std::chrono::seconds const &, nano::work_request const &);
|
||||
void cancel (nano::root const &, bool const local_stop = false);
|
||||
void cleanup_finished ();
|
||||
|
|
|
|||
|
|
@ -375,6 +375,24 @@ double nano::json_handler::multiplier_optional_impl (uint64_t & difficulty)
|
|||
return multiplier;
|
||||
}
|
||||
|
||||
nano::work_version nano::json_handler::work_version_optional_impl (nano::work_version const default_a)
|
||||
{
|
||||
nano::work_version result = default_a;
|
||||
boost::optional<std::string> version_text (request.get_optional<std::string> ("version"));
|
||||
if (!ec && version_text.is_initialized ())
|
||||
{
|
||||
if (*version_text == nano::to_string (nano::work_version::work_1))
|
||||
{
|
||||
result = nano::work_version::work_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_rpc::bad_work_version;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool decode_unsigned (std::string const & text, uint64_t & number)
|
||||
|
|
@ -697,7 +715,7 @@ void nano::json_handler::account_representative_set ()
|
|||
auto info (rpc_l->account_info_impl (block_transaction, account));
|
||||
if (!rpc_l->ec)
|
||||
{
|
||||
if (nano::work_validate (info.head, work))
|
||||
if (nano::work_validate (nano::work_version::work_1, info.head, work))
|
||||
{
|
||||
rpc_l->ec = nano::error_common::invalid_work;
|
||||
}
|
||||
|
|
@ -1277,6 +1295,8 @@ void nano::json_handler::block_create ()
|
|||
}
|
||||
}
|
||||
auto work (work_optional_impl ());
|
||||
// Default to work_1 if not specified
|
||||
auto work_version (work_version_optional_impl (nano::work_version::work_1));
|
||||
nano::raw_key prv;
|
||||
prv.data.clear ();
|
||||
nano::block_hash previous (0);
|
||||
|
|
@ -1542,7 +1562,7 @@ void nano::json_handler::block_create ()
|
|||
{
|
||||
if (work == 0)
|
||||
{
|
||||
node.work_generate (root_l, get_callback_l (block_l), nano::account (pub));
|
||||
node.work_generate (work_version, root_l, get_callback_l (block_l), nano::account (pub));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2103,10 +2123,10 @@ void epoch_upgrader (std::shared_ptr<nano::node> node_a, nano::private_key const
|
|||
.balance (info.balance)
|
||||
.link (link)
|
||||
.sign (raw_key, signer)
|
||||
.work (node_a->work_generate_blocking (info.head).value_or (0))
|
||||
.work (node_a->work_generate_blocking (nano::work_version::work_1, info.head).value_or (0))
|
||||
.build ();
|
||||
bool valid_signature (!nano::validate_message (signer, epoch->hash (), epoch->block_signature ()));
|
||||
bool valid_work (!nano::work_validate (*epoch.get ()));
|
||||
bool valid_work (!nano::work_validate (nano::work_version::work_1, *epoch.get ()));
|
||||
nano::process_result result (nano::process_result::old);
|
||||
if (valid_signature && valid_work)
|
||||
{
|
||||
|
|
@ -2162,10 +2182,10 @@ void epoch_upgrader (std::shared_ptr<nano::node> node_a, nano::private_key const
|
|||
.balance (0)
|
||||
.link (link)
|
||||
.sign (raw_key, signer)
|
||||
.work (node_a->work_generate_blocking (key.account).value_or (0))
|
||||
.work (node_a->work_generate_blocking (nano::work_version::work_1, key.account).value_or (0))
|
||||
.build ();
|
||||
bool valid_signature (!nano::validate_message (signer, epoch->hash (), epoch->block_signature ()));
|
||||
bool valid_work (!nano::work_validate (*epoch.get ()));
|
||||
bool valid_work (!nano::work_validate (nano::work_version::work_1, *epoch.get ()));
|
||||
nano::process_result result (nano::process_result::old);
|
||||
if (valid_signature && valid_work)
|
||||
{
|
||||
|
|
@ -3232,7 +3252,7 @@ void nano::json_handler::process ()
|
|||
}
|
||||
if (!rpc_l->ec)
|
||||
{
|
||||
if (!nano::work_validate (*block))
|
||||
if (!nano::work_validate (nano::work_version::work_1, *block))
|
||||
{
|
||||
auto result (rpc_l->node.process_local (block, watch_work_l));
|
||||
switch (result.code)
|
||||
|
|
@ -3345,7 +3365,7 @@ void nano::json_handler::receive ()
|
|||
{
|
||||
head = account;
|
||||
}
|
||||
if (nano::work_validate (head, work))
|
||||
if (nano::work_validate (nano::work_version::work_1, head, work))
|
||||
{
|
||||
ec = nano::error_common::invalid_work;
|
||||
}
|
||||
|
|
@ -3688,7 +3708,7 @@ void nano::json_handler::send ()
|
|||
}
|
||||
if (!ec && work)
|
||||
{
|
||||
if (nano::work_validate (info.head, work))
|
||||
if (nano::work_validate (nano::work_version::work_1, info.head, work))
|
||||
{
|
||||
ec = nano::error_common::invalid_work;
|
||||
}
|
||||
|
|
@ -4895,7 +4915,9 @@ void nano::json_handler::work_generate ()
|
|||
{
|
||||
boost::optional<nano::account> account;
|
||||
auto account_opt (request.get_optional<std::string> ("account"));
|
||||
if (account_opt.is_initialized ())
|
||||
// Default to work_1 if not specified
|
||||
auto work_version (work_version_optional_impl (nano::work_version::work_1));
|
||||
if (!ec && account_opt.is_initialized ())
|
||||
{
|
||||
account = account_impl (account_opt.get ());
|
||||
}
|
||||
|
|
@ -4912,7 +4934,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, this](boost::optional<uint64_t> const & work_a) {
|
||||
auto callback = [rpc_l, hash, work_version, this](boost::optional<uint64_t> const & work_a) {
|
||||
if (work_a)
|
||||
{
|
||||
boost::property_tree::ptree response_l;
|
||||
|
|
@ -4921,7 +4943,7 @@ void nano::json_handler::work_generate ()
|
|||
response_l.put ("work", nano::to_string_hex (work));
|
||||
std::stringstream ostream;
|
||||
uint64_t result_difficulty;
|
||||
nano::work_validate (hash, work, &result_difficulty);
|
||||
nano::work_validate (work_version, hash, work, &result_difficulty);
|
||||
response_l.put ("difficulty", nano::to_string_hex (result_difficulty));
|
||||
auto result_multiplier = nano::difficulty::to_multiplier (result_difficulty, this->node.network_params.network.publish_threshold);
|
||||
response_l.put ("multiplier", nano::to_string (result_multiplier));
|
||||
|
|
@ -4937,7 +4959,7 @@ void nano::json_handler::work_generate ()
|
|||
{
|
||||
if (node.local_work_generation_enabled ())
|
||||
{
|
||||
node.work.generate (hash, callback, difficulty);
|
||||
node.work.generate (work_version, hash, callback, difficulty);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4959,7 +4981,7 @@ void nano::json_handler::work_generate ()
|
|||
auto const & peers_l (secondary_work_peers_l ? node.config.secondary_work_peers : node.config.work_peers);
|
||||
if (node.work_generation_enabled (peers_l))
|
||||
{
|
||||
node.work_generate (hash, callback, difficulty, account, secondary_work_peers_l);
|
||||
node.work_generate (work_version, hash, callback, difficulty, account, secondary_work_peers_l);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5031,10 +5053,12 @@ void nano::json_handler::work_validate ()
|
|||
auto work (work_optional_impl ());
|
||||
auto difficulty (difficulty_optional_impl ());
|
||||
multiplier_optional_impl (difficulty);
|
||||
// Default to work_1 if not specified
|
||||
auto work_version (work_version_optional_impl (nano::work_version::work_1));
|
||||
if (!ec)
|
||||
{
|
||||
uint64_t result_difficulty (0);
|
||||
nano::work_validate (hash, work, &result_difficulty);
|
||||
nano::work_validate (work_version, hash, work, &result_difficulty);
|
||||
response_l.put ("valid", (result_difficulty >= difficulty) ? "1" : "0");
|
||||
response_l.put ("difficulty", nano::to_string_hex (result_difficulty));
|
||||
auto result_multiplier = nano::difficulty::to_multiplier (result_difficulty, node.network_params.network.publish_threshold);
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ public:
|
|||
uint64_t offset_optional_impl (uint64_t = 0);
|
||||
uint64_t difficulty_optional_impl ();
|
||||
double multiplier_optional_impl (uint64_t &);
|
||||
nano::work_version work_version_optional_impl (nano::work_version const default_a);
|
||||
bool enable_sign_hash{ false };
|
||||
std::function<void()> stop_callback;
|
||||
nano::node_rpc_config const & node_rpc_config;
|
||||
|
|
|
|||
|
|
@ -1006,14 +1006,14 @@ 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)
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version const version_a, nano::block & block_a)
|
||||
{
|
||||
return work_generate_blocking (block_a, network_params.network.publish_threshold);
|
||||
return work_generate_blocking (version_a, block_a, network_params.network.publish_threshold);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a)
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version const version_a, nano::block & block_a, uint64_t difficulty_a)
|
||||
{
|
||||
auto opt_work_l (work_generate_blocking (block_a.root (), difficulty_a, block_a.account ()));
|
||||
auto opt_work_l (work_generate_blocking (version_a, block_a.root (), difficulty_a, block_a.account ()));
|
||||
if (opt_work_l.is_initialized ())
|
||||
{
|
||||
block_a.block_work_set (*opt_work_l);
|
||||
|
|
@ -1021,37 +1021,61 @@ boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & bloc
|
|||
return opt_work_l;
|
||||
}
|
||||
|
||||
void nano::node::work_generate (nano::root const & root_a, std::function<void(boost::optional<uint64_t>)> callback_a, boost::optional<nano::account> const & account_a)
|
||||
void nano::node::work_generate (nano::work_version const version_a, nano::root const & root_a, std::function<void(boost::optional<uint64_t>)> callback_a, boost::optional<nano::account> const & account_a)
|
||||
{
|
||||
work_generate (root_a, callback_a, network_params.network.publish_threshold, account_a);
|
||||
work_generate (version_a, root_a, callback_a, network_params.network.publish_threshold, account_a);
|
||||
}
|
||||
|
||||
void nano::node::work_generate (nano::root const & root_a, std::function<void(boost::optional<uint64_t>)> callback_a, uint64_t difficulty_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, std::function<void(boost::optional<uint64_t>)> callback_a, uint64_t difficulty_a, boost::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 (root_a, peers_l, callback_a, difficulty_a, account_a))
|
||||
if (distributed_work.make (version_a, root_a, peers_l, callback_a, difficulty_a, account_a))
|
||||
{
|
||||
// Error in creating the job (either stopped or work generation is not possible)
|
||||
callback_a (boost::none);
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, boost::optional<nano::account> const & account_a)
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, boost::optional<nano::account> const & account_a)
|
||||
{
|
||||
return work_generate_blocking (root_a, network_params.network.publish_threshold, account_a);
|
||||
return work_generate_blocking (version_a, root_a, network_params.network.publish_threshold, account_a);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a, boost::optional<nano::account> const & account_a)
|
||||
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::promise<boost::optional<uint64_t>> promise;
|
||||
work_generate (
|
||||
root_a, [&promise](boost::optional<uint64_t> opt_work_a) {
|
||||
version_a, root_a, [&promise](boost::optional<uint64_t> opt_work_a) {
|
||||
promise.set_value (opt_work_a);
|
||||
},
|
||||
difficulty_a, account_a);
|
||||
return promise.get_future ().get ();
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a)
|
||||
{
|
||||
assert (network_params.network.is_test_network ());
|
||||
return work_generate_blocking (block_a, network_params.network.publish_threshold);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a)
|
||||
{
|
||||
assert (network_params.network.is_test_network ());
|
||||
return work_generate_blocking (nano::work_version::work_1, block_a, difficulty_a);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a)
|
||||
{
|
||||
assert (network_params.network.is_test_network ());
|
||||
return work_generate_blocking (root_a, network_params.network.publish_threshold);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a)
|
||||
{
|
||||
assert (network_params.network.is_test_network ());
|
||||
return work_generate_blocking (nano::work_version::work_1, root_a, difficulty_a);
|
||||
}
|
||||
|
||||
void nano::node::add_initial_peers ()
|
||||
{
|
||||
auto transaction (store.tx_begin_read ());
|
||||
|
|
|
|||
|
|
@ -129,12 +129,12 @@ 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::block &);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::root const &, uint64_t, boost::optional<nano::account> const & = boost::none);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::root const &, boost::optional<nano::account> const & = boost::none);
|
||||
void work_generate (nano::root const &, std::function<void(boost::optional<uint64_t>)>, uint64_t, boost::optional<nano::account> const & = boost::none, bool const = false);
|
||||
void work_generate (nano::root const &, std::function<void(boost::optional<uint64_t>)>, boost::optional<nano::account> const & = boost::none);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::block &, uint64_t);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::block &);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::root const &, uint64_t, boost::optional<nano::account> const & = boost::none);
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::work_version const, nano::root const &, boost::optional<nano::account> const & = boost::none);
|
||||
void work_generate (nano::work_version const, nano::root const &, std::function<void(boost::optional<uint64_t>)>, uint64_t, boost::optional<nano::account> const & = boost::none, bool const = false);
|
||||
void work_generate (nano::work_version const, nano::root const &, std::function<void(boost::optional<uint64_t>)>, boost::optional<nano::account> const & = boost::none);
|
||||
void add_initial_peers ();
|
||||
void block_confirm (std::shared_ptr<nano::block>);
|
||||
bool block_confirmed_or_being_confirmed (nano::transaction const &, nano::block_hash const &);
|
||||
|
|
@ -195,6 +195,15 @@ public:
|
|||
static double constexpr price_max = 16.0;
|
||||
static double constexpr free_cutoff = 1024.0;
|
||||
|
||||
// For tests only
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::block &, uint64_t);
|
||||
// For tests only
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::block &);
|
||||
// For tests only
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::root const &, uint64_t);
|
||||
// For tests only
|
||||
boost::optional<uint64_t> work_generate_blocking (nano::root const &);
|
||||
|
||||
private:
|
||||
void long_inactivity_cleanup ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -687,13 +687,13 @@ nano::opencl_work::~opencl_work ()
|
|||
}
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::opencl_work::generate_work (nano::root const & root_a, uint64_t const difficulty_a)
|
||||
boost::optional<uint64_t> nano::opencl_work::generate_work (nano::work_version const version_a, nano::root const & root_a, uint64_t const difficulty_a)
|
||||
{
|
||||
std::atomic<int> ticket_l{ 0 };
|
||||
return generate_work (root_a, difficulty_a, ticket_l);
|
||||
return generate_work (version_a, root_a, difficulty_a, ticket_l);
|
||||
}
|
||||
|
||||
boost::optional<uint64_t> nano::opencl_work::generate_work (nano::root const & root_a, uint64_t const difficulty_a, std::atomic<int> & ticket_a)
|
||||
boost::optional<uint64_t> nano::opencl_work::generate_work (nano::work_version const version_a, nano::root const & root_a, uint64_t const difficulty_a, std::atomic<int> & ticket_a)
|
||||
{
|
||||
nano::lock_guard<std::mutex> lock (mutex);
|
||||
bool error (false);
|
||||
|
|
@ -702,7 +702,7 @@ boost::optional<uint64_t> nano::opencl_work::generate_work (nano::root const & r
|
|||
uint64_t computed_difficulty (0);
|
||||
unsigned thread_count (config.threads);
|
||||
size_t work_size[] = { thread_count, 0, 0 };
|
||||
while ((nano::work_validate (root_a, result, &computed_difficulty) || computed_difficulty < difficulty_a) && !error && ticket_a == ticket_l)
|
||||
while ((nano::work_validate (version_a, root_a, result, &computed_difficulty) || computed_difficulty < difficulty_a) && !error && ticket_a == ticket_l)
|
||||
{
|
||||
result = rand.next ();
|
||||
cl_int write_error1 = clEnqueueWriteBuffer (queue, attempt_buffer, false, 0, sizeof (uint64_t), &result, 0, nullptr, nullptr);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/work.hpp>
|
||||
#include <nano/node/openclconfig.hpp>
|
||||
#include <nano/node/xorshift.hpp>
|
||||
|
||||
|
|
@ -40,8 +41,8 @@ class opencl_work
|
|||
public:
|
||||
opencl_work (bool &, nano::opencl_config const &, nano::opencl_environment &, nano::logger_mt &);
|
||||
~opencl_work ();
|
||||
boost::optional<uint64_t> generate_work (nano::root const &, uint64_t const);
|
||||
boost::optional<uint64_t> generate_work (nano::root const &, uint64_t const, std::atomic<int> &);
|
||||
boost::optional<uint64_t> generate_work (nano::work_version const, nano::root const &, uint64_t const);
|
||||
boost::optional<uint64_t> generate_work (nano::work_version const, nano::root const &, uint64_t const, std::atomic<int> &);
|
||||
static std::unique_ptr<opencl_work> create (bool, nano::opencl_config const &, nano::logger_mt &);
|
||||
nano::opencl_config const & config;
|
||||
std::mutex mutex;
|
||||
|
|
|
|||
|
|
@ -1134,10 +1134,10 @@ bool nano::wallet::action_complete (std::shared_ptr<nano::block> const & block_a
|
|||
bool error{ false };
|
||||
if (block_a != nullptr)
|
||||
{
|
||||
if (nano::work_validate (*block_a))
|
||||
if (nano::work_validate (nano::work_version::work_1, *block_a))
|
||||
{
|
||||
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 ()));
|
||||
error = !wallets.node.work_generate_blocking (*block_a, wallets.node.active.limited_active_difficulty ()).is_initialized ();
|
||||
error = !wallets.node.work_generate_blocking (nano::work_version::work_1, *block_a, wallets.node.active.limited_active_difficulty ()).is_initialized ();
|
||||
}
|
||||
if (!error)
|
||||
{
|
||||
|
|
@ -1217,7 +1217,7 @@ void nano::wallet::send_async (nano::account const & source_a, nano::account con
|
|||
// Update work for account if latest root is root_a
|
||||
void nano::wallet::work_update (nano::transaction const & transaction_a, nano::account const & account_a, nano::root const & root_a, uint64_t work_a)
|
||||
{
|
||||
assert (!nano::work_validate (root_a, work_a));
|
||||
assert (!nano::work_validate (nano::work_version::work_1, root_a, work_a));
|
||||
assert (store.exists (transaction_a, account_a));
|
||||
auto block_transaction (wallets.node.store.tx_begin_read ());
|
||||
auto latest (wallets.node.ledger.latest_root (block_transaction, account_a));
|
||||
|
|
@ -1364,7 +1364,7 @@ void nano::wallet::work_cache_blocking (nano::account const & account_a, nano::r
|
|||
{
|
||||
if (wallets.node.work_generation_enabled ())
|
||||
{
|
||||
auto opt_work_l (wallets.node.work_generate_blocking (root_a, account_a));
|
||||
auto opt_work_l (wallets.node.work_generate_blocking (nano::work_version::work_1, root_a, account_a));
|
||||
if (opt_work_l.is_initialized ())
|
||||
{
|
||||
auto transaction_l (wallets.tx_begin_write ());
|
||||
|
|
@ -1401,7 +1401,7 @@ void nano::work_watcher::stop ()
|
|||
stopped = true;
|
||||
}
|
||||
|
||||
void nano::work_watcher::add (std::shared_ptr<nano::block> block_a)
|
||||
void nano::work_watcher::add (std::shared_ptr<nano::block> block_a, nano::work_version const work_version_a)
|
||||
{
|
||||
auto block_l (std::dynamic_pointer_cast<nano::state_block> (block_a));
|
||||
if (!stopped && block_l != nullptr)
|
||||
|
|
@ -1410,7 +1410,7 @@ void nano::work_watcher::add (std::shared_ptr<nano::block> block_a)
|
|||
nano::unique_lock<std::mutex> lock (mutex);
|
||||
watched[root_l] = block_l;
|
||||
lock.unlock ();
|
||||
watching (root_l, block_l);
|
||||
watching (work_version_a, root_l, block_l);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1420,10 +1420,10 @@ void nano::work_watcher::update (nano::qualified_root const & root_a, std::share
|
|||
watched[root_a] = block_a;
|
||||
}
|
||||
|
||||
void nano::work_watcher::watching (nano::qualified_root const & root_a, std::shared_ptr<nano::state_block> block_a)
|
||||
void nano::work_watcher::watching (nano::work_version const version_a, nano::qualified_root const & root_a, std::shared_ptr<nano::state_block> block_a)
|
||||
{
|
||||
std::weak_ptr<nano::work_watcher> watcher_w (shared_from_this ());
|
||||
node.alarm.add (std::chrono::steady_clock::now () + node.config.work_watcher_period, [block_a, root_a, watcher_w]() {
|
||||
node.alarm.add (std::chrono::steady_clock::now () + node.config.work_watcher_period, [block_a, version_a, root_a, watcher_w]() {
|
||||
auto watcher_l = watcher_w.lock ();
|
||||
if (watcher_l && !watcher_l->stopped && block_a != nullptr)
|
||||
{
|
||||
|
|
@ -1433,7 +1433,7 @@ void nano::work_watcher::watching (nano::qualified_root const & root_a, std::sha
|
|||
lock.unlock ();
|
||||
uint64_t difficulty (0);
|
||||
auto root_l (block_a->root ());
|
||||
nano::work_validate (root_l, block_a->block_work (), &difficulty);
|
||||
nano::work_validate (version_a, root_l, block_a->block_work (), &difficulty);
|
||||
auto active_difficulty (watcher_l->node.active.limited_active_difficulty ());
|
||||
/*
|
||||
* Work watcher should still watch blocks even without work generation, although no rework is done
|
||||
|
|
@ -1442,7 +1442,7 @@ void nano::work_watcher::watching (nano::qualified_root const & root_a, std::sha
|
|||
if (active_difficulty > difficulty && watcher_l->node.work_generation_enabled ())
|
||||
{
|
||||
watcher_l->node.work_generate (
|
||||
root_l, [watcher_l, block_a, root_a](boost::optional<uint64_t> work_a) {
|
||||
version_a, root_l, [watcher_l, block_a, version_a, root_a](boost::optional<uint64_t> work_a) {
|
||||
if (block_a != nullptr && watcher_l != nullptr && !watcher_l->stopped)
|
||||
{
|
||||
bool updated_l{ false };
|
||||
|
|
@ -1457,12 +1457,12 @@ void nano::work_watcher::watching (nano::qualified_root const & root_a, std::sha
|
|||
watcher_l->node.active.update_difficulty (block);
|
||||
watcher_l->update (root_a, block);
|
||||
updated_l = true;
|
||||
watcher_l->watching (root_a, block);
|
||||
watcher_l->watching (version_a, root_a, block);
|
||||
}
|
||||
}
|
||||
if (!updated_l)
|
||||
{
|
||||
watcher_l->watching (root_a, block_a);
|
||||
watcher_l->watching (version_a, root_a, block_a);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1470,7 +1470,7 @@ void nano::work_watcher::watching (nano::qualified_root const & root_a, std::sha
|
|||
}
|
||||
else
|
||||
{
|
||||
watcher_l->watching (root_a, block_a);
|
||||
watcher_l->watching (version_a, root_a, block_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <nano/lib/work.hpp>
|
||||
#include <nano/node/lmdb/lmdb.hpp>
|
||||
#include <nano/node/lmdb/wallet_value.hpp>
|
||||
#include <nano/node/openclwork.hpp>
|
||||
|
|
@ -10,7 +11,6 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace nano
|
||||
{
|
||||
class node;
|
||||
|
|
@ -168,9 +168,9 @@ public:
|
|||
work_watcher (nano::node &);
|
||||
~work_watcher ();
|
||||
void stop ();
|
||||
void add (std::shared_ptr<nano::block>);
|
||||
void add (std::shared_ptr<nano::block>, nano::work_version const);
|
||||
void update (nano::qualified_root const &, std::shared_ptr<nano::state_block>);
|
||||
void watching (nano::qualified_root const &, std::shared_ptr<nano::state_block>);
|
||||
void watching (work_version const, nano::qualified_root const &, std::shared_ptr<nano::state_block>);
|
||||
void remove (std::shared_ptr<nano::block>);
|
||||
bool is_watched (nano::qualified_root const &);
|
||||
size_t size ();
|
||||
|
|
|
|||
|
|
@ -773,7 +773,7 @@ nano::websocket::message nano::websocket::message_builder::difficulty_changed (u
|
|||
return message_l;
|
||||
}
|
||||
|
||||
nano::websocket::message nano::websocket::message_builder::work_generation (nano::block_hash const & root_a, uint64_t work_a, uint64_t difficulty_a, uint64_t publish_threshold_a, std::chrono::milliseconds const & duration_a, std::string const & peer_a, std::vector<std::string> const & bad_peers_a, bool completed_a, bool cancelled_a)
|
||||
nano::websocket::message nano::websocket::message_builder::work_generation (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t work_a, uint64_t difficulty_a, uint64_t publish_threshold_a, std::chrono::milliseconds const & duration_a, std::string const & peer_a, std::vector<std::string> const & bad_peers_a, bool completed_a, bool cancelled_a)
|
||||
{
|
||||
nano::websocket::message message_l (nano::websocket::topic::work);
|
||||
set_common_fields (message_l);
|
||||
|
|
@ -785,6 +785,7 @@ nano::websocket::message nano::websocket::message_builder::work_generation (nano
|
|||
work_l.put ("duration", duration_a.count ());
|
||||
|
||||
boost::property_tree::ptree request_l;
|
||||
request_l.put ("version", nano::to_string (version_a));
|
||||
request_l.put ("hash", root_a.to_string ());
|
||||
request_l.put ("difficulty", nano::to_string_hex (difficulty_a));
|
||||
auto request_multiplier_l (nano::difficulty::to_multiplier (difficulty_a, publish_threshold_a));
|
||||
|
|
@ -797,7 +798,7 @@ nano::websocket::message nano::websocket::message_builder::work_generation (nano
|
|||
result_l.put ("source", peer_a);
|
||||
result_l.put ("work", nano::to_string_hex (work_a));
|
||||
uint64_t result_difficulty_l;
|
||||
nano::work_validate (root_a, work_a, &result_difficulty_l);
|
||||
nano::work_validate (version_a, root_a, work_a, &result_difficulty_l);
|
||||
result_l.put ("difficulty", nano::to_string_hex (result_difficulty_l));
|
||||
auto result_multiplier_l (nano::difficulty::to_multiplier (result_difficulty_l, publish_threshold_a));
|
||||
result_l.put ("multiplier", nano::to_string (result_multiplier_l));
|
||||
|
|
@ -817,14 +818,14 @@ nano::websocket::message nano::websocket::message_builder::work_generation (nano
|
|||
return message_l;
|
||||
}
|
||||
|
||||
nano::websocket::message nano::websocket::message_builder::work_cancelled (nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a)
|
||||
nano::websocket::message nano::websocket::message_builder::work_cancelled (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a)
|
||||
{
|
||||
return work_generation (root_a, 0, difficulty_a, publish_threshold_a, duration_a, "", bad_peers_a, false, true);
|
||||
return work_generation (version_a, root_a, 0, difficulty_a, publish_threshold_a, duration_a, "", bad_peers_a, false, true);
|
||||
}
|
||||
|
||||
nano::websocket::message nano::websocket::message_builder::work_failed (nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a)
|
||||
nano::websocket::message nano::websocket::message_builder::work_failed (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a)
|
||||
{
|
||||
return work_generation (root_a, 0, difficulty_a, publish_threshold_a, duration_a, "", bad_peers_a, false, false);
|
||||
return work_generation (version_a, root_a, 0, difficulty_a, publish_threshold_a, duration_a, "", bad_peers_a, false, false);
|
||||
}
|
||||
|
||||
nano::websocket::message nano::websocket::message_builder::bootstrap_started (std::string const & id_a, std::string const & mode_a)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <nano/boost/beast/websocket.hpp>
|
||||
#include <nano/lib/blocks.hpp>
|
||||
#include <nano/lib/numbers.hpp>
|
||||
#include <nano/lib/work.hpp>
|
||||
#include <nano/secure/common.hpp>
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
|
@ -88,9 +89,10 @@ namespace websocket
|
|||
message stopped_election (nano::block_hash const & hash_a);
|
||||
message vote_received (std::shared_ptr<nano::vote> vote_a, nano::vote_code code_a);
|
||||
message difficulty_changed (uint64_t publish_threshold_a, uint64_t difficulty_active_a);
|
||||
message work_generation (nano::block_hash const & root_a, uint64_t const work_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::string const & peer_a, std::vector<std::string> const & bad_peers_a, bool const completed_a = true, bool const cancelled_a = false);
|
||||
message work_cancelled (nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a);
|
||||
message work_failed (nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a);
|
||||
|
||||
message work_generation (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t const work_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::string const & peer_a, std::vector<std::string> const & bad_peers_a, bool const completed_a = true, bool const cancelled_a = false);
|
||||
message work_cancelled (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a);
|
||||
message work_failed (nano::work_version const version_a, nano::block_hash const & root_a, uint64_t const difficulty_a, uint64_t const publish_threshold_a, std::chrono::milliseconds const & duration_a, std::vector<std::string> const & bad_peers_a);
|
||||
message bootstrap_started (std::string const & id_a, std::string const & mode_a);
|
||||
message bootstrap_exited (std::string const & id_a, std::string const & mode_a, std::chrono::steady_clock::time_point const start_time_a, uint64_t const total_blocks_a);
|
||||
|
||||
|
|
|
|||
|
|
@ -2229,7 +2229,7 @@ void nano_qt::block_creation::create_send ()
|
|||
(void)error;
|
||||
assert (!error);
|
||||
nano::state_block send (account_l, info.head, info.representative, balance - amount_l.number (), destination_l, key, account_l, 0);
|
||||
if (wallet.node.work_generate_blocking (send).is_initialized ())
|
||||
if (wallet.node.work_generate_blocking (nano::work_version::work_1, send).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
send.serialize_json (block_l);
|
||||
|
|
@ -2308,7 +2308,7 @@ void nano_qt::block_creation::create_receive ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block receive (pending_key.account, info.head, info.representative, info.balance.number () + pending.amount.number (), source_l, key, pending_key.account, 0);
|
||||
if (wallet.node.work_generate_blocking (receive).is_initialized ())
|
||||
if (wallet.node.work_generate_blocking (nano::work_version::work_1, receive).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
receive.serialize_json (block_l);
|
||||
|
|
@ -2387,7 +2387,7 @@ void nano_qt::block_creation::create_change ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block change (account_l, info.head, representative_l, info.balance, 0, key, account_l, 0);
|
||||
if (wallet.node.work_generate_blocking (change).is_initialized ())
|
||||
if (wallet.node.work_generate_blocking (nano::work_version::work_1, change).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
change.serialize_json (block_l);
|
||||
|
|
@ -2464,7 +2464,7 @@ void nano_qt::block_creation::create_open ()
|
|||
if (!error)
|
||||
{
|
||||
nano::state_block open (pending_key.account, 0, representative_l, pending.amount, source_l, key, pending_key.account, 0);
|
||||
if (wallet.node.work_generate_blocking (open).is_initialized ())
|
||||
if (wallet.node.work_generate_blocking (nano::work_version::work_1, open).is_initialized ())
|
||||
{
|
||||
std::string block_l;
|
||||
open.serialize_json (block_l);
|
||||
|
|
|
|||
|
|
@ -3045,7 +3045,7 @@ TEST (rpc, work_peer_bad)
|
|||
node2.config.work_peers.push_back (std::make_pair (boost::asio::ip::address_v6::any ().to_string (), 0));
|
||||
nano::block_hash hash1 (1);
|
||||
std::atomic<uint64_t> work (0);
|
||||
node2.work_generate (hash1, [&work](boost::optional<uint64_t> work_a) {
|
||||
node2.work_generate (nano::work_version::work_1, hash1, [&work](boost::optional<uint64_t> work_a) {
|
||||
ASSERT_TRUE (work_a.is_initialized ());
|
||||
work = *work_a;
|
||||
});
|
||||
|
|
@ -3075,7 +3075,7 @@ TEST (rpc, work_peer_one)
|
|||
node2.config.work_peers.push_back (std::make_pair (node1.network.endpoint ().address ().to_string (), rpc.config.port));
|
||||
nano::keypair key1;
|
||||
uint64_t work (0);
|
||||
node2.work_generate (key1.pub, [&work](boost::optional<uint64_t> work_a) {
|
||||
node2.work_generate (nano::work_version::work_1, key1.pub, [&work](boost::optional<uint64_t> work_a) {
|
||||
ASSERT_TRUE (work_a.is_initialized ());
|
||||
work = *work_a;
|
||||
});
|
||||
|
|
@ -3122,7 +3122,7 @@ TEST (rpc, work_peer_many)
|
|||
for (auto i (0); i < works.size (); ++i)
|
||||
{
|
||||
nano::keypair key1;
|
||||
node1.work_generate (key1.pub, [& work = works[i]](boost::optional<uint64_t> work_a) {
|
||||
node1.work_generate (nano::work_version::work_1, key1.pub, [& work = works[i]](boost::optional<uint64_t> work_a) {
|
||||
work = *work_a;
|
||||
});
|
||||
while (nano::work_validate (key1.pub, works[i]))
|
||||
|
|
@ -3136,6 +3136,48 @@ TEST (rpc, work_peer_many)
|
|||
node1.stop ();
|
||||
}
|
||||
|
||||
TEST (rpc, work_version_invalid)
|
||||
{
|
||||
nano::system system;
|
||||
auto node = add_ipc_enabled_node (system);
|
||||
scoped_io_thread_name_change scoped_thread_name_io;
|
||||
nano::node_rpc_config node_rpc_config;
|
||||
nano::ipc::ipc_server ipc_server (*node, node_rpc_config);
|
||||
nano::rpc_config rpc_config (nano::get_available_port (), true);
|
||||
rpc_config.rpc_process.ipc_port = node->config.ipc_config.transport_tcp.port;
|
||||
nano::ipc_rpc_processor ipc_rpc_processor (system.io_ctx, rpc_config);
|
||||
nano::rpc rpc (system.io_ctx, rpc_config, ipc_rpc_processor);
|
||||
rpc.start ();
|
||||
nano::block_hash hash (1);
|
||||
boost::property_tree::ptree request;
|
||||
request.put ("action", "work_generate");
|
||||
request.put ("hash", hash.to_string ());
|
||||
request.put ("version", "work_invalid");
|
||||
{
|
||||
test_response response (request, rpc.config.port, system.io_ctx);
|
||||
system.deadline_set (5s);
|
||||
while (response.status == 0)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_EQ (200, response.status);
|
||||
ASSERT_EQ (1, response.json.count ("error"));
|
||||
ASSERT_EQ (std::error_code (nano::error_rpc::bad_work_version).message (), response.json.get<std::string> ("error"));
|
||||
}
|
||||
request.put ("action", "work_validate");
|
||||
{
|
||||
test_response response (request, rpc.config.port, system.io_ctx);
|
||||
system.deadline_set (5s);
|
||||
while (response.status == 0)
|
||||
{
|
||||
ASSERT_NO_ERROR (system.poll ());
|
||||
}
|
||||
ASSERT_EQ (200, response.status);
|
||||
ASSERT_EQ (1, response.json.count ("error"));
|
||||
ASSERT_EQ (std::error_code (nano::error_rpc::bad_work_version).message (), response.json.get<std::string> ("error"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST (rpc, block_count)
|
||||
{
|
||||
{
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ nano::uint128_t nano::ledger::account_pending (nano::transaction const & transac
|
|||
|
||||
nano::process_return nano::ledger::process (nano::write_transaction const & transaction_a, nano::block const & block_a, nano::signature_verification verification)
|
||||
{
|
||||
assert (!nano::work_validate (block_a));
|
||||
assert (!nano::work_validate (nano::work_version::work_1, block_a));
|
||||
ledger_processor processor (*this, transaction_a, verification);
|
||||
block_a.visit (processor);
|
||||
if (processor.result.code == nano::process_result::progress)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue