diff --git a/libraries/chain/chain_config.cpp b/libraries/chain/chain_config.cpp index 35c77f8325d..c39d89cee46 100644 --- a/libraries/chain/chain_config.cpp +++ b/libraries/chain/chain_config.cpp @@ -43,4 +43,10 @@ namespace eosio { namespace chain { "max authority depth should be at least 1" ); } +void chain_config2::validate() const{ + EOS_ASSERT(std::numeric_limits::max() > actor_blacklist.size(), action_validate_exception, "Overflow in blacklist when adding actor blacklist!"); + EOS_ASSERT(std::numeric_limits::max() > contract_blacklist.size(), action_validate_exception, "Overflow in blacklist when adding contract blacklist!"); + EOS_ASSERT(std::numeric_limits::max() > resource_greylist.size(), action_validate_exception, "Overflow in greylistwhen adding resource greylist!"); +} + } } // namespace eosio::chain diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index f3b0a841981..de4f6c04fed 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -32,6 +32,7 @@ using controller_index_set = index_set< account_index, account_sequence_index, global_property_multi_index, + global_property2_multi_index, dynamic_global_property_multi_index, block_summary_multi_index, transaction_multi_index, @@ -124,6 +125,7 @@ struct controller_impl { resource_limits_manager resource_limits; authorization_manager authorization; controller::config conf; + controller::config multisig_blacklists;///< multisig blacklists in memory chain_id_type chain_id; bool replaying= false; optional replay_head_time; @@ -400,6 +402,7 @@ struct controller_impl { ilog( "database initialized with hash: ${hash}", ("hash", hash) ); } + merge_msig_blacklist_into_conf(); } ~controller_impl() { @@ -641,6 +644,9 @@ struct controller_impl { }); db.create([](auto&){}); + db.create([&](auto &gpo) { + + }); authorization.initialize_database(); resource_limits.initialize_database(); @@ -666,7 +672,128 @@ struct controller_impl { conf.genesis.initial_timestamp ); } + void set_blacklist(blacklist_type list, list_action_type action, std::vector accounts) + { + //set list from set_blacklist action in system contract + EOS_ASSERT(action >= list_action_type::insert_type && action < list_action_type::list_action_type_count, transaction_exception, "unknown action: ${action}", ("action", static_cast(action))); + int64_t blacklist_type = static_cast(list); + const auto &gp2o = db.get(); + auto update_blacklists = [&](const shared_vector &db_blacklist, flat_set &conf_blacklist, flat_set &msig_blacklist){ + for (auto &a : db_blacklist){ + conf_blacklist.insert(a); + msig_blacklist.insert(a); + } + + auto update_blacklist = [&](auto &blacklist) { + if (action == list_action_type::insert_type){ + blacklist.insert(accounts.begin(), accounts.end()); + } + else if (action == list_action_type::remove_type){ + flat_set name_set(accounts.begin(), accounts.end()); + flat_set results; + results.reserve(blacklist.size()); + set_difference(blacklist.begin(), blacklist.end(), + name_set.begin(), name_set.end(), + std::inserter(results, results.begin())); + + blacklist = results; + } + }; + + update_blacklist(conf_blacklist); + update_blacklist(msig_blacklist); + auto insert_blacklists = [&](auto &gp2) { + auto insert_blacklist = [&](shared_vector &blacklist) { + blacklist.clear(); + + for (auto &a : msig_blacklist){ + blacklist.push_back(a); + } + }; + + switch (list){ + case blacklist_type::actor_blacklist_type: + insert_blacklist(gp2.cfg.actor_blacklist); + break; + case blacklist_type::contract_blacklist_type: + insert_blacklist(gp2.cfg.contract_blacklist); + break; + case blacklist_type::resource_greylist_type: + insert_blacklist(gp2.cfg.resource_greylist); + break; + default: + EOS_ASSERT(false, transaction_exception, + "unknown list type : ${blklsttype}", ("blklsttype", blacklist_type)); + } + }; + + db.modify(gp2o, [&](auto &gp2) { + insert_blacklists(gp2); + }); + }; + + switch (list){ + case blacklist_type::actor_blacklist_type: + update_blacklists(gp2o.cfg.actor_blacklist, conf.actor_blacklist, multisig_blacklists.actor_blacklist); + break; + case blacklist_type::contract_blacklist_type: + update_blacklists(gp2o.cfg.contract_blacklist, conf.contract_blacklist, multisig_blacklists.contract_blacklist); + break; + case blacklist_type::resource_greylist_type: + update_blacklists(gp2o.cfg.resource_greylist, conf.resource_greylist, multisig_blacklists.resource_greylist); + break; + default: + EOS_ASSERT(false, transaction_exception, + "unknown list type : ${blklsttype}", ("blklsttype", blacklist_type)); + } + } + + void check_msig_blacklist(blacklist_type blacklist_type,account_name account) + { + auto check_blacklist = [&](const flat_set& msig_blacklist){ + EOS_ASSERT(msig_blacklist.find(account) == msig_blacklist.end(), transaction_exception, + " do not remove account in multisig blacklist , account: ${account}", ("account", account)); + }; + + switch (blacklist_type) + { + case blacklist_type::actor_blacklist_type: + check_blacklist(multisig_blacklists.actor_blacklist); + break; + case blacklist_type::contract_blacklist_type: + check_blacklist(multisig_blacklists.contract_blacklist); + break; + case blacklist_type::resource_greylist_type: + check_blacklist(multisig_blacklists.resource_greylist); + break; + default: + EOS_ASSERT(false, transaction_exception, + "unknown list type : ${blklsttype}, account: ${account}", ("blklsttype",static_cast(blacklist_type))("account", account)); + } + } + + void merge_msig_blacklist_into_conf() + { + try{ + auto merge_blacklist = [&](const shared_vector& msig_blacklist_in_db,flat_set& conf_blacklist){ + + for (auto& a : msig_blacklist_in_db) + { + conf_blacklist.insert(a); + } + }; + + const auto &gp2o = db.get(); + merge_blacklist(gp2o.cfg.actor_blacklist,conf.actor_blacklist); + merge_blacklist(gp2o.cfg.contract_blacklist,conf.contract_blacklist); + merge_blacklist(gp2o.cfg.resource_greylist,conf.resource_greylist); + } + catch (...) + { + wlog("when plugin initialize,execute merge multsig blacklist to ignore exception before create global property2 object"); + } + } /** * @post regardless of the success of commit block there is no active pending block @@ -2201,6 +2328,7 @@ void controller::add_resource_greylist(const account_name &name) { } void controller::remove_resource_greylist(const account_name &name) { + my->check_msig_blacklist(blacklist_type::resource_greylist_type,name); my->conf.resource_greylist.erase(name); } @@ -2212,4 +2340,11 @@ const flat_set &controller::get_resource_greylist() const { return my->conf.resource_greylist; } +const global_property2_object& controller::get_global_properties2()const { + return my->db.get(); +} +void controller::set_blacklist(int64_t list, int64_t action, std::vector accounts) +{ + my->set_blacklist(static_cast(list), static_cast(action), accounts); +} } } /// eosio::chain diff --git a/libraries/chain/include/eosio/chain/chain_config.hpp b/libraries/chain/include/eosio/chain/chain_config.hpp index 37b73cb51fe..50faf064ed9 100644 --- a/libraries/chain/include/eosio/chain/chain_config.hpp +++ b/libraries/chain/include/eosio/chain/chain_config.hpp @@ -105,6 +105,16 @@ struct chain_config { }; +struct chain_config2 { + chain_config2( chainbase::allocator alloc ) + :actor_blacklist(alloc),contract_blacklist(alloc),resource_greylist(alloc){} + + shared_vector actor_blacklist; + shared_vector contract_blacklist; + shared_vector resource_greylist; + + void validate()const; +}; } } // namespace eosio::chain FC_REFLECT(eosio::chain::chain_config, @@ -119,3 +129,4 @@ FC_REFLECT(eosio::chain::chain_config, (max_inline_action_size)(max_inline_action_depth)(max_authority_depth) ) +FC_REFLECT( eosio::chain::chain_config2, (actor_blacklist)(contract_blacklist)(resource_greylist) ) diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 2aab3179668..1d2ed58ac28 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -31,6 +31,7 @@ namespace eosio { namespace chain { class dynamic_global_property_object; class global_property_object; + class global_property2_object; class permission_object; class account_object; using resource_limits::resource_limits_manager; @@ -50,6 +51,18 @@ namespace eosio { namespace chain { FULL, LIGHT }; + enum class blacklist_type:int64_t { + actor_blacklist_type=1, + contract_blacklist_type, + resource_greylist_type, + list_type_count + }; + enum class list_action_type:int64_t + { + insert_type = 1, + remove_type, + list_action_type_count + }; class controller { public: @@ -213,6 +226,8 @@ namespace eosio { namespace chain { void add_resource_greylist(const account_name &name); void remove_resource_greylist(const account_name &name); + const global_property2_object& get_global_properties2()const; + void set_blacklist(int64_t list, int64_t action, std::vector accounts); bool is_resource_greylisted(const account_name &name) const; const flat_set &get_resource_greylist() const; diff --git a/libraries/chain/include/eosio/chain/global_property_object.hpp b/libraries/chain/include/eosio/chain/global_property_object.hpp index 7f3c09cccf5..48a01cdbdac 100644 --- a/libraries/chain/include/eosio/chain/global_property_object.hpp +++ b/libraries/chain/include/eosio/chain/global_property_object.hpp @@ -34,6 +34,14 @@ namespace eosio { namespace chain { chain_config configuration; }; + class global_property2_object : public chainbase::object + { + OBJECT_CTOR(global_property2_object, (cfg)) + + id_type id; + chain_config2 cfg; + + }; /** @@ -71,11 +79,20 @@ namespace eosio { namespace chain { > >; + using global_property2_multi_index = chainbase::shared_multi_index_container< + global_property2_object, + indexed_by< + ordered_unique, + BOOST_MULTI_INDEX_MEMBER(global_property2_object, global_property2_object::id_type, id) + > + > + >; }} CHAINBASE_SET_INDEX_TYPE(eosio::chain::global_property_object, eosio::chain::global_property_multi_index) CHAINBASE_SET_INDEX_TYPE(eosio::chain::dynamic_global_property_object, eosio::chain::dynamic_global_property_multi_index) +CHAINBASE_SET_INDEX_TYPE(eosio::chain::global_property2_object, eosio::chain::global_property2_multi_index) FC_REFLECT(eosio::chain::dynamic_global_property_object, (global_action_sequence) @@ -84,3 +101,6 @@ FC_REFLECT(eosio::chain::dynamic_global_property_object, FC_REFLECT(eosio::chain::global_property_object, (proposed_schedule_block_num)(proposed_schedule)(configuration) ) +FC_REFLECT(eosio::chain::global_property2_object, + (cfg) + ) \ No newline at end of file diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index 21fbf216c43..f67fd858ee5 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -163,6 +163,7 @@ namespace eosio { namespace chain { index_double_object_type, index_long_double_object_type, global_property_object_type, + global_property2_object_type, dynamic_global_property_object_type, block_summary_object_type, transaction_object_type, diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index feb9efbef8a..91bf936ab7a 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -193,6 +193,21 @@ class privileged_api : public context_aware_api { }); } + void set_blacklist_packed(int64_t list, int64_t action, array_ptr packed_blockchain_blacklist, size_t datalen) + { + int64_t lstbegin = static_cast(blacklist_type::actor_blacklist_type); + int64_t lstend = static_cast(blacklist_type::list_type_count); + int64_t actbegin = static_cast(list_action_type::insert_type); + int64_t actend = static_cast(list_action_type::list_action_type_count); + EOS_ASSERT(list >= lstbegin && list < lstend, wasm_execution_error, "unkown blacklist type!"); + EOS_ASSERT(action >= actbegin && action < actend, wasm_execution_error, "unkown action type"); + + datastream ds(packed_blockchain_blacklist, datalen); + std::vector blacklist; + fc::raw::unpack(ds, blacklist); + + context.control.set_blacklist(list, action, blacklist); + } bool is_privileged( account_name n )const { return context.db.get( n ).privileged; } @@ -1700,6 +1715,7 @@ REGISTER_INTRINSICS(privileged_api, (set_proposed_producers, int64_t(int,int) ) (get_blockchain_parameters_packed, int(int, int) ) (set_blockchain_parameters_packed, void(int,int) ) + (set_blacklist_packed, void(int64_t,int64_t,int,int) ) (is_privileged, int(int64_t) ) (set_privileged, void(int64_t, int) ) );