diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index 7c007a8e..efea3ef7 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -9,7 +9,10 @@ namespace graphene { namespace chain { asset fee; account_id_type owner_account; - std::string url; + std::string url; + vesting_balance_id_type deposit; + public_key_type signing_key; + vesting_balance_id_type pay_vb; account_id_type fee_payer()const { return owner_account; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } @@ -22,7 +25,10 @@ namespace graphene { namespace chain { asset fee; son_id_type son_id; account_id_type owner_account; - std::string new_url; + optional new_url; + optional new_deposit; + optional new_signing_key; + optional new_pay_vb; account_id_type fee_payer()const { return owner_account; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } @@ -42,11 +48,13 @@ namespace graphene { namespace chain { } } // namespace graphene::chain -FC_REFLECT( graphene::chain::son_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_create_operation, (fee)(owner_account)(url) ) +FC_REFLECT(graphene::chain::son_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT(graphene::chain::son_create_operation, (fee)(owner_account)(url)(deposit)(signing_key) + (pay_vb) ) -FC_REFLECT( graphene::chain::son_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_update_operation, (fee)(son_id)(owner_account)(new_url) ) +FC_REFLECT(graphene::chain::son_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT(graphene::chain::son_update_operation, (fee)(son_id)(owner_account)(new_url)(new_deposit) + (new_signing_key)(new_pay_vb) ) -FC_REFLECT( graphene::chain::son_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_delete_operation, (fee)(son_id)(owner_account) ) +FC_REFLECT(graphene::chain::son_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT(graphene::chain::son_delete_operation, (fee)(son_id)(owner_account) ) diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 114b27cd..92d21b31 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -17,10 +17,13 @@ namespace graphene { namespace chain { static const uint8_t space_id = protocol_ids; static const uint8_t type_id = son_object_type; - account_id_type son_member_account; - vote_id_type vote_id; - uint64_t total_votes = 0; - string url; + account_id_type son_member_account; + vote_id_type vote_id; + uint64_t total_votes = 0; + string url; + vesting_balance_id_type deposit; + public_key_type signing_key; + vesting_balance_id_type pay_vb; }; struct by_account; @@ -43,4 +46,4 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), - (son_member_account)(vote_id)(total_votes)(url) ) + (son_member_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb) ) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 2aa2f6e6..8ac0cb24 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -22,8 +22,11 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) const auto& new_son_object = db().create( [&]( son_object& obj ){ obj.son_member_account = op.owner_account; - obj.vote_id = vote_id; - obj.url = op.url; + obj.vote_id = vote_id; + obj.url = op.url; + obj.deposit = op.deposit; + obj.signing_key = op.signing_key; + obj.pay_vb = op.pay_vb; }); return new_son_object.id; } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -44,7 +47,10 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) if(itr != idx.end()) { db().modify(*itr, [&op](son_object &so) { - so.url = op.new_url; + if(op.new_url.valid()) so.url = *op.new_url; + if(op.new_deposit.valid()) so.deposit = *op.new_deposit; + if(op.new_signing_key.valid()) so.signing_key = *op.new_signing_key; + if(op.new_pay_vb.valid()) so.pay_vb = *op.new_pay_vb; }); } return op.son_id; diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index d8a0f61c..75986ca7 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -8,100 +8,9 @@ using namespace graphene::chain; using namespace graphene::chain::test; -class test_create_son_member_evaluator: public create_son_evaluator { -public: - test_create_son_member_evaluator( database& link_db ): - ptr_trx_state( new transaction_evaluation_state( &link_db ) ) - { - trx_state = ptr_trx_state.get(); - } - std::unique_ptr ptr_trx_state; -}; - -class test_update_son_member_evaluator: public update_son_evaluator { -public: - test_update_son_member_evaluator( database& link_db ): - ptr_trx_state( new transaction_evaluation_state( &link_db ) ) - { - trx_state = ptr_trx_state.get(); - } - std::unique_ptr ptr_trx_state; -}; - -class test_delete_son_member_evaluator: public delete_son_evaluator { -public: - test_delete_son_member_evaluator( database& link_db ): - ptr_trx_state( new transaction_evaluation_state( &link_db ) ) - { - trx_state = ptr_trx_state.get(); - } - std::unique_ptr ptr_trx_state; -}; - BOOST_FIXTURE_TEST_SUITE( son_operation_tests, database_fixture ) BOOST_AUTO_TEST_CASE( create_son_test ) { - generate_blocks( HARDFORK_SON_TIME ); - while( db.head_block_time() <= HARDFORK_SON_TIME ) - { - generate_block(); - } - std::string test_url = "https://create_son_test"; - test_create_son_member_evaluator test_eval( db ); - son_create_operation op; - op.owner_account = account_id_type(1); - op.url = test_url; - - BOOST_CHECK_NO_THROW( test_eval.do_evaluate( op ) ); - auto id = test_eval.do_apply( op ); - const auto& idx = db.get_index_type().indices().get(); - - BOOST_REQUIRE( idx.size() == 1 ); - - auto obj = idx.find( op.owner_account ); - BOOST_REQUIRE( obj != idx.end() ); - BOOST_CHECK( obj->url == test_url ); - BOOST_CHECK( id == obj->id ); -} - -BOOST_AUTO_TEST_CASE( update_son_test ){ - INVOKE(create_son_test); - std::string new_url = "https://anewurl.com"; - test_update_son_member_evaluator test_eval( db ); - son_update_operation op; - op.owner_account = account_id_type(1); - op.new_url = new_url; - op.son_id = son_id_type(0); - - BOOST_CHECK_NO_THROW( test_eval.do_evaluate( op ) ); - auto id = test_eval.do_apply( op ); - const auto& idx = db.get_index_type().indices().get(); - - BOOST_REQUIRE( idx.size() == 1 ); - - auto obj = idx.find( op.owner_account ); - BOOST_REQUIRE( obj != idx.end() ); - BOOST_CHECK( obj->url == new_url ); - BOOST_CHECK( id == obj->id ); -} - -BOOST_AUTO_TEST_CASE( delete_son_test ) { - INVOKE(create_son_test); - test_delete_son_member_evaluator test_eval( db ); - - son_delete_operation delete_op; - delete_op.owner_account = account_id_type(1); - delete_op.son_id = son_id_type(0); - - BOOST_CHECK_NO_THROW( test_eval.do_evaluate( delete_op ) ); - test_eval.do_apply( delete_op ); - - const auto& idx = db.get_index_type().indices().get(); - BOOST_REQUIRE( idx.empty() ); -} - -BOOST_AUTO_TEST_CASE( update_delete_not_own ) { // fee payer needs to be the son object owner -try { generate_blocks(HARDFORK_SON_TIME); while (db.head_block_time() <= HARDFORK_SON_TIME) { generate_block(); @@ -114,28 +23,119 @@ try { upgrade_to_lifetime_member(alice); upgrade_to_lifetime_member(bob); + transfer( committee_account, alice_id, asset( 100000 ) ); + transfer( committee_account, bob_id, asset( 100000 ) ); + set_expiration(db, trx); std::string test_url = "https://create_son_test"; + // create deposit vesting + vesting_balance_id_type deposit; + { + vesting_balance_create_operation op; + op.creator = alice_id; + op.owner = alice_id; + op.amount = asset(10); + op.balance_type = vesting_balance_type::unspecified; + + trx.operations.push_back(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + deposit = ptx.operation_results[0].get(); + } + // create payment vesting + vesting_balance_id_type payment; + { + vesting_balance_create_operation op; + op.creator = alice_id; + op.owner = alice_id; + op.amount = asset(10); + op.balance_type = vesting_balance_type::unspecified; + + trx.operations.push_back(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + payment = ptx.operation_results[0].get(); + } + // alice became son { son_create_operation op; op.owner_account = alice_id; op.url = test_url; + op.deposit = deposit; + op.pay_vb = payment; + op.signing_key = alice_public_key; trx.operations.push_back(op); sign(trx, alice_private_key); PUSH_TX(db, trx, ~0); } generate_block(); - set_expiration(db, trx); - trx.clear(); - const auto& idx = db.get_index_type().indices().get(); BOOST_REQUIRE( idx.size() == 1 ); auto obj = idx.find( alice_id ); BOOST_REQUIRE( obj != idx.end() ); BOOST_CHECK( obj->url == test_url ); + BOOST_CHECK( obj->signing_key == alice_public_key ); + BOOST_CHECK( obj->deposit.instance == deposit.instance.value ); + BOOST_CHECK( obj->pay_vb.instance == payment.instance.value ); +} + +BOOST_AUTO_TEST_CASE( update_son_test ) { + + INVOKE(create_son_test); + GET_ACTOR(alice); + + std::string new_url = "https://anewurl.com"; + + { + son_update_operation op; + op.owner_account = alice_id; + op.new_url = new_url; + op.son_id = son_id_type(0); + + trx.operations.push_back(op); + sign(trx, alice_private_key); + PUSH_TX(db, trx, ~0); + } + generate_block(); + + const auto& idx = db.get_index_type().indices().get(); + BOOST_REQUIRE( idx.size() == 1 ); + auto obj = idx.find( alice_id ); + BOOST_REQUIRE( obj != idx.end() ); + BOOST_CHECK( obj->url == new_url ); +} + +BOOST_AUTO_TEST_CASE( delete_son_test ) { + + INVOKE(create_son_test); + GET_ACTOR(alice); + + { + son_delete_operation op; + op.owner_account = alice_id; + op.son_id = son_id_type(0); + + trx.operations.push_back(op); + sign(trx, alice_private_key); + PUSH_TX(db, trx, ~0); + } + generate_block(); + + const auto& idx = db.get_index_type().indices().get(); + BOOST_REQUIRE( idx.empty() ); +} + +BOOST_AUTO_TEST_CASE( update_delete_not_own ) { // fee payer needs to be the son object owner +try { + + INVOKE(create_son_test); + GET_ACTOR(alice); + GET_ACTOR(bob); // bob tries to update a son object he dont own { @@ -153,7 +153,8 @@ try { set_expiration(db, trx); trx.clear(); - obj = idx.find( alice_id ); + const auto& idx = db.get_index_type().indices().get(); + auto obj = idx.find( alice_id ); BOOST_REQUIRE( obj != idx.end() ); // not changing BOOST_CHECK( obj->url == "https://create_son_test" ); @@ -175,12 +176,10 @@ try { // not deleting BOOST_REQUIRE( obj != idx.end() ); BOOST_CHECK( obj->son_member_account.instance == alice_id.instance); - } catch (fc::exception &e) { edump((e.to_detail_string())); throw; } -} -BOOST_AUTO_TEST_SUITE_END() +} BOOST_AUTO_TEST_SUITE_END()