Merge branch 'feature/SONs-base' into feature/SON-134
This commit is contained in:
commit
b1fbd26bcf
10 changed files with 194 additions and 109 deletions
|
|
@ -222,21 +222,6 @@ signed_transaction database::create_signed_transaction( const fc::ecc::private_k
|
|||
return processed_trx;
|
||||
}
|
||||
|
||||
void database::remove_son_proposal( const proposal_object& proposal )
|
||||
{ try {
|
||||
if( proposal.proposed_transaction.operations.size() == 1 &&
|
||||
( proposal.proposed_transaction.operations.back().which() == operation::tag<son_delete_operation>::value ||
|
||||
proposal.proposed_transaction.operations.back().which() == operation::tag<son_report_down_operation>::value) )
|
||||
{
|
||||
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get<by_proposal>();
|
||||
auto son_proposal_itr = son_proposal_idx.find( proposal.id );
|
||||
if( son_proposal_itr == son_proposal_idx.end() ) {
|
||||
return;
|
||||
}
|
||||
remove( *son_proposal_itr );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (proposal) ) }
|
||||
|
||||
bool database::is_son_dereg_valid( son_id_type son_id )
|
||||
{
|
||||
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ void database::pay_sons()
|
|||
time_point_sec now = head_block_time();
|
||||
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::days(1)) {
|
||||
if( dpo.son_budget.value > 0 && ((now - dpo.last_son_payout_time) >= fc::seconds(get_global_properties().parameters.son_pay_time()))) {
|
||||
uint64_t total_txs_signed = 0;
|
||||
share_type son_budget = dpo.son_budget;
|
||||
get_index_type<son_stats_index>().inspect_all_objects([this, &total_txs_signed](const object& o) {
|
||||
|
|
@ -180,6 +180,128 @@ void database::update_son_metrics()
|
|||
}
|
||||
}
|
||||
|
||||
void database::update_son_statuses(const vector<son_info>& curr_active_sons, const 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>();
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// find all new_active_sons members that is not in cur_active_sons
|
||||
for_each(new_sons.begin(), new_sons.end(),
|
||||
[&sons_to_add, ¤t_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->status == son_status::inactive)
|
||||
{
|
||||
modify( *son, [&]( son_object& obj ){
|
||||
obj.status = son_status::active;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
continue;
|
||||
ilog( "${s}, status = ${ss}, total_votes = ${sv}", ("s", new_sons[i])("ss", son->status)("sv", son->total_votes) );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
bool should_recreate_pw = true;
|
||||
|
||||
// Expire for current son_wallet_object wallet, if exists
|
||||
const auto& idx_swi = get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
auto obj = idx_swi.rbegin();
|
||||
if (obj != idx_swi.rend()) {
|
||||
// Compare current wallet SONs and to-be lists of active sons
|
||||
auto cur_wallet_sons = (*obj).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);
|
||||
}
|
||||
}
|
||||
|
||||
should_recreate_pw = !wallet_son_sets_equal;
|
||||
|
||||
if (should_recreate_pw) {
|
||||
modify(*obj, [&, obj](son_wallet_object &swo) {
|
||||
swo.expires = head_block_time();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (should_recreate_pw) {
|
||||
// Create new son_wallet_object, to initiate wallet recreation
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void database::pay_workers( share_type& budget )
|
||||
{
|
||||
// ilog("Processing payroll! Available budget is ${b}", ("b", budget));
|
||||
|
|
@ -496,90 +618,8 @@ void database::update_active_sons()
|
|||
} else {
|
||||
ilog( "Active SONs set CHANGED" );
|
||||
|
||||
bool should_recreate_pw = true;
|
||||
|
||||
// Expire for current son_wallet_object wallet, if exists
|
||||
const auto& idx_swi = get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
auto obj = idx_swi.rbegin();
|
||||
if (obj != idx_swi.rend()) {
|
||||
// Compare current wallet SONs and to-be lists of active sons
|
||||
auto cur_wallet_sons = (*obj).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);
|
||||
}
|
||||
}
|
||||
|
||||
should_recreate_pw = !wallet_son_sets_equal;
|
||||
|
||||
if (should_recreate_pw) {
|
||||
modify(*obj, [&, obj](son_wallet_object &swo) {
|
||||
swo.expires = head_block_time();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (should_recreate_pw) {
|
||||
// Create new son_wallet_object, to initiate wallet recreation
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
vector<son_info> sons_to_remove;
|
||||
// find all cur_active_sons members that is not in new_active_sons
|
||||
for_each(cur_active_sons.begin(), cur_active_sons.end(),
|
||||
[&sons_to_remove, &new_active_sons](const son_info& si)
|
||||
{
|
||||
if(std::find(new_active_sons.begin(), new_active_sons.end(), si) ==
|
||||
new_active_sons.end())
|
||||
{
|
||||
sons_to_remove.push_back(si);
|
||||
}
|
||||
}
|
||||
);
|
||||
const auto& idx = get_index_type<son_index>().indices().get<by_id>();
|
||||
for( const son_info& si : sons_to_remove )
|
||||
{
|
||||
auto son = idx.find( si.son_id );
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
vector<son_info> sons_to_add;
|
||||
// find all new_active_sons members that is not in cur_active_sons
|
||||
for_each(new_active_sons.begin(), new_active_sons.end(),
|
||||
[&sons_to_add, &cur_active_sons](const son_info& si)
|
||||
{
|
||||
if(std::find(cur_active_sons.begin(), cur_active_sons.end(), si) ==
|
||||
cur_active_sons.end())
|
||||
{
|
||||
sons_to_add.push_back(si);
|
||||
}
|
||||
}
|
||||
);
|
||||
for( const son_info& si : sons_to_add )
|
||||
{
|
||||
auto son = idx.find( si.son_id );
|
||||
FC_ASSERT(son != idx.end(), "Invalid SON in active list, id={sonid}.", ("sonid", si.son_id));
|
||||
// keep maintenance status for new nodes
|
||||
if(son->status == son_status::inactive)
|
||||
{
|
||||
modify( *son, [&]( son_object& obj ){
|
||||
obj.status = son_status::active;
|
||||
});
|
||||
}
|
||||
}
|
||||
update_son_wallet(new_active_sons);
|
||||
update_son_statuses(cur_active_sons, new_active_sons);
|
||||
}
|
||||
|
||||
modify(gpo, [&]( global_property_object& gp ){
|
||||
|
|
|
|||
|
|
@ -652,4 +652,50 @@ void database::update_betting_markets(fc::time_point_sec current_block_time)
|
|||
remove_completed_events();
|
||||
}
|
||||
|
||||
void database::remove_son_proposal( const proposal_object& proposal )
|
||||
{ try {
|
||||
if( proposal.proposed_transaction.operations.size() == 1 &&
|
||||
( proposal.proposed_transaction.operations.back().which() == operation::tag<son_delete_operation>::value ||
|
||||
proposal.proposed_transaction.operations.back().which() == operation::tag<son_report_down_operation>::value) )
|
||||
{
|
||||
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get<by_proposal>();
|
||||
auto son_proposal_itr = son_proposal_idx.find( proposal.id );
|
||||
if( son_proposal_itr == son_proposal_idx.end() ) {
|
||||
return;
|
||||
}
|
||||
remove( *son_proposal_itr );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW( (proposal) ) }
|
||||
|
||||
void database::remove_inactive_son_down_proposals( const vector<son_id_type>& son_ids_to_remove )
|
||||
{
|
||||
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get< by_id >();
|
||||
std::vector<proposal_id_type> proposals_to_remove;
|
||||
|
||||
for( auto& son_proposal : son_proposal_idx )
|
||||
{
|
||||
if(son_proposal.proposal_type == son_proposal_type::son_report_down_proposal)
|
||||
{
|
||||
auto it = std::find(son_ids_to_remove.begin(), son_ids_to_remove.end(), son_proposal.son_id);
|
||||
if (it != son_ids_to_remove.end())
|
||||
{
|
||||
ilog( "Removing inactive proposal ${p} for son ${s}", ("p", son_proposal.proposal_id) ("s",son_proposal.son_id));
|
||||
proposals_to_remove.push_back(son_proposal.proposal_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto& proposal_id : proposals_to_remove )
|
||||
{
|
||||
const auto& proposal_obj = proposal_id(*this);
|
||||
remove_son_proposal(proposal_obj);
|
||||
remove(proposal_obj);
|
||||
}
|
||||
}
|
||||
|
||||
void database::remove_inactive_son_proposals( const vector<son_id_type>& son_ids_to_remove )
|
||||
{
|
||||
remove_inactive_son_down_proposals( son_ids_to_remove );
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@
|
|||
#define SON_DEREGISTER_TIME (60*60*12) // 12 Hours in seconds
|
||||
#define SON_HEARTBEAT_FREQUENCY (60*3) // 3 minutes in seconds
|
||||
#define SON_DOWN_TIME (60*3*2) // 2 Heartbeats in seconds
|
||||
#define SON_PAY_TIME (60*60*24) // 1 day
|
||||
#define MIN_SON_PAY_DAILY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200))
|
||||
#define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT)
|
||||
#define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0))
|
||||
|
|
|
|||
|
|
@ -304,7 +304,6 @@ namespace graphene { namespace chain {
|
|||
std::set<son_id_type> get_sons_to_be_deregistered();
|
||||
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 );
|
||||
void remove_son_proposal( const proposal_object& proposal );
|
||||
bool is_son_dereg_valid( son_id_type son_id );
|
||||
|
||||
time_point_sec head_block_time()const;
|
||||
|
|
@ -549,6 +548,11 @@ namespace graphene { namespace chain {
|
|||
void update_active_committee_members();
|
||||
void update_son_metrics();
|
||||
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_worker_votes();
|
||||
|
||||
template<class... Types>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace graphene { namespace chain {
|
|||
optional < uint32_t > son_vesting_amount;
|
||||
optional < uint32_t > son_vesting_period;
|
||||
optional < uint32_t > son_pay_daily_max;
|
||||
optional < uint32_t > son_pay_time;
|
||||
optional < uint32_t > son_deregister_time;
|
||||
optional < uint32_t > son_heartbeat_frequency;
|
||||
optional < uint32_t > son_down_time;
|
||||
|
|
@ -141,6 +142,9 @@ namespace graphene { namespace chain {
|
|||
inline uint16_t son_pay_daily_max()const {
|
||||
return extensions.value.son_pay_daily_max.valid() ? *extensions.value.son_pay_daily_max : MIN_SON_PAY_DAILY_MAX;
|
||||
}
|
||||
inline uint16_t son_pay_time()const {
|
||||
return extensions.value.son_pay_time.valid() ? *extensions.value.son_pay_time : SON_PAY_TIME;
|
||||
}
|
||||
inline uint16_t son_deregister_time()const {
|
||||
return extensions.value.son_deregister_time.valid() ? *extensions.value.son_deregister_time : SON_DEREGISTER_TIME;
|
||||
}
|
||||
|
|
@ -167,6 +171,7 @@ FC_REFLECT( graphene::chain::parameter_extension,
|
|||
(son_vesting_amount)
|
||||
(son_vesting_period)
|
||||
(son_pay_daily_max)
|
||||
(son_pay_time)
|
||||
(son_deregister_time)
|
||||
(son_heartbeat_frequency)
|
||||
(son_down_time)
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ void_result delete_son_evaluator::do_apply(const son_delete_operation& op)
|
|||
void_result son_heartbeat_evaluator::do_evaluate(const son_heartbeat_operation& op)
|
||||
{ try {
|
||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass
|
||||
FC_ASSERT(db().get(op.son_id).son_account == op.owner_account);
|
||||
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);
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ void_result process_son_wallet_deposit_evaluator::do_evaluate(const son_wallet_d
|
|||
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 transfer not found");
|
||||
//FC_ASSERT(itr->processed == false, "Son wallet transfer is already processed");
|
||||
|
||||
const database& d = db();
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ void_result process_son_wallet_withdraw_evaluator::do_evaluate(const son_wallet_
|
|||
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");
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type process_son_wallet_withdraw_evaluator::do_apply(const son_wallet_withdraw_process_operation& op)
|
||||
|
|
|
|||
|
|
@ -539,18 +539,22 @@ std::vector<zmq::message_t> zmq_listener::receive_multipart() {
|
|||
}
|
||||
|
||||
void zmq_listener::handle_zmq() {
|
||||
int linger = 0;
|
||||
socket.setsockopt(ZMQ_SUBSCRIBE, "hashblock", 9);
|
||||
socket.setsockopt(ZMQ_LINGER, &linger, sizeof(linger));
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "hashtx", 6 );
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "rawblock", 8 );
|
||||
//socket.setsockopt( ZMQ_SUBSCRIBE, "rawtx", 5 );
|
||||
socket.connect("tcp://" + ip + ":" + std::to_string(zmq_port));
|
||||
|
||||
while (true) {
|
||||
auto msg = receive_multipart();
|
||||
const auto header = std::string(static_cast<char *>(msg[0].data()), msg[0].size());
|
||||
const auto block_hash = boost::algorithm::hex(std::string(static_cast<char *>(msg[1].data()), msg[1].size()));
|
||||
|
||||
event_received(block_hash);
|
||||
try {
|
||||
auto msg = receive_multipart();
|
||||
const auto header = std::string(static_cast<char *>(msg[0].data()), msg[0].size());
|
||||
const auto block_hash = boost::algorithm::hex(std::string(static_cast<char *>(msg[1].data()), msg[1].size()));
|
||||
event_received(block_hash);
|
||||
} catch (zmq::error_t& e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue