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

Commit

Permalink
Resolve #17: Update blockchain configuration on round change
Browse files Browse the repository at this point in the history
The producer-median-voted blockchain configuration parameters are now
updated when the round changes. The previously expected-failing test
case for this now passes
  • Loading branch information
nathanielhourt committed Jun 13, 2017
1 parent dc91c3c commit d0e2c25
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 42 deletions.
34 changes: 16 additions & 18 deletions libraries/chain/chain_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,17 +470,14 @@ void chain_controller::_apply_block(const signed_block& next_block)
}
}

update_global_properties(next_block);
update_global_dynamic_data(next_block);
update_signing_producer(signing_producer, next_block);
update_last_irreversible_block();

create_block_summary(next_block);
clear_expired_transactions();

// TODO: figure out if we could collapse this function into
// update_global_dynamic_data() as perhaps these methods only need
// to be called for header validation?
update_producer_schedule();
if( !_node_property_object.debug_updates.empty() )
apply_debug_updates();

Expand Down Expand Up @@ -706,6 +703,21 @@ void chain_controller::create_block_summary(const signed_block& next_block) {
});
}

void chain_controller::update_global_properties(const signed_block& b) {
// If we're at the end of a round...
if (b.block_num() % config::ProducerCount == 0) {
// Get the new schedule and blockchain configuration
auto schedule = _admin->get_next_round(_db);
auto config = _admin->get_blockchain_configuration(_db, schedule);

_db.modify(get_global_properties(),
[schedule = std::move(schedule), config = std::move(config)] (global_property_object& gpo) {
gpo.active_producers = std::move(schedule);
gpo.configuration = std::move(config);
});
}
}

void chain_controller::add_checkpoints( const flat_map<uint32_t,block_id_type>& checkpts ) {
for (const auto& i : checkpts)
_checkpoints[i.first] = i.second;
Expand Down Expand Up @@ -1022,16 +1034,6 @@ void chain_controller::clear_expired_transactions()
transaction_idx.remove(*dedupe_index.rbegin());
} FC_CAPTURE_AND_RETHROW() }

void chain_controller::update_blockchain_configuration() {
auto config = _admin->get_blockchain_configuration(_db);
const auto& gpo = get_global_properties();

if (config != gpo.configuration)
_db.modify(gpo, [config = std::move(config)](global_property_object& gpo) {
gpo.configuration = std::move(config);
});
}

using boost::container::flat_set;

types::AccountName chain_controller::get_scheduled_producer(uint32_t slot_num)const
Expand Down Expand Up @@ -1077,10 +1079,6 @@ uint32_t chain_controller::producer_participation_rate()const
return uint64_t(config::Percent100) * __builtin_popcountll(dpo.recent_slots_filled) / 64;
}

void chain_controller::update_producer_schedule()
{
}

void chain_controller::set_validate_handler( const AccountName& contract, const AccountName& scope, const TypeName& action, message_validate_handler v ) {
message_validate_handlers[contract][std::make_pair(scope,action)] = v;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class chain_administration_interface {
virtual ~chain_administration_interface();

virtual ProducerRound get_next_round(const chainbase::database& db) = 0;
virtual BlockchainConfiguration get_blockchain_configuration(const chainbase::database& db) = 0;
virtual BlockchainConfiguration get_blockchain_configuration(const chainbase::database& db,
const ProducerRound& round) = 0;
};

} } // namespace eos::chain
12 changes: 1 addition & 11 deletions libraries/chain/include/eos/chain/chain_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,6 @@ namespace eos { namespace chain {
*/
uint32_t get_slot_at_time(fc::time_point_sec when)const;

void update_producer_schedule();

const global_property_object& get_global_properties()const;
const dynamic_global_property_object& get_dynamic_global_properties()const;
const node_property_object& get_node_properties()const;
Expand Down Expand Up @@ -299,21 +297,13 @@ namespace eos { namespace chain {
const producer_object& _validate_block_header(const signed_block& next_block)const;
void create_block_summary(const signed_block& next_block);

void update_global_properties(const signed_block& b);
void update_global_dynamic_data(const signed_block& b);
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();

void spinup_db();
void spinup_fork_db();

Expand Down
7 changes: 3 additions & 4 deletions libraries/chain/include/eos/chain/global_property_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ namespace eos { namespace chain {
{
OBJECT_CTOR(global_property_object)

id_type id;
BlockchainConfiguration configuration;

std::array<AccountName, config::ProducerCount> active_producers;
id_type id;
BlockchainConfiguration configuration;
std::array<AccountName, config::ProducerCount> active_producers;
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace eos { namespace native_contract {

class native_contract_chain_administrator : public chain::chain_administration_interface {

ProducerRound get_next_round(const chainbase::database& db);
chain::BlockchainConfiguration get_blockchain_configuration(const chainbase::database& db);
chain::BlockchainConfiguration get_blockchain_configuration(const chainbase::database& db,
const ProducerRound& round);
};

inline std::unique_ptr<chain::chain_administration_interface> make_administrator() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ namespace eos { namespace native_contract {
using administrator = native_contract_chain_administrator;

administrator::ProducerRound administrator::get_next_round(const chainbase::database& db) {

#warning TODO: Implement me
return db.get(chain::global_property_object::id_type()).active_producers;
}

chain::BlockchainConfiguration administrator::get_blockchain_configuration(const chainbase::database& db) {
chain::BlockchainConfiguration administrator::get_blockchain_configuration(const chainbase::database& db,
const ProducerRound& round) {
using boost::adaptors::transformed;
using types::AccountName;
using chain::producer_object;
Expand All @@ -24,8 +26,7 @@ chain::BlockchainConfiguration administrator::get_blockchain_configuration(const
return db.get<producer_object, chain::by_owner>(owner).configuration;
});

const auto& gpo = db.get(chain::global_property_object::id_type());
auto votes_range = gpo.active_producers | get_producer_votes;
auto votes_range = round | get_producer_votes;

return chain::BlockchainConfiguration::get_median_values({votes_range.begin(), votes_range.end()});
}
Expand Down
1 change: 1 addition & 0 deletions libraries/native_contract/staked_balance_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ void CreateProducer::apply(apply_context& context) {
db.create<producer_object>([&create](producer_object& p) {
p.owner = create.name;
p.signing_key = create.key;
p.configuration = create.configuration;
});
}

Expand Down
50 changes: 48 additions & 2 deletions tests/tests/database_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ BOOST_FIXTURE_TEST_CASE(get_blocks, testing_fixture)
} FC_LOG_AND_RETHROW() }

// Test producer votes on blockchain parameters in full blockchain context
BOOST_FIXTURE_TEST_CASE(producer_voting_parameters, testing_fixture, * boost::unit_test::expected_failures(1))
BOOST_FIXTURE_TEST_CASE(producer_voting_parameters, testing_fixture)
{ try {
Make_Database(db)
db.produce_blocks(21);
Expand Down Expand Up @@ -130,7 +130,53 @@ BOOST_FIXTURE_TEST_CASE(producer_voting_parameters, testing_fixture, * boost::un
db.produce_blocks(20);
BOOST_CHECK_NE(db.get_global_properties().configuration, medians);
db.produce_blocks();
#warning TODO: EXPECTED FAILURE: Round calculations aren't implemented yet, and that's where updating this will happen
BOOST_CHECK_EQUAL(db.get_global_properties().configuration, medians);
} FC_LOG_AND_RETHROW() }

// Test producer votes on blockchain parameters in full blockchain context, with missed blocks
BOOST_FIXTURE_TEST_CASE(producer_voting_parameters_2, testing_fixture)
{ try {
Make_Database(db)
db.produce_blocks(21);

vector<BlockchainConfiguration> votes{
{1024 , 512 , 4096 , Asset(5000 ).amount, Asset(4000 ).amount, Asset(100 ).amount, 512 },
{10000 , 100 , 4096 , Asset(3333 ).amount, Asset(27109 ).amount, Asset(10 ).amount, 100 },
{2048 , 1500 , 1000 , Asset(5432 ).amount, Asset(2000 ).amount, Asset(50 ).amount, 1500 },
{100 , 25 , 1024 , Asset(90000 ).amount, Asset(0 ).amount, Asset(433 ).amount, 25 },
{1024 , 1000 , 100 , Asset(10 ).amount, Asset(50 ).amount, Asset(200 ).amount, 1000 },
{420 , 400 , 2710 , Asset(27599 ).amount, Asset(1177 ).amount, Asset(27720).amount, 400 },
{271 , 200 , 66629 , Asset(2666 ).amount, Asset(99991 ).amount, Asset(277 ).amount, 200 },
{1057 , 1000 , 2770 , Asset(972 ).amount, Asset(302716 ).amount, Asset(578 ).amount, 1000 },
{9926 , 27 , 990 , Asset(99999 ).amount, Asset(39651 ).amount, Asset(4402 ).amount, 27 },
{1005 , 1000 , 1917 , Asset(937111 ).amount, Asset(2734 ).amount, Asset(1 ).amount, 1000 },
{80 , 70 , 5726 , Asset(63920 ).amount, Asset(231561 ).amount, Asset(27100).amount, 70 },
{471617, 333333, 100 , Asset(2666 ).amount, Asset(2650 ).amount, Asset(2772 ).amount, 333333},
{2222 , 1000 , 100 , Asset(33619 ).amount, Asset(1046 ).amount, Asset(10577).amount, 1000 },
{8 , 7 , 100 , Asset(5757267).amount, Asset(2257 ).amount, Asset(2888 ).amount, 7 },
{2717 , 2000 , 57797 , Asset(3366 ).amount, Asset(205 ).amount, Asset(4472 ).amount, 2000 },
{9997 , 5000 , 27700 , Asset(29199 ).amount, Asset(100 ).amount, Asset(221 ).amount, 5000 },
{163900, 200 , 882 , Asset(100 ).amount, Asset(5720233).amount, Asset(105 ).amount, 200 },
{728 , 80 , 27100 , Asset(28888 ).amount, Asset(6205 ).amount, Asset(5011 ).amount, 80 },
{91937 , 44444 , 652589, Asset(87612 ).amount, Asset(123 ).amount, Asset(2044 ).amount, 44444 },
{171 , 96 , 123456, Asset(8402 ).amount, Asset(321 ).amount, Asset(816 ).amount, 96 },
{17177 , 6767 , 654321, Asset(9926 ).amount, Asset(9264 ).amount, Asset(8196 ).amount, 6767 },
};
BlockchainConfiguration medians =
{1057, 512, 2770, Asset(9926).amount, Asset(2650).amount, Asset(816).amount, 512};
// If this fails, the medians variable probably needs to be updated to have the medians of the votes above
BOOST_REQUIRE_EQUAL(BlockchainConfiguration::get_median_values(votes), medians);

for (int i = 0; i < votes.size(); ++i) {
auto name = std::string("init") + fc::to_string(i);
Update_Producer(db, name, db.get_producer(name).signing_key, votes[i]);
}

BOOST_CHECK_NE(db.get_global_properties().configuration, medians);
db.produce_blocks(2);
db.produce_blocks(18, 5);
BOOST_CHECK_NE(db.get_global_properties().configuration, medians);
db.produce_blocks();
BOOST_CHECK_EQUAL(db.get_global_properties().configuration, medians);
} FC_LOG_AND_RETHROW() }

Expand Down

0 comments on commit d0e2c25

Please sign in to comment.