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_base_fee": 0,
|
||||||
"distribution_fee_per_holder": 0
|
"distribution_fee_per_holder": 0
|
||||||
}
|
}
|
||||||
|
],[
|
||||||
|
47,{
|
||||||
|
"fee": 100000
|
||||||
|
}
|
||||||
|
],[
|
||||||
|
48,{
|
||||||
|
"fee": 51000000
|
||||||
|
}
|
||||||
|
],[
|
||||||
|
49,{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"scale": 10
|
"scale": 10
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,16 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
a.network_fee_percentage = 0;
|
a.network_fee_percentage = 0;
|
||||||
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
|
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
|
||||||
}).get_id() == GRAPHENE_PROXY_TO_SELF_ACCOUNT);
|
}).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
|
// Create more special accounts
|
||||||
while( true )
|
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) {
|
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
|
||||||
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
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 =
|
const asset_object& core_asset =
|
||||||
create<asset_object>( [&]( asset_object& a ) {
|
create<asset_object>( [&]( asset_object& a ) {
|
||||||
a.symbol = GRAPHENE_SYMBOL;
|
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.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
|
||||||
a.options.flags = 0;
|
a.options.flags = 0;
|
||||||
a.options.issuer_permissions = 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.amount = 1;
|
||||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
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.amount = 1;
|
||||||
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
|
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
|
||||||
a.dynamic_asset_data_id = dyn_asset.id;
|
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( asset_id_type(core_asset.id) == asset().asset_id );
|
||||||
assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
|
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
|
// Create more special assets
|
||||||
while( true )
|
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;
|
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>();
|
const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>();
|
||||||
auto it = idx.begin();
|
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"
|
elog( "Genesis for asset ${aname} is not balanced\n"
|
||||||
" Debt is ${debt}\n"
|
" Debt is ${debt}\n"
|
||||||
" Supply is ${supply}\n",
|
" Supply is ${supply}\n",
|
||||||
|
("aname", debt_itr->first)
|
||||||
("debt", debt_itr->second)
|
("debt", debt_itr->second)
|
||||||
("supply", supply_itr->second)
|
("supply", supply_itr->second)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,8 @@ FC_REFLECT_DERIVED( graphene::chain::asset_dividend_data_object, (graphene::db::
|
||||||
(options)
|
(options)
|
||||||
(last_scheduled_payout_time)
|
(last_scheduled_payout_time)
|
||||||
(last_payout_time )
|
(last_payout_time )
|
||||||
|
(last_scheduled_distribution_time)
|
||||||
|
(last_distribution_time)
|
||||||
(dividend_distribution_account)
|
(dividend_distribution_account)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -369,4 +371,5 @@ FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
|
||||||
(dynamic_asset_data_id)
|
(dynamic_asset_data_id)
|
||||||
(bitasset_data_id)
|
(bitasset_data_id)
|
||||||
(buyback_account)
|
(buyback_account)
|
||||||
|
(dividend_data_id)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,8 @@
|
||||||
#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4))
|
#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)
|
/// 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 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.
|
/// Sentinel value used in the scheduler.
|
||||||
#define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0))
|
#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,
|
FC_REFLECT( graphene::chain::dividend_asset_options,
|
||||||
(next_payout_time)
|
(next_payout_time)
|
||||||
(payout_interval)
|
(payout_interval)
|
||||||
|
(minimum_fee_percentage)
|
||||||
|
(minimum_distribution_interval)
|
||||||
(extensions)
|
(extensions)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -268,13 +268,12 @@ namespace graphene { namespace chain {
|
||||||
assert(event.match.match_winners.size() == 1);
|
assert(event.match.match_winners.size() == 1);
|
||||||
const account_id_type& winner = *event.match.match_winners.begin();
|
const account_id_type& winner = *event.match.match_winners.begin();
|
||||||
uint16_t rake_fee_percentage = event.db.get_global_properties().parameters.rake_fee_percentage;
|
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),
|
event.db.adjust_balance(account_id_type(TOURNAMENT_RAKE_FEE_ACCOUNT_ID),
|
||||||
asset(rake_amount, fsm.tournament_obj->options.buy_in.asset_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,
|
event.db.adjust_balance(winner, asset(fsm.tournament_obj->prize_pool - rake_amount,
|
||||||
fsm.tournament_obj->options.buy_in.asset_id));
|
fsm.tournament_obj->options.buy_in.asset_id));
|
||||||
tournament_object& tournament = *fsm.tournament_obj;
|
fsm.tournament_obj->end_time = event.db.head_block_time();
|
||||||
tournament.end_time = event.db.head_block_time();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,10 @@
|
||||||
#include <fc/smart_ref_impl.hpp>
|
#include <fc/smart_ref_impl.hpp>
|
||||||
#include <fc/thread/thread.hpp>
|
#include <fc/thread/thread.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/market_object.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
using namespace graphene::generate_genesis_plugin;
|
using namespace graphene::generate_genesis_plugin;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
@ -41,187 +44,246 @@ using std::vector;
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
|
||||||
void generate_genesis_plugin::plugin_set_program_options(
|
void generate_genesis_plugin::plugin_set_program_options(
|
||||||
boost::program_options::options_description& command_line_options,
|
boost::program_options::options_description& command_line_options,
|
||||||
boost::program_options::options_description& config_file_options)
|
boost::program_options::options_description& config_file_options)
|
||||||
{
|
{
|
||||||
command_line_options.add_options()
|
command_line_options.add_options()
|
||||||
("output-genesis-file,o", bpo::value<std::string>()->default_value("genesis.json"), "Genesis file to create")
|
("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")
|
("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);
|
;
|
||||||
|
config_file_options.add(command_line_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string generate_genesis_plugin::plugin_name()const
|
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)
|
void generate_genesis_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||||
{ try {
|
{ try {
|
||||||
ilog("generate genesis plugin: plugin_initialize() begin");
|
ilog("generate genesis plugin: plugin_initialize() begin");
|
||||||
_options = &options;
|
_options = &options;
|
||||||
|
|
||||||
_genesis_filename = options["output-genesis-file"].as<std::string>();
|
_genesis_filename = options["output-genesis-file"].as<std::string>();
|
||||||
_block_to_snapshot = options["snapshot-block-number"].as<uint32_t>();
|
_csvlog_filename = options["output-csvlog-file"].as<std::string>();
|
||||||
database().applied_block.connect([this](const graphene::chain::signed_block& b){ block_applied(b); });
|
_block_to_snapshot = options["snapshot-block-number"].as<uint32_t>();
|
||||||
ilog("generate genesis plugin: plugin_initialize() end");
|
database().applied_block.connect([this](const graphene::chain::signed_block& b){ block_applied(b); });
|
||||||
} FC_LOG_AND_RETHROW() }
|
ilog("generate genesis plugin: plugin_initialize() end");
|
||||||
|
} FC_LOG_AND_RETHROW() }
|
||||||
|
|
||||||
void generate_genesis_plugin::plugin_startup()
|
void generate_genesis_plugin::plugin_startup()
|
||||||
{ try {
|
{ try {
|
||||||
ilog("generate genesis plugin: plugin_startup() begin");
|
ilog("generate genesis plugin: plugin_startup() begin");
|
||||||
chain::database& d = database();
|
chain::database& d = database();
|
||||||
if (d.head_block_num() == _block_to_snapshot)
|
if (d.head_block_num() == _block_to_snapshot)
|
||||||
{
|
{
|
||||||
ilog("generate genesis plugin: already at snapshot block");
|
ilog("generate genesis plugin: already at snapshot block");
|
||||||
generate_snapshot();
|
generate_snapshot();
|
||||||
}
|
}
|
||||||
else if (d.head_block_num() > _block_to_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");
|
elog("generate genesis plugin: already passed snapshot block, you must reindex to return to the snapshot state");
|
||||||
else
|
else
|
||||||
elog("generate genesis plugin: waiting for block ${snapshot_block} to generate snapshot, current head is ${head}",
|
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()));
|
("snapshot_block", _block_to_snapshot)("head", d.head_block_num()));
|
||||||
|
|
||||||
ilog("generate genesis plugin: plugin_startup() end");
|
ilog("generate genesis plugin: plugin_startup() end");
|
||||||
} FC_CAPTURE_AND_RETHROW() }
|
} FC_CAPTURE_AND_RETHROW() }
|
||||||
|
|
||||||
void generate_genesis_plugin::block_applied(const graphene::chain::signed_block& b)
|
void generate_genesis_plugin::block_applied(const graphene::chain::signed_block& b)
|
||||||
{
|
{
|
||||||
if (b.block_num() == _block_to_snapshot)
|
if (b.block_num() == _block_to_snapshot)
|
||||||
{
|
{
|
||||||
ilog("generate genesis plugin: snapshot block has arrived");
|
ilog("generate genesis plugin: snapshot block has arrived");
|
||||||
generate_snapshot();
|
generate_snapshot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string modify_account_name(const std::string& name)
|
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)
|
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)
|
bool is_exchange(const std::string& account_name)
|
||||||
{
|
{
|
||||||
return account_name == "poloniexcoldstorage" ||
|
return account_name == "poloniexcoldstorage" ||
|
||||||
account_name == "btc38-public-for-bts-cold" ||
|
account_name == "btc38-public-for-bts-cold" ||
|
||||||
account_name == "poloniexwallet" ||
|
account_name == "poloniexwallet" ||
|
||||||
account_name == "btercom" ||
|
account_name == "btercom" ||
|
||||||
account_name == "yunbi-cold-wallet" ||
|
account_name == "yunbi-cold-wallet" ||
|
||||||
account_name == "btc38-btsx-octo-72722" ||
|
account_name == "btc38-btsx-octo-72722" ||
|
||||||
account_name == "bittrex-deposit" ||
|
account_name == "bittrex-deposit" ||
|
||||||
account_name == "btc38btsxwithdrawal";
|
account_name == "btc38btsxwithdrawal";
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_genesis_plugin::generate_snapshot()
|
void generate_genesis_plugin::generate_snapshot()
|
||||||
{
|
{
|
||||||
ilog("generate genesis plugin: generating snapshot now");
|
ilog("generate genesis plugin: generating snapshot now");
|
||||||
graphene::chain::genesis_state_type new_genesis_state;
|
graphene::chain::genesis_state_type new_genesis_state;
|
||||||
chain::database& d = database();
|
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:
|
// we need collection of mutable objects
|
||||||
graphene::chain::share_type total_amount_to_distribute = 50000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
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
|
// walk through the balances; this index has the largest BTS balances first
|
||||||
// First, calculate the combined value of all BTS
|
// first, calculate orders and collaterals
|
||||||
auto& balance_index = d.get_index_type<graphene::chain::account_balance_index>().indices().get<graphene::chain::by_asset_balance>();
|
// second, update balance
|
||||||
graphene::chain::share_type total_bts_balance;
|
graphene::chain::share_type orders;
|
||||||
graphene::chain::share_type total_shares_dropped;
|
graphene::chain::share_type collaterals;
|
||||||
for (auto balance_iter = balance_index.begin(); balance_iter != balance_index.end() && balance_iter->asset_type == graphene::chain::asset_id_type(); ++balance_iter)
|
graphene::chain::share_type total_bts_balance;
|
||||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
std::ofstream logfile;
|
||||||
total_bts_balance += balance_iter->balance;
|
|
||||||
|
|
||||||
// Now, we assume we're distributing balances to all BTS holders proportionally, figure
|
bool sort = false;
|
||||||
// the smallest balance we can distribute and still assign the user a satoshi of the share drop
|
for (auto balance_iter = db_balances.begin(); balance_iter != db_balances.end(); ++balance_iter)
|
||||||
graphene::chain::share_type effective_total_bts_balance;
|
{
|
||||||
auto balance_iter = balance_index.begin();
|
orders = 0;
|
||||||
for (; balance_iter != balance_index.end() && balance_iter->asset_type == graphene::chain::asset_id_type(); ++balance_iter)
|
collaterals = 0;
|
||||||
if (!is_special_account(balance_iter->owner) && !is_exchange(balance_iter->owner(d).name))
|
// 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);
|
||||||
fc::uint128 share_drop_amount = total_amount_to_distribute.value;
|
std::for_each(order_range.first, order_range.second,
|
||||||
share_drop_amount *= balance_iter->balance.value;
|
[&orders] (const graphene::chain::limit_order_object& order) {
|
||||||
share_drop_amount /= total_bts_balance.value;
|
if (order.amount_for_sale().asset_id == graphene::chain::asset_id_type())
|
||||||
if (!share_drop_amount.to_uint64())
|
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
|
break; // balances are decreasing, so every balance after will also round to zero
|
||||||
total_shares_dropped += share_drop_amount.to_uint64();
|
total_shares_dropped += share_drop_amount.to_uint64();
|
||||||
effective_total_bts_balance += balance_iter->balance;
|
effective_total_bts_balance += balance_iter->balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// our iterator is just after the smallest balance we will process,
|
// our iterator is just after the smallest balance we will process,
|
||||||
// walk it backwards towards the larger balances, distributing the sharedrop as we go
|
// 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 remaining_amount_to_distribute = total_amount_to_distribute;
|
||||||
graphene::chain::share_type bts_balance_remaining = effective_total_bts_balance;
|
graphene::chain::share_type bts_balance_remaining = effective_total_bts_balance;
|
||||||
std::map<graphene::chain::account_id_type, graphene::chain::share_type> sharedrop_balances;
|
std::map<graphene::chain::account_id_type, graphene::chain::share_type> sharedrop_balances;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
--balance_iter;
|
--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;
|
||||||
fc::uint128 share_drop_amount = remaining_amount_to_distribute.value;
|
share_drop_amount /= bts_balance_remaining.value;
|
||||||
share_drop_amount *= balance_iter->balance.value;
|
graphene::chain::share_type amount_distributed = share_drop_amount.to_uint64();
|
||||||
share_drop_amount /= bts_balance_remaining.value;
|
sharedrop_balances[balance_iter->owner] = amount_distributed;
|
||||||
graphene::chain::share_type amount_distributed = share_drop_amount.to_uint64();
|
balance_iter->sharedrop = amount_distributed;
|
||||||
sharedrop_balances[balance_iter->owner] = amount_distributed;
|
|
||||||
|
|
||||||
remaining_amount_to_distribute -= amount_distributed;
|
remaining_amount_to_distribute -= amount_distributed;
|
||||||
bts_balance_remaining -= balance_iter->balance.value;
|
bts_balance_remaining -= balance_iter->balance.value;
|
||||||
}
|
} while (balance_iter != db_balances.begin());
|
||||||
} while (balance_iter != balance_index.begin());
|
assert(remaining_amount_to_distribute == 0);
|
||||||
assert(remaining_amount_to_distribute == 0);
|
|
||||||
|
|
||||||
auto& account_index = d.get_index_type<graphene::chain::account_index>();
|
logfile.open(_csvlog_filename);
|
||||||
auto& account_by_id_index = account_index.indices().get<graphene::chain::by_id>();
|
assert(logfile.is_open());
|
||||||
// inefficient way of crawling the graph, but we only do it once
|
logfile << "name,balance+orders+collaterals,balance,orders,collaterals,sharedrop\n";
|
||||||
std::set<graphene::chain::account_id_type> already_generated;
|
char del = ',';
|
||||||
for (;;)
|
char nl = '\n';
|
||||||
{
|
for(const auto& o : db_balances)
|
||||||
unsigned accounts_generated_this_round = 0;
|
{
|
||||||
for (const auto& sharedrop_value : sharedrop_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;
|
||||||
{
|
}
|
||||||
const graphene::chain::account_id_type& account_id = sharedrop_value.first;
|
ilog("CSV log written to file ${filename}", ("filename", _csvlog_filename));
|
||||||
const graphene::chain::share_type& sharedrop_amount = sharedrop_value.second;
|
logfile.close();
|
||||||
const graphene::chain::account_object& account_obj = account_id(d);
|
|
||||||
if (already_generated.find(account_id) == already_generated.end())
|
//auto& account_index = d.get_index_type<graphene::chain::account_index>();
|
||||||
{
|
//auto& account_by_id_index = account_index.indices().get<graphene::chain::by_id>();
|
||||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority owner;
|
// inefficient way of crawling the graph, but we only do it once
|
||||||
owner.weight_threshold = account_obj.owner.weight_threshold;
|
std::set<graphene::chain::account_id_type> already_generated;
|
||||||
owner.key_auths = account_obj.owner.key_auths;
|
for (;;)
|
||||||
for (const auto& value : account_obj.owner.account_auths)
|
{
|
||||||
|
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));
|
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority owner;
|
||||||
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
owner.weight_threshold = account_obj.owner.weight_threshold;
|
||||||
}
|
owner.key_auths = account_obj.owner.key_auths;
|
||||||
owner.key_auths = account_obj.owner.key_auths;
|
for (const auto& value : account_obj.owner.account_auths)
|
||||||
owner.address_auths = account_obj.owner.address_auths;
|
{
|
||||||
|
owner.account_auths.insert(std::make_pair(modify_account_name(value.first(d).name), value.second));
|
||||||
graphene::chain::genesis_state_type::initial_bts_account_type::initial_authority active;
|
sharedrop_balances[value.first] += 0; // make sure the account is generated, even if it has a zero balance
|
||||||
active.weight_threshold = account_obj.active.weight_threshold;
|
}
|
||||||
active.key_auths = account_obj.active.key_auths;
|
owner.key_auths = account_obj.owner.key_auths;
|
||||||
for (const auto& value : account_obj.active.account_auths)
|
owner.address_auths = account_obj.owner.address_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::initial_authority active;
|
||||||
graphene::chain::genesis_state_type::initial_bts_account_type(modify_account_name(account_obj.name),
|
active.weight_threshold = account_obj.active.weight_threshold;
|
||||||
owner, active,
|
active.key_auths = account_obj.active.key_auths;
|
||||||
sharedrop_amount));
|
for (const auto& value : account_obj.active.account_auths)
|
||||||
already_generated.insert(account_id);
|
{
|
||||||
++accounts_generated_this_round;
|
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
|
||||||
}
|
}
|
||||||
if (accounts_generated_this_round == 0)
|
active.key_auths = account_obj.active.key_auths;
|
||||||
break;
|
active.address_auths = account_obj.active.address_auths;
|
||||||
}
|
|
||||||
fc::json::save_to_file(new_genesis_state, _genesis_filename);
|
new_genesis_state.initial_bts_accounts.emplace_back(
|
||||||
ilog("New genesis state written to file ${filename}", ("filename", _genesis_filename));
|
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()
|
void generate_genesis_plugin::plugin_shutdown()
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,19 @@ private:
|
||||||
|
|
||||||
uint32_t _block_to_snapshot;
|
uint32_t _block_to_snapshot;
|
||||||
std::string _genesis_filename;
|
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
|
} } //graphene::generate_genesis_plugin
|
||||||
|
|
|
||||||
|
|
@ -1451,6 +1451,20 @@ class wallet_api
|
||||||
const variant_object& changed_values,
|
const variant_object& changed_values,
|
||||||
bool broadcast = false);
|
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.
|
/** Approve or disapprove a proposal.
|
||||||
*
|
*
|
||||||
* @param fee_paying_account The account paying the fee for the op.
|
* @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)
|
(get_prototype_operation)
|
||||||
(propose_parameter_change)
|
(propose_parameter_change)
|
||||||
(propose_fee_change)
|
(propose_fee_change)
|
||||||
|
(propose_dividend_asset_update)
|
||||||
(approve_proposal)
|
(approve_proposal)
|
||||||
(dbg_make_uia)
|
(dbg_make_uia)
|
||||||
(dbg_make_mia)
|
(dbg_make_mia)
|
||||||
|
|
|
||||||
|
|
@ -2804,6 +2804,46 @@ public:
|
||||||
return sign_transaction(tx, broadcast);
|
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(
|
signed_transaction approve_proposal(
|
||||||
const string& fee_paying_account,
|
const string& fee_paying_account,
|
||||||
const string& proposal_id,
|
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 );
|
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(
|
signed_transaction wallet_api::approve_proposal(
|
||||||
const string& fee_paying_account,
|
const string& fee_paying_account,
|
||||||
const string& proposal_id,
|
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 );
|
return my->approve_proposal( fee_paying_account, proposal_id, delta, broadcast );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
global_property_object wallet_api::get_global_properties() const
|
global_property_object wallet_api::get_global_properties() const
|
||||||
{
|
{
|
||||||
return my->get_global_properties();
|
return my->get_global_properties();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue