diff --git a/libraries/chain/BlockchainConfiguration.cpp b/libraries/chain/BlockchainConfiguration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cf3a5af9d88c5807009c664094576a4cc0e9307 --- /dev/null +++ b/libraries/chain/BlockchainConfiguration.cpp @@ -0,0 +1,62 @@ +#include + +#include + +#include + +namespace eos { namespace chain { + +template +struct properties_median_calculator_visitor { + properties_median_calculator_visitor (T& medians, Range votes) + : medians(medians), votes(votes) + {} + + template + void operator() (const char*) const { + auto median_itr = boost::begin(votes) + boost::distance(votes)/2; + boost::nth_element(votes, median_itr, [](const T& a, const T& b) { return a.*member < b.*member; }); + medians.*member = (*median_itr).*member; + } + + T& medians; + mutable Range votes; +}; +template +properties_median_calculator_visitor get_median_properties_calculator(T& medians, Range&& votes) { + return properties_median_calculator_visitor(medians, std::move(votes)); +} + +BlockchainConfiguration BlockchainConfiguration::get_median_values( + std::vector votes) { + BlockchainConfiguration results; + fc::reflector::visit(get_median_properties_calculator(results, std::move(votes))); + return results; +} + +template +struct comparison_visitor { + const T& a; + const T& b; + + template + void operator() (const char*) const { + if (a.*member != b.*member) + throw false; + } +}; + +bool BlockchainConfiguration::operator==(const BlockchainConfiguration& other) const { + try { + fc::reflector::visit(comparison_visitor{*this, other}); + } catch (bool) { + return false; + } + return true; +} + +std::ostream& operator<< (std::ostream& s, const BlockchainConfiguration& p) { + return s << fc::json::to_string(p); +} + +} } // namespace eos::chain diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index f07c3f5bb1b52e6e0e32ed834b8aedef068fa916..64b89b7d815942bf7c82f36bf4501051bc0b3bb8 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -12,9 +12,9 @@ add_library( eos_chain get_config.cpp block_log.cpp + BlockchainConfiguration.cpp ${HEADERS} - ${PROTOCOL_HEADERS} ) target_link_libraries( eos_chain fc chainbase eos_types wren ) diff --git a/libraries/chain/include/eos/chain/BlockchainConfiguration.hpp b/libraries/chain/include/eos/chain/BlockchainConfiguration.hpp new file mode 100644 index 0000000000000000000000000000000000000000..34715a8b6f0112e6764a894d8340d2517ff29554 --- /dev/null +++ b/libraries/chain/include/eos/chain/BlockchainConfiguration.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include + +namespace eos { +namespace chain { + +/** + * @brief Producer-voted blockchain configuration parameters + * + * This object stores the blockchain configuration, which is set by the block producers. Block producers each vote for + * their preference for each of the parameters in this object, and the blockchain runs according to the median of the + * values specified by the producers. + */ +struct BlockchainConfiguration : public types::BlockchainConfiguration { + using types::BlockchainConfiguration::BlockchainConfiguration; + + static BlockchainConfiguration get_median_values(std::vector votes); + + bool operator==(const BlockchainConfiguration& other) const; + friend std::ostream& operator<< (std::ostream& s, const BlockchainConfiguration& p); +}; + +} +} // namespace eos::chain + +FC_REFLECT_DERIVED(eos::chain::BlockchainConfiguration, (eos::types::BlockchainConfiguration), ) diff --git a/libraries/chain/include/eos/chain/producer_object.hpp b/libraries/chain/include/eos/chain/producer_object.hpp index 7668e17de2f815903d5ac920a4ec74438188af47..ccf42dac8f72186d1ac4b4b4460888dee84c3ba2 100644 --- a/libraries/chain/include/eos/chain/producer_object.hpp +++ b/libraries/chain/include/eos/chain/producer_object.hpp @@ -23,6 +23,7 @@ */ #pragma once #include +#include #include "multi_index_includes.hpp" @@ -37,6 +38,8 @@ namespace eos { namespace chain { public_key_type signing_key; int64_t total_missed = 0; uint32_t last_confirmed_block_num = 0; + + BlockchainConfiguration properties; }; struct by_key; @@ -60,4 +63,5 @@ FC_REFLECT(eos::chain::producer_object, (signing_key) (total_missed) (last_confirmed_block_num) + (properties) ) diff --git a/libraries/chain/include/eos/chain/types.hpp b/libraries/chain/include/eos/chain/types.hpp index 0a3a3b8e0d65e17952ee51d19f7fb45b4679b7fe..3cb871df0600a9aba357326fa70d42ce3dab4f22 100644 --- a/libraries/chain/include/eos/chain/types.hpp +++ b/libraries/chain/include/eos/chain/types.hpp @@ -113,6 +113,7 @@ namespace eos { namespace chain { using eos::types::AccountName; using eos::types::PermissionName; using eos::types::Asset; + using eos::types::ShareType; using eos::types::Authority; using eos::types::PermissionName; using eos::types::TypeName; diff --git a/libraries/types/CMakeLists.txt b/libraries/types/CMakeLists.txt index b3386047539c3b3d2873b303c1d83b52c3291dbd..f3b64f814892a0378bae2cbf46d4f52ee7354266 100644 --- a/libraries/types/CMakeLists.txt +++ b/libraries/types/CMakeLists.txt @@ -7,6 +7,7 @@ add_library( eos_types native.cpp ${HEADERS} "${CMAKE_CURRENT_SOURCE_DIR}/include/eos/types/generated.hpp" + types.eos ) target_include_directories( eos_types PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) target_link_libraries( eos_types eos_utilities fc ) diff --git a/libraries/types/types.eos b/libraries/types/types.eos index dbca75510b7ba8cc1c9df8dcc5b4db425324e5d8..35f9367d085075ddc174afdc40f1ae2b2e1f85d4 100644 --- a/libraries/types/types.eos +++ b/libraries/types/types.eos @@ -40,6 +40,14 @@ struct Authority keys KeyPermissionWeight[] accounts AccountPermissionWeight[] +struct BlockchainConfiguration + maxBlockSize UInt32 + targetBlockSize UInt32 + maxStorageSize UInt64 + electedPay ShareType + runnerUpPay ShareType + minAccountBalance ShareType + struct Transfer from AccountName # may not be the message.sender if message.sender has delegated authority by from to AccountName diff --git a/tests/tests/misc_tests.cpp b/tests/tests/misc_tests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15153735584e6d2d201727af01efc38d9b9f7ba1 --- /dev/null +++ b/tests/tests/misc_tests.cpp @@ -0,0 +1,36 @@ +#include + +#include + +namespace eos { +using namespace chain; + +BOOST_AUTO_TEST_SUITE(misc_tests) + +/// Test calculation of median values of blockchain operation properties +BOOST_AUTO_TEST_CASE(median_properties_test) +{ try { + vector votes{ + {1024 , 512 , 4096 , Asset(5000 ).amount, Asset(4000 ).amount, Asset(100 ).amount}, + {10000 , 100 , 4096 , Asset(3333 ).amount, Asset(27109 ).amount, Asset(10 ).amount}, + {2048 , 1500 , 1000 , Asset(5432 ).amount, Asset(2000 ).amount, Asset(50 ).amount}, + {100 , 25 , 1024 , Asset(90000 ).amount, Asset(0 ).amount, Asset(433 ).amount}, + {1024 , 1000 , 100 , Asset(10 ).amount, Asset(50 ).amount, Asset(200 ).amount}, + }; + BlockchainConfiguration medians{ + 1024, 512, 1024, Asset(5000).amount, Asset(2000).amount, Asset(100).amount + }; + + BOOST_CHECK_EQUAL(BlockchainConfiguration::get_median_values(votes), medians); + + votes.emplace_back(BlockchainConfiguration{1, 1, 1, 1, 1, 1}); + votes.emplace_back(BlockchainConfiguration{1, 1, 1, 1, 1, 1}); + medians = {1024, 100, 1000, Asset(3333).amount, Asset(50).amount, Asset(50).amount}; + + BOOST_CHECK_EQUAL(BlockchainConfiguration::get_median_values(votes), medians); + BOOST_CHECK_EQUAL(BlockchainConfiguration::get_median_values({medians}), medians); +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace eos