solution ...issues/#7 Allow vesting core tokens to vote and receive dividends
This commit is contained in:
parent
f2c0157bb7
commit
81c9e98d7b
2 changed files with 76 additions and 14 deletions
|
|
@ -727,14 +727,15 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
const asset_dividend_data_object& dividend_data,
|
const asset_dividend_data_object& dividend_data,
|
||||||
const fc::time_point_sec& current_head_block_time,
|
const fc::time_point_sec& current_head_block_time,
|
||||||
const account_balance_index& balance_index,
|
const account_balance_index& balance_index,
|
||||||
|
const vesting_balance_index& vesting_index,
|
||||||
const total_distributed_dividend_balance_object_index& distributed_dividend_balance_index,
|
const total_distributed_dividend_balance_object_index& distributed_dividend_balance_index,
|
||||||
const pending_dividend_payout_balance_for_holder_object_index& pending_payout_balance_index)
|
const pending_dividend_payout_balance_for_holder_object_index& pending_payout_balance_index)
|
||||||
{
|
{
|
||||||
dlog("Processing dividend payments for dividend holder asset type ${holder_asset} at time ${t}",
|
dlog("Processing dividend payments for dividend holder asset type ${holder_asset} at time ${t}",
|
||||||
("holder_asset", dividend_holder_asset_obj.symbol)("t", db.head_block_time()));
|
("holder_asset", dividend_holder_asset_obj.symbol)("t", db.head_block_time()));
|
||||||
auto current_distribution_account_balance_range =
|
auto current_distribution_account_balance_range =
|
||||||
balance_index.indices().get<by_account_asset>().equal_range(boost::make_tuple(dividend_data.dividend_distribution_account));
|
balance_index.indices().get<by_account_asset>().equal_range(boost::make_tuple(dividend_data.dividend_distribution_account));
|
||||||
auto previous_distribution_account_balance_range =
|
auto previous_distribution_account_balance_range =
|
||||||
distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id));
|
distributed_dividend_balance_index.indices().get<by_dividend_payout_asset>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id));
|
||||||
// the current range is now all current balances for the distribution account, sorted by asset_type
|
// the current range is now all current balances for the distribution account, sorted by asset_type
|
||||||
// the previous range is now all previous balances for this account, sorted by asset type
|
// the previous range is now all previous balances for this account, sorted by asset type
|
||||||
|
|
@ -744,7 +745,7 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
// get the list of accounts that hold nonzero balances of the dividend asset
|
// get the list of accounts that hold nonzero balances of the dividend asset
|
||||||
auto holder_balances_begin =
|
auto holder_balances_begin =
|
||||||
balance_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(dividend_holder_asset_obj.id));
|
balance_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(dividend_holder_asset_obj.id));
|
||||||
auto holder_balances_end =
|
auto holder_balances_end =
|
||||||
balance_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(dividend_holder_asset_obj.id, share_type()));
|
balance_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(dividend_holder_asset_obj.id, share_type()));
|
||||||
uint32_t holder_account_count = std::distance(holder_balances_begin, holder_balances_end);
|
uint32_t holder_account_count = std::distance(holder_balances_begin, holder_balances_end);
|
||||||
uint64_t distribution_base_fee = gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_base_fee;
|
uint64_t distribution_base_fee = gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_base_fee;
|
||||||
|
|
@ -752,6 +753,20 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
// the fee, in BTS, for distributing each asset in the account
|
// the fee, in BTS, for distributing each asset in the account
|
||||||
uint64_t total_fee_per_asset_in_core = distribution_base_fee + holder_account_count * (uint64_t)distribution_fee_per_holder;
|
uint64_t total_fee_per_asset_in_core = distribution_base_fee + holder_account_count * (uint64_t)distribution_fee_per_holder;
|
||||||
|
|
||||||
|
std::map<account_id_type, share_type> vesting_amounts;
|
||||||
|
// get only once a collection of accounts that hold nonzero vesting balances of the dividend asset
|
||||||
|
auto vesting_balances_begin =
|
||||||
|
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(dividend_holder_asset_obj.id));
|
||||||
|
auto vesting_balances_end =
|
||||||
|
vesting_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(dividend_holder_asset_obj.id, share_type()));
|
||||||
|
for (const vesting_balance_object& vesting_balance_obj : boost::make_iterator_range(vesting_balances_begin, vesting_balances_end))
|
||||||
|
{
|
||||||
|
vesting_amounts[vesting_balance_obj.owner] += vesting_balance_obj.balance.amount;
|
||||||
|
dlog("Vesting balance for account: ${owner}, amount: ${amount}",
|
||||||
|
("owner", vesting_balance_obj.owner(db).name)
|
||||||
|
("amount", vesting_balance_obj.balance.amount));
|
||||||
|
}
|
||||||
|
|
||||||
auto current_distribution_account_balance_iter = current_distribution_account_balance_range.first;
|
auto current_distribution_account_balance_iter = current_distribution_account_balance_range.first;
|
||||||
auto previous_distribution_account_balance_iter = previous_distribution_account_balance_range.first;
|
auto previous_distribution_account_balance_iter = previous_distribution_account_balance_range.first;
|
||||||
dlog("Current balances in distribution account: ${current}, Previous balances: ${previous}",
|
dlog("Current balances in distribution account: ${current}, Previous balances: ${previous}",
|
||||||
|
|
@ -764,9 +779,12 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
share_type total_balance_of_dividend_asset;
|
share_type total_balance_of_dividend_asset;
|
||||||
for (const account_balance_object& holder_balance_object : boost::make_iterator_range(holder_balances_begin, holder_balances_end))
|
for (const account_balance_object& holder_balance_object : boost::make_iterator_range(holder_balances_begin, holder_balances_end))
|
||||||
if (holder_balance_object.owner != dividend_data.dividend_distribution_account)
|
if (holder_balance_object.owner != dividend_data.dividend_distribution_account)
|
||||||
|
{
|
||||||
total_balance_of_dividend_asset += holder_balance_object.balance;
|
total_balance_of_dividend_asset += holder_balance_object.balance;
|
||||||
|
auto itr = vesting_amounts.find(holder_balance_object.owner);
|
||||||
|
if (itr != vesting_amounts.end())
|
||||||
|
total_balance_of_dividend_asset += itr->second;
|
||||||
|
}
|
||||||
// loop through all of the assets currently or previously held in the distribution account
|
// loop through all of the assets currently or previously held in the distribution account
|
||||||
while (current_distribution_account_balance_iter != current_distribution_account_balance_range.second ||
|
while (current_distribution_account_balance_iter != current_distribution_account_balance_range.second ||
|
||||||
previous_distribution_account_balance_iter != previous_distribution_account_balance_range.second)
|
previous_distribution_account_balance_iter != previous_distribution_account_balance_range.second)
|
||||||
|
|
@ -892,13 +910,21 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
|
|
||||||
// credit each account with their portion, don't send any back to the dividend distribution account
|
// credit each account with their portion, don't send any back to the dividend distribution account
|
||||||
for (const account_balance_object& holder_balance_object : boost::make_iterator_range(holder_balances_begin, holder_balances_end))
|
for (const account_balance_object& holder_balance_object : boost::make_iterator_range(holder_balances_begin, holder_balances_end))
|
||||||
if (holder_balance_object.owner != dividend_data.dividend_distribution_account &&
|
{
|
||||||
holder_balance_object.balance.value)
|
if (holder_balance_object.owner == dividend_data.dividend_distribution_account) continue;
|
||||||
|
|
||||||
|
auto holder_balance = holder_balance_object.balance;
|
||||||
|
|
||||||
|
auto itr = vesting_amounts.find(holder_balance_object.owner);
|
||||||
|
if (itr != vesting_amounts.end())
|
||||||
|
holder_balance += itr->second;
|
||||||
|
|
||||||
|
if (holder_balance.value)
|
||||||
{
|
{
|
||||||
fc::uint128_t amount_to_credit(delta_balance.value);
|
fc::uint128_t amount_to_credit(delta_balance.value);
|
||||||
amount_to_credit *= holder_balance_object.balance.value;
|
amount_to_credit *= holder_balance.value;
|
||||||
amount_to_credit /= total_balance_of_dividend_asset.value;
|
amount_to_credit /= total_balance_of_dividend_asset.value;
|
||||||
//wdump((delta_balance.value)(holder_balance_object.balance)(total_balance_of_dividend_asset));
|
wdump((delta_balance.value)(holder_balance)(total_balance_of_dividend_asset));
|
||||||
share_type shares_to_credit((int64_t)amount_to_credit.to_uint64());
|
share_type shares_to_credit((int64_t)amount_to_credit.to_uint64());
|
||||||
|
|
||||||
remaining_amount_to_distribute -= shares_to_credit;
|
remaining_amount_to_distribute -= shares_to_credit;
|
||||||
|
|
@ -920,6 +946,7 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
pending_balance.pending_balance += shares_to_credit;
|
pending_balance.pending_balance += shares_to_credit;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& pending_payout : pending_payout_balance_index.indices())
|
for (const auto& pending_payout : pending_payout_balance_index.indices())
|
||||||
dlog("Pending payout: ${account_name} -> ${amount}",
|
dlog("Pending payout: ${account_name} -> ${amount}",
|
||||||
|
|
@ -928,7 +955,6 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
dlog("Remaining balance not paid out: ${amount}",
|
dlog("Remaining balance not paid out: ${amount}",
|
||||||
("amount", asset(remaining_amount_to_distribute, payout_asset_type)));
|
("amount", asset(remaining_amount_to_distribute, payout_asset_type)));
|
||||||
|
|
||||||
|
|
||||||
share_type distributed_amount = delta_balance - remaining_amount_to_distribute;
|
share_type distributed_amount = delta_balance - remaining_amount_to_distribute;
|
||||||
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
|
if (previous_distribution_account_balance_iter == previous_distribution_account_balance_range.second ||
|
||||||
previous_distribution_account_balance_iter->dividend_payout_asset_type != payout_asset_type)
|
previous_distribution_account_balance_iter->dividend_payout_asset_type != payout_asset_type)
|
||||||
|
|
@ -1017,6 +1043,7 @@ void process_dividend_assets(database& db)
|
||||||
ilog("In process_dividend_assets time ${time}", ("time", db.head_block_time()));
|
ilog("In process_dividend_assets time ${time}", ("time", db.head_block_time()));
|
||||||
|
|
||||||
const account_balance_index& balance_index = db.get_index_type<account_balance_index>();
|
const account_balance_index& balance_index = db.get_index_type<account_balance_index>();
|
||||||
|
const vesting_balance_index& vbalance_index = db.get_index_type<vesting_balance_index>();
|
||||||
const total_distributed_dividend_balance_object_index& distributed_dividend_balance_index = db.get_index_type<total_distributed_dividend_balance_object_index>();
|
const total_distributed_dividend_balance_object_index& distributed_dividend_balance_index = db.get_index_type<total_distributed_dividend_balance_object_index>();
|
||||||
const pending_dividend_payout_balance_for_holder_object_index& pending_payout_balance_index = db.get_index_type<pending_dividend_payout_balance_for_holder_object_index>();
|
const pending_dividend_payout_balance_for_holder_object_index& pending_payout_balance_index = db.get_index_type<pending_dividend_payout_balance_for_holder_object_index>();
|
||||||
|
|
||||||
|
|
@ -1030,7 +1057,7 @@ void process_dividend_assets(database& db)
|
||||||
fc::time_point_sec current_head_block_time = db.head_block_time();
|
fc::time_point_sec current_head_block_time = db.head_block_time();
|
||||||
|
|
||||||
schedule_pending_dividend_balances(db, dividend_holder_asset_obj, dividend_data, current_head_block_time,
|
schedule_pending_dividend_balances(db, dividend_holder_asset_obj, dividend_data, current_head_block_time,
|
||||||
balance_index, distributed_dividend_balance_index, pending_payout_balance_index);
|
balance_index, vbalance_index, distributed_dividend_balance_index, pending_payout_balance_index);
|
||||||
if (dividend_data.options.next_payout_time &&
|
if (dividend_data.options.next_payout_time &&
|
||||||
db.head_block_time() >= *dividend_data.options.next_payout_time)
|
db.head_block_time() >= *dividend_data.options.next_payout_time)
|
||||||
{
|
{
|
||||||
|
|
@ -1180,6 +1207,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
struct vote_tally_helper {
|
struct vote_tally_helper {
|
||||||
database& d;
|
database& d;
|
||||||
const global_property_object& props;
|
const global_property_object& props;
|
||||||
|
std::map<account_id_type, share_type> vesting_amounts;
|
||||||
|
|
||||||
vote_tally_helper(database& d, const global_property_object& gpo)
|
vote_tally_helper(database& d, const global_property_object& gpo)
|
||||||
: d(d), props(gpo)
|
: d(d), props(gpo)
|
||||||
|
|
@ -1188,6 +1216,19 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1);
|
d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1);
|
||||||
d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1);
|
d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1);
|
||||||
d._total_voting_stake = 0;
|
d._total_voting_stake = 0;
|
||||||
|
|
||||||
|
const vesting_balance_index& vesting_index = d.get_index_type<vesting_balance_index>();
|
||||||
|
auto vesting_balances_begin =
|
||||||
|
vesting_index.indices().get<by_asset_balance>().lower_bound(boost::make_tuple(asset_id_type()));
|
||||||
|
auto vesting_balances_end =
|
||||||
|
vesting_index.indices().get<by_asset_balance>().upper_bound(boost::make_tuple(asset_id_type(), share_type()));
|
||||||
|
for (const vesting_balance_object& vesting_balance_obj : boost::make_iterator_range(vesting_balances_begin, vesting_balances_end))
|
||||||
|
{
|
||||||
|
vesting_amounts[vesting_balance_obj.owner] += vesting_balance_obj.balance.amount;
|
||||||
|
dlog("Vesting balance for account: ${owner}, amount: ${amount}",
|
||||||
|
("owner", vesting_balance_obj.owner(d).name)
|
||||||
|
("amount", vesting_balance_obj.balance.amount));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const account_object& stake_account) {
|
void operator()(const account_object& stake_account) {
|
||||||
|
|
@ -1206,6 +1247,10 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
|
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
|
||||||
+ d.get_balance(stake_account.get_id(), asset_id_type()).amount.value;
|
+ d.get_balance(stake_account.get_id(), asset_id_type()).amount.value;
|
||||||
|
|
||||||
|
auto itr = vesting_amounts.find(stake_account.id);
|
||||||
|
if (itr != vesting_amounts.end())
|
||||||
|
voting_stake += itr->second.value;
|
||||||
|
|
||||||
for( vote_id_type id : opinion_account.options.votes )
|
for( vote_id_type id : opinion_account.options.votes )
|
||||||
{
|
{
|
||||||
uint32_t offset = id.instance();
|
uint32_t offset = id.instance();
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,10 @@
|
||||||
#include <fc/uint128.hpp>
|
#include <fc/uint128.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/multi_index/composite_key.hpp>
|
||||||
|
|
||||||
|
#define offset_d(i,f) (long(&(i)->f) - long(i))
|
||||||
|
#define offset_s(t,f) offset_d((t*)1000, f)
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
using namespace graphene::db;
|
using namespace graphene::db;
|
||||||
|
|
@ -171,13 +173,28 @@ namespace graphene { namespace chain {
|
||||||
* @ingroup object_index
|
* @ingroup object_index
|
||||||
*/
|
*/
|
||||||
struct by_account;
|
struct by_account;
|
||||||
|
struct by_asset_balance;
|
||||||
typedef multi_index_container<
|
typedef multi_index_container<
|
||||||
vesting_balance_object,
|
vesting_balance_object,
|
||||||
indexed_by<
|
indexed_by<
|
||||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
ordered_non_unique< tag<by_account>,
|
ordered_non_unique< tag<by_account>,
|
||||||
member<vesting_balance_object, account_id_type, &vesting_balance_object::owner>
|
member<vesting_balance_object, account_id_type, &vesting_balance_object::owner>
|
||||||
>
|
>,
|
||||||
|
ordered_unique< tag<by_asset_balance>,
|
||||||
|
composite_key<
|
||||||
|
vesting_balance_object,
|
||||||
|
member_offset<vesting_balance_object, asset_id_type, (size_t) (offset_s(vesting_balance_object,balance) + offset_s(asset,asset_id))>,
|
||||||
|
member_offset<vesting_balance_object, share_type, (size_t) (offset_s(vesting_balance_object,balance) + offset_s(asset,amount))>
|
||||||
|
//member<vesting_balance_object, account_id_type, &vesting_balance_object::owner>
|
||||||
|
//member_offset<vesting_balance_object, account_id_type, (size_t) (offset_s(vesting_balance_object,owner))>
|
||||||
|
>,
|
||||||
|
composite_key_compare<
|
||||||
|
std::less< asset_id_type >,
|
||||||
|
std::greater< share_type >
|
||||||
|
//std::less< account_id_type >
|
||||||
|
>
|
||||||
|
>
|
||||||
>
|
>
|
||||||
> vesting_balance_multi_index_type;
|
> vesting_balance_multi_index_type;
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue