From 55dcc11b64a375c2e560ed4371eee4c593489729 Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Mon, 23 Mar 2020 12:42:52 +0000 Subject: [PATCH] Refactor work thresholds as nano::work_thresholds (#2672) Once we move to c++17, these can be constexpr-defined in lib/config.hpp. --- nano/core_test/active_transactions.cpp | 14 ++++---- nano/core_test/difficulty.cpp | 10 +++--- nano/core_test/distributed_work.cpp | 26 +++++++------- nano/core_test/node.cpp | 6 ++-- nano/core_test/wallet.cpp | 4 +-- nano/core_test/websocket.cpp | 10 +++--- nano/lib/config.cpp | 18 ++++++++++ nano/lib/config.hpp | 49 ++++++++++++++++++-------- nano/lib/work.cpp | 14 ++++---- nano/nano_node/entry.cpp | 6 ++-- nano/node/active_transactions.cpp | 12 +++---- nano/node/distributed_work.cpp | 6 ++-- nano/node/json_handler.cpp | 10 +++--- nano/node/node.cpp | 10 +++--- nano/node/nodeconfig.cpp | 4 +-- nano/node/nodeconfig.hpp | 2 +- nano/rpc_test/rpc.cpp | 20 +++++------ 17 files changed, 130 insertions(+), 91 deletions(-) diff --git a/nano/core_test/active_transactions.cpp b/nano/core_test/active_transactions.cpp index 42e50d04..8bf8ac3a 100644 --- a/nano/core_test/active_transactions.cpp +++ b/nano/core_test/active_transactions.cpp @@ -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::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::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 (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 (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 (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 (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::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::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 (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 (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 (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 (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 (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::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::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 (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 (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 ()); diff --git a/nano/core_test/difficulty.cpp b/nano/core_test/difficulty.cpp index 75760e1b..6ea13e01 100644 --- a/nano/core_test/difficulty.cpp +++ b/nano/core_test/difficulty.cpp @@ -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) diff --git a/nano/core_test/distributed_work.cpp b/nano/core_test/distributed_work.cpp index c396b0a5..b503a30c 100644 --- a/nano/core_test/distributed_work.cpp +++ b/nano/core_test/distributed_work.cpp @@ -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 (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) { diff --git a/nano/core_test/node.cpp b/nano/core_test/node.cpp index b41fe340..84b227ae 100644 --- a/nano/core_test/node.cpp +++ b/nano/core_test/node.cpp @@ -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 (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 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 (); } diff --git a/nano/core_test/wallet.cpp b/nano/core_test/wallet.cpp index b9a912eb..0ddf1666 100644 --- a/nano/core_test/wallet.cpp +++ b/nano/core_test/wallet.cpp @@ -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 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)); diff --git a/nano/core_test/websocket.cpp b/nano/core_test/websocket.cpp index fb908e03..5ea706a9 100644 --- a/nano/core_test/websocket.cpp +++ b/nano/core_test/websocket.cpp @@ -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 ("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 ("network_current"), network_current); ASSERT_EQ (network_current, node1->active.active_difficulty ()); double multiplier = message_contents.get ("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 ("version"), nano::to_string (nano::work_version::work_1)); ASSERT_EQ (request.get ("hash"), hash.to_string ()); - ASSERT_EQ (request.get ("difficulty"), nano::to_string_hex (node1->network_params.network.publish_threshold)); + ASSERT_EQ (request.get ("difficulty"), nano::to_string_hex (node1->network_params.network.publish_thresholds.base)); ASSERT_EQ (request.get ("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 ("difficulty"), result_difficulty); - ASSERT_GE (result_difficulty, node1->network_params.network.publish_threshold); - ASSERT_NEAR (result.get ("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 ("multiplier"), nano::difficulty::to_multiplier (result_difficulty, node1->network_params.network.publish_thresholds.base), 1e-6); ASSERT_EQ (result.get ("work"), nano::to_string_hex (work.get ())); ASSERT_EQ (1, contents.count ("bad_peers")); diff --git a/nano/lib/config.cpp b/nano/lib/config.cpp index 012921d5..74a02bb9 100644 --- a/nano/lib/config.cpp +++ b/nano/lib/config.cpp @@ -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 () diff --git a/nano/lib/config.hpp b/nano/lib/config.hpp index 38d48609..43c25973 100644 --- a/nano/lib/config.hpp +++ b/nano/lib/config.hpp @@ -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 (); -} +} \ No newline at end of file diff --git a/nano/lib/work.cpp b/nano/lib/work.cpp index 323452f0..884c3b01 100644 --- a/nano/lib/work.cpp +++ b/nano/lib/work.cpp @@ -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::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 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 const &)> callback_a, uint64_t difficulty_a) @@ -328,7 +328,7 @@ boost::optional nano::work_pool::generate (nano::root const & root_a) boost::optional 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 nano::work_pool::generate (nano::root const & root_a, uint64_t difficulty_a) diff --git a/nano/nano_node/entry.cpp b/nano/nano_node/entry.cpp index ea0ef373..9b93c330 100644 --- a/nano/nano_node/entry.cpp +++ b/nano/nano_node/entry.cpp @@ -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; diff --git a/nano/node/active_transactions.cpp b/nano/node/active_transactions.cpp index 75f47060..ffc0ccc7 100644 --- a/nano/node/active_transactions.cpp +++ b/nano/node/active_transactions.cpp @@ -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 (1, node_a.config.active_elections_size / 10)), @@ -708,7 +708,7 @@ void nano::active_transactions::update_adjusted_difficulty () auto existing_root (roots.get ().find (root)); if (existing_root != roots.get ().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::max () - average < static_cast (highest_level)) @@ -778,7 +778,7 @@ void nano::active_transactions::update_active_difficulty (nano::unique_lock 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= 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); diff --git a/nano/node/distributed_work.cpp b/nano/node/distributed_work.cpp index 33ee1815..74368d79 100644 --- a/nano/node/distributed_work.cpp +++ b/nano/node/distributed_work.cpp @@ -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); diff --git a/nano/node/json_handler.cpp b/nano/node/json_handler.cpp index 5edf4b08..c567e6a7 100644 --- a/nano/node/json_handler.cpp +++ b/nano/node/json_handler.cpp @@ -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 difficulty_text (request.get_optional ("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 (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 ("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; } diff --git a/nano/node/node.cpp b/nano/node/node.cpp index bdf4605b..b263d64e 100644 --- a/nano/node/node.cpp +++ b/nano/node/node.cpp @@ -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 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 nano::node::work_generate_blocking (nano::block & block_a, uint64_t difficulty_a) @@ -1028,7 +1028,7 @@ boost::optional 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)> callback_a, boost::optional 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)> callback_a, uint64_t difficulty_a, boost::optional 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 nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, boost::optional 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 nano::node::work_generate_blocking (nano::work_version const version_a, nano::root const & root_a, uint64_t difficulty_a, boost::optional const & account_a) @@ -1060,7 +1060,7 @@ boost::optional nano::node::work_generate_blocking (nano::work_version boost::optional 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 nano::node::work_generate_blocking (nano::root const & root_a, uint64_t difficulty_a) diff --git a/nano/node/nodeconfig.cpp b/nano/node/nodeconfig.cpp index a00fea85..5b68b130 100644 --- a/nano/node/nodeconfig.cpp +++ b/nano/node/nodeconfig.cpp @@ -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 ("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 ("max_queued_requests", max_queued_requests); diff --git a/nano/node/nodeconfig.hpp b/nano/node/nodeconfig.hpp index 995834e1..12f365ad 100644 --- a/nano/node/nodeconfig.hpp +++ b/nano/node/nodeconfig.hpp @@ -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; diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index c0e4a381..c1fcbcdb 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("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 ("multiplier")); ASSERT_NEAR (expected_multiplier, multiplier, 1e-6); auto network_current_text (response.json.get ("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