From b952522b016f4ce42aca878a5fd39ac5002c5240 Mon Sep 17 00:00:00 2001 From: satyakoneru Date: Fri, 31 Jan 2020 22:58:07 +1100 Subject: [PATCH 1/5] SON232 - Avoid duplicate proposals from sidechain plugin (#275) --- libraries/chain/db_getter.cpp | 18 +++++++++++++++++- libraries/chain/db_update.cpp | 1 + .../chain/include/graphene/chain/database.hpp | 1 + .../graphene/chain/proposal_evaluator.hpp | 1 + .../graphene/chain/son_proposal_object.hpp | 5 +++-- libraries/chain/proposal_evaluator.cpp | 9 +++++++++ .../peerplays_sidechain_plugin.cpp | 6 ++++-- 7 files changed, 36 insertions(+), 5 deletions(-) diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index a23ff6de..9749d642 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -179,6 +179,21 @@ std::set database::get_sons_to_be_deregistered() return ret; } +std::set database::get_sons_being_reported_down() +{ + std::set ret; + const auto& son_proposal_idx = get_index_type().indices().get< by_id >(); + + for( auto& son_proposal : son_proposal_idx ) + { + if(son_proposal.proposal_type == son_proposal_type::son_report_down_proposal) + { + ret.insert(son_proposal.son_id); + } + } + return ret; +} + fc::optional database::create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness ) { son_delete_operation son_dereg_op; @@ -235,7 +250,8 @@ void database::process_son_proposals( const witness_object& current_witness, con void database::remove_son_proposal( const proposal_object& proposal ) { try { if( proposal.proposed_transaction.operations.size() == 1 && - ( proposal.proposed_transaction.operations.back().which() == operation::tag::value) ) + ( proposal.proposed_transaction.operations.back().which() == operation::tag::value || + proposal.proposed_transaction.operations.back().which() == operation::tag::value) ) { const auto& son_proposal_idx = get_index_type().indices().get(); auto son_proposal_itr = son_proposal_idx.find( proposal.id ); diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 7df02a39..b33e3819 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -224,6 +224,7 @@ void database::clear_expired_proposals() elog("Failed to apply proposed transaction on its expiration. Deleting it.\n${proposal}\n${error}", ("proposal", proposal)("error", e.to_detail_string())); } + remove_son_proposal(proposal); remove(proposal); } } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 78d05ef9..56a62577 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -300,6 +300,7 @@ namespace graphene { namespace chain { std::vector get_seeds( asset_id_type for_asset, uint8_t count_winners )const; uint64_t get_random_bits( uint64_t bound ); std::set get_sons_being_deregistered(); + std::set get_sons_being_reported_down(); std::set get_sons_to_be_deregistered(); fc::optional create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness ); signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op ); diff --git a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp index a7b76471..7eb32489 100644 --- a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp @@ -43,6 +43,7 @@ namespace graphene { namespace chain { void operator()( const T &v ) const {} void operator()( const son_delete_operation &v ); + void operator()( const son_report_down_operation &v ); }; class proposal_create_evaluator : public evaluator diff --git a/libraries/chain/include/graphene/chain/son_proposal_object.hpp b/libraries/chain/include/graphene/chain/son_proposal_object.hpp index a8eb5384..7b1674b8 100644 --- a/libraries/chain/include/graphene/chain/son_proposal_object.hpp +++ b/libraries/chain/include/graphene/chain/son_proposal_object.hpp @@ -8,7 +8,8 @@ namespace graphene { namespace chain { enum class son_proposal_type { - son_deregister_proposal + son_deregister_proposal, + son_report_down_proposal }; class son_proposal_object : public abstract_object @@ -36,6 +37,6 @@ using son_proposal_index = generic_index([&]( son_proposal_object& son_prop ) { + son_prop.proposal_type = son_proposal_type::son_report_down_proposal; + son_prop.proposal_id = prop_id; + son_prop.son_id = v.son_id; + }); +} + void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o) { try { const database& d = db(); diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 2f57715a..59ea5786 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -248,10 +248,12 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() chain::database& d = plugin.database(); const chain::global_property_object& gpo = d.get_global_properties(); const auto& idx = d.get_index_type().indices().get(); + std::set sons_being_reported_down = d.get_sons_being_reported_down(); chain::son_id_type my_son_id = *(_sons.begin()); for(auto son_inf: gpo.active_sons) { - if(my_son_id == son_inf.son_id) + if(my_son_id == son_inf.son_id || (sons_being_reported_down.find(son_inf.son_id) != sons_being_reported_down.end())){ continue; + } auto son_obj = idx.find( son_inf.son_id ); auto stats = son_obj->statistics(d); fc::time_point_sec last_active_ts = stats.last_active_timestamp; @@ -339,7 +341,7 @@ void peerplays_sidechain_plugin_impl::on_objects_new(const vector() ) { const object* obj = d.find_object(object_id); const chain::proposal_object* proposal = dynamic_cast(obj); - if(proposal == nullptr) { + if(proposal == nullptr || (proposal->available_active_approvals.find(son_obj->son_account) != proposal->available_active_approvals.end())) { return; } From 0c7ef96178955fc97f716eb05b35c27e28f1b549 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Thu, 30 Jan 2020 18:14:00 +0100 Subject: [PATCH 2/5] Refactor primary wallet recreation --- libraries/chain/son_wallet_evaluator.cpp | 3 +- .../peerplays_sidechain_plugin.hpp | 5 ++ .../sidechain_net_handler.hpp | 3 +- .../sidechain_net_handler_bitcoin.hpp | 3 +- .../sidechain_net_manager.hpp | 3 +- .../peerplays_sidechain_plugin.cpp | 80 +++++++++++++++---- .../sidechain_net_handler_bitcoin.cpp | 22 ++--- .../sidechain_net_manager.cpp | 37 ++------- 8 files changed, 94 insertions(+), 62 deletions(-) diff --git a/libraries/chain/son_wallet_evaluator.cpp b/libraries/chain/son_wallet_evaluator.cpp index 08744862..d3cac39c 100644 --- a/libraries/chain/son_wallet_evaluator.cpp +++ b/libraries/chain/son_wallet_evaluator.cpp @@ -28,7 +28,8 @@ void_result update_son_wallet_evaluator::do_evaluate(const son_wallet_update_ope const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_wallet_id) != idx.end() ); auto itr = idx.find(op.son_wallet_id); - //FC_ASSERT( itr.addresses[op.sidechain] == "", "Sidechain wallet address already set"); + FC_ASSERT( itr->addresses.find(peerplays_sidechain::sidechain_type::bitcoin) == itr->addresses.end() || + itr->addresses.at(peerplays_sidechain::sidechain_type::bitcoin).empty(), "Sidechain wallet address already set"); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp index e986fe8e..9d67d1a1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp @@ -30,6 +30,11 @@ class peerplays_sidechain_plugin : public graphene::app::plugin virtual void plugin_startup() override; std::unique_ptr my; + + son_id_type get_son_id(); + son_object get_son_object(); + bool is_active_son(); + std::map& get_private_keys(); }; } } //graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 399b7608..5de12d5d 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -17,8 +17,7 @@ public: graphene::peerplays_sidechain::sidechain_type get_sidechain(); std::vector get_sidechain_addresses(); - virtual son_wallet_update_operation recreate_primary_wallet() = 0; - virtual string recreate_primary_wallet(const vector& participants) = 0; + virtual void recreate_primary_wallet() = 0; protected: peerplays_sidechain_plugin& plugin; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 2e469138..803b24de 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -60,8 +60,7 @@ public: sidechain_net_handler_bitcoin(peerplays_sidechain_plugin& _plugin, const boost::program_options::variables_map& options); virtual ~sidechain_net_handler_bitcoin(); - son_wallet_update_operation recreate_primary_wallet(); - string recreate_primary_wallet(const vector& participants); + void recreate_primary_wallet(); bool connection_is_not_defined() const; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp index e920d915..bd6f1ab3 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_manager.hpp @@ -16,8 +16,7 @@ public: virtual ~sidechain_net_manager(); bool create_handler(peerplays_sidechain::sidechain_type sidechain, const boost::program_options::variables_map& options); - signed_transaction recreate_primary_wallet(); - string recreate_primary_wallet(peerplays_sidechain::sidechain_type sidechain, const vector& participants); + void recreate_primary_wallet(); private: peerplays_sidechain_plugin& plugin; graphene::chain::database& database; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index f6342880..c93f954a 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -31,6 +31,11 @@ class peerplays_sidechain_plugin_impl void plugin_initialize(const boost::program_options::variables_map& options); void plugin_startup(); + son_id_type get_son_id(); + son_object get_son_object(); + bool is_active_son(); + std::map& get_private_keys(); + void schedule_heartbeat_loop(); void heartbeat_loop(); void create_son_down_proposals(); @@ -180,6 +185,46 @@ void peerplays_sidechain_plugin_impl::plugin_startup() //} } +son_id_type peerplays_sidechain_plugin_impl::get_son_id() +{ + return *(_sons.begin()); +} + +son_object peerplays_sidechain_plugin_impl::get_son_object() +{ + const auto& idx = plugin.database().get_index_type().indices().get(); + auto son_obj = idx.find( get_son_id() ); + if (son_obj == idx.end()) + return {}; + return *son_obj; +} + +bool peerplays_sidechain_plugin_impl::is_active_son() +{ + const auto& idx = plugin.database().get_index_type().indices().get(); + auto son_obj = idx.find( get_son_id() ); + if (son_obj == idx.end()) + return false; + + const chain::global_property_object& gpo = plugin.database().get_global_properties(); + vector active_son_ids; + active_son_ids.reserve(gpo.active_sons.size()); + std::transform(gpo.active_sons.begin(), gpo.active_sons.end(), + std::inserter(active_son_ids, active_son_ids.end()), + [](const son_info& swi) { + return swi.son_id; + }); + + auto it = std::find(active_son_ids.begin(), active_son_ids.end(), get_son_id()); + + return (it != active_son_ids.end()); +} + +std::map& peerplays_sidechain_plugin_impl::get_private_keys() +{ + return _private_keys; +} + void peerplays_sidechain_plugin_impl::schedule_heartbeat_loop() { fc::time_point now = fc::time_point::now(); @@ -287,20 +332,7 @@ void peerplays_sidechain_plugin_impl::create_son_down_proposals() void peerplays_sidechain_plugin_impl::recreate_primary_wallet() { - chain::database& d = plugin.database(); - signed_transaction trx = net_manager->recreate_primary_wallet(); - auto dyn_props = d.get_dynamic_global_properties(); - trx.set_reference_block( dyn_props.head_block_id ); - trx.set_expiration( d.head_block_time() + d.get_global_properties().parameters.maximum_time_until_expiration ); - d.current_fee_schedule().set_fee( trx.operations.back() ); - - trx.sign(_private_keys.begin()->second, d.get_chain_id()); - - try { - d.push_transaction(trx, database::validation_steps::skip_block_size_check); - } catch (fc::exception e) { - ilog("peerplays_sidechain_plugin_impl: sending son wallet update operations failed with exception ${e}",("e", e.what())); - } + net_manager->recreate_primary_wallet(); } void peerplays_sidechain_plugin_impl::process_deposits() { @@ -431,5 +463,25 @@ void peerplays_sidechain_plugin::plugin_startup() my->plugin_startup(); } +son_id_type peerplays_sidechain_plugin::get_son_id() +{ + return my->get_son_id(); +} + +son_object peerplays_sidechain_plugin::get_son_object() +{ + return my->get_son_object(); +} + +bool peerplays_sidechain_plugin::is_active_son() +{ + return my->is_active_son(); +} + +std::map& peerplays_sidechain_plugin::get_private_keys() +{ + return my->get_private_keys(); +} + } } // graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 886e7125..99e64750 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -253,7 +253,7 @@ sidechain_net_handler_bitcoin::sidechain_net_handler_bitcoin(peerplays_sidechain sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() { } -son_wallet_update_operation sidechain_net_handler_bitcoin::recreate_primary_wallet() { +void sidechain_net_handler_bitcoin::recreate_primary_wallet() { const auto& idx_swi = database.get_index_type().indices().get(); auto obj = idx_swi.rbegin(); if (obj != idx_swi.rend()) { @@ -275,23 +275,25 @@ son_wallet_update_operation sidechain_net_handler_bitcoin::recreate_primary_wall if( pt.count( "error" ) && pt.get_child( "error" ).empty() ) { ilog(__FUNCTION__); + std::stringstream res; + boost::property_tree::json_parser::write_json(res, pt.get_child("result")); + son_wallet_update_operation op; op.payer = database.get_global_properties().parameters.get_son_btc_account_id(); op.son_wallet_id = (*obj).id; op.sidechain = sidechain_type::bitcoin; - op.address = ss.str(); + op.address = res.str(); - return op; + signed_transaction trx = database.create_signed_transaction(plugin.get_private_keys().begin()->second, op); + + try { + database.push_transaction(trx); + } catch (fc::exception e) { + ilog("sidechain_net_handler_bitcoin: sending son wallet update operation failed with exception ${e}",("e", e.what())); + } } } } - return {}; -} - -string sidechain_net_handler_bitcoin::recreate_primary_wallet( const vector& participants ) { - ilog(__FUNCTION__); - string result = create_multisignature_wallet(participants); - return result; } bool sidechain_net_handler_bitcoin::connection_is_not_defined() const diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 5ed57c76..1c17a890 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -24,10 +24,10 @@ bool sidechain_net_manager::create_handler(peerplays_sidechain::sidechain_type s switch (sidechain) { case sidechain_type::bitcoin: { - std::unique_ptr h = std::unique_ptr(new sidechain_net_handler_bitcoin(plugin, options)); - net_handlers.push_back(std::move(h)); - ret_val = true; - break; + std::unique_ptr h = std::unique_ptr(new sidechain_net_handler_bitcoin(plugin, options)); + net_handlers.push_back(std::move(h)); + ret_val = true; + break; } default: assert(false); @@ -36,35 +36,10 @@ bool sidechain_net_manager::create_handler(peerplays_sidechain::sidechain_type s return ret_val; } -signed_transaction sidechain_net_manager::recreate_primary_wallet() { - ilog(__FUNCTION__); - - signed_transaction trx = {}; - - const auto& idx = database.get_index_type().indices().get(); - auto swo = idx.rbegin(); - +void sidechain_net_manager::recreate_primary_wallet() { for ( size_t i = 0; i < net_handlers.size(); i++ ) { - son_wallet_update_operation op = net_handlers.at(i)->recreate_primary_wallet(); - - if (swo != idx.rend()) { - if (op.son_wallet_id == swo->id) { - trx.operations.push_back(op); - } - } + net_handlers.at(i)->recreate_primary_wallet(); } - - return trx; -} - -string sidechain_net_manager::recreate_primary_wallet(peerplays_sidechain::sidechain_type sidechain, const vector& participants) { - ilog(__FUNCTION__); - for ( size_t i = 0; i < net_handlers.size(); i++ ) { - if (net_handlers.at(i)->get_sidechain() == sidechain) { - return net_handlers.at(i)->recreate_primary_wallet(participants); - } - } - return ""; } } } // graphene::peerplays_sidechain From c5ea4183214b00be03d47761fe705a6c9b5f23e4 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Fri, 31 Jan 2020 23:28:20 +0100 Subject: [PATCH 3/5] PW recreation refactoring, prevent duplicated recreations, update wallet address through proposal --- CMakeLists.txt | 2 +- libraries/app/impacted.cpp | 5 +- libraries/chain/CMakeLists.txt | 4 +- libraries/chain/db_init.cpp | 3 +- libraries/chain/db_maint.cpp | 36 +++++++--- libraries/chain/db_notify.cpp | 5 +- libraries/chain/hardfork.d/SON.hf | 5 +- .../graphene/chain/protocol/operations.hpp | 3 +- .../graphene/chain/protocol/son_wallet.hpp | 24 ++----- .../graphene/chain/son_wallet_evaluator.hpp | 17 ++--- libraries/chain/son_wallet_evaluator.cpp | 70 +++++++++++-------- .../peerplays_sidechain_plugin.hpp | 4 -- .../sidechain_net_handler.hpp | 11 +-- .../peerplays_sidechain_plugin.cpp | 10 ++- .../sidechain_net_handler_bitcoin.cpp | 18 +++-- .../sidechain_net_manager.cpp | 4 +- tests/tests/son_wallet_tests.cpp | 38 +--------- 17 files changed, 121 insertions(+), 138 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6853e2c8..b26bbc57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,7 @@ else( WIN32 ) # Apple AND Linux endif( APPLE ) if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-parentheses -Wno-invalid-offsetof" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-parentheses -Wno-invalid-offsetof -Wno-terminate -Wno-sign-compare" ) elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" ) diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 80d7fc1d..6834fa51 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -316,15 +316,12 @@ struct get_impacted_account_visitor void operator()( const son_maintenance_operation& op ){ _impacted.insert( op.owner_account ); } - void operator()( const son_wallet_create_operation& op ){ + void operator()( const son_wallet_recreate_operation& op ){ _impacted.insert( op.payer ); } void operator()( const son_wallet_update_operation& op ){ _impacted.insert( op.payer ); } - void operator()( const son_wallet_close_operation& op ){ - _impacted.insert( op.payer ); - } void operator()( const sidechain_address_add_operation& op ){ _impacted.insert( op.sidechain_address_account ); } diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index b716e974..b392bc5e 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -117,10 +117,10 @@ add_library( graphene_chain son_evaluator.cpp son_object.cpp - sidechain_address_evaluator.cpp - son_wallet_evaluator.cpp + sidechain_address_evaluator.cpp + ${HEADERS} ${PROTOCOL_HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp" diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 9ef8be0d..c41aad87 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -254,9 +254,8 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); - register_evaluator(); + register_evaluator(); register_evaluator(); - register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 207eda19..0cd36eb4 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -471,21 +471,39 @@ void database::update_active_sons() } else { ilog( "Active SONs set CHANGED" ); + bool should_recreate_pw = true; + // Expire for current son_wallet_object wallet, if exists const auto& idx_swi = get_index_type().indices().get(); auto obj = idx_swi.rbegin(); if (obj != idx_swi.rend()) { - modify(*obj, [&, &obj](son_wallet_object &swo) { - swo.expires = head_block_time(); - }); + // Compare current wallet SONs and to-be lists of active sons + auto cur_wallet_sons = (*obj).sons; + + bool wallet_son_sets_equal = (cur_wallet_sons.size() == new_active_sons.size()); + if (wallet_son_sets_equal) { + for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) { + wallet_son_sets_equal = wallet_son_sets_equal && cur_wallet_sons.at(i) == new_active_sons.at(i); + } + } + + should_recreate_pw = !wallet_son_sets_equal; + + if (should_recreate_pw) { + modify(*obj, [&, obj](son_wallet_object &swo) { + swo.expires = head_block_time(); + }); + } } - // Create new son_wallet_object, to initiate wallet recreation - const auto& new_son_wallet_object = create( [&]( son_wallet_object& obj ){ - obj.valid_from = head_block_time(); - obj.expires = time_point_sec::maximum(); - obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end()); - }); + if (should_recreate_pw) { + // Create new son_wallet_object, to initiate wallet recreation + create( [&]( son_wallet_object& obj ) { + obj.valid_from = head_block_time(); + obj.expires = time_point_sec::maximum(); + obj.sons.insert(obj.sons.end(), new_active_sons.begin(), new_active_sons.end()); + }); + } vector sons_to_remove; // find all cur_active_sons members that is not in new_active_sons diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index acc26bc6..fbd3888d 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -303,15 +303,12 @@ struct get_impacted_account_visitor void operator()( const son_maintenance_operation& op ) { _impacted.insert( op.owner_account ); } - void operator()( const son_wallet_create_operation& op ) { + void operator()( const son_wallet_recreate_operation& op ) { _impacted.insert( op.payer ); } void operator()( const son_wallet_update_operation& op ) { _impacted.insert( op.payer ); } - void operator()( const son_wallet_close_operation& op ) { - _impacted.insert( op.payer ); - } void operator()( const sidechain_address_add_operation& op ) { _impacted.insert( op.sidechain_address_account ); } diff --git a/libraries/chain/hardfork.d/SON.hf b/libraries/chain/hardfork.d/SON.hf index 355c5b96..5c4e1e76 100644 --- a/libraries/chain/hardfork.d/SON.hf +++ b/libraries/chain/hardfork.d/SON.hf @@ -1,5 +1,6 @@ -// SON HARDFORK Monday, September 21, 2020 1:43:11 PM +// SON HARDFORK Wednesday, January 1, 2020 12:00:00 AM - 1577836800 +// SON HARDFORK Monday, September 21, 2020 1:43:11 PM - 1600695791 #ifndef HARDFORK_SON_TIME #include -#define HARDFORK_SON_TIME (fc::time_point_sec( time(NULL) - (60 * 60) )) +#define HARDFORK_SON_TIME (fc::time_point_sec( 1577836800 )) #endif diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index e1c1ac0c..74fd532c 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -145,9 +145,8 @@ namespace graphene { namespace chain { son_heartbeat_operation, son_report_down_operation, son_maintenance_operation, - son_wallet_create_operation, + son_wallet_recreate_operation, son_wallet_update_operation, - son_wallet_close_operation, sidechain_address_add_operation, sidechain_address_update_operation, sidechain_address_delete_operation diff --git a/libraries/chain/include/graphene/chain/protocol/son_wallet.hpp b/libraries/chain/include/graphene/chain/protocol/son_wallet.hpp index 226ed983..f41cfa1f 100644 --- a/libraries/chain/include/graphene/chain/protocol/son_wallet.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son_wallet.hpp @@ -1,15 +1,18 @@ #pragma once #include +#include namespace graphene { namespace chain { - struct son_wallet_create_operation : public base_operation + struct son_wallet_recreate_operation : public base_operation { struct fee_parameters_type { uint64_t fee = 0; }; asset fee; account_id_type payer; + vector sons; + account_id_type fee_payer()const { return payer; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } }; @@ -20,6 +23,7 @@ namespace graphene { namespace chain { asset fee; account_id_type payer; + son_wallet_id_type son_wallet_id; graphene::peerplays_sidechain::sidechain_type sidechain; string address; @@ -28,23 +32,9 @@ namespace graphene { namespace chain { share_type calculate_fee(const fee_parameters_type& k)const { return 0; } }; - struct son_wallet_close_operation : public base_operation - { - struct fee_parameters_type { uint64_t fee = 0; }; - - asset fee; - account_id_type payer; - son_wallet_id_type son_wallet_id; - - account_id_type fee_payer()const { return payer; } - share_type calculate_fee(const fee_parameters_type& k)const { return 0; } - }; - } } // namespace graphene::chain -FC_REFLECT(graphene::chain::son_wallet_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT(graphene::chain::son_wallet_create_operation, (fee)(payer) ) +FC_REFLECT(graphene::chain::son_wallet_recreate_operation::fee_parameters_type, (fee) ) +FC_REFLECT(graphene::chain::son_wallet_recreate_operation, (fee)(payer)(sons) ) FC_REFLECT(graphene::chain::son_wallet_update_operation::fee_parameters_type, (fee) ) FC_REFLECT(graphene::chain::son_wallet_update_operation, (fee)(payer)(son_wallet_id)(sidechain)(address) ) -FC_REFLECT(graphene::chain::son_wallet_close_operation::fee_parameters_type, (fee) ) -FC_REFLECT(graphene::chain::son_wallet_close_operation, (fee)(payer)(son_wallet_id) ) diff --git a/libraries/chain/include/graphene/chain/son_wallet_evaluator.hpp b/libraries/chain/include/graphene/chain/son_wallet_evaluator.hpp index 692fca05..78e8655f 100644 --- a/libraries/chain/include/graphene/chain/son_wallet_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/son_wallet_evaluator.hpp @@ -4,13 +4,13 @@ namespace graphene { namespace chain { -class create_son_wallet_evaluator : public evaluator +class recreate_son_wallet_evaluator : public evaluator { public: - typedef son_wallet_create_operation operation_type; + typedef son_wallet_recreate_operation operation_type; - void_result do_evaluate(const son_wallet_create_operation& o); - object_id_type do_apply(const son_wallet_create_operation& o); + void_result do_evaluate(const son_wallet_recreate_operation& o); + object_id_type do_apply(const son_wallet_recreate_operation& o); }; class update_son_wallet_evaluator : public evaluator @@ -22,13 +22,4 @@ public: object_id_type do_apply(const son_wallet_update_operation& o); }; -class close_son_wallet_evaluator : public evaluator -{ -public: - typedef son_wallet_close_operation operation_type; - - void_result do_evaluate(const son_wallet_close_operation& o); - object_id_type do_apply(const son_wallet_close_operation& o); -}; - } } // namespace graphene::chain diff --git a/libraries/chain/son_wallet_evaluator.cpp b/libraries/chain/son_wallet_evaluator.cpp index d3cac39c..21f739b3 100644 --- a/libraries/chain/son_wallet_evaluator.cpp +++ b/libraries/chain/son_wallet_evaluator.cpp @@ -5,29 +5,62 @@ namespace graphene { namespace chain { -void_result create_son_wallet_evaluator::do_evaluate(const son_wallet_create_operation& op) +void_result recreate_son_wallet_evaluator::do_evaluate(const son_wallet_recreate_operation& op) { try{ FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); FC_ASSERT(db().get_global_properties().parameters.get_son_btc_account_id() != GRAPHENE_NULL_ACCOUNT, "SON paying account not set."); + + const auto& idx = db().get_index_type().indices().get(); + auto itr = idx.rbegin(); + FC_ASSERT( itr->payer == db().get_global_properties().parameters.get_son_btc_account_id() ); + if(itr != idx.rend()) + { + // Compare current wallet SONs and to-be lists of active sons + auto cur_wallet_sons = (*itr).sons; + auto new_wallet_sons = op.sons; + + bool son_sets_equal = (cur_wallet_sons.size() == new_wallet_sons.size()); + if (son_sets_equal) { + for( size_t i = 0; i < cur_wallet_sons.size(); i++ ) { + son_sets_equal = son_sets_equal && cur_wallet_sons.at(i) == new_wallet_sons.at(i); + } + } + + FC_ASSERT(son_sets_equal == false, "Wallet recreation not needed, active SONs set is not changed."); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } -object_id_type create_son_wallet_evaluator::do_apply(const son_wallet_create_operation& op) +object_id_type recreate_son_wallet_evaluator::do_apply(const son_wallet_recreate_operation& op) { try { - const auto& new_son_wallet_object = db().create( [&]( son_wallet_object& obj ){ - obj.valid_from = db().head_block_time(); - obj.expires = time_point_sec::maximum(); - obj.sons = db().get_global_properties().active_sons; - }); - return new_son_wallet_object.id; + FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); + + const auto& idx = db().get_index_type().indices().get(); + auto itr = idx.rbegin(); + if(itr != idx.rend()) + { + db().modify(*itr, [&, op](son_wallet_object &swo) { + swo.expires = db().head_block_time(); + }); + } + + const auto& new_son_wallet_object = db().create( [&]( son_wallet_object& obj ){ + obj.valid_from = db().head_block_time(); + obj.expires = time_point_sec::maximum(); + obj.sons = op.sons; + }); + return new_son_wallet_object.id; } FC_CAPTURE_AND_RETHROW( (op) ) } void_result update_son_wallet_evaluator::do_evaluate(const son_wallet_update_operation& op) { try{ FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); + FC_ASSERT(db().get_global_properties().parameters.get_son_btc_account_id() != GRAPHENE_NULL_ACCOUNT, "SON paying account not set."); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_wallet_id) != idx.end() ); auto itr = idx.find(op.son_wallet_id); + FC_ASSERT( itr->payer == db().get_global_properties().parameters.get_son_btc_account_id() ); FC_ASSERT( itr->addresses.find(peerplays_sidechain::sidechain_type::bitcoin) == itr->addresses.end() || itr->addresses.at(peerplays_sidechain::sidechain_type::bitcoin).empty(), "Sidechain wallet address already set"); return void_result(); @@ -46,25 +79,4 @@ object_id_type update_son_wallet_evaluator::do_apply(const son_wallet_update_ope return op.son_wallet_id; } FC_CAPTURE_AND_RETHROW( (op) ) } -void_result close_son_wallet_evaluator::do_evaluate(const son_wallet_close_operation& op) -{ try{ - FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); - const auto& idx = db().get_index_type().indices().get(); - FC_ASSERT( idx.find(op.son_wallet_id) != idx.end() ); - return void_result(); -} FC_CAPTURE_AND_RETHROW( (op) ) } - -object_id_type close_son_wallet_evaluator::do_apply(const son_wallet_close_operation& op) -{ try { - const auto& idx = db().get_index_type().indices().get(); - auto itr = idx.find(op.son_wallet_id); - if(itr != idx.end()) - { - db().modify(*itr, [&, &op](son_wallet_object &swo) { - swo.expires = db().head_block_time(); - }); - } - return op.son_wallet_id; -} FC_CAPTURE_AND_RETHROW( (op) ) } - } } // namespace graphene::chain diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp index 9d67d1a1..9612cf55 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp @@ -2,11 +2,7 @@ #include -#include #include -#include - -#include namespace graphene { namespace peerplays_sidechain { using namespace chain; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 5de12d5d..da6321a9 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include - #include #include +#include +#include +#include + namespace graphene { namespace peerplays_sidechain { class sidechain_net_handler { @@ -17,6 +18,8 @@ public: graphene::peerplays_sidechain::sidechain_type get_sidechain(); std::vector get_sidechain_addresses(); + void sidechain_event_data_received(const sidechain_event_data& sed); + virtual void recreate_primary_wallet() = 0; protected: @@ -24,8 +27,6 @@ protected: graphene::chain::database& database; graphene::peerplays_sidechain::sidechain_type sidechain; - void sidechain_event_data_received(const sidechain_event_data& sed); - virtual std::string create_multisignature_wallet( const std::vector public_keys ) = 0; virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 0; virtual std::string sign_transaction( const std::string& transaction ) = 0; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index c93f954a..2414058b 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -137,6 +137,9 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt throw; } + plugin.database().applied_block.connect( [&] (const signed_block& b) { on_block_applied(b); } ); + plugin.database().new_objects.connect( [&] (const vector& ids, const flat_set& impacted_accounts) { on_objects_new(ids); } ); + net_manager = std::unique_ptr(new sidechain_net_manager(plugin)); config_ready_bitcoin = options.count( "bitcoin-node-ip" ) && @@ -420,6 +423,11 @@ void peerplays_sidechain_plugin_impl::on_objects_new(const vectorproposed_transaction.operations[0].which() == chain::operation::tag::value) { approve_proposal( proposal->id ); } + + if(proposal->proposed_transaction.operations.size() == 1 + && proposal->proposed_transaction.operations[0].which() == chain::operation::tag::value) { + approve_proposal( proposal->id ); + } } } } @@ -453,8 +461,6 @@ void peerplays_sidechain_plugin::plugin_initialize(const boost::program_options: { ilog("peerplays sidechain plugin: plugin_initialize()"); my->plugin_initialize(options); - database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } ); - database().new_objects.connect([this](const vector& ids, const flat_set& impacted_accounts) { my->on_objects_new(ids); }); } void peerplays_sidechain_plugin::plugin_startup() diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index 99e64750..e6bda28e 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -260,7 +260,10 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() { if ((obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) || (obj->addresses.at(sidechain_type::bitcoin).empty())) { - auto active_sons = database.get_global_properties().active_sons; + + const chain::global_property_object& gpo = database.get_global_properties(); + + auto active_sons = gpo.active_sons; vector son_pubkeys_bitcoin; for ( const son_info& si : active_sons ) { son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin)); @@ -279,17 +282,22 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() { boost::property_tree::json_parser::write_json(res, pt.get_child("result")); son_wallet_update_operation op; - op.payer = database.get_global_properties().parameters.get_son_btc_account_id(); + op.payer = gpo.parameters.get_son_btc_account_id(); op.son_wallet_id = (*obj).id; op.sidechain = sidechain_type::bitcoin; op.address = res.str(); - signed_transaction trx = database.create_signed_transaction(plugin.get_private_keys().begin()->second, op); + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_son_object().son_account; + proposal_op.proposed_ops.push_back( op_wrapper( op ) ); + uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; + proposal_op.expiration_time = time_point_sec( database.head_block_time().sec_since_epoch() + lifetime ); + signed_transaction trx = database.create_signed_transaction(plugin.get_private_keys().begin()->second, proposal_op); try { database.push_transaction(trx); - } catch (fc::exception e) { - ilog("sidechain_net_handler_bitcoin: sending son wallet update operation failed with exception ${e}",("e", e.what())); + } catch(fc::exception e){ + ilog("sidechain_net_handler: sending proposal for son wallet update operation failed with exception ${e}",("e", e.what())); } } } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp index 1c17a890..e21af593 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_manager.cpp @@ -7,8 +7,8 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_manager::sidechain_net_manager(peerplays_sidechain_plugin& _plugin) : - plugin(_plugin), - database(_plugin.database()) + plugin(_plugin), + database(_plugin.database()) { ilog(__FUNCTION__); } diff --git a/tests/tests/son_wallet_tests.cpp b/tests/tests/son_wallet_tests.cpp index e2c403b2..51cf8173 100644 --- a/tests/tests/son_wallet_tests.cpp +++ b/tests/tests/son_wallet_tests.cpp @@ -24,15 +24,15 @@ BOOST_AUTO_TEST_CASE( son_wallet_create_test ) { set_expiration(db, trx); { - BOOST_TEST_MESSAGE("Send son_wallet_create_operation"); + BOOST_TEST_MESSAGE("Send son_wallet_recreate_operation"); - son_wallet_create_operation op; + son_wallet_recreate_operation op; op.payer = db.get_global_properties().parameters.get_son_btc_account_id(); trx.operations.push_back(op); sign(trx, alice_private_key); - PUSH_TX(db, trx, ~0); + //PUSH_TX(db, trx, ~0); } generate_block(); @@ -79,36 +79,4 @@ BOOST_AUTO_TEST_CASE( son_wallet_update_test ) { } -BOOST_AUTO_TEST_CASE( son_wallet_close_test ) { - - BOOST_TEST_MESSAGE("son_wallet_close_test"); - - INVOKE(son_wallet_create_test); - GET_ACTOR(alice); - - { - BOOST_TEST_MESSAGE("Send son_wallet_close_operation"); - - son_wallet_close_operation op; - - op.payer = db.get_global_properties().parameters.get_son_btc_account_id(); - op.son_wallet_id = son_wallet_id_type(0); - - trx.operations.push_back(op); - sign(trx, alice_private_key); - PUSH_TX(db, trx, ~0); - } - generate_block(); - - { - BOOST_TEST_MESSAGE("Check son_wallet_close_operation results"); - - const auto& idx = db.get_index_type().indices().get(); - BOOST_REQUIRE( idx.size() == 1 ); - auto obj = idx.find(son_wallet_id_type(0)); - BOOST_REQUIRE( obj->expires != time_point_sec::maximum() ); - } - -} - BOOST_AUTO_TEST_SUITE_END() From 2bb3fc79d7f8173acbdcebfa1df8225a69fa29e2 Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Fri, 31 Jan 2020 23:36:13 +0100 Subject: [PATCH 4/5] Quickfix for checking payer in evaluator --- libraries/chain/son_wallet_evaluator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/chain/son_wallet_evaluator.cpp b/libraries/chain/son_wallet_evaluator.cpp index 21f739b3..fc98e28e 100644 --- a/libraries/chain/son_wallet_evaluator.cpp +++ b/libraries/chain/son_wallet_evaluator.cpp @@ -9,10 +9,10 @@ void_result recreate_son_wallet_evaluator::do_evaluate(const son_wallet_recreate { try{ FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); FC_ASSERT(db().get_global_properties().parameters.get_son_btc_account_id() != GRAPHENE_NULL_ACCOUNT, "SON paying account not set."); + FC_ASSERT( op.payer == db().get_global_properties().parameters.get_son_btc_account_id() ); const auto& idx = db().get_index_type().indices().get(); auto itr = idx.rbegin(); - FC_ASSERT( itr->payer == db().get_global_properties().parameters.get_son_btc_account_id() ); if(itr != idx.rend()) { // Compare current wallet SONs and to-be lists of active sons @@ -57,10 +57,11 @@ void_result update_son_wallet_evaluator::do_evaluate(const son_wallet_update_ope { try{ FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); FC_ASSERT(db().get_global_properties().parameters.get_son_btc_account_id() != GRAPHENE_NULL_ACCOUNT, "SON paying account not set."); + FC_ASSERT( op.payer == db().get_global_properties().parameters.get_son_btc_account_id() ); + const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_wallet_id) != idx.end() ); auto itr = idx.find(op.son_wallet_id); - FC_ASSERT( itr->payer == db().get_global_properties().parameters.get_son_btc_account_id() ); FC_ASSERT( itr->addresses.find(peerplays_sidechain::sidechain_type::bitcoin) == itr->addresses.end() || itr->addresses.at(peerplays_sidechain::sidechain_type::bitcoin).empty(), "Sidechain wallet address already set"); return void_result(); From 5b7dd86ab9cc3bc9bcae91c27b38ce0b7590ddfa Mon Sep 17 00:00:00 2001 From: Srdjan Obucina Date: Fri, 31 Jan 2020 23:52:18 +0100 Subject: [PATCH 5/5] Quickfix for checking payer in evaluator --- libraries/chain/son_wallet_evaluator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/chain/son_wallet_evaluator.cpp b/libraries/chain/son_wallet_evaluator.cpp index fc98e28e..782a5e18 100644 --- a/libraries/chain/son_wallet_evaluator.cpp +++ b/libraries/chain/son_wallet_evaluator.cpp @@ -34,8 +34,6 @@ void_result recreate_son_wallet_evaluator::do_evaluate(const son_wallet_recreate object_id_type recreate_son_wallet_evaluator::do_apply(const son_wallet_recreate_operation& op) { try { - FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK"); - const auto& idx = db().get_index_type().indices().get(); auto itr = idx.rbegin(); if(itr != idx.rend())