From 988a1771ede12b2dc272fd6e25bb0f044b448dbb Mon Sep 17 00:00:00 2001 From: PixelPlex Date: Fri, 26 Jul 2019 13:05:35 +0300 Subject: [PATCH 01/34] Added SON object --- libraries/app/api.cpp | 7 +- libraries/app/database_api.cpp | 23 +++++++ libraries/app/impacted.cpp | 6 ++ .../app/include/graphene/app/database_api.hpp | 16 +++++ libraries/chain/CMakeLists.txt | 2 + .../son_operations_evaluator.cpp | 45 +++++++++++++ libraries/chain/db_init.cpp | 9 +++ libraries/chain/db_notify.cpp | 11 +++ .../graphene/chain/btc-sidechain/son.hpp | 46 +++++++++++++ .../chain/btc-sidechain/son_operations.hpp | 35 ++++++++++ .../son_operations_evaluator.hpp | 25 +++++++ .../graphene/chain/global_property_object.hpp | 2 + .../graphene/chain/protocol/account.hpp | 3 + .../graphene/chain/protocol/operations.hpp | 6 +- .../include/graphene/chain/protocol/types.hpp | 4 ++ .../include/graphene/chain/protocol/vote.hpp | 3 +- libraries/net/CMakeLists.txt | 2 +- .../wallet/include/graphene/wallet/wallet.hpp | 23 +++++++ libraries/wallet/wallet.cpp | 42 ++++++++++++ tests/CMakeLists.txt | 4 ++ tests/btc_sidechain_tests/main.cpp | 17 +++++ .../son_operations_tests.cpp | 67 +++++++++++++++++++ tests/common/genesis_file_util.hpp | 2 +- 23 files changed, 395 insertions(+), 5 deletions(-) create mode 100644 libraries/chain/btc-sidechain/son_operations_evaluator.cpp create mode 100644 libraries/chain/include/graphene/chain/btc-sidechain/son.hpp create mode 100644 libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp create mode 100644 libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp create mode 100644 tests/btc_sidechain_tests/main.cpp create mode 100644 tests/btc_sidechain_tests/son_operations_tests.cpp diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 0cb6ae0de..9d3148dbb 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -432,7 +432,12 @@ namespace graphene { namespace app { } case balance_object_type:{ /** these are free from any accounts */ break; - } + } case son_member_object_type:{ + const auto& son_object = dynamic_cast(obj); + assert( son_object != nullptr ); + accounts.insert( son_object->son_member_account ); + break; + } case sport_object_type: case event_group_object_type: case event_object_type: diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 3f95a8c16..d6bffe04e 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -136,6 +136,9 @@ class database_api_impl : public std::enable_shared_from_this fc::optional get_committee_member_by_account(account_id_type account)const; map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; + // SON members + fc::optional get_son_member_by_account(account_id_type account)const; + // Votes vector lookup_vote_ids( const vector& votes )const; @@ -1577,6 +1580,26 @@ map database_api_impl::lookup_committee_member return committee_members_by_account_name; } +////////////////////////////////////////////////////////////////////// +// // +// SON members // +// // +////////////////////////////////////////////////////////////////////// + +fc::optional database_api::get_son_member_by_account(account_id_type account)const +{ + return my->get_son_member_by_account( account ); +} + +fc::optional database_api_impl::get_son_member_by_account(account_id_type account) const +{ + const auto& idx = _db.get_index_type().indices().get(); + auto itr = idx.find(account); + if( itr != idx.end() ) + return *itr; + return {}; +} + ////////////////////////////////////////////////////////////////////// // // // Votes // diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 9d64cf11b..1b7797ffd 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -282,6 +282,12 @@ struct get_impacted_account_visitor _impacted.insert( op.affiliate ); } void operator()( const affiliate_referral_payout_operation& op ) { } + void operator()( const son_member_create_operation& op ){ + _impacted.insert( op.owner_account ); + } + void operator()( const son_member_delete_operation& op ){ + _impacted.insert( op.owner_account ); + } }; void operation_get_impacted_accounts( const operation& op, flat_set& result ) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 3fac4b5f0..0500023e3 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -44,6 +44,8 @@ #include #include +#include + #include #include #include @@ -546,6 +548,17 @@ class database_api */ map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; + ///////////////// + // SON members // + ///////////////// + + /** + * @brief Get the son_member owned by a given account + * @param account The ID of the account whose son_member should be retrieved + * @return The son_member object, or null if the account does not have a son_member + */ + fc::optional get_son_member_by_account(account_id_type account)const; + /// WORKERS @@ -757,6 +770,9 @@ FC_API(graphene::app::database_api, (get_committee_member_by_account) (lookup_committee_member_accounts) + // SON members + (get_son_member_by_account) + // workers (get_workers_by_account) // Votes diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index a328cf1f1..c7c8e7f81 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -111,6 +111,8 @@ add_library( graphene_chain affiliate_payout.cpp + btc-sidechain/son_operations_evaluator.cpp + ${HEADERS} ${PROTOCOL_HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp" diff --git a/libraries/chain/btc-sidechain/son_operations_evaluator.cpp b/libraries/chain/btc-sidechain/son_operations_evaluator.cpp new file mode 100644 index 000000000..9ce855b3d --- /dev/null +++ b/libraries/chain/btc-sidechain/son_operations_evaluator.cpp @@ -0,0 +1,45 @@ +#include + +#include +#include + +namespace graphene { namespace chain { + +void_result create_son_member_evaluator::do_evaluate(const son_member_create_operation& op) +{ try{ + FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON."); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +object_id_type create_son_member_evaluator::do_apply(const son_member_create_operation& op) +{ try { + vote_id_type vote_id; + db().modify(db().get_global_properties(), [&vote_id](global_property_object& p) { + vote_id = get_next_vote_id(p, vote_id_type::son); + }); + + const auto& new_son_object = db().create( [&]( son_member_object& obj ){ + obj.son_member_account = op.owner_account; + obj.vote_id = vote_id; + obj.url = op.url; + }); + return new_son_object.id; +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result delete_son_member_evaluator::do_evaluate(const son_member_delete_operation& op) +{ try { + database& d = db(); + const auto& idx = d.get_index_type().indices().get(); + FC_ASSERT( idx.find(op.owner_account) != idx.end() ); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result delete_son_member_evaluator::do_apply(const son_member_delete_operation& op) +{ try { + const auto& idx = db().get_index_type().indices().get(); + db().remove(*idx.find(op.owner_account)); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +} } // namespace graphene::chain + \ No newline at end of file diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index d58c68f75..d3f797966 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -77,8 +77,12 @@ #include #include +#include + #include +#include + #include #include #include @@ -237,6 +241,9 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + + register_evaluator(); + register_evaluator(); } void database::initialize_indexes() @@ -301,6 +308,8 @@ void database::initialize_indexes() //add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); + + add_index< primary_index >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 53ec524df..2f3d89c3a 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -269,6 +269,12 @@ struct get_impacted_account_visitor _impacted.insert( op.affiliate ); } void operator()( const affiliate_referral_payout_operation& op ) { } + void operator()( const son_member_create_operation& op ) { + _impacted.insert( op.owner_account ); + } + void operator()( const son_member_delete_operation& op ) { + _impacted.insert( op.owner_account ); + } }; void operation_get_impacted_accounts( const operation& op, flat_set& result ) @@ -357,6 +363,11 @@ void get_relevant_accounts( const object* obj, flat_set& accoun } case balance_object_type:{ /** these are free from any accounts */ break; + } case son_member_object_type:{ + const auto& son_object = dynamic_cast(obj); + assert( son_object != nullptr ); + accounts.insert( son_object->son_member_account ); + break; } } } diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son.hpp b/libraries/chain/include/graphene/chain/btc-sidechain/son.hpp new file mode 100644 index 000000000..6b6d7bac7 --- /dev/null +++ b/libraries/chain/include/graphene/chain/btc-sidechain/son.hpp @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include + +namespace graphene { namespace chain { + using namespace graphene::db; + + /** + * @class son_member_object + * @brief tracks information about a son_member account. + * @ingroup object + */ + class son_member_object : public abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = son_member_object_type; + + account_id_type son_member_account; + vote_id_type vote_id; + uint64_t total_votes = 0; + string url; + }; + + struct by_account; + struct by_vote_id; + using son_member_multi_index_type = multi_index_container< + son_member_object, + indexed_by< + ordered_unique< tag, + member + >, + ordered_unique< tag, + member + >, + ordered_unique< tag, + member + > + > + >; + using son_member_index = generic_index; +} } // graphene::chain + +FC_REFLECT_DERIVED( graphene::chain::son_member_object, (graphene::db::object), + (son_member_account)(vote_id)(total_votes)(url) ) diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp b/libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp new file mode 100644 index 000000000..700dc5fcd --- /dev/null +++ b/libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp @@ -0,0 +1,35 @@ +#pragma once +#include + +namespace graphene { namespace chain { + + struct son_member_create_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 0; }; + + asset fee; + account_id_type owner_account; + std::string url; + + account_id_type fee_payer()const { return owner_account; } + share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + }; + + struct son_member_delete_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 0; }; + + asset fee; + account_id_type owner_account; + + account_id_type fee_payer()const { return owner_account; } + share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + }; + +} } // namespace graphene::chain + +FC_REFLECT( graphene::chain::son_member_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::son_member_create_operation, (fee)(owner_account)(url) ) + +FC_REFLECT( graphene::chain::son_member_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::son_member_delete_operation, (fee)(owner_account) ) diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp b/libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp new file mode 100644 index 000000000..f6a3e63ed --- /dev/null +++ b/libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +namespace graphene { namespace chain { + +class create_son_member_evaluator : public evaluator +{ +public: + typedef son_member_create_operation operation_type; + + void_result do_evaluate(const son_member_create_operation& o); + object_id_type do_apply(const son_member_create_operation& o); +}; + +class delete_son_member_evaluator : public evaluator +{ +public: + typedef son_member_delete_operation operation_type; + + void_result do_evaluate(const son_member_delete_operation& o); + void_result do_apply(const son_member_delete_operation& o); +}; + +} } // namespace graphene::chain diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 77f85df68..277f6cf53 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -52,6 +52,8 @@ namespace graphene { namespace chain { vector active_committee_members; // updated once per maintenance interval flat_set active_witnesses; // updated once per maintenance interval // n.b. witness scheduling is done by witness_schedule object + + flat_set active_son_members; // updated once per maintenance interval }; /** diff --git a/libraries/chain/include/graphene/chain/protocol/account.hpp b/libraries/chain/include/graphene/chain/protocol/account.hpp index 6d13a4d3e..496e9067b 100644 --- a/libraries/chain/include/graphene/chain/protocol/account.hpp +++ b/libraries/chain/include/graphene/chain/protocol/account.hpp @@ -52,6 +52,9 @@ namespace graphene { namespace chain { /// The number of active committee members this account votes the blockchain should appoint /// Must not exceed the actual number of committee members voted for in @ref votes uint16_t num_committee = 0; + /// The number of active son members this account votes the blockchain should appoint + /// Must not exceed the actual number of son members voted for in @ref votes + uint16_t num_son = 0; /// This is the list of vote IDs this account votes for. The weight of these votes is determined by this /// account's balance of core asset. flat_set votes; diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 104a2ec38..73258a9d5 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -45,6 +45,8 @@ #include #include +#include + namespace graphene { namespace chain { /** @@ -129,7 +131,9 @@ namespace graphene { namespace chain { sport_delete_operation, event_group_delete_operation, affiliate_payout_operation, // VIRTUAL - affiliate_referral_payout_operation // VIRTUAL + affiliate_referral_payout_operation, // VIRTUAL + son_member_create_operation, + son_member_delete_operation > operation; /// @} // operations group diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 4b6e1589e..cdac849ba 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -145,6 +145,7 @@ namespace graphene { namespace chain { betting_market_group_object_type, betting_market_object_type, bet_object_type, + son_member_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -202,6 +203,7 @@ namespace graphene { namespace chain { class betting_market_group_object; class betting_market_object; class bet_object; + class son_member_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -228,6 +230,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type; typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; + typedef object_id< protocol_ids, son_member_object_type, son_member_object> son_member_id_type; // implementation types class global_property_object; @@ -402,6 +405,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (betting_market_group_object_type) (betting_market_object_type) (bet_object_type) + (son_member_object_type) (OBJECT_TYPE_COUNT) ) FC_REFLECT_ENUM( graphene::chain::impl_object_type, diff --git a/libraries/chain/include/graphene/chain/protocol/vote.hpp b/libraries/chain/include/graphene/chain/protocol/vote.hpp index 215d49029..d970ed74a 100644 --- a/libraries/chain/include/graphene/chain/protocol/vote.hpp +++ b/libraries/chain/include/graphene/chain/protocol/vote.hpp @@ -64,6 +64,7 @@ struct vote_id_type committee, witness, worker, + son, VOTE_TYPE_COUNT }; @@ -148,5 +149,5 @@ void from_variant( const fc::variant& var, graphene::chain::vote_id_type& vo ); FC_REFLECT_TYPENAME( fc::flat_set ) -FC_REFLECT_ENUM( graphene::chain::vote_id_type::vote_type, (witness)(committee)(worker)(VOTE_TYPE_COUNT) ) +FC_REFLECT_ENUM( graphene::chain::vote_id_type::vote_type, (witness)(committee)(worker)(son)(VOTE_TYPE_COUNT) ) FC_REFLECT( graphene::chain::vote_id_type, (content) ) diff --git a/libraries/net/CMakeLists.txt b/libraries/net/CMakeLists.txt index 39f9cd05c..f8f323c32 100644 --- a/libraries/net/CMakeLists.txt +++ b/libraries/net/CMakeLists.txt @@ -10,7 +10,7 @@ set(SOURCES node.cpp add_library( graphene_net ${SOURCES} ${HEADERS} ) target_link_libraries( graphene_net - PUBLIC fc graphene_db ) + PUBLIC graphene_chain ) target_include_directories( graphene_net PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../chain/include" diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index a71891381..c15c3954a 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1378,6 +1378,28 @@ class wallet_api bool approve, bool broadcast = false); + /** Vote for a given son_member. + * + * An account can publish a list of all son_memberes they approve of. This + * command allows you to add or remove son_memberes from this list. + * Each account's vote is weighted according to the number of shares of the + * core asset owned by that account at the time the votes are tallied. + * + * @note you cannot vote against a son_member, you can only vote for the son_member + * or not vote for the son_member. + * + * @param voting_account the name or id of the account who is voting with their shares + * @param son_member the name or id of the son_member' owner account + * @param approve true if you wish to vote in favor of that son_member, false to + * remove your vote in favor of that son_member + * @param broadcast true if you wish to broadcast the transaction + * @return the signed transaction changing your vote for the given son_member + */ + signed_transaction vote_for_son_member(string voting_account, + string son_member, + bool approve, + bool broadcast = false); + /** Vote for a given witness. * * An account can publish a list of all witnesses they approve of. This @@ -1965,6 +1987,7 @@ FC_API( graphene::wallet::wallet_api, (get_vesting_balances) (withdraw_vesting) (vote_for_committee_member) + (vote_for_son_member) (vote_for_witness) (update_witness_votes) (set_voting_proxy) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 812740e6d..3c0629db4 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2024,6 +2024,40 @@ class wallet_api_impl return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (voting_account)(committee_member)(approve)(broadcast) ) } + signed_transaction vote_for_son_member(string voting_account, + string son_member, + bool approve, + bool broadcast /* = false */) + { try { + account_object voting_account_object = get_account(voting_account); + account_id_type son_member_owner_account_id = get_account_id(son_member); + fc::optional son_member_obj = _remote_db->get_son_member_by_account(son_member_owner_account_id); + if (!son_member_obj) + FC_THROW("Account ${son_member} is not registered as a son_member", ("son_member", son_member)); + if (approve) + { + auto insert_result = voting_account_object.options.votes.insert(son_member_obj->vote_id); + if (!insert_result.second) + FC_THROW("Account ${account} was already voting for son_member ${son_member}", ("account", voting_account)("son_member", son_member)); + } + else + { + unsigned votes_removed = voting_account_object.options.votes.erase(son_member_obj->vote_id); + if (!votes_removed) + FC_THROW("Account ${account} is already not voting for son_member ${son_member}", ("account", voting_account)("son_member", son_member)); + } + account_update_operation account_update_op; + account_update_op.account = voting_account_object.id; + account_update_op.new_options = voting_account_object.options; + + signed_transaction tx; + tx.operations.push_back( account_update_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (voting_account)(son_member)(approve)(broadcast) ) } + signed_transaction vote_for_witness(string voting_account, string witness, bool approve, @@ -4044,6 +4078,14 @@ signed_transaction wallet_api::vote_for_committee_member(string voting_account, return my->vote_for_committee_member(voting_account, witness, approve, broadcast); } +signed_transaction wallet_api::vote_for_son_member(string voting_account, + string son_member, + bool approve, + bool broadcast /* = false */) +{ + return my->vote_for_son_member(voting_account, son_member, approve, broadcast); +} + signed_transaction wallet_api::vote_for_witness(string voting_account, string witness, bool approve, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 57a451aa8..bd7e0791d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -41,4 +41,8 @@ file(GLOB RANDOM_SOURCES "random/*.cpp") add_executable( random_test ${RANDOM_SOURCES} ${COMMON_SOURCES} ) target_link_libraries( random_test graphene_chain graphene_app graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +file(GLOB UNIT_TESTS "btc_sidechain_tests/*.cpp") +add_executable( btc_sidechain_test ${UNIT_TESTS} ${COMMON_SOURCES} ) +target_link_libraries( btc_sidechain_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} ) + add_subdirectory( generate_empty_blocks ) diff --git a/tests/btc_sidechain_tests/main.cpp b/tests/btc_sidechain_tests/main.cpp new file mode 100644 index 000000000..40b64f9d9 --- /dev/null +++ b/tests/btc_sidechain_tests/main.cpp @@ -0,0 +1,17 @@ +#include +#include +#include + +extern uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP; + +boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { + std::srand(time(NULL)); + std::cout << "Random number generator seeded to " << time(NULL) << std::endl; + const char* genesis_timestamp_str = getenv("GRAPHENE_TESTING_GENESIS_TIMESTAMP"); + if( genesis_timestamp_str != nullptr ) + { + GRAPHENE_TESTING_GENESIS_TIMESTAMP = std::stoul( genesis_timestamp_str ); + } + std::cout << "GRAPHENE_TESTING_GENESIS_TIMESTAMP is " << GRAPHENE_TESTING_GENESIS_TIMESTAMP << std::endl; + return nullptr; +} diff --git a/tests/btc_sidechain_tests/son_operations_tests.cpp b/tests/btc_sidechain_tests/son_operations_tests.cpp new file mode 100644 index 000000000..08f9ca68a --- /dev/null +++ b/tests/btc_sidechain_tests/son_operations_tests.cpp @@ -0,0 +1,67 @@ +#include + +#include + +#include "../common/database_fixture.hpp" + +#include +#include + +using namespace graphene::chain; +using namespace graphene::chain::test; + +class test_create_son_member_evaluator: public create_son_member_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_delete_son_member_evaluator: public delete_son_member_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 ){ + std::string test_url = "https://create_son_test"; + test_create_son_member_evaluator test_eval( db ); + son_member_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( delete_son_test ){ + INVOKE(create_son_test); + test_delete_son_member_evaluator test_eval( db ); + + son_member_delete_operation delete_op; + delete_op.owner_account = account_id_type(1); + 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_SUITE_END() \ No newline at end of file diff --git a/tests/common/genesis_file_util.hpp b/tests/common/genesis_file_util.hpp index e058df02c..be56eaf4a 100644 --- a/tests/common/genesis_file_util.hpp +++ b/tests/common/genesis_file_util.hpp @@ -40,4 +40,4 @@ boost::filesystem::path create_genesis_file(fc::temp_directory& directory) { fc::json::save_to_file(genesis_state, genesis_out); return genesis_path; -} +} \ No newline at end of file From 7d6b2156e44cccb2e1837072a7a9eebd3b15a5bd Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 19 Sep 2019 11:52:23 -0300 Subject: [PATCH 02/34] rename and move stuff --- .../app/include/graphene/app/database_api.hpp | 3 +-- libraries/chain/CMakeLists.txt | 2 +- libraries/chain/db_init.cpp | 8 ++------ .../graphene/chain/protocol/operations.hpp | 3 +-- .../son_operations.hpp => protocol/son.hpp} | 0 ...erations_evaluator.hpp => son_evaluator.hpp} | 2 +- .../{btc-sidechain/son.hpp => son_object.hpp} | 0 ...erations_evaluator.cpp => son_evaluator.cpp} | 4 ++-- tests/CMakeLists.txt | 4 ---- tests/btc_sidechain_tests/main.cpp | 17 ----------------- .../son_operations_tests.cpp | 4 ++-- 11 files changed, 10 insertions(+), 37 deletions(-) rename libraries/chain/include/graphene/chain/{btc-sidechain/son_operations.hpp => protocol/son.hpp} (100%) rename libraries/chain/include/graphene/chain/{btc-sidechain/son_operations_evaluator.hpp => son_evaluator.hpp} (92%) rename libraries/chain/include/graphene/chain/{btc-sidechain/son.hpp => son_object.hpp} (100%) rename libraries/chain/{btc-sidechain/son_operations_evaluator.cpp => son_evaluator.cpp} (93%) delete mode 100644 tests/btc_sidechain_tests/main.cpp rename tests/{btc_sidechain_tests => tests}/son_operations_tests.cpp (94%) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 0500023e3..c64302432 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -43,8 +43,7 @@ #include #include #include - -#include +#include #include #include diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c7c8e7f81..5b3eea311 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -111,7 +111,7 @@ add_library( graphene_chain affiliate_payout.cpp - btc-sidechain/son_operations_evaluator.cpp + son_evaluator.cpp ${HEADERS} ${PROTOCOL_HEADERS} diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index d3f797966..647ffb5fb 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -49,13 +49,12 @@ #include #include #include - - #include #include #include #include #include +#include #include #include @@ -76,13 +75,10 @@ #include #include #include - -#include +#include #include -#include - #include #include #include diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 73258a9d5..6760791f6 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -44,8 +44,7 @@ #include #include #include - -#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp similarity index 100% rename from libraries/chain/include/graphene/chain/btc-sidechain/son_operations.hpp rename to libraries/chain/include/graphene/chain/protocol/son.hpp diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp b/libraries/chain/include/graphene/chain/son_evaluator.hpp similarity index 92% rename from libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp rename to libraries/chain/include/graphene/chain/son_evaluator.hpp index f6a3e63ed..57b879b68 100644 --- a/libraries/chain/include/graphene/chain/btc-sidechain/son_operations_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/son_evaluator.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/btc-sidechain/son.hpp b/libraries/chain/include/graphene/chain/son_object.hpp similarity index 100% rename from libraries/chain/include/graphene/chain/btc-sidechain/son.hpp rename to libraries/chain/include/graphene/chain/son_object.hpp diff --git a/libraries/chain/btc-sidechain/son_operations_evaluator.cpp b/libraries/chain/son_evaluator.cpp similarity index 93% rename from libraries/chain/btc-sidechain/son_operations_evaluator.cpp rename to libraries/chain/son_evaluator.cpp index 9ce855b3d..b469a0de5 100644 --- a/libraries/chain/btc-sidechain/son_operations_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -1,7 +1,7 @@ -#include +#include #include -#include +#include namespace graphene { namespace chain { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 88c6e8ea0..fef122b5d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,8 +45,4 @@ file(GLOB RANDOM_SOURCES "random/*.cpp") add_executable( random_test ${RANDOM_SOURCES} ${COMMON_SOURCES} ) target_link_libraries( random_test graphene_chain graphene_app graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) -file(GLOB UNIT_TESTS "btc_sidechain_tests/*.cpp") -add_executable( btc_sidechain_test ${UNIT_TESTS} ${COMMON_SOURCES} ) -target_link_libraries( btc_sidechain_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} ) - add_subdirectory( generate_empty_blocks ) diff --git a/tests/btc_sidechain_tests/main.cpp b/tests/btc_sidechain_tests/main.cpp deleted file mode 100644 index 40b64f9d9..000000000 --- a/tests/btc_sidechain_tests/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include - -extern uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP; - -boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { - std::srand(time(NULL)); - std::cout << "Random number generator seeded to " << time(NULL) << std::endl; - const char* genesis_timestamp_str = getenv("GRAPHENE_TESTING_GENESIS_TIMESTAMP"); - if( genesis_timestamp_str != nullptr ) - { - GRAPHENE_TESTING_GENESIS_TIMESTAMP = std::stoul( genesis_timestamp_str ); - } - std::cout << "GRAPHENE_TESTING_GENESIS_TIMESTAMP is " << GRAPHENE_TESTING_GENESIS_TIMESTAMP << std::endl; - return nullptr; -} diff --git a/tests/btc_sidechain_tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp similarity index 94% rename from tests/btc_sidechain_tests/son_operations_tests.cpp rename to tests/tests/son_operations_tests.cpp index 08f9ca68a..45ff8a4eb 100644 --- a/tests/btc_sidechain_tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -4,8 +4,8 @@ #include "../common/database_fixture.hpp" -#include -#include +#include +#include using namespace graphene::chain; using namespace graphene::chain::test; From 38ec5537734cb26bf8aeb63863c5bac77e101f97 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 19 Sep 2019 13:22:46 -0300 Subject: [PATCH 03/34] remove member from operation names --- libraries/app/impacted.cpp | 4 ++-- libraries/chain/db_init.cpp | 5 ++--- libraries/chain/db_notify.cpp | 4 ++-- .../graphene/chain/protocol/operations.hpp | 4 ++-- .../include/graphene/chain/protocol/son.hpp | 12 ++++++------ .../include/graphene/chain/son_evaluator.hpp | 16 ++++++++-------- libraries/chain/son_evaluator.cpp | 8 ++++---- tests/tests/son_operations_tests.cpp | 8 ++++---- 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 1b7797ffd..c67f220f3 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -282,10 +282,10 @@ struct get_impacted_account_visitor _impacted.insert( op.affiliate ); } void operator()( const affiliate_referral_payout_operation& op ) { } - void operator()( const son_member_create_operation& op ){ + void operator()( const son_create_operation& op ){ _impacted.insert( op.owner_account ); } - void operator()( const son_member_delete_operation& op ){ + void operator()( const son_delete_operation& op ){ _impacted.insert( op.owner_account ); } }; diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 647ffb5fb..4f3059509 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -237,9 +237,8 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); - - 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 2f3d89c3a..de4f57b47 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -269,10 +269,10 @@ struct get_impacted_account_visitor _impacted.insert( op.affiliate ); } void operator()( const affiliate_referral_payout_operation& op ) { } - void operator()( const son_member_create_operation& op ) { + void operator()( const son_create_operation& op ) { _impacted.insert( op.owner_account ); } - void operator()( const son_member_delete_operation& op ) { + void operator()( const son_delete_operation& op ) { _impacted.insert( op.owner_account ); } }; diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 6760791f6..5259c0dac 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -131,8 +131,8 @@ namespace graphene { namespace chain { event_group_delete_operation, affiliate_payout_operation, // VIRTUAL affiliate_referral_payout_operation, // VIRTUAL - son_member_create_operation, - son_member_delete_operation + son_create_operation, + son_delete_operation > operation; /// @} // operations group diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index 700dc5fcd..eb3554331 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -3,7 +3,7 @@ namespace graphene { namespace chain { - struct son_member_create_operation : public base_operation + struct son_create_operation : public base_operation { struct fee_parameters_type { uint64_t fee = 0; }; @@ -15,7 +15,7 @@ namespace graphene { namespace chain { share_type calculate_fee(const fee_parameters_type& k)const { return 0; } }; - struct son_member_delete_operation : public base_operation + struct son_delete_operation : public base_operation { struct fee_parameters_type { uint64_t fee = 0; }; @@ -28,8 +28,8 @@ namespace graphene { namespace chain { } } // namespace graphene::chain -FC_REFLECT( graphene::chain::son_member_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_member_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) ) -FC_REFLECT( graphene::chain::son_member_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_member_delete_operation, (fee)(owner_account) ) +FC_REFLECT( graphene::chain::son_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::son_delete_operation, (fee)(owner_account) ) diff --git a/libraries/chain/include/graphene/chain/son_evaluator.hpp b/libraries/chain/include/graphene/chain/son_evaluator.hpp index 57b879b68..43cfd0fb3 100644 --- a/libraries/chain/include/graphene/chain/son_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/son_evaluator.hpp @@ -4,22 +4,22 @@ namespace graphene { namespace chain { -class create_son_member_evaluator : public evaluator +class create_son_evaluator : public evaluator { public: - typedef son_member_create_operation operation_type; + typedef son_create_operation operation_type; - void_result do_evaluate(const son_member_create_operation& o); - object_id_type do_apply(const son_member_create_operation& o); + void_result do_evaluate(const son_create_operation& o); + object_id_type do_apply(const son_create_operation& o); }; -class delete_son_member_evaluator : public evaluator +class delete_son_evaluator : public evaluator { public: - typedef son_member_delete_operation operation_type; + typedef son_delete_operation operation_type; - void_result do_evaluate(const son_member_delete_operation& o); - void_result do_apply(const son_member_delete_operation& o); + void_result do_evaluate(const son_delete_operation& o); + void_result do_apply(const son_delete_operation& o); }; } } // namespace graphene::chain diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index b469a0de5..a5551a64e 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -5,13 +5,13 @@ namespace graphene { namespace chain { -void_result create_son_member_evaluator::do_evaluate(const son_member_create_operation& op) +void_result create_son_evaluator::do_evaluate(const son_create_operation& op) { try{ FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON."); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } -object_id_type create_son_member_evaluator::do_apply(const son_member_create_operation& op) +object_id_type create_son_evaluator::do_apply(const son_create_operation& op) { try { vote_id_type vote_id; db().modify(db().get_global_properties(), [&vote_id](global_property_object& p) { @@ -26,7 +26,7 @@ object_id_type create_son_member_evaluator::do_apply(const son_member_create_ope return new_son_object.id; } FC_CAPTURE_AND_RETHROW( (op) ) } -void_result delete_son_member_evaluator::do_evaluate(const son_member_delete_operation& op) +void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { database& d = db(); const auto& idx = d.get_index_type().indices().get(); @@ -34,7 +34,7 @@ void_result delete_son_member_evaluator::do_evaluate(const son_member_delete_ope return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } -void_result delete_son_member_evaluator::do_apply(const son_member_delete_operation& op) +void_result delete_son_evaluator::do_apply(const son_delete_operation& op) { try { const auto& idx = db().get_index_type().indices().get(); db().remove(*idx.find(op.owner_account)); diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 45ff8a4eb..16ff197fb 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -10,7 +10,7 @@ using namespace graphene::chain; using namespace graphene::chain::test; -class test_create_son_member_evaluator: public create_son_member_evaluator { +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 ) ) @@ -20,7 +20,7 @@ class test_create_son_member_evaluator: public create_son_member_evaluator { std::unique_ptr ptr_trx_state; }; -class test_delete_son_member_evaluator: public delete_son_member_evaluator { +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 ) ) @@ -35,7 +35,7 @@ BOOST_FIXTURE_TEST_SUITE( son_operation_tests, database_fixture ) BOOST_AUTO_TEST_CASE( create_son_test ){ std::string test_url = "https://create_son_test"; test_create_son_member_evaluator test_eval( db ); - son_member_create_operation op; + son_create_operation op; op.owner_account = account_id_type(1); op.url = test_url; @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE( delete_son_test ){ INVOKE(create_son_test); test_delete_son_member_evaluator test_eval( db ); - son_member_delete_operation delete_op; + son_delete_operation delete_op; delete_op.owner_account = account_id_type(1); BOOST_CHECK_NO_THROW( test_eval.do_evaluate( delete_op ) ); test_eval.do_apply( delete_op ); From 52e9c2a5a63cfa45088c1fae70b408fcfd43d256 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 19 Sep 2019 13:32:01 -0300 Subject: [PATCH 04/34] remove not needed library --- tests/tests/son_operations_tests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 16ff197fb..c60055e21 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -1,7 +1,5 @@ #include -#include - #include "../common/database_fixture.hpp" #include From ba77a33711b79b9ae25871b1e232a0417fa27ef7 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 20 Sep 2019 08:38:22 -0300 Subject: [PATCH 05/34] rename object, add update operation skeleton --- libraries/app/api.cpp | 8 ++++---- libraries/app/database_api.cpp | 6 +++--- libraries/app/impacted.cpp | 3 +++ .../app/include/graphene/app/database_api.hpp | 2 +- libraries/chain/db_notify.cpp | 11 +++++++---- .../graphene/chain/global_property_object.hpp | 2 +- .../graphene/chain/protocol/operations.hpp | 1 + .../include/graphene/chain/protocol/son.hpp | 16 ++++++++++++++++ .../include/graphene/chain/protocol/types.hpp | 10 ++++++---- .../include/graphene/chain/son_evaluator.hpp | 9 +++++++++ .../chain/include/graphene/chain/son_object.hpp | 16 ++++++++-------- libraries/chain/son_evaluator.cpp | 15 ++++++++++++++- libraries/wallet/wallet.cpp | 2 +- programs/js_operation_serializer/main.cpp | 1 + 14 files changed, 75 insertions(+), 27 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 9d3148dbb..21542d9d3 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -432,10 +432,10 @@ namespace graphene { namespace app { } case balance_object_type:{ /** these are free from any accounts */ break; - } case son_member_object_type:{ - const auto& son_object = dynamic_cast(obj); - assert( son_object != nullptr ); - accounts.insert( son_object->son_member_account ); + } case son_object_type:{ + const auto& aobj = dynamic_cast(obj); + assert( aobj != nullptr ); + accounts.insert( aobj->son_member_account ); break; } case sport_object_type: diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index d6bffe04e..ccf68c53e 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -137,7 +137,7 @@ class database_api_impl : public std::enable_shared_from_this map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; // SON members - fc::optional get_son_member_by_account(account_id_type account)const; + fc::optional get_son_member_by_account(account_id_type account)const; // Votes vector lookup_vote_ids( const vector& votes )const; @@ -1586,12 +1586,12 @@ map database_api_impl::lookup_committee_member // // ////////////////////////////////////////////////////////////////////// -fc::optional database_api::get_son_member_by_account(account_id_type account)const +fc::optional database_api::get_son_member_by_account(account_id_type account)const { return my->get_son_member_by_account( account ); } -fc::optional database_api_impl::get_son_member_by_account(account_id_type account) const +fc::optional database_api_impl::get_son_member_by_account(account_id_type account) const { const auto& idx = _db.get_index_type().indices().get(); auto itr = idx.find(account); diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index c67f220f3..a202264e1 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -283,6 +283,9 @@ struct get_impacted_account_visitor } void operator()( const affiliate_referral_payout_operation& op ) { } void operator()( const son_create_operation& op ){ + _impacted.insert( op.owner_account ); + } + void operator()( const son_update_operation& op ){ _impacted.insert( op.owner_account ); } void operator()( const son_delete_operation& op ){ diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index c64302432..7d239b202 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -556,7 +556,7 @@ class database_api * @param account The ID of the account whose son_member should be retrieved * @return The son_member object, or null if the account does not have a son_member */ - fc::optional get_son_member_by_account(account_id_type account)const; + fc::optional get_son_member_by_account(account_id_type account)const; /// WORKERS diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index de4f57b47..3709382ca 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -272,6 +272,9 @@ struct get_impacted_account_visitor void operator()( const son_create_operation& op ) { _impacted.insert( op.owner_account ); } + void operator()( const son_update_operation& op ) { + _impacted.insert( op.owner_account ); + } void operator()( const son_delete_operation& op ) { _impacted.insert( op.owner_account ); } @@ -363,10 +366,10 @@ void get_relevant_accounts( const object* obj, flat_set& accoun } case balance_object_type:{ /** these are free from any accounts */ break; - } case son_member_object_type:{ - const auto& son_object = dynamic_cast(obj); - assert( son_object != nullptr ); - accounts.insert( son_object->son_member_account ); + } case son_object_type:{ + const auto& aobj = dynamic_cast(obj); + assert( aobj != nullptr ); + accounts.insert( aobj->son_member_account ); break; } } diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 277f6cf53..771e912c8 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -53,7 +53,7 @@ namespace graphene { namespace chain { flat_set active_witnesses; // updated once per maintenance interval // n.b. witness scheduling is done by witness_schedule object - flat_set active_son_members; // updated once per maintenance interval + flat_set active_son_members; // updated once per maintenance interval }; /** diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 5259c0dac..cd31a5d2b 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -132,6 +132,7 @@ namespace graphene { namespace chain { affiliate_payout_operation, // VIRTUAL affiliate_referral_payout_operation, // VIRTUAL son_create_operation, + son_update_operation, son_delete_operation > operation; diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index eb3554331..5d6bb18b9 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -15,6 +15,19 @@ namespace graphene { namespace chain { share_type calculate_fee(const fee_parameters_type& k)const { return 0; } }; + struct son_update_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 0; }; + + asset fee; + son_id_type son_id; + account_id_type owner_account; + std::string new_url; + + account_id_type fee_payer()const { return owner_account; } + share_type calculate_fee(const fee_parameters_type& k)const { return 0; } + }; + struct son_delete_operation : public base_operation { struct fee_parameters_type { uint64_t fee = 0; }; @@ -31,5 +44,8 @@ namespace graphene { namespace 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_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_delete_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::son_delete_operation, (fee)(owner_account) ) diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index cdac849ba..326f69c74 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -145,7 +145,7 @@ namespace graphene { namespace chain { betting_market_group_object_type, betting_market_object_type, bet_object_type, - son_member_object_type, + son_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -203,7 +203,7 @@ namespace graphene { namespace chain { class betting_market_group_object; class betting_market_object; class bet_object; - class son_member_object; + class son_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -230,7 +230,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type; typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; - typedef object_id< protocol_ids, son_member_object_type, son_member_object> son_member_id_type; + typedef object_id< protocol_ids, son_object_type, son_object> son_id_type; // implementation types class global_property_object; @@ -405,7 +405,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (betting_market_group_object_type) (betting_market_object_type) (bet_object_type) - (son_member_object_type) + (son_object_type) (OBJECT_TYPE_COUNT) ) FC_REFLECT_ENUM( graphene::chain::impl_object_type, @@ -473,6 +473,8 @@ FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type ) FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type ) FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type ) FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::son_id_type ) + FC_REFLECT( graphene::chain::void_t, ) diff --git a/libraries/chain/include/graphene/chain/son_evaluator.hpp b/libraries/chain/include/graphene/chain/son_evaluator.hpp index 43cfd0fb3..bb6a1820c 100644 --- a/libraries/chain/include/graphene/chain/son_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/son_evaluator.hpp @@ -13,6 +13,15 @@ class create_son_evaluator : public evaluator object_id_type do_apply(const son_create_operation& o); }; +class update_son_evaluator : public evaluator +{ +public: + typedef son_update_operation operation_type; + + void_result do_evaluate(const son_update_operation& o); + object_id_type do_apply(const son_update_operation& o); +}; + class delete_son_evaluator : public evaluator { public: diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 6b6d7bac7..114b27cd2 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -7,15 +7,15 @@ namespace graphene { namespace chain { using namespace graphene::db; /** - * @class son_member_object + * @class son_object * @brief tracks information about a son_member account. * @ingroup object */ - class son_member_object : public abstract_object + class son_object : public abstract_object { public: static const uint8_t space_id = protocol_ids; - static const uint8_t type_id = son_member_object_type; + static const uint8_t type_id = son_object_type; account_id_type son_member_account; vote_id_type vote_id; @@ -26,21 +26,21 @@ namespace graphene { namespace chain { struct by_account; struct by_vote_id; using son_member_multi_index_type = multi_index_container< - son_member_object, + son_object, indexed_by< ordered_unique< tag, member >, ordered_unique< tag, - member + member >, ordered_unique< tag, - member + member > > >; - using son_member_index = generic_index; + using son_member_index = generic_index; } } // graphene::chain -FC_REFLECT_DERIVED( graphene::chain::son_member_object, (graphene::db::object), +FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), (son_member_account)(vote_id)(total_votes)(url) ) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index a5551a64e..b12363d94 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -18,7 +18,7 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) vote_id = get_next_vote_id(p, vote_id_type::son); }); - const auto& new_son_object = db().create( [&]( son_member_object& obj ){ + 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; @@ -26,6 +26,19 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) return new_son_object.id; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result update_son_evaluator::do_evaluate(const son_update_operation& op) +{ try{ + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +object_id_type update_son_evaluator::do_apply(const son_update_operation& op) +{ try { + + + return son_id_type(0); +} FC_CAPTURE_AND_RETHROW( (op) ) } + void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { database& d = db(); diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 3c0629db4..630add0f4 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2031,7 +2031,7 @@ class wallet_api_impl { try { account_object voting_account_object = get_account(voting_account); account_id_type son_member_owner_account_id = get_account_id(son_member); - fc::optional son_member_obj = _remote_db->get_son_member_by_account(son_member_owner_account_id); + fc::optional son_member_obj = _remote_db->get_son_member_by_account(son_member_owner_account_id); if (!son_member_obj) FC_THROW("Account ${son_member} is not registered as a son_member", ("son_member", son_member)); if (approve) diff --git a/programs/js_operation_serializer/main.cpp b/programs/js_operation_serializer/main.cpp index 8994b36b5..a921c0c30 100644 --- a/programs/js_operation_serializer/main.cpp +++ b/programs/js_operation_serializer/main.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include From 5dcb55c99281a8c5fd94d124a4dee387ade06268 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 21 Sep 2019 09:23:32 -0300 Subject: [PATCH 06/34] add modify logic, test case, modify delete --- .../include/graphene/chain/protocol/son.hpp | 3 +- libraries/chain/son_evaluator.cpp | 26 ++++++++------ tests/tests/son_operations_tests.cpp | 35 +++++++++++++++++++ 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index 5d6bb18b9..7c007a8ed 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -33,6 +33,7 @@ namespace graphene { namespace chain { struct fee_parameters_type { uint64_t fee = 0; }; asset fee; + son_id_type son_id; account_id_type owner_account; account_id_type fee_payer()const { return owner_account; } @@ -48,4 +49,4 @@ 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_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::son_delete_operation, (fee)(owner_account) ) +FC_REFLECT( graphene::chain::son_delete_operation, (fee)(son_id)(owner_account) ) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index b12363d94..a93cfda0f 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -27,30 +27,36 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) } FC_CAPTURE_AND_RETHROW( (op) ) } void_result update_son_evaluator::do_evaluate(const son_update_operation& op) -{ try{ - +{ try { + const auto& idx = db().get_index_type().indices().get(); + FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } object_id_type update_son_evaluator::do_apply(const son_update_operation& op) { try { - - - return son_id_type(0); + const auto& idx = db().get_index_type().indices().get(); + auto itr = idx.find(op.son_id); + if(itr != idx.end()) + { + db().modify(*itr, [&op](son_object &so) { + so.url = op.new_url; + }); + } + return op.son_id; } FC_CAPTURE_AND_RETHROW( (op) ) } void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { - database& d = db(); - const auto& idx = d.get_index_type().indices().get(); - FC_ASSERT( idx.find(op.owner_account) != idx.end() ); + const auto& idx = db().get_index_type().indices().get(); + FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } void_result delete_son_evaluator::do_apply(const son_delete_operation& op) { try { - const auto& idx = db().get_index_type().indices().get(); - db().remove(*idx.find(op.owner_account)); + const auto& idx = db().get_index_type().indices().get(); + db().remove(*idx.find(op.son_id)); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index c60055e21..c4c3baf0d 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -18,6 +18,16 @@ class test_create_son_member_evaluator: public create_son_evaluator { 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 ): @@ -49,12 +59,37 @@ BOOST_AUTO_TEST_CASE( create_son_test ){ 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 ); From 6efbf84339eacad929627c1aa44cd57648cd0e2a Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 21 Sep 2019 09:56:23 -0300 Subject: [PATCH 07/34] change indentation of the son tests --- tests/tests/son_operations_tests.cpp | 112 +++++++++++++-------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index c4c3baf0d..609fe522d 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -10,91 +10,91 @@ 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; + 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; + 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; + 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 ){ - 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_AUTO_TEST_CASE( create_son_test ) { + 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_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 ); + 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 ); + 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); + 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); + 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_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 ); + 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 ); + 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 ); + 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); + 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 ); + 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() ); + const auto& idx = db.get_index_type().indices().get(); + BOOST_REQUIRE( idx.empty() ); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 0a5d6945684bbf4b72d381d958ea0f7904563f0b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 21 Sep 2019 12:19:57 -0300 Subject: [PATCH 08/34] add hardfork guards --- libraries/chain/proposal_evaluator.cpp | 12 ++++++++++++ libraries/chain/son_evaluator.cpp | 6 +++++- tests/tests/son_operations_tests.cpp | 7 +++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 8306128dd..58af6888c 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -140,6 +140,18 @@ struct proposal_operation_hardfork_visitor FC_ASSERT( vbco.balance_type == vesting_balance_type::unspecified, "balance_type in vesting create not allowed yet!" ); } + void operator()(const son_create_operation &v) const { + FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_create_operation not allowed yet!" ); + } + + void operator()(const son_update_operation &v) const { + FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_update_operation not allowed yet!" ); + } + + void operator()(const son_delete_operation &v) const { + FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_delete_operation not allowed yet!" ); + } + // loop and self visit in proposals void operator()(const proposal_create_operation &v) const { for (const op_wrapper &op : v.proposed_ops) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index a93cfda0f..920571ed1 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -2,12 +2,14 @@ #include #include +#include namespace graphene { namespace chain { void_result create_son_evaluator::do_evaluate(const son_create_operation& op) { try{ - FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON."); + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); + FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON."); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -28,6 +30,7 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) void_result update_son_evaluator::do_evaluate(const son_update_operation& op) { try { + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); @@ -48,6 +51,7 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 609fe522d..616e9492c 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -41,6 +41,11 @@ class test_delete_son_member_evaluator: public delete_son_evaluator { 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; @@ -60,9 +65,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) { } 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; From 723c802006429ecf775c9b19f9a5d2e80ecf5216 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 21 Sep 2019 18:45:40 -0300 Subject: [PATCH 09/34] minor clean --- libraries/chain/db_init.cpp | 1 + libraries/chain/son_evaluator.cpp | 1 - tests/common/genesis_file_util.hpp | 2 +- tests/tests/son_operations_tests.cpp | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 4f3059509..7c949c6fe 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -238,6 +238,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); } diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 920571ed1..e11799f8c 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -65,4 +65,3 @@ void_result delete_son_evaluator::do_apply(const son_delete_operation& op) } FC_CAPTURE_AND_RETHROW( (op) ) } } } // namespace graphene::chain - \ No newline at end of file diff --git a/tests/common/genesis_file_util.hpp b/tests/common/genesis_file_util.hpp index be56eaf4a..e058df02c 100644 --- a/tests/common/genesis_file_util.hpp +++ b/tests/common/genesis_file_util.hpp @@ -40,4 +40,4 @@ boost::filesystem::path create_genesis_file(fc::temp_directory& directory) { fc::json::save_to_file(genesis_state, genesis_out); return genesis_path; -} \ No newline at end of file +} diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 616e9492c..90b290994 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -100,4 +100,4 @@ BOOST_AUTO_TEST_CASE( delete_son_test ){ BOOST_REQUIRE( idx.empty() ); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From 3a4445b20c04ece1c2e41c9cdfd23f9e66fcc65f Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 24 Sep 2019 17:10:34 -0300 Subject: [PATCH 10/34] add missing SON hardfork file --- libraries/chain/hardfork.d/SON.hf | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 libraries/chain/hardfork.d/SON.hf diff --git a/libraries/chain/hardfork.d/SON.hf b/libraries/chain/hardfork.d/SON.hf new file mode 100644 index 000000000..badde1f45 --- /dev/null +++ b/libraries/chain/hardfork.d/SON.hf @@ -0,0 +1,4 @@ +// SON HARDFORK Monday, September 21, 2020 1:43:11 PM +#ifndef HARDFORK_SON_TIME +#define HARDFORK_SON_TIME (fc::time_point_sec( 1600695791 )) +#endif \ No newline at end of file From 17dfc6af6449b4023e3290fbf2f805bb09e27680 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 25 Sep 2019 18:17:42 -0300 Subject: [PATCH 11/34] add protection to delete and modify son object only if owner --- libraries/chain/son_evaluator.cpp | 2 + tests/tests/son_operations_tests.cpp | 85 +++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index e11799f8c..2aa2f6e6c 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -31,6 +31,7 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) void_result update_son_evaluator::do_evaluate(const son_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass + FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); @@ -52,6 +53,7 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass + FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 90b290994..d8a0f61c1 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE( update_son_test ){ BOOST_CHECK( id == obj->id ); } -BOOST_AUTO_TEST_CASE( delete_son_test ){ +BOOST_AUTO_TEST_CASE( delete_son_test ) { INVOKE(create_son_test); test_delete_son_member_evaluator test_eval( db ); @@ -100,4 +100,87 @@ BOOST_AUTO_TEST_CASE( delete_son_test ){ 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(); + } + generate_block(); + set_expiration(db, trx); + + ACTORS((alice)(bob)); + + upgrade_to_lifetime_member(alice); + upgrade_to_lifetime_member(bob); + + set_expiration(db, trx); + std::string test_url = "https://create_son_test"; + + // alice became son + { + son_create_operation op; + op.owner_account = alice_id; + op.url = test_url; + 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 ); + + // bob tries to update a son object he dont own + { + son_update_operation op; + op.owner_account = bob_id; + op.new_url = "whatever"; + op.son_id = son_id_type(0); + + trx.operations.push_back(op); + sign(trx, bob_private_key); + GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception); + } + generate_block(); + + set_expiration(db, trx); + trx.clear(); + + obj = idx.find( alice_id ); + BOOST_REQUIRE( obj != idx.end() ); + // not changing + BOOST_CHECK( obj->url == "https://create_son_test" ); + + // bob tries to delete a son object he dont own + { + son_delete_operation op; + op.owner_account = bob_id; + op.son_id = son_id_type(0); + + trx.operations.push_back(op); + sign(trx, bob_private_key); + GRAPHENE_REQUIRE_THROW(PUSH_TX( db, trx ), fc::exception); + + } + generate_block(); + + obj = idx.find( alice_id ); + // 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() From 4d0a5b683fef4ba607bab97c189064076829667c Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 27 Sep 2019 16:03:33 -0300 Subject: [PATCH 12/34] add son vote type to lookup_vote_ids --- libraries/app/database_api.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index ccf68c53e..0711bd049 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -1619,6 +1619,7 @@ vector database_api_impl::lookup_vote_ids( const vector& const auto& committee_idx = _db.get_index_type().indices().get(); const auto& for_worker_idx = _db.get_index_type().indices().get(); const auto& against_worker_idx = _db.get_index_type().indices().get(); + const auto& son_idx = _db.get_index_type().indices().get(); vector result; result.reserve( votes.size() ); @@ -1661,6 +1662,16 @@ vector database_api_impl::lookup_vote_ids( const vector& } break; } + case vote_id_type::son: + { + auto itr = son_idx.find( id ); + if( itr != son_idx.end() ) + result.emplace_back( variant( *itr ) ); + else + result.emplace_back( variant() ); + break; + } + case vote_id_type::VOTE_TYPE_COUNT: break; // supress unused enum value warnings } } From e2c579bb02668125bff13ee8b25c11498b8eb29a Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 28 Sep 2019 18:35:38 -0300 Subject: [PATCH 13/34] add additional fields to son object and operations --- .../include/graphene/chain/protocol/son.hpp | 24 ++- .../include/graphene/chain/son_object.hpp | 13 +- libraries/chain/son_evaluator.cpp | 12 +- tests/tests/son_operations_tests.cpp | 191 +++++++++--------- 4 files changed, 128 insertions(+), 112 deletions(-) diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index 7c007a8ed..efea3ef73 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 114b27cd2..92d21b317 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 2aa2f6e6c..8ac0cb24e 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 d8a0f61c1..75986ca77 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -8,134 +8,134 @@ 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; -}; +BOOST_FIXTURE_TEST_SUITE( son_operation_tests, database_fixture ) -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(); +BOOST_AUTO_TEST_CASE( create_son_test ) { + generate_blocks(HARDFORK_SON_TIME); + while (db.head_block_time() <= HARDFORK_SON_TIME) { + generate_block(); } - std::unique_ptr ptr_trx_state; -}; + generate_block(); + set_expiration(db, trx); + + ACTORS((alice)(bob)); + + upgrade_to_lifetime_member(alice); + upgrade_to_lifetime_member(bob); -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 ) ) + 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; { - trx_state = ptr_trx_state.get(); + 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(); } - std::unique_ptr ptr_trx_state; -}; + // 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; -BOOST_FIXTURE_TEST_SUITE( son_operation_tests, database_fixture ) + 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(); + } -BOOST_AUTO_TEST_CASE( create_son_test ) { - generate_blocks( HARDFORK_SON_TIME ); - while( db.head_block_time() <= HARDFORK_SON_TIME ) + // alice became son { - generate_block(); + 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); } - 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; + generate_block(); - 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 ); + auto obj = idx.find( alice_id ); BOOST_REQUIRE( obj != idx.end() ); BOOST_CHECK( obj->url == test_url ); - BOOST_CHECK( id == obj->id ); + 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); - 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 ); +BOOST_AUTO_TEST_CASE( update_son_test ) { - 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); + GET_ACTOR(alice); - BOOST_CHECK_NO_THROW( test_eval.do_evaluate( delete_op ) ); - test_eval.do_apply( delete_op ); + std::string new_url = "https://anewurl.com"; - const auto& idx = db.get_index_type().indices().get(); - BOOST_REQUIRE( idx.empty() ); -} + { + son_update_operation op; + op.owner_account = alice_id; + op.new_url = new_url; + op.son_id = son_id_type(0); -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(); + trx.operations.push_back(op); + sign(trx, alice_private_key); + PUSH_TX(db, trx, ~0); } generate_block(); - set_expiration(db, trx); - ACTORS((alice)(bob)); + 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 ); +} - upgrade_to_lifetime_member(alice); - upgrade_to_lifetime_member(bob); +BOOST_AUTO_TEST_CASE( delete_son_test ) { - set_expiration(db, trx); - std::string test_url = "https://create_son_test"; + INVOKE(create_son_test); + GET_ACTOR(alice); - // alice became son { - son_create_operation op; + son_delete_operation op; op.owner_account = alice_id; - op.url = test_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(); - 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_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() From 3a65102e567299852ac0c230d5bfd47ca277762e Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 2 Oct 2019 01:47:24 +0200 Subject: [PATCH 14/34] WIP, SON operations, cli_wallet commands and RPC - create_son, update_son, delete_son, list_sons - get_sons, get_son_by_account, lookup_son_accounts, get_son_count --- libraries/app/database_api.cpp | 66 +++++++- .../app/include/graphene/app/database_api.hpp | 34 ++++- .../wallet/include/graphene/wallet/wallet.hpp | 61 ++++++++ libraries/wallet/wallet.cpp | 141 +++++++++++++++++- 4 files changed, 292 insertions(+), 10 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 0711bd049..facf6d141 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -137,7 +137,10 @@ class database_api_impl : public std::enable_shared_from_this map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; // SON members - fc::optional get_son_member_by_account(account_id_type account)const; + vector> get_sons(const vector& son_ids)const; + fc::optional get_son_by_account(account_id_type account)const; + map lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const; + uint64_t get_son_count()const; // Votes vector lookup_vote_ids( const vector& votes )const; @@ -1586,12 +1589,29 @@ map database_api_impl::lookup_committee_member // // ////////////////////////////////////////////////////////////////////// -fc::optional database_api::get_son_member_by_account(account_id_type account)const +vector> database_api::get_sons(const vector& son_ids)const { - return my->get_son_member_by_account( account ); + return my->get_sons( son_ids ); } -fc::optional database_api_impl::get_son_member_by_account(account_id_type account) const +vector> database_api_impl::get_sons(const vector& son_ids)const +{ + vector> result; result.reserve(son_ids.size()); + std::transform(son_ids.begin(), son_ids.end(), std::back_inserter(result), + [this](son_id_type id) -> optional { + if(auto o = _db.find(id)) + return *o; + return {}; + }); + return result; +} + +fc::optional database_api::get_son_by_account(account_id_type account)const +{ + return my->get_son_by_account( account ); +} + +fc::optional database_api_impl::get_son_by_account(account_id_type account) const { const auto& idx = _db.get_index_type().indices().get(); auto itr = idx.find(account); @@ -1600,6 +1620,44 @@ fc::optional database_api_impl::get_son_member_by_account(account_id return {}; } +map database_api::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const +{ + return my->lookup_son_accounts( lower_bound_name, limit ); +} + +map database_api_impl::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const +{ + FC_ASSERT( limit <= 1000 ); + const auto& sons_by_id = _db.get_index_type().indices().get(); + + // we want to order sons by account name, but that name is in the account object + // so the son_member_index doesn't have a quick way to access it. + // get all the names and look them all up, sort them, then figure out what + // records to return. This could be optimized, but we expect the + // number of witnesses to be few and the frequency of calls to be rare + std::map sons_by_account_name; + for (const son_object& son : sons_by_id) + if (auto account_iter = _db.find(son.son_member_account)) + if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name + sons_by_account_name.insert(std::make_pair(account_iter->name, son.id)); + + auto end_iter = sons_by_account_name.begin(); + while (end_iter != sons_by_account_name.end() && limit--) + ++end_iter; + sons_by_account_name.erase(end_iter, sons_by_account_name.end()); + return sons_by_account_name; +} + +uint64_t database_api::get_son_count()const +{ + return my->get_son_count(); +} + +uint64_t database_api_impl::get_son_count()const +{ + return _db.get_index_type().indices().size(); +} + ////////////////////////////////////////////////////////////////////// // // // Votes // diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 7d239b202..44df27ac7 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -552,12 +552,33 @@ class database_api ///////////////// /** - * @brief Get the son_member owned by a given account - * @param account The ID of the account whose son_member should be retrieved - * @return The son_member object, or null if the account does not have a son_member + * @brief Get a list of SONs by ID + * @param son_ids IDs of the SONs to retrieve + * @return The SONs corresponding to the provided IDs + * + * This function has semantics identical to @ref get_objects + */ + vector> get_sons(const vector& son_ids)const; + + /** + * @brief Get the SON owned by a given account + * @param account The ID of the account whose SON should be retrieved + * @return The SON object, or null if the account does not have a SON + */ + fc::optional get_son_by_account(account_id_type account)const; + + /** + * @brief Get names and IDs for registered SONs + * @param lower_bound_name Lower bound of the first name to return + * @param limit Maximum number of results to return -- must not exceed 1000 + * @return Map of SON names to corresponding IDs */ - fc::optional get_son_member_by_account(account_id_type account)const; + map lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const; + /** + * @brief Get the total number of SONs registered with the blockchain + */ + uint64_t get_son_count()const; /// WORKERS @@ -770,7 +791,10 @@ FC_API(graphene::app::database_api, (lookup_committee_member_accounts) // SON members - (get_son_member_by_account) + (get_sons) + (get_son_by_account) + (lookup_son_accounts) + (get_son_count) // workers (get_workers_by_account) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index c15c3954a..741c1764e 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1271,6 +1271,63 @@ class wallet_api */ committee_member_object get_committee_member(string owner_account); + + /** Creates a SON object owned by the given account. + * + * An account can have at most one SON object. + * + * @param owner_account the name or id of the account which is creating the SON + * @param url a URL to include in the SON record in the blockchain. Clients may + * display this when showing a list of SONs. May be blank. + * @param broadcast true to broadcast the transaction on the network + * @returns the signed transaction registering a SON + */ + signed_transaction create_son(string owner_account, + string url, + bool broadcast = false); + + /** + * Update a SON object owned by the given account. + * + * @param witness The name of the SON's owner account. Also accepts the ID of the owner account or the ID of the SON. + * @param url Same as for create_son. The empty string makes it remain the same. + * @param block_signing_key The new block signing public key. The empty string makes it remain the same. + * @param broadcast true if you wish to broadcast the transaction. + */ + signed_transaction update_son(string owner_account, + string url, + string block_signing_key, + bool broadcast = false); + + + /** Deletes a SON object owned by the given account. + * + * An account can have at most one witness object. + * + * @param owner_account the name or id of the account which is creating the witness + * @param url a URL to include in the witness record in the blockchain. Clients may + * display this when showing a list of witnesses. May be blank. + * @param broadcast true to broadcast the transaction on the network + * @returns the signed transaction registering a witness + */ + signed_transaction delete_son(string owner_account, + bool broadcast = false); + + /** Lists all SONs in the blockchain. + * This returns a list of all account names that own SON, and the associated SON id, + * sorted by name. This lists SONs whether they are currently voted in or not. + * + * Use the \c lowerbound and limit parameters to page through the list. To retrieve all SONs, + * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass + * the last SON name returned as the \c lowerbound for the next \c list_sons() call. + * + * @param lowerbound the name of the first SON to return. If the named SON does not exist, + * the list will start at the SON that comes after \c lowerbound + * @param limit the maximum number of SON to return (max: 1000) + * @returns a list of SON mapping SON names to SON ids + */ + map list_sons(const string& lowerbound, uint32_t limit); + /** Creates a witness object owned by the given account. * * An account can have at most one witness object. @@ -1980,6 +2037,10 @@ FC_API( graphene::wallet::wallet_api, (get_committee_member) (list_witnesses) (list_committee_members) + (create_son) + (update_son) + (delete_son) + (list_sons) (create_witness) (update_witness) (create_worker) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 630add0f4..3f9c4eda6 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1720,6 +1720,41 @@ class wallet_api_impl FC_CAPTURE_AND_RETHROW( (owner_account) ) } + son_object get_son(string owner_account) + { + try + { + fc::optional son_id = maybe_id(owner_account); + if (son_id) + { + std::vector ids_to_get; + ids_to_get.push_back(*son_id); + std::vector> son_objects = _remote_db->get_sons(ids_to_get); + if (son_objects.front()) + return *son_objects.front(); + FC_THROW("No SON is registered for id ${id}", ("id", owner_account)); + } + else + { + // then maybe it's the owner account + try + { + account_id_type owner_account_id = get_account_id(owner_account); + fc::optional son = _remote_db->get_son_by_account(owner_account_id); + if (son) + return *son; + else + FC_THROW("No SON is registered for account ${account}", ("account", owner_account)); + } + catch (const fc::exception&) + { + FC_THROW("No account or SON named ${account}", ("account", owner_account)); + } + } + } + FC_CAPTURE_AND_RETHROW( (owner_account) ) + } + committee_member_object get_committee_member(string owner_account) { try @@ -1755,6 +1790,84 @@ class wallet_api_impl FC_CAPTURE_AND_RETHROW( (owner_account) ) } + signed_transaction create_son(string owner_account, + string url, + bool broadcast /* = false */) + { try { + account_object son_account = get_account(owner_account); + fc::ecc::private_key active_private_key = get_private_key_for_account(son_account); + int son_key_index = find_first_unused_derived_key_index(active_private_key); + fc::ecc::private_key son_private_key = derive_private_key(key_to_wif(active_private_key), son_key_index); + graphene::chain::public_key_type son_public_key = son_private_key.get_public_key(); + + son_create_operation son_create_op; + son_create_op.owner_account = son_account.id; + son_create_op.signing_key = son_public_key; + son_create_op.url = url; + secret_hash_type::encoder enc; + fc::raw::pack(enc, son_private_key); + fc::raw::pack(enc, secret_hash_type()); + //son_create_op.initial_secret = secret_hash_type::hash(enc.result()); + + + if (_remote_db->get_son_by_account(son_create_op.owner_account)) + FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account)); + + signed_transaction tx; + tx.operations.push_back( son_create_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + //_wallet.pending_witness_registrations[owner_account] = key_to_wif(son_private_key); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } + + signed_transaction update_son(string owner_account, + string url, + string block_signing_key, + bool broadcast /* = false */) + { try { + son_object son = get_son(owner_account); + account_object son_account = get_account( son.son_member_account ); + fc::ecc::private_key active_private_key = get_private_key_for_account(son_account); + + son_update_operation son_update_op; + son_update_op.son_id = son.id; + son_update_op.owner_account = son_account.id; + if( url != "" ) + son_update_op.new_url = url; + if( block_signing_key != "" ) { + son_update_op.new_signing_key = public_key_type( block_signing_key ); + } + + signed_transaction tx; + tx.operations.push_back( son_update_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees ); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (owner_account)(url)(block_signing_key)(broadcast) ) } + + signed_transaction delete_son(string owner_account, + bool broadcast /* = false */) + { try { + son_object son = get_son(owner_account); + account_object son_account = get_account( son.son_member_account ); + fc::ecc::private_key active_private_key = get_private_key_for_account(son_account); + + son_delete_operation son_delete_op; + son_delete_op.son_id = son.id; + son_delete_op.owner_account = son_account.id; + + signed_transaction tx; + tx.operations.push_back( son_delete_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees ); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } + signed_transaction create_witness(string owner_account, string url, bool broadcast /* = false */) @@ -2031,7 +2144,7 @@ class wallet_api_impl { try { account_object voting_account_object = get_account(voting_account); account_id_type son_member_owner_account_id = get_account_id(son_member); - fc::optional son_member_obj = _remote_db->get_son_member_by_account(son_member_owner_account_id); + fc::optional son_member_obj = _remote_db->get_son_by_account(son_member_owner_account_id); if (!son_member_obj) FC_THROW("Account ${son_member} is not registered as a son_member", ("son_member", son_member)); if (approve) @@ -4018,6 +4131,32 @@ committee_member_object wallet_api::get_committee_member(string owner_account) return my->get_committee_member(owner_account); } +signed_transaction wallet_api::create_son(string owner_account, + string url, + bool broadcast /* = false */) +{ + return my->create_son(owner_account, url, broadcast); +} + +signed_transaction wallet_api::update_son(string owner_account, + string url, + string block_signing_key, + bool broadcast /* = false */) +{ + return my->update_son(owner_account, url, block_signing_key, broadcast); +} + +signed_transaction wallet_api::delete_son(string owner_account, + bool broadcast /* = false */) +{ + my->delete_son(owner_account, broadcast); +} + +map wallet_api::list_sons(const string& lowerbound, uint32_t limit) +{ + my->_remote_db->lookup_son_accounts(lowerbound, limit); +} + signed_transaction wallet_api::create_witness(string owner_account, string url, bool broadcast /* = false */) From 44f185e0c2243f4a1e296d7cca0c011bd9048d34 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 2 Oct 2019 18:28:07 +0200 Subject: [PATCH 15/34] WIP, SON operations, cli_wallet commands and RPC - claim_registered_son - some renaming, to follow existing naming convention --- libraries/app/database_api.cpp | 8 ++-- libraries/chain/db_init.cpp | 2 +- .../graphene/chain/global_property_object.hpp | 2 +- .../include/graphene/chain/son_object.hpp | 2 +- libraries/chain/son_evaluator.cpp | 8 ++-- .../wallet/include/graphene/wallet/wallet.hpp | 3 +- libraries/wallet/wallet.cpp | 40 +++++++++++++++++-- tests/tests/son_operations_tests.cpp | 8 ++-- 8 files changed, 54 insertions(+), 19 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index facf6d141..52640d887 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -1613,7 +1613,7 @@ fc::optional database_api::get_son_by_account(account_id_type accoun fc::optional database_api_impl::get_son_by_account(account_id_type account) const { - const auto& idx = _db.get_index_type().indices().get(); + const auto& idx = _db.get_index_type().indices().get(); auto itr = idx.find(account); if( itr != idx.end() ) return *itr; @@ -1628,7 +1628,7 @@ map database_api::lookup_son_accounts(const string& lower_b map database_api_impl::lookup_son_accounts(const string& lower_bound_name, uint32_t limit)const { FC_ASSERT( limit <= 1000 ); - const auto& sons_by_id = _db.get_index_type().indices().get(); + const auto& sons_by_id = _db.get_index_type().indices().get(); // we want to order sons by account name, but that name is in the account object // so the son_member_index doesn't have a quick way to access it. @@ -1655,7 +1655,7 @@ uint64_t database_api::get_son_count()const uint64_t database_api_impl::get_son_count()const { - return _db.get_index_type().indices().size(); + return _db.get_index_type().indices().size(); } ////////////////////////////////////////////////////////////////////// @@ -1677,7 +1677,7 @@ vector database_api_impl::lookup_vote_ids( const vector& const auto& committee_idx = _db.get_index_type().indices().get(); const auto& for_worker_idx = _db.get_index_type().indices().get(); const auto& against_worker_idx = _db.get_index_type().indices().get(); - const auto& son_idx = _db.get_index_type().indices().get(); + const auto& son_idx = _db.get_index_type().indices().get(); vector result; result.reserve( votes.size() ); diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 7c949c6fe..5e7ab107c 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -305,7 +305,7 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index >(); - add_index< primary_index >(); + add_index< primary_index >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 771e912c8..b976eea08 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -53,7 +53,7 @@ namespace graphene { namespace chain { flat_set active_witnesses; // updated once per maintenance interval // n.b. witness scheduling is done by witness_schedule object - flat_set active_son_members; // updated once per maintenance interval + flat_set active_sons; // updated once per maintenance interval }; /** diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 92d21b317..022249445 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -42,7 +42,7 @@ namespace graphene { namespace chain { > > >; - using son_member_index = generic_index; + using son_index = generic_index; } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 8ac0cb24e..821739bb8 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -35,14 +35,14 @@ void_result update_son_evaluator::do_evaluate(const son_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); - const auto& idx = db().get_index_type().indices().get(); + const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } object_id_type update_son_evaluator::do_apply(const son_update_operation& op) { try { - const auto& idx = db().get_index_type().indices().get(); + const auto& idx = db().get_index_type().indices().get(); auto itr = idx.find(op.son_id); if(itr != idx.end()) { @@ -60,14 +60,14 @@ void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); - const auto& idx = db().get_index_type().indices().get(); + const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } void_result delete_son_evaluator::do_apply(const son_delete_operation& op) { try { - const auto& idx = db().get_index_type().indices().get(); + const auto& idx = db().get_index_type().indices().get(); db().remove(*idx.find(op.son_id)); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 741c1764e..1005e634f 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -188,6 +188,7 @@ struct wallet_data // incomplete account regs map > pending_account_registrations; map pending_witness_registrations; + map pending_son_registrations; key_label_index_type labeled_keys; blind_receipt_index_type blind_receipts; @@ -1932,7 +1933,7 @@ FC_REFLECT( graphene::wallet::wallet_data, (my_accounts) (cipher_keys) (extra_keys) - (pending_account_registrations)(pending_witness_registrations) + (pending_account_registrations)(pending_witness_registrations)(pending_son_registrations) (labeled_keys) (blind_receipts) (committed_game_moves) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 3f9c4eda6..39a1998c1 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -292,6 +292,23 @@ class wallet_api_impl _wallet.pending_account_registrations.erase( it ); } + // after a son registration succeeds, this saves the private key in the wallet permanently + // + void claim_registered_son(const std::string& son_name) + { + auto iter = _wallet.pending_son_registrations.find(son_name); + FC_ASSERT(iter != _wallet.pending_son_registrations.end()); + std::string wif_key = iter->second; + + // get the list key id this key is registered with in the chain + fc::optional son_private_key = wif_to_key(wif_key); + FC_ASSERT(son_private_key); + + auto pub_key = son_private_key->get_public_key(); + _keys[pub_key] = wif_key; + _wallet.pending_son_registrations.erase(iter); + } + // after a witness registration succeeds, this saves the private key in the wallet permanently // void claim_registered_witness(const std::string& witness_name) @@ -353,6 +370,24 @@ class wallet_api_impl claim_registered_witness(optional_account->name); } } + + if (!_wallet.pending_son_registrations.empty()) + { + // make a vector of the owner accounts for sons pending registration + std::vector pending_son_names = boost::copy_range >(boost::adaptors::keys(_wallet.pending_son_registrations)); + + // look up the owners on the blockchain + std::vector> owner_account_objects = _remote_db->lookup_account_names(pending_son_names); + + // if any of them have registered sons, claim them + for( const fc::optional& optional_account : owner_account_objects ) + if (optional_account) + { + fc::optional son_obj = _remote_db->get_son_by_account(optional_account->id); + if (son_obj) + claim_registered_son(optional_account->name); + } + } } // return true if any of my_accounts are players in this tournament @@ -665,6 +700,7 @@ class wallet_api_impl result["participation"] = (100*dynamic_props.recent_slots_filled.popcount()) / 128.0; result["active_witnesses"] = global_props.active_witnesses; result["active_committee_members"] = global_props.active_committee_members; + result["active_sons"] = global_props.active_sons; result["entropy"] = dynamic_props.random; return result; } @@ -1807,8 +1843,6 @@ class wallet_api_impl secret_hash_type::encoder enc; fc::raw::pack(enc, son_private_key); fc::raw::pack(enc, secret_hash_type()); - //son_create_op.initial_secret = secret_hash_type::hash(enc.result()); - if (_remote_db->get_son_by_account(son_create_op.owner_account)) FC_THROW("Account ${owner_account} is already a SON", ("owner_account", owner_account)); @@ -1818,7 +1852,7 @@ class wallet_api_impl set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); tx.validate(); - //_wallet.pending_witness_registrations[owner_account] = key_to_wif(son_private_key); + _wallet.pending_son_registrations[owner_account] = key_to_wif(son_private_key); return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 75986ca77..1b8f1cbc5 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) { } generate_block(); - const auto& idx = db.get_index_type().indices().get(); + 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() ); @@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE( update_son_test ) { } generate_block(); - const auto& idx = db.get_index_type().indices().get(); + 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() ); @@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE( delete_son_test ) { } generate_block(); - const auto& idx = db.get_index_type().indices().get(); + const auto& idx = db.get_index_type().indices().get(); BOOST_REQUIRE( idx.empty() ); } @@ -153,7 +153,7 @@ try { set_expiration(db, trx); trx.clear(); - const auto& idx = db.get_index_type().indices().get(); + const auto& idx = db.get_index_type().indices().get(); auto obj = idx.find( alice_id ); BOOST_REQUIRE( obj != idx.end() ); // not changing From 457c8b9d9f8ded0f06d7c84fd11e33369622dd2c Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 01:17:29 +0200 Subject: [PATCH 16/34] WIP, SON related operations, cli_wallet commands and RPC - Updating global_property_object --- libraries/chain/db_init.cpp | 3 +- libraries/chain/db_maint.cpp | 105 ++++++++++++++++++ .../chain/include/graphene/chain/config.hpp | 4 + .../chain/include/graphene/chain/database.hpp | 2 + .../graphene/chain/global_property_object.hpp | 1 + .../chain/immutable_chain_parameters.hpp | 2 + .../chain/protocol/chain_parameters.hpp | 2 + 7 files changed, 117 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 5e7ab107c..3f95b44ba 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -256,6 +256,7 @@ void database::initialize_indexes() acnt_index->add_secondary_index(); add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); @@ -304,8 +305,6 @@ void database::initialize_indexes() //add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); - - add_index< primary_index >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 06e15a196..ab89b2281 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -326,6 +326,96 @@ void database::update_active_committee_members() }); } FC_CAPTURE_AND_RETHROW() } +void database::update_active_sons() +{ try { + assert( _sons_count_histogram_buffer.size() > 0 ); + share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2; + + /// accounts that vote for 0 or 1 son do not get to express an opinion on + /// the number of sons to have (they abstain and are non-voting accounts) + + share_type stake_tally = 0; + + size_t son_count = 0; + if( stake_target > 0 ) + { + while( (son_count < _sons_count_histogram_buffer.size() - 1) + && (stake_tally <= stake_target) ) + { + stake_tally += _sons_count_histogram_buffer[++son_count]; + } + } + + const chain_property_object& cpo = get_chain_properties(); + auto sons = sort_votable_objects(std::max(son_count*2+1, (size_t)cpo.immutable_parameters.min_son_count)); + + const global_property_object& gpo = get_global_properties(); + + const auto& all_sons = get_index_type().indices(); + + for( const son_object& son : all_sons ) + { + modify( son, [&]( son_object& obj ){ + obj.total_votes = _vote_tally_buffer[son.vote_id]; + }); + } + + // Update SON authority + modify( get(GRAPHENE_SON_ACCOUNT_ID), [&]( account_object& a ) + { + if( head_block_time() < HARDFORK_533_TIME ) + { + uint64_t total_votes = 0; + map weights; + a.active.weight_threshold = 0; + a.active.clear(); + + for( const son_object& son : sons ) + { + weights.emplace(son.son_member_account, _vote_tally_buffer[son.vote_id]); + total_votes += _vote_tally_buffer[son.vote_id]; + } + + // total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits, + // then I want to keep the most significant 16 bits of what's left. + int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0); + for( const auto& weight : weights ) + { + // Ensure that everyone has at least one vote. Zero weights aren't allowed. + uint16_t votes = std::max((weight.second >> bits_to_drop), uint64_t(1) ); + a.active.account_auths[weight.first] += votes; + a.active.weight_threshold += votes; + } + + a.active.weight_threshold /= 2; + a.active.weight_threshold += 1; + } + else + { + vote_counter vc; + for( const son_object& son : sons ) + vc.add( son.son_member_account, std::max(_vote_tally_buffer[son.vote_id], UINT64_C(1)) ); + vc.finish( a.active ); + } + } ); + + modify(gpo, [&]( global_property_object& gp ){ + gp.active_sons.clear(); + gp.active_sons.reserve(sons.size()); + std::transform(sons.begin(), sons.end(), + std::inserter(gp.active_sons, gp.active_sons.end()), + [](const son_object& s) { + return s.id; + }); + }); + + //const witness_schedule_object& wso = witness_schedule_id_type()(*this); + //modify(wso, [&](witness_schedule_object& _wso) + //{ + // _wso.scheduler.update(gpo.active_witnesses); + //}); +} FC_CAPTURE_AND_RETHROW() } + void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); @@ -1401,6 +1491,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._vote_tally_buffer.resize(props.next_available_vote_id); d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); + d._sons_count_histogram_buffer.resize(props.parameters.maximum_son s committee_count / 2 + 1); d._total_voting_stake = 0; auto balance_type = vesting_balance_type::unspecified; @@ -1503,6 +1594,18 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g // same rationale as for witnesses d._committee_count_histogram_buffer[offset] += voting_stake; } + if( opinion_account.options.num_son <= props.parameters.maximum_son_count ) + { + uint16_t offset = std::min(size_t(opinion_account.options.num_son/2), + d._son_count_histogram_buffer.size() - 1); + // votes for a number greater than maximum_son_count + // are turned into votes for maximum_son_count. + // + // in particular, this takes care of the case where a + // member was voting for a high number, then the + // parameter was lowered. + d._son_count_histogram_buffer[offset] += voting_stake; + } d._total_voting_stake += voting_stake; } @@ -1533,11 +1636,13 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g }; clear_canary a(_witness_count_histogram_buffer), b(_committee_count_histogram_buffer), + d(_son_count_histogram_buffer), c(_vote_tally_buffer); update_top_n_authorities(*this); update_active_witnesses(); update_active_committee_members(); + update_active_sons(); update_worker_votes(); modify(gpo, [this](global_property_object& p) { diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7b3e87439..62ad468f5 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -90,8 +90,10 @@ #define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT (11) #define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT (11) +#define GRAPHENE_DEFAULT_MIN_SON_COUNT (5) #define GRAPHENE_DEFAULT_MAX_WITNESSES (1001) // SHOULD BE ODD #define GRAPHENE_DEFAULT_MAX_COMMITTEE (1001) // SHOULD BE ODD +#define GRAPHENE_DEFAULT_MAX_SONS (15) #define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC (60*60*24*7*4) // Four weeks #define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks #define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT) @@ -173,6 +175,8 @@ #define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5)) /// #define GRAPHENE_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6)) +/// +#define GRAPHENE_SON_ACCOUNT_ID (graphene::chain::account_id_type(7)) /// Sentinel value used in the scheduler. #define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0)) ///@} diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 179fb2dfb..9d7967b92 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -497,6 +497,7 @@ namespace graphene { namespace chain { void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); void update_active_witnesses(); void update_active_committee_members(); + void update_active_sons(); void update_worker_votes(); public: double calculate_vesting_factor(const account_object& stake_account); @@ -537,6 +538,7 @@ namespace graphene { namespace chain { vector _vote_tally_buffer; vector _witness_count_histogram_buffer; vector _committee_count_histogram_buffer; + vector _sons_count_histogram_buffer; uint64_t _total_voting_stake; flat_map _checkpoints; diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index b976eea08..788ccdafd 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -150,4 +150,5 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje (next_available_vote_id) (active_committee_members) (active_witnesses) + (active_sons) ) diff --git a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp index 0082383c9..ade1a459a 100644 --- a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp @@ -35,6 +35,7 @@ struct immutable_chain_parameters { uint16_t min_committee_member_count = GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT; uint16_t min_witness_count = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT; + uint16_t min_son_count = GRAPHENE_DEFAULT_MIN_SON_COUNT; uint32_t num_special_accounts = 0; uint32_t num_special_assets = 0; }; @@ -44,6 +45,7 @@ struct immutable_chain_parameters FC_REFLECT( graphene::chain::immutable_chain_parameters, (min_committee_member_count) (min_witness_count) + (min_son_count) (num_special_accounts) (num_special_assets) ) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 87c2e3fef..2d97857e6 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -61,6 +61,7 @@ namespace graphene { namespace chain { uint8_t maximum_asset_feed_publishers = GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS; ///< the maximum number of feed publishers for a given asset uint16_t maximum_witness_count = GRAPHENE_DEFAULT_MAX_WITNESSES; ///< maximum number of active witnesses uint16_t maximum_committee_count = GRAPHENE_DEFAULT_MAX_COMMITTEE; ///< maximum number of active committee_members + uint16_t maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS uint16_t maximum_authority_membership = GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP; ///< largest number of keys/accounts an authority can have uint16_t reserve_percent_of_fee = GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE; ///< the percentage of the network's allocation of a fee that is taken out of circulation uint16_t network_percent_of_fee = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; ///< percent of transaction fees paid to network @@ -150,6 +151,7 @@ FC_REFLECT( graphene::chain::chain_parameters, (maximum_asset_feed_publishers) (maximum_witness_count) (maximum_committee_count) + (maximum_son_count) (maximum_authority_membership) (reserve_percent_of_fee) (network_percent_of_fee) From 49564af60ad4ade409eb660af5ce99c8b966cba0 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 01:17:29 +0200 Subject: [PATCH 17/34] WIP, SON related operations, cli_wallet commands and RPC - Updating global_property_object --- libraries/chain/db_init.cpp | 3 +- libraries/chain/db_maint.cpp | 105 ++++++++++++++++++ .../chain/include/graphene/chain/config.hpp | 4 + .../chain/include/graphene/chain/database.hpp | 2 + .../graphene/chain/global_property_object.hpp | 1 + .../chain/immutable_chain_parameters.hpp | 2 + .../chain/protocol/chain_parameters.hpp | 2 + 7 files changed, 117 insertions(+), 2 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 5e7ab107c..3f95b44ba 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -256,6 +256,7 @@ void database::initialize_indexes() acnt_index->add_secondary_index(); add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); @@ -304,8 +305,6 @@ void database::initialize_indexes() //add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); - - add_index< primary_index >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 06e15a196..c6ea58f71 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -326,6 +326,96 @@ void database::update_active_committee_members() }); } FC_CAPTURE_AND_RETHROW() } +void database::update_active_sons() +{ try { + assert( _son_count_histogram_buffer.size() > 0 ); + share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2; + + /// accounts that vote for 0 or 1 son do not get to express an opinion on + /// the number of sons to have (they abstain and are non-voting accounts) + + share_type stake_tally = 0; + + size_t son_count = 0; + if( stake_target > 0 ) + { + while( (son_count < _son_count_histogram_buffer.size() - 1) + && (stake_tally <= stake_target) ) + { + stake_tally += _son_count_histogram_buffer[++son_count]; + } + } + + const chain_property_object& cpo = get_chain_properties(); + auto sons = sort_votable_objects(std::max(son_count*2+1, (size_t)cpo.immutable_parameters.min_son_count)); + + const global_property_object& gpo = get_global_properties(); + + const auto& all_sons = get_index_type().indices(); + + for( const son_object& son : all_sons ) + { + modify( son, [&]( son_object& obj ){ + obj.total_votes = _vote_tally_buffer[son.vote_id]; + }); + } + + // Update SON authority + modify( get(GRAPHENE_SON_ACCOUNT_ID), [&]( account_object& a ) + { + if( head_block_time() < HARDFORK_533_TIME ) + { + uint64_t total_votes = 0; + map weights; + a.active.weight_threshold = 0; + a.active.clear(); + + for( const son_object& son : sons ) + { + weights.emplace(son.son_member_account, _vote_tally_buffer[son.vote_id]); + total_votes += _vote_tally_buffer[son.vote_id]; + } + + // total_votes is 64 bits. Subtract the number of leading low bits from 64 to get the number of useful bits, + // then I want to keep the most significant 16 bits of what's left. + int8_t bits_to_drop = std::max(int(boost::multiprecision::detail::find_msb(total_votes)) - 15, 0); + for( const auto& weight : weights ) + { + // Ensure that everyone has at least one vote. Zero weights aren't allowed. + uint16_t votes = std::max((weight.second >> bits_to_drop), uint64_t(1) ); + a.active.account_auths[weight.first] += votes; + a.active.weight_threshold += votes; + } + + a.active.weight_threshold /= 2; + a.active.weight_threshold += 1; + } + else + { + vote_counter vc; + for( const son_object& son : sons ) + vc.add( son.son_member_account, std::max(_vote_tally_buffer[son.vote_id], UINT64_C(1)) ); + vc.finish( a.active ); + } + } ); + + modify(gpo, [&]( global_property_object& gp ){ + gp.active_sons.clear(); + gp.active_sons.reserve(sons.size()); + std::transform(sons.begin(), sons.end(), + std::inserter(gp.active_sons, gp.active_sons.end()), + [](const son_object& s) { + return s.id; + }); + }); + + //const witness_schedule_object& wso = witness_schedule_id_type()(*this); + //modify(wso, [&](witness_schedule_object& _wso) + //{ + // _wso.scheduler.update(gpo.active_witnesses); + //}); +} FC_CAPTURE_AND_RETHROW() } + void database::initialize_budget_record( fc::time_point_sec now, budget_record& rec )const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); @@ -1401,6 +1491,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._vote_tally_buffer.resize(props.next_available_vote_id); d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); + d._son_count_histogram_buffer.resize(props.parameters.maximum_son s committee_count / 2 + 1); d._total_voting_stake = 0; auto balance_type = vesting_balance_type::unspecified; @@ -1503,6 +1594,18 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g // same rationale as for witnesses d._committee_count_histogram_buffer[offset] += voting_stake; } + if( opinion_account.options.num_son <= props.parameters.maximum_son_count ) + { + uint16_t offset = std::min(size_t(opinion_account.options.num_son/2), + d._son_count_histogram_buffer.size() - 1); + // votes for a number greater than maximum_son_count + // are turned into votes for maximum_son_count. + // + // in particular, this takes care of the case where a + // member was voting for a high number, then the + // parameter was lowered. + d._son_count_histogram_buffer[offset] += voting_stake; + } d._total_voting_stake += voting_stake; } @@ -1533,11 +1636,13 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g }; clear_canary a(_witness_count_histogram_buffer), b(_committee_count_histogram_buffer), + d(_son_count_histogram_buffer), c(_vote_tally_buffer); update_top_n_authorities(*this); update_active_witnesses(); update_active_committee_members(); + update_active_sons(); update_worker_votes(); modify(gpo, [this](global_property_object& p) { diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7b3e87439..62ad468f5 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -90,8 +90,10 @@ #define GRAPHENE_DEFAULT_MIN_WITNESS_COUNT (11) #define GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT (11) +#define GRAPHENE_DEFAULT_MIN_SON_COUNT (5) #define GRAPHENE_DEFAULT_MAX_WITNESSES (1001) // SHOULD BE ODD #define GRAPHENE_DEFAULT_MAX_COMMITTEE (1001) // SHOULD BE ODD +#define GRAPHENE_DEFAULT_MAX_SONS (15) #define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC (60*60*24*7*4) // Four weeks #define GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks #define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT) @@ -173,6 +175,8 @@ #define GRAPHENE_PROXY_TO_SELF_ACCOUNT (graphene::chain::account_id_type(5)) /// #define GRAPHENE_RAKE_FEE_ACCOUNT_ID (graphene::chain::account_id_type(6)) +/// +#define GRAPHENE_SON_ACCOUNT_ID (graphene::chain::account_id_type(7)) /// Sentinel value used in the scheduler. #define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0)) ///@} diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 179fb2dfb..5a2530f6c 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -497,6 +497,7 @@ namespace graphene { namespace chain { void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); void update_active_witnesses(); void update_active_committee_members(); + void update_active_sons(); void update_worker_votes(); public: double calculate_vesting_factor(const account_object& stake_account); @@ -537,6 +538,7 @@ namespace graphene { namespace chain { vector _vote_tally_buffer; vector _witness_count_histogram_buffer; vector _committee_count_histogram_buffer; + vector _son_count_histogram_buffer; uint64_t _total_voting_stake; flat_map _checkpoints; diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index b976eea08..788ccdafd 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -150,4 +150,5 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje (next_available_vote_id) (active_committee_members) (active_witnesses) + (active_sons) ) diff --git a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp index 0082383c9..ade1a459a 100644 --- a/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/immutable_chain_parameters.hpp @@ -35,6 +35,7 @@ struct immutable_chain_parameters { uint16_t min_committee_member_count = GRAPHENE_DEFAULT_MIN_COMMITTEE_MEMBER_COUNT; uint16_t min_witness_count = GRAPHENE_DEFAULT_MIN_WITNESS_COUNT; + uint16_t min_son_count = GRAPHENE_DEFAULT_MIN_SON_COUNT; uint32_t num_special_accounts = 0; uint32_t num_special_assets = 0; }; @@ -44,6 +45,7 @@ struct immutable_chain_parameters FC_REFLECT( graphene::chain::immutable_chain_parameters, (min_committee_member_count) (min_witness_count) + (min_son_count) (num_special_accounts) (num_special_assets) ) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 87c2e3fef..2d97857e6 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -61,6 +61,7 @@ namespace graphene { namespace chain { uint8_t maximum_asset_feed_publishers = GRAPHENE_DEFAULT_MAX_ASSET_FEED_PUBLISHERS; ///< the maximum number of feed publishers for a given asset uint16_t maximum_witness_count = GRAPHENE_DEFAULT_MAX_WITNESSES; ///< maximum number of active witnesses uint16_t maximum_committee_count = GRAPHENE_DEFAULT_MAX_COMMITTEE; ///< maximum number of active committee_members + uint16_t maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS uint16_t maximum_authority_membership = GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP; ///< largest number of keys/accounts an authority can have uint16_t reserve_percent_of_fee = GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE; ///< the percentage of the network's allocation of a fee that is taken out of circulation uint16_t network_percent_of_fee = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; ///< percent of transaction fees paid to network @@ -150,6 +151,7 @@ FC_REFLECT( graphene::chain::chain_parameters, (maximum_asset_feed_publishers) (maximum_witness_count) (maximum_committee_count) + (maximum_son_count) (maximum_authority_membership) (reserve_percent_of_fee) (network_percent_of_fee) From e0ff81387996165fa37b69fac63e4a2632077d51 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 01:24:31 +0200 Subject: [PATCH 18/34] WIP, SON operations, cli_wallet commands and RPC - Updating global_property_object --- libraries/chain/db_maint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index c6ea58f71..ce1783d82 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1491,7 +1491,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._vote_tally_buffer.resize(props.next_available_vote_id); d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); - d._son_count_histogram_buffer.resize(props.parameters.maximum_son s committee_count / 2 + 1); + d._son_count_histogram_buffer.resize(props.parameters.maximum_son / 2 + 1); d._total_voting_stake = 0; auto balance_type = vesting_balance_type::unspecified; From 203ee892186fa610fd3bccbf0bf7d98e241344a1 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 01:26:35 +0200 Subject: [PATCH 19/34] WIP, SON operations, cli_wallet commands and RPC - Updating global_property_object --- libraries/chain/db_maint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index ce1783d82..7b3791462 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -1491,7 +1491,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g d._vote_tally_buffer.resize(props.next_available_vote_id); d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); - d._son_count_histogram_buffer.resize(props.parameters.maximum_son / 2 + 1); + d._son_count_histogram_buffer.resize(props.parameters.maximum_son_count / 2 + 1); d._total_voting_stake = 0; auto balance_type = vesting_balance_type::unspecified; From ecfcd8eda1f9e10b9deeb36510eec17da8d1165f Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 19:02:55 +0200 Subject: [PATCH 20/34] WIP, SON operations, cli_wallet commands and RPC - Decrease SON hardfork time for test purposes --- libraries/chain/hardfork.d/SON.hf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/hardfork.d/SON.hf b/libraries/chain/hardfork.d/SON.hf index badde1f45..ac4a053b2 100644 --- a/libraries/chain/hardfork.d/SON.hf +++ b/libraries/chain/hardfork.d/SON.hf @@ -1,4 +1,4 @@ // SON HARDFORK Monday, September 21, 2020 1:43:11 PM #ifndef HARDFORK_SON_TIME -#define HARDFORK_SON_TIME (fc::time_point_sec( 1600695791 )) +#define HARDFORK_SON_TIME (fc::time_point_sec( 1000000000 )) #endif \ No newline at end of file From 4d1bec05bc6fd7b3ab36c6a59097cd393dd8cee7 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 19:50:49 +0200 Subject: [PATCH 21/34] WIP, SON operations, cli_wallet commands and RPC - get_son in cli_wallet --- libraries/wallet/include/graphene/wallet/wallet.hpp | 6 ++++++ libraries/wallet/wallet.cpp | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 1005e634f..23a648f3e 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1260,6 +1260,12 @@ class wallet_api */ map list_committee_members(const string& lowerbound, uint32_t limit); + /** Returns information about the given son. + * @param owner_account the name or id of the SON account owner, or the id of the SON + * @returns the information about the SON stored in the block chain + */ + son_object get_son(string owner_account); + /** Returns information about the given witness. * @param owner_account the name or id of the witness account owner, or the id of the witness * @returns the information about the witness stored in the block chain diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 39a1998c1..e6664fdee 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4155,6 +4155,11 @@ map wallet_api::list_committee_members(const st return my->_remote_db->lookup_committee_member_accounts(lowerbound, limit); } +son_object wallet_api::get_son(string owner_account) +{ + return my->get_son(owner_account); +} + witness_object wallet_api::get_witness(string owner_account) { return my->get_witness(owner_account); From 5ecbba87179ddceb14485c30d2e497d52f523fc6 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 3 Oct 2019 19:57:34 +0200 Subject: [PATCH 22/34] WIP, SON operations, cli_wallet commands and RPC - get_son in cli_wallet --- libraries/wallet/include/graphene/wallet/wallet.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 23a648f3e..84f4d9838 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -2040,6 +2040,7 @@ FC_API( graphene::wallet::wallet_api, (settle_asset) (whitelist_account) (create_committee_member) + (get_son) (get_witness) (get_committee_member) (list_witnesses) From e4bf00e349ba06b57044c1bafb0bea66efcddc99 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Fri, 4 Oct 2019 01:24:30 +0200 Subject: [PATCH 23/34] WIP, SON operations, cli_wallet commands and RPC - update_son_votes --- .../wallet/include/graphene/wallet/wallet.hpp | 36 ++++++++++++- libraries/wallet/wallet.cpp | 50 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 84f4d9838..584596153 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1464,9 +1464,42 @@ class wallet_api bool approve, bool broadcast = false); + /** Change your SON votes. + * + * An account can publish a list of all SONs they approve of. + * Each account's vote is weighted according to the number of shares of the + * core asset owned by that account at the time the votes are tallied. + * This command allows you to add or remove one or more SON from this list + * in one call. When you are changing your vote on several SONs, this + * may be easier than multiple `vote_for_sons` and + * `set_desired_witness_and_committee_member_count` calls. + * + * @note you cannot vote against a SON, you can only vote for the SON + * or not vote for the SON. + * + * @param voting_account the name or id of the account who is voting with their shares + * @param sons_to_approve the names or ids of the sons owner accounts you wish + * to approve (these will be added to the list of sons + * you currently approve). This list can be empty. + * @param sons_to_reject the names or ids of the SONs owner accounts you wish + * to reject (these will be removed from the list of SONs + * you currently approve). This list can be empty. + * @param desired_number_of_sons the number of SONs you believe the network + * should have. You must vote for at least this many + * SONs. You can set this to 0 to abstain from + * voting on the number of SONNs. + * @param broadcast true if you wish to broadcast the transaction + * @return the signed transaction changing your vote for the given witnesses + */ + signed_transaction update_son_votes(string voting_account, + std::vector sons_to_approve, + std::vector sons_to_reject, + uint16_t desired_number_of_son, + bool broadcast = false); + /** Vote for a given witness. * - * An account can publish a list of all witnesses they approve of. This + * An account can publish a list of all witnesses they approve of. This * command allows you to add or remove witnesses from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -2057,6 +2090,7 @@ FC_API( graphene::wallet::wallet_api, (withdraw_vesting) (vote_for_committee_member) (vote_for_son_member) + (update_son_votes) (vote_for_witness) (update_witness_votes) (set_voting_proxy) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index e6664fdee..fbb06eb35 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2205,6 +2205,47 @@ class wallet_api_impl return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (voting_account)(son_member)(approve)(broadcast) ) } + signed_transaction update_son_votes(string voting_account, + std::vector sons_to_approve, + std::vector sons_to_reject, + uint16_t desired_number_of_sons, + bool broadcast /* = false */) + { try { + account_object voting_account_object = get_account(voting_account); + for (const std::string& son : sons_to_approve) + { + account_id_type son_owner_account_id = get_account_id(son); + fc::optional son_obj = _remote_db->get_son_by_account(son_owner_account_id); + if (!son_obj) + FC_THROW("Account ${son} is not registered as a witness", ("son", son)); + auto insert_result = voting_account_object.options.votes.insert(son_obj->vote_id); + if (!insert_result.second) + FC_THROW("Account ${account} was already voting for son ${son}", ("account", voting_account)("son", son)); + } + for (const std::string& son : sons_to_reject) + { + account_id_type son_owner_account_id = get_account_id(son); + fc::optional son_obj = _remote_db->get_son_by_account(son_owner_account_id); + if (!son_obj) + FC_THROW("Account ${son} is not registered as a son", ("son", son)); + unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id); + if (!votes_removed) + FC_THROW("Account ${account} is already not voting for son ${son}", ("account", voting_account)("son", son)); + } + voting_account_object.options.num_son = desired_number_of_sons; + + account_update_operation account_update_op; + account_update_op.account = voting_account_object.id; + account_update_op.new_options = voting_account_object.options; + + signed_transaction tx; + tx.operations.push_back( account_update_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (voting_account)(sons_to_approve)(sons_to_reject)(desired_number_of_sons)(broadcast) ) } + signed_transaction vote_for_witness(string voting_account, string witness, bool approve, @@ -4264,6 +4305,15 @@ signed_transaction wallet_api::vote_for_son_member(string voting_account, return my->vote_for_son_member(voting_account, son_member, approve, broadcast); } +signed_transaction wallet_api::update_son_votes(string voting_account, + std::vector sons_to_approve, + std::vector sons_to_reject, + uint16_t desired_number_of_sons, + bool broadcast /* = false */) +{ + return my->update_son_votes(voting_account, sons_to_approve, sons_to_reject, desired_number_of_sons, broadcast); +} + signed_transaction wallet_api::vote_for_witness(string voting_account, string witness, bool approve, From 8bc204c69bb4f248cf93ea9b93202714b92535ff Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Fri, 4 Oct 2019 02:43:16 +0200 Subject: [PATCH 24/34] WIP, SON operations, cli_wallet commands and RPC - rename vote_for_son_member to vote_for_son --- libraries/wallet/include/graphene/wallet/wallet.hpp | 4 ++-- libraries/wallet/wallet.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 584596153..d8d7330ac 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1459,7 +1459,7 @@ class wallet_api * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given son_member */ - signed_transaction vote_for_son_member(string voting_account, + signed_transaction vote_for_son(string voting_account, string son_member, bool approve, bool broadcast = false); @@ -2089,7 +2089,7 @@ FC_API( graphene::wallet::wallet_api, (get_vesting_balances) (withdraw_vesting) (vote_for_committee_member) - (vote_for_son_member) + (vote_for_son) (update_son_votes) (vote_for_witness) (update_witness_votes) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index fbb06eb35..bce5ec250 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2171,7 +2171,7 @@ class wallet_api_impl return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (voting_account)(committee_member)(approve)(broadcast) ) } - signed_transaction vote_for_son_member(string voting_account, + signed_transaction vote_for_son(string voting_account, string son_member, bool approve, bool broadcast /* = false */) @@ -4297,12 +4297,12 @@ signed_transaction wallet_api::vote_for_committee_member(string voting_account, return my->vote_for_committee_member(voting_account, witness, approve, broadcast); } -signed_transaction wallet_api::vote_for_son_member(string voting_account, +signed_transaction wallet_api::vote_for_son(string voting_account, string son_member, bool approve, bool broadcast /* = false */) { - return my->vote_for_son_member(voting_account, son_member, approve, broadcast); + return my->vote_for_son(voting_account, son_member, approve, broadcast); } signed_transaction wallet_api::update_son_votes(string voting_account, From 3e4322b08dbb44470214d4d5c97cbdba312b8d85 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Sun, 6 Oct 2019 14:08:15 +0200 Subject: [PATCH 25/34] WIP, SON operations, cli_wallet commands and RPC - CLI Wallet tests imported from develop branch --- tests/CMakeLists.txt | 10 + tests/cli/main.cpp | 482 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 492 insertions(+) create mode 100644 tests/cli/main.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fef122b5d..472da6766 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,4 +45,14 @@ file(GLOB RANDOM_SOURCES "random/*.cpp") add_executable( random_test ${RANDOM_SOURCES} ${COMMON_SOURCES} ) target_link_libraries( random_test graphene_chain graphene_app graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +file(GLOB CLI_SOURCES "cli/*.cpp") +add_executable( cli_test ${CLI_SOURCES} ) +if(WIN32) + list(APPEND PLATFORM_SPECIFIC_LIBS ws2_32) +endif() +target_link_libraries( cli_test graphene_chain graphene_app graphene_witness graphene_wallet graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +if(MSVC) + set_source_files_properties( cli/main.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) +endif(MSVC) + add_subdirectory( generate_empty_blocks ) diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp new file mode 100644 index 000000000..acaf30126 --- /dev/null +++ b/tests/cli/main.cpp @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2019 PBSA, 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 + +#ifdef _WIN32 +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 + #endif + #include + #include +#else +#include +#include +#include +#endif +#include + +#include + +#define BOOST_TEST_MODULE Test Application +#include + +/***** + * Global Initialization for Windows + * ( sets up Winsock stuf ) + */ +#ifdef _WIN32 +int sockInit(void) +{ + WSADATA wsa_data; + return WSAStartup(MAKEWORD(1,1), &wsa_data); +} +int sockQuit(void) +{ + return WSACleanup(); +} +#endif + +/********************* + * Helper Methods + *********************/ + +#include "../common/genesis_file_util.hpp" + +#define INVOKE(test) ((struct test*)this)->test_method(); + +////// +/// @brief attempt to find an available port on localhost +/// @returns an available port number, or -1 on error +///// +int get_available_port() +{ + struct sockaddr_in sin; + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd == -1) + return -1; + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (::bind(socket_fd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) == -1) + return -1; + socklen_t len = sizeof(sin); + if (getsockname(socket_fd, (struct sockaddr *)&sin, &len) == -1) + return -1; +#ifdef _WIN32 + closesocket(socket_fd); +#else + close(socket_fd); +#endif + return ntohs(sin.sin_port); +} + +/////////// +/// @brief Start the application +/// @param app_dir the temporary directory to use +/// @param server_port_number to be filled with the rpc endpoint port number +/// @returns the application object +////////// +std::shared_ptr start_application(fc::temp_directory& app_dir, int& server_port_number) { + std::shared_ptr app1(new graphene::app::application{}); + + app1->register_plugin< graphene::bookie::bookie_plugin>(); + app1->register_plugin(); + app1->startup_plugins(); + boost::program_options::variables_map cfg; +#ifdef _WIN32 + sockInit(); +#endif + server_port_number = get_available_port(); + cfg.emplace( + "rpc-endpoint", + boost::program_options::variable_value(string("127.0.0.1:" + std::to_string(server_port_number)), false) + ); + cfg.emplace("genesis-json", boost::program_options::variable_value(create_genesis_file(app_dir), false)); + cfg.emplace("seed-nodes", boost::program_options::variable_value(string("[]"), false)); + + app1->initialize(app_dir.path(), cfg); + + app1->initialize_plugins(cfg); + app1->startup_plugins(); + + app1->startup(); + fc::usleep(fc::milliseconds(500)); + return app1; +} + +/////////// +/// Send a block to the db +/// @param app the application +/// @param returned_block the signed block +/// @returns true on success +/////////// +bool generate_block(std::shared_ptr app, graphene::chain::signed_block& returned_block) +{ + try { + fc::ecc::private_key committee_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan"))); + auto db = app->chain_database(); + returned_block = db->generate_block( db->get_slot_time(1), + db->get_scheduled_witness(1), + committee_key, + database::skip_nothing ); + return true; + } catch (exception &e) { + return false; + } +} + +bool generate_block(std::shared_ptr app) +{ + graphene::chain::signed_block returned_block; + return generate_block(app, returned_block); +} + +/////////// +/// @brief Skip intermediate blocks, and generate a maintenance block +/// @param app the application +/// @returns true on success +/////////// +bool generate_maintenance_block(std::shared_ptr app) { + try { + fc::ecc::private_key committee_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan"))); + uint32_t skip = ~0; + auto db = app->chain_database(); + auto maint_time = db->get_dynamic_global_properties().next_maintenance_time; + auto slots_to_miss = db->get_slot_at_time(maint_time); + db->generate_block(db->get_slot_time(slots_to_miss), + db->get_scheduled_witness(slots_to_miss), + committee_key, + skip); + return true; + } catch (exception& e) + { + return false; + } +} + +/////////// +/// @brief a class to make connecting to the application server easier +/////////// +class client_connection +{ +public: + ///////// + // constructor + ///////// + client_connection( + std::shared_ptr app, + const fc::temp_directory& data_dir, + const int server_port_number + ) + { + wallet_data.chain_id = app->chain_database()->get_chain_id(); + wallet_data.ws_server = "ws://127.0.0.1:" + std::to_string(server_port_number); + wallet_data.ws_user = ""; + wallet_data.ws_password = ""; + websocket_connection = websocket_client.connect( wallet_data.ws_server ); + + api_connection = std::make_shared(*websocket_connection); + + remote_login_api = api_connection->get_remote_api< graphene::app::login_api >(1); + BOOST_CHECK(remote_login_api->login( wallet_data.ws_user, wallet_data.ws_password ) ); + + wallet_api_ptr = std::make_shared(wallet_data, remote_login_api); + wallet_filename = data_dir.path().generic_string() + "/wallet.json"; + wallet_api_ptr->set_wallet_filename(wallet_filename); + + wallet_api = fc::api(wallet_api_ptr); + + wallet_cli = std::make_shared(); + for( auto& name_formatter : wallet_api_ptr->get_result_formatters() ) + wallet_cli->format_result( name_formatter.first, name_formatter.second ); + + boost::signals2::scoped_connection closed_connection(websocket_connection->closed.connect([=]{ + cerr << "Server has disconnected us.\n"; + wallet_cli->stop(); + })); + (void)(closed_connection); + } + ~client_connection() + { + // wait for everything to finish up + fc::usleep(fc::milliseconds(500)); + } +public: + fc::http::websocket_client websocket_client; + graphene::wallet::wallet_data wallet_data; + fc::http::websocket_connection_ptr websocket_connection; + std::shared_ptr api_connection; + fc::api remote_login_api; + std::shared_ptr wallet_api_ptr; + fc::api wallet_api; + std::shared_ptr wallet_cli; + std::string wallet_filename; +}; + + +/////////////////////////////// +// Cli Wallet Fixture +/////////////////////////////// + +struct cli_fixture +{ + class dummy + { + public: + ~dummy() + { + // wait for everything to finish up + fc::usleep(fc::milliseconds(500)); + } + }; + dummy dmy; + int server_port_number; + fc::temp_directory app_dir; + std::shared_ptr app1; + client_connection con; + std::vector nathan_keys; + + cli_fixture() : + server_port_number(0), + app_dir( graphene::utilities::temp_directory_path() ), + app1( start_application(app_dir, server_port_number) ), + con( app1, app_dir, server_port_number ), + nathan_keys( {"5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"} ) + { + BOOST_TEST_MESSAGE("Setup cli_wallet::boost_fixture_test_case"); + + using namespace graphene::chain; + using namespace graphene::app; + + try + { + BOOST_TEST_MESSAGE("Setting wallet password"); + con.wallet_api_ptr->set_password("supersecret"); + con.wallet_api_ptr->unlock("supersecret"); + + // import Nathan account + BOOST_TEST_MESSAGE("Importing nathan key"); + BOOST_CHECK_EQUAL(nathan_keys[0], "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"); + BOOST_CHECK(con.wallet_api_ptr->import_key("nathan", nathan_keys[0])); + } catch( fc::exception& e ) { + edump((e.to_detail_string())); + throw; + } + } + + ~cli_fixture() + { + BOOST_TEST_MESSAGE("Cleanup cli_wallet::boost_fixture_test_case"); + + // wait for everything to finish up + fc::usleep(fc::seconds(1)); + + app1->shutdown(); +#ifdef _WIN32 + sockQuit(); +#endif + } +}; + +/////////////////////////////// +// Tests +/////////////////////////////// + +//////////////// +// Start a server and connect using the same calls as the CLI +//////////////// +BOOST_FIXTURE_TEST_CASE( cli_connect, cli_fixture ) +{ + BOOST_TEST_MESSAGE("Testing wallet connection."); +} + +BOOST_FIXTURE_TEST_CASE( upgrade_nathan_account, cli_fixture ) +{ + try + { + BOOST_TEST_MESSAGE("Upgrade Nathan's account"); + + account_object nathan_acct_before_upgrade, nathan_acct_after_upgrade; + std::vector import_txs; + signed_transaction upgrade_tx; + + BOOST_TEST_MESSAGE("Importing nathan's balance"); + import_txs = con.wallet_api_ptr->import_balance("nathan", nathan_keys, true); + nathan_acct_before_upgrade = con.wallet_api_ptr->get_account("nathan"); + + BOOST_CHECK(generate_block(app1)); + + // upgrade nathan + BOOST_TEST_MESSAGE("Upgrading Nathan to LTM"); + upgrade_tx = con.wallet_api_ptr->upgrade_account("nathan", true); + + nathan_acct_after_upgrade = con.wallet_api_ptr->get_account("nathan"); + + // verify that the upgrade was successful + BOOST_CHECK_PREDICATE( + std::not_equal_to(), + (nathan_acct_before_upgrade.membership_expiration_date.sec_since_epoch()) + (nathan_acct_after_upgrade.membership_expiration_date.sec_since_epoch()) + ); + BOOST_CHECK(nathan_acct_after_upgrade.is_lifetime_member()); + } catch( fc::exception& e ) { + edump((e.to_detail_string())); + throw; + } +} + +BOOST_FIXTURE_TEST_CASE( create_new_account, cli_fixture ) +{ + try + { + INVOKE(upgrade_nathan_account); + + // create a new account + graphene::wallet::brain_key_info bki = con.wallet_api_ptr->suggest_brain_key(); + BOOST_CHECK(!bki.brain_priv_key.empty()); + signed_transaction create_acct_tx = con.wallet_api_ptr->create_account_with_brain_key( + bki.brain_priv_key, "jmjatlanta", "nathan", "nathan", true + ); + // save the private key for this new account in the wallet file + BOOST_CHECK(con.wallet_api_ptr->import_key("jmjatlanta", bki.wif_priv_key)); + con.wallet_api_ptr->save_wallet_file(con.wallet_filename); + + // attempt to give jmjatlanta some CORE + BOOST_TEST_MESSAGE("Transferring CORE from Nathan to jmjatlanta"); + signed_transaction transfer_tx = con.wallet_api_ptr->transfer( + "nathan", "jmjatlanta", "10000", "1.3.0", "Here are some CORE token for your new account", true + ); + } catch( fc::exception& e ) { + edump((e.to_detail_string())); + throw; + } +} + +/////////////////////// +// Start a server and connect using the same calls as the CLI +// Vote for two witnesses, and make sure they both stay there +// after a maintenance block +/////////////////////// +BOOST_FIXTURE_TEST_CASE( cli_vote_for_2_witnesses, cli_fixture ) +{ + try + { + BOOST_TEST_MESSAGE("Cli Vote Test for 2 Witnesses"); + + INVOKE(upgrade_nathan_account); // just to fund nathan + + // get the details for init1 + witness_object init1_obj = con.wallet_api_ptr->get_witness("init1"); + int init1_start_votes = init1_obj.total_votes; + // Vote for a witness + signed_transaction vote_witness1_tx = con.wallet_api_ptr->vote_for_witness("nathan", "init1", true, true); + + // generate a block to get things started + BOOST_CHECK(generate_block(app1)); + // wait for a maintenance interval + BOOST_CHECK(generate_maintenance_block(app1)); + + // Verify that the vote is there + init1_obj = con.wallet_api_ptr->get_witness("init1"); + witness_object init2_obj = con.wallet_api_ptr->get_witness("init2"); + int init1_middle_votes = init1_obj.total_votes; + BOOST_CHECK(init1_middle_votes > init1_start_votes); + + // Vote for a 2nd witness + int init2_start_votes = init2_obj.total_votes; + signed_transaction vote_witness2_tx = con.wallet_api_ptr->vote_for_witness("nathan", "init2", true, true); + + // send another block to trigger maintenance interval + BOOST_CHECK(generate_maintenance_block(app1)); + + // Verify that both the first vote and the 2nd are there + init2_obj = con.wallet_api_ptr->get_witness("init2"); + init1_obj = con.wallet_api_ptr->get_witness("init1"); + + int init2_middle_votes = init2_obj.total_votes; + BOOST_CHECK(init2_middle_votes > init2_start_votes); + int init1_last_votes = init1_obj.total_votes; + BOOST_CHECK(init1_last_votes > init1_start_votes); + } catch( fc::exception& e ) { + edump((e.to_detail_string())); + throw; + } +} + +/////////////////////// +// Check account history pagination +/////////////////////// +BOOST_FIXTURE_TEST_CASE( account_history_pagination, cli_fixture ) +{ + try + { + INVOKE(create_new_account); + + // attempt to give jmjatlanta some peerplay + BOOST_TEST_MESSAGE("Transferring peerplay from Nathan to jmjatlanta"); + for(int i = 1; i <= 199; i++) + { + signed_transaction transfer_tx = con.wallet_api_ptr->transfer("nathan", "jmjatlanta", std::to_string(i), + "1.3.0", "Here are some CORE token for your new account", true); + } + + BOOST_CHECK(generate_block(app1)); + + // now get account history and make sure everything is there (and no duplicates) + std::vector history = con.wallet_api_ptr->get_account_history("jmjatlanta", 300); + BOOST_CHECK_EQUAL(201u, history.size() ); + + std::set operation_ids; + + for(auto& op : history) + { + if( operation_ids.find(op.op.id) != operation_ids.end() ) + { + BOOST_FAIL("Duplicate found"); + } + operation_ids.insert(op.op.id); + } + } catch( fc::exception& e ) { + edump((e.to_detail_string())); + throw; + } +} \ No newline at end of file From 7b6562ec85653099f0252c93b44448bf912c2945 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 8 Oct 2019 21:14:26 +0200 Subject: [PATCH 26/34] Some renaming to follow existing naming convention, code cleanup --- .gitlab-ci.yml | 6 +- .gitmodules | 6 +- libraries/app/api.cpp | 2 +- libraries/app/database_api.cpp | 4 +- libraries/chain/db_init.cpp | 4 +- libraries/chain/db_maint.cpp | 8 +- libraries/chain/db_notify.cpp | 2 +- libraries/chain/hardfork.d/SON.hf | 3 +- .../include/graphene/chain/son_object.hpp | 12 +- libraries/chain/son_evaluator.cpp | 6 +- .../wallet/include/graphene/wallet/wallet.hpp | 174 +++++++++--------- libraries/wallet/wallet.cpp | 33 ++-- tests/tests/son_operations_tests.cpp | 2 +- 13 files changed, 129 insertions(+), 133 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8355d7959..9d39a4c12 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,10 +19,10 @@ build: - tests/ tags: - builder - + test: stage: test - dependencies: + dependencies: - build script: - ./tests/betting_test @@ -30,7 +30,7 @@ test: - ./tests/cli_test tags: - builder - + code_quality: stage: test image: docker:stable diff --git a/.gitmodules b/.gitmodules index 4a2c72e06..5572259c0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,6 +3,6 @@ url = https://github.com/bitshares/bitshares-core.wiki.git ignore = dirty [submodule "libraries/fc"] - path = libraries/fc - url = https://github.com/PBSA/peerplays-fc.git - ignore = dirty + path = libraries/fc + url = https://github.com/PBSA/peerplays-fc.git + ignore = dirty diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 264fee9db..833069f8a 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -441,7 +441,7 @@ namespace graphene { namespace app { } case son_object_type:{ const auto& aobj = dynamic_cast(obj); assert( aobj != nullptr ); - accounts.insert( aobj->son_member_account ); + accounts.insert( aobj->son_account ); break; } case sport_object_type: diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 4952cd4d0..a984394be 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -1736,13 +1736,13 @@ map database_api_impl::lookup_son_accounts(const string& lo const auto& sons_by_id = _db.get_index_type().indices().get(); // we want to order sons by account name, but that name is in the account object - // so the son_member_index doesn't have a quick way to access it. + // so the son_index doesn't have a quick way to access it. // get all the names and look them all up, sort them, then figure out what // records to return. This could be optimized, but we expect the // number of witnesses to be few and the frequency of calls to be rare std::map sons_by_account_name; for (const son_object& son : sons_by_id) - if (auto account_iter = _db.find(son.son_member_account)) + if (auto account_iter = _db.find(son.son_account)) if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name sons_by_account_name.insert(std::make_pair(account_iter->name, son.id)); diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 4f764a64c..02634c06a 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -262,10 +262,8 @@ void database::initialize_indexes() acnt_index->add_secondary_index(); add_index< primary_index >(); // 256 members per chunk + add_index< primary_index >(); // 256 sons per chunk add_index< primary_index >(); // 1024 witnesses per chunk - add_index< primary_index >(); - add_index< primary_index >(); - add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index ca5a2b606..765d3c72c 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -253,7 +253,7 @@ void database::update_active_witnesses() void database::update_active_committee_members() { try { assert( _committee_count_histogram_buffer.size() > 0 ); - share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2; + share_type stake_target = (_total_voting_stake-_committee_count_histogram_buffer[0]) / 2; /// accounts that vote for 0 or 1 witness do not get to express an opinion on /// the number of witnesses to have (they abstain and are non-voting accounts) @@ -329,7 +329,7 @@ void database::update_active_committee_members() void database::update_active_sons() { try { assert( _son_count_histogram_buffer.size() > 0 ); - share_type stake_target = (_total_voting_stake-_witness_count_histogram_buffer[0]) / 2; + share_type stake_target = (_total_voting_stake-_son_count_histogram_buffer[0]) / 2; /// accounts that vote for 0 or 1 son do not get to express an opinion on /// the number of sons to have (they abstain and are non-voting accounts) @@ -372,7 +372,7 @@ void database::update_active_sons() for( const son_object& son : sons ) { - weights.emplace(son.son_member_account, _vote_tally_buffer[son.vote_id]); + weights.emplace(son.son_account, _vote_tally_buffer[son.vote_id]); total_votes += _vote_tally_buffer[son.vote_id]; } @@ -394,7 +394,7 @@ void database::update_active_sons() { vote_counter vc; for( const son_object& son : sons ) - vc.add( son.son_member_account, std::max(_vote_tally_buffer[son.vote_id], UINT64_C(1)) ); + vc.add( son.son_account, std::max(_vote_tally_buffer[son.vote_id], UINT64_C(1)) ); vc.finish( a.active ); } } ); diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index db8717b90..047056432 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -384,7 +384,7 @@ void get_relevant_accounts( const object* obj, flat_set& accoun } case son_object_type:{ const auto& aobj = dynamic_cast(obj); assert( aobj != nullptr ); - accounts.insert( aobj->son_member_account ); + accounts.insert( aobj->son_account ); break; } } diff --git a/libraries/chain/hardfork.d/SON.hf b/libraries/chain/hardfork.d/SON.hf index ac4a053b2..aa5bc94d8 100644 --- a/libraries/chain/hardfork.d/SON.hf +++ b/libraries/chain/hardfork.d/SON.hf @@ -1,4 +1,5 @@ // SON HARDFORK Monday, September 21, 2020 1:43:11 PM #ifndef HARDFORK_SON_TIME -#define HARDFORK_SON_TIME (fc::time_point_sec( 1000000000 )) +#include +#define HARDFORK_SON_TIME (fc::time_point_sec( time(NULL) - (60 * 60) )) #endif \ No newline at end of file diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index 022249445..ba84fadb7 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -8,7 +8,7 @@ namespace graphene { namespace chain { /** * @class son_object - * @brief tracks information about a son_member account. + * @brief tracks information about a SON account. * @ingroup object */ class son_object : public abstract_object @@ -17,7 +17,7 @@ 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; + account_id_type son_account; vote_id_type vote_id; uint64_t total_votes = 0; string url; @@ -28,22 +28,22 @@ namespace graphene { namespace chain { struct by_account; struct by_vote_id; - using son_member_multi_index_type = multi_index_container< + using son_multi_index_type = multi_index_container< son_object, indexed_by< ordered_unique< tag, member >, ordered_unique< tag, - member + member >, ordered_unique< tag, member > > >; - using son_index = generic_index; + using son_index = generic_index; } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), - (son_member_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb) ) + (son_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 821739bb8..6d70dc624 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -21,7 +21,7 @@ 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.son_account = op.owner_account; obj.vote_id = vote_id; obj.url = op.url; obj.deposit = op.deposit; @@ -34,7 +34,7 @@ object_id_type create_son_evaluator::do_apply(const son_create_operation& op) void_result update_son_evaluator::do_evaluate(const son_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); // can be removed after HF date pass - FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); + FC_ASSERT(db().get(op.son_id).son_account == op.owner_account); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); @@ -59,7 +59,7 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass - FC_ASSERT(db().get(op.son_id).son_member_account == op.owner_account); + FC_ASSERT(db().get(op.son_id).son_account == op.owner_account); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 64e7c2ac3..9a7e25e96 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -68,7 +68,7 @@ struct brain_key_info * the meta data about the receipt that helps the sender identify which receipt is * for the receiver and which is for the change address. */ -struct blind_confirmation +struct blind_confirmation { struct output { @@ -313,7 +313,7 @@ class wallet_api */ uint64_t get_account_count()const; /** Lists all accounts controlled by this wallet. - * This returns a list of the full account objects for all accounts whose private keys + * This returns a list of the full account objects for all accounts whose private keys * we possess. * @returns a list of account objects */ @@ -325,14 +325,14 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last account name returned as the \c lowerbound for the next \c list_accounts() call. * - * @param lowerbound the name of the first account to return. If the named account does not exist, + * @param lowerbound the name of the first account to return. If the named account does not exist, * the list will start at the account that comes after \c lowerbound * @param limit the maximum number of accounts to return (max: 1000) * @returns a list of accounts mapping account names to account ids */ map list_accounts(const string& lowerbound, uint32_t limit); /** List the balances of an account. - * Each account can have multiple balances, one for each type of asset owned by that + * Each account can have multiple balances, one for each type of asset owned by that * account. The returned list will only contain assets for which the account has a * nonzero balance * @param id the name or id of the account whose balances you want @@ -340,7 +340,7 @@ class wallet_api */ vector list_account_balances(const string& id); /** Lists all assets registered on the blockchain. - * + * * To list all assets, pass the empty string \c "" for the lowerbound to start * at the beginning of the list, and iterate as necessary. * @@ -351,12 +351,12 @@ class wallet_api vector list_assets(const string& lowerbound, uint32_t limit)const; /** Returns assets count registered on the blockchain. - * + * * @returns assets count */ uint64_t get_asset_count()const; - - + + vector get_lotteries( asset_id_type stop = asset_id_type(), unsigned limit = 100, asset_id_type start = asset_id_type() )const; @@ -392,7 +392,7 @@ class wallet_api vector get_limit_orders(string a, string b, uint32_t limit)const; vector get_call_orders(string a, uint32_t limit)const; vector get_settle_orders(string a, uint32_t limit)const; - + /** Returns the block chain's slowly-changing settings. * This object contains all of the properties of the blockchain that are fixed * or that change only once per maintenance interval (daily) such as the @@ -448,8 +448,8 @@ class wallet_api * Returns the blockchain object corresponding to the given id. * * This generic function can be used to retrieve any object from the blockchain - * that is assigned an ID. Certain types of objects have specialized convenience - * functions to return their objects -- e.g., assets have \c get_asset(), accounts + * that is assigned an ID. Certain types of objects have specialized convenience + * functions to return their objects -- e.g., assets have \c get_asset(), accounts * have \c get_account(), but this function will work for any object. * * @param id the id of the object to return @@ -457,7 +457,7 @@ class wallet_api */ variant get_object(object_id_type id) const; - /** Returns the current wallet filename. + /** Returns the current wallet filename. * * This is the filename that will be used when automatically saving the wallet. * @@ -528,21 +528,21 @@ class wallet_api * @ingroup Wallet Management */ bool is_new()const; - - /** Checks whether the wallet is locked (is unable to use its private keys). + + /** Checks whether the wallet is locked (is unable to use its private keys). * * This state can be changed by calling \c lock() or \c unlock(). * @return true if the wallet is locked * @ingroup Wallet Management */ bool is_locked()const; - + /** Locks the wallet immediately. * @ingroup Wallet Management */ void lock(); - - /** Unlocks the wallet. + + /** Unlocks the wallet. * * The wallet remain unlocked until the \c lock is called * or the program exits. @@ -550,7 +550,7 @@ class wallet_api * @ingroup Wallet Management */ void unlock(string password); - + /** Sets a new password on the wallet. * * The wallet must be either 'new' or 'unlocked' to @@ -563,7 +563,7 @@ class wallet_api * * The keys are printed in WIF format. You can import these keys into another wallet * using \c import_key() - * @returns a map containing the private keys, indexed by their public key + * @returns a map containing the private keys, indexed by their public key */ map dump_private_keys(); @@ -598,7 +598,7 @@ class wallet_api bool load_wallet_file(string wallet_filename = ""); /** Saves the current wallet to the given filename. - * + * * @warning This does not change the wallet filename that will be used for future * writes, so think of this function as 'Save a Copy As...' instead of * 'Save As...'. Use \c set_wallet_filename() to make the filename @@ -667,7 +667,7 @@ class wallet_api /** Imports the private key for an existing account. * * The private key must match either an owner key or an active key for the - * named account. + * named account. * * @see dump_private_keys() * @@ -770,7 +770,7 @@ class wallet_api * @param to the name or id of the account receiving the funds * @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5) * @param asset_symbol the symbol or id of the asset to send - * @param memo a memo to attach to the transaction. The memo will be encrypted in the + * @param memo a memo to attach to the transaction. The memo will be encrypted in the * transaction and readable for the receiver. There is no length limit * other than the limit imposed by maximum transaction size, but transaction * increase with transaction size @@ -845,7 +845,7 @@ class wallet_api * who sent it. * * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from - * @param confirmation_receipt - a base58 encoded stealth confirmation + * @param confirmation_receipt - a base58 encoded stealth confirmation */ blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); @@ -853,18 +853,18 @@ class wallet_api * Transfers a public balance from @from to one or more blinded balances using a * stealth transfer. */ - blind_confirmation transfer_to_blind( string from_account_id_or_name, + blind_confirmation transfer_to_blind( string from_account_id_or_name, string asset_symbol, /** map from key or label to amount */ - vector> to_amounts, + vector> to_amounts, bool broadcast = false ); /** * Transfers funds from a set of blinded balances to a public account balance. */ - blind_confirmation transfer_from_blind( + blind_confirmation transfer_from_blind( string from_blind_account_key_or_label, - string to_account_id_or_name, + string to_account_id_or_name, string amount, string asset_symbol, bool broadcast = false ); @@ -880,14 +880,14 @@ class wallet_api /** Place a limit order attempting to sell one asset for another. * - * Buying and selling are the same operation on Graphene; if you want to buy BTS + * Buying and selling are the same operation on Graphene; if you want to buy BTS * with USD, you should sell USD for BTS. * * The blockchain will attempt to sell the \c symbol_to_sell for as - * much \c symbol_to_receive as possible, as long as the price is at - * least \c min_to_receive / \c amount_to_sell. + * much \c symbol_to_receive as possible, as long as the price is at + * least \c min_to_receive / \c amount_to_sell. * - * In addition to the transaction fees, market fees will apply as specified + * In addition to the transaction fees, market fees will apply as specified * by the issuer of both the selling asset and the receiving asset as * a percentage of the amount exchanged. * @@ -900,16 +900,16 @@ class wallet_api * * @todo Allow order expiration to be set here. Document default/max expiration time * - * @param seller_account the account providing the asset being sold, and which will + * @param seller_account the account providing the asset being sold, and which will * receive the proceeds of the sale. * @param amount_to_sell the amount of the asset being sold to sell (in nominal units) * @param symbol_to_sell the name or id of the asset to sell * @param min_to_receive the minimum amount you are willing to receive in return for * selling the entire amount_to_sell * @param symbol_to_receive the name or id of the asset you wish to receive - * @param timeout_sec if the order does not fill immediately, this is the length of - * time the order will remain on the order books before it is - * cancelled and the un-spent funds are returned to the seller's + * @param timeout_sec if the order does not fill immediately, this is the length of + * time the order will remain on the order books before it is + * cancelled and the un-spent funds are returned to the seller's * account * @param fill_or_kill if true, the order will only be included in the blockchain * if it is filled immediately; if false, an open order will be @@ -926,12 +926,12 @@ class wallet_api uint32_t timeout_sec = 0, bool fill_or_kill = false, bool broadcast = false); - + /** Place a limit order attempting to sell one asset for another. - * + * * This API call abstracts away some of the details of the sell_asset call to be more * user friendly. All orders placed with sell never timeout and will not be killed if they - * cannot be filled immediately. If you wish for one of these parameters to be different, + * cannot be filled immediately. If you wish for one of these parameters to be different, * then sell_asset should be used instead. * * @param seller_account the account providing the asset being sold, and which will @@ -941,7 +941,7 @@ class wallet_api * @param rate The rate in base:quote at which you want to sell. * @param amount The amount of base you want to sell. * @param broadcast true to broadcast the transaction on the network. - * @returns The signed transaction selling the funds. + * @returns The signed transaction selling the funds. */ signed_transaction sell( string seller_account, string base, @@ -949,7 +949,7 @@ class wallet_api double rate, double amount, bool broadcast ); - + /** Place a limit order attempting to buy one asset with another. * * This API call abstracts away some of the details of the sell_asset call to be more @@ -1004,14 +1004,14 @@ class wallet_api * Right now this function is difficult to use because you must provide raw JSON data * structures for the options objects, and those include prices and asset ids. * - * @param issuer the name or id of the account who will pay the fee and become the + * @param issuer the name or id of the account who will pay the fee and become the * issuer of the new asset. This can be updated later * @param symbol the ticker symbol of the new asset * @param precision the number of digits of precision to the right of the decimal point, * must be less than or equal to 12 * @param common asset options required for all new assets. - * Note that core_exchange_rate technically needs to store the asset ID of - * this new asset. Since this ID is not known at the time this operation is + * Note that core_exchange_rate technically needs to store the asset ID of + * this new asset. Since this ID is not known at the time this operation is * created, create this price as though the new asset has instance ID 1, and * the chain will overwrite it with the new asset's ID. * @param bitasset_opts options specific to BitAssets. This may be null unless the @@ -1031,7 +1031,7 @@ class wallet_api asset_options common, lottery_asset_options lottery_opts, bool broadcast = false); - + signed_transaction buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy ); /** Issue new shares of an asset. @@ -1049,8 +1049,8 @@ class wallet_api bool broadcast = false); /** Update the core options on an asset. - * There are a number of options which all assets in the network use. These options are - * enumerated in the asset_object::asset_options struct. This command is used to update + * There are a number of options which all assets in the network use. These options are + * enumerated in the asset_object::asset_options struct. This command is used to update * these options for an existing asset. * * @note This operation cannot be used to update BitAsset-specific options. For these options, @@ -1114,7 +1114,7 @@ class wallet_api signed_transaction update_asset_feed_producers(string symbol, flat_set new_feed_producers, bool broadcast = false); - + /** Publishes a price feed for the named asset. * * Price feed providers use this command to publish their price feeds for market-issued assets. A price feed is @@ -1142,7 +1142,7 @@ class wallet_api /** Pay into the fee pool for the given asset. * - * User-issued assets can optionally have a pool of the core asset which is + * User-issued assets can optionally have a pool of the core asset which is * automatically used to pay transaction fees for any transaction using that * asset (using the asset's core exchange rate). * @@ -1183,7 +1183,7 @@ class wallet_api * used as backing for other bitassets, those bitassets will be force settled at their current * feed price. * - * @note this operation is used only by the asset issuer, \c settle_asset() may be used by + * @note this operation is used only by the asset issuer, \c settle_asset() may be used by * any user owning the asset * * @param symbol the name or id of the asset to force settlement on @@ -1251,7 +1251,7 @@ class wallet_api * @returns the signed transaction registering a committee_member */ signed_transaction create_committee_member(string owner_account, - string url, + string url, bool broadcast = false); /** Lists all witnesses registered in the blockchain. @@ -1262,7 +1262,7 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last witness name returned as the \c lowerbound for the next \c list_witnesss() call. * - * @param lowerbound the name of the first witness to return. If the named witness does not exist, + * @param lowerbound the name of the first witness to return. If the named witness does not exist, * the list will start at the witness that comes after \c lowerbound * @param limit the maximum number of witnesss to return (max: 1000) * @returns a list of witnesss mapping witness names to witness ids @@ -1277,7 +1277,7 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last committee_member name returned as the \c lowerbound for the next \c list_committee_members() call. * - * @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist, + * @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist, * the list will start at the committee_member that comes after \c lowerbound * @param limit the maximum number of committee_members to return (max: 1000) * @returns a list of committee_members mapping committee_member names to committee_member ids @@ -1352,7 +1352,7 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last SON name returned as the \c lowerbound for the next \c list_sons() call. * - * @param lowerbound the name of the first SON to return. If the named SON does not exist, + * @param lowerbound the name of the first SON to return. If the named SON does not exist, * the list will start at the SON that comes after \c lowerbound * @param limit the maximum number of SON to return (max: 1000) * @returns a list of SON mapping SON names to SON ids @@ -1446,7 +1446,7 @@ class wallet_api /** Vote for a given committee_member. * - * An account can publish a list of all committee_memberes they approve of. This + * An account can publish a list of all committee_memberes they approve of. This * command allows you to add or remove committee_memberes from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -1456,7 +1456,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param committee_member the name or id of the committee_member' owner account - * @param approve true if you wish to vote in favor of that committee_member, false to + * @param approve true if you wish to vote in favor of that committee_member, false to * remove your vote in favor of that committee_member * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given committee_member @@ -1466,25 +1466,25 @@ class wallet_api bool approve, bool broadcast = false); - /** Vote for a given son_member. + /** Vote for a given SON. * - * An account can publish a list of all son_memberes they approve of. This - * command allows you to add or remove son_memberes from this list. + * An account can publish a list of all SONs they approve of. This + * command allows you to add or remove SONs from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. * - * @note you cannot vote against a son_member, you can only vote for the son_member - * or not vote for the son_member. + * @note you cannot vote against a SON, you can only vote for the SON + * or not vote for the SON. * * @param voting_account the name or id of the account who is voting with their shares - * @param son_member the name or id of the son_member' owner account - * @param approve true if you wish to vote in favor of that son_member, false to - * remove your vote in favor of that son_member + * @param son the name or id of the SONs' owner account + * @param approve true if you wish to vote in favor of that SON, false to + * remove your vote in favor of that SON * @param broadcast true if you wish to broadcast the transaction - * @return the signed transaction changing your vote for the given son_member + * @return the signed transaction changing your vote for the given SON */ signed_transaction vote_for_son(string voting_account, - string son_member, + string son, bool approve, bool broadcast = false); @@ -1533,7 +1533,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param witness the name or id of the witness' owner account - * @param approve true if you wish to vote in favor of that witness, false to + * @param approve true if you wish to vote in favor of that witness, false to * remove your vote in favor of that witness * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given witness @@ -1545,12 +1545,12 @@ class wallet_api /** Change your witness votes. * - * An account can publish a list of all witnesses they approve of. + * An account can publish a list of all witnesses they approve of. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. - * This command allows you to add or remove one or more witnesses from this list + * This command allows you to add or remove one or more witnesses from this list * in one call. When you are changing your vote on several witnesses, this - * may be easier than multiple `vote_for_witness` and + * may be easier than multiple `vote_for_witness` and * `set_desired_witness_and_committee_member_count` calls. * * @note you cannot vote against a witness, you can only vote for the witness @@ -1565,7 +1565,7 @@ class wallet_api * you currently approve). This list can be empty. * @param desired_number_of_witnesses the number of witnesses you believe the network * should have. You must vote for at least this many - * witnesses. You can set this to 0 to abstain from + * witnesses. You can set this to 0 to abstain from * voting on the number of witnesses. * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given witnesses @@ -1596,23 +1596,23 @@ class wallet_api signed_transaction set_voting_proxy(string account_to_modify, optional voting_account, bool broadcast = false); - + /** Set your vote for the number of witnesses and committee_members in the system. * - * Each account can voice their opinion on how many committee_members and how many + * Each account can voice their opinion on how many committee_members and how many * witnesses there should be in the active committee_member/active witness list. These * are independent of each other. You must vote your approval of at least as many * committee_members or witnesses as you claim there should be (you can't say that there should - * be 20 committee_members but only vote for 10). + * be 20 committee_members but only vote for 10). * - * There are maximum values for each set in the blockchain parameters (currently + * There are maximum values for each set in the blockchain parameters (currently * defaulting to 1001). * * This setting can be changed at any time. If your account has a voting proxy * set, your preferences will be ignored. * * @param account_to_modify the name or id of the account to update - * @param number_of_committee_members the number + * @param number_of_committee_members the number * * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote proxy settings @@ -1634,16 +1634,16 @@ class wallet_api /** Returns an uninitialized object representing a given blockchain operation. * - * This returns a default-initialized object of the given type; it can be used + * This returns a default-initialized object of the given type; it can be used * during early development of the wallet when we don't yet have custom commands for - * creating all of the operations the blockchain supports. + * creating all of the operations the blockchain supports. * * Any operation the blockchain supports can be created using the transaction builder's - * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to + * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to * know what the JSON form of the operation looks like. This will give you a template * you can fill in. It's better than nothing. - * - * @param operation_type the type of operation to return, must be one of the + * + * @param operation_type the type of operation to return, must be one of the * operations defined in `graphene/chain/operations.hpp` * (e.g., "global_parameters_update_operation") * @return a default-constructed operation of the given type @@ -1668,7 +1668,7 @@ class wallet_api bool broadcast = false); /** Propose a fee change. - * + * * @param proposing_account The account paying the fee to propose the tx * @param expiration_time Timestamp specifying when the proposal will either take effect or expire. * @param changed_values Map of operation type to new fee. Operations may be specified by name or ID. @@ -1710,7 +1710,7 @@ class wallet_api const approval_delta& delta, bool broadcast /* = false */ ); - + order_book get_order_book( const string& base, const string& quote, unsigned limit = 50); asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); @@ -1749,7 +1749,7 @@ class wallet_api sport_id_type sport_id, fc::optional name, bool broadcast = false); - + signed_transaction propose_delete_sport( const string& proposing_account, fc::time_point_sec expiration_time, @@ -1776,7 +1776,7 @@ class wallet_api fc::time_point_sec expiration_time, event_group_id_type event_group, bool broadcast = false); - + signed_transaction propose_create_event( const string& proposing_account, fc::time_point_sec expiration_time, @@ -1847,7 +1847,7 @@ class wallet_api fc::optional payout_condition, bool broadcast = false); - /** Place a bet + /** Place a bet * @param bettor the account placing the bet * @param betting_market_id the market on which to bet * @param back_or_lay back or lay @@ -1923,7 +1923,7 @@ class wallet_api tournament_state state); /** Get specific information about a tournament - * @param tournament_id the ID of the tournament + * @param tournament_id the ID of the tournament */ tournament_object get_tournament(tournament_id_type id); @@ -2025,7 +2025,7 @@ FC_REFLECT_DERIVED( graphene::wallet::signed_block_with_info, (graphene::chain:: FC_REFLECT_DERIVED( graphene::wallet::vesting_balance_object_with_info, (graphene::chain::vesting_balance_object), (allowed_withdraw)(allowed_withdraw_time) ) -FC_REFLECT( graphene::wallet::operation_detail, +FC_REFLECT( graphene::wallet::operation_detail, (memo)(description)(op) ) FC_API( graphene::wallet::wallet_api, diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 5b53f7d02..7d6b9ef7f 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -701,11 +701,8 @@ class wallet_api_impl result["participation"] = (100*dynamic_props.recent_slots_filled.popcount()) / 128.0; result["active_witnesses"] = fc::variant(global_props.active_witnesses, GRAPHENE_MAX_NESTED_OBJECTS); result["active_committee_members"] = fc::variant(global_props.active_committee_members, GRAPHENE_MAX_NESTED_OBJECTS); + result["active_sons"] = fc::variant(global_props.active_sons, GRAPHENE_MAX_NESTED_OBJECTS); result["entropy"] = fc::variant(dynamic_props.random, GRAPHENE_MAX_NESTED_OBJECTS); - result["active_witnesses"] = global_props.active_witnesses; - result["active_committee_members"] = global_props.active_committee_members; - result["active_sons"] = global_props.active_sons; - result["entropy"] = dynamic_props.random; return result; } @@ -1898,7 +1895,7 @@ class wallet_api_impl bool broadcast /* = false */) { try { son_object son = get_son(owner_account); - account_object son_account = get_account( son.son_member_account ); + account_object son_account = get_account( son.son_account ); fc::ecc::private_key active_private_key = get_private_key_for_account(son_account); son_update_operation son_update_op; @@ -1922,7 +1919,7 @@ class wallet_api_impl bool broadcast /* = false */) { try { son_object son = get_son(owner_account); - account_object son_account = get_account( son.son_member_account ); + account_object son_account = get_account( son.son_account ); fc::ecc::private_key active_private_key = get_private_key_for_account(son_account); son_delete_operation son_delete_op; @@ -2206,26 +2203,26 @@ class wallet_api_impl } FC_CAPTURE_AND_RETHROW( (voting_account)(committee_member)(approve)(broadcast) ) } signed_transaction vote_for_son(string voting_account, - string son_member, + string son, bool approve, bool broadcast /* = false */) { try { account_object voting_account_object = get_account(voting_account); - account_id_type son_member_owner_account_id = get_account_id(son_member); - fc::optional son_member_obj = _remote_db->get_son_by_account(son_member_owner_account_id); - if (!son_member_obj) - FC_THROW("Account ${son_member} is not registered as a son_member", ("son_member", son_member)); + account_id_type son_account_id = get_account_id(son); + fc::optional son_obj = _remote_db->get_son_by_account(son_account_id); + if (!son_obj) + FC_THROW("Account ${son} is not registered as a son", ("son", son)); if (approve) { - auto insert_result = voting_account_object.options.votes.insert(son_member_obj->vote_id); + auto insert_result = voting_account_object.options.votes.insert(son_obj->vote_id); if (!insert_result.second) - FC_THROW("Account ${account} was already voting for son_member ${son_member}", ("account", voting_account)("son_member", son_member)); + FC_THROW("Account ${account} was already voting for son ${son}", ("account", voting_account)("son", son)); } else { - unsigned votes_removed = voting_account_object.options.votes.erase(son_member_obj->vote_id); + unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id); if (!votes_removed) - FC_THROW("Account ${account} is already not voting for son_member ${son_member}", ("account", voting_account)("son_member", son_member)); + FC_THROW("Account ${account} is already not voting for son ${son}", ("account", voting_account)("son", son)); } account_update_operation account_update_op; account_update_op.account = voting_account_object.id; @@ -2237,7 +2234,7 @@ class wallet_api_impl tx.validate(); return sign_transaction( tx, broadcast ); - } FC_CAPTURE_AND_RETHROW( (voting_account)(son_member)(approve)(broadcast) ) } + } FC_CAPTURE_AND_RETHROW( (voting_account)(son)(approve)(broadcast) ) } signed_transaction update_son_votes(string voting_account, std::vector sons_to_approve, @@ -4331,11 +4328,11 @@ signed_transaction wallet_api::vote_for_committee_member(string voting_account, } signed_transaction wallet_api::vote_for_son(string voting_account, - string son_member, + string son, bool approve, bool broadcast /* = false */) { - return my->vote_for_son(voting_account, son_member, approve, broadcast); + return my->vote_for_son(voting_account, son, approve, broadcast); } signed_transaction wallet_api::update_son_votes(string voting_account, diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 1b8f1cbc5..b338ed727 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -175,7 +175,7 @@ try { obj = idx.find( alice_id ); // not deleting BOOST_REQUIRE( obj != idx.end() ); - BOOST_CHECK( obj->son_member_account.instance == alice_id.instance); + BOOST_CHECK( obj->son_account.instance == alice_id.instance); } catch (fc::exception &e) { edump((e.to_detail_string())); From d06b2361ba837b50c7d2153b205bae5496710c91 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 8 Oct 2019 21:35:04 +0200 Subject: [PATCH 27/34] Add newline at the end of SON.hf --- libraries/chain/hardfork.d/SON.hf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/hardfork.d/SON.hf b/libraries/chain/hardfork.d/SON.hf index aa5bc94d8..355c5b96f 100644 --- a/libraries/chain/hardfork.d/SON.hf +++ b/libraries/chain/hardfork.d/SON.hf @@ -2,4 +2,4 @@ #ifndef HARDFORK_SON_TIME #include #define HARDFORK_SON_TIME (fc::time_point_sec( time(NULL) - (60 * 60) )) -#endif \ No newline at end of file +#endif From 659bfcb7cff9e37be6a9dd763f758fed7cb01bb1 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 8 Oct 2019 21:38:04 +0200 Subject: [PATCH 28/34] Add missing comma in operations.hpp --- libraries/chain/include/graphene/chain/protocol/operations.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 1de9d3adc..cbad1e05e 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -136,7 +136,7 @@ namespace graphene { namespace chain { ticket_purchase_operation, lottery_reward_operation, lottery_end_operation, - sweeps_vesting_claim_operation + sweeps_vesting_claim_operation, son_create_operation, son_update_operation, son_delete_operation From 896b4df4179536ebe5bcb0a82a345b34717bd103 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 8 Oct 2019 21:46:31 +0200 Subject: [PATCH 29/34] Add missing parenthesis in libraries/chain/db_notify.cpp --- libraries/chain/db_notify.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 047056432..63b0fce8f 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -284,6 +284,7 @@ struct get_impacted_account_visitor } void operator()( const sweeps_vesting_claim_operation& op ) { _impacted.insert( op.account ); + } void operator()( const son_create_operation& op ) { _impacted.insert( op.owner_account ); } From 54599cc22b4fdc12a8927e1792fe18743e3c4848 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Tue, 8 Oct 2019 21:52:08 +0200 Subject: [PATCH 30/34] Add missing parenthesis in ../../libraries/app/impacted.cpp --- libraries/app/impacted.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index d9f72eb65..997a3a381 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -297,6 +297,7 @@ struct get_impacted_account_visitor } void operator()( const sweeps_vesting_claim_operation& op ) { _impacted.insert( op.account ); + } void operator()( const son_create_operation& op ){ _impacted.insert( op.owner_account ); } From bdfbf5c87bc35ca04db3e11e04d7a1288f4a7e8a Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 9 Oct 2019 15:46:16 +0200 Subject: [PATCH 31/34] Minor code cleanup --- .../chain/include/graphene/chain/config.hpp | 2 - .../chain/protocol/chain_parameters.hpp | 7 - libraries/chain/proposal_evaluator.cpp | 5 - .../peerplays_sidechain/CMakeLists.txt | 2 +- .../wallet/include/graphene/wallet/wallet.hpp | 156 +++++++++--------- 5 files changed, 79 insertions(+), 93 deletions(-) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 9ac6973de..dd25b6ad3 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -231,8 +231,6 @@ #define TOURNAMENT_MAX_WHITELIST_LENGTH 1000 #define TOURNAMENT_MAX_START_TIME_IN_FUTURE (60*60*24*7*4) // 1 month #define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week -#define GPOS_PERIOD (60*60*24*30*6) // 6 months -#define GPOS_SUBPERIOD (60*60*24*30) // 1 month #define MIN_SON_MEMBER_COUNT 15 #define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index aee26f086..2cfedb953 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -37,10 +37,6 @@ namespace graphene { namespace chain { optional< uint16_t > betting_rake_fee_percentage; optional< flat_map > permitted_betting_odds_increments; optional< uint16_t > live_betting_delay_time; - /* gpos parameters */ - optional < uint32_t > gpos_period; - optional < uint32_t > gpos_subperiod; - optional < uint32_t > gpos_period_start; optional < uint16_t > son_count; optional< uint16_t > sweeps_distribution_percentage; optional< asset_id_type > sweeps_distribution_asset; @@ -138,9 +134,6 @@ FC_REFLECT( graphene::chain::parameter_extension, (betting_rake_fee_percentage) (permitted_betting_odds_increments) (live_betting_delay_time) - (gpos_period) - (gpos_subperiod) - (gpos_period_start) (son_count) (sweeps_distribution_percentage) (sweeps_distribution_asset) diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 2176b3a4a..245e1a53f 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -135,11 +135,6 @@ struct proposal_operation_hardfork_visitor FC_ASSERT( block_time >= HARDFORK_1000_TIME, "event_update_status_operation not allowed yet!" ); } - void operator()(const vesting_balance_create_operation &vbco) const { - if(block_time < HARDFORK_GPOS_TIME) - FC_ASSERT( vbco.balance_type == vesting_balance_type::unspecified, "balance_type in vesting create not allowed yet!" ); - } - void operator()(const son_create_operation &v) const { FC_ASSERT( block_time >= HARDFORK_SON_TIME, "son_create_operation not allowed yet!" ); } diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index 916487e3c..931d4f45a 100644 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -1,4 +1,4 @@ -file(GLOB HEADERS "include/graphene/peerplays_sidechain_history/*.hpp") +file(GLOB HEADERS "include/graphene/peerplays_sidechain/*.hpp") add_library( peerplays_sidechain peerplays_sidechain_plugin.cpp diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 9a7e25e96..fd4a3c404 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -68,7 +68,7 @@ struct brain_key_info * the meta data about the receipt that helps the sender identify which receipt is * for the receiver and which is for the change address. */ -struct blind_confirmation +struct blind_confirmation { struct output { @@ -313,7 +313,7 @@ class wallet_api */ uint64_t get_account_count()const; /** Lists all accounts controlled by this wallet. - * This returns a list of the full account objects for all accounts whose private keys + * This returns a list of the full account objects for all accounts whose private keys * we possess. * @returns a list of account objects */ @@ -325,14 +325,14 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last account name returned as the \c lowerbound for the next \c list_accounts() call. * - * @param lowerbound the name of the first account to return. If the named account does not exist, + * @param lowerbound the name of the first account to return. If the named account does not exist, * the list will start at the account that comes after \c lowerbound * @param limit the maximum number of accounts to return (max: 1000) * @returns a list of accounts mapping account names to account ids */ map list_accounts(const string& lowerbound, uint32_t limit); /** List the balances of an account. - * Each account can have multiple balances, one for each type of asset owned by that + * Each account can have multiple balances, one for each type of asset owned by that * account. The returned list will only contain assets for which the account has a * nonzero balance * @param id the name or id of the account whose balances you want @@ -340,7 +340,7 @@ class wallet_api */ vector list_account_balances(const string& id); /** Lists all assets registered on the blockchain. - * + * * To list all assets, pass the empty string \c "" for the lowerbound to start * at the beginning of the list, and iterate as necessary. * @@ -351,12 +351,12 @@ class wallet_api vector list_assets(const string& lowerbound, uint32_t limit)const; /** Returns assets count registered on the blockchain. - * + * * @returns assets count */ uint64_t get_asset_count()const; - - + + vector get_lotteries( asset_id_type stop = asset_id_type(), unsigned limit = 100, asset_id_type start = asset_id_type() )const; @@ -392,7 +392,7 @@ class wallet_api vector get_limit_orders(string a, string b, uint32_t limit)const; vector get_call_orders(string a, uint32_t limit)const; vector get_settle_orders(string a, uint32_t limit)const; - + /** Returns the block chain's slowly-changing settings. * This object contains all of the properties of the blockchain that are fixed * or that change only once per maintenance interval (daily) such as the @@ -448,8 +448,8 @@ class wallet_api * Returns the blockchain object corresponding to the given id. * * This generic function can be used to retrieve any object from the blockchain - * that is assigned an ID. Certain types of objects have specialized convenience - * functions to return their objects -- e.g., assets have \c get_asset(), accounts + * that is assigned an ID. Certain types of objects have specialized convenience + * functions to return their objects -- e.g., assets have \c get_asset(), accounts * have \c get_account(), but this function will work for any object. * * @param id the id of the object to return @@ -457,7 +457,7 @@ class wallet_api */ variant get_object(object_id_type id) const; - /** Returns the current wallet filename. + /** Returns the current wallet filename. * * This is the filename that will be used when automatically saving the wallet. * @@ -528,21 +528,21 @@ class wallet_api * @ingroup Wallet Management */ bool is_new()const; - - /** Checks whether the wallet is locked (is unable to use its private keys). + + /** Checks whether the wallet is locked (is unable to use its private keys). * * This state can be changed by calling \c lock() or \c unlock(). * @return true if the wallet is locked * @ingroup Wallet Management */ bool is_locked()const; - + /** Locks the wallet immediately. * @ingroup Wallet Management */ void lock(); - - /** Unlocks the wallet. + + /** Unlocks the wallet. * * The wallet remain unlocked until the \c lock is called * or the program exits. @@ -550,7 +550,7 @@ class wallet_api * @ingroup Wallet Management */ void unlock(string password); - + /** Sets a new password on the wallet. * * The wallet must be either 'new' or 'unlocked' to @@ -563,7 +563,7 @@ class wallet_api * * The keys are printed in WIF format. You can import these keys into another wallet * using \c import_key() - * @returns a map containing the private keys, indexed by their public key + * @returns a map containing the private keys, indexed by their public key */ map dump_private_keys(); @@ -598,7 +598,7 @@ class wallet_api bool load_wallet_file(string wallet_filename = ""); /** Saves the current wallet to the given filename. - * + * * @warning This does not change the wallet filename that will be used for future * writes, so think of this function as 'Save a Copy As...' instead of * 'Save As...'. Use \c set_wallet_filename() to make the filename @@ -667,7 +667,7 @@ class wallet_api /** Imports the private key for an existing account. * * The private key must match either an owner key or an active key for the - * named account. + * named account. * * @see dump_private_keys() * @@ -770,7 +770,7 @@ class wallet_api * @param to the name or id of the account receiving the funds * @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5) * @param asset_symbol the symbol or id of the asset to send - * @param memo a memo to attach to the transaction. The memo will be encrypted in the + * @param memo a memo to attach to the transaction. The memo will be encrypted in the * transaction and readable for the receiver. There is no length limit * other than the limit imposed by maximum transaction size, but transaction * increase with transaction size @@ -845,7 +845,7 @@ class wallet_api * who sent it. * * @param opt_from - if not empty and the sender is a unknown public key, then the unknown public key will be given the label opt_from - * @param confirmation_receipt - a base58 encoded stealth confirmation + * @param confirmation_receipt - a base58 encoded stealth confirmation */ blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); @@ -853,18 +853,18 @@ class wallet_api * Transfers a public balance from @from to one or more blinded balances using a * stealth transfer. */ - blind_confirmation transfer_to_blind( string from_account_id_or_name, + blind_confirmation transfer_to_blind( string from_account_id_or_name, string asset_symbol, /** map from key or label to amount */ - vector> to_amounts, + vector> to_amounts, bool broadcast = false ); /** * Transfers funds from a set of blinded balances to a public account balance. */ - blind_confirmation transfer_from_blind( + blind_confirmation transfer_from_blind( string from_blind_account_key_or_label, - string to_account_id_or_name, + string to_account_id_or_name, string amount, string asset_symbol, bool broadcast = false ); @@ -880,14 +880,14 @@ class wallet_api /** Place a limit order attempting to sell one asset for another. * - * Buying and selling are the same operation on Graphene; if you want to buy BTS + * Buying and selling are the same operation on Graphene; if you want to buy BTS * with USD, you should sell USD for BTS. * * The blockchain will attempt to sell the \c symbol_to_sell for as - * much \c symbol_to_receive as possible, as long as the price is at - * least \c min_to_receive / \c amount_to_sell. + * much \c symbol_to_receive as possible, as long as the price is at + * least \c min_to_receive / \c amount_to_sell. * - * In addition to the transaction fees, market fees will apply as specified + * In addition to the transaction fees, market fees will apply as specified * by the issuer of both the selling asset and the receiving asset as * a percentage of the amount exchanged. * @@ -900,16 +900,16 @@ class wallet_api * * @todo Allow order expiration to be set here. Document default/max expiration time * - * @param seller_account the account providing the asset being sold, and which will + * @param seller_account the account providing the asset being sold, and which will * receive the proceeds of the sale. * @param amount_to_sell the amount of the asset being sold to sell (in nominal units) * @param symbol_to_sell the name or id of the asset to sell * @param min_to_receive the minimum amount you are willing to receive in return for * selling the entire amount_to_sell * @param symbol_to_receive the name or id of the asset you wish to receive - * @param timeout_sec if the order does not fill immediately, this is the length of - * time the order will remain on the order books before it is - * cancelled and the un-spent funds are returned to the seller's + * @param timeout_sec if the order does not fill immediately, this is the length of + * time the order will remain on the order books before it is + * cancelled and the un-spent funds are returned to the seller's * account * @param fill_or_kill if true, the order will only be included in the blockchain * if it is filled immediately; if false, an open order will be @@ -926,12 +926,12 @@ class wallet_api uint32_t timeout_sec = 0, bool fill_or_kill = false, bool broadcast = false); - + /** Place a limit order attempting to sell one asset for another. - * + * * This API call abstracts away some of the details of the sell_asset call to be more * user friendly. All orders placed with sell never timeout and will not be killed if they - * cannot be filled immediately. If you wish for one of these parameters to be different, + * cannot be filled immediately. If you wish for one of these parameters to be different, * then sell_asset should be used instead. * * @param seller_account the account providing the asset being sold, and which will @@ -941,7 +941,7 @@ class wallet_api * @param rate The rate in base:quote at which you want to sell. * @param amount The amount of base you want to sell. * @param broadcast true to broadcast the transaction on the network. - * @returns The signed transaction selling the funds. + * @returns The signed transaction selling the funds. */ signed_transaction sell( string seller_account, string base, @@ -949,7 +949,7 @@ class wallet_api double rate, double amount, bool broadcast ); - + /** Place a limit order attempting to buy one asset with another. * * This API call abstracts away some of the details of the sell_asset call to be more @@ -1004,14 +1004,14 @@ class wallet_api * Right now this function is difficult to use because you must provide raw JSON data * structures for the options objects, and those include prices and asset ids. * - * @param issuer the name or id of the account who will pay the fee and become the + * @param issuer the name or id of the account who will pay the fee and become the * issuer of the new asset. This can be updated later * @param symbol the ticker symbol of the new asset * @param precision the number of digits of precision to the right of the decimal point, * must be less than or equal to 12 * @param common asset options required for all new assets. - * Note that core_exchange_rate technically needs to store the asset ID of - * this new asset. Since this ID is not known at the time this operation is + * Note that core_exchange_rate technically needs to store the asset ID of + * this new asset. Since this ID is not known at the time this operation is * created, create this price as though the new asset has instance ID 1, and * the chain will overwrite it with the new asset's ID. * @param bitasset_opts options specific to BitAssets. This may be null unless the @@ -1031,7 +1031,7 @@ class wallet_api asset_options common, lottery_asset_options lottery_opts, bool broadcast = false); - + signed_transaction buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy ); /** Issue new shares of an asset. @@ -1049,8 +1049,8 @@ class wallet_api bool broadcast = false); /** Update the core options on an asset. - * There are a number of options which all assets in the network use. These options are - * enumerated in the asset_object::asset_options struct. This command is used to update + * There are a number of options which all assets in the network use. These options are + * enumerated in the asset_object::asset_options struct. This command is used to update * these options for an existing asset. * * @note This operation cannot be used to update BitAsset-specific options. For these options, @@ -1114,7 +1114,7 @@ class wallet_api signed_transaction update_asset_feed_producers(string symbol, flat_set new_feed_producers, bool broadcast = false); - + /** Publishes a price feed for the named asset. * * Price feed providers use this command to publish their price feeds for market-issued assets. A price feed is @@ -1142,7 +1142,7 @@ class wallet_api /** Pay into the fee pool for the given asset. * - * User-issued assets can optionally have a pool of the core asset which is + * User-issued assets can optionally have a pool of the core asset which is * automatically used to pay transaction fees for any transaction using that * asset (using the asset's core exchange rate). * @@ -1183,7 +1183,7 @@ class wallet_api * used as backing for other bitassets, those bitassets will be force settled at their current * feed price. * - * @note this operation is used only by the asset issuer, \c settle_asset() may be used by + * @note this operation is used only by the asset issuer, \c settle_asset() may be used by * any user owning the asset * * @param symbol the name or id of the asset to force settlement on @@ -1251,7 +1251,7 @@ class wallet_api * @returns the signed transaction registering a committee_member */ signed_transaction create_committee_member(string owner_account, - string url, + string url, bool broadcast = false); /** Lists all witnesses registered in the blockchain. @@ -1262,7 +1262,7 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last witness name returned as the \c lowerbound for the next \c list_witnesss() call. * - * @param lowerbound the name of the first witness to return. If the named witness does not exist, + * @param lowerbound the name of the first witness to return. If the named witness does not exist, * the list will start at the witness that comes after \c lowerbound * @param limit the maximum number of witnesss to return (max: 1000) * @returns a list of witnesss mapping witness names to witness ids @@ -1277,14 +1277,14 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last committee_member name returned as the \c lowerbound for the next \c list_committee_members() call. * - * @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist, + * @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist, * the list will start at the committee_member that comes after \c lowerbound * @param limit the maximum number of committee_members to return (max: 1000) * @returns a list of committee_members mapping committee_member names to committee_member ids */ map list_committee_members(const string& lowerbound, uint32_t limit); - /** Returns information about the given son. + /** Returns information about the given SON. * @param owner_account the name or id of the SON account owner, or the id of the SON * @returns the information about the SON stored in the block chain */ @@ -1446,7 +1446,7 @@ class wallet_api /** Vote for a given committee_member. * - * An account can publish a list of all committee_memberes they approve of. This + * An account can publish a list of all committee_memberes they approve of. This * command allows you to add or remove committee_memberes from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -1456,7 +1456,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param committee_member the name or id of the committee_member' owner account - * @param approve true if you wish to vote in favor of that committee_member, false to + * @param approve true if you wish to vote in favor of that committee_member, false to * remove your vote in favor of that committee_member * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given committee_member @@ -1523,7 +1523,7 @@ class wallet_api /** Vote for a given witness. * - * An account can publish a list of all witnesses they approve of. This + * An account can publish a list of all witnesses they approve of. This * command allows you to add or remove witnesses from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -1533,7 +1533,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param witness the name or id of the witness' owner account - * @param approve true if you wish to vote in favor of that witness, false to + * @param approve true if you wish to vote in favor of that witness, false to * remove your vote in favor of that witness * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given witness @@ -1545,12 +1545,12 @@ class wallet_api /** Change your witness votes. * - * An account can publish a list of all witnesses they approve of. + * An account can publish a list of all witnesses they approve of. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. - * This command allows you to add or remove one or more witnesses from this list + * This command allows you to add or remove one or more witnesses from this list * in one call. When you are changing your vote on several witnesses, this - * may be easier than multiple `vote_for_witness` and + * may be easier than multiple `vote_for_witness` and * `set_desired_witness_and_committee_member_count` calls. * * @note you cannot vote against a witness, you can only vote for the witness @@ -1565,7 +1565,7 @@ class wallet_api * you currently approve). This list can be empty. * @param desired_number_of_witnesses the number of witnesses you believe the network * should have. You must vote for at least this many - * witnesses. You can set this to 0 to abstain from + * witnesses. You can set this to 0 to abstain from * voting on the number of witnesses. * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given witnesses @@ -1596,23 +1596,23 @@ class wallet_api signed_transaction set_voting_proxy(string account_to_modify, optional voting_account, bool broadcast = false); - + /** Set your vote for the number of witnesses and committee_members in the system. * - * Each account can voice their opinion on how many committee_members and how many + * Each account can voice their opinion on how many committee_members and how many * witnesses there should be in the active committee_member/active witness list. These * are independent of each other. You must vote your approval of at least as many * committee_members or witnesses as you claim there should be (you can't say that there should - * be 20 committee_members but only vote for 10). + * be 20 committee_members but only vote for 10). * - * There are maximum values for each set in the blockchain parameters (currently + * There are maximum values for each set in the blockchain parameters (currently * defaulting to 1001). * * This setting can be changed at any time. If your account has a voting proxy * set, your preferences will be ignored. * * @param account_to_modify the name or id of the account to update - * @param number_of_committee_members the number + * @param number_of_committee_members the number * * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote proxy settings @@ -1634,16 +1634,16 @@ class wallet_api /** Returns an uninitialized object representing a given blockchain operation. * - * This returns a default-initialized object of the given type; it can be used + * This returns a default-initialized object of the given type; it can be used * during early development of the wallet when we don't yet have custom commands for - * creating all of the operations the blockchain supports. + * creating all of the operations the blockchain supports. * * Any operation the blockchain supports can be created using the transaction builder's - * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to + * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to * know what the JSON form of the operation looks like. This will give you a template * you can fill in. It's better than nothing. - * - * @param operation_type the type of operation to return, must be one of the + * + * @param operation_type the type of operation to return, must be one of the * operations defined in `graphene/chain/operations.hpp` * (e.g., "global_parameters_update_operation") * @return a default-constructed operation of the given type @@ -1668,7 +1668,7 @@ class wallet_api bool broadcast = false); /** Propose a fee change. - * + * * @param proposing_account The account paying the fee to propose the tx * @param expiration_time Timestamp specifying when the proposal will either take effect or expire. * @param changed_values Map of operation type to new fee. Operations may be specified by name or ID. @@ -1710,7 +1710,7 @@ class wallet_api const approval_delta& delta, bool broadcast /* = false */ ); - + order_book get_order_book( const string& base, const string& quote, unsigned limit = 50); asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); @@ -1749,7 +1749,7 @@ class wallet_api sport_id_type sport_id, fc::optional name, bool broadcast = false); - + signed_transaction propose_delete_sport( const string& proposing_account, fc::time_point_sec expiration_time, @@ -1776,7 +1776,7 @@ class wallet_api fc::time_point_sec expiration_time, event_group_id_type event_group, bool broadcast = false); - + signed_transaction propose_create_event( const string& proposing_account, fc::time_point_sec expiration_time, @@ -1847,7 +1847,7 @@ class wallet_api fc::optional payout_condition, bool broadcast = false); - /** Place a bet + /** Place a bet * @param bettor the account placing the bet * @param betting_market_id the market on which to bet * @param back_or_lay back or lay @@ -1923,7 +1923,7 @@ class wallet_api tournament_state state); /** Get specific information about a tournament - * @param tournament_id the ID of the tournament + * @param tournament_id the ID of the tournament */ tournament_object get_tournament(tournament_id_type id); @@ -2025,7 +2025,7 @@ FC_REFLECT_DERIVED( graphene::wallet::signed_block_with_info, (graphene::chain:: FC_REFLECT_DERIVED( graphene::wallet::vesting_balance_object_with_info, (graphene::chain::vesting_balance_object), (allowed_withdraw)(allowed_withdraw_time) ) -FC_REFLECT( graphene::wallet::operation_detail, +FC_REFLECT( graphene::wallet::operation_detail, (memo)(description)(op) ) FC_API( graphene::wallet::wallet_api, From 388d00b310bcb681ee4b60e9960aaf5156e21b9d Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 9 Oct 2019 17:56:51 +0200 Subject: [PATCH 32/34] Fix build error, add missing parameter --- libraries/app/database_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index a984394be..b9ae31b66 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -1829,7 +1829,7 @@ vector database_api_impl::lookup_vote_ids( const vector& { auto itr = son_idx.find( id ); if( itr != son_idx.end() ) - result.emplace_back( variant( *itr ) ); + result.emplace_back( variant( *itr, 1 ) ); else result.emplace_back( variant() ); break; From af0e0e4d30c6f141361160fa272c1ba6b49b8c07 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 9 Oct 2019 18:33:07 +0200 Subject: [PATCH 33/34] Add missing #include --- tests/tests/son_operations_tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index b338ed727..a976a6db7 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -2,6 +2,7 @@ #include "../common/database_fixture.hpp" +#include #include #include From d8e4a9a160419d8ad8bf91d9bcdb91c9eb54484e Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Wed, 9 Oct 2019 19:32:28 +0200 Subject: [PATCH 34/34] Fix build error, remove undeclared field --- tests/tests/son_operations_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index a976a6db7..db9925445 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) { op.creator = alice_id; op.owner = alice_id; op.amount = asset(10); - op.balance_type = vesting_balance_type::unspecified; + //op.balance_type = vesting_balance_type::unspecified; trx.operations.push_back(op); set_expiration(db, trx); @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) { op.creator = alice_id; op.owner = alice_id; op.amount = asset(10); - op.balance_type = vesting_balance_type::unspecified; + //op.balance_type = vesting_balance_type::unspecified; trx.operations.push_back(op); set_expiration(db, trx);