Merge branch 'feature/son-for-hive-voting' into feature/319-vote_id_type-as-map

This commit is contained in:
Vlad Dobromyslov 2022-03-17 11:24:29 +03:00
commit 6e157ee580
5 changed files with 288 additions and 1 deletions

View file

@ -1085,6 +1085,49 @@ void database::init_genesis(const genesis_state_type& genesis_state)
p.parameters.current_fees = genesis_state.initial_parameters.current_fees;
});
#ifndef NDEBUG
const son_schedule_object& ssohive =
#endif
create<son_schedule_object>([&](son_schedule_object& _sso)
{
// for scheduled
memset(_sso.rng_seed.begin(), 0, _sso.rng_seed.size());
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
auto init_witnesses = get_global_properties().active_witnesses;
_sso.scheduler = son_scheduler();
_sso.scheduler._min_token_count = std::max(int(init_witnesses.size()) / 2, 1);
_sso.last_scheduling_block = 0;
_sso.recent_slots_filled = fc::uint128::max_value();
});
assert( ssohive.id == son_schedule_id_type(1) );
#ifndef NDEBUG
const son_schedule_object& ssobitcoin =
#endif
create<son_schedule_object>([&](son_schedule_object& _sso)
{
// for scheduled
memset(_sso.rng_seed.begin(), 0, _sso.rng_seed.size());
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
auto init_witnesses = get_global_properties().active_witnesses;
_sso.scheduler = son_scheduler();
_sso.scheduler._min_token_count = std::max(int(init_witnesses.size()) / 2, 1);
_sso.last_scheduling_block = 0;
_sso.recent_slots_filled = fc::uint128::max_value();
});
assert( ssobitcoin.id == son_schedule_id_type(2) );
// Create FBA counters
create<fba_accumulator_object>([&]( fba_accumulator_object& acc )

View file

@ -818,6 +818,52 @@ void database::update_active_sons()
_sso.scheduler.produce_schedule(rng);
}
});
// for now put the all active_sons in hive schedule object
// later we will make here the change which will take only son's from
// active_sons that are hive
const son_schedule_object& ssohive = son_schedule_id_type(1)(*this);
modify(ssohive, [&](son_schedule_object& _sso)
{
flat_set<son_id_type> active_sons;
active_sons.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_sons, active_sons.end()),
[](const son_info& swi) {
return swi.son_id;
});
_sso.scheduler.update(active_sons);
// similar to witness, produce schedule for sons
if(cur_active_sons.size() == 0 && new_active_sons.size() > 0)
{
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
for( size_t i=0; i<new_active_sons.size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});
// for now put the all active_sons in bitcoin schedule object
// later we will make here the change which will take only son's from
// active_sons that are bitcoin
const son_schedule_object& ssobitcoin = son_schedule_id_type(2)(*this);
modify(ssobitcoin, [&](son_schedule_object& _sso)
{
flat_set<son_id_type> active_sons;
active_sons.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_sons, active_sons.end()),
[](const son_info& swi) {
return swi.son_id;
});
_sso.scheduler.update(active_sons);
// similar to witness, produce schedule for sons
if(cur_active_sons.size() == 0 && new_active_sons.size() > 0)
{
witness_scheduler_rng rng(_sso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
for( size_t i=0; i<new_active_sons.size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});
} FC_CAPTURE_AND_RETHROW() }
void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const

View file

@ -115,6 +115,49 @@ son_id_type database::get_scheduled_son( uint32_t slot_num )const
return sid;
}
// this is just prototype to prove that active_sons are in hive schedule_object and
// bitcoin schedule object
son_id_type database::get_scheduled_son( sidechain_type type, uint32_t slot_num )const
{
son_id_type sid;
const global_property_object& gpo = get_global_properties();
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM)
{
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
const son_schedule_object& sso = type == sidechain_type::hive ? son_schedule_id_type(1)(*this) : son_schedule_id_type(2)(*this);
uint64_t current_aslot = dpo.current_aslot + slot_num;
return sso.current_shuffled_sons[ current_aslot % sso.current_shuffled_sons.size() ];
}
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM &&
slot_num != 0 )
{
const son_schedule_object& sso = type == sidechain_type::hive ? son_schedule_id_type(1)(*this) : son_schedule_id_type(2)(*this);
// ask the near scheduler who goes in the given slot
bool slot_is_near = sso.scheduler.get_slot(slot_num-1, sid);
if(! slot_is_near)
{
// if the near scheduler doesn't know, we have to extend it to
// a far scheduler.
// n.b. instantiating it is slow, but block gaps long enough to
// need it are likely pretty rare.
witness_scheduler_rng far_rng(sso.rng_seed.begin(), GRAPHENE_FAR_SCHEDULE_CTR_IV);
far_future_son_scheduler far_scheduler =
far_future_son_scheduler(sso.scheduler, far_rng);
if(!far_scheduler.get_slot(slot_num-1, sid))
{
// no scheduled son -- somebody set up us the bomb
// n.b. this code path is impossible, the present
// implementation of far_future_son_scheduler
// returns true unconditionally
assert( false );
}
}
}
return sid;
}
fc::time_point_sec database::get_slot_time(uint32_t slot_num)const
{
if( slot_num == 0 )
@ -192,6 +235,8 @@ void database::update_witness_schedule()
void database::update_son_schedule()
{
const son_schedule_object& sso = son_schedule_id_type()(*this);
const son_schedule_object& ssohive = son_schedule_id_type(1)(*this);
const son_schedule_object& ssobitcoin = son_schedule_id_type(2)(*this);
const global_property_object& gpo = get_global_properties();
if( head_block_num() % gpo.active_sons.size() == 0 )
@ -221,6 +266,58 @@ void database::update_son_schedule()
_sso.current_shuffled_sons[j] );
}
});
modify( ssohive, [&]( son_schedule_object& _sso )
{
_sso.current_shuffled_sons.clear();
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
for( const son_info& w : gpo.active_sons )
_sso.current_shuffled_sons.push_back( w.son_id );
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
{
/// High performance random generator
/// http://xorshift.di.unimi.it/
uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL;
k ^= (k >> 12);
k ^= (k << 25);
k ^= (k >> 27);
k *= 2685821657736338717ULL;
uint32_t jmax = _sso.current_shuffled_sons.size() - i;
uint32_t j = i + k%jmax;
std::swap( _sso.current_shuffled_sons[i],
_sso.current_shuffled_sons[j] );
}
});
modify( ssobitcoin, [&]( son_schedule_object& _sso )
{
_sso.current_shuffled_sons.clear();
_sso.current_shuffled_sons.reserve( gpo.active_sons.size() );
for( const son_info& w : gpo.active_sons )
_sso.current_shuffled_sons.push_back( w.son_id );
auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32;
for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i )
{
/// High performance random generator
/// http://xorshift.di.unimi.it/
uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL;
k ^= (k >> 12);
k ^= (k << 25);
k ^= (k >> 27);
k *= 2685821657736338717ULL;
uint32_t jmax = _sso.current_shuffled_sons.size() - i;
uint32_t j = i + k%jmax;
std::swap( _sso.current_shuffled_sons[i],
_sso.current_shuffled_sons[j] );
}
});
}
}
@ -309,6 +406,8 @@ void database::update_son_schedule(const signed_block& next_block)
auto start = fc::time_point::now();
const global_property_object& gpo = get_global_properties();
const son_schedule_object& sso = get(son_schedule_id_type());
const son_schedule_object& ssohive = get(son_schedule_id_type(1));
const son_schedule_object& ssobitcoin = get(son_schedule_id_type(2));
uint32_t schedule_needs_filled = gpo.active_sons.size();
uint32_t schedule_slot = get_slot_at_time(next_block.timestamp);
@ -321,9 +420,16 @@ void database::update_son_schedule(const signed_block& next_block)
son_id_type first_son;
bool slot_is_near = sso.scheduler.get_slot( schedule_slot-1, first_son );
son_id_type son;
son_id_type first_son_hive;
bool slot_is_near_hive = ssohive.scheduler.get_slot( schedule_slot-1, first_son_hive );
son_id_type son_hive;
son_id_type first_son_bitcoin;
bool slot_is_near_bitcoin = ssobitcoin.scheduler.get_slot( schedule_slot-1, first_son_bitcoin );
son_id_type son_bitcoin;
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
assert( dpo.random.data_size() == witness_scheduler_rng::seed_length );
@ -361,6 +467,72 @@ void database::update_son_schedule(const signed_block& next_block)
(_sso.recent_slots_filled << 1)
+ 1) << (schedule_slot - 1);
});
modify(ssohive, [&](son_schedule_object& _sso)
{
_sso.slots_since_genesis += schedule_slot;
witness_scheduler_rng rng(ssohive.rng_seed.data, _sso.slots_since_genesis);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.size()) / 2, 1);
if( slot_is_near_hive )
{
uint32_t drain = schedule_slot;
while( drain > 0 )
{
if( _sso.scheduler.size() == 0 )
break;
_sso.scheduler.consume_schedule();
--drain;
}
}
else
{
_sso.scheduler.reset_schedule( first_son_hive );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son_hive) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
}
_sso.last_scheduling_block = next_block.block_num();
_sso.recent_slots_filled = (
(_sso.recent_slots_filled << 1)
+ 1) << (schedule_slot - 1);
});
modify(ssobitcoin, [&](son_schedule_object& _sso)
{
_sso.slots_since_genesis += schedule_slot;
witness_scheduler_rng rng(ssohive.rng_seed.data, _sso.slots_since_genesis);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.size()) / 2, 1);
if( slot_is_near_bitcoin )
{
uint32_t drain = schedule_slot;
while( drain > 0 )
{
if( _sso.scheduler.size() == 0 )
break;
_sso.scheduler.consume_schedule();
--drain;
}
}
else
{
_sso.scheduler.reset_schedule( first_son_bitcoin );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son_bitcoin) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
}
_sso.last_scheduling_block = next_block.block_num();
_sso.recent_slots_filled = (
(_sso.recent_slots_filled << 1)
+ 1) << (schedule_slot - 1);
});
auto end = fc::time_point::now();
static uint64_t total_time = 0;
static uint64_t calls = 0;

View file

@ -258,6 +258,22 @@ namespace graphene { namespace chain {
*/
son_id_type get_scheduled_son(uint32_t slot_num)const;
/**
* @brief Get the bitcoin or hive son scheduled for block production in a slot.
*
* slot_num always corresponds to a time in the future.
*
* If slot_num == 1, returns the next scheduled son.
* If slot_num == 2, returns the next scheduled son after
* 1 block gap.
*
* Use the get_slot_time() and get_slot_at_time() functions
* to convert between slot_num and timestamp.
*
* Passing slot_num == 0 returns GRAPHENE_NULL_WITNESS
*/
son_id_type get_scheduled_son(sidechain_type type, uint32_t slot_num)const;
/**
* Get the time at which the given slot occurs.
*

View file

@ -456,6 +456,16 @@ void peerplays_sidechain_plugin_impl::son_processing() {
ilog("Scheduled SON: ${scheduled_son_id} Now: ${now} ",
("scheduled_son_id", scheduled_son_id)("now", now));
// for the test prove that in hive scheduled son is active son
chain::son_id_type scheduled_hive_son_id = plugin.database().get_scheduled_son(sidechain_type::hive ,1);
ilog("Scheduled SON[!HIVE!]: ${scheduled_son_id} Now: ${now} ",
("scheduled_son_id", scheduled_hive_son_id)("now", now));
// for the test prove that in hive scheduled son is active son
chain::son_id_type scheduled_bitcoin_son_id = plugin.database().get_scheduled_son(sidechain_type::bitcoin ,1);
ilog("Scheduled SON[!HIVE!]: ${scheduled_son_id} Now: ${now} ",
("scheduled_son_id", scheduled_bitcoin_son_id)("now", now));
for (son_id_type son_id : plugin.get_sons()) {
if (plugin.is_son_deregistered(son_id)) {
continue;