From f7e56be44208f242989d7b61eebd72a28ea0fe05 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 5 Jun 2021 20:56:24 +0000 Subject: [PATCH] Split db_init.cpp into two files --- libraries/chain/CMakeLists.txt | 4 +- libraries/chain/database.cpp | 3 +- libraries/chain/db_genesis.cpp | 553 +++++++++++++++++++++++++++++++++ libraries/chain/db_init.cpp | 510 ------------------------------ 4 files changed, 558 insertions(+), 512 deletions(-) create mode 100644 libraries/chain/db_genesis.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 485ae1f6cc..7c4d91e6d6 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -8,14 +8,15 @@ if( GRAPHENE_DISABLE_UNITY_BUILD ) db_balance.cpp db_block.cpp db_debug.cpp + db_genesis.cpp db_getter.cpp db_init.cpp db_maint.cpp db_management.cpp db_market.cpp + db_notify.cpp db_update.cpp db_witness_schedule.cpp - db_notify.cpp ) message( STATUS "Graphene database unity build disabled" ) else( GRAPHENE_DISABLE_UNITY_BUILD ) @@ -81,6 +82,7 @@ target_include_directories( graphene_chain set( GRAPHENE_CHAIN_BIG_FILES db_init.cpp + db_genesis.cpp db_block.cpp db_maint.cpp db_market.cpp diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 788a29f008..7e599a16ce 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -24,11 +24,12 @@ #include "db_balance.cpp" #include "db_block.cpp" #include "db_debug.cpp" +#include "db_genesis.cpp" #include "db_getter.cpp" #include "db_init.cpp" #include "db_maint.cpp" #include "db_management.cpp" #include "db_market.cpp" +#include "db_notify.cpp" #include "db_update.cpp" #include "db_witness_schedule.cpp" -#include "db_notify.cpp" \ No newline at end of file diff --git a/libraries/chain/db_genesis.cpp b/libraries/chain/db_genesis.cpp new file mode 100644 index 0000000000..9893b7178a --- /dev/null +++ b/libraries/chain/db_genesis.cpp @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2017 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace graphene { namespace chain { + +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_transaction_signatures; } + ~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 blockchain accounts + fc::ecc::private_key null_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); + create([](account_balance_object& b) { + b.balance = GRAPHENE_MAX_SHARE_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( [&n](account_statistics_object& s){ + s.owner = n.id; + s.name = n.name; + s.core_in_balance = GRAPHENE_MAX_SHARE_SUPPLY; + }).id; + }); + FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT); + FC_ASSERT(create([this](account_object& a) { + a.name = "witness-account"; + a.statistics = create([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).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([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).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([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).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([this](account_object& a) { + a.name = "temp-account"; + a.statistics = create([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).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([this](account_object& a) { + a.name = "proxy-to-self"; + a.statistics = create([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).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().get_next_id().instance(); + if( id >= genesis_state.immutable_parameters.num_special_accounts ) + break; + const account_object& acct = create([this,id](account_object& a) { + a.name = "special-account-" + std::to_string(id); + a.statistics = create([&a](account_statistics_object& s){ + s.owner = a.id; + s.name = a.name; + }).id; + a.owner.weight_threshold = 1; + a.active.weight_threshold = 1; + a.registrar = a.lifetime_referrer = a.referrer = account_id_type(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& a) { + a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY; + }); + const asset_object& core_asset = + create( [&genesis_state,&dyn_asset]( 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 = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 1; + a.options.core_exchange_rate.quote.asset_id = asset_id_type(0); + a.dynamic_asset_data_id = dyn_asset.id; + }); + FC_ASSERT( dyn_asset.id == asset_dynamic_data_id_type() ); + FC_ASSERT( asset_id_type(core_asset.id) == asset().asset_id ); + FC_ASSERT( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) ); + _p_core_asset_obj = &core_asset; + _p_core_dynamic_data_obj = &dyn_asset; + // Create more special assets + while( true ) + { + uint64_t id = get_index().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& a) { + a.current_supply = 0; + }); + const asset_object& asset_obj = create( [id,&dyn_asset]( 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 = asset_id_type(0); + a.options.core_exchange_rate.quote.amount = 1; + a.options.core_exchange_rate.quote.asset_id = asset_id_type(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 + _p_global_prop_obj = & create([&genesis_state](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.get_mutable_fees().zero_all_fees(); + + }); + _p_dyn_global_prop_obj = & create([&genesis_state](dynamic_global_property_object& p) { + p.time = genesis_state.initial_timestamp; + p.dynamic_flags = 0; + p.witness_budget = 0; + p.recent_slots_filled = std::numeric_limits::max(); + }); + + 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" ); + + _p_chain_property_obj = & create([chain_id,&genesis_state](chain_property_object& p) + { + p.chain_id = chain_id; + p.immutable_parameters = genesis_state.immutable_parameters; + } ); + for (uint32_t i = 0; i <= 0x10000; i++) + create( [&]( 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()); + + 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().indices().get(); + 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().indices().get(); + const auto get_asset_id = [&assets_by_symbol](const string& symbol) { + auto itr = assets_by_symbol.find(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 total_supplies; + map 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().get_next_id(); + total_supplies[ new_asset_id ] = 0; + + asset_dynamic_data_id_type dynamic_data_id; + optional 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(); + + modify( owner_account_id(*this).statistics(*this), [&collateral_rec]( account_statistics_object& o ) { + o.total_core_in_orders = collateral_rec.collateral; + }); + + create([&](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[ asset_id_type(0) ] += collateral_rec.collateral; + total_debts[ new_asset_id ] += collateral_rec.debt; + ++collateral_holder_number; + } + + bitasset_data_id = create([&core_asset,new_asset_id](asset_bitasset_data_object& b) { + b.options.short_backing_asset = core_asset.id; + b.options.minimum_feeds = GRAPHENE_DEFAULT_MINIMUM_FEEDS; + b.asset_id = new_asset_id; + }).id; + } + + dynamic_data_id = create([&asset](asset_dynamic_data_object& d) { + d.accumulated_fees = asset.accumulated_fees; + }).id; + + total_supplies[ new_asset_id ] += asset.accumulated_fees; + + create([&](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 | override_authority | white_list | transfer_restricted | disable_confidential | + ( asset.is_bitasset ? disable_force_settle | global_settle | witness_fed_asset | committee_fed_asset : 0 ); + 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([&handout,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& 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[ asset_id_type(0) ] > 0 ) + { + adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{})); + } + else + { + total_supplies[ asset_id_type(0) ] = GRAPHENE_MAX_SHARE_SUPPLY; + } + + const auto& idx = get_index_type().indices().get(); + 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", + ("aname", it->symbol) + ("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& 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(), [&genesis_state](global_property_object& p) { + for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i ) + { + p.active_witnesses.insert(witness_id_type(i)); + } + }); + + // Enable fees + modify(get_global_properties(), [&genesis_state](global_property_object& p) { + p.parameters.get_mutable_fees() = genesis_state.initial_parameters.get_current_fees(); + }); + + // Create witness scheduler + _p_witness_schedule_obj = & create([this]( witness_schedule_object& wso ) + { + for( const witness_id_type& wid : get_global_properties().active_witnesses ) + wso.current_shuffled_witnesses.push_back( wid ); + }); + + // Create FBA counters + create([&]( fba_accumulator_object& acc ) + { + FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_to_blind ) ); + acc.accumulated_fba_fees = 0; +#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET + acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; +#endif + }); + + create([&]( fba_accumulator_object& acc ) + { + FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_blind_transfer ) ); + acc.accumulated_fba_fees = 0; +#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET + acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; +#endif + }); + + create([&]( fba_accumulator_object& acc ) + { + FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_from_blind ) ); + acc.accumulated_fba_fees = 0; +#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET + acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; +#endif + }); + + FC_ASSERT( get_index().get_next_id() == fba_accumulator_id_type( fba_accumulator_id_count ) ); + + //debug_dump(); + + _undo_db.enable(); +} FC_CAPTURE_AND_RETHROW() } + +} } diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 9114657041..d90baf4f67 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -23,7 +23,6 @@ */ #include -#include #include #include @@ -72,10 +71,6 @@ #include #include -#include - -#include - namespace graphene { namespace chain { void database::initialize_evaluators() @@ -192,509 +187,4 @@ void database::initialize_indexes() add_index< primary_index< simple_index< fba_accumulator_object > > >(); } -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_transaction_signatures; } - ~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 blockchain accounts - fc::ecc::private_key null_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); - create([](account_balance_object& b) { - b.balance = GRAPHENE_MAX_SHARE_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( [&n](account_statistics_object& s){ - s.owner = n.id; - s.name = n.name; - s.core_in_balance = GRAPHENE_MAX_SHARE_SUPPLY; - }).id; - }); - FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT); - FC_ASSERT(create([this](account_object& a) { - a.name = "witness-account"; - a.statistics = create([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).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([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).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([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).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([this](account_object& a) { - a.name = "temp-account"; - a.statistics = create([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).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([this](account_object& a) { - a.name = "proxy-to-self"; - a.statistics = create([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).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().get_next_id().instance(); - if( id >= genesis_state.immutable_parameters.num_special_accounts ) - break; - const account_object& acct = create([this,id](account_object& a) { - a.name = "special-account-" + std::to_string(id); - a.statistics = create([&a](account_statistics_object& s){ - s.owner = a.id; - s.name = a.name; - }).id; - a.owner.weight_threshold = 1; - a.active.weight_threshold = 1; - a.registrar = a.lifetime_referrer = a.referrer = account_id_type(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& a) { - a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY; - }); - const asset_object& core_asset = - create( [&genesis_state,&dyn_asset]( 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 = asset_id_type(0); - a.options.core_exchange_rate.quote.amount = 1; - a.options.core_exchange_rate.quote.asset_id = asset_id_type(0); - a.dynamic_asset_data_id = dyn_asset.id; - }); - FC_ASSERT( dyn_asset.id == asset_dynamic_data_id_type() ); - FC_ASSERT( asset_id_type(core_asset.id) == asset().asset_id ); - FC_ASSERT( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) ); - _p_core_asset_obj = &core_asset; - _p_core_dynamic_data_obj = &dyn_asset; - // Create more special assets - while( true ) - { - uint64_t id = get_index().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& a) { - a.current_supply = 0; - }); - const asset_object& asset_obj = create( [id,&dyn_asset]( 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 = asset_id_type(0); - a.options.core_exchange_rate.quote.amount = 1; - a.options.core_exchange_rate.quote.asset_id = asset_id_type(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 - _p_global_prop_obj = & create([&genesis_state](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.get_mutable_fees().zero_all_fees(); - - }); - _p_dyn_global_prop_obj = & create([&genesis_state](dynamic_global_property_object& p) { - p.time = genesis_state.initial_timestamp; - p.dynamic_flags = 0; - p.witness_budget = 0; - p.recent_slots_filled = std::numeric_limits::max(); - }); - - 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" ); - - _p_chain_property_obj = & create([chain_id,&genesis_state](chain_property_object& p) - { - p.chain_id = chain_id; - p.immutable_parameters = genesis_state.immutable_parameters; - } ); - for (uint32_t i = 0; i <= 0x10000; i++) - create( [&]( 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()); - - 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().indices().get(); - 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().indices().get(); - const auto get_asset_id = [&assets_by_symbol](const string& symbol) { - auto itr = assets_by_symbol.find(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 total_supplies; - map 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().get_next_id(); - total_supplies[ new_asset_id ] = 0; - - asset_dynamic_data_id_type dynamic_data_id; - optional 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(); - - modify( owner_account_id(*this).statistics(*this), [&collateral_rec]( account_statistics_object& o ) { - o.total_core_in_orders = collateral_rec.collateral; - }); - - create([&](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[ asset_id_type(0) ] += collateral_rec.collateral; - total_debts[ new_asset_id ] += collateral_rec.debt; - ++collateral_holder_number; - } - - bitasset_data_id = create([&core_asset,new_asset_id](asset_bitasset_data_object& b) { - b.options.short_backing_asset = core_asset.id; - b.options.minimum_feeds = GRAPHENE_DEFAULT_MINIMUM_FEEDS; - b.asset_id = new_asset_id; - }).id; - } - - dynamic_data_id = create([&asset](asset_dynamic_data_object& d) { - d.accumulated_fees = asset.accumulated_fees; - }).id; - - total_supplies[ new_asset_id ] += asset.accumulated_fees; - - create([&](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 | override_authority | white_list | transfer_restricted | disable_confidential | - ( asset.is_bitasset ? disable_force_settle | global_settle | witness_fed_asset | committee_fed_asset : 0 ); - 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([&handout,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& 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[ asset_id_type(0) ] > 0 ) - { - adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{})); - } - else - { - total_supplies[ asset_id_type(0) ] = GRAPHENE_MAX_SHARE_SUPPLY; - } - - const auto& idx = get_index_type().indices().get(); - 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", - ("aname", it->symbol) - ("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& 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(), [&genesis_state](global_property_object& p) { - for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i ) - { - p.active_witnesses.insert(witness_id_type(i)); - } - }); - - // Enable fees - modify(get_global_properties(), [&genesis_state](global_property_object& p) { - p.parameters.get_mutable_fees() = genesis_state.initial_parameters.get_current_fees(); - }); - - // Create witness scheduler - _p_witness_schedule_obj = & create([this]( witness_schedule_object& wso ) - { - for( const witness_id_type& wid : get_global_properties().active_witnesses ) - wso.current_shuffled_witnesses.push_back( wid ); - }); - - // Create FBA counters - create([&]( fba_accumulator_object& acc ) - { - FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_to_blind ) ); - acc.accumulated_fba_fees = 0; -#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET - acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; -#endif - }); - - create([&]( fba_accumulator_object& acc ) - { - FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_blind_transfer ) ); - acc.accumulated_fba_fees = 0; -#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET - acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; -#endif - }); - - create([&]( fba_accumulator_object& acc ) - { - FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_from_blind ) ); - acc.accumulated_fba_fees = 0; -#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET - acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET; -#endif - }); - - FC_ASSERT( get_index().get_next_id() == fba_accumulator_id_type( fba_accumulator_id_count ) ); - - //debug_dump(); - - _undo_db.enable(); -} FC_CAPTURE_AND_RETHROW() } - } }