Progress #17: Add assets, initial witness count to genesis state

This commit is contained in:
Nathan Hourt 2015-07-01 17:18:49 -04:00
parent ae80339362
commit 66c9606652
9 changed files with 177 additions and 147 deletions

View file

@ -165,8 +165,8 @@ namespace detail {
nathan_key.get_public_key(),
nathan_key.get_public_key(),
true);
initial_state.initial_committee.push_back({name});
initial_state.initial_witnesses.push_back({name, nathan_key.get_public_key(), secret});
initial_state.initial_committee_candidates.push_back({name});
initial_state.initial_witness_candidates.push_back({name, nathan_key.get_public_key(), secret});
}
initial_state.initial_accounts.emplace_back("nathan", nathan_key.get_public_key());

View file

@ -96,7 +96,7 @@ void account_statistics_object::process_fees(const account_object& a, database&
share_type lifetime_cut = cut_fee(core_fee_total, account.lifetime_referrer_fee_percentage);
share_type referral = core_fee_total - network_cut - lifetime_cut;
d.modify(dynamic_asset_data_id_type()(d), [network_cut](asset_dynamic_data_object& d) {
d.modify(asset_dynamic_data_id_type()(d), [network_cut](asset_dynamic_data_object& d) {
d.accumulated_fees += network_cut;
});

View file

@ -53,9 +53,10 @@
#include <graphene/chain/balance_evaluator.hpp>
#include <fc/uint128.hpp>
#include <fc/crypto/digest.hpp>
#include <boost/algorithm/string.hpp>
namespace graphene { namespace chain {
void database::initialize_evaluators()
@ -146,7 +147,7 @@ void database::initialize_indexes()
void database::init_genesis(const genesis_state_type& genesis_state)
{ try {
FC_ASSERT(genesis_state.initial_witnesses.size() > 0,
FC_ASSERT(genesis_state.initial_witness_candidates.size() > 0,
"Cannot start a chain with zero witnesses.");
_undo_db.disable();
@ -259,40 +260,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
});
create<block_summary_object>([&](block_summary_object&) {});
// Create initial balances
const auto& asset_idx = get_index_type<asset_index>().indices().get<by_symbol>();
share_type total_allocation = 0;
if( !genesis_state.initial_balances.empty() )
{
for( const auto& handout : genesis_state.initial_balances )
{
create<balance_object>([&handout,&asset_idx,total_allocation](balance_object& b) {
b.balance = asset(handout.amount, asset_idx.find(handout.asset_symbol)->get_id());
b.owner = handout.owner;
});
total_allocation += handout.amount;
}
}
// Create initial vesting balances
if( !genesis_state.initial_vesting_balances.empty() )
{
for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances )
{
create<balance_object>([&](balance_object& b) {
b.balance = asset(vest.amount, asset_idx.find(vest.asset_symbol)->get_id());
b.owner = vest.owner;
linear_vesting_policy policy;
policy.earliest_withdraw_time = vest.earliest_withdrawal_date;
policy.begin_date = vest.vesting_start_date;
policy.vesting_seconds = (vest.vesting_end_date - vest.vesting_start_date).to_seconds();
policy.begin_balance = b.balance.amount;
b.vesting_policy = policy;
});
total_allocation += vest.amount;
}
}
// Create initial accounts
if( !genesis_state.initial_accounts.empty() )
{
@ -300,17 +267,17 @@ void database::init_genesis(const genesis_state_type& genesis_state)
{
key_id_type key_id = apply_operation(genesis_eval_state,
key_create_operation({asset(),
committee_account.id,
GRAPHENE_TEMP_ACCOUNT,
account.owner_key})).get<object_id_type>();
account_create_operation cop;
cop.name = account.name;
cop.registrar = account_id_type(1);
cop.registrar = GRAPHENE_TEMP_ACCOUNT;
cop.owner = authority(1, key_id, 1);
if( account.owner_key != account.active_key )
{
key_id = apply_operation(genesis_eval_state,
key_create_operation({asset(),
committee_account.id,
GRAPHENE_TEMP_ACCOUNT,
account.owner_key})).get<object_id_type>();
cop.active = authority(1, key_id, 1);
} else {
@ -328,6 +295,126 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}
}
}
const auto& accounts_by_name = get_index_type<account_index>().indices().get<by_name>();
auto get_account_id = [&accounts_by_name](const string& name) {
auto itr = accounts_by_name.find(name);
FC_ASSERT(itr != accounts_by_name.end());
return itr->get_id();
};
// Create initial assets
const auto& assets_by_symbol = get_index_type<asset_index>().indices().get<by_symbol>();
auto get_asset_id = [&assets_by_symbol](const string& symbol) {
auto itr = assets_by_symbol.find(symbol);
FC_ASSERT(itr != assets_by_symbol.end());
return itr->get_id();
};
if( !genesis_state.initial_assets.empty() )
{
for( const genesis_state_type::initial_asset_type& asset : genesis_state.initial_assets )
{
asset_dynamic_data_id_type dynamic_data_id;
optional<asset_bitasset_data_id_type> bitasset_data_id;
if( asset.bitasset_options.valid() )
{
share_type total_allocated;
asset_id_type new_asset_id = get_index_type<asset_index>().get_next_id();
asset_id_type collateral_asset_id = get_asset_id(asset.bitasset_options->backing_asset_symbol);
int collateral_holder_number = 0;
for( const auto& collateral_rec : asset.bitasset_options->collateral_records )
{
key_id_type key_id = apply_operation(genesis_eval_state,
key_create_operation{{},
GRAPHENE_TEMP_ACCOUNT,
collateral_rec.owner}).get<object_id_type>();
account_create_operation cop;
cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number);
boost::algorithm::to_lower(cop.name);
cop.registrar = GRAPHENE_TEMP_ACCOUNT;
cop.owner = authority(1, key_id, 1);
cop.active = cop.owner;
account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>();
create<call_order_object>([&](call_order_object& c) {
c.borrower = owner_account_id;
c.collateral = collateral_rec.collateral;
c.debt = collateral_rec.debt;
c.call_price = price::call_price(chain::asset(c.debt, new_asset_id),
chain::asset(c.collateral, collateral_asset_id),
asset.bitasset_options->maintenance_collateral_ratio);
});
total_allocated += collateral_rec.debt;
}
bitasset_data_id = create<asset_bitasset_data_object>([&](asset_bitasset_data_object& b) {
b.options.feed_lifetime_sec = asset.bitasset_options->feed_lifetime_sec;
b.options.minimum_feeds = asset.bitasset_options->minimum_feeds;
b.options.force_settlement_delay_sec = asset.bitasset_options->force_settlement_delay_sec;
b.options.force_settlement_offset_percent = asset.bitasset_options->force_settlement_offset_percent;
b.options.maximum_force_settlement_volume = asset.bitasset_options->maximum_force_settlement_volume;
b.options.short_backing_asset = get_asset_id(asset.bitasset_options->backing_asset_symbol);
}).id;
dynamic_data_id = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& d) {
d.current_supply = total_allocated;
d.accumulated_fees = asset.initial_accumulated_fees;
}).id;
} else
dynamic_data_id = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& d) {
d.accumulated_fees = asset.initial_accumulated_fees;
}).id;
create<asset_object>([&](asset_object& a) {
a.symbol = asset.symbol;
a.options.description = asset.description;
a.precision = asset.precision;
a.issuer = get_account_id(asset.issuer_name);
a.options.max_supply = asset.max_supply;
a.options.market_fee_percent = asset.market_fee_percent;
a.options.max_market_fee = asset.max_market_fee;
a.options.issuer_permissions = asset.issuer_permissions;
a.options.flags = asset.flags;
a.dynamic_asset_data_id = dynamic_data_id;
a.bitasset_data_id = bitasset_data_id;
});
}
}
// Create initial balances
share_type total_allocation;
if( !genesis_state.initial_balances.empty() )
{
for( const auto& handout : genesis_state.initial_balances )
{
create<balance_object>([&handout,&assets_by_symbol,total_allocation](balance_object& b) {
b.balance = asset(handout.amount, assets_by_symbol.find(handout.asset_symbol)->get_id());
b.owner = handout.owner;
});
total_allocation += handout.amount;
}
}
// Create initial vesting balances
if( !genesis_state.initial_vesting_balances.empty() )
{
for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances )
{
create<balance_object>([&](balance_object& b) {
b.balance = asset(vest.amount, assets_by_symbol.find(vest.asset_symbol)->get_id());
b.owner = vest.owner;
linear_vesting_policy policy;
policy.earliest_withdraw_time = vest.earliest_withdrawal_date;
policy.begin_date = vest.vesting_start_date;
policy.vesting_seconds = (vest.vesting_end_date - vest.vesting_start_date).to_seconds();
policy.begin_balance = b.balance.amount;
b.vesting_policy = policy;
});
total_allocation += vest.amount;
}
}
// Set current supply based on allocations, if they happened
if( total_allocation > 0 )
@ -338,39 +425,36 @@ void database::init_genesis(const genesis_state_type& genesis_state)
adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{}));
}
flat_set<delegate_id_type> init_delegates;
flat_set<witness_id_type> init_witnesses;
const auto& accounts_by_name = get_index_type<account_index>().indices().get<by_name>();
// Create initial witnesses and delegates
std::for_each(genesis_state.initial_witnesses.begin(), genesis_state.initial_witnesses.end(),
std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(),
[&](const genesis_state_type::initial_witness_type& witness) {
const account_object& witness_account = *accounts_by_name.find(witness.owner_name);
const key_object& signing_key = create<key_object>([&witness](key_object& k) { k.key_data = witness.block_signing_key; });
const key_object& signing_key = create<key_object>([&witness](key_object& k) {
k.key_data = witness.block_signing_key;
});
witness_create_operation op;
op.block_signing_key = signing_key.get_id();
op.initial_secret = witness.initial_secret;
op.witness_account = witness_account.get_id();
witness_id_type id = apply_operation(genesis_eval_state, op).get<object_id_type>();
init_witnesses.emplace(id);
op.witness_account = get_account_id(witness.owner_name);
apply_operation(genesis_eval_state, op).get<object_id_type>();
});
std::for_each(genesis_state.initial_committee.begin(), genesis_state.initial_committee.end(),
std::for_each(genesis_state.initial_committee_candidates.begin(), genesis_state.initial_committee_candidates.end(),
[&](const genesis_state_type::initial_committee_member_type& member) {
const account_object& member_account = *accounts_by_name.find(member.owner_name);
delegate_create_operation op;
op.delegate_account = member_account.get_id();
delegate_id_type id = apply_operation(genesis_eval_state, op).get<object_id_type>();
init_delegates.emplace(id);
op.delegate_account = get_account_id(member.owner_name);
apply_operation(genesis_eval_state, op).get<object_id_type>();
});
// Set initial witnesses and committee as active
// Set active witnesses
modify(get_global_properties(), [&](global_property_object& p) {
p.active_delegates = vector<delegate_id_type>(init_delegates.begin(), init_delegates.end());
p.active_witnesses = init_witnesses;
std::transform(p.active_witnesses.begin(), p.active_witnesses.end(),
std::inserter(p.witness_accounts, p.witness_accounts.begin()),
[&](witness_id_type id) { return get(id).witness_account; });
auto idx = get_index_type<witness_index>().indices();
for( auto itr = idx.begin();
itr != idx.end() && p.active_witnesses.size() < genesis_state.initial_active_witnesses;
++itr )
{
p.active_witnesses.insert(itr->id);
p.witness_accounts.insert(itr->witness_account);
}
});
// Initialize witness schedule
@ -383,6 +467,8 @@ void database::init_genesis(const genesis_state_type& genesis_state)
witness_scheduler_rng rng(_wso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV);
auto init_witnesses = get_global_properties().active_witnesses;
_wso.scheduler = witness_scheduler();
_wso.scheduler._min_token_count = init_witnesses.size() / 2;
_wso.scheduler.update(init_witnesses);
@ -391,7 +477,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
_wso.scheduler.produce_schedule(rng);
_wso.last_scheduling_block = 0;
}) ;
});
assert( wso.id == witness_schedule_id_type() );
// Enable fees

View file

@ -118,7 +118,7 @@ void database::update_witness_schedule(signed_block next_block)
_wso.slots_since_genesis += schedule_slot;
witness_scheduler_rng rng(wso.rng_seed.data, _wso.slots_since_genesis);
_wso.scheduler._min_token_count = gpo.active_witnesses.size() / 2;
_wso.scheduler._min_token_count = std::max(int(gpo.active_witnesses.size()) / 2, 1);
uint32_t drain = schedule_slot;
while( drain > 0 )
{

View file

@ -110,11 +110,11 @@ namespace graphene { namespace chain {
{ FC_ASSERT(amount.asset_id == id); return amount_to_pretty_string(amount.amount); }
/// Ticker symbol for this asset, i.e. "USD"
string symbol;
string symbol;
/// Maximum number of digits after the decimal point (must be <= 12)
uint8_t precision;
uint8_t precision;
/// ID of the account which issued this asset.
account_id_type issuer;
account_id_type issuer;
/**
* @brief The asset_options struct contains options available on all assets in the network
@ -124,17 +124,18 @@ namespace graphene { namespace chain {
struct asset_options {
/// The maximum supply of this asset which may exist at any given time. This can be as large as
/// GRAPHENE_MAX_SHARE_SUPPLY
share_type max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
share_type max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
/// When this asset is traded on the markets, this percentage of the total traded will be exacted and paid
/// to the issuer. This is a fixed point value, representing hundredths of a percent, i.e. a value of 100
/// in this field means a 1% fee is charged on market trades of this asset.
uint16_t market_fee_percent = 0;
share_type max_market_fee = GRAPHENE_MAX_SHARE_SUPPLY;
uint16_t market_fee_percent = 0;
/// Market fees calculated as @ref market_fee_percent of the traded volume are capped to this value
share_type max_market_fee = GRAPHENE_MAX_SHARE_SUPPLY;
/// The flags which the issuer has permission to update. See @ref asset_issuer_permission_flags
uint16_t issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
uint16_t issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
/// The currently active flags on this permission. See @ref asset_issuer_permission_flags
uint16_t flags = 0;
uint16_t flags = 0;
/// When a non-core asset is used to pay a fee, the blockchain must convert that asset to core asset in
/// order to accept the fee. If this asset's fee pool is funded, the chain will automatically deposite fees
@ -161,7 +162,7 @@ namespace graphene { namespace chain {
* data that describes the meaning/purpose of this asset, fee will be charged proportional to
* size of description.
*/
string description;
string description;
/// Perform internal consistency checks.
/// @throws fc::exception if any check fails
@ -197,7 +198,7 @@ namespace graphene { namespace chain {
};
/// Current supply, fee pool, and collected fees are stored in a separate object as they change frequently.
dynamic_asset_data_id_type dynamic_asset_data_id;
asset_dynamic_data_id_type dynamic_asset_data_id;
/// Extra data associated with BitAssets. This field is non-null if and only if is_market_issued() returns true
optional<asset_bitasset_data_id_type> bitasset_data_id;
@ -263,17 +264,18 @@ namespace graphene { namespace chain {
share_type max_force_settlement_volume(share_type current_supply)const;
/** return true if there has been a black swan, false otherwise */
bool has_settlement()const { return !settlement_price.is_null(); }
bool has_settlement()const { return !settlement_price.is_null(); }
/**
* In the event of a black swan, the swan price is saved in the settlement price,
* and all margin positions are settled at the same price with the siezed collateral
* being moved into the settlement fund. From this point on no further updates to
* the asset are permitted (no feeds, etc) and forced settlement occurs using
* the settlement price and fund.
* In the event of a black swan, the swan price is saved in the settlement price, and all margin positions
* are settled at the same price with the siezed collateral being moved into the settlement fund. From this
* point on no further updates to the asset are permitted (no feeds, etc) and forced settlement occurs
* immediately when requested, using the settlement price and fund.
*/
///@{
price settlement_price;
/// Price at which force settlements of a black swanned asset will occur
price settlement_price;
/// Amount of collateral which is available for force settlement
share_type settlement_fund;
///@}

View file

@ -25,6 +25,7 @@
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/fork_database.hpp>
#include <graphene/chain/block_database.hpp>
#include <graphene/chain/genesis_state.hpp>
#include <graphene/db/object_database.hpp>
#include <graphene/db/object.hpp>
@ -39,54 +40,6 @@ namespace graphene { namespace chain {
using graphene::db::abstract_object;
using graphene::db::object;
struct genesis_state_type {
struct initial_account_type {
initial_account_type(const string& name = string(),
const public_key_type& owner_key = public_key_type(),
const public_key_type& active_key = public_key_type(),
bool is_lifetime_member = false)
: name(name),
owner_key(owner_key),
active_key(active_key == public_key_type()? owner_key : active_key),
is_lifetime_member(is_lifetime_member)
{}
string name;
public_key_type owner_key;
public_key_type active_key;
bool is_lifetime_member;
};
struct initial_balance_type {
address owner;
string asset_symbol;
share_type amount;
};
struct initial_vesting_balance_type {
address owner;
string asset_symbol;
share_type amount;
time_point_sec vesting_start_date;
time_point_sec earliest_withdrawal_date;
time_point_sec vesting_end_date;
};
struct initial_witness_type {
/// Must correspond to one of the allocation targets.
string owner_name;
public_key_type block_signing_key;
secret_hash_type initial_secret;
};
struct initial_committee_member_type {
/// Must correspond to one of the allocation targets.
string owner_name;
};
chain_parameters initial_parameters;
vector<initial_account_type> initial_accounts;
vector<initial_balance_type> initial_balances;
vector<initial_vesting_balance_type> initial_vesting_balances;
vector<initial_witness_type> initial_witnesses;
vector<initial_committee_member_type> initial_committee;
};
namespace detail
{
/**
@ -527,14 +480,3 @@ namespace graphene { namespace chain {
}
}
} }
FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key)(is_lifetime_member))
FC_REFLECT(graphene::chain::genesis_state_type::initial_balance_type,
(owner)(asset_symbol)(amount))
FC_REFLECT(graphene::chain::genesis_state_type::initial_vesting_balance_type,
(owner)(asset_symbol)(amount)(vesting_start_date)(earliest_withdrawal_date)(vesting_end_date))
FC_REFLECT(graphene::chain::genesis_state_type::initial_witness_type, (owner_name)(block_signing_key)(initial_secret))
FC_REFLECT(graphene::chain::genesis_state_type::initial_committee_member_type, (owner_name))
FC_REFLECT(graphene::chain::genesis_state_type,
(initial_parameters)(initial_accounts)(initial_balances)
(initial_vesting_balances)(initial_witnesses)(initial_committee))

View file

@ -197,7 +197,7 @@ namespace graphene { namespace chain {
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
typedef object_id< implementation_ids, impl_asset_dynamic_data_type, asset_dynamic_data_object> dynamic_asset_data_id_type;
typedef object_id< implementation_ids, impl_asset_dynamic_data_type, asset_dynamic_data_object> asset_dynamic_data_id_type;
typedef object_id< implementation_ids, impl_asset_bitasset_data_type, asset_bitasset_data_object> asset_bitasset_data_id_type;
typedef object_id< implementation_ids, impl_account_balance_object_type, account_balance_object> account_balance_id_type;
typedef object_id< implementation_ids, impl_account_statistics_object_type,account_statistics_object> account_statistics_id_type;
@ -646,7 +646,7 @@ FC_REFLECT_TYPENAME( graphene::chain::relative_key_id_type )
FC_REFLECT_TYPENAME( graphene::chain::relative_account_id_type )
FC_REFLECT_TYPENAME( graphene::chain::global_property_id_type )
FC_REFLECT_TYPENAME( graphene::chain::dynamic_global_property_id_type )
FC_REFLECT_TYPENAME( graphene::chain::dynamic_asset_data_id_type )
FC_REFLECT_TYPENAME( graphene::chain::asset_dynamic_data_id_type )
FC_REFLECT_TYPENAME( graphene::chain::asset_bitasset_data_id_type )
FC_REFLECT_TYPENAME( graphene::chain::account_balance_id_type )
FC_REFLECT_TYPENAME( graphene::chain::account_statistics_id_type )

View file

@ -70,8 +70,8 @@ database_fixture::database_fixture()
delegate_priv_key.get_public_key(),
delegate_priv_key.get_public_key(),
true);
genesis_state.initial_committee.push_back({name});
genesis_state.initial_witnesses.push_back({name, delegate_priv_key.get_public_key(), secret});
genesis_state.initial_committee_candidates.push_back({name});
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
}
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0});
db.init_genesis(genesis_state);

View file

@ -49,8 +49,8 @@ genesis_state_type make_genesis() {
delegate_priv_key.get_public_key(),
delegate_priv_key.get_public_key(),
true);
genesis_state.initial_committee.push_back({name});
genesis_state.initial_witnesses.push_back({name, delegate_priv_key.get_public_key(), secret});
genesis_state.initial_committee_candidates.push_back({name});
genesis_state.initial_witness_candidates.push_back({name, delegate_priv_key.get_public_key(), secret});
}
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0});
return genesis_state;