diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 4e3d4625..bba9e7f1 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -19,6 +19,7 @@ if( GRAPHENE_DISABLE_UNITY_BUILD ) db_maint.cpp db_management.cpp db_market.cpp + db_sidechain.cpp db_update.cpp db_witness_schedule.cpp ) diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 7711f543..36e2a161 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -31,6 +31,7 @@ #include "db_maint.cpp" #include "db_management.cpp" #include "db_market.cpp" +#include "db_sidechain.cpp" #include "db_update.cpp" #include "db_witness_schedule.cpp" #include "db_notify.cpp" \ No newline at end of file diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 267c58f5..df23cd10 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -445,20 +446,49 @@ void database::update_active_sons() } } ); + // Compare current and to-be lists of active sons + //const global_property_object& gpo = get_global_properties(); + auto cur_active_sons = gpo.active_sons; + vector new_active_sons; + for( const son_object& son : sons ) { + son_info swi; + swi.son_id = son.id; + swi.total_votes = son.total_votes; + swi.signing_key = son.signing_key; + swi.sidechain_public_keys = son.sidechain_public_keys; + new_active_sons.push_back(swi); + } + + bool son_sets_equal = (cur_active_sons.size() == new_active_sons.size()); + if (son_sets_equal) { + for( size_t i = 0; i < cur_active_sons.size(); i++ ) { + son_sets_equal = son_sets_equal && cur_active_sons.at(i) == new_active_sons.at(i); + } + } + + if (son_sets_equal) { + ilog( "Active SONs set NOT CHANGED" ); + } else { + ilog( "Active SONs set CHANGED" ); + // Store new SON info, initiate wallet recreation and transfer of funds + } + 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; - }); + gp.active_sons.reserve(new_active_sons.size()); + gp.active_sons.insert(gp.active_sons.end(), new_active_sons.begin(), new_active_sons.end()); }); const son_schedule_object& sso = son_schedule_id_type()(*this); modify(sso, [&](son_schedule_object& _sso) { - flat_set active_sons(gpo.active_sons.begin(), gpo.active_sons.end()); + flat_set active_sons; + active_sons.reserve(gpo.active_sons.size()); + std::transform(gpo.active_sons.begin(), gpo.active_sons.end(), + std::inserter(active_sons, active_sons.end()), + [](const son_info& swi) { + return swi.son_id; + }); _sso.scheduler.update(active_sons); }); diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index 029a55d4..f6d164d2 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -40,6 +40,7 @@ database::database() : { initialize_indexes(); initialize_evaluators(); + initialize_db_sidechain(); } database::~database() diff --git a/libraries/chain/db_sidechain.cpp b/libraries/chain/db_sidechain.cpp new file mode 100644 index 00000000..77594b3f --- /dev/null +++ b/libraries/chain/db_sidechain.cpp @@ -0,0 +1,10 @@ +#include + +namespace graphene { namespace chain { + +void database::initialize_db_sidechain() +{ + recreate_primary_wallet = false; +} + +} } diff --git a/libraries/chain/db_witness_schedule.cpp b/libraries/chain/db_witness_schedule.cpp index 3ce11443..31caad4b 100644 --- a/libraries/chain/db_witness_schedule.cpp +++ b/libraries/chain/db_witness_schedule.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -200,8 +201,8 @@ void database::update_son_schedule() _sso.current_shuffled_sons.clear(); _sso.current_shuffled_sons.reserve( gpo.active_sons.size() ); - for( const son_id_type& w : gpo.active_sons ) - _sso.current_shuffled_sons.push_back( w ); + for( const son_info& w : gpo.active_sons ) + _sso.current_shuffled_sons.push_back( w.son_id ); auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32; for( uint32_t i = 0; i < _sso.current_shuffled_sons.size(); ++i ) diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 719c6240..78d05ef9 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -40,6 +40,8 @@ #include +#include + #include #include @@ -600,6 +602,13 @@ namespace graphene { namespace chain { * database::close() has not been called, or failed during execution. */ bool _opened = false; + + /////////////////////// db_sidechain.cpp //////////////////// + public: + bool recreate_primary_wallet; + void initialize_db_sidechain(); + protected: + private: }; namespace detail diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 130648e9..1d985a2d 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace graphene { namespace chain { @@ -51,7 +52,7 @@ namespace graphene { namespace chain { uint32_t next_available_vote_id = 0; vector active_committee_members; // updated once per maintenance interval flat_set active_witnesses; // updated once per maintenance interval - vector active_sons; // updated once per maintenance interval + vector active_sons; // updated once per maintenance interval }; /** diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 5b040850..1d056740 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -147,6 +147,7 @@ namespace graphene { namespace chain { bet_object_type, son_object_type, son_proposal_object_type, + son_wallet_object_type, sidechain_address_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -211,6 +212,7 @@ namespace graphene { namespace chain { class bet_object; class son_object; class son_proposal_object; + class son_wallet_object; class sidechain_address_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; @@ -240,6 +242,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; typedef object_id< protocol_ids, son_object_type, son_object> son_id_type; typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type; + typedef object_id< protocol_ids, son_wallet_object_type, son_wallet_object> son_wallet_id_type; typedef object_id< protocol_ids, sidechain_address_object_type, sidechain_address_object> sidechain_address_id_type; // implementation types diff --git a/libraries/chain/include/graphene/chain/son_info.hpp b/libraries/chain/include/graphene/chain/son_info.hpp new file mode 100644 index 00000000..d30f0f6b --- /dev/null +++ b/libraries/chain/include/graphene/chain/son_info.hpp @@ -0,0 +1,36 @@ +#pragma once +#include +#include + +namespace graphene { namespace chain { + using namespace graphene::db; + + /** + * @class son_info + * @brief tracks information about a SON info required to re/create primary wallet + * @ingroup object + */ + struct son_info { + son_id_type son_id; + uint64_t total_votes = 0; + public_key_type signing_key; + flat_map sidechain_public_keys; + + bool operator==(const son_info& rhs) { + bool son_sets_equal = + (son_id == rhs.son_id) && + (total_votes == rhs.total_votes) && + (signing_key == rhs.signing_key) && + (sidechain_public_keys.size() == rhs.sidechain_public_keys.size()); + + if (son_sets_equal) { + // Compare sidechain public keys + } + return son_sets_equal; + } + }; + +} } + +FC_REFLECT( graphene::chain::son_info, + (son_id)(total_votes)(signing_key)(sidechain_public_keys) ) diff --git a/libraries/chain/include/graphene/chain/son_wallet_object.hpp b/libraries/chain/include/graphene/chain/son_wallet_object.hpp new file mode 100644 index 00000000..c3ea204d --- /dev/null +++ b/libraries/chain/include/graphene/chain/son_wallet_object.hpp @@ -0,0 +1,36 @@ +#pragma once +#include +#include + +namespace graphene { namespace chain { + using namespace graphene::db; + + /** + * @class son_wallet_object + * @brief tracks information about a SON wallet. + * @ingroup object + */ + class son_wallet_object : public abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = son_wallet_object_type; + + flat_map addresses; + }; + + struct by_sidechain_type; + struct by_address; + using son_wallet_multi_index_type = multi_index_container< + son_wallet_object, + indexed_by< + ordered_unique< tag, + member + > + > + >; + using son_wallet_index = generic_index; +} } // graphene::chain + +FC_REFLECT_DERIVED( graphene::chain::son_wallet_object, (graphene::db::object), + (addresses) ) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index e88f4a00..be837940 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1942,7 +1942,14 @@ public: map list_active_sons() { try { global_property_object gpo = get_global_properties(); - std::vector> son_objects = _remote_db->get_sons(gpo.active_sons); + vector son_ids; + son_ids.reserve(gpo.active_sons.size()); + std::transform(gpo.active_sons.begin(), gpo.active_sons.end(), + std::inserter(son_ids, son_ids.end()), + [](const son_info& swi) { + return swi.son_id; + }); + std::vector> son_objects = _remote_db->get_sons(son_ids); vector owners; owners.resize(son_objects.size()); std::transform(son_objects.begin(), son_objects.end(), owners.begin(), @@ -1952,7 +1959,7 @@ public: }); vector> accs = _remote_db->get_accounts(owners); map result; - std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(), + std::transform(accs.begin(), accs.end(), son_ids.begin(), std::inserter(result, result.end()), [](fc::optional& acct, son_id_type& sid) { FC_ASSERT(acct, "Invalid active SONs list in global properties.");