Merge branch 'rock-paper-scissors-ro' into rock-paper-scissors
This commit is contained in:
commit
b72eae0941
10 changed files with 377 additions and 143 deletions
10
genesis.json
10
genesis.json
|
|
@ -201,6 +201,16 @@
|
|||
"distribution_base_fee": 0,
|
||||
"distribution_fee_per_holder": 0
|
||||
}
|
||||
],[
|
||||
47,{
|
||||
"fee": 100000
|
||||
}
|
||||
],[
|
||||
48,{
|
||||
"fee": 51000000
|
||||
}
|
||||
],[
|
||||
49,{}
|
||||
]
|
||||
],
|
||||
"scale": 10
|
||||
|
|
|
|||
|
|
@ -327,7 +327,16 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
a.network_fee_percentage = 0;
|
||||
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
|
||||
}).get_id() == GRAPHENE_PROXY_TO_SELF_ACCOUNT);
|
||||
|
||||
FC_ASSERT(create<account_object>([this](account_object& a) {
|
||||
a.name = "test-dividend-distribution";
|
||||
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
|
||||
a.owner.weight_threshold = 1;
|
||||
a.active.weight_threshold = 1;
|
||||
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_PROXY_TO_SELF_ACCOUNT;
|
||||
a.membership_expiration_date = time_point_sec::maximum();
|
||||
a.network_fee_percentage = 0;
|
||||
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
|
||||
}).get_id() == TOURNAMENT_RAKE_FEE_ACCOUNT_ID);
|
||||
// Create more special accounts
|
||||
while( true )
|
||||
{
|
||||
|
|
@ -353,6 +362,22 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
|
||||
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
});
|
||||
|
||||
const asset_dividend_data_object& div_asset =
|
||||
create<asset_dividend_data_object>([&](asset_dividend_data_object& a) {
|
||||
a.options.minimum_distribution_interval = 3*24*60*60;
|
||||
a.options.minimum_fee_percentage = 10*GRAPHENE_1_PERCENT;
|
||||
a.options.next_payout_time = genesis_state.initial_timestamp + fc::hours(1);
|
||||
a.options.payout_interval = 7*24*60*60;
|
||||
a.dividend_distribution_account = TOURNAMENT_RAKE_FEE_ACCOUNT_ID;
|
||||
});
|
||||
const asset_bitasset_data_object& bit_asset =
|
||||
create<asset_bitasset_data_object>([&](asset_bitasset_data_object& a) {
|
||||
a.current_feed.maintenance_collateral_ratio = 1750;
|
||||
a.current_feed.maximum_short_squeeze_ratio = 1500;
|
||||
a.current_feed_publication_time = genesis_state.initial_timestamp + fc::hours(1);
|
||||
});
|
||||
|
||||
const asset_object& core_asset =
|
||||
create<asset_object>( [&]( asset_object& a ) {
|
||||
a.symbol = GRAPHENE_SYMBOL;
|
||||
|
|
@ -360,15 +385,58 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
|
||||
a.options.flags = 0;
|
||||
a.options.issuer_permissions = 0;
|
||||
a.issuer = GRAPHENE_NULL_ACCOUNT;
|
||||
a.issuer = GRAPHENE_COMMITTEE_ACCOUNT;
|
||||
a.options.core_exchange_rate.base.amount = 1;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 1;
|
||||
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
|
||||
a.dynamic_asset_data_id = dyn_asset.id;
|
||||
});
|
||||
a.dividend_data_id = div_asset.id;
|
||||
a.bitasset_data_id = bit_asset.id;
|
||||
});
|
||||
assert( asset_id_type(core_asset.id) == asset().asset_id );
|
||||
assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
|
||||
|
||||
#ifdef _DEFAULT_DIVIDEND_ASSET
|
||||
// Create default dividend asset
|
||||
const asset_dynamic_data_object& dyn_asset1 =
|
||||
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
|
||||
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
});
|
||||
const asset_dividend_data_object& div_asset1 =
|
||||
create<asset_dividend_data_object>([&](asset_dividend_data_object& a) {
|
||||
a.options.minimum_distribution_interval = 3*24*60*60;
|
||||
a.options.minimum_fee_percentage = 10*GRAPHENE_1_PERCENT;
|
||||
a.options.next_payout_time = genesis_state.initial_timestamp + fc::hours(1);
|
||||
a.options.payout_interval = 7*24*60*60;
|
||||
a.dividend_distribution_account = TOURNAMENT_RAKE_FEE_ACCOUNT_ID;
|
||||
});
|
||||
const asset_bitasset_data_object& bit_asset1 =
|
||||
create<asset_bitasset_data_object>([&](asset_bitasset_data_object& a) {
|
||||
a.current_feed.maintenance_collateral_ratio = 1750;
|
||||
a.current_feed.maximum_short_squeeze_ratio = 1500;
|
||||
a.current_feed_publication_time = genesis_state.initial_timestamp + fc::hours(1);
|
||||
});
|
||||
|
||||
const asset_object& default_asset =
|
||||
create<asset_object>( [&]( asset_object& a ) {
|
||||
a.symbol = "DEFAULT";
|
||||
a.options.max_market_fee =
|
||||
a.options.max_supply = genesis_state.max_core_supply;
|
||||
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
|
||||
a.options.flags = 0;
|
||||
a.options.issuer_permissions = 79;
|
||||
a.issuer = TOURNAMENT_RAKE_FEE_ACCOUNT_ID;
|
||||
a.options.core_exchange_rate.base.amount = 1;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 1;
|
||||
a.options.core_exchange_rate.quote.asset_id = asset_id_type(1);
|
||||
a.dynamic_asset_data_id = dyn_asset1.id;
|
||||
a.dividend_data_id = div_asset1.id;
|
||||
a.bitasset_data_id = bit_asset1.id;
|
||||
});
|
||||
assert( default_asset.id == asset_id_type(1) );
|
||||
#endif
|
||||
// Create more special assets
|
||||
while( true )
|
||||
{
|
||||
|
|
@ -634,6 +702,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
{
|
||||
total_supplies[ asset_id_type(0) ] = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
}
|
||||
#ifdef _DEFAULT_DIVIDEND_ASSET
|
||||
total_debts[ asset_id_type(1) ] =
|
||||
total_supplies[ asset_id_type(1) ] = 0;
|
||||
#endif
|
||||
// it is workaround, should be clarified
|
||||
total_debts[ asset_id_type() ] = total_supplies[ asset_id_type() ];
|
||||
|
||||
const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>();
|
||||
auto it = idx.begin();
|
||||
|
|
@ -653,6 +727,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
elog( "Genesis for asset ${aname} is not balanced\n"
|
||||
" Debt is ${debt}\n"
|
||||
" Supply is ${supply}\n",
|
||||
("aname", debt_itr->first)
|
||||
("debt", debt_itr->second)
|
||||
("supply", supply_itr->second)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -352,6 +352,8 @@ FC_REFLECT_DERIVED( graphene::chain::asset_dividend_data_object, (graphene::db::
|
|||
(options)
|
||||
(last_scheduled_payout_time)
|
||||
(last_payout_time )
|
||||
(last_scheduled_distribution_time)
|
||||
(last_distribution_time)
|
||||
(dividend_distribution_account)
|
||||
)
|
||||
|
||||
|
|
@ -369,4 +371,5 @@ FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
|
|||
(dynamic_asset_data_id)
|
||||
(bitasset_data_id)
|
||||
(buyback_account)
|
||||
(dividend_data_id)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@
|
|||
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
|
||||
/// Represents the canonical account for specifying you will vote directly (as opposed to a proxy)
|
||||
#define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5))
|
||||
///
|
||||
#define TOURNAMENT_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6))
|
||||
/// Sentinel value used in the scheduler.
|
||||
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -595,6 +595,8 @@ FC_REFLECT( graphene::chain::asset_options,
|
|||
FC_REFLECT( graphene::chain::dividend_asset_options,
|
||||
(next_payout_time)
|
||||
(payout_interval)
|
||||
(minimum_fee_percentage)
|
||||
(minimum_distribution_interval)
|
||||
(extensions)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -268,13 +268,12 @@ namespace graphene { namespace chain {
|
|||
assert(event.match.match_winners.size() == 1);
|
||||
const account_id_type& winner = *event.match.match_winners.begin();
|
||||
uint16_t rake_fee_percentage = event.db.get_global_properties().parameters.rake_fee_percentage;
|
||||
share_type rake_amount = (fc::uint128_t(fsm.tournament_obj->prize_pool.value) * rake_fee_percentage / GRAPHENE_1_PERCENT).to_uint64();
|
||||
share_type rake_amount = (fc::uint128_t(fsm.tournament_obj->prize_pool.value) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100).to_uint64();
|
||||
event.db.adjust_balance(account_id_type(TOURNAMENT_RAKE_FEE_ACCOUNT_ID),
|
||||
asset(rake_amount, fsm.tournament_obj->options.buy_in.asset_id));
|
||||
event.db.adjust_balance(winner, asset(fsm.tournament_obj->prize_pool - rake_amount,
|
||||
fsm.tournament_obj->options.buy_in.asset_id));
|
||||
tournament_object& tournament = *fsm.tournament_obj;
|
||||
tournament.end_time = event.db.head_block_time();
|
||||
fsm.tournament_obj->end_time = event.db.head_block_time();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@
|
|||
#include <fc/smart_ref_impl.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace graphene::generate_genesis_plugin;
|
||||
using std::string;
|
||||
|
|
@ -41,187 +44,246 @@ using std::vector;
|
|||
namespace bpo = boost::program_options;
|
||||
|
||||
void generate_genesis_plugin::plugin_set_program_options(
|
||||
boost::program_options::options_description& command_line_options,
|
||||
boost::program_options::options_description& config_file_options)
|
||||
boost::program_options::options_description& command_line_options,
|
||||
boost::program_options::options_description& config_file_options)
|
||||
{
|
||||
command_line_options.add_options()
|
||||
("output-genesis-file,o", bpo::value<std::string>()->default_value("genesis.json"), "Genesis file to create")
|
||||
("snapshot-block-number", bpo::value<uint32_t>()->default_value(0), "Block number at which to snapshot balances")
|
||||
;
|
||||
config_file_options.add(command_line_options);
|
||||
command_line_options.add_options()
|
||||
("output-genesis-file,o", bpo::value<std::string>()->default_value("genesis.json"), "Genesis file to create")
|
||||
("output-csvlog-file,o", bpo::value<std::string>()->default_value("log.csv"), "CSV log file to create")
|
||||
("snapshot-block-number", bpo::value<uint32_t>()->default_value(0), "Block number at which to snapshot balances")
|
||||
;
|
||||
config_file_options.add(command_line_options);
|
||||
}
|
||||
|
||||
std::string generate_genesis_plugin::plugin_name()const
|
||||
{
|
||||
return "generate_genesis";
|
||||
return "generate_genesis";
|
||||
}
|
||||
|
||||
void generate_genesis_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{ try {
|
||||
ilog("generate genesis plugin: plugin_initialize() begin");
|
||||
_options = &options;
|
||||
ilog("generate genesis plugin: plugin_initialize() begin");
|
||||
_options = &options;
|
||||
|
||||
_genesis_filename = options["output-genesis-file"].as<std::string>();
|
||||
_block_to_snapshot = options["snapshot-block-number"].as<uint32_t>();
|
||||
database().applied_block.connect([this](const graphene::chain::signed_block& b){ block_applied(b); });
|
||||
ilog("generate genesis plugin: plugin_initialize() end");
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
_genesis_filename = options["output-genesis-file"].as<std::string>();
|
||||
_csvlog_filename = options["output-csvlog-file"].as<std::string>();
|
||||
_block_to_snapshot = options["snapshot-block-number"].as<uint32_t>();
|
||||
database().applied_block.connect([this](const graphene::chain::signed_block& b){ block_applied(b); });
|
||||
ilog("generate genesis plugin: plugin_initialize() end");
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
void generate_genesis_plugin::plugin_startup()
|
||||
{ try {
|
||||
ilog("generate genesis plugin: plugin_startup() begin");
|
||||
chain::database& d = database();
|
||||
if (d.head_block_num() == _block_to_snapshot)
|
||||
{
|
||||
ilog("generate genesis plugin: already at snapshot block");
|
||||
generate_snapshot();
|
||||
}
|
||||
else if (d.head_block_num() > _block_to_snapshot)
|
||||
elog("generate genesis plugin: already passed snapshot block, you must reindex to return to the snapshot state");
|
||||
else
|
||||
elog("generate genesis plugin: waiting for block ${snapshot_block} to generate snapshot, current head is ${head}",
|
||||
("snapshot_block", _block_to_snapshot)("head", d.head_block_num()));
|
||||
ilog("generate genesis plugin: plugin_startup() begin");
|
||||
chain::database& d = database();
|
||||
if (d.head_block_num() == _block_to_snapshot)
|
||||
{
|
||||
ilog("generate genesis plugin: already at snapshot block");
|
||||
generate_snapshot();
|
||||
}
|
||||
else if (d.head_block_num() > _block_to_snapshot)
|
||||
elog("generate genesis plugin: already passed snapshot block, you must reindex to return to the snapshot state");
|
||||
else
|
||||
elog("generate genesis plugin: waiting for block ${snapshot_block} to generate snapshot, current head is ${head}",
|
||||
("snapshot_block", _block_to_snapshot)("head", d.head_block_num()));
|
||||
|
||||
ilog("generate genesis plugin: plugin_startup() end");
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
ilog("generate genesis plugin: plugin_startup() end");
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void generate_genesis_plugin::block_applied(const graphene::chain::signed_block& b)
|
||||
{
|
||||
if (b.block_num() == _block_to_snapshot)
|
||||
{
|
||||
ilog("generate genesis plugin: snapshot block has arrived");
|
||||
generate_snapshot();
|
||||
}
|
||||
if (b.block_num() == _block_to_snapshot)
|
||||
{
|
||||
ilog("generate genesis plugin: snapshot block has arrived");
|
||||
generate_snapshot();
|
||||
}
|
||||
}
|
||||
|
||||
std::string modify_account_name(const std::string& name)
|
||||
{
|
||||
return std::string("bts-") + name;
|
||||
return std::string("bts-") + name;
|
||||
}
|
||||
|
||||
bool is_special_account(const graphene::chain::account_id_type& account_id)
|
||||
{
|
||||
return account_id.instance < 100;
|
||||
return account_id.instance < 100;
|
||||
}
|
||||
|
||||
bool is_exchange(const std::string& account_name)
|
||||
{
|
||||
return account_name == "poloniexcoldstorage" ||
|
||||
account_name == "btc38-public-for-bts-cold" ||
|
||||
account_name == "poloniexwallet" ||
|
||||
account_name == "btercom" ||
|
||||
account_name == "yunbi-cold-wallet" ||
|
||||
account_name == "btc38-btsx-octo-72722" ||
|
||||
account_name == "bittrex-deposit" ||
|
||||
account_name == "btc38btsxwithdrawal";
|
||||
return account_name == "poloniexcoldstorage" ||
|
||||
account_name == "btc38-public-for-bts-cold" ||
|
||||
account_name == "poloniexwallet" ||
|
||||
account_name == "btercom" ||
|
||||
account_name == "yunbi-cold-wallet" ||
|
||||
account_name == "btc38-btsx-octo-72722" ||
|
||||
account_name == "bittrex-deposit" ||
|
||||
account_name == "btc38btsxwithdrawal";
|
||||
}
|
||||
|
||||
void generate_genesis_plugin::generate_snapshot()
|
||||
{
|
||||
ilog("generate genesis plugin: generating snapshot now");
|
||||
graphene::chain::genesis_state_type new_genesis_state;
|
||||
chain::database& d = database();
|
||||
ilog("generate genesis plugin: generating snapshot now");
|
||||
graphene::chain::genesis_state_type new_genesis_state;
|
||||
chain::database& d = database();
|
||||
|
||||
// we'll distribute 5% of 1,000,000 tokens, so:
|
||||
graphene::chain::share_type total_amount_to_distribute = 50000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
|
||||
// we'll distribute 5% of 1,000,000 tokens, so:
|
||||
graphene::chain::share_type total_amount_to_distribute = 50000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
// we need collection of mutable objects
|
||||
std::vector<my_account_balance_object> db_balances;
|
||||
// copy const objects to our collection
|
||||
auto& balance_index = d.get_index_type<graphene::chain::account_balance_index>().indices().get<graphene::chain::by_asset_balance>();
|
||||
for (auto balance_iter = balance_index.begin(); balance_iter != balance_index.end() && balance_iter->asset_type == graphene::chain::asset_id_type(); ++balance_iter)
|
||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
||||
{
|
||||
// it is possible due to constructor
|
||||
db_balances.emplace_back(*balance_iter);
|
||||
}
|
||||
|
||||
// walk through the balances; this index has the largest BTS balances first
|
||||
// First, calculate the combined value of all BTS
|
||||
auto& balance_index = d.get_index_type<graphene::chain::account_balance_index>().indices().get<graphene::chain::by_asset_balance>();
|
||||
graphene::chain::share_type total_bts_balance;
|
||||
graphene::chain::share_type total_shares_dropped;
|
||||
for (auto balance_iter = balance_index.begin(); balance_iter != balance_index.end() && balance_iter->asset_type == graphene::chain::asset_id_type(); ++balance_iter)
|
||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
||||
total_bts_balance += balance_iter->balance;
|
||||
// walk through the balances; this index has the largest BTS balances first
|
||||
// first, calculate orders and collaterals
|
||||
// second, update balance
|
||||
graphene::chain::share_type orders;
|
||||
graphene::chain::share_type collaterals;
|
||||
graphene::chain::share_type total_bts_balance;
|
||||
std::ofstream logfile;
|
||||
|
||||
// Now, we assume we're distributing balances to all BTS holders proportionally, figure
|
||||
// the smallest balance we can distribute and still assign the user a satoshi of the share drop
|
||||
graphene::chain::share_type effective_total_bts_balance;
|
||||
auto balance_iter = balance_index.begin();
|
||||
for (; balance_iter != balance_index.end() && balance_iter->asset_type == graphene::chain::asset_id_type(); ++balance_iter)
|
||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
||||
{
|
||||
fc::uint128 share_drop_amount = total_amount_to_distribute.value;
|
||||
share_drop_amount *= balance_iter->balance.value;
|
||||
share_drop_amount /= total_bts_balance.value;
|
||||
if (!share_drop_amount.to_uint64())
|
||||
bool sort = false;
|
||||
for (auto balance_iter = db_balances.begin(); balance_iter != db_balances.end(); ++balance_iter)
|
||||
{
|
||||
orders = 0;
|
||||
collaterals = 0;
|
||||
// BTS tied up in market orders
|
||||
auto order_range = d.get_index_type<graphene::chain::limit_order_index>().indices().get<graphene::chain::by_account>().equal_range(balance_iter->owner);
|
||||
std::for_each(order_range.first, order_range.second,
|
||||
[&orders] (const graphene::chain::limit_order_object& order) {
|
||||
if (order.amount_for_sale().asset_id == graphene::chain::asset_id_type())
|
||||
orders += order.amount_for_sale().amount;
|
||||
});
|
||||
// BTS tied up in collateral for SmartCoins
|
||||
auto collateral_range = d.get_index_type<graphene::chain::call_order_index>().indices().get<graphene::chain::by_account>().equal_range(balance_iter->owner);
|
||||
|
||||
std::for_each(collateral_range.first, collateral_range.second,
|
||||
[&collaterals] (const graphene::chain::call_order_object& order) {
|
||||
collaterals += order.collateral;
|
||||
});
|
||||
|
||||
balance_iter->initial_balance = balance_iter->balance;
|
||||
balance_iter->orders = orders;
|
||||
balance_iter->collaterals = collaterals;
|
||||
balance_iter->balance += orders + collaterals;
|
||||
sort = sort || orders.value > 0 || collaterals.value > 0;
|
||||
total_bts_balance += balance_iter->balance;
|
||||
}
|
||||
|
||||
if (sort)
|
||||
{
|
||||
ilog("generate genesis plugin: sorting");
|
||||
std::sort(db_balances.begin(), db_balances.end(),
|
||||
[](const my_account_balance_object & a, const my_account_balance_object & b) -> bool
|
||||
{
|
||||
return a.balance.value > b.balance.value;
|
||||
});
|
||||
}
|
||||
|
||||
graphene::chain::share_type total_shares_dropped;
|
||||
// Now, we assume we're distributing balances to all BTS holders proportionally, figure
|
||||
// the smallest balance we can distribute and still assign the user a satoshi of the share drop
|
||||
graphene::chain::share_type effective_total_bts_balance;
|
||||
auto balance_iter = db_balances.begin();
|
||||
for (balance_iter = db_balances.begin(); balance_iter != db_balances.end(); ++balance_iter)
|
||||
{
|
||||
fc::uint128 share_drop_amount = total_amount_to_distribute.value;
|
||||
share_drop_amount *= balance_iter->balance.value;
|
||||
share_drop_amount /= total_bts_balance.value;
|
||||
if (!share_drop_amount.to_uint64())
|
||||
break; // balances are decreasing, so every balance after will also round to zero
|
||||
total_shares_dropped += share_drop_amount.to_uint64();
|
||||
effective_total_bts_balance += balance_iter->balance;
|
||||
}
|
||||
total_shares_dropped += share_drop_amount.to_uint64();
|
||||
effective_total_bts_balance += balance_iter->balance;
|
||||
}
|
||||
|
||||
// our iterator is just after the smallest balance we will process,
|
||||
// walk it backwards towards the larger balances, distributing the sharedrop as we go
|
||||
graphene::chain::share_type remaining_amount_to_distribute = total_amount_to_distribute;
|
||||
graphene::chain::share_type bts_balance_remaining = effective_total_bts_balance;
|
||||
std::map<graphene::chain::account_id_type, graphene::chain::share_type> sharedrop_balances;
|
||||
// our iterator is just after the smallest balance we will process,
|
||||
// walk it backwards towards the larger balances, distributing the sharedrop as we go
|
||||
graphene::chain::share_type remaining_amount_to_distribute = total_amount_to_distribute;
|
||||
graphene::chain::share_type bts_balance_remaining = effective_total_bts_balance;
|
||||
std::map<graphene::chain::account_id_type, graphene::chain::share_type> sharedrop_balances;
|
||||
|
||||
do {
|
||||
--balance_iter;
|
||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
||||
{
|
||||
fc::uint128 share_drop_amount = remaining_amount_to_distribute.value;
|
||||
share_drop_amount *= balance_iter->balance.value;
|
||||
share_drop_amount /= bts_balance_remaining.value;
|
||||
graphene::chain::share_type amount_distributed = share_drop_amount.to_uint64();
|
||||
sharedrop_balances[balance_iter->owner] = amount_distributed;
|
||||
do {
|
||||
--balance_iter;
|
||||
fc::uint128 share_drop_amount = remaining_amount_to_distribute.value;
|
||||
share_drop_amount *= balance_iter->balance.value;
|
||||
share_drop_amount /= bts_balance_remaining.value;
|
||||
graphene::chain::share_type amount_distributed = share_drop_amount.to_uint64();
|
||||
sharedrop_balances[balance_iter->owner] = amount_distributed;
|
||||
balance_iter->sharedrop = amount_distributed;
|
||||
|
||||
remaining_amount_to_distribute -= amount_distributed;
|
||||
bts_balance_remaining -= balance_iter->balance.value;
|
||||
}
|
||||
} while (balance_iter != balance_index.begin());
|
||||
assert(remaining_amount_to_distribute == 0);
|
||||
remaining_amount_to_distribute -= amount_distributed;
|
||||
bts_balance_remaining -= balance_iter->balance.value;
|
||||
} while (balance_iter != db_balances.begin());
|
||||
assert(remaining_amount_to_distribute == 0);
|
||||
|
||||
auto& account_index = d.get_index_type<graphene::chain::account_index>();
|
||||
auto& account_by_id_index = account_index.indices().get<graphene::chain::by_id>();
|
||||
// inefficient way of crawling the graph, but we only do it once
|
||||
std::set<graphene::chain::account_id_type> already_generated;
|
||||
for (;;)
|
||||
{
|
||||
unsigned accounts_generated_this_round = 0;
|
||||
for (const auto& sharedrop_value : sharedrop_balances)
|
||||
{
|
||||
const graphene::chain::account_id_type& account_id = sharedrop_value.first;
|
||||
const graphene::chain::share_type& sharedrop_amount = sharedrop_value.second;
|
||||
const graphene::chain::account_object& account_obj = account_id(d);
|
||||
if (already_generated.find(account_id) == already_generated.end())
|
||||
{
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority owner;
|
||||
owner.weight_threshold = account_obj.owner.weight_threshold;
|
||||
owner.key_auths = account_obj.owner.key_auths;
|
||||
for (const auto& value : account_obj.owner.account_auths)
|
||||
logfile.open(_csvlog_filename);
|
||||
assert(logfile.is_open());
|
||||
logfile << "name,balance+orders+collaterals,balance,orders,collaterals,sharedrop\n";
|
||||
char del = ',';
|
||||
char nl = '\n';
|
||||
for(const auto& o : db_balances)
|
||||
{
|
||||
logfile << o.owner(d).name << del << o.balance.value << del << o.initial_balance.value << del << o.orders.value << del << o.collaterals.value << del << o.sharedrop.value << nl;
|
||||
}
|
||||
ilog("CSV log written to file ${filename}", ("filename", _csvlog_filename));
|
||||
logfile.close();
|
||||
|
||||
//auto& account_index = d.get_index_type<graphene::chain::account_index>();
|
||||
//auto& account_by_id_index = account_index.indices().get<graphene::chain::by_id>();
|
||||
// inefficient way of crawling the graph, but we only do it once
|
||||
std::set<graphene::chain::account_id_type> already_generated;
|
||||
for (;;)
|
||||
{
|
||||
unsigned accounts_generated_this_round = 0;
|
||||
for (const auto& sharedrop_value : sharedrop_balances)
|
||||
{
|
||||
const graphene::chain::account_id_type& account_id = sharedrop_value.first;
|
||||
const graphene::chain::share_type& sharedrop_amount = sharedrop_value.second;
|
||||
const graphene::chain::account_object& account_obj = account_id(d);
|
||||
if (already_generated.find(account_id) == already_generated.end())
|
||||
{
|
||||
owner.account_auths.insert(std::make_pair(modify_account_name(value.first(d).name), value.second));
|
||||
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
||||
}
|
||||
owner.key_auths = account_obj.owner.key_auths;
|
||||
owner.address_auths = account_obj.owner.address_auths;
|
||||
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority active;
|
||||
active.weight_threshold = account_obj.active.weight_threshold;
|
||||
active.key_auths = account_obj.active.key_auths;
|
||||
for (const auto& value : account_obj.active.account_auths)
|
||||
{
|
||||
active.account_auths.insert(std::make_pair(modify_account_name(value.first(d).name), value.second));
|
||||
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
||||
}
|
||||
active.key_auths = account_obj.active.key_auths;
|
||||
active.address_auths = account_obj.active.address_auths;
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority owner;
|
||||
owner.weight_threshold = account_obj.owner.weight_threshold;
|
||||
owner.key_auths = account_obj.owner.key_auths;
|
||||
for (const auto& value : account_obj.owner.account_auths)
|
||||
{
|
||||
owner.account_auths.insert(std::make_pair(modify_account_name(value.first(d).name), value.second));
|
||||
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
||||
}
|
||||
owner.key_auths = account_obj.owner.key_auths;
|
||||
owner.address_auths = account_obj.owner.address_auths;
|
||||
|
||||
new_genesis_state.initial_bts_accounts.emplace_back(
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type(modify_account_name(account_obj.name),
|
||||
owner, active,
|
||||
sharedrop_amount));
|
||||
already_generated.insert(account_id);
|
||||
++accounts_generated_this_round;
|
||||
}
|
||||
}
|
||||
if (accounts_generated_this_round == 0)
|
||||
break;
|
||||
}
|
||||
fc::json::save_to_file(new_genesis_state, _genesis_filename);
|
||||
ilog("New genesis state written to file ${filename}", ("filename", _genesis_filename));
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority active;
|
||||
active.weight_threshold = account_obj.active.weight_threshold;
|
||||
active.key_auths = account_obj.active.key_auths;
|
||||
for (const auto& value : account_obj.active.account_auths)
|
||||
{
|
||||
active.account_auths.insert(std::make_pair(modify_account_name(value.first(d).name), value.second));
|
||||
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
||||
}
|
||||
active.key_auths = account_obj.active.key_auths;
|
||||
active.address_auths = account_obj.active.address_auths;
|
||||
|
||||
new_genesis_state.initial_bts_accounts.emplace_back(
|
||||
graphene::chain::genesis_state_type::initial_bts_account_type(modify_account_name(account_obj.name),
|
||||
owner, active,
|
||||
sharedrop_amount));
|
||||
already_generated.insert(account_id);
|
||||
++accounts_generated_this_round;
|
||||
}
|
||||
}
|
||||
if (accounts_generated_this_round == 0)
|
||||
break;
|
||||
}
|
||||
fc::json::save_to_file(new_genesis_state, _genesis_filename);
|
||||
ilog("New genesis state written to file ${filename}", ("filename", _genesis_filename));
|
||||
}
|
||||
|
||||
void generate_genesis_plugin::plugin_shutdown()
|
||||
|
|
|
|||
|
|
@ -54,6 +54,19 @@ private:
|
|||
|
||||
uint32_t _block_to_snapshot;
|
||||
std::string _genesis_filename;
|
||||
std::string _csvlog_filename;
|
||||
};
|
||||
|
||||
class my_account_balance_object : public graphene::chain::account_balance_object
|
||||
{
|
||||
public:
|
||||
// constructor copying from base class
|
||||
my_account_balance_object(const graphene::chain::account_balance_object& abo) : graphene::chain::account_balance_object(abo) {}
|
||||
|
||||
graphene::chain::share_type initial_balance;
|
||||
graphene::chain::share_type orders;
|
||||
graphene::chain::share_type collaterals;
|
||||
graphene::chain::share_type sharedrop;
|
||||
};
|
||||
|
||||
} } //graphene::generate_genesis_plugin
|
||||
|
|
|
|||
|
|
@ -1451,6 +1451,20 @@ class wallet_api
|
|||
const variant_object& changed_values,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Propose a dividend asset update.
|
||||
*
|
||||
* @param proposing_account The account paying the fee to propose the tx
|
||||
* @param expiration_time Timestamp specifying when the proposal will either take effect or expire.
|
||||
* @param changed_values dividend asset parameters to update
|
||||
* @param broadcast true if you wish to broadcast the transaction
|
||||
* @return the signed version of the transaction
|
||||
*/
|
||||
signed_transaction propose_dividend_asset_update(
|
||||
const string& proposing_account,
|
||||
fc::time_point_sec expiration_time,
|
||||
const variant_object& changed_values,
|
||||
bool broadcast = false);
|
||||
|
||||
/** Approve or disapprove a proposal.
|
||||
*
|
||||
* @param fee_paying_account The account paying the fee for the op.
|
||||
|
|
@ -1682,6 +1696,7 @@ FC_API( graphene::wallet::wallet_api,
|
|||
(get_prototype_operation)
|
||||
(propose_parameter_change)
|
||||
(propose_fee_change)
|
||||
(propose_dividend_asset_update)
|
||||
(approve_proposal)
|
||||
(dbg_make_uia)
|
||||
(dbg_make_mia)
|
||||
|
|
|
|||
|
|
@ -2804,6 +2804,46 @@ public:
|
|||
return sign_transaction(tx, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction propose_dividend_asset_update(
|
||||
const string& proposing_account,
|
||||
fc::time_point_sec expiration_time,
|
||||
const variant_object& changed_values,
|
||||
bool broadcast = false)
|
||||
{
|
||||
FC_ASSERT( changed_values.contains("asset_to_update") );
|
||||
|
||||
const chain_parameters& current_params = get_global_properties().parameters;
|
||||
asset_update_dividend_operation changed_op;
|
||||
fc::reflector<asset_update_dividend_operation>::visit(
|
||||
fc::from_variant_visitor<asset_update_dividend_operation>( changed_values, changed_op )
|
||||
);
|
||||
|
||||
optional<asset_object> asset_to_update = find_asset(changed_op.asset_to_update);
|
||||
if (!asset_to_update)
|
||||
FC_THROW("No asset with that symbol exists!");
|
||||
|
||||
asset_update_dividend_operation update_op;
|
||||
update_op.issuer = asset_to_update->issuer;
|
||||
update_op.asset_to_update = asset_to_update->id;
|
||||
update_op.new_options = changed_op.new_options;
|
||||
|
||||
proposal_create_operation prop_op;
|
||||
|
||||
prop_op.expiration_time = expiration_time;
|
||||
prop_op.review_period_seconds = current_params.committee_proposal_review_period;
|
||||
prop_op.fee_paying_account = get_account(proposing_account).id;
|
||||
|
||||
prop_op.proposed_ops.emplace_back( update_op );
|
||||
current_params.current_fees->set_fee( prop_op.proposed_ops.back().op );
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back(prop_op);
|
||||
set_operation_fees(tx, current_params.current_fees);
|
||||
tx.validate();
|
||||
|
||||
return sign_transaction(tx, broadcast);
|
||||
}
|
||||
|
||||
signed_transaction approve_proposal(
|
||||
const string& fee_paying_account,
|
||||
const string& proposal_id,
|
||||
|
|
@ -3877,6 +3917,16 @@ signed_transaction wallet_api::propose_fee_change(
|
|||
return my->propose_fee_change( proposing_account, expiration_time, changed_fees, broadcast );
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::propose_dividend_asset_update(
|
||||
const string& proposing_account,
|
||||
fc::time_point_sec expiration_time,
|
||||
const variant_object& changed_fees,
|
||||
bool broadcast /* = false */
|
||||
)
|
||||
{
|
||||
return my->propose_dividend_asset_update( proposing_account, expiration_time, changed_fees, broadcast );
|
||||
}
|
||||
|
||||
signed_transaction wallet_api::approve_proposal(
|
||||
const string& fee_paying_account,
|
||||
const string& proposal_id,
|
||||
|
|
@ -3887,6 +3937,9 @@ signed_transaction wallet_api::approve_proposal(
|
|||
return my->approve_proposal( fee_paying_account, proposal_id, delta, broadcast );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
global_property_object wallet_api::get_global_properties() const
|
||||
{
|
||||
return my->get_global_properties();
|
||||
|
|
|
|||
Loading…
Reference in a new issue