SON126 - Witness Proposals to deregister SONs
This commit is contained in:
parent
e0242bcf86
commit
011d3a51a5
13 changed files with 189 additions and 3 deletions
|
|
@ -426,6 +426,26 @@ signed_block database::_generate_block(
|
|||
_pending_tx_session.reset();
|
||||
_pending_tx_session = _undo_db.start_undo_session();
|
||||
|
||||
if( head_block_time() > HARDFORK_SON_TIME )
|
||||
{
|
||||
std::set<son_id_type> sons_to_be_dereg = get_sons_to_be_deregistered();
|
||||
if(sons_to_be_dereg.size() > 0)
|
||||
{
|
||||
std::set<son_id_type> sons_being_dereg = get_sons_being_deregistered();
|
||||
for( auto& son : sons_to_be_dereg)
|
||||
{
|
||||
if(sons_being_dereg.find(son) == sons_being_dereg.end())
|
||||
{
|
||||
auto op = create_son_deregister_proposal(son, witness_obj);
|
||||
if(op.valid())
|
||||
{
|
||||
_pending_tx.insert( _pending_tx.begin(), create_signed_transaction( block_signing_private_key, *op ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t postponed_tx_count = 0;
|
||||
// pop pending state (reset to head block state)
|
||||
for( const processed_transaction& tx : _pending_tx )
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@
|
|||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/chain_property_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
#include <ctime>
|
||||
|
|
@ -141,4 +142,68 @@ const std::vector<uint32_t> database::get_winner_numbers( asset_id_type for_asse
|
|||
return result;
|
||||
}
|
||||
|
||||
std::set<son_id_type> database::get_sons_being_deregistered()
|
||||
{
|
||||
std::set<son_id_type> ret;
|
||||
const auto& son_proposal_idx = get_index_type<son_proposal_index>().indices().get< by_id >();
|
||||
|
||||
for( auto& son_proposal : son_proposal_idx )
|
||||
{
|
||||
if(son_proposal.proposal_type == son_proposal_type::son_deregister_proposal)
|
||||
{
|
||||
ret.insert(son_proposal.son_id);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::set<son_id_type> database::get_sons_to_be_deregistered()
|
||||
{
|
||||
std::set<son_id_type> ret;
|
||||
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
|
||||
|
||||
for( auto& son : son_idx )
|
||||
{
|
||||
if(son.status == son_status::in_maintenance)
|
||||
{
|
||||
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
|
||||
// is needed for release of funds from the PW
|
||||
if(head_block_time() - stats.last_down_timestamp >= fc::hours(SON_DEREGISTER_TIME))
|
||||
{
|
||||
ret.insert(son.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
fc::optional<operation> database::create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness )
|
||||
{
|
||||
son_delete_operation son_dereg_op;
|
||||
son_dereg_op.payer = current_witness.witness_account;
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = current_witness.witness_account;
|
||||
proposal_op.proposed_ops.push_back( op_wrapper( son_dereg_op ) );
|
||||
uint32_t lifetime = ( get_global_properties().parameters.block_interval * get_global_properties().active_witnesses.size() ) * 3;
|
||||
proposal_op.expiration_time = time_point_sec( head_block_time().sec_since_epoch() + lifetime );
|
||||
return proposal_op;
|
||||
}
|
||||
|
||||
signed_transaction database::create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op )
|
||||
{
|
||||
signed_transaction processed_trx;
|
||||
auto dyn_props = get_dynamic_global_properties();
|
||||
processed_trx.set_reference_block( dyn_props.head_block_id );
|
||||
processed_trx.set_expiration( head_block_time() + get_global_properties().parameters.maximum_time_until_expiration );
|
||||
processed_trx.operations.push_back( op );
|
||||
current_fee_schedule().set_fee( processed_trx.operations.back() );
|
||||
|
||||
processed_trx.sign( signing_private_key, get_chain_id() );
|
||||
|
||||
return processed_trx;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include <graphene/chain/betting_market_object.hpp>
|
||||
#include <graphene/chain/global_betting_statistics_object.hpp>
|
||||
#include <graphene/chain/son_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/asset_evaluator.hpp>
|
||||
|
|
@ -288,6 +289,7 @@ void database::initialize_indexes()
|
|||
tournament_details_idx->add_secondary_index<tournament_players_index>();
|
||||
add_index< primary_index<match_index> >();
|
||||
add_index< primary_index<game_index> >();
|
||||
add_index< primary_index<son_proposal_index> >();
|
||||
|
||||
//Implementation object indexes
|
||||
add_index< primary_index<transaction_index > >();
|
||||
|
|
|
|||
|
|
@ -233,7 +233,8 @@
|
|||
#define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week
|
||||
#define MIN_SON_MEMBER_COUNT 15
|
||||
#define SON_VESTING_AMOUNT (50*GRAPHENE_BLOCKCHAIN_PRECISION) // 50 PPY
|
||||
#define SON_VESTING_PERIOD (60*60*24*30) // 2 days
|
||||
#define SON_VESTING_PERIOD (60*60*24*2) // 2 days
|
||||
#define SON_DEREGISTER_TIME (12) // 12 Hours
|
||||
#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))
|
||||
|
|
|
|||
|
|
@ -279,6 +279,10 @@ namespace graphene { namespace chain {
|
|||
const std::vector<uint32_t> get_winner_numbers( asset_id_type for_asset, uint32_t count_members, uint8_t count_winners ) const;
|
||||
std::vector<uint32_t> get_seeds( asset_id_type for_asset, uint8_t count_winners )const;
|
||||
uint64_t get_random_bits( uint64_t bound );
|
||||
std::set<son_id_type> get_sons_being_deregistered();
|
||||
std::set<son_id_type> get_sons_to_be_deregistered();
|
||||
fc::optional<operation> create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness );
|
||||
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
|
||||
|
||||
time_point_sec head_block_time()const;
|
||||
uint32_t head_block_num()const;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,21 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class son_hardfork_visitor
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
database& db;
|
||||
proposal_id_type prop_id;
|
||||
|
||||
son_hardfork_visitor( database& _db, const proposal_id_type& _prop_id ) : db( _db ), prop_id( _prop_id ) {}
|
||||
|
||||
template<typename T>
|
||||
void operator()( const T &v ) const {}
|
||||
|
||||
void operator()( const son_delete_operation &v );
|
||||
};
|
||||
|
||||
class proposal_create_evaluator : public evaluator<proposal_create_evaluator>
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -40,9 +40,10 @@ namespace graphene { namespace chain {
|
|||
|
||||
asset fee;
|
||||
son_id_type son_id;
|
||||
account_id_type payer;
|
||||
account_id_type owner_account;
|
||||
|
||||
account_id_type fee_payer()const { return owner_account; }
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ namespace graphene { namespace chain {
|
|||
betting_market_object_type,
|
||||
bet_object_type,
|
||||
son_object_type,
|
||||
son_proposal_object_type,
|
||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
|
|
@ -207,6 +208,7 @@ namespace graphene { namespace chain {
|
|||
class betting_market_object;
|
||||
class bet_object;
|
||||
class son_object;
|
||||
class son_proposal_object;
|
||||
|
||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||
|
|
@ -234,6 +236,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
|
||||
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
||||
typedef object_id< protocol_ids, son_object_type, son_object> son_id_type;
|
||||
typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type;
|
||||
|
||||
// implementation types
|
||||
class global_property_object;
|
||||
|
|
@ -417,6 +420,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
|||
(betting_market_object_type)
|
||||
(bet_object_type)
|
||||
(son_object_type)
|
||||
(son_proposal_object_type)
|
||||
(OBJECT_TYPE_COUNT)
|
||||
)
|
||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||
|
|
@ -488,6 +492,7 @@ FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
|||
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_id_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::son_proposal_id_type )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::void_t, )
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
enum class son_status
|
||||
{
|
||||
inactive,
|
||||
active,
|
||||
in_maintenance
|
||||
};
|
||||
/**
|
||||
* @class son_statistics_object
|
||||
* @ingroup object
|
||||
|
|
@ -23,6 +29,10 @@ namespace graphene { namespace chain {
|
|||
son_id_type owner;
|
||||
// Transactions signed since the last son payouts
|
||||
uint64_t txs_signed = 0;
|
||||
// Total Downtime barring the current down time in seconds, used for stats to present to user
|
||||
uint64_t total_downtime = 0;
|
||||
// Down timestamp, if son status is in_maintenance use this
|
||||
fc::time_point_sec last_down_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -44,6 +54,7 @@ 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;
|
||||
|
||||
void pay_son_fee(share_type pay, database& db);
|
||||
};
|
||||
|
|
@ -76,6 +87,8 @@ namespace graphene { namespace chain {
|
|||
using son_stats_index = generic_index<son_statistics_object, son_stats_multi_index_type>;
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::son_status, (inactive)(active)(in_maintenance) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object),
|
||||
(son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb) )
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
enum class son_proposal_type
|
||||
{
|
||||
son_deregister_proposal
|
||||
};
|
||||
|
||||
class son_proposal_object : public abstract_object<son_proposal_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = son_proposal_object_type;
|
||||
|
||||
son_proposal_id_type get_id()const { return id; }
|
||||
|
||||
proposal_id_type proposal_id;
|
||||
son_id_type son_id;
|
||||
son_proposal_type proposal_type;
|
||||
};
|
||||
|
||||
//struct by_proposal;
|
||||
//struct by_type;
|
||||
using son_proposal_multi_index_container = multi_index_container<
|
||||
son_proposal_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >
|
||||
>
|
||||
>;
|
||||
using son_proposal_index = generic_index<son_proposal_object, son_proposal_multi_index_container>;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_ENUM(graphene::chain::son_proposal_type, (son_deregister_proposal) )
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::son_proposal_object, (graphene::chain::object), (proposal_id)(son_id)(proposal_type) )
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
#include <graphene/chain/proposal_evaluator.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/son_proposal_object.hpp>
|
||||
#include <graphene/chain/protocol/account.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/chain/protocol/tournament.hpp>
|
||||
|
|
@ -154,6 +155,15 @@ struct proposal_operation_hardfork_visitor
|
|||
}
|
||||
};
|
||||
|
||||
void son_hardfork_visitor::operator()( const son_delete_operation &v )
|
||||
{
|
||||
db.create<son_proposal_object>([&]( son_proposal_object& son_prop ) {
|
||||
son_prop.proposal_type = son_proposal_type::son_deregister_proposal;
|
||||
son_prop.proposal_id = prop_id;
|
||||
son_prop.son_id = v.son_id;
|
||||
});
|
||||
}
|
||||
|
||||
void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o)
|
||||
{ try {
|
||||
const database& d = db();
|
||||
|
|
@ -232,6 +242,12 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
|
|||
std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin()));
|
||||
});
|
||||
|
||||
son_hardfork_visitor son_vtor(d, proposal.id);
|
||||
for(auto& op: o.proposed_ops)
|
||||
{
|
||||
op.op.visit(son_vtor);
|
||||
}
|
||||
|
||||
return proposal.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1918,6 +1918,7 @@ public:
|
|||
son_delete_operation son_delete_op;
|
||||
son_delete_op.son_id = son.id;
|
||||
son_delete_op.owner_account = son.son_account;
|
||||
son_delete_op.payer = son.son_account;
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( son_delete_op );
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ try {
|
|||
son_delete_operation op;
|
||||
op.owner_account = alice_id;
|
||||
op.son_id = son_id_type(0);
|
||||
op.payer = alice_id;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
|
|
@ -205,6 +206,7 @@ try {
|
|||
son_delete_operation op;
|
||||
op.owner_account = bob_id;
|
||||
op.son_id = son_id_type(0);
|
||||
op.payer = bob_id;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, bob_private_key);
|
||||
|
|
|
|||
Loading…
Reference in a new issue