diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index ad6ac5dce..a166e7e5c 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -110,6 +110,8 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio } if( d.head_block_time() < HARDFORK_999_TIME ) FC_ASSERT( !op.extensions.value.affiliate_distributions.valid(), "Affiliate reward distributions not allowed yet" ); + if (d.head_block_time() < HARDFORK_SON_TIME) + FC_ASSERT(op.name != "son-account", "Son account creation before SON hardfork"); FC_ASSERT( fee_paying_account->is_lifetime_member(), "Only Lifetime members may register an account." ); FC_ASSERT( op.referrer(d).is_member(d.head_block_time()), "The referrer must be either a lifetime or annual subscriber." ); diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 7a26a2cbe..e61684389 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -42,6 +42,9 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o database& d = db(); + if (d.head_block_time() < HARDFORK_SON_TIME) + FC_ASSERT(op.symbol != "BTC", "BTC asset creation before SON hardfork"); + const auto& chain_parameters = d.get_global_properties().parameters; FC_ASSERT( op.common_options.whitelist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities ); FC_ASSERT( op.common_options.blacklist_authorities.size() <= chain_parameters.maximum_asset_whitelist_authorities ); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index db46b7b9a..fcc9d1a79 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1856,12 +1856,40 @@ void perform_son_tasks(database& db) a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; }); - db.modify( gpo, [&]( global_property_object& gpo ) { + db.modify( gpo, [&son_account]( global_property_object& gpo ) { gpo.parameters.extensions.value.son_account = son_account.get_id(); if( gpo.pending_parameters ) gpo.pending_parameters->extensions.value.son_account = son_account.get_id(); }); } + // create BTC asset here because son_account is the issuer of the BTC + if (gpo.parameters.btc_asset() == asset_id_type() && db.head_block_time() >= HARDFORK_SON_TIME) + { + const asset_dynamic_data_object& dyn_asset = + db.create([](asset_dynamic_data_object& a) { + a.current_supply = 0; + }); + + const asset_object& btc_asset = + db.create( [&gpo, &dyn_asset]( asset_object& a ) { + a.symbol = "BTC"; + a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; + a.precision = 8; + a.options.flags = 0; + a.options.issuer_permissions = 0; + a.issuer = gpo.parameters.son_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; + }); + db.modify( gpo, [&btc_asset]( global_property_object& gpo ) { + gpo.parameters.extensions.value.btc_asset = btc_asset.get_id(); + if( gpo.pending_parameters ) + gpo.pending_parameters->extensions.value.btc_asset = btc_asset.get_id(); + }); + } } void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 03b26183d..b8c9562e8 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -58,6 +58,7 @@ namespace graphene { namespace chain { optional < uint32_t > son_heartbeat_frequency; optional < uint32_t > son_down_time; optional < account_id_type > son_account; + optional < asset_id_type > btc_asset; }; struct chain_parameters @@ -174,6 +175,9 @@ namespace graphene { namespace chain { inline account_id_type son_account() const { return extensions.value.son_account.valid() ? *extensions.value.son_account : GRAPHENE_NULL_ACCOUNT; } + inline asset_id_type btc_asset() const { + return extensions.value.btc_asset.valid() ? *extensions.value.btc_asset : asset_id_type(); + } }; } } // graphene::chain @@ -199,6 +203,7 @@ FC_REFLECT( graphene::chain::parameter_extension, (son_heartbeat_frequency) (son_down_time) (son_account) + (btc_asset) ) FC_REFLECT( graphene::chain::chain_parameters, diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index 28d3522ca..c948616f2 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { create_bitasset("USD", account_id_type()); // create op 0 const account_object& dan = create_account("dan"); // create op 1 create_bitasset("CNY", dan.id); // create op 2 - create_bitasset("BTC", account_id_type()); // create op 3 + create_bitasset("BTCTEST", account_id_type()); // create op 3 create_bitasset("XMR", dan.id); // create op 4 create_bitasset("EUR", account_id_type()); // create op 5 create_bitasset("OIL", dan.id); // create op 6 diff --git a/tests/tests/affiliate_tests.cpp b/tests/tests/affiliate_tests.cpp index 72482a0a9..804d9e8a8 100644 --- a/tests/tests/affiliate_tests.cpp +++ b/tests/tests/affiliate_tests.cpp @@ -289,7 +289,7 @@ BOOST_AUTO_TEST_CASE( affiliate_payout_helper_test ) { ACTORS( (irene) ); - const asset_id_type btc_id = create_user_issued_asset( "BTC", irene, 0 ).id; + const asset_id_type btc_id = create_user_issued_asset( "BTCTEST", irene, 0 ).id; issue_uia( irene, asset( 100000, btc_id ) ); affiliate_test_helper ath( *this ); @@ -517,7 +517,7 @@ BOOST_AUTO_TEST_CASE( bookie_payout_test ) { try { ACTORS( (irene) ); - const asset_id_type btc_id = create_user_issued_asset( "BTC", irene, 0 ).id; + const asset_id_type btc_id = create_user_issued_asset( "BTCTEST", irene, 0 ).id; affiliate_test_helper ath( *this ); @@ -616,7 +616,7 @@ BOOST_AUTO_TEST_CASE( statistics_test ) INVOKE(bookie_payout_test); - const asset_id_type btc_id = get_asset( "BTC" ).id; + const asset_id_type btc_id = get_asset( "BTCTEST" ).id; transfer( ath.alice_id, ath.ann_id, asset( 100, btc_id ), asset(0) ); transfer( ath.alice_id, ath.audrey_id, asset( 100, btc_id ), asset(0) ); diff --git a/tests/tests/history_api_tests.cpp b/tests/tests/history_api_tests.cpp index 943b8265d..8b8a1a517 100644 --- a/tests/tests/history_api_tests.cpp +++ b/tests/tests/history_api_tests.cpp @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(get_account_history_additional) { const account_object& dan = create_account("dan"); // create op 1 create_bitasset("CNY", dan.id); // create op 2 - create_bitasset("BTC", account_id_type()); // create op 3 + create_bitasset("BTCTEST", account_id_type()); // create op 3 create_bitasset("XMR", dan.id); // create op 4 create_bitasset("EUR", account_id_type()); // create op 5 create_bitasset("OIL", dan.id); // create op 6 @@ -454,7 +454,7 @@ BOOST_AUTO_TEST_CASE(track_account) { BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); // create more ops, starting with an untracked account - create_bitasset( "BTC", account_id_type() ); + create_bitasset( "BTCTEST", account_id_type() ); create_bitasset( "GBP", dan_id ); generate_block( ~database::skip_fork_db ); @@ -468,7 +468,7 @@ BOOST_AUTO_TEST_CASE(track_account) { db.pop_block(); // Try again, should result in same object IDs - create_bitasset( "BTC", account_id_type() ); + create_bitasset( "BTCTEST", account_id_type() ); create_bitasset( "GBP", dan_id ); generate_block();