From 0192a02fdf7cb8c18f4b90bd90c4e77920f7b63e Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Wed, 24 Jan 2018 15:06:29 +0100 Subject: [PATCH 01/14] Disable use of new_issuer after hardfork #199 --- libraries/chain/asset_evaluator.cpp | 2 ++ libraries/chain/hardfork.d/CORE_199.hf | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 libraries/chain/hardfork.d/CORE_199.hf diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 9802a647ce..a420094293 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -262,6 +262,8 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) if( o.new_issuer ) { + FC_ASSERT( d.head_block_time() < HARDFORK_CORE_199_TIME, + "Since Hardfork #199, updating issuer requires the use of asset_change_issuer_operation.") FC_ASSERT(d.find_object(*o.new_issuer)); if( a.is_market_issued() && *o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) { diff --git a/libraries/chain/hardfork.d/CORE_199.hf b/libraries/chain/hardfork.d/CORE_199.hf new file mode 100644 index 0000000000..788829e238 --- /dev/null +++ b/libraries/chain/hardfork.d/CORE_199.hf @@ -0,0 +1,4 @@ +// bitshares-core #199 Require owner key for change of asset-issuer (new operation) +#ifndef HARDFORK_CORE_199_TIME +#define HARDFORK_CORE_199_TIME (fc::time_point_sec( 1512747600 )) +#endif From 75ece832a9811a1fd95ad02ffb2eb5a666c0cac2 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Thu, 25 Jan 2018 12:56:48 +0100 Subject: [PATCH 02/14] Implement functionality of asset_update_issuer_operation --- libraries/app/impacted.cpp | 4 ++ libraries/chain/asset_evaluator.cpp | 40 ++++++++++++++++++- libraries/chain/db_init.cpp | 1 + libraries/chain/db_notify.cpp | 5 ++- .../graphene/chain/asset_evaluator.hpp | 31 ++++++++++++++ .../graphene/chain/protocol/asset_ops.hpp | 37 +++++++++++++++++ .../graphene/chain/protocol/fee_schedule.hpp | 16 ++++++++ .../graphene/chain/protocol/operations.hpp | 3 +- libraries/chain/proposal_evaluator.cpp | 9 +++++ libraries/chain/protocol/asset_ops.cpp | 6 +++ 10 files changed, 149 insertions(+), 3 deletions(-) diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 5f2d4fdbe4..f3b610ab9c 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -97,6 +97,10 @@ struct get_impacted_account_visitor _impacted.insert( *(op.new_issuer) ); } + void operator()( const asset_update_issuer_operation& op ) { + _impacted.insert( op.new_issuer ); + } + void operator()( const asset_update_bitasset_operation& op ) {} void operator()( const asset_update_feed_producers_operation& op ) {} diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index a420094293..4c1dc45193 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -263,7 +263,7 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) if( o.new_issuer ) { FC_ASSERT( d.head_block_time() < HARDFORK_CORE_199_TIME, - "Since Hardfork #199, updating issuer requires the use of asset_change_issuer_operation.") + "Since Hardfork #199, updating issuer requires the use of asset_change_issuer_operation."); FC_ASSERT(d.find_object(*o.new_issuer)); if( a.is_market_issued() && *o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) { @@ -330,6 +330,44 @@ void_result asset_update_evaluator::do_apply(const asset_update_operation& o) return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } +void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer_operation& o) +{ try { + database& d = db(); + + const asset_object& a = o.asset_to_update(d); + auto a_copy = a; + a_copy.validate(); + + FC_ASSERT(d.find_object(o.new_issuer)); + if( a.is_market_issued() && o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) + { + const asset_object& backing = a.bitasset_data(d).options.short_backing_asset(d); + if( backing.is_market_issued() ) + { + const asset_object& backing_backing = backing.bitasset_data(d).options.short_backing_asset(d); + FC_ASSERT( backing_backing.get_id() == asset_id_type(), + "May not create a blockchain-controlled market asset which is not backed by CORE."); + } else + FC_ASSERT( backing.get_id() == asset_id_type(), + "May not create a blockchain-controlled market asset which is not backed by CORE."); + } + + asset_to_update = &a; + FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + + return void_result(); +} FC_CAPTURE_AND_RETHROW((o)) } + +void_result asset_update_issuer_evaluator::do_apply(const asset_update_issuer_operation& o) +{ try { + database& d = db(); + d.modify(*asset_to_update, [&](asset_object& a) { + a.issuer = o.new_issuer; + }); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (o) ) } + void_result asset_update_bitasset_evaluator::do_evaluate(const asset_update_bitasset_operation& o) { try { database& d = db(); diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 65dbaafec9..b22dd220a8 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -172,6 +172,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); } void database::initialize_indexes() diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 8760feb041..02a35512a5 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -84,7 +84,10 @@ struct get_impacted_account_visitor if( op.new_issuer ) _impacted.insert( *(op.new_issuer) ); } - + void operator()( const asset_update_issuer_operation& op ) + { + _impacted.insert( op.new_issuer ); + } void operator()( const asset_update_bitasset_operation& op ) {} void operator()( const asset_update_feed_producers_operation& op ) {} diff --git a/libraries/chain/include/graphene/chain/asset_evaluator.hpp b/libraries/chain/include/graphene/chain/asset_evaluator.hpp index 67718a7bf8..67e49193d9 100644 --- a/libraries/chain/include/graphene/chain/asset_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/asset_evaluator.hpp @@ -78,6 +78,17 @@ namespace graphene { namespace chain { const asset_object* asset_to_update = nullptr; }; + class asset_update_issuer_evaluator : public evaluator + { + public: + typedef asset_update_issuer_operation operation_type; + + void_result do_evaluate( const asset_update_issuer_operation& o ); + void_result do_apply( const asset_update_issuer_operation& o ); + + const asset_object* asset_to_update = nullptr; + }; + class asset_update_bitasset_evaluator : public evaluator { public: @@ -152,4 +163,24 @@ namespace graphene { namespace chain { void_result do_apply( const asset_claim_fees_operation& o ); }; + namespace impl { // TODO: remove after HARDFORK_CORE_199_TIME has passed + class hf_199_visitor { + public: + typedef void result_type; + + template + void operator()( const T& v )const {} + + void operator()( const graphene::chain::asset_update_issuer_operation& v )const { + FC_ASSERT( false, "Not allowed until hardfork 199" ); + } + + void operator()( const graphene::chain::proposal_create_operation& v )const { + for( const op_wrapper& op : v.proposed_ops ) + op.op.visit( *this ); + } + }; + } + + } } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp index 3f5ede199e..df0fb0d0f9 100644 --- a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp +++ b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp @@ -442,6 +442,35 @@ namespace graphene { namespace chain { void validate()const; }; + /** + * @brief Update issuer of an asset + * @ingroup operations + * + * An issuer has general administrative power of an asset and in some cases + * also its shares issued to individuals. Thus, changing the issuer today + * requires the use of a separate operation that needs to be signed by the + * owner authority. + * + */ + struct asset_update_issuer_operation : public base_operation + { + struct fee_parameters_type { + uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; + }; + + asset fee; + account_id_type issuer; + asset_id_type asset_to_update; + account_id_type new_issuer; + extensions_type extensions; + + account_id_type fee_payer()const { return issuer; } + void validate()const; + + void get_required_owner_authorities( flat_set& a )const + { a.insert( issuer ); } + }; + } } // graphene::chain @@ -479,6 +508,7 @@ FC_REFLECT( graphene::chain::asset_settle_operation::fee_parameters_type, (fee) FC_REFLECT( graphene::chain::asset_settle_cancel_operation::fee_parameters_type, ) FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::asset_update_operation::fee_parameters_type, (fee)(price_per_kbyte) ) +FC_REFLECT( graphene::chain::asset_update_issuer_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::asset_update_bitasset_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::asset_update_feed_producers_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::asset_publish_feed_operation::fee_parameters_type, (fee) ) @@ -504,6 +534,13 @@ FC_REFLECT( graphene::chain::asset_update_operation, (new_options) (extensions) ) +FC_REFLECT( graphene::chain::asset_update_issuer_operation, + (fee) + (issuer) + (asset_to_update) + (new_issuer) + (extensions) + ) FC_REFLECT( graphene::chain::asset_update_bitasset_operation, (fee) (issuer) diff --git a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp index 2d3813083e..f28a4fea4e 100644 --- a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp +++ b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp @@ -77,6 +77,22 @@ namespace graphene { namespace chain { } }; + template<> + class fee_helper { + public: + const asset_update_issuer_operation::fee_parameters_type& cget(const flat_set& parameters)const + { + auto itr = parameters.find( asset_update_issuer_operation::fee_parameters_type() ); + if ( itr != parameters.end() ) + return itr->get(); + + static asset_update_issuer_operation::fee_parameters_type dummy; + dummy.fee = fee_helper().cget(parameters).fee; + return dummy; + } + }; + + /** * @brief contains all of the parameters necessary to calculate the fee for any operation */ diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 3377a2f9c1..71c5a84cd6 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -93,7 +93,8 @@ namespace graphene { namespace chain { asset_claim_fees_operation, fba_distribute_operation, // VIRTUAL bid_collateral_operation, - execute_bid_operation // VIRTUAL + execute_bid_operation, // VIRTUAL + asset_update_issuer_operation > operation; /// @} // operations group diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index a64a38ddc6..0e4edfef79 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -26,6 +26,9 @@ #include #include #include +#include +#include + #include @@ -75,6 +78,12 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati _proposed_trx.operations.push_back(op.op); _proposed_trx.validate(); + if( d.head_block_time() <= HARDFORK_CORE_199_TIME ) + { // TODO: remove after HARDFORK_CORE_199_TIME has passed + graphene::chain::impl::hf_199_visitor hf_199; + hf_199( o ); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/libraries/chain/protocol/asset_ops.cpp b/libraries/chain/protocol/asset_ops.cpp index fd1c11be00..0be5013cd4 100644 --- a/libraries/chain/protocol/asset_ops.cpp +++ b/libraries/chain/protocol/asset_ops.cpp @@ -123,6 +123,12 @@ void asset_update_operation::validate()const FC_ASSERT(dummy.asset_id == asset_id_type()); } +void asset_update_issuer_operation::validate()const +{ + FC_ASSERT( fee.amount >= 0 ); + FC_ASSERT(issuer != new_issuer); +} + share_type asset_update_operation::calculate_fee(const asset_update_operation::fee_parameters_type& k)const { return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); From 4e9f6e9bd287f72043c6c9b8d6daf9994a0e3017 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Thu, 25 Jan 2018 18:30:58 +0100 Subject: [PATCH 03/14] Add hf_199 visitor and implement unittests for asset_update_issuer_operation --- libraries/chain/asset_evaluator.cpp | 7 ++++ tests/tests/operation_tests.cpp | 59 +++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 4c1dc45193..1899059332 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -355,6 +355,13 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer asset_to_update = &a; FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + if( d.head_block_time() <= HARDFORK_CORE_199_TIME ) + { // TODO: remove after HARDFORK_CORE_199_TIME has passed + graphene::chain::impl::hf_199_visitor hf_199; + hf_199( o ); + } + + return void_result(); } FC_CAPTURE_AND_RETHROW((o)) } diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 8779727ebe..99e10df356 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -718,6 +718,65 @@ BOOST_AUTO_TEST_CASE( update_uia ) } } +BOOST_AUTO_TEST_CASE( update_uia_issuer ) +{ + using namespace graphene; + using namespace graphene::chain; + using namespace graphene::chain::test; + try { + // committee_account owns the asset UIA_TEST_SYMBOL + // alice owns nothing + // bob owns nothing + INVOKE(create_uia); + const auto& test = get_asset(UIA_TEST_SYMBOL); + const auto& committee_account = account_id_type()(db); + const auto& alice = create_account("alice"); + const auto& bob = create_account("bob"); + + auto update_issuer = [&]( asset_object asset, account_object issuer, account_object new_issuer ) + { + asset_update_issuer_operation op; + op.issuer = issuer.id; + op.new_issuer = new_issuer.id; + op.asset_to_update = asset.id; + signed_transaction tx; + tx.operations.push_back( op ); + db.current_fee_schedule().set_fee( tx.operations.back() ); + set_expiration( db, tx ); + PUSH_TX( db, tx, ~0 ); + }; + + if( db.head_block_time() <= HARDFORK_CORE_199_TIME ) + { + BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, committee_account, bob ), fc::exception ); + generate_blocks( HARDFORK_CORE_199_TIME ); + while( db.head_block_time() <= HARDFORK_CORE_199_TIME ) + { + generate_block(); + } + } + + BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob ), fc::exception ); + + BOOST_TEST_MESSAGE( "Updating issuer to alice" ); + update_issuer( test, committee_account, alice ); + + BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, committee_account, bob ), fc::exception ); + + BOOST_TEST_MESSAGE( "Updating issuer to bob" ); + update_issuer( test, alice, bob ); + + } + catch( const fc::exception& e ) + { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_CASE( issue_uia ) { try { From 05bd614bbcba77d3b1103b40d41f235c2b437c87 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Fri, 26 Jan 2018 15:33:18 +0100 Subject: [PATCH 04/14] improved unittests and fixed hardfork conditions --- libraries/chain/asset_evaluator.cpp | 4 +- libraries/chain/hardfork.d/CORE_199.hf | 2 +- .../graphene/chain/protocol/asset_ops.hpp | 4 + libraries/chain/proposal_evaluator.cpp | 2 +- tests/tests/operation_tests.cpp | 91 +++++++++++++------ 5 files changed, 72 insertions(+), 31 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 1899059332..d1bc4d63e9 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -335,8 +335,6 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer database& d = db(); const asset_object& a = o.asset_to_update(d); - auto a_copy = a; - a_copy.validate(); FC_ASSERT(d.find_object(o.new_issuer)); if( a.is_market_issued() && o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) @@ -355,7 +353,7 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer asset_to_update = &a; FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); - if( d.head_block_time() <= HARDFORK_CORE_199_TIME ) + if( d.head_block_time() < HARDFORK_CORE_199_TIME ) { // TODO: remove after HARDFORK_CORE_199_TIME has passed graphene::chain::impl::hf_199_visitor hf_199; hf_199( o ); diff --git a/libraries/chain/hardfork.d/CORE_199.hf b/libraries/chain/hardfork.d/CORE_199.hf index 788829e238..88e207b173 100644 --- a/libraries/chain/hardfork.d/CORE_199.hf +++ b/libraries/chain/hardfork.d/CORE_199.hf @@ -1,4 +1,4 @@ // bitshares-core #199 Require owner key for change of asset-issuer (new operation) #ifndef HARDFORK_CORE_199_TIME -#define HARDFORK_CORE_199_TIME (fc::time_point_sec( 1512747600 )) +#define HARDFORK_CORE_199_TIME (fc::time_point_sec( 1600000000 )) #endif diff --git a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp index df0fb0d0f9..6e602e83d3 100644 --- a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp +++ b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp @@ -469,6 +469,10 @@ namespace graphene { namespace chain { void get_required_owner_authorities( flat_set& a )const { a.insert( issuer ); } + + void get_required_active_authorities( flat_set& a )const + { } + }; diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 0e4edfef79..14de5fb1f8 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -78,7 +78,7 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati _proposed_trx.operations.push_back(op.op); _proposed_trx.validate(); - if( d.head_block_time() <= HARDFORK_CORE_199_TIME ) + if( d.head_block_time() < HARDFORK_CORE_199_TIME ) { // TODO: remove after HARDFORK_CORE_199_TIME has passed graphene::chain::impl::hf_199_visitor hf_199; hf_199( o ); diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 99e10df356..bbd82fb56c 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -724,16 +724,45 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) using namespace graphene::chain; using namespace graphene::chain::test; try { - // committee_account owns the asset UIA_TEST_SYMBOL - // alice owns nothing - // bob owns nothing - INVOKE(create_uia); - const auto& test = get_asset(UIA_TEST_SYMBOL); - const auto& committee_account = account_id_type()(db); - const auto& alice = create_account("alice"); - const auto& bob = create_account("bob"); - auto update_issuer = [&]( asset_object asset, account_object issuer, account_object new_issuer ) + // Lambda for creating accounts with 2 different keys + auto create_account_2_keys = [&]( const string name, + fc::ecc::private_key active, + fc::ecc::private_key owner ) { + + trx.operations.push_back(make_account()); + account_create_operation op = trx.operations.back().get(); + op.name = name; + op.active = authority(1, public_key_type(active.get_public_key()), 1); + op.owner = authority(1, public_key_type(owner.get_public_key()), 1); + signed_transaction trx; + trx.operations.push_back(op); + db.current_fee_schedule().set_fee( trx.operations.back() ); + set_expiration( db, trx ); + PUSH_TX( db, trx, ~0 ); + + return get_account(name); + }; + + auto update_asset_issuer = [&](asset_object current, + account_object new_issuer) { + asset_update_operation op; + op.issuer = current.issuer; + op.asset_to_update = current.id; + op.new_options = current.options; + op.new_issuer = new_issuer.id; + signed_transaction tx; + tx.operations.push_back( op ); + db.current_fee_schedule().set_fee( tx.operations.back() ); + set_expiration( db, tx ); + PUSH_TX( db, tx, ~0 ); + }; + + // Lambda for updating the issuer on chain using a particular key + auto update_issuer = [&](asset_object asset, + account_object issuer, + account_object new_issuer, + fc::ecc::private_key key) { asset_update_issuer_operation op; op.issuer = issuer.id; @@ -743,31 +772,41 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) tx.operations.push_back( op ); db.current_fee_schedule().set_fee( tx.operations.back() ); set_expiration( db, tx ); - PUSH_TX( db, tx, ~0 ); + sign(tx, key); + PUSH_TX( db, tx, database::skip_transaction_dupe_check ); }; - if( db.head_block_time() <= HARDFORK_CORE_199_TIME ) - { - BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, committee_account, bob ), fc::exception ); - generate_blocks( HARDFORK_CORE_199_TIME ); - while( db.head_block_time() <= HARDFORK_CORE_199_TIME ) - { - generate_block(); - } - } + // Create alice account + fc::ecc::private_key alice_owner = fc::ecc::private_key::regenerate(fc::digest("key1")); + fc::ecc::private_key alice_active = fc::ecc::private_key::regenerate(fc::digest("key2")); + fc::ecc::private_key bob_owner = fc::ecc::private_key::regenerate(fc::digest("key3")); + fc::ecc::private_key bob_active = fc::ecc::private_key::regenerate(fc::digest("key4")); - BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob ), fc::exception ); + // Create accounts + const auto& alice = create_account_2_keys("alice", alice_active, alice_owner); + const auto& bob = create_account_2_keys("bob", bob_active, bob_owner); + + // Create asset + const auto& test = create_user_issued_asset("UPDATEISSUER", alice, 0); + + BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob, alice_owner), fc::exception ); - BOOST_TEST_MESSAGE( "Updating issuer to alice" ); - update_issuer( test, committee_account, alice ); + // Fast Forward to Hardfork time + generate_blocks( HARDFORK_CORE_199_TIME ); BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, committee_account, bob ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, bob, alice, bob_active ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, bob, alice, bob_owner ), fc::exception ); + + BOOST_TEST_MESSAGE( "Can't change issuer with alice's active key" ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob, alice_active ), fc::exception ); + + BOOST_TEST_MESSAGE( "Old method with asset_update needs to fail" ); + GRAPHENE_REQUIRE_THROW( update_asset_issuer( test, bob ), fc::exception ); BOOST_TEST_MESSAGE( "Updating issuer to bob" ); - update_issuer( test, alice, bob ); + update_issuer( test, alice, bob, alice_owner ); } catch( const fc::exception& e ) From 08b1e409e61f8ea67ac78c5e87a5e6010fbd5460 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Tue, 30 Jan 2018 15:52:05 +0100 Subject: [PATCH 05/14] [wallet] add update_asset_issuer call in the cli_wallet --- .../wallet/include/graphene/wallet/wallet.hpp | 17 +++++++++ libraries/wallet/wallet.cpp | 35 ++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 4290d2b172..bcd2510e05 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1038,6 +1038,22 @@ class wallet_api asset_options new_options, bool broadcast = false); + /** Update the issuer of an asset + * Since this call requires the owner authority of the current issuer to sign the transaction, + * a separated operation is used to change the issuer. This call simplifies the use of this action. + * + * @note This operation requires the owner key to be available in the wallet. + * + * @param symbol the name or id of the asset to update + * @param new_issuer if changing the asset's issuer, the name or id of the new issuer. + * null if you wish to remain the issuer of the asset + * @param broadcast true to broadcast the transaction on the network + * @returns the signed transaction updating the asset + */ + signed_transaction update_asset_issuer(string symbol, + string new_issuer, + bool broadcast = false); + /** Update the options specific to a BitAsset. * * BitAssets have some options which are not relevant to other asset types. This operation is used to update those @@ -1656,6 +1672,7 @@ FC_API( graphene::wallet::wallet_api, (get_transaction_id) (create_asset) (update_asset) + (update_asset_issuer) (update_bitasset) (update_asset_feed_producers) (publish_asset_feed) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index e986cff8f4..498e914df8 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1159,10 +1159,7 @@ class wallet_api_impl FC_THROW("No asset with that symbol exists!"); optional new_issuer_account_id; if (new_issuer) - { - account_object new_issuer_account = get_account(*new_issuer); - new_issuer_account_id = new_issuer_account.id; - } + FC_THROW("The use of 'new_issuer' is no longer supported. Please use `update_asset_issuer' instead!"); asset_update_operation update_op; update_op.issuer = asset_to_update->issuer; @@ -1178,6 +1175,29 @@ class wallet_api_impl return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (symbol)(new_issuer)(new_options)(broadcast) ) } + signed_transaction update_asset_issuer(string symbol, + string new_issuer, + bool broadcast /* = false */) + { try { + optional asset_to_update = find_asset(symbol); + if (!asset_to_update) + FC_THROW("No asset with that symbol exists!"); + + account_object new_issuer_account = get_account(new_issuer); + + asset_update_issuer_operation update_issuer; + update_issuer.issuer = asset_to_update->issuer; + update_issuer.asset_to_update = asset_to_update->id; + update_issuer.new_issuer = new_issuer_account.id; + + signed_transaction tx; + tx.operations.push_back( update_issuer ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (symbol)(new_issuer)(broadcast) ) } + signed_transaction update_bitasset(string symbol, bitasset_options new_options, bool broadcast /* = false */) @@ -3302,6 +3322,13 @@ signed_transaction wallet_api::update_asset(string symbol, return my->update_asset(symbol, new_issuer, new_options, broadcast); } +signed_transaction wallet_api::update_asset_issuer(string symbol, + string new_issuer, + bool broadcast /* = false */) +{ + return my->update_asset_issuer(symbol, new_issuer, broadcast); +} + signed_transaction wallet_api::update_bitasset(string symbol, bitasset_options new_options, bool broadcast /* = false */) From 29a3f6841b192ef2ec25e4a26a0d530df21ab49a Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 2 Feb 2018 15:10:28 +0100 Subject: [PATCH 06/14] Refactored some common code into new function --- libraries/chain/asset_evaluator.cpp | 45 ++++++++++++----------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index d1bc4d63e9..bbd4660d1a 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -251,6 +251,23 @@ void_result asset_fund_fee_pool_evaluator::do_apply(const asset_fund_fee_pool_op return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } +static void validate_new_issuer( const database& d, const asset_object& a, account_id_type new_issuer ) +{ try { + FC_ASSERT(d.find_object(new_issuer)); + if( a.is_market_issued() && new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) + { + const asset_object& backing = a.bitasset_data(d).options.short_backing_asset(d); + if( backing.is_market_issued() ) + { + const asset_object& backing_backing = backing.bitasset_data(d).options.short_backing_asset(d); + FC_ASSERT( backing_backing.get_id() == asset_id_type(), + "May not create a blockchain-controlled market asset which is not backed by CORE."); + } else + FC_ASSERT( backing.get_id() == asset_id_type(), + "May not create a blockchain-controlled market asset which is not backed by CORE."); + } +} FC_CAPTURE_AND_RETHROW( (a)(new_issuer) ) } + void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) { try { database& d = db(); @@ -264,19 +281,7 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) { FC_ASSERT( d.head_block_time() < HARDFORK_CORE_199_TIME, "Since Hardfork #199, updating issuer requires the use of asset_change_issuer_operation."); - FC_ASSERT(d.find_object(*o.new_issuer)); - if( a.is_market_issued() && *o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) - { - const asset_object& backing = a.bitasset_data(d).options.short_backing_asset(d); - if( backing.is_market_issued() ) - { - const asset_object& backing_backing = backing.bitasset_data(d).options.short_backing_asset(d); - FC_ASSERT( backing_backing.get_id() == asset_id_type(), - "May not create a blockchain-controlled market asset which is not backed by CORE."); - } else - FC_ASSERT( backing.get_id() == asset_id_type(), - "May not create a blockchain-controlled market asset which is not backed by CORE."); - } + validate_new_issuer( d, a, *o.new_issuer ); } if( (d.head_block_time() < HARDFORK_572_TIME) || (a.dynamic_asset_data_id(d).current_supply != 0) ) @@ -336,19 +341,7 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer const asset_object& a = o.asset_to_update(d); - FC_ASSERT(d.find_object(o.new_issuer)); - if( a.is_market_issued() && o.new_issuer == GRAPHENE_COMMITTEE_ACCOUNT ) - { - const asset_object& backing = a.bitasset_data(d).options.short_backing_asset(d); - if( backing.is_market_issued() ) - { - const asset_object& backing_backing = backing.bitasset_data(d).options.short_backing_asset(d); - FC_ASSERT( backing_backing.get_id() == asset_id_type(), - "May not create a blockchain-controlled market asset which is not backed by CORE."); - } else - FC_ASSERT( backing.get_id() == asset_id_type(), - "May not create a blockchain-controlled market asset which is not backed by CORE."); - } + validate_new_issuer( d, a, o.new_issuer ); asset_to_update = &a; FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); From ff4a35b73938acfa82259f467a40bbe8f30a4e57 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Fri, 9 Feb 2018 13:52:40 +0100 Subject: [PATCH 07/14] fix assert comment --- libraries/chain/asset_evaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index bbd4660d1a..a6819895c3 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -280,7 +280,7 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) if( o.new_issuer ) { FC_ASSERT( d.head_block_time() < HARDFORK_CORE_199_TIME, - "Since Hardfork #199, updating issuer requires the use of asset_change_issuer_operation."); + "Since Hardfork #199, updating issuer requires the use of asset_update_issuer_operation."); validate_new_issuer( d, a, *o.new_issuer ); } From f5c2e0a3006f9d61c63fae1467a31dc6a9737238 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Fri, 9 Feb 2018 13:54:16 +0100 Subject: [PATCH 08/14] fix documentation of update_asset_issuer call in the wallet --- libraries/wallet/include/graphene/wallet/wallet.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index bcd2510e05..d949b6951a 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1046,7 +1046,6 @@ class wallet_api * * @param symbol the name or id of the asset to update * @param new_issuer if changing the asset's issuer, the name or id of the new issuer. - * null if you wish to remain the issuer of the asset * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction updating the asset */ From 4a91978a486dc201fe25895302bc9fb519b38ded Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Mon, 12 Feb 2018 17:06:13 +0100 Subject: [PATCH 09/14] Fix assert message --- libraries/chain/asset_evaluator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index a6819895c3..ac7b2bc418 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -296,7 +296,7 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) "Flag change is forbidden by issuer permissions"); asset_to_update = &a; - FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + FC_ASSERT( o.issuer == a.issuer, "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); const auto& chain_parameters = d.get_global_properties().parameters; @@ -344,7 +344,7 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer validate_new_issuer( d, a, o.new_issuer ); asset_to_update = &a; - FC_ASSERT( o.issuer == a.issuer, "", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + FC_ASSERT( o.issuer == a.issuer, "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); if( d.head_block_time() < HARDFORK_CORE_199_TIME ) { // TODO: remove after HARDFORK_CORE_199_TIME has passed From 2cfef3ed0c2eecfd4588540051d6bc14e29a3f42 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Tue, 13 Feb 2018 13:48:05 +0100 Subject: [PATCH 10/14] [tests] properly reload objects after new blocks have been generated and use const references --- tests/tests/operation_tests.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index bbd82fb56c..616824b98b 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -744,8 +744,8 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) return get_account(name); }; - auto update_asset_issuer = [&](asset_object current, - account_object new_issuer) { + auto update_asset_issuer = [&](const asset_object& current, + const account_object& new_issuer) { asset_update_operation op; op.issuer = current.issuer; op.asset_to_update = current.id; @@ -759,10 +759,10 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) }; // Lambda for updating the issuer on chain using a particular key - auto update_issuer = [&](asset_object asset, - account_object issuer, - account_object new_issuer, - fc::ecc::private_key key) + auto update_issuer = [&](const asset_object& asset, + const account_object& issuer, + const account_object& new_issuer, + const fc::ecc::private_key& key) { asset_update_issuer_operation op; op.issuer = issuer.id; @@ -785,28 +785,30 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) // Create accounts const auto& alice = create_account_2_keys("alice", alice_active, alice_owner); const auto& bob = create_account_2_keys("bob", bob_active, bob_owner); + const account_id_type alice_id = alice.id; + const account_id_type bob_id = bob.id; // Create asset - const auto& test = create_user_issued_asset("UPDATEISSUER", alice, 0); + const auto& test = create_user_issued_asset("UPDATEISSUER", alice_id(db), 0); BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob, alice_owner), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, alice_id(db), bob_id(db), alice_owner), fc::exception ); // Fast Forward to Hardfork time generate_blocks( HARDFORK_CORE_199_TIME ); BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, bob, alice, bob_active ), fc::exception ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, bob, alice, bob_owner ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, bob_id(db), alice_id(db), bob_active ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, bob_id(db), alice_id(db), bob_owner ), fc::exception ); BOOST_TEST_MESSAGE( "Can't change issuer with alice's active key" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, alice, bob, alice_active ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test, alice_id(db), bob_id(db), alice_active ), fc::exception ); BOOST_TEST_MESSAGE( "Old method with asset_update needs to fail" ); - GRAPHENE_REQUIRE_THROW( update_asset_issuer( test, bob ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_asset_issuer( test, bob_id(db) ), fc::exception ); BOOST_TEST_MESSAGE( "Updating issuer to bob" ); - update_issuer( test, alice, bob, alice_owner ); + update_issuer( test, alice_id(db), bob_id(db), alice_owner ); } catch( const fc::exception& e ) From 53bb08bf2cb6bcd5c7f7550179715568e90b16ae Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Tue, 13 Feb 2018 15:28:12 +0100 Subject: [PATCH 11/14] [wallet] ensure that asset_update works until the hard fork --- libraries/wallet/wallet.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 498e914df8..3dbc5c6bf5 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -1159,7 +1160,12 @@ class wallet_api_impl FC_THROW("No asset with that symbol exists!"); optional new_issuer_account_id; if (new_issuer) - FC_THROW("The use of 'new_issuer' is no longer supported. Please use `update_asset_issuer' instead!"); + { + FC_ASSERT( _remote_db->get_dynamic_global_properties().time < HARDFORK_CORE_199_TIME, + "The use of 'new_issuer' is no longer supported. Please use `update_asset_issuer' instead!"); + account_object new_issuer_account = get_account(*new_issuer); + new_issuer_account_id = new_issuer_account.id; + } asset_update_operation update_op; update_op.issuer = asset_to_update->issuer; From 76de8f4a708a70b478eecf5a4bdef6a2e3d77cb2 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Thu, 15 Feb 2018 17:33:40 +0100 Subject: [PATCH 12/14] [tests] add test to verify new issuer, also modify to reload objects --- tests/tests/operation_tests.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 616824b98b..a08a5a47dc 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -759,7 +759,7 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) }; // Lambda for updating the issuer on chain using a particular key - auto update_issuer = [&](const asset_object& asset, + auto update_issuer = [&](const asset_id_type asset_id, const account_object& issuer, const account_object& new_issuer, const fc::ecc::private_key& key) @@ -767,7 +767,7 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) asset_update_issuer_operation op; op.issuer = issuer.id; op.new_issuer = new_issuer.id; - op.asset_to_update = asset.id; + op.asset_to_update = asset_id; signed_transaction tx; tx.operations.push_back( op ); db.current_fee_schedule().set_fee( tx.operations.back() ); @@ -790,25 +790,28 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) // Create asset const auto& test = create_user_issued_asset("UPDATEISSUER", alice_id(db), 0); + const asset_id_type test_id = test.id; BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, alice_id(db), bob_id(db), alice_owner), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test_id, alice_id(db), bob_id(db), alice_owner), fc::exception ); // Fast Forward to Hardfork time generate_blocks( HARDFORK_CORE_199_TIME ); BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, bob_id(db), alice_id(db), bob_active ), fc::exception ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, bob_id(db), alice_id(db), bob_owner ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test_id, bob_id(db), alice_id(db), bob_active ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test_id, bob_id(db), alice_id(db), bob_owner ), fc::exception ); BOOST_TEST_MESSAGE( "Can't change issuer with alice's active key" ); - GRAPHENE_REQUIRE_THROW( update_issuer( test, alice_id(db), bob_id(db), alice_active ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_issuer( test_id, alice_id(db), bob_id(db), alice_active ), fc::exception ); BOOST_TEST_MESSAGE( "Old method with asset_update needs to fail" ); - GRAPHENE_REQUIRE_THROW( update_asset_issuer( test, bob_id(db) ), fc::exception ); + GRAPHENE_REQUIRE_THROW( update_asset_issuer( test_id(db), bob_id(db) ), fc::exception ); BOOST_TEST_MESSAGE( "Updating issuer to bob" ); - update_issuer( test, alice_id(db), bob_id(db), alice_owner ); + update_issuer( test_id, alice_id(db), bob_id(db), alice_owner ); + + BOOST_CHECK(test_id(db).issuer == bob_id); } catch( const fc::exception& e ) From d2f67c3cfb1af781fb96fa2c2fb21a8c5f2f7086 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Thu, 15 Feb 2018 17:44:22 +0100 Subject: [PATCH 13/14] [tests] add unit test for the hf_xxx_visitor via proposals --- tests/tests/operation_tests.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index a08a5a47dc..5dab0a9476 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -776,6 +776,33 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) PUSH_TX( db, tx, database::skip_transaction_dupe_check ); }; + auto update_issuer_proposal = [&](const asset_id_type asset_id, + const account_object& issuer, + const account_object& new_issuer, + const fc::ecc::private_key& key) + { + asset_update_issuer_operation op; + op.issuer = issuer.id; + op.new_issuer = new_issuer.id; + op.asset_to_update = asset_id; + + const auto& curfees = *db.get_global_properties().parameters.current_fees; + const auto& proposal_create_fees = curfees.get(); + proposal_create_operation prop; + prop.fee_paying_account = issuer.id; + prop.proposed_ops.emplace_back( op ); + prop.expiration_time = db.head_block_time() + fc::days(1); + prop.fee = asset( proposal_create_fees.fee + proposal_create_fees.price_per_kbyte ); + + signed_transaction tx; + tx.operations.push_back( prop ); + db.current_fee_schedule().set_fee( tx.operations.back() ); + set_expiration( db, tx ); + sign( tx, key ); + PUSH_TX( db, tx ); + + }; + // Create alice account fc::ecc::private_key alice_owner = fc::ecc::private_key::regenerate(fc::digest("key1")); fc::ecc::private_key alice_active = fc::ecc::private_key::regenerate(fc::digest("key2")); @@ -795,9 +822,15 @@ BOOST_AUTO_TEST_CASE( update_uia_issuer ) BOOST_TEST_MESSAGE( "can't use this operation before the hardfork" ); GRAPHENE_REQUIRE_THROW( update_issuer( test_id, alice_id(db), bob_id(db), alice_owner), fc::exception ); + BOOST_TEST_MESSAGE( "can't use this operation before the hardfork (even if wrapped into a proposal)" ); + GRAPHENE_REQUIRE_THROW( update_issuer_proposal( test_id, alice_id(db), bob_id(db), alice_owner), fc::exception ); + // Fast Forward to Hardfork time generate_blocks( HARDFORK_CORE_199_TIME ); + BOOST_TEST_MESSAGE( "After hardfork time, proposal goes through (but doesn't execute yet)" ); + update_issuer_proposal( test_id, alice_id(db), bob_id(db), alice_owner); + BOOST_TEST_MESSAGE( "Can't change issuer if not my asset" ); GRAPHENE_REQUIRE_THROW( update_issuer( test_id, bob_id(db), alice_id(db), bob_active ), fc::exception ); GRAPHENE_REQUIRE_THROW( update_issuer( test_id, bob_id(db), alice_id(db), bob_owner ), fc::exception ); From e2be061fcd247deb298fdea4a7221d8c69d11c07 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Tue, 27 Feb 2018 15:49:33 +0100 Subject: [PATCH 14/14] fix merge fuckups --- libraries/chain/asset_evaluator.cpp | 8 +++++-- .../graphene/chain/asset_evaluator.hpp | 23 +++++++++++++------ .../graphene/chain/protocol/asset_ops.hpp | 1 - .../graphene/chain/protocol/fee_schedule.hpp | 1 + .../graphene/chain/protocol/operations.hpp | 4 ++-- libraries/chain/proposal_evaluator.cpp | 1 + libraries/chain/protocol/asset_ops.cpp | 2 +- 7 files changed, 27 insertions(+), 13 deletions(-) diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 823b372ab7..4ff392648f 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -296,7 +296,9 @@ void_result asset_update_evaluator::do_evaluate(const asset_update_operation& o) "Flag change is forbidden by issuer permissions"); asset_to_update = &a; - FC_ASSERT( o.issuer == a.issuer, "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + FC_ASSERT( o.issuer == a.issuer, + "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", + ("o.issuer", o.issuer)("a.issuer", a.issuer) ); const auto& chain_parameters = d.get_global_properties().parameters; @@ -344,7 +346,9 @@ void_result asset_update_issuer_evaluator::do_evaluate(const asset_update_issuer validate_new_issuer( d, a, o.new_issuer ); asset_to_update = &a; - FC_ASSERT( o.issuer == a.issuer, "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", ("o.issuer", o.issuer)("a.issuer", a.issuer) ); + FC_ASSERT( o.issuer == a.issuer, + "Incorrect issuer for asset! (${o.issuer} != ${a.issuer})", + ("o.issuer", o.issuer)("a.issuer", a.issuer) ); if( d.head_block_time() < HARDFORK_CORE_199_TIME ) { // TODO: remove after HARDFORK_CORE_199_TIME has passed diff --git a/libraries/chain/include/graphene/chain/asset_evaluator.hpp b/libraries/chain/include/graphene/chain/asset_evaluator.hpp index 49af147c89..04280b3a0e 100644 --- a/libraries/chain/include/graphene/chain/asset_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/asset_evaluator.hpp @@ -163,16 +163,25 @@ namespace graphene { namespace chain { void_result do_apply( const asset_claim_fees_operation& o ); }; - namespace impl { // TODO: remove after HARDFORK_CORE_199_TIME has passed - class hf_199_visitor { + class asset_claim_pool_evaluator : public evaluator + { + public: + typedef asset_claim_pool_operation operation_type; + + void_result do_evaluate( const asset_claim_pool_operation& o ); + void_result do_apply( const asset_claim_pool_operation& o ); + }; + + namespace impl { + class hf_188_visitor { // TODO: remove after HARDFORK_CORE_188_TIME has passed public: typedef void result_type; template void operator()( const T& v )const {} - void operator()( const graphene::chain::asset_update_issuer_operation& v )const { - FC_ASSERT( false, "Not allowed until hardfork 199" ); + void operator()( const graphene::chain::asset_claim_pool_operation& v )const { + FC_ASSERT( false, "Not allowed until hardfork 188" ); } void operator()( const graphene::chain::proposal_create_operation& v )const { @@ -181,15 +190,15 @@ namespace graphene { namespace chain { } }; - class hf_188_visitor { + class hf_199_visitor { // TODO: remove after HARDFORK_CORE_199_TIME has passed public: typedef void result_type; template void operator()( const T& v )const {} - void operator()( const graphene::chain::asset_claim_pool_operation& v )const { - FC_ASSERT( false, "Not allowed until hardfork 188" ); + void operator()( const graphene::chain::asset_update_issuer_operation& v )const { + FC_ASSERT( false, "Not allowed until hardfork 199" ); } void operator()( const graphene::chain::proposal_create_operation& v )const { diff --git a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp index 0f5d858885..9e7512b090 100644 --- a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp +++ b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp @@ -442,7 +442,6 @@ namespace graphene { namespace chain { void validate()const; }; - /** /** * @brief Update issuer of an asset * @ingroup operations diff --git a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp index cbf98aee80..a08ee98a2c 100644 --- a/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp +++ b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp @@ -92,6 +92,7 @@ namespace graphene { namespace chain { } }; + template<> class fee_helper { public: const asset_claim_pool_operation::fee_parameters_type& cget(const flat_set& parameters)const diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 7536f4254c..de2cfa7fd9 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -94,8 +94,8 @@ namespace graphene { namespace chain { fba_distribute_operation, // VIRTUAL bid_collateral_operation, execute_bid_operation, // VIRTUAL - asset_update_issuer_operation, - asset_claim_pool_operation + asset_claim_pool_operation, + asset_update_issuer_operation > operation; /// @} // operations group diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 57061838d3..b48e8ee34f 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -82,6 +82,7 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati { // TODO: remove after HARDFORK_CORE_199_TIME has passed graphene::chain::impl::hf_199_visitor hf_199; hf_199( o ); + } if( d.head_block_time() < HARDFORK_CORE_188_TIME ) { // TODO: remove after HARDFORK_CORE_188_TIME has passed diff --git a/libraries/chain/protocol/asset_ops.cpp b/libraries/chain/protocol/asset_ops.cpp index 939a057901..c6e53fb216 100644 --- a/libraries/chain/protocol/asset_ops.cpp +++ b/libraries/chain/protocol/asset_ops.cpp @@ -126,7 +126,7 @@ void asset_update_operation::validate()const void asset_update_issuer_operation::validate()const { FC_ASSERT( fee.amount >= 0 ); - FC_ASSERT(issuer != new_issuer); + FC_ASSERT( issuer != new_issuer ); } share_type asset_update_operation::calculate_fee(const asset_update_operation::fee_parameters_type& k)const