Refactor work thresholds as nano::work_thresholds (#2672)

Once we move to c++17, these can be constexpr-defined in lib/config.hpp.
This commit is contained in:
Guilherme Lawless 2020-03-23 12:42:52 +00:00 committed by GitHub
commit 55dcc11b64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 130 additions and 91 deletions

View file

@ -147,12 +147,12 @@ TEST (active_transactions, adjusted_difficulty_priority)
//genesis and key1,key2 are opened
//start chain of 2 on each
auto send3 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send2->hash (), nano::test_genesis_key.pub, 9 * nano::xrb_ratio, key3.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send2->hash (), nano::difficulty::from_multiplier (1500, node1.network_params.network.publish_threshold))));
auto send4 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send3->hash (), nano::test_genesis_key.pub, 8 * nano::xrb_ratio, key3.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send3->hash (), nano::difficulty::from_multiplier (1500, node1.network_params.network.publish_threshold))));
auto send5 (std::make_shared<nano::state_block> (key1.pub, open1->hash (), key1.pub, 9 * nano::xrb_ratio, key3.pub, key1.prv, key1.pub, *system.work.generate (open1->hash (), nano::difficulty::from_multiplier (100, node1.network_params.network.publish_threshold))));
auto send6 (std::make_shared<nano::state_block> (key1.pub, send5->hash (), key1.pub, 8 * nano::xrb_ratio, key3.pub, key1.prv, key1.pub, *system.work.generate (send5->hash (), nano::difficulty::from_multiplier (100, node1.network_params.network.publish_threshold))));
auto send7 (std::make_shared<nano::state_block> (key2.pub, open2->hash (), key2.pub, 9 * nano::xrb_ratio, key3.pub, key2.prv, key2.pub, *system.work.generate (open2->hash (), nano::difficulty::from_multiplier (500, node1.network_params.network.publish_threshold))));
auto send8 (std::make_shared<nano::state_block> (key2.pub, send7->hash (), key2.pub, 8 * nano::xrb_ratio, key3.pub, key2.prv, key2.pub, *system.work.generate (send7->hash (), nano::difficulty::from_multiplier (500, node1.network_params.network.publish_threshold))));
auto send3 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send2->hash (), nano::test_genesis_key.pub, 9 * nano::xrb_ratio, key3.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send2->hash (), nano::difficulty::from_multiplier (1500, node1.network_params.network.publish_thresholds.base))));
auto send4 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send3->hash (), nano::test_genesis_key.pub, 8 * nano::xrb_ratio, key3.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send3->hash (), nano::difficulty::from_multiplier (1500, node1.network_params.network.publish_thresholds.base))));
auto send5 (std::make_shared<nano::state_block> (key1.pub, open1->hash (), key1.pub, 9 * nano::xrb_ratio, key3.pub, key1.prv, key1.pub, *system.work.generate (open1->hash (), nano::difficulty::from_multiplier (100, node1.network_params.network.publish_thresholds.base))));
auto send6 (std::make_shared<nano::state_block> (key1.pub, send5->hash (), key1.pub, 8 * nano::xrb_ratio, key3.pub, key1.prv, key1.pub, *system.work.generate (send5->hash (), nano::difficulty::from_multiplier (100, node1.network_params.network.publish_thresholds.base))));
auto send7 (std::make_shared<nano::state_block> (key2.pub, open2->hash (), key2.pub, 9 * nano::xrb_ratio, key3.pub, key2.prv, key2.pub, *system.work.generate (open2->hash (), nano::difficulty::from_multiplier (500, node1.network_params.network.publish_thresholds.base))));
auto send8 (std::make_shared<nano::state_block> (key2.pub, send7->hash (), key2.pub, 8 * nano::xrb_ratio, key3.pub, key2.prv, key2.pub, *system.work.generate (send7->hash (), nano::difficulty::from_multiplier (500, node1.network_params.network.publish_thresholds.base))));
node1.process_active (send3); // genesis
node1.process_active (send5); // key1
@ -363,7 +363,7 @@ TEST (active_transactions, prioritize_chains)
auto send4 (std::make_shared<nano::state_block> (key1.pub, send3->hash (), key1.pub, nano::xrb_ratio * 7, key2.pub, key1.prv, key1.pub, *system.work.generate (send3->hash ())));
auto send5 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 20 * nano::xrb_ratio, key2.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send1->hash ())));
auto send6 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send5->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 30 * nano::xrb_ratio, key3.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, *system.work.generate (send5->hash ())));
auto open2 (std::make_shared<nano::state_block> (key2.pub, 0, key2.pub, 10 * nano::xrb_ratio, send5->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub, nano::difficulty::from_multiplier (50., node1.network_params.network.publish_threshold))));
auto open2 (std::make_shared<nano::state_block> (key2.pub, 0, key2.pub, 10 * nano::xrb_ratio, send5->hash (), key2.prv, key2.pub, *system.work.generate (key2.pub, nano::difficulty::from_multiplier (50., node1.network_params.network.publish_thresholds.base))));
auto difficulty1 (open2->difficulty ());
auto difficulty2 (send6->difficulty ());

View file

@ -62,10 +62,12 @@ TEST (difficulty, multipliers)
TEST (difficulty, network_constants)
{
ASSERT_NEAR (8., nano::difficulty::to_multiplier (nano::network_constants::publish_full_epoch_2_threshold, nano::network_constants::publish_full_epoch_1_threshold), 1e-10);
ASSERT_NEAR (1 / 8., nano::difficulty::to_multiplier (nano::network_constants::publish_full_epoch_2_receive_threshold, nano::network_constants::publish_full_epoch_1_threshold), 1e-10);
ASSERT_NEAR (1., nano::difficulty::to_multiplier (nano::network_constants::publish_full_epoch_2_receive_threshold, nano::network_constants::publish_full_threshold), 1e-10);
ASSERT_NEAR (1 / 64., nano::difficulty::to_multiplier (nano::network_constants::publish_beta_threshold, nano::network_constants::publish_full_epoch_1_threshold), 1e-10);
nano::network_constants constants;
ASSERT_NEAR (1., nano::difficulty::to_multiplier (constants.publish_full.epoch_2_receive, constants.publish_full.entry), 1e-10);
ASSERT_NEAR (1., nano::difficulty::to_multiplier (constants.publish_full.epoch_2, constants.publish_full.base), 1e-10);
ASSERT_NEAR (8., nano::difficulty::to_multiplier (constants.publish_full.epoch_2, constants.publish_full.epoch_1), 1e-10);
ASSERT_NEAR (1 / 8., nano::difficulty::to_multiplier (constants.publish_full.epoch_2_receive, constants.publish_full.epoch_1), 1e-10);
ASSERT_NEAR (1 / 64., nano::difficulty::to_multiplier (constants.publish_beta.base, constants.publish_full.epoch_1), 1e-10);
}
TEST (difficulty, overflow)

View file

@ -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::work_version::work_1, 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.base));
}
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 (nano::work_version::work_1, 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_thresholds.base, 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::work_version::work_1, 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.base));
}
TEST (distributed_work, no_peers_cancel)
@ -55,7 +55,7 @@ TEST (distributed_work, no_peers_cancel)
nano::system system;
nano::node_config node_config (nano::get_available_port (), system.logging);
node_config.max_work_generate_multiplier = 1e6;
node_config.max_work_generate_difficulty = nano::difficulty::from_multiplier (node_config.max_work_generate_multiplier, nano::network_constants::publish_test_threshold);
node_config.max_work_generate_difficulty = nano::difficulty::from_multiplier (node_config.max_work_generate_multiplier, nano::network_constants ().publish_test.base);
auto & node = *system.add_node (node_config);
nano::block_hash hash{ 1 };
bool done{ false };
@ -63,7 +63,7 @@ TEST (distributed_work, no_peers_cancel)
ASSERT_FALSE (work_a.is_initialized ());
done = true;
};
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_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_thresholds.base)));
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 (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_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_thresholds.base)));
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 (nano::work_version::work_1, 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_thresholds.base)));
}
// 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 (nano::work_version::work_1, 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_thresholds.base));
}
// 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 (nano::work_version::work_1, 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_thresholds.base, 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 (nano::work_version::work_1, 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_thresholds.base, 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 (nano::work_version::work_1, 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_thresholds.base, 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 (nano::work_version::work_1, 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_thresholds.base, 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 (nano::work_version::work_1, 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_thresholds.base, nano::account ()));
system.deadline_set (5s);
while (!done)
{

View file

@ -3732,7 +3732,7 @@ TEST (active_difficulty, recalculate_work)
auto & node1 = *system.add_node (node_config);
nano::genesis genesis;
nano::keypair key1;
ASSERT_EQ (node1.network_params.network.publish_threshold, node1.active.active_difficulty ());
ASSERT_EQ (node1.network_params.network.publish_thresholds.base, node1.active.active_difficulty ());
auto send1 (std::make_shared<nano::send_block> (genesis.hash (), key1.pub, 0, nano::test_genesis_key.prv, nano::test_genesis_key.pub, 0));
node1.work_generate_blocking (*send1);
auto multiplier1 = nano::difficulty::to_multiplier (send1->difficulty (), nano::work_threshold (send1->work_version ()));
@ -3744,7 +3744,7 @@ TEST (active_difficulty, recalculate_work)
ASSERT_NO_ERROR (system.poll ());
}
auto sum (std::accumulate (node1.active.multipliers_cb.begin (), node1.active.multipliers_cb.end (), double(0)));
ASSERT_EQ (node1.active.active_difficulty (), nano::difficulty::from_multiplier (sum / node1.active.multipliers_cb.size (), node1.network_params.network.publish_threshold));
ASSERT_EQ (node1.active.active_difficulty (), nano::difficulty::from_multiplier (sum / node1.active.multipliers_cb.size (), node1.network_params.network.publish_thresholds.base));
nano::unique_lock<std::mutex> lock (node1.active.mutex);
// Fake history records to force work recalculation
for (auto i (0); i < node1.active.multipliers_cb.size (); i++)
@ -3755,7 +3755,7 @@ TEST (active_difficulty, recalculate_work)
node1.process_active (send1);
node1.active.update_active_difficulty (lock);
sum = std::accumulate (node1.active.multipliers_cb.begin (), node1.active.multipliers_cb.end (), double(0));
ASSERT_EQ (node1.active.trended_active_difficulty, nano::difficulty::from_multiplier (sum / node1.active.multipliers_cb.size (), node1.network_params.network.publish_threshold));
ASSERT_EQ (node1.active.trended_active_difficulty, nano::difficulty::from_multiplier (sum / node1.active.multipliers_cb.size (), node1.network_params.network.publish_thresholds.base));
lock.unlock ();
}

View file

@ -1137,7 +1137,7 @@ TEST (wallet, work_watcher_update)
auto difficulty1 (block1->difficulty ());
auto const block2 (wallet.send_action (nano::test_genesis_key.pub, key.pub, 200));
auto difficulty2 (block2->difficulty ());
auto multiplier = nano::difficulty::to_multiplier (std::max (difficulty1, difficulty2), node.network_params.network.publish_threshold);
auto multiplier = nano::difficulty::to_multiplier (std::max (difficulty1, difficulty2), node.network_params.network.publish_thresholds.base);
uint64_t updated_difficulty1{ difficulty1 }, updated_difficulty2{ difficulty2 };
{
nano::unique_lock<std::mutex> lock (node.active.mutex);
@ -1243,7 +1243,7 @@ TEST (wallet, work_watcher_cancel)
nano::node_config node_config (nano::get_available_port (), system.logging);
node_config.work_watcher_period = 1s;
node_config.max_work_generate_multiplier = 1e6;
node_config.max_work_generate_difficulty = nano::difficulty::from_multiplier (node_config.max_work_generate_multiplier, nano::network_constants::publish_test_threshold);
node_config.max_work_generate_difficulty = nano::difficulty::from_multiplier (node_config.max_work_generate_multiplier, nano::network_constants ().publish_test.base);
node_config.enable_voting = false;
auto & node = *system.add_node (node_config);
auto & wallet (*system.wallet (0));

View file

@ -104,14 +104,14 @@ TEST (websocket, active_difficulty)
auto message_contents = event.get_child ("message");
uint64_t network_minimum;
nano::from_string_hex (message_contents.get<std::string> ("network_minimum"), network_minimum);
ASSERT_EQ (network_minimum, node1->network_params.network.publish_threshold);
ASSERT_EQ (network_minimum, node1->network_params.network.publish_thresholds.base);
uint64_t network_current;
nano::from_string_hex (message_contents.get<std::string> ("network_current"), network_current);
ASSERT_EQ (network_current, node1->active.active_difficulty ());
double multiplier = message_contents.get<double> ("multiplier");
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (node1->active.active_difficulty (), node1->network_params.network.publish_threshold), 1e-6);
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (node1->active.active_difficulty (), node1->network_params.network.publish_thresholds.base), 1e-6);
}
// Subscribes to block confirmations, confirms a block and then awaits websocket notification
@ -680,15 +680,15 @@ TEST (websocket, work)
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<std::string> ("difficulty"), nano::to_string_hex (node1->network_params.network.publish_thresholds.base));
ASSERT_EQ (request.get<double> ("multiplier"), 1.0);
ASSERT_EQ (1, contents.count ("result"));
auto & result = contents.get_child ("result");
uint64_t result_difficulty;
nano::from_string_hex (result.get<std::string> ("difficulty"), result_difficulty);
ASSERT_GE (result_difficulty, node1->network_params.network.publish_threshold);
ASSERT_NEAR (result.get<double> ("multiplier"), nano::difficulty::to_multiplier (result_difficulty, node1->network_params.network.publish_threshold), 1e-6);
ASSERT_GE (result_difficulty, node1->network_params.network.publish_thresholds.base);
ASSERT_NEAR (result.get<double> ("multiplier"), nano::difficulty::to_multiplier (result_difficulty, node1->network_params.network.publish_thresholds.base), 1e-6);
ASSERT_EQ (result.get<std::string> ("work"), nano::to_string_hex (work.get ()));
ASSERT_EQ (1, contents.count ("bad_peers"));

View file

@ -7,6 +7,24 @@
namespace nano
{
work_thresholds const network_constants::publish_full (
0xffffffc000000000,
0xfffffff800000000, // 8x higher than epoch_1
0xfffffe0000000000 // 8x lower than epoch_1
);
work_thresholds const network_constants::publish_beta (
0xfffff00000000000, // 64x lower than publish_full.epoch_1
0xfffff00000000000,
0xfffff00000000000 //
);
work_thresholds const network_constants::publish_test (
0xff00000000000000, // Very low for tests
0xff00000000000000,
0xff00000000000000 //
);
const char * network_constants::active_network_err_msg = "Invalid network. Valid values are live, beta and test.";
uint8_t get_major_node_version ()

View file

@ -66,6 +66,31 @@ enum class nano_networks
rai_live_network = 2,
};
struct work_thresholds
{
uint64_t const epoch_1;
uint64_t const epoch_2;
uint64_t const epoch_2_receive;
// Automatically calculated. The base threshold is the maximum of all thresholds and is used for all work multiplier calculations
uint64_t const base;
// Automatically calculated. The entry threshold is the minimum of all thresholds and defines the required work to enter the node, but does not guarantee a block is processed
uint64_t const entry;
constexpr work_thresholds (uint64_t epoch_1_a, uint64_t epoch_2_a, uint64_t epoch_2_receive_a) :
epoch_1 (epoch_1_a), epoch_2 (epoch_2_a), epoch_2_receive (epoch_2_receive_a),
base (std::max ({ epoch_1, epoch_2, epoch_2_receive })),
entry (std::min ({ epoch_1, epoch_2, epoch_2_receive }))
{
}
work_thresholds () = delete;
work_thresholds operator= (nano::work_thresholds const & other_a)
{
return other_a;
}
};
class network_constants
{
public:
@ -75,11 +100,9 @@ public:
}
network_constants (nano_networks network_a) :
current_network (network_a)
current_network (network_a),
publish_thresholds (is_live_network () ? publish_full : is_beta_network () ? publish_beta : publish_test)
{
// The minimum threshold to enter the node, does not guarantee a block is processed
publish_threshold = is_test_network () ? publish_test_threshold : is_beta_network () ? publish_beta_threshold : publish_full_threshold;
// A representative is classified as principal based on its weight and this factor
principal_weight_factor = 1000; // 0.1%
@ -90,22 +113,18 @@ public:
request_interval_ms = is_test_network () ? 20 : 500;
}
/** Network work thresholds */
static uint64_t const publish_full_epoch_1_threshold{ 0xffffffc000000000 };
static uint64_t const publish_full_epoch_2_threshold{ 0xfffffff800000000 }; // 8x higher than epoch 1
static uint64_t const publish_full_epoch_2_receive_threshold{ 0xfffffe0000000000 }; // 8x lower than epoch 1
static uint64_t const publish_full_threshold{ std::min ({ publish_full_epoch_1_threshold, publish_full_epoch_2_threshold, publish_full_epoch_2_receive_threshold }) };
static_assert (publish_full_threshold == publish_full_epoch_2_receive_threshold, "publish_full_threshold is ill-defined");
static uint64_t const publish_beta_threshold{ 0xfffff00000000000 }; // 64x lower than epoch 1
static uint64_t const publish_test_threshold{ 0xff00000000000000 }; // very low for tests
/** Network work thresholds. Define these inline as constexpr when moving to cpp17. */
static const nano::work_thresholds publish_full;
static const nano::work_thresholds publish_beta;
static const nano::work_thresholds publish_test;
/** Error message when an invalid network is specified */
static const char * active_network_err_msg;
/** The network this param object represents. This may differ from the global active network; this is needed for certain --debug... commands */
nano_networks current_network{ nano::network_constants::active_network };
uint64_t publish_threshold;
nano::work_thresholds publish_thresholds;
unsigned principal_weight_factor;
uint16_t default_node_port;
uint16_t default_rpc_port;
@ -190,4 +209,4 @@ void force_nano_test_network ();
/** Checks if we are running inside a valgrind instance */
bool running_within_valgrind ();
}
}

View file

@ -76,7 +76,7 @@ uint64_t nano::work_threshold (nano::work_version const version_a, nano::block_d
uint64_t nano::work_v1::threshold ()
{
static nano::network_constants network_constants;
return network_constants.publish_threshold;
return network_constants.publish_thresholds.base;
}
uint64_t nano::work_v1::threshold (nano::block_details const details_a)
@ -86,18 +86,18 @@ uint64_t nano::work_v1::threshold (nano::block_details const details_a)
if (!network_constants.is_live_network ())
{
return network_constants.publish_threshold;
return network_constants.publish_thresholds.base;
}
uint64_t result{ std::numeric_limits<uint64_t>::max () };
switch (details_a.epoch)
{
case nano::epoch::epoch_2:
result = (details_a.is_receive || details_a.is_epoch) ? nano::network_constants::publish_full_epoch_2_receive_threshold : nano::network_constants::publish_full_epoch_2_threshold;
result = (details_a.is_receive || details_a.is_epoch) ? network_constants.publish_full.epoch_2_receive : network_constants.publish_full.epoch_2;
break;
case nano::epoch::epoch_1:
case nano::epoch::epoch_0:
result = nano::network_constants::publish_full_epoch_1_threshold;
result = network_constants.publish_full.epoch_1;
break;
default:
debug_assert (false && "Invalid epoch specified to work_v1 ledger work_threshold");
@ -125,7 +125,7 @@ uint64_t nano::work_v1::value (nano::root const & root_a, uint64_t work_a)
debug_assert (false);
std::exit (1);
}
return network_constants.publish_threshold + 1;
return network_constants.publish_thresholds.base + 1;
}
#endif
@ -294,7 +294,7 @@ void nano::work_pool::generate (nano::root const & root_a, std::function<void(bo
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);
generate (version_a, root_a, callback_a, network_constants.publish_thresholds.base);
}
void nano::work_pool::generate (nano::root const & root_a, std::function<void(boost::optional<uint64_t> const &)> callback_a, uint64_t difficulty_a)
@ -328,7 +328,7 @@ boost::optional<uint64_t> nano::work_pool::generate (nano::root const & 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);
return generate (version_a, root_a, network_constants.publish_thresholds.base);
}
boost::optional<uint64_t> nano::work_pool::generate (nano::root const & root_a, uint64_t difficulty_a)

View file

@ -327,7 +327,7 @@ int main (int argc, char * const * argv)
}
else if (vm.count ("debug_profile_validate"))
{
uint64_t difficulty{ nano::network_constants::publish_full_threshold };
uint64_t difficulty{ nano::network_constants ().publish_full.base };
std::cerr << "Starting validation profile" << std::endl;
auto start (std::chrono::steady_clock::now ());
bool valid{ false };
@ -392,7 +392,7 @@ int main (int argc, char * const * argv)
result = -1;
}
}
uint64_t difficulty (network_constants.publish_threshold);
uint64_t difficulty (network_constants.publish_thresholds.base);
auto difficulty_it = vm.find ("difficulty");
if (difficulty_it != vm.end ())
{
@ -401,7 +401,7 @@ int main (int argc, char * const * argv)
std::cerr << "Invalid difficulty\n";
result = -1;
}
else if (difficulty < network_constants.publish_threshold)
else if (difficulty < network_constants.publish_thresholds.base)
{
std::cerr << "Difficulty below publish threshold\n";
result = -1;

View file

@ -18,7 +18,7 @@ nano::active_transactions::active_transactions (nano::node & node_a, nano::confi
confirmation_height_processor (confirmation_height_processor_a),
node (node_a),
multipliers_cb (20, 1.),
trended_active_difficulty (node_a.network_params.network.publish_threshold),
trended_active_difficulty (node_a.network_params.network.publish_thresholds.base),
check_all_elections_period (node_a.network_params.network.is_test_network () ? 10ms : 5s),
election_time_to_live (node_a.network_params.network.is_test_network () ? 0s : 2s),
prioritized_cutoff (std::max<size_t> (1, node_a.config.active_elections_size / 10)),
@ -708,7 +708,7 @@ void nano::active_transactions::update_adjusted_difficulty ()
auto existing_root (roots.get<tag_root> ().find (root));
if (existing_root != roots.get<tag_root> ().end ())
{
sum += nano::difficulty::to_multiplier (existing_root->difficulty, node.network_params.network.publish_threshold);
sum += nano::difficulty::to_multiplier (existing_root->difficulty, node.network_params.network.publish_thresholds.base);
elections_list.emplace_back (root, level);
if (level > highest_level)
{
@ -726,7 +726,7 @@ void nano::active_transactions::update_adjusted_difficulty ()
if (!elections_list.empty ())
{
double multiplier = sum / elections_list.size ();
uint64_t average = nano::difficulty::from_multiplier (multiplier, node.network_params.network.publish_threshold);
uint64_t average = nano::difficulty::from_multiplier (multiplier, node.network_params.network.publish_thresholds.base);
// Prevent overflow
int64_t limiter (0);
if (std::numeric_limits<std::uint64_t>::max () - average < static_cast<uint64_t> (highest_level))
@ -778,7 +778,7 @@ void nano::active_transactions::update_active_difficulty (nano::unique_lock<std:
}
if (prioritized.size () > 10 || (node.network_params.network.is_test_network () && !prioritized.empty ()))
{
multiplier = nano::difficulty::to_multiplier (prioritized[prioritized.size () / 2], node.network_params.network.publish_threshold);
multiplier = nano::difficulty::to_multiplier (prioritized[prioritized.size () / 2], node.network_params.network.publish_thresholds.base);
}
if (!prioritized.empty ())
{
@ -788,8 +788,8 @@ void nano::active_transactions::update_active_difficulty (nano::unique_lock<std:
debug_assert (multiplier >= 1);
multipliers_cb.push_front (multiplier);
auto sum (std::accumulate (multipliers_cb.begin (), multipliers_cb.end (), double(0)));
auto difficulty = nano::difficulty::from_multiplier (sum / multipliers_cb.size (), node.network_params.network.publish_threshold);
debug_assert (difficulty >= node.network_params.network.publish_threshold);
auto difficulty = nano::difficulty::from_multiplier (sum / multipliers_cb.size (), node.network_params.network.publish_thresholds.base);
debug_assert (difficulty >= node.network_params.network.publish_thresholds.base);
trended_active_difficulty = difficulty;
node.observers.difficulty.notify (trended_active_difficulty);

View file

@ -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.version, 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_thresholds.base, elapsed.value (), winner, bad_peers));
}
else if (status == work_generation_status::cancelled)
{
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));
node_l->websocket_server->broadcast (builder.work_cancelled (request.version, request.root, request.difficulty, node_l->network_params.network.publish_thresholds.base, 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.version, 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_thresholds.base, elapsed.value (), bad_peers));
}
}
stop_once (true);

View file

@ -345,7 +345,7 @@ uint64_t nano::json_handler::work_optional_impl ()
uint64_t nano::json_handler::difficulty_optional_impl ()
{
uint64_t difficulty (node.network_params.network.publish_threshold);
uint64_t difficulty (node.network_params.network.publish_thresholds.base);
boost::optional<std::string> difficulty_text (request.get_optional<std::string> ("difficulty"));
if (!ec && difficulty_text.is_initialized ())
{
@ -366,7 +366,7 @@ double nano::json_handler::multiplier_optional_impl (uint64_t & difficulty)
auto success = boost::conversion::try_lexical_convert<double> (multiplier_text.get (), multiplier);
if (success && multiplier > 0.)
{
difficulty = nano::difficulty::from_multiplier (multiplier, node.network_params.network.publish_threshold);
difficulty = nano::difficulty::from_multiplier (multiplier, node.network_params.network.publish_thresholds.base);
}
else
{
@ -909,10 +909,10 @@ void nano::json_handler::accounts_pending ()
void nano::json_handler::active_difficulty ()
{
auto include_trend (request.get<bool> ("include_trend", false));
response_l.put ("network_minimum", nano::to_string_hex (node.network_params.network.publish_threshold));
response_l.put ("network_minimum", nano::to_string_hex (node.network_params.network.publish_thresholds.base));
auto difficulty_active = node.active.active_difficulty ();
response_l.put ("network_current", nano::to_string_hex (difficulty_active));
auto multiplier = nano::difficulty::to_multiplier (difficulty_active, node.network_params.network.publish_threshold);
auto multiplier = nano::difficulty::to_multiplier (difficulty_active, node.network_params.network.publish_thresholds.base);
response_l.put ("multiplier", nano::to_string (multiplier));
if (include_trend)
{
@ -4938,7 +4938,7 @@ void nano::json_handler::work_generate ()
auto hash (hash_impl ());
auto difficulty (difficulty_optional_impl ());
multiplier_optional_impl (difficulty);
if (!ec && (difficulty > node.config.max_work_generate_difficulty || difficulty < node.network_params.network.publish_threshold))
if (!ec && (difficulty > node.config.max_work_generate_difficulty || difficulty < node.network_params.network.publish_thresholds.base))
{
ec = nano::error_rpc::difficulty_limit;
}

View file

@ -259,7 +259,7 @@ startup_time (std::chrono::steady_clock::now ())
if (this->websocket_server->any_subscriber (nano::websocket::topic::active_difficulty))
{
nano::websocket::message_builder builder;
auto msg (builder.difficulty_changed (network_params.network.publish_threshold, active_difficulty));
auto msg (builder.difficulty_changed (network_params.network.publish_thresholds.base, active_difficulty));
this->websocket_server->broadcast (msg);
}
});
@ -1013,7 +1013,7 @@ bool nano::node::work_generation_enabled (std::vector<std::pair<std::string, uin
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a)
{
return work_generate_blocking (block_a, network_params.network.publish_threshold);
return work_generate_blocking (block_a, network_params.network.publish_thresholds.base);
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a)
@ -1028,7 +1028,7 @@ boost::optional<uint64_t> nano::node::work_generate_blocking (nano::block & bloc
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 (version_a, root_a, callback_a, network_params.network.publish_threshold, account_a);
work_generate (version_a, root_a, callback_a, network_params.network.publish_thresholds.base, 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, uint64_t difficulty_a, boost::optional<nano::account> const & account_a, bool secondary_work_peers_a)
@ -1043,7 +1043,7 @@ void nano::node::work_generate (nano::work_version const version_a, nano::root c
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 (version_a, root_a, network_params.network.publish_threshold, account_a);
return work_generate_blocking (version_a, root_a, network_params.network.publish_thresholds.base, 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)
@ -1060,7 +1060,7 @@ boost::optional<uint64_t> nano::node::work_generate_blocking (nano::work_version
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a)
{
debug_assert (network_params.network.is_test_network ());
return work_generate_blocking (root_a, network_params.network.publish_threshold);
return work_generate_blocking (root_a, network_params.network.publish_thresholds.base);
}
boost::optional<uint64_t> nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a)

View file

@ -35,7 +35,7 @@ external_address (boost::asio::ip::address_v6{}.to_string ())
{
peering_port = network_params.network.default_node_port;
}
max_work_generate_difficulty = nano::difficulty::from_multiplier (max_work_generate_multiplier, network_params.network.publish_threshold);
max_work_generate_difficulty = nano::difficulty::from_multiplier (max_work_generate_multiplier, network_params.network.publish_thresholds.base);
switch (network_params.network.network ())
{
case nano::nano_networks::nano_test_network:
@ -359,7 +359,7 @@ nano::error nano::node_config::deserialize_toml (nano::tomlconfig & toml)
nano::network_constants network;
toml.get<double> ("max_work_generate_multiplier", max_work_generate_multiplier);
max_work_generate_difficulty = nano::difficulty::from_multiplier (max_work_generate_multiplier, network.publish_threshold);
max_work_generate_difficulty = nano::difficulty::from_multiplier (max_work_generate_multiplier, network.publish_thresholds.base);
toml.get<uint32_t> ("max_queued_requests", max_queued_requests);

View file

@ -95,7 +95,7 @@ public:
bool backup_before_upgrade{ false };
std::chrono::seconds work_watcher_period{ std::chrono::seconds (5) };
double max_work_generate_multiplier{ 64. };
uint64_t max_work_generate_difficulty{ nano::network_constants::publish_full_threshold };
uint64_t max_work_generate_difficulty{ nano::network_constants ().publish_full.base };
uint32_t max_queued_requests{ 512 };
nano::rocksdb_config rocksdb_config;
nano::lmdb_config lmdb_config;

View file

@ -2837,7 +2837,7 @@ TEST (rpc, work_generate)
ASSERT_FALSE (nano::from_string_hex (response_difficulty_text, response_difficulty));
ASSERT_EQ (result_difficulty, response_difficulty);
auto multiplier = response.json.get<double> ("multiplier");
ASSERT_NEAR (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_threshold), multiplier, 1e-6);
ASSERT_NEAR (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_thresholds.base), multiplier, 1e-6);
};
verify_response (request, hash);
request.put ("use_peers", "true");
@ -2882,7 +2882,7 @@ TEST (rpc, work_generate_difficulty)
ASSERT_EQ (result_difficulty, response_difficulty);
auto multiplier = response.json.get<double> ("multiplier");
// Expected multiplier from base threshold, not from the given difficulty
ASSERT_EQ (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_threshold), multiplier);
ASSERT_EQ (nano::difficulty::to_multiplier (result_difficulty, node->network_params.network.publish_thresholds.base), multiplier);
ASSERT_GE (result_difficulty, difficulty);
}
{
@ -2971,7 +2971,7 @@ TEST (rpc, work_generate_multiplier)
ASSERT_EQ (response.json.get<std::string> ("error"), ec.message ());
}
{
double max_multiplier (nano::difficulty::to_multiplier (node->config.max_work_generate_difficulty, node->network_params.network.publish_threshold));
double max_multiplier (nano::difficulty::to_multiplier (node->config.max_work_generate_difficulty, node->network_params.network.publish_thresholds.base));
request.put ("multiplier", max_multiplier + 1);
test_response response (request, rpc.config.port, system.io_ctx);
system.deadline_set (5s);
@ -3814,9 +3814,9 @@ TEST (rpc, work_validate)
std::string difficulty_text (response.json.get<std::string> ("difficulty"));
uint64_t difficulty;
ASSERT_FALSE (nano::from_string_hex (difficulty_text, difficulty));
ASSERT_GE (difficulty, params.network.publish_threshold);
ASSERT_GE (difficulty, params.network.publish_thresholds.base);
double multiplier (response.json.get<double> ("multiplier"));
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (difficulty, params.network.publish_threshold), 1e-6);
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (difficulty, params.network.publish_thresholds.base), 1e-6);
}
uint64_t work2 (0);
request.put ("work", nano::to_string_hex (work2));
@ -3833,12 +3833,12 @@ TEST (rpc, work_validate)
std::string difficulty_text (response.json.get<std::string> ("difficulty"));
uint64_t difficulty;
ASSERT_FALSE (nano::from_string_hex (difficulty_text, difficulty));
ASSERT_GE (params.network.publish_threshold, difficulty);
ASSERT_GE (params.network.publish_thresholds.base, difficulty);
double multiplier (response.json.get<double> ("multiplier"));
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (difficulty, params.network.publish_threshold), 1e-6);
ASSERT_NEAR (multiplier, nano::difficulty::to_multiplier (difficulty, params.network.publish_thresholds.base), 1e-6);
}
auto result_difficulty (nano::work_difficulty (nano::work_version::work_1, hash, work1));
ASSERT_GE (result_difficulty, params.network.publish_threshold);
ASSERT_GE (result_difficulty, params.network.publish_thresholds.base);
request.put ("work", nano::to_string_hex (work1));
request.put ("difficulty", nano::to_string_hex (result_difficulty));
{
@ -7248,13 +7248,13 @@ TEST (rpc, active_difficulty)
auto network_minimum_text (response.json.get<std::string> ("network_minimum"));
uint64_t network_minimum;
ASSERT_FALSE (nano::from_string_hex (network_minimum_text, network_minimum));
ASSERT_EQ (node->network_params.network.publish_threshold, network_minimum);
ASSERT_EQ (node->network_params.network.publish_thresholds.base, network_minimum);
auto multiplier (response.json.get<double> ("multiplier"));
ASSERT_NEAR (expected_multiplier, multiplier, 1e-6);
auto network_current_text (response.json.get<std::string> ("network_current"));
uint64_t network_current;
ASSERT_FALSE (nano::from_string_hex (network_current_text, network_current));
ASSERT_EQ (nano::difficulty::from_multiplier (expected_multiplier, node->network_params.network.publish_threshold), network_current);
ASSERT_EQ (nano::difficulty::from_multiplier (expected_multiplier, node->network_params.network.publish_thresholds.base), network_current);
ASSERT_EQ (response.json.not_found (), response.json.find ("difficulty_trend"));
}
// Test include_trend optional