From 773be4f6c0526db6edfdb6fa36a7b1e1e5dbe91c Mon Sep 17 00:00:00 2001 From: Guilherme Lawless Date: Mon, 16 Mar 2020 15:47:02 +0000 Subject: [PATCH] Definitions for work thresholds with epoch_2 (#2638) * Definitions for work thresholds with epoch_2 This article outlines the decision process for these thresholds: [Development Update: V21 PoW Difficulty Increases](https://medium.com/nanocurrency/development-update-v21-pow-difficulty-increases-362b5d052c8e). Only adds definitions, `nano::work_threshold (version, details)` is not yet used anywhere besides tests. * Add temporary work validation in blockprocessor::add until ledger validation is in * Formatting --- nano/core_test/difficulty.cpp | 5 ++++- nano/lib/config.hpp | 13 ++++++++--- nano/lib/work.cpp | 42 ++++++++++++++++++++++++++++++++++- nano/lib/work.hpp | 5 +++++ nano/node/blockprocessor.cpp | 2 ++ 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/nano/core_test/difficulty.cpp b/nano/core_test/difficulty.cpp index d2193ab2..75760e1b 100644 --- a/nano/core_test/difficulty.cpp +++ b/nano/core_test/difficulty.cpp @@ -62,7 +62,10 @@ TEST (difficulty, multipliers) TEST (difficulty, network_constants) { - ASSERT_NEAR (64., nano::difficulty::to_multiplier (nano::network_constants::publish_full_threshold, nano::network_constants::publish_beta_threshold), 1e-10); + 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); } TEST (difficulty, overflow) diff --git a/nano/lib/config.hpp b/nano/lib/config.hpp index 7a4f9157..38d48609 100644 --- a/nano/lib/config.hpp +++ b/nano/lib/config.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace boost @@ -76,6 +77,7 @@ public: network_constants (nano_networks network_a) : current_network (network_a) { + // 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 @@ -88,9 +90,14 @@ public: request_interval_ms = is_test_network () ? 20 : 500; } - /** Network work thresholds. ~5 seconds of work for the live network */ - static uint64_t const publish_full_threshold{ 0xffffffc000000000 }; - static uint64_t const publish_beta_threshold{ 0xfffff00000000000 }; // 64x lower than full + /** 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 /** Error message when an invalid network is specified */ diff --git a/nano/lib/work.cpp b/nano/lib/work.cpp index 2983d39e..323452f0 100644 --- a/nano/lib/work.cpp +++ b/nano/lib/work.cpp @@ -54,7 +54,21 @@ uint64_t nano::work_threshold (nano::work_version const version_a) result = nano::work_v1::threshold (); break; default: - debug_assert (false && "Invalid version specified to work_threshold"); + debug_assert (false && "Invalid version specified to entry work_threshold"); + } + return result; +} + +uint64_t nano::work_threshold (nano::work_version const version_a, nano::block_details const details_a) +{ + uint64_t result{ std::numeric_limits::max () }; + switch (version_a) + { + case nano::work_version::work_1: + result = nano::work_v1::threshold (details_a); + break; + default: + debug_assert (false && "Invalid version specified to ledger work_threshold"); } return result; } @@ -65,6 +79,32 @@ uint64_t nano::work_v1::threshold () return network_constants.publish_threshold; } +uint64_t nano::work_v1::threshold (nano::block_details const details_a) +{ + static_assert (nano::epoch::max == nano::epoch::epoch_2, "work_v1::threshold is ill-defined"); + static nano::network_constants network_constants; + + if (!network_constants.is_live_network ()) + { + return network_constants.publish_threshold; + } + + 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; + break; + case nano::epoch::epoch_1: + case nano::epoch::epoch_0: + result = nano::network_constants::publish_full_epoch_1_threshold; + break; + default: + debug_assert (false && "Invalid epoch specified to work_v1 ledger work_threshold"); + } + return result; +} + #ifndef NANO_FUZZER_TEST uint64_t nano::work_v1::value (nano::root const & root_a, uint64_t work_a) { diff --git a/nano/lib/work.hpp b/nano/lib/work.hpp index b64ff8ad..031d21e3 100644 --- a/nano/lib/work.hpp +++ b/nano/lib/work.hpp @@ -21,16 +21,21 @@ enum class work_version std::string to_string (nano::work_version const version_a); class block; +class block_details; bool work_validate (nano::block const &); bool work_validate (nano::work_version const, nano::root const &, uint64_t const); uint64_t work_difficulty (nano::work_version const, nano::root const &, uint64_t const); +// Entry threshold uint64_t work_threshold (nano::work_version const); +// Ledger threshold +uint64_t work_threshold (nano::work_version const, nano::block_details const); namespace work_v1 { uint64_t value (nano::root const & root_a, uint64_t work_a); uint64_t threshold (); + uint64_t threshold (nano::block_details const); } class opencl_work; class work_item final diff --git a/nano/node/blockprocessor.cpp b/nano/node/blockprocessor.cpp index cecaad5b..a68b83ec 100644 --- a/nano/node/blockprocessor.cpp +++ b/nano/node/blockprocessor.cpp @@ -75,7 +75,9 @@ void nano::block_processor::add (std::shared_ptr block_a, uint64_t void nano::block_processor::add (nano::unchecked_info const & info_a) { + debug_assert (!nano::work_validate (*info_a.block)); bool should_notify{ false }; + if (info_a.block->difficulty () >= nano::work_threshold (info_a.block->work_version ())) { nano::lock_guard lock (mutex); if (info_a.verified == nano::signature_verification::unknown && (info_a.block->type () == nano::block_type::state || info_a.block->type () == nano::block_type::open || !info_a.account.is_zero ()))