From 1f5f3863b63eff0cd6f5a7af8a4c61ca7f297609 Mon Sep 17 00:00:00 2001 From: Harry Wong Date: Mon, 13 May 2019 22:19:29 +0800 Subject: [PATCH] Store action versions in global object --- libraries/chain/controller.cpp | 24 ++++- .../chain/include/evt/chain/controller.hpp | 2 + .../include/evt/chain/execution_context.hpp | 14 ++- .../evt/chain/execution_context_impl.hpp | 94 ++++++++++++++----- .../evt/chain/global_property_object.hpp | 4 +- 5 files changed, 105 insertions(+), 33 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index e33646f59..18ecbff5e 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -195,7 +195,7 @@ struct controller_impl { , token_db_cache(token_db, cfg.db_config.object_cache_size) , conf(cfg) , chain_id(cfg.genesis.compute_chain_id()) - , exec_ctx() + , exec_ctx(s) , read_mode(cfg.read_mode) , system_api(contracts::evt_contract_abi(), cfg.max_serialization_time) { @@ -1532,6 +1532,28 @@ controller::set_chain_config(const chain_config& config) { }); } +void +controller::set_action_versions(vector vers) { + const auto& gpo = get_global_properties(); + my->db.modify(gpo, [&](auto& gp) { + gp.action_vers.clear(); + for(auto& av : vers) { + gp.action_vers.push_back(av); + } + }); +} + +void +controller::set_action_version(name action, int version) { + const auto& gpo = get_global_properties(); + my->db.modify(gpo, [&](auto& gp) { + gp.action_vers.clear(); + for(auto& av : vers) { + gp.action_vers.push_back(av); + } + }); +} + const producer_schedule_type& controller::active_producers() const { if(!(my->pending.has_value())) { diff --git a/libraries/chain/include/evt/chain/controller.hpp b/libraries/chain/include/evt/chain/controller.hpp index 7149e5e35..e148acb56 100644 --- a/libraries/chain/include/evt/chain/controller.hpp +++ b/libraries/chain/include/evt/chain/controller.hpp @@ -187,6 +187,8 @@ class controller { int64_t set_proposed_producers(vector producers); void set_chain_config(const chain_config&); + void set_action_versions(vector vers); + void set_action_version(name action, int version); bool light_validation_allowed(bool replay_opts_disabled_by_policy) const; bool skip_auth_check() const; diff --git a/libraries/chain/include/evt/chain/execution_context.hpp b/libraries/chain/include/evt/chain/execution_context.hpp index dd0f4cbf1..8a203e12b 100644 --- a/libraries/chain/include/evt/chain/execution_context.hpp +++ b/libraries/chain/include/evt/chain/execution_context.hpp @@ -14,6 +14,12 @@ namespace evt { namespace chain { struct action_ver { name act; int ver; +}; +using shared_action_vers = shared_vector; + +struct action_ver_type { + name act; + int ver; string type; }; @@ -27,10 +33,7 @@ class execution_context : boost::noncopyable { virtual int set_version_unsafe(name act, int ver) = 0; virtual int get_current_version(name act) const = 0; virtual int get_max_version(name act) const = 0; - virtual std::vector get_current_actions() const = 0; - -public: - void set_versions(const std::vector& acts); + virtual std::vector get_current_actions() const = 0; }; // helper method to add const lvalue reference to type object @@ -39,4 +42,5 @@ using add_clr_t = typename std::add_const: }} // namespace evt::chain -FC_REFLECT(evt::chain::action_ver, (act)(ver)(type)); \ No newline at end of file +FC_REFLECT(evt::chain::action_ver, (act)(ver)); +FC_REFLECT(evt::chain::action_ver_type, (act)(ver)(type)); diff --git a/libraries/chain/include/evt/chain/execution_context_impl.hpp b/libraries/chain/include/evt/chain/execution_context_impl.hpp index e855857d7..913994c48 100644 --- a/libraries/chain/include/evt/chain/execution_context_impl.hpp +++ b/libraries/chain/include/evt/chain/execution_context_impl.hpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -24,23 +25,61 @@ namespace evt { namespace chain { template class execution_context_impl : public execution_context { public: - execution_context_impl() - : curr_vers_() { + execution_context_impl(controller& chain) + : chain_(chain) { constexpr auto index_of = [](auto& act) { return hana::index_if(act_names_, hana::equal.to(hana::ulong_c)).value(); }; - auto act_types = hana::sort.by(hana::ordering([](auto& act) { return hana::int_c; }), act_types_); + auto act_types = hana::sort.by(hana::ordering([](auto& act) { return hana::int_c; }), act_types_); + auto& conf = chain.get_dynamic_global_properties(); + hana::for_each(act_types, [&](auto& act) { auto i = index_of(act); type_names_[i].emplace_back(decltype(+act)::type::get_type_name()); assert(type_names_[i].size() == decltype(+act)::type::get_version()); - curr_vers_[i] = 1; // ver starts from 1 }); act_names_arr_ = hana::unpack(act_names_, [](auto ...i) { return std::array{{i...}}; }); + + if(conf.action_vers.empty()) { + auto avs = std::vector(); + for(auto i = 0u; i < act_names_arr_.size(); i++) { + avs.emplace_back(action_ver { + .act = name(act_names_arr_[i]), + .ver = 1, // set version to 1 + .type = type_names_[i][0] + }); + } + chain.set_action_versions(avs); + } + else if(conf.action_vers.size() != act_names_arr_.size()) { + // added new actions + FC_ASSERT(conf.action_vers.size() < act_names_arr_.size()); + auto tmp = std::map(); // map name to ver + for(auto& av : conf.action_vers) { + tmp[av.name] = av.ver; + } + + auto avs = std::vector(); + avs.reserve(act_names_arr_.size()); + + for(auto i = 0u; i < act_names_arr_.size(); i++) { + auto it = tmp.find(act_names_arr_[i]); + auto ver = 1; + if(it != tmp.cend()) { + ver = it->second; + } + avs.emplace_back(action_ver { + .act = name(act_names_arr_[i]), + .ver = ver, + .type = type_names_[i][ver - 1] + }); + } + chain.set_action_versions(avs); + } } ~execution_context_impl() override {} @@ -66,26 +105,28 @@ class execution_context_impl : public execution_context { int set_version(name act, int newver) override { - auto actindex = index_of(act); - auto cver = curr_vers_[actindex]; - auto mver = type_names_[actindex].size(); + auto index = index_of(act); + auto& conf = chain.get_dynamic_global_properties(); + auto cver = conf.action_vers[index].ver; + auto mver = type_names_[index].size(); EVT_ASSERT2(newver > cver && newver <= (int)mver, action_version_exception, "New version should be in range ({},{}]", cver, mver); - auto old_ver = cver; - curr_vers_[actindex] = newver; + auto old_ver = cver; + chain_.set_action_version(act, newver); return old_ver; } int set_version_unsafe(name act, int newver) override { - auto actindex = index_of(act); - auto cver = curr_vers_[actindex]; - auto mver = type_names_[actindex].size() - 1; + auto index = index_of(act); + auto& conf = chain.get_dynamic_global_properties(); + auto cver = conf.action_vers[index].ver; + auto mver = type_names_[index].size() - 1; - auto old_ver = cver; - curr_vers_[actindex] = newver; + auto old_ver = cver; + chain_.set_action_version(act, newver); return old_ver; } @@ -115,7 +156,7 @@ class execution_context_impl : public execution_context { auto name = act_names_[i]; auto vers = hana::filter(act_types_, [&](auto& t) { return hana::equal(name, hana::ulong_c); }); - auto cver = curr_vers_[i]; + auto cver = get_curr_ver(i); static_assert(hana::length(vers)() > hana::size_c<0>(), "empty version actions!"); @@ -161,7 +202,7 @@ class execution_context_impl : public execution_context { auto name = act_names_[i.value()]; auto vers = hana::filter(act_types_, [&](auto& t) { return hana::equal(name, hana::ulong_c); }); - auto cver = curr_vers_[i.value()]; + auto cver = get_curr_ver(i.value()); static_assert(hana::length(vers)() > hana::size_c<0>(), "empty version actions!"); @@ -173,26 +214,27 @@ class execution_context_impl : public execution_context { }); } - std::vector + std::vector get_current_actions() const override { - auto acts = std::vector(); + auto acts = std::vector(); acts.reserve(act_names_arr_.size()); - for(auto i = 0u; i < act_names_arr_.size(); i++) { - acts.emplace_back(action_ver { - .act = name(act_names_arr_[i]), - .ver = curr_vers_[i], - .type = type_names_[i][curr_vers_[i]] + auto& conf = chain.get_dynamic_global_properties(); + for(auto& av : conf.action_vers) { + acts.push_back(action_ver_type { + .name = av.name, + .version = av.version, + .type = get_acttype_name(av.name) }); } - return acts; } private: int get_curr_ver(int index) const { - return curr_vers_[index]; + auto& conf = chain.get_dynamic_global_properties(); + return conf.action_vers[index].ver; } private: @@ -200,7 +242,7 @@ class execution_context_impl : public execution_context { static constexpr auto act_names_ = hana::sort(hana::unique(hana::transform(act_types_, [](auto& a) { return hana::ulong_c; }))); private: - std::array curr_vers_; + controller& chain_; std::array act_names_arr_; std::array, hana::length(act_names_)> type_names_; }; diff --git a/libraries/chain/include/evt/chain/global_property_object.hpp b/libraries/chain/include/evt/chain/global_property_object.hpp index 6d3700c6b..da678fc90 100644 --- a/libraries/chain/include/evt/chain/global_property_object.hpp +++ b/libraries/chain/include/evt/chain/global_property_object.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ class global_property_object optional proposed_schedule_block_num; shared_producer_schedule_type proposed_schedule; chain_config configuration; + shared_action_vers action_vers; }; /** @@ -64,4 +66,4 @@ CHAINBASE_SET_INDEX_TYPE(evt::chain::global_property_object, evt::chain::global_ CHAINBASE_SET_INDEX_TYPE(evt::chain::dynamic_global_property_object, evt::chain::dynamic_global_property_multi_index); FC_REFLECT(evt::chain::dynamic_global_property_object, (global_action_sequence)); -FC_REFLECT(evt::chain::global_property_object, (proposed_schedule_block_num)(proposed_schedule)(configuration)); +FC_REFLECT(evt::chain::global_property_object, (proposed_schedule_block_num)(proposed_schedule)(configuration)(action_vers));