void account_history_plugin_impl::update_account_histories( const signed_block& b ) { graphene::chain::database& db = database(); const vector<operation_history_object>& hist = db.get_applied_operations(); for( auto op : hist ) { // add to the operation history index const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h ){ h = op; }); // get the set of accounts this operation applies to flat_set<account_id_type> impacted; vector<authority> other; operation_get_required_authorities( op.op, impacted, impacted, other ); op.op.visit( operation_get_impacted_accounts( oho, _self, impacted ) ); for( auto& a : other ) for( auto& item : a.account_auths ) impacted.insert( item.first ); // for each operation this account applies to that is in the config link it into the history if( _tracked_accounts.size() == 0 ) { for( auto& account_id : impacted ) { // we don't do index_account_keys here anymore, because // that indexing now happens in observers' post_evaluate() // add history const auto& stats_obj = account_id(db).statistics(db); const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){ obj.operation_id = oho.id; obj.next = stats_obj.most_recent_op; }); db.modify( stats_obj, [&]( account_statistics_object& obj ){ obj.most_recent_op = ath.id; }); } } else { for( auto account_id : _tracked_accounts ) { if( impacted.find( account_id ) != impacted.end() ) { // add history const auto& stats_obj = account_id(db).statistics(db); const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){ obj.operation_id = oho.id; obj.next = stats_obj.most_recent_op; }); db.modify( stats_obj, [&]( account_statistics_object& obj ){ obj.most_recent_op = ath.id; }); } } } } }
std::shared_ptr<model::Query> PbQueryFactory::deserialize( const protocol::Query &pb_query) { std::shared_ptr<model::Query> val; if (pb_query.has_get_account()) { // Convert to get Account auto pb_cast = pb_query.get_account(); auto account_query = GetAccount(); account_query.account_id = pb_cast.account_id(); val = std::make_shared<model::GetAccount>(account_query); } if (pb_query.has_get_account_assets()) { // Convert to get Account Asset auto pb_cast = pb_query.get_account_assets(); auto query = GetAccountAssets(); query.account_id = pb_cast.account_id(); query.asset_id = pb_cast.asset_id(); val = std::make_shared<model::GetAccountAssets>(query); } if (pb_query.has_get_account_signatories()) { // Convert to get Signatories auto pb_cast = pb_query.get_account_signatories(); auto query = GetSignatories(); query.account_id = pb_cast.account_id(); val = std::make_shared<model::GetSignatories>(query); } if (pb_query.has_get_account_transactions()) { // Convert to get Signatories auto pb_cast = pb_query.get_account_transactions(); auto query = GetAccountTransactions(); query.account_id = pb_cast.account_id(); val = std::make_shared<model::GetAccountTransactions>(query); } if (!val) { // Query not implemented return nullptr; } Signature sign; auto pb_sign = pb_query.header().signature(); std::copy(pb_sign.pubkey().begin(), pb_sign.pubkey().end(), sign.pubkey.begin()); std::copy(pb_sign.signature().begin(), pb_sign.signature().end(), sign.signature.begin()); val->query_counter = pb_query.query_counter(); val->signature = sign; val->created_ts = pb_query.header().created_time(); val->creator_account_id = pb_query.creator_account_id(); model::HashProviderImpl hashProvider; // TODO: get rid off unnecessary object initialization val->query_hash = hashProvider.get_hash(val); return val; }
void database::init_genesis(const genesis_state_type& genesis_state) { try { FC_ASSERT( genesis_state.initial_timestamp != time_point_sec(), "Must initialize genesis timestamp." ); FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % GRAPHENE_DEFAULT_BLOCK_INTERVAL == 0, "Genesis timestamp must be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL." ); FC_ASSERT(genesis_state.initial_witness_candidates.size() > 0, "Cannot start a chain with zero witnesses."); FC_ASSERT(genesis_state.initial_active_witnesses <= genesis_state.initial_witness_candidates.size(), "initial_active_witnesses is larger than the number of candidate witnesses."); _undo_db.disable(); struct auth_inhibitor { auth_inhibitor(database& db) : db(db), old_flags(db.node_properties().skip_flags) { db.node_properties().skip_flags |= skip_authority_check; } ~auth_inhibitor() { db.node_properties().skip_flags = old_flags; } private: database& db; uint32_t old_flags; } inhibitor(*this); transaction_evaluation_state genesis_eval_state(this); flat_index<block_summary_object>& bsi = get_mutable_index_type< flat_index<block_summary_object> >(); bsi.resize(0xffff+1); // Create blockchain accounts fc::ecc::private_key null_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); create<account_balance_object>([](account_balance_object& b) { b.balance = GRAPHENE_MAX_SHARE_SUPPLY; }); const account_object& committee_account = create<account_object>( [&](account_object& n) { n.membership_expiration_date = time_point_sec::maximum(); n.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; n.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; n.owner.weight_threshold = 1; n.active.weight_threshold = 1; n.name = "committee-account"; n.statistics = create<account_statistics_object>( [&](account_statistics_object& s){ s.owner = n.id; }).id; }); FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT); FC_ASSERT(create<account_object>([this](account_object& a) { a.name = "witness-account"; 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_WITNESS_ACCOUNT; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }).get_id() == GRAPHENE_WITNESS_ACCOUNT); FC_ASSERT(create<account_object>([this](account_object& a) { a.name = "relaxed-committee-account"; 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_RELAXED_COMMITTEE_ACCOUNT; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }).get_id() == GRAPHENE_RELAXED_COMMITTEE_ACCOUNT); FC_ASSERT(create<account_object>([this](account_object& a) { a.name = "null-account"; 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_NULL_ACCOUNT; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = 0; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT; }).get_id() == GRAPHENE_NULL_ACCOUNT); FC_ASSERT(create<account_object>([this](account_object& a) { a.name = "temp-account"; a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id; a.owner.weight_threshold = 0; a.active.weight_threshold = 0; a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_TEMP_ACCOUNT; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }).get_id() == GRAPHENE_TEMP_ACCOUNT); FC_ASSERT(create<account_object>([this](account_object& a) { a.name = "proxy-to-self"; 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_NULL_ACCOUNT; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = 0; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT; }).get_id() == GRAPHENE_PROXY_TO_SELF_ACCOUNT); // Create more special accounts while( true ) { uint64_t id = get_index<account_object>().get_next_id().instance(); if( id >= genesis_state.immutable_parameters.num_special_accounts ) break; const account_object& acct = create<account_object>([&](account_object& a) { a.name = "special-account-" + std::to_string(id); 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 = id; a.membership_expiration_date = time_point_sec::maximum(); a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }); FC_ASSERT( acct.get_id() == account_id_type(id) ); remove( acct ); } // Create core asset const asset_dynamic_data_object& dyn_asset = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) { a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY; }); const asset_object& core_asset = create<asset_object>( [&]( asset_object& a ) { a.symbol = GRAPHENE_SYMBOL; a.options.max_supply = genesis_state.max_core_supply; a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; a.options.flags = 0; a.options.issuer_permissions = 0; a.issuer = GRAPHENE_NULL_ACCOUNT; a.options.core_exchange_rate.base.amount = 1; a.options.core_exchange_rate.base.asset_id = 0; a.options.core_exchange_rate.quote.amount = 1; a.options.core_exchange_rate.quote.asset_id = 0; a.dynamic_asset_data_id = dyn_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) ); // Create more special assets while( true ) { uint64_t id = get_index<asset_object>().get_next_id().instance(); if( id >= genesis_state.immutable_parameters.num_special_assets ) break; const asset_dynamic_data_object& dyn_asset = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) { a.current_supply = 0; }); const asset_object& asset_obj = create<asset_object>( [&]( asset_object& a ) { a.symbol = "SPECIAL" + std::to_string( id ); a.options.max_supply = 0; a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; a.options.flags = 0; a.options.issuer_permissions = 0; a.issuer = GRAPHENE_NULL_ACCOUNT; a.options.core_exchange_rate.base.amount = 1; a.options.core_exchange_rate.base.asset_id = 0; a.options.core_exchange_rate.quote.amount = 1; a.options.core_exchange_rate.quote.asset_id = 0; a.dynamic_asset_data_id = dyn_asset.id; }); FC_ASSERT( asset_obj.get_id() == asset_id_type(id) ); remove( asset_obj ); } chain_id_type chain_id = genesis_state.compute_chain_id(); // Create global properties create<global_property_object>([&](global_property_object& p) { p.parameters = genesis_state.initial_parameters; // Set fees to zero initially, so that genesis initialization needs not pay them // We'll fix it at the end of the function p.parameters.current_fees->zero_all_fees(); }); create<dynamic_global_property_object>([&](dynamic_global_property_object& p) { p.time = genesis_state.initial_timestamp; p.dynamic_flags = 0; p.witness_budget = 0; p.recent_slots_filled = fc::uint128::max_value(); }); FC_ASSERT( (genesis_state.immutable_parameters.min_witness_count & 1) == 1, "min_witness_count must be odd" ); FC_ASSERT( (genesis_state.immutable_parameters.min_committee_member_count & 1) == 1, "min_committee_member_count must be odd" ); create<chain_property_object>([&](chain_property_object& p) { p.chain_id = chain_id; p.immutable_parameters = genesis_state.immutable_parameters; } ); create<block_summary_object>([&](block_summary_object&) {}); // Create initial accounts for( const auto& account : genesis_state.initial_accounts ) { account_create_operation cop; cop.name = account.name; cop.registrar = GRAPHENE_TEMP_ACCOUNT; cop.owner = authority(1, account.owner_key, 1); if( account.active_key == public_key_type() ) { cop.active = cop.owner; cop.options.memo_key = account.owner_key; } else { cop.active = authority(1, account.active_key, 1); cop.options.memo_key = account.active_key; } account_id_type account_id(apply_operation(genesis_eval_state, cop).get<object_id_type>()); if( account.is_lifetime_member ) { account_upgrade_operation op; op.account_to_upgrade = account_id; op.upgrade_to_lifetime_member = true; apply_operation(genesis_eval_state, op); } } // Helper function to get account ID by name 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(), "Unable to find account '${acct}'. Did you forget to add a record for it to initial_accounts?", ("acct", name)); return itr->get_id(); }; // Helper function to get asset ID by symbol const auto& assets_by_symbol = get_index_type<asset_index>().indices().get<by_symbol>(); const auto get_asset_id = [&assets_by_symbol](const string& symbol) { auto itr = assets_by_symbol.find(symbol); // TODO: This is temporary for handling BTS snapshot if( symbol == "BTS" ) itr = assets_by_symbol.find(GRAPHENE_SYMBOL); FC_ASSERT(itr != assets_by_symbol.end(), "Unable to find asset '${sym}'. Did you forget to add a record for it to initial_assets?", ("sym", symbol)); return itr->get_id(); }; map<asset_id_type, share_type> total_supplies; map<asset_id_type, share_type> total_debts; // Create initial assets for( const genesis_state_type::initial_asset_type& asset : genesis_state.initial_assets ) { asset_id_type new_asset_id = get_index_type<asset_index>().get_next_id(); total_supplies[ new_asset_id ] = 0; asset_dynamic_data_id_type dynamic_data_id; optional<asset_bitasset_data_id_type> bitasset_data_id; if( asset.is_bitasset ) { int collateral_holder_number = 0; total_debts[ new_asset_id ] = 0; for( const auto& collateral_rec : asset.collateral_records ) { 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, collateral_rec.owner, 1); cop.active = cop.owner; account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>(); modify( owner_account_id(*this).statistics(*this), [&]( account_statistics_object& o ) { o.total_core_in_orders = collateral_rec.collateral; }); 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, core_asset.id), GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO); }); total_supplies[ 0 ] += collateral_rec.collateral; total_debts[ new_asset_id ] += collateral_rec.debt; ++collateral_holder_number; } bitasset_data_id = create<asset_bitasset_data_object>([&](asset_bitasset_data_object& b) { b.options.short_backing_asset = core_asset.id; b.options.minimum_feeds = GRAPHENE_DEFAULT_MINIMUM_FEEDS; }).id; } dynamic_data_id = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& d) { d.accumulated_fees = asset.accumulated_fees; }).id; total_supplies[ new_asset_id ] += asset.accumulated_fees; create<asset_object>([&](asset_object& a) { a.symbol = asset.symbol; a.options.description = asset.description; a.precision = asset.precision; string issuer_name = asset.issuer_name; a.issuer = get_account_id(issuer_name); a.options.max_supply = asset.max_supply; a.options.flags = witness_fed_asset; a.options.issuer_permissions = charge_market_fee | global_settle | witness_fed_asset | committee_fed_asset; a.dynamic_asset_data_id = dynamic_data_id; a.bitasset_data_id = bitasset_data_id; }); } // Create initial balances share_type total_allocation; for( const auto& handout : genesis_state.initial_balances ) { const auto asset_id = get_asset_id(handout.asset_symbol); create<balance_object>([&handout,&get_asset_id,total_allocation,asset_id](balance_object& b) { b.balance = asset(handout.amount, asset_id); b.owner = handout.owner; }); total_supplies[ asset_id ] += handout.amount; } // Create initial vesting balances for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances ) { const auto asset_id = get_asset_id(vest.asset_symbol); create<balance_object>([&](balance_object& b) { b.owner = vest.owner; b.balance = asset(vest.amount, asset_id); linear_vesting_policy policy; policy.begin_timestamp = vest.begin_timestamp; policy.vesting_cliff_seconds = 0; policy.vesting_duration_seconds = vest.vesting_duration_seconds; policy.begin_balance = vest.begin_balance; b.vesting_policy = std::move(policy); }); total_supplies[ asset_id ] += vest.amount; } if( total_supplies[ 0 ] > 0 ) { adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{})); } else { total_supplies[ 0 ] = GRAPHENE_MAX_SHARE_SUPPLY; } const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>(); auto it = idx.begin(); bool has_imbalanced_assets = false; while( it != idx.end() ) { if( it->bitasset_data_id.valid() ) { auto supply_itr = total_supplies.find( it->id ); auto debt_itr = total_debts.find( it->id ); FC_ASSERT( supply_itr != total_supplies.end() ); FC_ASSERT( debt_itr != total_debts.end() ); if( supply_itr->second != debt_itr->second ) { has_imbalanced_assets = true; elog( "Genesis for asset ${aname} is not balanced\n" " Debt is ${debt}\n" " Supply is ${supply}\n", ("debt", debt_itr->second) ("supply", supply_itr->second) ); } } ++it; } FC_ASSERT( !has_imbalanced_assets ); // Save tallied supplies for( const auto& item : total_supplies ) { const auto asset_id = item.first; const auto total_supply = item.second; modify( get( asset_id ), [ & ]( asset_object& asset ) { modify( get( asset.dynamic_asset_data_id ), [ & ]( asset_dynamic_data_object& asset_data ) { asset_data.current_supply = total_supply; } ); } ); } // Create special witness account const witness_object& wit = create<witness_object>([&](witness_object& w) {}); FC_ASSERT( wit.id == GRAPHENE_NULL_WITNESS ); remove(wit); // Create initial witnesses std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(), [&](const genesis_state_type::initial_witness_type& witness) { witness_create_operation op; op.witness_account = get_account_id(witness.owner_name); op.block_signing_key = witness.block_signing_key; apply_operation(genesis_eval_state, op); }); // Create initial committee members std::for_each(genesis_state.initial_committee_candidates.begin(), genesis_state.initial_committee_candidates.end(), [&](const genesis_state_type::initial_committee_member_type& member) { committee_member_create_operation op; op.committee_member_account = get_account_id(member.owner_name); apply_operation(genesis_eval_state, op); }); // Create initial workers std::for_each(genesis_state.initial_worker_candidates.begin(), genesis_state.initial_worker_candidates.end(), [&](const genesis_state_type::initial_worker_type& worker) { worker_create_operation op; op.owner = get_account_id(worker.owner_name); op.work_begin_date = genesis_state.initial_timestamp; op.work_end_date = time_point_sec::maximum(); op.daily_pay = worker.daily_pay; op.name = "Genesis-Worker-" + worker.owner_name; op.initializer = vesting_balance_worker_initializer{uint16_t(0)}; apply_operation(genesis_eval_state, std::move(op)); }); // Set active witnesses modify(get_global_properties(), [&](global_property_object& p) { for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i ) { p.active_witnesses.insert(i); p.witness_accounts.insert(get(witness_id_type(i)).witness_account); } }); // Enable fees modify(get_global_properties(), [&genesis_state](global_property_object& p) { p.parameters.current_fees = genesis_state.initial_parameters.current_fees; }); // Create witness scheduler create<witness_schedule_object>([&]( witness_schedule_object& wso ) { for( const witness_id_type& wid : get_global_properties().active_witnesses ) wso.current_shuffled_witnesses.push_back( wid ); }); debug_dump(); _undo_db.enable(); } FC_CAPTURE_AND_RETHROW() }
void database::init_genesis(const genesis_allocation& initial_allocation) { try { _undo_db.disable(); fc::ecc::private_key genesis_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis"))); const key_object& genesis_key = create<key_object>( [&genesis_private_key](key_object& k) { k.key_data = public_key_type(genesis_private_key.get_public_key()); }); const account_statistics_object& genesis_statistics = create<account_statistics_object>( [&](account_statistics_object& b){ }); create<account_balance_object>( [](account_balance_object& b) { b.balance = GRAPHENE_INITIAL_SUPPLY; }); const account_object& genesis_account = create<account_object>( [&](account_object& n) { n.name = "genesis"; n.owner.add_authority(genesis_key.get_id(), 1); n.owner.weight_threshold = 1; n.active = n.owner; n.memo_key = genesis_key.id; n.statistics = genesis_statistics.id; }); vector<delegate_id_type> init_delegates; vector<witness_id_type> init_witnesses; flat_set<witness_id_type> init_witness_set; auto delegates_and_witnesses = std::max(GRAPHENE_MIN_WITNESS_COUNT, GRAPHENE_MIN_DELEGATE_COUNT); for( int i = 0; i < delegates_and_witnesses; ++i ) { const account_statistics_object& stats_obj = create<account_statistics_object>( [&](account_statistics_object&){ }); const account_object& delegate_account = create<account_object>( [&](account_object& a) { a.active = a.owner = genesis_account.owner; a.name = string("init") + fc::to_string(i); a.statistics = stats_obj.id; }); const delegate_object& init_delegate = create<delegate_object>( [&](delegate_object& d) { d.delegate_account = delegate_account.id; d.vote_id = i * 2; }); init_delegates.push_back(init_delegate.id); const witness_object& init_witness = create<witness_object>( [&](witness_object& d) { d.witness_account = delegate_account.id; d.vote_id = i * 2 + 1; secret_hash_type::encoder enc; fc::raw::pack( enc, genesis_private_key ); fc::raw::pack( enc, d.last_secret ); d.next_secret = secret_hash_type::hash(enc.result()); }); init_witnesses.push_back(init_witness.id); init_witness_set.insert(init_witness.id); } create<block_summary_object>( [&](block_summary_object& p) { }); const witness_schedule_object& wso = create<witness_schedule_object>( [&]( witness_schedule_object& _wso ) { memset( _wso.rng_seed.begin(), 0, _wso.rng_seed.size() ); witness_scheduler_rng rng( _wso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV ); _wso.scheduler = witness_scheduler(); _wso.scheduler._min_token_count = init_witnesses.size() / 2; _wso.scheduler.update( init_witness_set ); for( int i=0; i<init_witnesses.size(); i++ ) _wso.scheduler.produce_schedule( rng ); _wso.last_scheduling_block = 0; } ) ; assert( wso.id == witness_schedule_id_type() ); const global_property_object& properties = create<global_property_object>( [&](global_property_object& p) { p.active_delegates = init_delegates; for( const witness_id_type& wit : init_witnesses ) p.active_witnesses.insert( wit ); p.next_available_vote_id = delegates_and_witnesses * 2; p.chain_id = fc::digest(initial_allocation); }); (void)properties; create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) { p.time = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP ); }); const asset_dynamic_data_object& dyn_asset = create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) { a.current_supply = GRAPHENE_INITIAL_SUPPLY; }); const asset_object& core_asset = create<asset_object>( [&]( asset_object& a ) { a.symbol = GRAPHENE_SYMBOL; a.options.max_supply = GRAPHENE_INITIAL_SUPPLY; a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; a.options.flags = 0; a.options.issuer_permissions = 0; a.issuer = genesis_account.id; a.options.core_exchange_rate.base.amount = 1; a.options.core_exchange_rate.base.asset_id = 0; a.options.core_exchange_rate.quote.amount = 1; a.options.core_exchange_rate.quote.asset_id = 0; a.dynamic_asset_data_id = dyn_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) ); (void)core_asset; if( !initial_allocation.empty() ) { share_type total_allocation = 0; for( const auto& handout : initial_allocation ) total_allocation += handout.second; auto mangle_to_name = [](const fc::static_variant<public_key_type, address>& key) { string addr = string(key.which() == std::decay<decltype(key)>::type::tag<address>::value? key.get<address>() : key.get<public_key_type>()); string result = "bts"; string key_string = string(addr).substr(sizeof(GRAPHENE_ADDRESS_PREFIX)-1); for( char c : key_string ) { if( isupper(c) ) result += string("-") + char(tolower(c)); else result += c; } return result; }; fc::time_point start_time = fc::time_point::now(); for( const auto& handout : initial_allocation ) { asset amount(handout.second); amount.amount = ((fc::uint128(amount.amount.value) * GRAPHENE_INITIAL_SUPPLY)/total_allocation.value).to_uint64(); if( amount.amount == 0 ) { wlog("Skipping zero allocation to ${k}", ("k", handout.first)); continue; } signed_transaction trx; trx.operations.emplace_back(key_create_operation({asset(), genesis_account.id, handout.first})); relative_key_id_type key_id(0); authority account_authority(1, key_id, 1); account_create_operation cop; cop.name = mangle_to_name(handout.first); cop.registrar = account_id_type(1); cop.active = account_authority; cop.owner = account_authority; cop.memo_key = key_id; trx.operations.push_back(cop); trx.validate(); auto ptrx = apply_transaction(trx, ~0); trx = signed_transaction(); account_id_type account_id(ptrx.operation_results.back().get<object_id_type>()); trx.operations.emplace_back(transfer_operation({ asset(), genesis_account.id, account_id, amount, memo_data()//vector<char>() })); trx.validate(); apply_transaction(trx, ~0); } asset leftovers = get_balance(account_id_type(), asset_id_type()); if( leftovers.amount > 0 ) { modify(*get_index_type<account_balance_index>().indices().get<by_balance>().find(boost::make_tuple(account_id_type(), asset_id_type())), [](account_balance_object& b) { b.adjust_balance(-b.get_balance()); }); modify(core_asset.dynamic_asset_data_id(*this), [&leftovers](asset_dynamic_data_object& d) { d.accumulated_fees += leftovers.amount; }); } fc::microseconds duration = fc::time_point::now() - start_time; ilog("Finished allocating to ${n} accounts in ${t} milliseconds.", ("n", initial_allocation.size())("t", duration.count() / 1000)); } _undo_db.enable(); } FC_LOG_AND_RETHROW() }