[Feature_307] - Create schedule object for hive and bitcoin
This commit is contained in:
parent
25b7d2bf21
commit
1ec31b06f1
5 changed files with 288 additions and 1 deletions
|
|
@ -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 )
|
||||
|
|
|
|||
|
|
@ -823,6 +823,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue