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

Commit

Permalink
Ref #12, #17: Progress on chain configuration voting
Browse files Browse the repository at this point in the history
Add support for producers specifying their votes on chain configuration
values to CreateProducer and UpdateProducer.

Add more tests around chain configuration, including a failing test case
verifying that the blockchain itself handles configuration updates
correctly. Presently this test fails because the chain does not yet
attempt to keep track of rounds, thus it cannot update the configuration
at the beginning of the round.
  • Loading branch information
nathanielhourt committed May 9, 2017
1 parent a78a354 commit 5e8b89b
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 116 deletions.
43 changes: 33 additions & 10 deletions libraries/chain/BlockchainConfiguration.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
#include <eos/chain/BlockchainConfiguration.hpp>

#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm/nth_element.hpp>

#include <fc/io/json.hpp>

namespace eos { namespace chain {

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

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

BlockchainConfiguration& BlockchainConfiguration::operator=(const types::BlockchainConfiguration& other) {
if (&other != this)
fc::reflector<BlockchainConfiguration>::visit(assign_visitor<types::BlockchainConfiguration>{*this, other});
return *this;
}

template <typename T, typename Range>
struct properties_median_calculator_visitor {
properties_median_calculator_visitor (T& medians, Range votes)
Expand Down Expand Up @@ -34,6 +51,10 @@ BlockchainConfiguration BlockchainConfiguration::get_median_values(
return results;
}

std::ostream& operator<< (std::ostream& s, const BlockchainConfiguration& p) {
return s << fc::json::to_string(p);
}

template <typename T>
struct comparison_visitor {
const T& a;
Expand All @@ -42,21 +63,23 @@ struct comparison_visitor {
template <typename Member, class Class, Member (Class::*member)>
void operator() (const char*) const {
if (a.*member != b.*member)
// Throw to stop comparing fields: the structs are unequal
throw false;
}
};

bool BlockchainConfiguration::operator==(const BlockchainConfiguration& other) const {
try {
fc::reflector<BlockchainConfiguration>::visit(comparison_visitor<BlockchainConfiguration>{*this, other});
} catch (bool) {
return false;
bool operator==(const types::BlockchainConfiguration& a, const types::BlockchainConfiguration& b) {
// Yes, it's gross, I'm using a boolean exception to direct normal control flow... that's why it's buried deep in an
// implementation detail file. I think it's worth it for the generalization, though: this code keeps working no
// matter what updates happen to BlockchainConfiguration
if (&a != &b) {
try {
fc::reflector<BlockchainConfiguration>::visit(comparison_visitor<types::BlockchainConfiguration>{a, b});
} 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
29 changes: 21 additions & 8 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <fc/io/fstream.hpp>

#include <boost/algorithm/string.hpp>
#include <boost/range/adaptor/transformed.hpp>

#include <fstream>
#include <functional>
Expand Down Expand Up @@ -262,11 +263,10 @@ void database::push_transaction(const SignedTransaction& trx, uint32_t skip)
} FC_CAPTURE_AND_RETHROW((trx)) }

void database::_push_transaction(const SignedTransaction& trx) {

// If this is the first transaction pushed after applying a block, start a new undo session.
// This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
if( !_pending_tx_session.valid() )
_pending_tx_session = start_undo_session( true );
if (!_pending_tx_session.valid())
_pending_tx_session = start_undo_session(true);

auto temp_session = start_undo_session(true);
_apply_transaction(trx);
Expand Down Expand Up @@ -318,7 +318,7 @@ signed_block database::_generate_block(
FC_ASSERT( producer_obj.signing_key == block_signing_private_key.get_public_key() );

static const size_t max_block_header_size = fc::raw::pack_size( signed_block_header() ) + 4;
auto maximum_block_size = get_global_properties().parameters.maximum_block_size;
auto maximum_block_size = get_global_properties().configuration.maxBlockSize;
size_t total_block_size = max_block_header_size;

signed_block pending_block;
Expand Down Expand Up @@ -570,12 +570,12 @@ void database::validate_referenced_accounts(const SignedTransaction& trx)const {
void database::validate_expiration(const SignedTransaction& trx) const
{ try {
fc::time_point_sec now = head_block_time();
const chain_parameters& chain_parameters = get_global_properties().parameters;
const BlockchainConfiguration& chain_configuration = get_global_properties().configuration;

EOS_ASSERT(trx.expiration <= now + chain_parameters.maximum_time_until_expiration,
EOS_ASSERT(trx.expiration <= now + int32_t(chain_configuration.maxTrxLifetime),
transaction_exception, "Transaction expiration is too far in the future",
("trx.expiration",trx.expiration)("now",now)
("max_til_exp",chain_parameters.maximum_time_until_expiration));
("max_til_exp",chain_configuration.maxTrxLifetime));
EOS_ASSERT(now <= trx.expiration, transaction_exception, "Transaction is expired",
("now",now)("trx.exp",trx.expiration));
} FC_CAPTURE_AND_RETHROW((trx)) }
Expand Down Expand Up @@ -839,7 +839,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)

// Create global properties
create<global_property_object>([&](global_property_object& p) {
p.parameters = genesis_state.initial_parameters;
p.configuration = genesis_state.initial_configuration;
std::copy(initial_producers.begin(), initial_producers.end(), p.active_producers.begin());
});
create<dynamic_global_property_object>([&](dynamic_global_property_object& p) {
Expand Down Expand Up @@ -1088,6 +1088,19 @@ void database::clear_expired_transactions()
transaction_idx.remove(*dedupe_index.rbegin());
} FC_CAPTURE_AND_RETHROW() }

void database::update_blockchain_configuration() {
auto get_producer = [this](producer_id_type id) { return get(id); };
auto get_votes = [](const producer_object& p) { return p.configuration; };
using boost::adaptors::transformed;

auto votes_range = get_global_properties().active_producers | transformed(get_producer) | transformed(get_votes);

auto medians = BlockchainConfiguration::get_median_values({votes_range.begin(), votes_range.end()});
modify(get_global_properties(), [&medians](global_property_object& p) {
p.configuration = std::move(medians);
});
}

using boost::container::flat_set;

producer_id_type database::get_scheduled_producer(uint32_t slot_num)const
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/get_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ fc::variant_object get_config()

result["KeyPrefix"] = config::KeyPrefix;
result["BlockIntervalSeconds"] = config::BlockIntervalSeconds;
result["MaxBlockSize"] = config::MaxBlockSize;
result["MaxSecondsUntilExpiration"] = config::MaxSecondsUntilExpiration;
result["MaxBlockSize"] = config::DefaultMaxBlockSize;
result["MaxSecondsUntilExpiration"] = config::DefaultMaxTrxLifetime;
result["ProducerCount"] = config::ProducerCount;
result["IrreversibleThresholdPercent"] = config::IrreversibleThresholdPercent;
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ namespace chain {
struct BlockchainConfiguration : public types::BlockchainConfiguration {
using types::BlockchainConfiguration::BlockchainConfiguration;

BlockchainConfiguration& operator= (const types::BlockchainConfiguration& other);

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);
};

bool operator==(const types::BlockchainConfiguration& a, const types::BlockchainConfiguration& b);
inline bool operator!=(const types::BlockchainConfiguration& a, const types::BlockchainConfiguration& b) {
return !(a == b);
}

}
} // namespace eos::chain

Expand Down
46 changes: 0 additions & 46 deletions libraries/chain/include/eos/chain/chain_parameters.hpp

This file was deleted.

16 changes: 14 additions & 2 deletions libraries/chain/include/eos/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@
* THE SOFTWARE.
*/
#pragma once
#include <eos/types/native.hpp>
#include <eos/types/Asset.hpp>

namespace eos { namespace config {
using types::UInt32;
using types::UInt64;
using types::ShareType;
using types::Asset;

const static char KeyPrefix[] = "EOS";

const static int BlockIntervalSeconds = 3;
Expand All @@ -32,8 +39,13 @@ const static int BlockIntervalSeconds = 3;
const static int Percent100 = 10000;
const static int Percent1 = 100;

const static int MaxBlockSize = 256 * 1024;
const static int MaxSecondsUntilExpiration = 60*60;
const static UInt32 DefaultMaxBlockSize = 256 * 1024;
const static UInt32 DefaultTargetBlockSize = 128 * 1024;
const static UInt64 DefaultMaxStorageSize = 10 * 1024;
const static ShareType DefaultElectedPay = Asset(100).amount;
const static ShareType DefaultRunnerUpPay = Asset(75).amount;
const static ShareType DefaultMinEosBalance = Asset(100).amount;
const static UInt32 DefaultMaxTrxLifetime = 60*60;

const static int ProducerCount = 21;
const static int IrreversibleThresholdPercent = 70 * Percent1;
Expand Down
13 changes: 10 additions & 3 deletions libraries/chain/include/eos/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,14 +353,11 @@ namespace eos { namespace chain {
void validate_message_precondition(precondition_validate_context& c)const;
void apply_message(apply_context& c);



bool should_check_for_duplicate_transactions()const { return !(_skip_flags&skip_transaction_dupe_check); }
bool should_check_tapos()const { return !(_skip_flags&skip_tapos_check); }

///Steps involved in applying a new block
///@{

const producer_object& validate_block_header(uint32_t skip, const signed_block& next_block)const;
const producer_object& _validate_block_header(const signed_block& next_block)const;
void create_block_summary(const signed_block& next_block);
Expand All @@ -369,6 +366,16 @@ namespace eos { namespace chain {
void update_signing_producer(const producer_object& signing_producer, const signed_block& new_block);
void update_last_irreversible_block();
void clear_expired_transactions();
/// @}

/**
* @brief Update the blockchain configuration based on the medians of producer votes
*
* Called any time the set of active producers changes or an active producer updates his votes, this method
* will calculate the medians of the active producers' votes on the blockchain configuration values and will
* set the current configuration according to those medians.
*/
void update_blockchain_configuration();

optional<session> _pending_tx_session;
deque<SignedTransaction> _pending_transactions;
Expand Down
15 changes: 12 additions & 3 deletions libraries/chain/include/eos/chain/genesis_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
#pragma once

#include <eos/chain/chain_parameters.hpp>
#include <eos/chain/BlockchainConfiguration.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/immutable_chain_parameters.hpp>

Expand Down Expand Up @@ -62,7 +62,16 @@ struct genesis_state_type {
};

time_point_sec initial_timestamp;
chain_parameters initial_parameters;
BlockchainConfiguration initial_configuration =
{
config::DefaultMaxBlockSize,
config::DefaultTargetBlockSize,
config::DefaultMaxStorageSize,
config::DefaultElectedPay,
config::DefaultRunnerUpPay,
config::DefaultMinEosBalance,
config::DefaultMaxTrxLifetime
};
immutable_chain_parameters immutable_parameters;
vector<initial_account_type> initial_accounts;
vector<initial_producer_type> initial_producers;
Expand All @@ -87,5 +96,5 @@ FC_REFLECT(eos::chain::genesis_state_type::initial_account_type, (name)(balance)
FC_REFLECT(eos::chain::genesis_state_type::initial_producer_type, (owner_name)(block_signing_key))

FC_REFLECT(eos::chain::genesis_state_type,
(initial_timestamp)(initial_parameters)(immutable_parameters)(initial_accounts)
(initial_timestamp)(initial_configuration)(immutable_parameters)(initial_accounts)
(initial_producers)(initial_chain_id))
6 changes: 3 additions & 3 deletions libraries/chain/include/eos/chain/global_property_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#include <fc/uint128.hpp>
#include <fc/array.hpp>

#include <eos/chain/chain_parameters.hpp>
#include <eos/chain/types.hpp>
#include <eos/chain/database.hpp>
#include <eos/chain/BlockchainConfiguration.hpp>

#include <chainbase/chainbase.hpp>

Expand All @@ -48,7 +48,7 @@ namespace eos { namespace chain {
OBJECT_CTOR(global_property_object)

id_type id;
chain_parameters parameters;
BlockchainConfiguration configuration;

std::array<producer_id_type, config::ProducerCount> active_producers;
};
Expand Down Expand Up @@ -139,6 +139,6 @@ FC_REFLECT(eos::chain::dynamic_global_property_object,
)

FC_REFLECT(eos::chain::global_property_object,
(parameters)
(configuration)
(active_producers)
)
4 changes: 2 additions & 2 deletions libraries/chain/include/eos/chain/producer_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace eos { namespace chain {
int64_t total_missed = 0;
uint32_t last_confirmed_block_num = 0;

BlockchainConfiguration properties;
BlockchainConfiguration configuration;
};

struct by_key;
Expand All @@ -63,5 +63,5 @@ FC_REFLECT(eos::chain::producer_object,
(signing_key)
(total_missed)
(last_confirmed_block_num)
(properties)
(configuration)
)
Loading

0 comments on commit 5e8b89b

Please sign in to comment.