Merge branch 'master' of github.com:cryptonomex/graphene

This commit is contained in:
Daniel Larimer 2015-07-01 18:17:55 -04:00
commit 07f621cd65
14 changed files with 417 additions and 151 deletions

View file

@ -302,6 +302,29 @@ namespace graphene { namespace app {
return witnesses_by_account_name;
}
map<string, delegate_id_type> database_api::lookup_delegate_accounts(const string& lower_bound_name, uint32_t limit)const
{
FC_ASSERT( limit <= 1000 );
const auto& delegates_by_id = _db.get_index_type<delegate_index>().indices().get<by_id>();
// we want to order delegates by account name, but that name is in the account object
// so the delegate_index doesn't have a quick way to access it.
// get all the names and look them all up, sort them, then figure out what
// records to return. This could be optimized, but we expect the
// number of delegates to be few and the frequency of calls to be rare
std::map<std::string, delegate_id_type> delegates_by_account_name;
for (const delegate_object& delegate : delegates_by_id)
if (auto account_iter = _db.find(delegate.delegate_account))
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
delegates_by_account_name.insert(std::make_pair(account_iter->name, delegate.id));
auto end_iter = delegates_by_account_name.begin();
while (end_iter != delegates_by_account_name.end() && limit--)
++end_iter;
delegates_by_account_name.erase(end_iter, delegates_by_account_name.end());
return delegates_by_account_name;
}
vector<optional<witness_object>> database_api::get_witnesses(const vector<witness_id_type>& witness_ids)const
{
vector<optional<witness_object>> result; result.reserve(witness_ids.size());
@ -314,6 +337,18 @@ namespace graphene { namespace app {
return result;
}
vector<optional<delegate_object>> database_api::get_delegates(const vector<delegate_id_type>& delegate_ids)const
{
vector<optional<delegate_object>> result; result.reserve(delegate_ids.size());
std::transform(delegate_ids.begin(), delegate_ids.end(), std::back_inserter(result),
[this](delegate_id_type id) -> optional<delegate_object> {
if(auto o = _db.find(id))
return *o;
return {};
});
return result;
}
login_api::login_api(application& a)
:_app(a)
{

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

@ -206,6 +206,14 @@ namespace graphene { namespace app {
*/
map<string, witness_id_type> lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const;
/**
* @brief Get names and IDs for registered delegates
* @param lower_bound_name Lower bound of the first name to return
* @param limit Maximum number of results to return -- must not exceed 1000
* @return Map of delegate names to corresponding IDs
*/
map<string, delegate_id_type> lookup_delegate_accounts(const string& lower_bound_name, uint32_t limit)const;
/**
* @brief Get a list of witnesses by ID
* @param witness_ids IDs of the witnesses to retrieve
@ -215,6 +223,15 @@ namespace graphene { namespace app {
*/
vector<optional<witness_object>> get_witnesses(const vector<witness_id_type>& witness_ids)const;
/**
* @brief Get a list of delegates by ID
* @param delegate_ids IDs of the delegates to retrieve
* @return The delegates corresponding to the provided IDs
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<delegate_object>> get_delegates(const vector<delegate_id_type>& delegate_ids)const;
/**
* @group Push Notification Methods
* These methods may be used to get push notifications whenever an object or market is changed
@ -441,9 +458,11 @@ FC_API(graphene::app::database_api,
(list_assets)
(get_delegate_by_account)
(get_witnesses)
(get_delegates)
(get_witness_by_account)
(get_witness_count)
(lookup_witness_accounts)
(lookup_delegate_accounts)
(subscribe_to_objects)
(unsubscribe_from_objects)
(subscribe_to_market)

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()
@ -147,7 +148,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();
@ -260,40 +261,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() )
{
@ -301,17 +268,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 {
@ -329,6 +296,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 )
@ -339,39 +426,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
@ -384,6 +468,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);
@ -392,7 +478,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
{
/**
@ -525,14 +478,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

@ -0,0 +1,115 @@
#pragma once
#include <graphene/chain/types.hpp>
#include <string>
#include <vector>
namespace graphene { namespace chain {
using std::string;
using std::vector;
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_asset_type {
string symbol;
string description;
uint8_t precision;
string issuer_name;
share_type max_supply;
uint16_t market_fee_percent;
share_type max_market_fee;
uint16_t issuer_permissions;
uint16_t flags;
struct initial_bitasset_options {
uint32_t feed_lifetime_sec;
uint8_t minimum_feeds;
uint32_t force_settlement_delay_sec;
uint16_t force_settlement_offset_percent;
uint16_t maximum_force_settlement_volume;
string backing_asset_symbol;
struct initial_collateral_position {
address owner;
share_type collateral;
share_type debt;
};
uint16_t maintenance_collateral_ratio;
vector<initial_collateral_position> collateral_records;
};
optional<initial_bitasset_options> bitasset_options;
share_type initial_accumulated_fees;
};
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 initial accounts
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 initial accounts
string owner_name;
};
chain_parameters initial_parameters;
vector<initial_account_type> initial_accounts;
vector<initial_asset_type> initial_assets;
vector<initial_balance_type> initial_balances;
vector<initial_vesting_balance_type> initial_vesting_balances;
int initial_active_witnesses = GRAPHENE_DEFAULT_NUM_WITNESSES;
vector<initial_witness_type> initial_witness_candidates;
// These are only candidates; the chain will have no active committee members at genesis
vector<initial_committee_member_type> initial_committee_candidates;
};
} } // namespace graphene::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_asset_type::initial_bitasset_options::initial_collateral_position,
(collateral)(debt))
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options,
(feed_lifetime_sec)(minimum_feeds)(force_settlement_delay_sec)(force_settlement_offset_percent)
(maximum_force_settlement_volume)(backing_asset_symbol)(maintenance_collateral_ratio)(collateral_records))
FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type,
(symbol)(description)(precision)(issuer_name)(max_supply)(market_fee_percent)
(issuer_permissions)(flags)(bitasset_options)(initial_accumulated_fees))
FC_REFLECT(graphene::chain::genesis_state_type,
(initial_parameters)(initial_accounts)(initial_assets)(initial_balances)
(initial_vesting_balances)(initial_active_witnesses)(initial_witness_candidates)
(initial_committee_candidates))

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

@ -807,10 +807,13 @@ class wallet_api
* An account can have at most one delegate object.
*
* @param owner_account the name or id of the account which is creating the delegate
* @param url a URL to include in the delegate record in the blockchain. Clients may
* display this when showing a list of delegates. May be blank.
* @param broadcast true to broadcast the transaction on the network
* @returns the signed transaction registering a delegate
*/
signed_transaction create_delegate(string owner_account,
string url,
bool broadcast = false);
/** Lists all witnesses registered in the blockchain.
@ -828,12 +831,33 @@ class wallet_api
*/
map<string,witness_id_type> list_witnesses(const string& lowerbound, uint32_t limit);
/** Lists all delegates registered in the blockchain.
* This returns a list of all account names that own delegates, and the associated delegate id,
* sorted by name. This lists delegates whether they are currently voted in or not.
*
* Use the \c lowerbound and limit parameters to page through the list. To retrieve all delegates,
* start by setting \c lowerbound to the empty string \c "", and then each iteration, pass
* the last delegate name returned as the \c lowerbound for the next \c list_delegates() call.
*
* @param lowerbound the name of the first delegate to return. If the named delegate does not exist,
* the list will start at the delegate that comes after \c lowerbound
* @param limit the maximum number of delegates to return (max: 1000)
* @returns a list of delegates mapping delegate names to delegate ids
*/
map<string, delegate_id_type> list_delegates(const string& lowerbound, uint32_t limit);
/** Returns information about the given witness.
* @param witness_name_or_id the name or id of the witness account owner, or the id of the witness
* @param owner_account the name or id of the witness account owner, or the id of the witness
* @returns the information about the witness stored in the block chain
*/
witness_object get_witness(string owner_account);
/** Returns information about the given delegate.
* @param owner_account the name or id of the delegate account owner, or the id of the delegate
* @returns the information about the delegate stored in the block chain
*/
delegate_object get_delegate(string owner_account);
/** Creates a witness object owned by the given account.
*
* An account can have at most one witness object.

View file

@ -279,12 +279,14 @@ private:
}
}
}
void enable_umask_protection()
{
#ifdef __unix__
_old_umask = umask( S_IRWXG | S_IRWXO );
#endif
}
void disable_umask_protection()
{
#ifdef __unix__
@ -1169,12 +1171,13 @@ public:
return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW( (authorizing_account)(account_to_list)(new_listing_status)(broadcast) ) }
signed_transaction create_delegate(string owner_account,
signed_transaction create_delegate(string owner_account, string url,
bool broadcast /* = false */)
{ try {
delegate_create_operation delegate_create_op;
delegate_create_op.delegate_account = get_account_id(owner_account);
delegate_create_op.url = url;
if (_remote_db->get_delegate_by_account(delegate_create_op.delegate_account))
FC_THROW("Account ${owner_account} is already a delegate", ("owner_account", owner_account));
@ -1221,6 +1224,41 @@ public:
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
delegate_object get_delegate(string owner_account)
{
try
{
fc::optional<delegate_id_type> delegate_id = maybe_id<delegate_id_type>(owner_account);
if (delegate_id)
{
std::vector<delegate_id_type> ids_to_get;
ids_to_get.push_back(*delegate_id);
std::vector<fc::optional<delegate_object>> delegate_objects = _remote_db->get_delegates(ids_to_get);
if (delegate_objects.front())
return *delegate_objects.front();
FC_THROW("No delegate is registered for id ${id}", ("id", owner_account));
}
else
{
// then maybe it's the owner account
try
{
account_id_type owner_account_id = get_account_id(owner_account);
fc::optional<delegate_object> delegate = _remote_db->get_delegate_by_account(owner_account_id);
if (delegate)
return *delegate;
else
FC_THROW("No delegate is registered for account ${account}", ("account", owner_account));
}
catch (const fc::exception&)
{
FC_THROW("No account or delegate named ${account}", ("account", owner_account));
}
}
}
FC_CAPTURE_AND_RETHROW( (owner_account) )
}
signed_transaction create_witness(string owner_account,
string url,
bool broadcast /* = false */)
@ -2072,10 +2110,10 @@ signed_transaction wallet_api::whitelist_account(string authorizing_account,
return my->whitelist_account(authorizing_account, account_to_list, new_listing_status, broadcast);
}
signed_transaction wallet_api::create_delegate(string owner_account,
signed_transaction wallet_api::create_delegate(string owner_account, string url,
bool broadcast /* = false */)
{
return my->create_delegate(owner_account, broadcast);
return my->create_delegate(owner_account, url, broadcast);
}
map<string,witness_id_type> wallet_api::list_witnesses(const string& lowerbound, uint32_t limit)
@ -2083,6 +2121,11 @@ map<string,witness_id_type> wallet_api::list_witnesses(const string& lowerbound,
return my->_remote_db->lookup_witness_accounts(lowerbound, limit);
}
map<string,delegate_id_type> wallet_api::list_delegates(const string& lowerbound, uint32_t limit)
{
return my->_remote_db->lookup_delegate_accounts(lowerbound, limit);
}
witness_object wallet_api::get_witness(string owner_account)
{
return my->get_witness(owner_account);

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;