14 namespace witness_schedule {
44 const auto& witness_obj = witness_service.
get(witness);
45 ret.
items.push_back({ witness_obj.id, witness, witness_obj.votes, witness_obj.virtual_scheduled_time });
56 void database::update_witness_schedule()
64 debug_log(ctx,
"update_witness_schedule");
67 auto& witness_service =
_db.witness_service();
69 const witness_schedule_object& wso = schedule_service.get();
71 using active_witnesses_container = boost::container::flat_map<witness_id_type, account_name_type>;
73 active_witnesses_container active_witnesses;
76 const auto& widx =
_db.get_index<
witness_index>().indices().get<by_vote_name>();
78 for (
auto itr = widx.begin(); itr != widx.end(); ++itr)
80 debug_log(ctx,
"witness=${w}", (
"w", *itr));
85 if (itr->signing_key == public_key_type())
90 debug_log(ctx,
"active=${active}", (
"active", itr->owner));
92 FC_ASSERT(active_witnesses.insert(std::make_pair(itr->id, itr->owner)).second);
97 fc::uint128 new_virtual_time = wso.current_virtual_time;
99 const auto& schedule_idx =
_db.get_index<
witness_index>().indices().get<by_schedule_time>();
100 auto sitr = schedule_idx.begin();
101 std::vector<decltype(sitr)> processed_witnesses;
105 new_virtual_time = sitr->virtual_scheduled_time;
106 processed_witnesses.push_back(sitr);
108 if (sitr->signing_key == public_key_type())
113 if (active_witnesses.find(sitr->id) == active_witnesses.end())
115 FC_ASSERT(active_witnesses.insert(std::make_pair(sitr->id, sitr->owner)).second);
118 debug_log(ctx,
"runner=${runner}", (
"runner", *sitr));
122 debug_log(ctx,
"number_of_active_witnesses=${active_witnesses}", (
"active_witnesses", active_witnesses.size()));
126 for (
auto itr = processed_witnesses.begin(); itr != processed_witnesses.end(); ++itr)
128 auto new_virtual_scheduled_time
129 = new_virtual_time + VIRTUAL_SCHEDULE_LAP_LENGTH / ((*itr)->votes.value + 1);
130 if (new_virtual_scheduled_time < new_virtual_time)
133 new_virtual_time = fc::uint128();
134 _reset_witness_virtual_schedule_time();
137 _db.modify(*(*itr), [&](witness_object& wo) {
138 wo.virtual_position = fc::uint128();
139 wo.virtual_last_update = new_virtual_time;
140 wo.virtual_scheduled_time = new_virtual_scheduled_time;
142 debug_log(ctx,
"update_wo=${wo}", (
"wo", wo));
146 schedule_service.update([&](witness_schedule_object& _wso) {
147 for (
size_t i = 0; i < active_witnesses.size(); i++)
149 _wso.current_shuffled_witnesses[i] = active_witnesses.nth(i)->second;
157 _wso.num_scheduled_witnesses = std::max<uint8_t>(active_witnesses.size(), 1);
160 auto now_hi = uint64_t(
_db.head_block_time().sec_since_epoch()) << 32;
162 debug_log(ctx,
"head_block_time=${t}", (
"t",
_db.head_block_time().to_iso_string()));
163 debug_log(ctx,
"now_hi=${now_hi}", (
"now_hi", now_hi));
165 debug_log(ctx,
"before_shufle=${schedule}",
168 for (uint32_t i = 0; i < _wso.num_scheduled_witnesses; ++i)
172 uint64_t k = now_hi + uint64_t(i) * 2685821657736338717ULL;
176 k *= 2685821657736338717ULL;
178 uint32_t jmax = _wso.num_scheduled_witnesses - i;
179 uint32_t j = i + k % jmax;
180 std::swap(_wso.current_shuffled_witnesses[i], _wso.current_shuffled_witnesses[j]);
183 _wso.current_virtual_time = new_virtual_time;
186 debug_log(ctx,
"new_schedule=${schedule}",
189 _update_witness_majority_version();
190 _update_witness_hardfork_version_votes();
191 _update_witness_median_props();
195 void database::_reset_witness_virtual_schedule_time()
199 block_info ctx =
_db.head_block_context();
201 debug_log(ctx,
"_reset_witness_virtual_schedule_time");
205 schedule_service.update([&](witness_schedule_object& o) {
206 o.current_virtual_time = fc::uint128();
209 const witness_schedule_object& wso = schedule_service.get();
212 for (
const auto& witness : idx)
214 _db.modify(witness, [&](witness_object& wobj) {
215 wobj.virtual_position = fc::uint128();
216 wobj.virtual_last_update = wso.current_virtual_time;
217 wobj.virtual_scheduled_time = VIRTUAL_SCHEDULE_LAP_LENGTH / (wobj.votes.value + 1);
222 void database::_update_witness_median_props()
229 auto& witness_service =
_db.witness_service();
232 std::vector<const witness_object*>
active;
233 active.reserve(wso.num_scheduled_witnesses);
234 for (
int i = 0; i < wso.num_scheduled_witnesses; i++)
236 active.push_back(&witness_service.get(wso.current_shuffled_witnesses[i]));
240 std::sort(
active.begin(),
active.end(), [&](
const witness_object* a,
const witness_object* b) {
241 return a->proposed_chain_props.account_creation_fee.amount < b->proposed_chain_props.account_creation_fee.amount;
243 asset median_account_creation_fee =
active[
active.size() / 2]->proposed_chain_props.account_creation_fee;
246 std::sort(
active.begin(),
active.end(), [&](
const witness_object* a,
const witness_object* b) {
247 return a->proposed_chain_props.maximum_block_size < b->proposed_chain_props.maximum_block_size;
249 uint32_t median_maximum_block_size =
active[
active.size() / 2]->proposed_chain_props.maximum_block_size;
251 _db.obtain_service<dbs_dynamic_global_property>().
update([&](dynamic_global_property_object& _dgpo) {
252 _dgpo.median_chain_props.account_creation_fee = median_account_creation_fee;
253 _dgpo.median_chain_props.maximum_block_size = median_maximum_block_size;
259 void database::_update_witness_majority_version()
264 auto& witness_service =
_db.witness_service();
266 flat_map<version, uint32_t, std::greater<version>> witness_versions;
267 for (uint32_t i = 0; i < wso.num_scheduled_witnesses; i++)
269 auto witness = witness_service.get(wso.current_shuffled_witnesses[i]);
270 if (witness_versions.find(witness.running_version) == witness_versions.end())
272 witness_versions[witness.running_version] = 1;
276 witness_versions[witness.running_version] += 1;
280 auto majority_version =
_db.obtain_service<dbs_dynamic_global_property>().get().majority_version;
284 for (
auto ver_itr = witness_versions.begin(); ver_itr != witness_versions.end(); ++ver_itr)
286 auto witnesses_on_version = ver_itr->second;
289 majority_version = ver_itr->first;
294 _db.obtain_service<dbs_dynamic_global_property>().
update(
295 [&](dynamic_global_property_object& _dgpo) { _dgpo.majority_version = majority_version; });
298 void database::_update_witness_hardfork_version_votes()
303 auto& witness_service =
_db.witness_service();
305 flat_map<std::tuple<hardfork_version, time_point_sec>, uint32_t> hardfork_version_votes;
307 for (uint32_t i = 0; i < wso.num_scheduled_witnesses; i++)
309 auto witness = witness_service.get(wso.current_shuffled_witnesses[i]);
311 auto version_vote = std::make_tuple(witness.hardfork_version_vote, witness.hardfork_time_vote);
312 if (hardfork_version_votes.find(version_vote) == hardfork_version_votes.end())
314 hardfork_version_votes[version_vote] = 1;
318 hardfork_version_votes[version_vote] += 1;
322 auto hf_itr = hardfork_version_votes.begin();
324 while (hf_itr != hardfork_version_votes.end())
328 const auto& hfp =
_db.obtain_service<dbs_hardfork_property>().get();
329 if (hfp.next_hardfork != std::get<0>(hf_itr->first) || hfp.next_hardfork_time != std::get<1>(hf_itr->first))
331 _db.modify(hfp, [&](hardfork_property_object& hpo) {
332 hpo.next_hardfork = std::get<0>(hf_itr->first);
333 hpo.next_hardfork_time = std::get<1>(hf_itr->first);
343 if (hf_itr == hardfork_version_votes.end())
345 _db.obtain_service<dbs_hardfork_property>().
update(
346 [&](hardfork_property_object& hpo) { hpo.next_hardfork = hpo.current_hardfork_version; });
354 (witness_id)(witness_name)(votes)(virtual_scheduled_time))
fc::uint128 current_virtual_time
uint8_t num_scheduled_witnesses
fc::array< account_name_type, SCORUM_MAX_WITNESSES_LIMIT > current_shuffled_witnesses
#define SCORUM_MAX_VOTED_WITNESSES
#define SCORUM_HARDFORK_REQUIRED_WITNESSES
#define SCORUM_MAX_WITNESSES_LIMIT
#define SCORUM_MAX_WITNESSES
#define debug_log(CTX, FORMAT,...)
FC_REFLECT(appender_args,(appender)(stream)) FC_REFLECT_DERIVED(file_appender_args
printable_schedule get_witness_schedule(const witness_schedule_object &wso, witness_service_i &witness_service)
std::vector< printable_schedule_item > schedule_type
void update(fc::flat_map< uuid_type, bet_resolved_operation > &results, const bet_data &bet, asset income, uuid_type game_uuid, bet_resolve_kind kind)
shared_multi_index_container< witness_object, indexed_by< ordered_unique< tag< by_id >, member< witness_object, witness_id_type, &witness_object::id > >, ordered_unique< tag< by_name >, member< witness_object, account_name_type, &witness_object::owner > >, ordered_unique< tag< by_vote_name >, composite_key< witness_object, member< witness_object, share_type, &witness_object::votes >, member< witness_object, account_name_type, &witness_object::owner > >, composite_key_compare< std::greater< share_type >, std::less< account_name_type > > >, ordered_unique< tag< by_schedule_time >, composite_key< witness_object, member< witness_object, fc::uint128, &witness_object::virtual_scheduled_time >, member< witness_object, witness_id_type, &witness_object::id > > > > > witness_index
dbs_service_base< witness_schedule_service_i > dbs_witness_schedule
fc::safe< share_value_type > share_type
fc::fixed_string_16 account_name_type
fc::uint128 virtual_scheduled_time
witness_id_type witness_id
account_name_type witness_name
uint8_t num_scheduled_witnesses
fc::uint128 current_virtual_time
virtual const witness_object & get(const account_name_type &owner) const =0