#308 List of active SONs per sidechain

This commit is contained in:
serkixenos 2022-04-07 19:06:07 +00:00
parent 94a3998d7a
commit eb5ef77aee
26 changed files with 734 additions and 511 deletions

View file

@ -700,7 +700,12 @@ void database::_apply_block( const signed_block& next_block )
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM) {
update_witness_schedule(next_block);
if(global_props.active_sons.size() > 0) {
bool need_to_update_son_schedule = false;
for(const auto& active_sons : global_props.active_sons){
if(!active_sons.second.empty())
need_to_update_son_schedule = true;
}
if(need_to_update_son_schedule) {
update_son_schedule(next_block);
}
}
@ -737,6 +742,8 @@ void database::_apply_block( const signed_block& next_block )
update_maintenance_flag( maint_needed );
if (global_props.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SHUFFLED_ALGORITHM) {
update_witness_schedule();
//! Fixme - here we should take active_sons size for sidechain
if(global_props.active_sons.size() > 0) {
update_son_schedule();
}

View file

@ -222,11 +222,18 @@ std::set<son_id_type> database::get_sons_to_be_deregistered()
for( auto& son : son_idx )
{
if(son.status == son_status::in_maintenance)
bool need_to_be_deregistered = true;
for(const auto& status : son.statuses)
{
if(status.second != son_status::in_maintenance)
need_to_be_deregistered = false;
}
if(need_to_be_deregistered)
{
auto stats = son.statistics(*this);
// TODO : We need to add a function that returns if we can deregister SON
// i.e. with introduction of PW code, we have to make a decision if the SON
// TODO : We need to add a function that returns if we can deregister SON
// i.e. with introduction of PW code, we have to make a decision if the SON
// is needed for release of funds from the PW
if(head_block_time() - stats.last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time()))
{
@ -289,11 +296,18 @@ bool database::is_son_dereg_valid( son_id_type son_id )
return false;
}
return (son->status == son_status::in_maintenance &&
bool status_in_maintenance = true;
for(const auto& status : son->statuses)
{
if(status.second != son_status::in_maintenance)
status_in_maintenance = false;
}
return (status_in_maintenance &&
(head_block_time() - son->statistics(*this).last_down_timestamp >= fc::seconds(get_global_properties().parameters.son_deregister_time())));
}
bool database::is_son_active( son_id_type son_id )
bool database::is_son_active( sidechain_type type, son_id_type son_id )
{
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
auto son = son_idx.find( son_id );
@ -303,9 +317,15 @@ bool database::is_son_active( son_id_type son_id )
}
const global_property_object& gpo = get_global_properties();
if(!gpo.active_sons.contains(type))
{
return false;
}
const auto& gpo_as = gpo.active_sons.at(type);
vector<son_id_type> active_son_ids;
active_son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
active_son_ids.reserve(gpo_as.size());
std::transform(gpo_as.cbegin(), gpo_as.cend(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info& swi) {
return swi.son_id;

View file

@ -84,7 +84,7 @@ vector<std::reference_wrapper<const son_object>> database::sort_votable_objects<
std::vector<std::reference_wrapper<const son_object>> refs;
for( auto& son : all_sons )
{
if(son.has_valid_config(head_block_time()) && son.status != son_status::deregistered)
if(son.has_valid_config(head_block_time()) && son.statuses.at(sidechain) != son_status::deregistered)
{
refs.push_back(std::cref(son));
}
@ -186,6 +186,7 @@ void database::pay_sons()
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
// Current requirement is that we have to pay every 24 hours, so the following check
if( dpo.son_budget.value > 0 && ((now - dpo.last_son_payout_time) >= fc::seconds(get_global_properties().parameters.son_pay_time()))) {
//! Fixme - sort_votable_objects only for bitcoin
auto sons = sort_votable_objects<son_index>(sidechain_type::bitcoin, get_global_properties().parameters.maximum_son_count());
// After SON2 HF
uint64_t total_votes = 0;
@ -280,122 +281,131 @@ void database::pay_sons()
}
}
void database::update_son_metrics(const vector<son_info>& curr_active_sons)
void database::update_son_metrics(const flat_map<sidechain_type, vector<son_info> >& curr_active_sons)
{
vector<son_id_type> current_sons;
for(const auto& curr_active_sidechain_sons : curr_active_sons) {
const auto& sidechain = curr_active_sidechain_sons.first;
const auto& _curr_active_sidechain_sons = curr_active_sidechain_sons.second;
current_sons.reserve(curr_active_sons.size());
std::transform(curr_active_sons.begin(), curr_active_sons.end(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
vector<son_id_type> current_sons;
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
for( auto& son : son_idx )
{
auto& stats = son.statistics(*this);
bool is_active_son = (std::find(current_sons.begin(), current_sons.end(), son.id) != current_sons.end());
modify( stats, [&]( son_statistics_object& _stats )
{
if(is_active_son) {
_stats.total_voted_time = _stats.total_voted_time + get_global_properties().parameters.maintenance_interval;
}
_stats.total_downtime += _stats.current_interval_downtime;
_stats.current_interval_downtime = 0;
for (const auto &str : _stats.sidechain_txs_reported) {
_stats.sidechain_txs_reported.at(str.first) = 0;
}
});
current_sons.reserve(_curr_active_sidechain_sons.size());
std::transform(_curr_active_sidechain_sons.cbegin(), _curr_active_sidechain_sons.cend(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
const auto &son_idx = get_index_type<son_index>().indices().get<by_id>();
for (auto &son : son_idx) {
auto &stats = son.statistics(*this);
bool is_active_son = (std::find(current_sons.begin(), current_sons.end(), son.id) != current_sons.end());
modify(stats, [&](son_statistics_object &_stats) {
if (is_active_son) {
_stats.total_voted_time[sidechain] = _stats.total_voted_time[sidechain] + get_global_properties().parameters.maintenance_interval;
}
_stats.total_downtime[sidechain] += _stats.current_interval_downtime[sidechain];
_stats.current_interval_downtime[sidechain] = 0;
_stats.sidechain_txs_reported[sidechain] = 0;
});
}
}
}
void database::update_son_statuses(const vector<son_info>& curr_active_sons, const vector<son_info>& new_active_sons)
void database::update_son_statuses( const flat_map<sidechain_type, vector<son_info> >& curr_active_sons,
const flat_map<sidechain_type, vector<son_info> >& new_active_sons )
{
vector<son_id_type> current_sons, new_sons;
vector<son_id_type> sons_to_remove, sons_to_add;
const auto& idx = get_index_type<son_index>().indices().get<by_id>();
for(const auto& new_active_sidechain_sons : new_active_sons) {
const auto& sidechain = new_active_sidechain_sons.first;
current_sons.reserve(curr_active_sons.size());
std::transform(curr_active_sons.begin(), curr_active_sons.end(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
vector<son_id_type> current_sons, new_sons;
vector<son_id_type> sons_to_remove, sons_to_add;
const auto &idx = get_index_type<son_index>().indices().get<by_id>();
new_sons.reserve(new_active_sons.size());
std::transform(new_active_sons.begin(), new_active_sons.end(),
std::inserter(new_sons, new_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
// find all cur_active_sons members that is not in new_active_sons
for_each(current_sons.begin(), current_sons.end(),
[&sons_to_remove, &new_sons](const son_id_type& si)
{
if(std::find(new_sons.begin(), new_sons.end(), si) ==
new_sons.end())
{
sons_to_remove.push_back(si);
}
}
);
for( const auto& sid : sons_to_remove )
{
auto son = idx.find( sid );
if(son == idx.end()) // SON is deleted already
continue;
// keep maintenance status for nodes becoming inactive
if(son->status == son_status::active)
{
modify( *son, [&]( son_object& obj ){
obj.status = son_status::inactive;
});
if(curr_active_sons.contains(sidechain)) {
current_sons.reserve(curr_active_sons.at(sidechain).size());
std::transform(curr_active_sons.at(sidechain).cbegin(), curr_active_sons.at(sidechain).cend(),
std::inserter(current_sons, current_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
}
}
// find all new_active_sons members that is not in cur_active_sons
for_each(new_sons.begin(), new_sons.end(),
[&sons_to_add, &current_sons](const son_id_type& si)
{
if(std::find(current_sons.begin(), current_sons.end(), si) ==
current_sons.end())
{
sons_to_add.push_back(si);
}
}
);
new_sons.reserve(new_active_sons.at(sidechain).size());
std::transform(new_active_sons.at(sidechain).cbegin(), new_active_sons.at(sidechain).cend(),
std::inserter(new_sons, new_sons.end()),
[](const son_info &swi) {
return swi.son_id;
});
for( const auto& sid : sons_to_add )
{
auto son = idx.find( sid );
FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", sid));
// keep maintenance status for new nodes
if(son->status == son_status::inactive)
{
modify( *son, [&]( son_object& obj ){
obj.status = son_status::active;
});
}
}
// find all cur_active_sons members that is not in new_active_sons
for_each(current_sons.begin(), current_sons.end(),
[&sons_to_remove, &new_sons](const son_id_type &si) {
if (std::find(new_sons.begin(), new_sons.end(), si) ==
new_sons.end()) {
sons_to_remove.push_back(si);
}
});
ilog("New SONS");
for(size_t i = 0; i < new_sons.size(); i++) {
auto son = idx.find( new_sons[i] );
if(son == idx.end()) // SON is deleted already
for (const auto &sid : sons_to_remove) {
auto son = idx.find(sid);
if (son == idx.end()) // SON is deleted already
continue;
ilog( "${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->status)("sv", son->total_votes) );
// keep maintenance status for nodes becoming inactive
if (son->statuses.at(sidechain) == son_status::active) {
modify(*son, [&](son_object &obj) {
obj.statuses.at(sidechain) = son_status::inactive;
});
}
}
// find all new_active_sons members that is not in cur_active_sons
for_each(new_sons.begin(), new_sons.end(),
[&sons_to_add, &current_sons](const son_id_type &si) {
if (std::find(current_sons.begin(), current_sons.end(), si) ==
current_sons.end()) {
sons_to_add.push_back(si);
}
});
for (const auto &sid : sons_to_add) {
auto son = idx.find(sid);
FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", sid));
// keep maintenance status for new nodes
if (son->statuses.at(sidechain) == son_status::inactive) {
modify(*son, [&](son_object &obj) {
obj.statuses.at(sidechain) = son_status::active;
});
}
}
ilog("New SONS for sidechain = ${sidechain}", ("sidechain", sidechain));
for (size_t i = 0; i < new_sons.size(); i++) {
auto son = idx.find(new_sons[i]);
if (son == idx.end()) // SON is deleted already
continue;
ilog("${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->statuses.at(sidechain))("sv", son->total_votes));
}
}
if( sons_to_remove.size() > 0 )
{
//! Remove inactive sons (when all sidechain inactive)
vector<son_id_type> sons_to_remove;
const auto &idx = get_index_type<son_index>().indices().get<by_id>();
for(const auto& son : idx) {
bool inactive_son = true;
for(const auto& status : son.statuses) {
if (status.second != son_status::inactive)
inactive_son = false;
}
if (inactive_son)
sons_to_remove.emplace_back(son.id);
}
if (sons_to_remove.size() > 0) {
remove_inactive_son_proposals(sons_to_remove);
}
}
void database::update_son_wallet(const vector<son_info>& new_active_sons)
void database::update_son_wallet(const flat_map<sidechain_type, vector<son_info> >& new_active_sons)
{
bool should_recreate_pw = true;
@ -408,8 +418,16 @@ void database::update_son_wallet(const vector<son_info>& new_active_sons)
bool wallet_son_sets_equal = (cur_wallet_sons.size() == new_active_sons.size());
if (wallet_son_sets_equal) {
for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) {
wallet_son_sets_equal = wallet_son_sets_equal && cur_wallet_sons.at(i) == new_active_sons.at(i);
for( const auto& cur_wallet_sidechain_sons : cur_wallet_sons ) {
const auto& sidechain = cur_wallet_sidechain_sons.first;
const auto& _cur_wallet_sidechain_sons = cur_wallet_sidechain_sons.second;
wallet_son_sets_equal = wallet_son_sets_equal && (_cur_wallet_sidechain_sons.size() == new_active_sons.at(sidechain).size());
if (wallet_son_sets_equal) {
for (size_t i = 0; i < _cur_wallet_sidechain_sons.size(); i++) {
wallet_son_sets_equal = wallet_son_sets_equal && (_cur_wallet_sidechain_sons.at(i) == new_active_sons.at(sidechain).at(i));
}
}
}
}
@ -429,7 +447,12 @@ void database::update_son_wallet(const vector<son_info>& new_active_sons)
create<son_wallet_object>( [&]( son_wallet_object& obj ) {
obj.valid_from = head_block_time();
obj.expires = time_point_sec::maximum();
obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end());
for(const auto& new_active_sidechain_sons : new_active_sons){
const auto& sidechain = new_active_sidechain_sons.first;
const auto& _new_active_sidechain_sons = new_active_sidechain_sons.second;
obj.sons[sidechain].insert(obj.sons[sidechain].end(), _new_active_sidechain_sons.cbegin(), _new_active_sidechain_sons.cend());
}
});
}
}
@ -701,26 +724,39 @@ void database::update_active_sons()
const global_property_object& gpo = get_global_properties();
const chain_parameters& cp = gpo.parameters;
auto sons = sort_votable_objects<son_index>(sidechain_type::bitcoin, cp.maximum_son_count());
//! Fixme - sort_votable_objects - fix bitcoin + hive -> deduce auto
flat_map<sidechain_type, vector<std::reference_wrapper<const son_object> > > sons;
sons[sidechain_type::bitcoin] = sort_votable_objects<son_index>(sidechain_type::bitcoin, cp.maximum_son_count());
sons[sidechain_type::hive] = sort_votable_objects<son_index>(sidechain_type::hive, cp.maximum_son_count());
const auto& all_sons = get_index_type<son_index>().indices();
auto& local_vote_buffer_ref = _vote_tally_buffer;
for( const son_object& son : all_sons )
{
if(son.status == son_status::request_maintenance)
bool status_in_maintenance = true;
for(const auto& status: son.statuses)
{
auto& stats = son.statistics(*this);
modify( stats, [&]( son_statistics_object& _s){
_s.last_down_timestamp = head_block_time();
});
if(status.second != son_status::in_maintenance)
status_in_maintenance = false;
}
if(status_in_maintenance)
{
auto &stats = son.statistics(*this);
modify(stats, [&](son_statistics_object &_s) {
_s.last_down_timestamp = head_block_time();
});
}
modify( son, [local_vote_buffer_ref]( son_object& obj ){
for(const auto& sidechain_vote_id : obj.sidechain_vote_ids ){
obj.total_votes[sidechain_vote_id.first] = local_vote_buffer_ref[sidechain_vote_id.second];
}
if(obj.status == son_status::request_maintenance)
obj.status = son_status::in_maintenance;
for(auto& status: obj.statuses)
{
if (status.second == son_status::request_maintenance)
status.second = son_status::in_maintenance;
}
});
}
@ -729,21 +765,24 @@ void database::update_active_sons()
{
modify( get(gpo.parameters.son_account()), [&]( account_object& a )
{
set<account_id_type> account_ids;
for(const auto& sidechain_sons : sons)
{
for( const son_object& son : sidechain_sons.second )
{
account_ids.emplace(son.son_account);
}
}
if( head_block_time() < HARDFORK_533_TIME )
{
map<account_id_type, uint64_t> weights;
a.active.weight_threshold = 0;
a.active.account_auths.clear();
for( const son_object& son : sons )
{
weights.emplace(son.son_account, uint64_t(1));
}
for( const auto& weight : weights )
for( const auto& account_id : account_ids )
{
// Ensure that everyone has at least one vote. Zero weights aren't allowed.
a.active.account_auths[weight.first] += 1;
a.active.account_auths[account_id] += 1;
a.active.weight_threshold += 1;
}
@ -754,8 +793,10 @@ void database::update_active_sons()
else
{
vote_counter vc;
for( const son_object& son : sons )
vc.add( son.son_account, UINT64_C(1) );
for( const auto& account_id : account_ids )
{
vc.add(account_id, UINT64_C(1));
}
vc.finish_2_3( a.active );
}
} );
@ -763,22 +804,36 @@ void database::update_active_sons()
// Compare current and to-be lists of active sons
auto cur_active_sons = gpo.active_sons;
vector<son_info> new_active_sons;
const auto cur_active_sons = gpo.active_sons;
flat_map<sidechain_type, vector<son_info> > new_active_sons;
const auto &acc = get(gpo.parameters.son_account());
for( const son_object& son : sons ) {
son_info swi;
swi.son_id = son.id;
swi.weight = acc.active.account_auths.at(son.son_account);
swi.signing_key = son.signing_key;
swi.sidechain_public_keys = son.sidechain_public_keys;
new_active_sons.push_back(swi);
for( const auto& sidechain_sons : sons ){
const auto& sidechain = sidechain_sons.first;
const auto& sons_array = sidechain_sons.second;
new_active_sons[sidechain].reserve(sons_array.size());
for( const son_object& son : sons_array ) {
son_info swi;
swi.son_id = son.id;
swi.weight = acc.active.account_auths.at(son.son_account);
swi.signing_key = son.signing_key;
swi.public_key = son.sidechain_public_keys.at(sidechain);
new_active_sons[sidechain].push_back(swi);
}
}
bool son_sets_equal = (cur_active_sons.size() == new_active_sons.size());
if (son_sets_equal) {
for( size_t i = 0; i < cur_active_sons.size(); i++ ) {
son_sets_equal = son_sets_equal && cur_active_sons.at(i) == new_active_sons.at(i);
for( const auto& cur_active_sidechain_sons : cur_active_sons ){
const auto& sidechain = cur_active_sidechain_sons.first;
const auto& _cur_active_sidechain_sons = cur_active_sidechain_sons.second;
son_sets_equal = son_sets_equal && (_cur_active_sidechain_sons.size() == new_active_sons.at(sidechain).size());
if (son_sets_equal) {
for (size_t i = 0; i < _cur_active_sidechain_sons.size(); i++) {
son_sets_equal = son_sets_equal && (_cur_active_sidechain_sons.at(i) == new_active_sons.at(sidechain).at(i));
}
}
}
}
@ -797,25 +852,32 @@ void database::update_active_sons()
modify(gpo, [&]( global_property_object& gp ){
gp.active_sons.clear();
gp.active_sons.reserve(new_active_sons.size());
gp.active_sons.insert(gp.active_sons.end(), new_active_sons.begin(), new_active_sons.end());
for( const auto& new_active_sidechain_sons : new_active_sons ) {
const auto& sidechain = new_active_sidechain_sons.first;
const auto& _new_active_sidechain_sons = new_active_sidechain_sons.second;
gp.active_sons[sidechain].reserve(_new_active_sidechain_sons.size());
gp.active_sons[sidechain].insert(gp.active_sons[sidechain].end(), _new_active_sidechain_sons.cbegin(), _new_active_sidechain_sons.cend());
}
});
//! Fixme - fix this schedule
const son_schedule_object& sso = son_schedule_id_type()(*this);
modify(sso, [&](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(),
active_sons.reserve(gpo.active_sons.at(sidechain_type::bitcoin).size());
std::transform(gpo.active_sons.at(sidechain_type::bitcoin).cbegin(), gpo.active_sons.at(sidechain_type::bitcoin).cend(),
std::inserter(active_sons, active_sons.end()),
[](const son_info& swi) {
return swi.son_id;
});
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)
if(cur_active_sons.at(sidechain_type::bitcoin).size() == 0 && new_active_sons.at(sidechain_type::bitcoin).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 )
for( size_t i=0; i<new_active_sons.at(sidechain_type::bitcoin).size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});
@ -827,18 +889,18 @@ void database::update_active_sons()
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(),
active_sons.reserve(gpo.active_sons.at(sidechain_type::hive).size());
std::transform(gpo.active_sons.at(sidechain_type::hive).cbegin(), gpo.active_sons.at(sidechain_type::hive).cend(),
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)
if(cur_active_sons.at(sidechain_type::hive).size() == 0 && new_active_sons.at(sidechain_type::hive).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 )
for( size_t i=0; i<new_active_sons.at(sidechain_type::hive).size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});
@ -850,18 +912,18 @@ void database::update_active_sons()
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(),
active_sons.reserve(gpo.active_sons.at(sidechain_type::bitcoin).size());
std::transform(gpo.active_sons.at(sidechain_type::bitcoin).cbegin(), gpo.active_sons.at(sidechain_type::bitcoin).cend(),
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)
if(cur_active_sons.at(sidechain_type::bitcoin).size() == 0 && new_active_sons.at(sidechain_type::bitcoin).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 )
for( size_t i=0; i<new_active_sons.at(sidechain_type::bitcoin).size(); ++i )
_sso.scheduler.produce_schedule(rng);
}
});

View file

@ -74,49 +74,6 @@ witness_id_type database::get_scheduled_witness( uint32_t slot_num )const
return wid;
}
son_id_type database::get_scheduled_son( 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 = son_schedule_id_type()(*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 = son_schedule_id_type()(*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;
}
// 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;
@ -126,7 +83,7 @@ son_id_type database::get_scheduled_son( sidechain_type type, uint32_t slot_num
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() ];
return sso.current_shuffled_sons.at(type)[ current_aslot % sso.current_shuffled_sons.size() ];
}
if (gpo.parameters.witness_schedule_algorithm == GRAPHENE_WITNESS_SCHEDULED_ALGORITHM &&
slot_num != 0 )
@ -239,6 +196,7 @@ void database::update_son_schedule()
const son_schedule_object& ssobitcoin = son_schedule_id_type(2)(*this);
const global_property_object& gpo = get_global_properties();
//! Fixme - here we should take active_sons size for sidechain
if( head_block_num() % gpo.active_sons.size() == 0 )
{
modify( sso, [&]( son_schedule_object& _sso )
@ -246,24 +204,37 @@ void database::update_son_schedule()
_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 );
for(const auto& sidechain_sons : gpo.active_sons)
{
const auto& sidechain = sidechain_sons.first;
const auto& active_sons = sidechain_sons.second;
_sso.current_shuffled_sons[sidechain].reserve( active_sons.size() );
for (const son_info &w : active_sons)
_sso.current_shuffled_sons[sidechain].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 )
for(const auto& sidechain_current_shuffled_sons : _sso.current_shuffled_sons)
{
/// 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;
const auto& sidechain = sidechain_current_shuffled_sons.first;
const auto& current_shuffled_sons = sidechain_current_shuffled_sons.second;
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] );
for (uint32_t i = 0; i < 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 = current_shuffled_sons.size() - i;
uint32_t j = i + k % jmax;
std::swap(_sso.current_shuffled_sons[sidechain][i],
_sso.current_shuffled_sons[sidechain][j]);
}
}
});
@ -272,24 +243,36 @@ void database::update_son_schedule()
_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 );
for(const auto& sidechain_sons : gpo.active_sons)
{
const auto& sidechain = sidechain_sons.first;
const auto& active_sons = sidechain_sons.second;
for (const son_info &w : active_sons)
_sso.current_shuffled_sons[sidechain].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 )
for(const auto& sidechain_current_shuffled_sons : _sso.current_shuffled_sons)
{
/// 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;
const auto& sidechain = sidechain_current_shuffled_sons.first;
const auto& current_shuffled_sons = sidechain_current_shuffled_sons.second;
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] );
for (uint32_t i = 0; i < 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 = current_shuffled_sons.size() - i;
uint32_t j = i + k % jmax;
std::swap(_sso.current_shuffled_sons[sidechain][i],
_sso.current_shuffled_sons[sidechain][j]);
}
}
});
@ -298,24 +281,36 @@ void database::update_son_schedule()
_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 );
for(const auto& sidechain_sons : gpo.active_sons)
{
const auto& sidechain = sidechain_sons.first;
const auto& active_sons = sidechain_sons.second;
for (const son_info &w : active_sons)
_sso.current_shuffled_sons[sidechain].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 )
for(const auto& sidechain_current_shuffled_sons : _sso.current_shuffled_sons)
{
/// 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;
const auto& sidechain = sidechain_current_shuffled_sons.first;
const auto& current_shuffled_sons = sidechain_current_shuffled_sons.second;
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] );
for (uint32_t i = 0; i < 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 = current_shuffled_sons.size() - i;
uint32_t j = i + k % jmax;
std::swap(_sso.current_shuffled_sons[sidechain][i],
_sso.current_shuffled_sons[sidechain][j]);
}
}
});
}
@ -408,7 +403,15 @@ void database::update_son_schedule(const signed_block& next_block)
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();
const flat_map<sidechain_type, uint32_t> schedule_needs_filled = [&gpo]()
{
flat_map<sidechain_type, uint32_t> schedule_needs_filled;
for(const auto& sidechain_active_sons : gpo.active_sons)
{
schedule_needs_filled[sidechain_active_sons.first] = sidechain_active_sons.second.size();
}
return schedule_needs_filled;
}();
uint32_t schedule_slot = get_slot_at_time(next_block.timestamp);
// We shouldn't be able to generate _pending_block with timestamp
@ -440,7 +443,7 @@ void database::update_son_schedule(const signed_block& next_block)
_sso.slots_since_genesis += schedule_slot;
witness_scheduler_rng rng(sso.rng_seed.data, _sso.slots_since_genesis);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.size()) / 2, 1);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.at(sidechain_type::bitcoin).size()) / 2, 1);
if( slot_is_near )
{
@ -457,7 +460,7 @@ void database::update_son_schedule(const signed_block& next_block)
{
_sso.scheduler.reset_schedule( first_son );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son) )
while( !_sso.scheduler.get_slot(schedule_needs_filled.at(sidechain_type::bitcoin), son) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
@ -473,7 +476,7 @@ void database::update_son_schedule(const signed_block& next_block)
_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);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.at(sidechain_type::hive).size()) / 2, 1);
if( slot_is_near_hive )
{
@ -490,7 +493,7 @@ void database::update_son_schedule(const signed_block& next_block)
{
_sso.scheduler.reset_schedule( first_son_hive );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son_hive) )
while( !_sso.scheduler.get_slot(schedule_needs_filled.at(sidechain_type::hive), son_hive) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());
@ -506,7 +509,7 @@ void database::update_son_schedule(const signed_block& next_block)
_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);
_sso.scheduler._min_token_count = std::max(int(gpo.active_sons.at(sidechain_type::bitcoin).size()) / 2, 1);
if( slot_is_near_bitcoin )
{
@ -523,7 +526,7 @@ void database::update_son_schedule(const signed_block& next_block)
{
_sso.scheduler.reset_schedule( first_son_bitcoin );
}
while( !_sso.scheduler.get_slot(schedule_needs_filled, son_bitcoin) )
while( !_sso.scheduler.get_slot(schedule_needs_filled.at(sidechain_type::bitcoin), son_bitcoin) )
{
if( _sso.scheduler.produce_schedule(rng) & emit_turn )
memcpy(_sso.rng_seed.begin(), dpo.random.data(), dpo.random.data_size());

View file

@ -242,22 +242,6 @@ namespace graphene { namespace chain {
*/
witness_id_type get_scheduled_witness(uint32_t slot_num)const;
/**
* @brief Get the 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(uint32_t slot_num)const;
/**
* @brief Get the bitcoin or hive son scheduled for block production in a slot.
*
@ -327,7 +311,7 @@ namespace graphene { namespace chain {
fc::optional<operation> create_son_deregister_proposal( son_id_type son_id, account_id_type paying_son );
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
bool is_son_dereg_valid( son_id_type son_id );
bool is_son_active( son_id_type son_id );
bool is_son_active( sidechain_type type, son_id_type son_id );
bool is_asset_creation_allowed(const string& symbol);
time_point_sec head_block_time()const;
@ -529,6 +513,7 @@ namespace graphene { namespace chain {
template<class Index>
vector<std::reference_wrapper<const typename Index::object_type>> sort_votable_objects(size_t count)const;
//! Fixme return map here
template<class Index>
vector<std::reference_wrapper<const typename Index::object_type>> sort_votable_objects(sidechain_type sidechain, size_t count)const;
@ -586,13 +571,14 @@ namespace graphene { namespace chain {
void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props);
void update_active_witnesses();
void update_active_committee_members();
void update_son_metrics( const vector<son_info>& curr_active_sons );
void update_son_metrics( const flat_map<sidechain_type, vector<son_info> >& curr_active_sons );
void update_active_sons();
void remove_son_proposal( const proposal_object& proposal );
void remove_inactive_son_down_proposals( const vector<son_id_type>& son_ids_to_remove );
void remove_inactive_son_proposals( const vector<son_id_type>& son_ids_to_remove );
void update_son_statuses( const vector<son_info>& cur_active_sons, const vector<son_info>& new_active_sons );
void update_son_wallet( const vector<son_info>& new_active_sons );
void update_son_statuses( const flat_map<sidechain_type, vector<son_info> >& curr_active_sons,
const flat_map<sidechain_type, vector<son_info> >& new_active_sons );
void update_son_wallet( const flat_map<sidechain_type, vector<son_info> >& new_active_sons );
void update_worker_votes();
public:

View file

@ -49,10 +49,18 @@ namespace graphene { namespace chain {
chain_parameters parameters;
optional<chain_parameters> pending_parameters;
uint32_t next_available_vote_id = 0;
vector<committee_member_id_type> active_committee_members; // updated once per maintenance interval
flat_set<witness_id_type> active_witnesses; // updated once per maintenance interval
vector<son_info> active_sons; // updated once per maintenance interval
uint32_t next_available_vote_id = 0;
vector<committee_member_id_type> active_committee_members; // updated once per maintenance interval
flat_set<witness_id_type> active_witnesses; // updated once per maintenance interval
//! Fixme - delete sidechain type from here
flat_map<sidechain_type, vector<son_info> > active_sons = []() // updated once per maintenance interval
{
flat_map<sidechain_type, vector<son_info> > active_sons;
active_sons[sidechain_type::bitcoin] = vector<son_info>();
active_sons[sidechain_type::hive] = vector<son_info>();
return active_sons;
}();
// n.b. witness scheduling is done by witness_schedule object
};

View file

@ -11,7 +11,7 @@ namespace graphene { namespace chain {
asset fee;
account_id_type payer;
vector<son_info> sons;
flat_map<sidechain_type, vector<son_info> > sons;
account_id_type fee_payer()const { return payer; }
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }

View file

@ -14,26 +14,15 @@ namespace graphene { namespace chain {
son_id_type son_id;
weight_type weight = 0;
public_key_type signing_key;
flat_map<sidechain_type, string> sidechain_public_keys;
string public_key;
bool operator==(const son_info& rhs) {
bool operator==(const son_info& rhs) const {
bool son_sets_equal =
(son_id == rhs.son_id) &&
(weight == rhs.weight) &&
(signing_key == rhs.signing_key) &&
(sidechain_public_keys.size() == rhs.sidechain_public_keys.size());
(public_key == rhs.public_key);
if (son_sets_equal) {
bool sidechain_public_keys_equal = true;
for (size_t i = 0; i < sidechain_public_keys.size(); i++) {
const auto lhs_scpk = sidechain_public_keys.nth(i);
const auto rhs_scpk = rhs.sidechain_public_keys.nth(i);
sidechain_public_keys_equal = sidechain_public_keys_equal &&
(lhs_scpk->first == rhs_scpk->first) &&
(lhs_scpk->second == rhs_scpk->second);
}
son_sets_equal = son_sets_equal && sidechain_public_keys_equal;
}
return son_sets_equal;
}
};
@ -44,4 +33,4 @@ FC_REFLECT( graphene::chain::son_info,
(son_id)
(weight)
(signing_key)
(sidechain_public_keys) )
(public_key) )

View file

@ -35,11 +35,11 @@ namespace graphene { namespace chain {
// Transactions signed since the last son payouts
flat_map<sidechain_type, uint64_t> txs_signed;
// Total Voted Active time i.e. duration selected as part of voted active SONs
uint64_t total_voted_time = 0;
flat_map<sidechain_type, uint64_t> total_voted_time; //! Fixme - check if we need map of sidechain_type here
// Total Downtime barring the current down time in seconds, used for stats to present to user
uint64_t total_downtime = 0;
flat_map<sidechain_type, uint64_t> total_downtime; //! Fixme - check if we need map of sidechain_type here
// Current Interval Downtime since last maintenance
uint64_t current_interval_downtime = 0;
flat_map<sidechain_type, uint64_t> current_interval_downtime; //! Fixme - check if we need map of sidechain_type here
// Down timestamp, if son status is in_maintenance use this
fc::time_point_sec last_down_timestamp;
// Last Active heartbeat timestamp
@ -71,7 +71,14 @@ namespace graphene { namespace chain {
public_key_type signing_key;
vesting_balance_id_type pay_vb;
son_statistics_id_type statistics;
son_status status = son_status::inactive;
//! Fixme - delete sidechain type from here
flat_map<sidechain_type, son_status> statuses = []()
{
flat_map<sidechain_type, son_status> statuses;
statuses[sidechain_type::bitcoin] = son_status::inactive;
statuses[sidechain_type::hive] = son_status::inactive;
return statuses;
}();
flat_map<sidechain_type, string> sidechain_public_keys;
void pay_son_fee(share_type pay, database& db);
@ -132,7 +139,7 @@ FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object),
(signing_key)
(pay_vb)
(statistics)
(status)
(statuses)
(sidechain_public_keys)
)

View file

@ -21,7 +21,7 @@ namespace graphene { namespace chain {
time_point_sec expires;
flat_map<sidechain_type, string> addresses;
vector<son_info> sons;
flat_map<sidechain_type, vector<son_info> > sons;
};
struct by_valid_from;

View file

@ -96,7 +96,7 @@ class son_schedule_object : public graphene::db::abstract_object<son_schedule_ob
static const uint8_t space_id = implementation_ids;
static const uint8_t type_id = impl_son_schedule_object_type;
vector< son_id_type > current_shuffled_sons;
flat_map<sidechain_type, vector<son_id_type > > current_shuffled_sons;
son_scheduler scheduler;
uint32_t last_scheduling_block;

View file

@ -47,7 +47,7 @@ void_result update_sidechain_address_evaluator::do_evaluate(const sidechain_addr
{ try {
const auto& sidx = db().get_index_type<son_index>().indices().get<by_account>();
const auto& son_obj = sidx.find(op.payer);
FC_ASSERT( son_obj != sidx.end() && db().is_son_active(son_obj->id), "Non active SON trying to update deposit address object" );
FC_ASSERT( son_obj != sidx.end() && db().is_son_active(op.sidechain, son_obj->id), "Non active SON trying to update deposit address object" );
const auto& sdpke_idx = db().get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_public_key_and_expires>();
FC_ASSERT( op.deposit_address.valid() && op.deposit_public_key.valid() && op.deposit_address_data.valid(), "Update operation by SON is not valid");
FC_ASSERT( (*op.deposit_address).length() > 0 && (*op.deposit_public_key).length() > 0 && (*op.deposit_address_data).length() > 0, "SON should create a valid deposit address with valid deposit public key");

View file

@ -97,7 +97,8 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op)
if(op.new_signing_key.valid()) so.signing_key = *op.new_signing_key;
if(op.new_sidechain_public_keys.valid()) so.sidechain_public_keys = *op.new_sidechain_public_keys;
if(op.new_pay_vb.valid()) so.pay_vb = *op.new_pay_vb;
if(so.status == son_status::deregistered) so.status = son_status::inactive;
for(auto& status : so.statuses)
if(status.second == son_status::deregistered) status.second = son_status::inactive;
});
}
return op.son_id;
@ -130,7 +131,8 @@ void_result deregister_son_evaluator::do_apply(const son_deregister_operation& o
});
db().modify(*son, [&op](son_object &so) {
so.status = son_status::deregistered;
for(auto& status : so.statuses)
status.second = son_status::deregistered;
});
auto stats_obj = ss_idx.find(son->statistics);
@ -147,12 +149,18 @@ void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation&
{ try {
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
auto itr = idx.find(op.son_id);
const auto itr = idx.find(op.son_id);
FC_ASSERT( itr != idx.end() );
FC_ASSERT(itr->son_account == op.owner_account);
auto stats = itr->statistics( db() );
// Inactive SONs need not send heartbeats
FC_ASSERT((itr->status == son_status::active) || (itr->status == son_status::in_maintenance) || (itr->status == son_status::request_maintenance), "Inactive SONs need not send heartbeats");
bool status_need_to_send_heartbeats = false;
for(const auto& status : itr->statuses)
{
if( (status.second == son_status::active) || (status.second == son_status::in_maintenance) || (status.second == son_status::request_maintenance) )
status_need_to_send_heartbeats = true;
}
FC_ASSERT(status_need_to_send_heartbeats, "Inactive SONs need not send heartbeats");
// Account for network delays
fc::time_point_sec min_ts = db().head_block_time() - fc::seconds(5 * db().block_interval());
// Account for server ntp sync difference
@ -167,44 +175,48 @@ void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation&
object_id_type son_heartbeat_evaluator::do_apply(const son_heartbeat_operation& op)
{ try {
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
auto itr = idx.find(op.son_id);
const auto itr = idx.find(op.son_id);
if(itr != idx.end())
{
const global_property_object& gpo = db().get_global_properties();
vector<son_id_type> active_son_ids;
active_son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), op.son_id);
bool is_son_active = true;
for(const auto& active_sidechain_sons : gpo.active_sons) {
const auto& sidechain = active_sidechain_sons.first;
const auto& active_sons = active_sidechain_sons.second;
if(it_son == active_son_ids.end()) {
is_son_active = false;
}
vector<son_id_type> active_son_ids;
active_son_ids.reserve(active_sons.size());
std::transform(active_sons.cbegin(), active_sons.cend(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info &swi) {
return swi.son_id;
});
if(itr->status == son_status::in_maintenance) {
db().modify( itr->statistics( db() ), [&]( son_statistics_object& sso )
{
sso.current_interval_downtime += op.ts.sec_since_epoch() - sso.last_down_timestamp.sec_since_epoch();
sso.last_active_timestamp = op.ts;
} );
const auto it_son = std::find(active_son_ids.begin(), active_son_ids.end(), op.son_id);
bool is_son_active = true;
db().modify(*itr, [&is_son_active](son_object &so) {
if(is_son_active) {
so.status = son_status::active;
} else {
so.status = son_status::inactive;
}
});
} else if ((itr->status == son_status::active) || (itr->status == son_status::request_maintenance)) {
db().modify( itr->statistics( db() ), [&]( son_statistics_object& sso )
{
sso.last_active_timestamp = op.ts;
} );
if (it_son == active_son_ids.end()) {
is_son_active = false;
}
if (itr->statuses.at(sidechain) == son_status::in_maintenance) {
db().modify(itr->statistics(db()), [&](son_statistics_object &sso) {
sso.current_interval_downtime[sidechain] += op.ts.sec_since_epoch() - sso.last_down_timestamp.sec_since_epoch();
sso.last_active_timestamp = op.ts;
});
db().modify(*itr, [&is_son_active, &sidechain](son_object &so) {
if (is_son_active) {
so.statuses[sidechain] = son_status::active;
} else {
so.statuses[sidechain] = son_status::inactive;
}
});
} else if ((itr->statuses.at(sidechain) == son_status::active) || (itr->statuses.at(sidechain) == son_status::request_maintenance)) {
db().modify(itr->statistics(db()), [&](son_statistics_object &sso) {
sso.last_active_timestamp = op.ts;
});
}
}
}
return op.son_id;
@ -216,9 +228,15 @@ void_result son_report_down_evaluator::do_evaluate(const son_report_down_operati
FC_ASSERT(op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer.");
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
FC_ASSERT( idx.find(op.son_id) != idx.end() );
auto itr = idx.find(op.son_id);
auto stats = itr->statistics( db() );
FC_ASSERT(itr->status == son_status::active || itr->status == son_status::request_maintenance, "Inactive/Deregistered/in_maintenance SONs cannot be reported on as down");
const auto itr = idx.find(op.son_id);
const auto stats = itr->statistics( db() );
bool status_need_to_report_down = false;
for(const auto& status : itr->statuses)
{
if( (status.second == son_status::active) || (status.second == son_status::request_maintenance) )
status_need_to_report_down = true;
}
FC_ASSERT(status_need_to_report_down, "Inactive/Deregistered/in_maintenance SONs cannot be reported on as down");
FC_ASSERT(op.down_ts >= stats.last_active_timestamp, "down_ts should be greater than last_active_timestamp");
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -226,19 +244,28 @@ void_result son_report_down_evaluator::do_evaluate(const son_report_down_operati
object_id_type son_report_down_evaluator::do_apply(const son_report_down_operation& op)
{ try {
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
auto itr = idx.find(op.son_id);
const auto itr = idx.find(op.son_id);
if(itr != idx.end())
{
if ((itr->status == son_status::active) || (itr->status == son_status::request_maintenance)) {
db().modify( itr->statistics( db() ), [&]( son_statistics_object& sso )
{
sso.last_down_timestamp = op.down_ts;
});
bool status_report_down = true;
db().modify(*itr, [&op](son_object &so) {
so.status = son_status::in_maintenance;
});
}
for( const auto& status : itr->statuses ) {
const auto& sidechain = status.first;
if ((status.second == son_status::active) || (status.second == son_status::request_maintenance)) {
db().modify(*itr, [&sidechain](son_object &so) {
so.statuses[sidechain] = son_status::in_maintenance;
});
}
else
status_report_down = false;
}
if(status_report_down) {
db().modify(itr->statistics(db()), [&](son_statistics_object &sso) {
sso.last_down_timestamp = op.down_ts;
});
}
}
return op.son_id;
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -252,9 +279,19 @@ void_result son_maintenance_evaluator::do_evaluate(const son_maintenance_operati
FC_ASSERT( itr != idx.end() );
// Inactive SONs can't go to maintenance, toggle between active and request_maintenance states
if(op.request_type == son_maintenance_request_type::request_maintenance) {
FC_ASSERT(itr->status == son_status::active, "Inactive SONs can't request for maintenance");
} else if(op.request_type == son_maintenance_request_type::cancel_request_maintenance) {
FC_ASSERT(itr->status == son_status::request_maintenance, "Only maintenance requested SONs can cancel the request");
bool status_active = false;
for(const auto& status : itr->statuses) {
if( (status.second == son_status::active) )
status_active = true;
}
FC_ASSERT(status_active, "Inactive SONs can't request for maintenance");
} else if(op.request_type == son_maintenance_request_type::cancel_request_maintenance) {
bool status_request_maintenance = false;
for(const auto& status : itr->statuses) {
if( (status.second == son_status::request_maintenance) )
status_request_maintenance = true;
}
FC_ASSERT(status_request_maintenance, "Only maintenance requested SONs can cancel the request");
} else {
FC_ASSERT(false, "Invalid maintenance operation");
}
@ -267,15 +304,33 @@ object_id_type son_maintenance_evaluator::do_apply(const son_maintenance_operati
auto itr = idx.find(op.son_id);
if(itr != idx.end())
{
if(itr->status == son_status::active && op.request_type == son_maintenance_request_type::request_maintenance) {
db().modify(*itr, [](son_object &so) {
so.status = son_status::request_maintenance;
});
} else if(itr->status == son_status::request_maintenance && op.request_type == son_maintenance_request_type::cancel_request_maintenance) {
db().modify(*itr, [](son_object &so) {
so.status = son_status::active;
});
}
bool status_active = false;
for(const auto& status : itr->statuses) {
if( (status.second == son_status::active) )
status_active = true;
}
if(status_active && op.request_type == son_maintenance_request_type::request_maintenance) {
db().modify(*itr, [](son_object &so) {
for(auto& status : so.statuses) {
status.second = son_status::request_maintenance;
}
});
}
else
{
bool status_request_maintenance = false;
for(const auto& status : itr->statuses) {
if( (status.second == son_status::request_maintenance) )
status_request_maintenance = true;
}
if(status_request_maintenance && op.request_type == son_maintenance_request_type::cancel_request_maintenance) {
db().modify(*itr, [](son_object &so) {
for(auto& status : so.statuses) {
status.second = son_status::active;
}
});
}
}
}
return op.son_id;
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -23,9 +23,9 @@ void_result create_son_wallet_deposit_evaluator::do_evaluate(const son_wallet_de
const auto &swdo_idx = db().get_index_type<son_wallet_deposit_index>().indices().get<by_sidechain_uid>();
const auto swdo = swdo_idx.find(op.sidechain_uid);
if (swdo == swdo_idx.end()) {
auto &gpo = db().get_global_properties();
const auto &gpo = db().get_global_properties();
bool expected = false;
for (auto &si : gpo.active_sons) {
for (auto &si : gpo.active_sons.at(op.sidechain)) {
if (op.son_id == si.son_id) {
expected = true;
break;
@ -78,8 +78,8 @@ object_id_type create_son_wallet_deposit_evaluator::do_apply(const son_wallet_de
swdo.peerplays_to = op.peerplays_to;
swdo.peerplays_asset = op.peerplays_asset;
auto &gpo = db().get_global_properties();
for (auto &si : gpo.active_sons) {
const auto &gpo = db().get_global_properties();
for (auto &si : gpo.active_sons.at(op.sidechain)) {
swdo.expected_reports.insert(std::make_pair(si.son_id, si.weight));
auto stats_itr = db().get_index_type<son_stats_index>().indices().get<by_owner>().find(si.son_id);
@ -142,11 +142,11 @@ void_result process_son_wallet_deposit_evaluator::do_evaluate(const son_wallet_d
{ try{
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
FC_ASSERT(db().get_global_properties().active_sons.size() >= db().get_chain_properties().immutable_parameters.min_son_count, "Min required voted SONs not present");
const auto& idx = db().get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
const auto& itr = idx.find(op.son_wallet_deposit_id);
FC_ASSERT(itr != idx.end(), "Son wallet deposit not found");
FC_ASSERT(db().get_global_properties().active_sons.at(itr->sidechain).size() >= db().get_chain_properties().immutable_parameters.min_son_count, "Min required voted SONs not present");
FC_ASSERT(!itr->processed, "Son wallet deposit is already processed");
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -20,8 +20,16 @@ void_result recreate_son_wallet_evaluator::do_evaluate(const son_wallet_recreate
bool son_sets_equal = (cur_wallet_sons.size() == new_wallet_sons.size());
if (son_sets_equal) {
for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) {
son_sets_equal = son_sets_equal && cur_wallet_sons.at(i) == new_wallet_sons.at(i);
for( const auto& cur_wallet_sidechain_sons : cur_wallet_sons ) {
const auto& sidechain = cur_wallet_sidechain_sons.first;
const auto& _cur_wallet_sidechain_sons = cur_wallet_sidechain_sons.second;
son_sets_equal = son_sets_equal && (_cur_wallet_sidechain_sons.size() == new_wallet_sons.at(sidechain).size());
if (son_sets_equal) {
for (size_t i = 0; i < cur_wallet_sons.size(); i++) {
son_sets_equal = son_sets_equal && _cur_wallet_sidechain_sons.at(i) == new_wallet_sons.at(sidechain).at(i);
}
}
}
}

View file

@ -23,9 +23,9 @@ void_result create_son_wallet_withdraw_evaluator::do_evaluate(const son_wallet_w
const auto &swwo_idx = db().get_index_type<son_wallet_withdraw_index>().indices().get<by_peerplays_uid>();
const auto swwo = swwo_idx.find(op.peerplays_uid);
if (swwo == swwo_idx.end()) {
auto &gpo = db().get_global_properties();
const auto &gpo = db().get_global_properties();
bool expected = false;
for (auto &si : gpo.active_sons) {
for (auto &si : gpo.active_sons.at(op.sidechain)) {
if (op.son_id == si.son_id) {
expected = true;
break;
@ -76,8 +76,8 @@ object_id_type create_son_wallet_withdraw_evaluator::do_apply(const son_wallet_w
swwo.withdraw_currency = op.withdraw_currency;
swwo.withdraw_amount = op.withdraw_amount;
auto &gpo = db().get_global_properties();
for (auto &si : gpo.active_sons) {
const auto &gpo = db().get_global_properties();
for (auto &si : gpo.active_sons.at(op.sidechain)) {
swwo.expected_reports.insert(std::make_pair(si.son_id, si.weight));
auto stats_itr = db().get_index_type<son_stats_index>().indices().get<by_owner>().find(si.son_id);
@ -140,11 +140,11 @@ void_result process_son_wallet_withdraw_evaluator::do_evaluate(const son_wallet_
{ try{
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
FC_ASSERT( op.payer == db().get_global_properties().parameters.son_account(), "SON paying account must be set as payer." );
FC_ASSERT(db().get_global_properties().active_sons.size() >= db().get_chain_properties().immutable_parameters.min_son_count, "Min required voted SONs not present");
const auto& idx = db().get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
const auto& itr = idx.find(op.son_wallet_withdraw_id);
FC_ASSERT(itr != idx.end(), "Son wallet withdraw not found");
FC_ASSERT(db().get_global_properties().active_sons.at(itr->sidechain).size() >= db().get_chain_properties().immutable_parameters.min_son_count, "Min required voted SONs not present");
FC_ASSERT(!itr->processed, "Son wallet withdraw is already processed");
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -316,10 +316,12 @@ bool peerplays_sidechain_plugin_impl::is_active_son(son_id_type son_id) {
if (son_obj == idx.end())
return false;
//! Fixme - now only bitcoin, fix according to sidechain_type
const chain::global_property_object &gpo = plugin.database().get_global_properties();
vector<son_id_type> active_son_ids;
active_son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
active_son_ids.reserve(gpo.active_sons.at(sidechain_type::bitcoin).size());
std::transform(gpo.active_sons.at(sidechain_type::bitcoin).cbegin(), gpo.active_sons.at(sidechain_type::bitcoin).cend(),
std::inserter(active_son_ids, active_son_ids.end()),
[](const son_info &swi) {
return swi.son_id;
@ -336,7 +338,13 @@ bool peerplays_sidechain_plugin_impl::is_son_deregistered(son_id_type son_id) {
if (son_obj == idx.end())
return true;
if (son_obj->status == chain::son_status::deregistered) {
bool status_deregistered = true;
for(const auto& status : son_obj->statuses) {
if( (status.second != son_status::deregistered) )
status_deregistered = false;
}
if (status_deregistered) {
return true;
}
@ -362,8 +370,13 @@ bool peerplays_sidechain_plugin_impl::is_son_down_op_valid(const chain::operatio
fc::time_point_sec last_maintenance_time = dgpo.next_maintenance_time - gpo.parameters.maintenance_interval;
fc::time_point_sec last_active_ts = ((stats.last_active_timestamp > last_maintenance_time) ? stats.last_active_timestamp : last_maintenance_time);
int64_t down_threshold = gpo.parameters.son_down_time();
if (((son_obj->status == chain::son_status::active) || (son_obj->status == chain::son_status::request_maintenance)) &&
((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
bool status_son_down_op_valid = true;
for(const auto& status : son_obj->statuses) {
if( (status.second != son_status::active) && (status.second != son_status::request_maintenance) )
status_son_down_op_valid = false;
}
if ((status_son_down_op_valid) && ((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
return true;
}
return false;
@ -398,7 +411,14 @@ void peerplays_sidechain_plugin_impl::heartbeat_loop() {
chain::database &d = plugin.database();
for (son_id_type son_id : sons) {
if (is_active_son(son_id) || get_son_object(son_id).status == chain::son_status::in_maintenance) {
const auto& son_obj = get_son_object(son_id);
bool status_in_maintenance= false;
for(const auto& status : son_obj.statuses) {
if( (status.second == son_status::in_maintenance) )
status_in_maintenance = true;
}
if (is_active_son(son_id) || status_in_maintenance) {
ilog("Sending heartbeat for SON ${son}", ("son", son_id));
chain::son_heartbeat_operation op;
@ -436,7 +456,9 @@ void peerplays_sidechain_plugin_impl::schedule_son_processing() {
}
void peerplays_sidechain_plugin_impl::son_processing() {
if (plugin.database().get_global_properties().active_sons.size() <= 0) {
//! Fixme - here we must check size for every sidechain
if (plugin.database().get_global_properties().active_sons.at(sidechain_type::bitcoin).size() <= 0 &&
plugin.database().get_global_properties().active_sons.at(sidechain_type::hive).size() <= 0) {
return;
}
@ -452,19 +474,18 @@ void peerplays_sidechain_plugin_impl::son_processing() {
return; // Not synced
}
chain::son_id_type scheduled_son_id = plugin.database().get_scheduled_son(1);
ilog("Scheduled SON: ${scheduled_son_id} Now: ${now} ",
("scheduled_son_id", scheduled_son_id)("now", now));
//! Fixme - get real scheduled_son_id according to sidechain_type
chain::son_id_type scheduled_son_id;
// 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));
ilog("Scheduled SON[!HIVE!]: ${scheduled_hive_son_id} Now: ${now} ",
("scheduled_hive_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));
ilog("Scheduled SON[!BITCOIN!]: ${scheduled_bitcoin_son_id} Now: ${now} ",
("scheduled_bitcoin_son_id", scheduled_bitcoin_son_id)("now", now));
for (son_id_type son_id : plugin.get_sons()) {
if (plugin.is_son_deregistered(son_id)) {
@ -612,7 +633,11 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
const auto &idx = d.get_index_type<chain::son_index>().indices().get<by_id>();
std::set<son_id_type> sons_being_reported_down = d.get_sons_being_reported_down();
chain::son_id_type my_son_id = get_current_son_id();
for (auto son_inf : gpo.active_sons) {
//! Fixme - now set bitcoin
//! Do we need to separate create_son_down_proposals for different sidechain_types
for (auto son_inf : gpo.active_sons.at(sidechain_type::bitcoin)) {
if (my_son_id == son_inf.son_id || (sons_being_reported_down.find(son_inf.son_id) != sons_being_reported_down.end())) {
continue;
}
@ -621,8 +646,13 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() {
fc::time_point_sec last_maintenance_time = dgpo.next_maintenance_time - gpo.parameters.maintenance_interval;
fc::time_point_sec last_active_ts = ((stats.last_active_timestamp > last_maintenance_time) ? stats.last_active_timestamp : last_maintenance_time);
int64_t down_threshold = gpo.parameters.son_down_time();
if (((son_obj->status == chain::son_status::active) || (son_obj->status == chain::son_status::request_maintenance)) &&
((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
bool status_son_down_valid = true;
for(const auto& status : son_obj->statuses) {
if( (status.second != son_status::active) && (status.second != son_status::request_maintenance) )
status_son_down_valid = false;
}
if ((status_son_down_valid) && ((fc::time_point::now() - last_active_ts) > fc::seconds(down_threshold))) {
ilog("Sending son down proposal for ${t} from ${s}", ("t", std::string(object_id_type(son_obj->id)))("s", std::string(object_id_type(my_son_id))));
chain::proposal_create_operation op = create_son_down_proposal(son_inf.son_id, last_active_ts);
chain::signed_transaction trx = d.create_signed_transaction(plugin.get_private_key(get_son_object(my_son_id).signing_key), op);

View file

@ -399,6 +399,7 @@ void sidechain_net_handler::process_active_sons_change() {
}
void sidechain_net_handler::create_deposit_addresses() {
//! Fixme - here we must consider sidechain size
if (database.get_global_properties().active_sons.size() < database.get_chain_properties().immutable_parameters.min_son_count) {
return;
}
@ -406,6 +407,7 @@ void sidechain_net_handler::create_deposit_addresses() {
}
void sidechain_net_handler::process_deposits() {
//! Fixme - here we must consider sidechain size
if (database.get_global_properties().active_sons.size() < database.get_chain_properties().immutable_parameters.min_son_count) {
return;
}
@ -441,6 +443,7 @@ void sidechain_net_handler::process_deposits() {
}
void sidechain_net_handler::process_withdrawals() {
//! Fixme - here we must consider sidechain size
if (database.get_global_properties().active_sons.size() < database.get_chain_properties().immutable_parameters.min_son_count) {
return;
}

View file

@ -904,8 +904,9 @@ void zmq_listener::handle_zmq() {
// =============================================================================
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
sidechain_net_handler(_plugin, options) {
sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options)
: sidechain_net_handler(_plugin, options)
{
sidechain = sidechain_type::bitcoin;
if (options.count("debug-rpc-calls")) {
@ -1024,8 +1025,8 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
const auto swo = idx.find(swo_id);
if (swo != idx.end()) {
auto active_sons = gpo.active_sons;
vector<son_info> wallet_sons = swo->sons;
const auto& active_sons = gpo.active_sons.at(sidechain);
vector<son_info> wallet_sons = swo->sons.at(sidechain);
bool son_sets_equal = (active_sons.size() == wallet_sons.size());
@ -1036,10 +1037,10 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
}
if (son_sets_equal) {
auto active_sons = gpo.active_sons;
const auto& active_sons = gpo.active_sons.at(sidechain);
vector<string> son_pubkeys_bitcoin;
for (const son_info &si : active_sons) {
son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin));
son_pubkeys_bitcoin.push_back(si.public_key);
}
string reply_str = create_primary_wallet_address(active_sons);
@ -1242,7 +1243,7 @@ bool sidechain_net_handler_bitcoin::process_proposal(const proposal_object &po)
read_transaction_data(sto->transaction, tx_hex, in_amounts, redeem_script);
bitcoin_transaction tx = unpack(parse_hex(tx_hex));
bitcoin::bytes pubkey = parse_hex(son->sidechain_public_keys.at(sidechain_type::bitcoin));
bitcoin::bytes pubkey = parse_hex(son->sidechain_public_keys.at(sidechain));
vector<bitcoin::bytes> sigs = read_byte_arrays_from_string(signature);
for (size_t i = 0; i < tx.vin.size(); i++) {
const auto &sighash_str = get_signature_hash(tx, parse_hex(redeem_script), static_cast<int64_t>(in_amounts[i]), i, 1, true).str();
@ -1272,8 +1273,8 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
const auto &active_sw = swi.rbegin();
if (active_sw != swi.rend()) {
if ((active_sw->addresses.find(sidechain_type::bitcoin) == active_sw->addresses.end()) ||
(active_sw->addresses.at(sidechain_type::bitcoin).empty())) {
if ((active_sw->addresses.find(sidechain) == active_sw->addresses.end()) ||
(active_sw->addresses.at(sidechain).empty())) {
if (proposal_exists(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
return;
@ -1281,7 +1282,7 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
const chain::global_property_object &gpo = database.get_global_properties();
auto active_sons = gpo.active_sons;
const auto& active_sons = gpo.active_sons.at(sidechain);
string reply_str = create_primary_wallet_address(active_sons);
std::stringstream active_pw_ss(reply_str);
@ -1303,7 +1304,7 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
son_wallet_update_operation swu_op;
swu_op.payer = gpo.parameters.son_account();
swu_op.son_wallet_id = active_sw->id;
swu_op.sidechain = sidechain_type::bitcoin;
swu_op.sidechain = sidechain;
swu_op.address = res.str();
proposal_op.proposed_ops.emplace_back(swu_op);
@ -1318,7 +1319,7 @@ void sidechain_net_handler_bitcoin::process_primary_wallet() {
stc_op.object_id = prev_sw->id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = prev_sw->sons;
stc_op.signers = prev_sw->sons.at(sidechain);
proposal_op.proposed_ops.emplace_back(stc_op);
}
}
@ -1344,9 +1345,8 @@ void sidechain_net_handler_bitcoin::process_sidechain_addresses() {
const chain::global_property_object &gpo = database.get_global_properties();
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkeys;
for (auto &son : gpo.active_sons) {
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
auto pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
for (auto &son : gpo.active_sons.at(sidechain)) {
auto pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(son.public_key)));
pubkeys.push_back(std::make_pair(pubkey, son.weight));
}
@ -1422,7 +1422,7 @@ bool sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_obj
stc_op.object_id = swdo.id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
stc_op.signers = gpo.active_sons.at(sidechain);
proposal_op.proposed_ops.emplace_back(stc_op);
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
@ -1466,7 +1466,7 @@ bool sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw
stc_op.object_id = swwo.id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
stc_op.signers = gpo.active_sons.at(sidechain);
proposal_op.proposed_ops.emplace_back(stc_op);
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
@ -1517,8 +1517,8 @@ bool sidechain_net_handler_bitcoin::settle_sidechain_transaction(const sidechain
using namespace bitcoin;
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
for (auto si : sto.signers) {
std::string pub_key_str = si.sidechain_public_keys.at(sidechain_type::bitcoin);
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
//! Fixme - check public_key here
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(si.public_key)));
pubkey_weights.push_back(std::make_pair(pub_key, si.weight));
}
btc_weighted_multisig_address addr(pubkey_weights, network_type);
@ -1558,8 +1558,7 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
for (auto &son : son_pubkeys) {
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(son.public_key)));
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
}
@ -1576,7 +1575,7 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_address(const s
std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address) {
const auto &address_data = prev_swo.addresses.find(sidechain_type::bitcoin);
const auto &address_data = prev_swo.addresses.find(sidechain);
if (address_data == prev_swo.addresses.end()) {
return "";
}
@ -1627,12 +1626,12 @@ std::string sidechain_net_handler_bitcoin::create_primary_wallet_transaction(con
std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_wallet_deposit_object &swdo) {
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
auto obj = idx.rbegin();
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
if (obj == idx.rend() || obj->addresses.find(sidechain) == obj->addresses.end()) {
return "";
}
//Get redeem script for deposit address
std::string redeem_script = get_redeemscript_for_userdeposit(swdo.sidechain_from);
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
std::string pw_address_json = obj->addresses.find(sidechain)->second;
std::stringstream ss(pw_address_json);
boost::property_tree::ptree json;
@ -1668,11 +1667,11 @@ std::string sidechain_net_handler_bitcoin::create_deposit_transaction(const son_
std::string sidechain_net_handler_bitcoin::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) {
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
auto obj = idx.rbegin();
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
if (obj == idx.rend() || obj->addresses.find(sidechain) == obj->addresses.end()) {
return "";
}
std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second;
std::string pw_address_json = obj->addresses.find(sidechain)->second;
std::stringstream ss(pw_address_json);
boost::property_tree::ptree json;
@ -1847,14 +1846,13 @@ std::string sidechain_net_handler_bitcoin::get_redeemscript_for_userdeposit(cons
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
auto obj = idx.rbegin();
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
if (obj == idx.rend() || obj->addresses.find(sidechain) == obj->addresses.end()) {
return "";
}
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
for (auto &son : obj->sons) {
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
for (auto &son : obj->sons.at(sidechain)) {
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(son.public_key)));
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
}
auto user_pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(addr_itr->deposit_public_key)));

View file

@ -114,8 +114,9 @@ std::string hive_node_rpc_client::get_last_irreversible_block_num() {
return retrieve_value_from_reply(reply_str, "last_irreversible_block_num");
}
sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) :
sidechain_net_handler(_plugin, options) {
sidechain_net_handler_hive::sidechain_net_handler_hive(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options)
: sidechain_net_handler(_plugin, options)
{
sidechain = sidechain_type::hive;
if (options.count("debug-rpc-calls")) {
@ -213,8 +214,8 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) {
const auto swo = idx.find(swo_id);
if (swo != idx.end()) {
auto active_sons = gpo.active_sons;
vector<son_info> wallet_sons = swo->sons;
auto active_sons = gpo.active_sons.at(sidechain);
vector<son_info> wallet_sons = swo->sons.at(sidechain);
bool son_sets_equal = (active_sons.size() == wallet_sons.size());
@ -251,7 +252,7 @@ bool sidechain_net_handler_hive::process_proposal(const proposal_object &po) {
uint32_t total_weight = 0;
for (const auto &wallet_son : wallet_sons) {
total_weight = total_weight + wallet_son.weight;
account_auths[wallet_son.sidechain_public_keys.at(sidechain)] = wallet_son.weight;
account_auths[wallet_son.public_key] = wallet_son.weight;
}
std::string memo_key = node_rpc_client->get_account_memo_key("son-account");
@ -487,12 +488,12 @@ void sidechain_net_handler_hive::process_primary_wallet() {
const chain::global_property_object &gpo = database.get_global_properties();
auto active_sons = gpo.active_sons;
const auto& active_sons = gpo.active_sons.at(sidechain);
fc::flat_map<std::string, uint16_t> account_auths;
uint32_t total_weight = 0;
for (const auto &active_son : active_sons) {
total_weight = total_weight + active_son.weight;
account_auths[active_son.sidechain_public_keys.at(sidechain)] = active_son.weight;
account_auths[active_son.public_key] = active_son.weight;
}
std::string memo_key = node_rpc_client->get_account_memo_key("son-account");
@ -547,7 +548,7 @@ void sidechain_net_handler_hive::process_primary_wallet() {
stc_op.object_id = active_sw->id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
stc_op.signers = gpo.active_sons.at(sidechain);
proposal_op.proposed_ops.emplace_back(stc_op);
@ -704,7 +705,7 @@ bool sidechain_net_handler_hive::process_withdrawal(const son_wallet_withdraw_ob
stc_op.object_id = swwo.id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
stc_op.signers = gpo.active_sons.at(sidechain);
proposal_op.proposed_ops.emplace_back(stc_op);
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);

View file

@ -197,7 +197,7 @@ bool sidechain_net_handler_peerplays::process_deposit(const son_wallet_deposit_o
stc_op.object_id = swdo.id;
stc_op.sidechain = sidechain;
stc_op.transaction = tx_str;
stc_op.signers = gpo.active_sons;
stc_op.signers = gpo.active_sons.at(sidechain);
proposal_create_operation proposal_op;
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;

View file

@ -2232,68 +2232,80 @@ public:
} FC_CAPTURE_AND_RETHROW( (owner_account) ) }
map<string, son_id_type> list_active_sons()
{ try {
global_property_object gpo = get_global_properties();
vector<son_id_type> son_ids;
son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(son_ids, son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
vector<std::string> owners;
for(auto obj: son_objects)
{
try
{
std::string acc_id = account_id_to_string(obj->son_account);
owners.push_back(acc_id);
//! Fixme - now only bitcoin, fix according to sidechain_type
const global_property_object& gpo = get_global_properties();
vector<son_id_type> son_ids;
son_ids.reserve(gpo.active_sons.at(sidechain_type::bitcoin).size());
std::transform(gpo.active_sons.at(sidechain_type::bitcoin).cbegin(), gpo.active_sons.at(sidechain_type::bitcoin).cend(),
std::inserter(son_ids, son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
vector<std::string> owners;
for(auto obj: son_objects)
{
std::string acc_id = account_id_to_string(obj->son_account);
owners.push_back(acc_id);
}
vector< optional< account_object> > accs = _remote_db->get_accounts(owners);
std::remove_if(son_objects.begin(), son_objects.end(),
[](const fc::optional<son_object>& obj) -> bool { return obj.valid(); });
map<string, son_id_type> result;
std::transform(accs.begin(), accs.end(), son_objects.begin(),
std::inserter(result, result.end()),
[](fc::optional<account_object>& acct, fc::optional<son_object> son) {
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
return std::make_pair<string, son_id_type>(string(acct->name), std::move(son->id));
});
return result;
}
vector< optional< account_object> > accs = _remote_db->get_accounts(owners);
std::remove_if(son_objects.begin(), son_objects.end(),
[](const fc::optional<son_object>& obj) -> bool { return obj.valid(); });
map<string, son_id_type> result;
std::transform(accs.begin(), accs.end(), son_objects.begin(),
std::inserter(result, result.end()),
[](fc::optional<account_object>& acct, fc::optional<son_object> son) {
FC_ASSERT(acct, "Invalid active SONs list in global properties.");
return std::make_pair<string, son_id_type>(string(acct->name), std::move(son->id));
});
return result;
} FC_CAPTURE_AND_RETHROW() }
FC_CAPTURE_AND_RETHROW()
}
map<son_id_type, string> get_son_network_status()
{ try {
global_property_object gpo = get_global_properties();
vector<son_id_type> son_ids;
son_ids.reserve(gpo.active_sons.size());
std::transform(gpo.active_sons.begin(), gpo.active_sons.end(),
std::inserter(son_ids, son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
{
try
{
//! Fixme - now only bitcoin, fix according to sidechain_type
map<son_id_type, string> result;
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
for(auto son_obj: son_objects) {
string status;
if (son_obj) {
son_statistics_object sso = get_object(son_obj->statistics);
if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_heartbeat_frequency()) > time_point::now()) {
status = "OK, regular SON heartbeat";
} else {
if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_down_time()) > time_point::now()) {
status = "OK, irregular SON heartbeat, but not triggering SON down proposal";
const global_property_object& gpo = get_global_properties();
vector<son_id_type> son_ids;
son_ids.reserve(gpo.active_sons.at(sidechain_type::bitcoin).size());
std::transform(gpo.active_sons.at(sidechain_type::bitcoin).cbegin(), gpo.active_sons.at(sidechain_type::bitcoin).cend(),
std::inserter(son_ids, son_ids.end()),
[](const son_info& swi) {
return swi.son_id;
});
map<son_id_type, string> result;
std::vector<fc::optional<son_object>> son_objects = _remote_db->get_sons(son_ids);
for(auto son_obj: son_objects) {
string status;
if (son_obj) {
son_statistics_object sso = get_object(son_obj->statistics);
if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_heartbeat_frequency()) > time_point::now()) {
status = "OK, regular SON heartbeat";
} else {
status = "NOT OK, irregular SON heartbeat, triggering SON down proposal";
if (sso.last_active_timestamp + fc::seconds(gpo.parameters.son_down_time()) > time_point::now()) {
status = "OK, irregular SON heartbeat, but not triggering SON down proposal";
} else {
status = "NOT OK, irregular SON heartbeat, triggering SON down proposal";
}
}
} else {
status = "NOT OK, invalid SON id";
}
} else {
status = "NOT OK, invalid SON id";
result[son_obj->id] = status;
}
result[son_obj->id] = status;
return result;
}
return result;
} FC_CAPTURE_AND_RETHROW() }
FC_CAPTURE_AND_RETHROW()
}
optional<son_wallet_object> get_active_son_wallet()
{ try {

View file

@ -408,10 +408,12 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture )
vote_tx = con.wallet_api_ptr->vote_for_son(name1, name2, sidechain_type::hive, true, true);
}
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
BOOST_CHECK(generate_maintenance_block());
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
for(unsigned int i = 0; i < son_number - 1; i++)
{
@ -421,10 +423,12 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture )
vote_tx = con.wallet_api_ptr->vote_for_son(name1, name2, sidechain_type::hive, true, true);
}
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
BOOST_CHECK(generate_maintenance_block());
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
for(unsigned int i = 0; i < son_number - 2; i++)
{
@ -434,10 +438,12 @@ BOOST_FIXTURE_TEST_CASE( select_top_fifteen_sons, cli_fixture )
vote_tx = con.wallet_api_ptr->vote_for_son(name1, name2, sidechain_type::hive, true, true);
}
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
BOOST_CHECK(generate_maintenance_block());
BOOST_CHECK(gpo.active_sons.size() == gpo.parameters.maximum_son_count());
BOOST_CHECK(gpo.active_sons.at(sidechain_type::bitcoin).size() == gpo.parameters.maximum_son_count());
BOOST_CHECK(gpo.active_sons.at(sidechain_type::hive).size() == gpo.parameters.maximum_son_count());
} catch( fc::exception& e ) {
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
@ -721,7 +727,8 @@ BOOST_AUTO_TEST_CASE( related_functions )
try
{
global_property_object gpo = con.wallet_api_ptr->get_global_properties();
BOOST_CHECK(gpo.active_sons.size() == 0);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::bitcoin).size() == 0);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::hive).size() == 0);
flat_map<sidechain_type, string> sidechain_public_keys;
@ -738,7 +745,8 @@ BOOST_AUTO_TEST_CASE( related_functions )
sth.create_son("son2account", "http://son2", sidechain_public_keys);
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_CHECK(gpo.active_sons.size() == 2);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::bitcoin).size() == 2);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::hive).size() == 2);
} catch( fc::exception& e ) {
BOOST_TEST_MESSAGE("SON cli wallet tests exception");
@ -797,9 +805,11 @@ BOOST_FIXTURE_TEST_CASE( cli_list_active_sons, cli_fixture )
}
BOOST_CHECK(generate_maintenance_block());
gpo = con.wallet_api_ptr->get_global_properties();
BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size());
BOOST_TEST_MESSAGE("gpo active_sons[bitcoin]: " << gpo.active_sons.at(sidechain_type::bitcoin).size());
BOOST_TEST_MESSAGE("gpo active_sons[hive]: " << gpo.active_sons.at(sidechain_type::hive).size());
BOOST_CHECK(gpo.active_sons.size() == son_number);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::bitcoin).size() == son_number);
BOOST_CHECK(gpo.active_sons.at(sidechain_type::hive).size() == son_number);
map<string, son_id_type> active_sons = con.wallet_api_ptr->list_active_sons();
BOOST_CHECK(active_sons.size() == son_number);
@ -858,7 +868,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test )
BOOST_CHECK(generate_maintenance_block());
son_object son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active);
// put SON in maintenance mode
con.wallet_api_ptr->request_son_maintenance(name, true);
@ -866,7 +877,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test )
// check SON is in request_maintenance
son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::request_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::request_maintenance);
// restore SON activity
con.wallet_api_ptr->cancel_request_son_maintenance(name, true);
@ -874,7 +886,8 @@ BOOST_AUTO_TEST_CASE( maintenance_test )
// check SON is active
son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active);
// put SON in maintenance mode
con.wallet_api_ptr->request_son_maintenance(name, true);
@ -882,14 +895,16 @@ BOOST_AUTO_TEST_CASE( maintenance_test )
// check SON is in request_maintenance
son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::request_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::request_maintenance);
// process maintenance
BOOST_CHECK(generate_maintenance_block());
// check SON is in maintenance
son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::in_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::in_maintenance);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::in_maintenance);
} catch( fc::exception& e ) {
@ -1006,7 +1021,8 @@ BOOST_AUTO_TEST_CASE( sidechain_withdraw_transaction_test )
BOOST_CHECK(generate_maintenance_block());
son_object son_obj = con.wallet_api_ptr->get_son(name);
BOOST_CHECK(son_obj.status == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK(son_obj.statuses.at(sidechain_type::hive) == son_status::active);
// create son account
std::string account_name("peerplaystest");

View file

@ -87,7 +87,8 @@ BOOST_AUTO_TEST_CASE( sidechain_address_update_test ) {
{
son_info sinfo;
sinfo.son_id = son.id;
_gpo.active_sons.push_back(sinfo);
_gpo.active_sons[sidechain_type::bitcoin].push_back(sinfo);
_gpo.active_sons[sidechain_type::hive].push_back(sinfo);
});
generate_block();
{

View file

@ -193,7 +193,8 @@ try {
// Modify SON's status to active
db.modify( *obj, [&]( son_object& _s)
{
_s.status = son_status::in_maintenance;
_s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance;
_s.statuses[sidechain_type::hive] = son_status::in_maintenance;
});
db.modify( *son_stats_obj, [&]( son_statistics_object& _s)
@ -218,7 +219,8 @@ try {
generate_block();
BOOST_REQUIRE( idx.size() == 1 );
BOOST_REQUIRE( obj->status == son_status::deregistered );
BOOST_REQUIRE( obj->statuses.at(sidechain_type::bitcoin) == son_status::deregistered );
BOOST_REQUIRE( obj->statuses.at(sidechain_type::hive) == son_status::deregistered );
BOOST_REQUIRE( son_stats_obj->deregistered_timestamp == now );
deposit_vesting = db.get<vesting_balance_object>(vesting_balance_id_type(0));
@ -604,7 +606,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
// Modify SON's status to active
db.modify( *obj, [&]( son_object& _s)
{
_s.status = son_status::active;
_s.statuses[sidechain_type::bitcoin] = son_status::active;
_s.statuses[sidechain_type::hive] = son_status::active;
});
db.modify( *son_stats_obj, [&]( son_statistics_object& _s)
@ -626,7 +629,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
PUSH_TX( db, trx, ~0);
generate_block();
trx.clear();
BOOST_CHECK( obj->status == son_status::request_maintenance);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::request_maintenance);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::request_maintenance);
}
{
@ -643,13 +647,15 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
PUSH_TX( db, trx, ~0);
generate_block();
trx.clear();
BOOST_CHECK( obj->status == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active);
}
// Modify SON's status to in_maintenance
db.modify( *obj, [&]( son_object& _s)
{
_s.status = son_status::in_maintenance;
_s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance;
_s.statuses[sidechain_type::hive] = son_status::in_maintenance;
});
uint64_t downtime = 0;
@ -668,16 +674,19 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
PUSH_TX( db, trx, ~0);
generate_block();
trx.clear();
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime, op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
downtime += op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch();
BOOST_CHECK( obj->status == son_status::inactive);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::inactive);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::inactive);
BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts);
}
// Modify SON's status to in_maintenance
db.modify( *obj, [&]( son_object& _s)
{
_s.status = son_status::in_maintenance;
_s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance;
_s.statuses[sidechain_type::bitcoin] = son_status::in_maintenance;
});
// SON is selected as one of the active SONs
@ -685,7 +694,8 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
{
son_info son_inf;
son_inf.son_id = son_id_type(0);
_gpo.active_sons.push_back(son_inf);
_gpo.active_sons[sidechain_type::bitcoin].push_back(son_inf);
_gpo.active_sons[sidechain_type::hive].push_back(son_inf);
});
{
@ -702,9 +712,11 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
PUSH_TX( db, trx, ~0);
generate_block();
trx.clear();
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime, downtime + op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), downtime + op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), downtime + op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch());
downtime += op.ts.sec_since_epoch() - son_stats_obj->last_down_timestamp.sec_since_epoch();
BOOST_CHECK( obj->status == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active);
BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts);
}
@ -722,8 +734,10 @@ BOOST_AUTO_TEST_CASE( son_heartbeat_test ) {
PUSH_TX( db, trx, ~0);
generate_block();
trx.clear();
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime, downtime);
BOOST_CHECK( obj->status == son_status::active);
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::bitcoin), downtime);
BOOST_REQUIRE_EQUAL(son_stats_obj->current_interval_downtime.at(sidechain_type::hive), downtime);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active);
BOOST_CHECK( son_stats_obj->last_active_timestamp == op.ts);
}
} FC_LOG_AND_RETHROW()
@ -749,7 +763,8 @@ BOOST_AUTO_TEST_CASE( son_report_down_test ) {
auto son_stats_obj = sidx.find( obj->statistics );
BOOST_REQUIRE( son_stats_obj != sidx.end() );
BOOST_CHECK( obj->status == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::active);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::active);
{
// Check that transaction fails if down_ts < last_active_timestamp
@ -801,7 +816,8 @@ BOOST_AUTO_TEST_CASE( son_report_down_test ) {
generate_block();
trx.clear();
BOOST_CHECK( obj->status == son_status::in_maintenance);
BOOST_CHECK( obj->statuses.at(sidechain_type::bitcoin) == son_status::in_maintenance);
BOOST_CHECK( obj->statuses.at(sidechain_type::hive) == son_status::in_maintenance);
BOOST_CHECK( son_stats_obj->last_down_timestamp == op.down_ts);
}

View file

@ -154,13 +154,14 @@ BOOST_AUTO_TEST_CASE( son_wallet_recreate_test ) {
op.payer = db.get_global_properties().parameters.son_account();
//! Fixme - add hive tests
{
son_info si;
si.son_id = son_id_type(0);
si.weight = 1000;
si.signing_key = alice_public_key;
si.sidechain_public_keys[sidechain_type::bitcoin] = "";
op.sons.push_back(si);
si.public_key = "";
op.sons[sidechain_type::bitcoin].push_back(si);
}
{
@ -168,8 +169,8 @@ BOOST_AUTO_TEST_CASE( son_wallet_recreate_test ) {
si.son_id = son_id_type(1);
si.weight = 1000;
si.signing_key = bob_public_key;
si.sidechain_public_keys[sidechain_type::bitcoin] = "";
op.sons.push_back(si);
si.public_key = "";
op.sons[sidechain_type::bitcoin].push_back(si);
}
trx.operations.push_back(op);