/* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. * * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, * are permitted until September 8, 2015, provided that the following conditions are met: * * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace graphene { namespace chain { void database::initialize_evaluators() { _operation_evaluators.resize(255); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); } void database::initialize_indexes() { reset_indexes(); //Protocol object indexes add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index > >(); add_index< primary_index >(); //Implementation object indexes add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index> >(); add_index< primary_index< simple_index< witness_schedule_object > > >(); } void database::init_genesis(const genesis_state_type& genesis_state) { try { FC_ASSERT(genesis_state.initial_witnesses.size() > 0, "Cannot start a chain with zero 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); // Create initial accounts fc::ecc::private_key null_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); create( [&null_private_key](key_object& k) { k.key_data = public_key_type(null_private_key.get_public_key()); }); create( [](account_balance_object& b) { b.balance = GRAPHENE_INITIAL_SUPPLY; }); const account_object& committee_account = create( [&](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& b){}).id; }); FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT); FC_ASSERT(create([this](account_object& a) { a.name = "witness-account"; a.statistics = create([](account_statistics_object&){}).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([this](account_object& a) { a.name = "relaxed-committee-account"; a.statistics = create([](account_statistics_object&){}).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([this](account_object& a) { a.name = "null-account"; a.statistics = create([](account_statistics_object&){}).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 = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }).get_id() == GRAPHENE_NULL_ACCOUNT); FC_ASSERT(create([this](account_object& a) { a.name = "temp-account"; a.statistics = create([](account_statistics_object&){}).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); // Create core asset const asset_dynamic_data_object& dyn_asset = create( [&]( asset_dynamic_data_object& a ) { a.current_supply = GRAPHENE_INITIAL_SUPPLY; }); const asset_object& core_asset = create( [&]( 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 = committee_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; // Create global properties create([&](global_property_object& p) { p.chain_id = fc::digest(genesis_state); p.parameters = genesis_state.initial_parameters; }); create( [&](dynamic_global_property_object& p) { p.time = fc::time_point_sec(GRAPHENE_GENESIS_TIMESTAMP); p.witness_budget = 0; }); create([&](block_summary_object& p) { }); // Create user accounts, apply initial stake allocation if( !genesis_state.allocation_targets.empty() ) { share_type total_allocation = 0; for( const auto& handout : genesis_state.allocation_targets ) total_allocation += handout.weight; fc::time_point start_time = fc::time_point::now(); for( const auto& handout : genesis_state.allocation_targets ) { asset amount(handout.weight); key_id_type key_id = apply_operation(genesis_eval_state, key_create_operation({asset(), committee_account.id, handout.addr})).get(); account_create_operation cop; cop.name = handout.name; cop.registrar = account_id_type(1); cop.active = authority(1, key_id, 1); cop.owner = cop.active; cop.options.memo_key = key_id; account_id_type account_id(apply_operation(genesis_eval_state, cop).get()); if( handout.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); } if( amount.amount > 0 ) { amount.amount = ((fc::uint128(amount.amount.value) * GRAPHENE_INITIAL_SUPPLY)/total_allocation.value).to_uint64(); apply_operation(genesis_eval_state, transfer_operation({asset(), committee_account.id, account_id, amount, memo_data() })); } } if( total_allocation != 0 ) { asset leftovers = get_balance(account_id_type(), asset_id_type()); if( leftovers.amount > 0 ) { modify(*get_index_type().indices().get().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", genesis_state.allocation_targets.size())("t", duration.count() / 1000)); } flat_set init_delegates; flat_set init_witnesses; const auto& accounts_by_name = get_index_type().indices().get(); // Create initial witnesses and delegates std::for_each(genesis_state.initial_witnesses.begin(), genesis_state.initial_witnesses.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([&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(); init_witnesses.emplace(id); }); std::for_each(genesis_state.initial_committee.begin(), genesis_state.initial_committee.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(); init_delegates.emplace(id); }); // Set initial witnesses and committee as active modify(get_global_properties(), [&](global_property_object& p) { p.active_delegates = vector(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; }); }); // Initialize witness schedule const witness_schedule_object& wso = create([&](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_witnesses); for( size_t i=0; i