* Remove json config code This improves compile/test times a bit. The json->toml upgrade paths are removed as well. In the unlikely case someone needs to upgrade from v19.x and earlier, the solution is to run a v2x node (prior to this change) to perform the upgrade. Closes #3530 * Remove stat_config json deserialization as well * Remove stat_config header's deserialize_json and jsonconfig::read_and_update
179 lines
6.8 KiB
C++
179 lines
6.8 KiB
C++
#include <nano/crypto_lib/random_pool.hpp>
|
|
#include <nano/lib/blocks.hpp>
|
|
#include <nano/lib/logger_mt.hpp>
|
|
#include <nano/lib/timer.hpp>
|
|
#include <nano/lib/work.hpp>
|
|
#include <nano/node/logging.hpp>
|
|
#include <nano/node/openclconfig.hpp>
|
|
#include <nano/node/openclwork.hpp>
|
|
#include <nano/secure/common.hpp>
|
|
#include <nano/secure/utility.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <future>
|
|
|
|
TEST (work, one)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
|
|
nano::change_block block (1, 1, nano::keypair ().prv, 3, 4);
|
|
block.block_work_set (*pool.generate (block.root ()));
|
|
ASSERT_LT (nano::dev::network_params.work.threshold_base (block.work_version ()), nano::dev::network_params.work.difficulty (block));
|
|
}
|
|
|
|
TEST (work, disabled)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, 0 };
|
|
auto result (pool.generate (nano::block_hash ()));
|
|
ASSERT_FALSE (result.is_initialized ());
|
|
}
|
|
|
|
TEST (work, validate)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
|
|
nano::send_block send_block (1, 1, 2, nano::keypair ().prv, 4, 6);
|
|
ASSERT_LT (nano::dev::network_params.work.difficulty (send_block), nano::dev::network_params.work.threshold_base (send_block.work_version ()));
|
|
send_block.block_work_set (*pool.generate (send_block.root ()));
|
|
ASSERT_LT (nano::dev::network_params.work.threshold_base (send_block.work_version ()), nano::dev::network_params.work.difficulty (send_block));
|
|
}
|
|
|
|
TEST (work, cancel)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
|
|
auto iterations (0);
|
|
auto done (false);
|
|
while (!done)
|
|
{
|
|
nano::root key (1);
|
|
pool.generate (
|
|
nano::work_version::work_1, key, nano::dev::network_params.work.base, [&done] (boost::optional<uint64_t> work_a) {
|
|
done = !work_a;
|
|
});
|
|
pool.cancel (key);
|
|
++iterations;
|
|
ASSERT_LT (iterations, 200);
|
|
}
|
|
}
|
|
|
|
TEST (work, cancel_many)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
|
|
nano::root key1 (1);
|
|
nano::root key2 (2);
|
|
nano::root key3 (1);
|
|
nano::root key4 (1);
|
|
nano::root key5 (3);
|
|
nano::root key6 (1);
|
|
pool.generate (nano::work_version::work_1, key1, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.generate (nano::work_version::work_1, key2, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.generate (nano::work_version::work_1, key3, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.generate (nano::work_version::work_1, key4, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.generate (nano::work_version::work_1, key5, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.generate (nano::work_version::work_1, key6, nano::dev::network_params.work.base, [] (boost::optional<uint64_t>) {});
|
|
pool.cancel (key1);
|
|
}
|
|
|
|
TEST (work, opencl)
|
|
{
|
|
nano::logging logging;
|
|
logging.init (nano::unique_path ());
|
|
nano::logger_mt logger;
|
|
bool error (false);
|
|
nano::opencl_environment environment (error);
|
|
ASSERT_TRUE (!error || !nano::opencl_loaded);
|
|
if (!environment.platforms.empty () && !environment.platforms.begin ()->devices.empty ())
|
|
{
|
|
nano::opencl_config config (0, 0, 16 * 1024);
|
|
auto opencl (nano::opencl_work::create (true, config, logger, nano::dev::network_params.work));
|
|
if (opencl != nullptr)
|
|
{
|
|
// 0 threads, should add 1 for managing OpenCL
|
|
nano::work_pool pool{ nano::dev::network_params.network, 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;
|
|
uint64_t difficulty (0xff00000000000000);
|
|
uint64_t difficulty_add (0x000f000000000000);
|
|
for (auto i (0); i < 16; ++i)
|
|
{
|
|
nano::random_pool::generate_block (root.bytes.data (), root.bytes.size ());
|
|
auto result (*pool.generate (nano::work_version::work_1, root, difficulty));
|
|
ASSERT_GE (nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, result), difficulty);
|
|
difficulty += difficulty_add;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "Error starting OpenCL test" << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Device with OpenCL support not found. Skipping OpenCL test" << std::endl;
|
|
}
|
|
}
|
|
|
|
TEST (work, difficulty)
|
|
{
|
|
nano::work_pool pool{ nano::dev::network_params.network, std::numeric_limits<unsigned>::max () };
|
|
nano::root root (1);
|
|
uint64_t difficulty1 (0xff00000000000000);
|
|
uint64_t difficulty2 (0xfff0000000000000);
|
|
uint64_t difficulty3 (0xffff000000000000);
|
|
uint64_t result_difficulty1 (0);
|
|
do
|
|
{
|
|
auto work1 = *pool.generate (nano::work_version::work_1, root, difficulty1);
|
|
result_difficulty1 = nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, work1);
|
|
} while (result_difficulty1 > difficulty2);
|
|
ASSERT_GT (result_difficulty1, difficulty1);
|
|
uint64_t result_difficulty2 (0);
|
|
do
|
|
{
|
|
auto work2 = *pool.generate (nano::work_version::work_1, root, difficulty2);
|
|
result_difficulty2 = nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, work2);
|
|
} while (result_difficulty2 > difficulty3);
|
|
ASSERT_GT (result_difficulty2, difficulty2);
|
|
}
|
|
|
|
TEST (work, eco_pow)
|
|
{
|
|
auto work_func = [] (std::promise<std::chrono::nanoseconds> & promise, std::chrono::nanoseconds interval) {
|
|
nano::work_pool pool{ nano::dev::network_params.network, 1, interval };
|
|
constexpr auto num_iterations = 5;
|
|
|
|
nano::timer<std::chrono::nanoseconds> timer;
|
|
timer.start ();
|
|
for (int i = 0; i < num_iterations; ++i)
|
|
{
|
|
nano::root root (1);
|
|
uint64_t difficulty1 (0xff00000000000000);
|
|
uint64_t difficulty2 (0xfff0000000000000);
|
|
uint64_t result_difficulty (0);
|
|
do
|
|
{
|
|
auto work = *pool.generate (nano::work_version::work_1, root, difficulty1);
|
|
result_difficulty = nano::dev::network_params.work.difficulty (nano::work_version::work_1, root, work);
|
|
} while (result_difficulty > difficulty2);
|
|
ASSERT_GT (result_difficulty, difficulty1);
|
|
}
|
|
|
|
promise.set_value_at_thread_exit (timer.stop ());
|
|
};
|
|
|
|
std::promise<std::chrono::nanoseconds> promise1;
|
|
std::future<std::chrono::nanoseconds> future1 = promise1.get_future ();
|
|
std::promise<std::chrono::nanoseconds> promise2;
|
|
std::future<std::chrono::nanoseconds> future2 = promise2.get_future ();
|
|
|
|
std::thread thread1 (work_func, std::ref (promise1), std::chrono::nanoseconds (0));
|
|
std::thread thread2 (work_func, std::ref (promise2), std::chrono::milliseconds (10));
|
|
|
|
thread1.join ();
|
|
thread2.join ();
|
|
|
|
// Confirm that the eco pow rate limiter is working.
|
|
// It's possible under some unlucky circumstances that this fails to the random nature of valid work generation.
|
|
ASSERT_LT (future1.get (), future2.get ());
|
|
}
|