Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Ref #17: Define types, logic, tests
Browse files Browse the repository at this point in the history
This commit adds the BlockchainConfiguration type, which contains the
values to be voted on by producers. It also adds the algorithm to create
a BlockchainConfiguration containing the median values from a vector of
BlockchainConfigurations. Finally, it adds a testcase which verifies that
the median calculation is performed correctly.
  • Loading branch information
nathanielhourt committed May 4, 2017
1 parent 296ef5d commit 0204bcd
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 1 deletion.
62 changes: 62 additions & 0 deletions libraries/chain/BlockchainConfiguration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <eos/chain/BlockchainConfiguration.hpp>

#include <boost/range/algorithm.hpp>

#include <fc/io/json.hpp>

namespace eos { namespace chain {

template <typename T, typename Range>
struct properties_median_calculator_visitor {
properties_median_calculator_visitor (T& medians, Range votes)
: medians(medians), votes(votes)
{}

template <typename Member, class Class, Member (Class::*member)>
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 <typename T, typename Range>
properties_median_calculator_visitor<T, Range> get_median_properties_calculator(T& medians, Range&& votes) {
return properties_median_calculator_visitor<T, Range>(medians, std::move(votes));
}

BlockchainConfiguration BlockchainConfiguration::get_median_values(
std::vector<BlockchainConfiguration> votes) {
BlockchainConfiguration results;
fc::reflector<BlockchainConfiguration>::visit(get_median_properties_calculator(results, std::move(votes)));
return results;
}

template <typename T>
struct comparison_visitor {
const T& a;
const T& b;

template <typename Member, class Class, Member (Class::*member)>
void operator() (const char*) const {
if (a.*member != b.*member)
throw false;
}
};

bool BlockchainConfiguration::operator==(const BlockchainConfiguration& other) const {
try {
fc::reflector<BlockchainConfiguration>::visit(comparison_visitor<BlockchainConfiguration>{*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
2 changes: 1 addition & 1 deletion libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
29 changes: 29 additions & 0 deletions libraries/chain/include/eos/chain/BlockchainConfiguration.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <eos/chain/types.hpp>

#include <eos/types/generated.hpp>

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<BlockchainConfiguration> 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), )
4 changes: 4 additions & 0 deletions libraries/chain/include/eos/chain/producer_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
#pragma once
#include <eos/chain/types.hpp>
#include <eos/chain/BlockchainConfiguration.hpp>

#include "multi_index_includes.hpp"

Expand All @@ -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;
Expand All @@ -60,4 +63,5 @@ FC_REFLECT(eos::chain::producer_object,
(signing_key)
(total_missed)
(last_confirmed_block_num)
(properties)
)
1 change: 1 addition & 0 deletions libraries/chain/include/eos/chain/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions libraries/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down
8 changes: 8 additions & 0 deletions libraries/types/types.eos
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions tests/tests/misc_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <eos/chain/BlockchainConfiguration.hpp>

#include <boost/test/unit_test.hpp>

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<BlockchainConfiguration> 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

0 comments on commit 0204bcd

Please sign in to comment.