From e2859665f92d46b2482dcd1c3b474fb12b243d0b Mon Sep 17 00:00:00 2001 From: Dmitry Kostenko Date: Thu, 13 Jan 2022 13:38:27 +0200 Subject: [PATCH] feat(hardfork): common hardfork logic. add functionality to update go part config --- libraries/cli/include/cli/default_config.hpp | 7 +++++-- libraries/cli/include/cli/devnet_config.hpp | 3 +++ libraries/cli/include/cli/testnet_config.hpp | 3 +++ libraries/cli/src/config.cpp | 8 +++++++ libraries/config/CMakeLists.txt | 2 ++ libraries/config/include/config/hardfork.hpp | 14 +++++++++++++ .../include/config/state_api_config.hpp | 2 ++ libraries/config/src/hardfork.cpp | 15 +++++++++++++ libraries/config/src/state_api_config.cpp | 4 +++- .../include/final_chain/final_chain.hpp | 2 ++ .../include/final_chain/state_api.hpp | 2 ++ .../consensus/src/final_chain/final_chain.cpp | 4 ++++ .../consensus/src/final_chain/state_api.cpp | 9 ++++++++ .../core_libs/node/include/node/node.hpp | 10 +++++++++ libraries/core_libs/node/src/node.cpp | 17 +++++++++++++++ submodules/taraxa-evm | 2 +- tests/final_chain_test.cpp | 20 ++++++++++++++++++ tests/state_api_test.cpp | 21 ++++++++++++------- 18 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 libraries/config/include/config/hardfork.hpp create mode 100644 libraries/config/src/hardfork.cpp diff --git a/libraries/cli/include/cli/default_config.hpp b/libraries/cli/include/cli/default_config.hpp index b1c8515dd3..f734e0f97f 100644 --- a/libraries/cli/include/cli/default_config.hpp +++ b/libraries/cli/include/cli/default_config.hpp @@ -202,8 +202,11 @@ const char *default_json = R"foo({ "disable_nonce_check": true }, "genesis_balances": { - "0274cfffea9fa850e54c93a23042f12a87358a82": "0x141e8d17", - "111f91441efc8c6c0edf6534970cc887e2fabaa8": "0x24048ce3d" + "0274cfffea9fa850e54c93a23042f12a87358a82": "0x141e8d17000000000000000000", + "111f91441efc8c6c0edf6534970cc887e2fabaa8": "0x24048ce3d000000000000000000" + }, + "hardforks": { + "enable_vrf_adjustion_block": "0x12c" } } }, diff --git a/libraries/cli/include/cli/devnet_config.hpp b/libraries/cli/include/cli/devnet_config.hpp index e048abe716..e2441aeaf9 100644 --- a/libraries/cli/include/cli/devnet_config.hpp +++ b/libraries/cli/include/cli/devnet_config.hpp @@ -126,6 +126,9 @@ const char *devnet_json = R"foo({ "genesis_balances": { "2cd4da7d3b345e022ca7e997c2bb3276a4d3d2e9": "0x1027e72f1f12813088000000", "7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0x1027e72f1f12813088000000" + }, + "hardforks": { + "enable_vrf_adjustion_block": "0x0" } } }, diff --git a/libraries/cli/include/cli/testnet_config.hpp b/libraries/cli/include/cli/testnet_config.hpp index b2027b0672..cf82032760 100644 --- a/libraries/cli/include/cli/testnet_config.hpp +++ b/libraries/cli/include/cli/testnet_config.hpp @@ -129,6 +129,9 @@ const char *testnet_json = R"foo({ "genesis_balances": { "6c05d6e367a8c798308efbf4cefc1a18921a6f89": "0x1027e72f1f12813088000000", "f4a52b8f6dc8ab046fec6ad02e77023c044342e4": "0x1027e72f1f12813088000000" + }, + "hardforks": { + "enable_vrf_adjustion_block": "0x0" } } }, diff --git a/libraries/cli/src/config.cpp b/libraries/cli/src/config.cpp index be35a5c352..44f179bf1e 100644 --- a/libraries/cli/src/config.cpp +++ b/libraries/cli/src/config.cpp @@ -178,6 +178,14 @@ Config::Config(int argc, const char* argv[]) { Tools::writeJsonToFile(wallet, wallet_json); } + // override hardforks data with one from default json + // TODO: make it only add new fields, but not override the old ones? + { + // network_id is exactly the same thing as chain_id. So get it from config + network_id = dev::getUInt(config_json["chain_config"]["chain_id"]); + auto network_config_json = Tools::generateConfig((Config::NetworkIdType)network_id); + config_json["chain_config"]["hardforks"] = network_config_json["chain_config"]["hardforks"]; + } // Load config node_config_ = FullNodeConfig(config_json, wallet_json); diff --git a/libraries/config/CMakeLists.txt b/libraries/config/CMakeLists.txt index 7748fefe0c..707556215c 100644 --- a/libraries/config/CMakeLists.txt +++ b/libraries/config/CMakeLists.txt @@ -5,6 +5,7 @@ set(HEADERS include/config/final_chain_config.hpp include/config/pbft_config.hpp include/config/state_api_config.hpp + include/config/hardfork.hpp ) set(SOURCES @@ -13,6 +14,7 @@ set(SOURCES src/chain_config.cpp src/final_chain_config.cpp src/state_api_config.cpp + src/hardfork.cpp ) # Configure file with version diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp new file mode 100644 index 0000000000..b869090242 --- /dev/null +++ b/libraries/config/include/config/hardfork.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "common/encoding_rlp.hpp" + +struct Hardforks { + uint64_t fix_genesis_hardfork_block_num = 0; + void processFixGenesisHardfork() const; + HAS_RLP_FIELDS +}; + +Json::Value enc_json(const Hardforks& obj); +void dec_json(const Json::Value& json, Hardforks& obj); \ No newline at end of file diff --git a/libraries/config/include/config/state_api_config.hpp b/libraries/config/include/config/state_api_config.hpp index a67c3a58ab..839ac4ffe0 100644 --- a/libraries/config/include/config/state_api_config.hpp +++ b/libraries/config/include/config/state_api_config.hpp @@ -5,6 +5,7 @@ #include "common/encoding_rlp.hpp" #include "common/types.hpp" +#include "config/hardfork.hpp" namespace taraxa::state_api { @@ -54,6 +55,7 @@ struct Config { ExecutionOptions execution_options; BalanceMap genesis_balances; std::optional dpos; + Hardforks hardforks; HAS_RLP_FIELDS diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp new file mode 100644 index 0000000000..ec8c94d0fd --- /dev/null +++ b/libraries/config/src/hardfork.cpp @@ -0,0 +1,15 @@ +#include "config/hardfork.hpp" + +Json::Value enc_json(const Hardforks& obj) { + Json::Value json(Json::objectValue); + json["fix_genesis_hardfork_block_num"] = dev::toJS(obj.fix_genesis_hardfork_block_num); + return json; +} + +void dec_json(const Json::Value& json, Hardforks& obj) { + if (auto const& e = json["fix_genesis_hardfork_block_num"]) { + obj.fix_genesis_hardfork_block_num = dev::getUInt(e); + } +} + +RLP_FIELDS_DEFINE(Hardforks, fix_genesis_hardfork_block_num) diff --git a/libraries/config/src/state_api_config.cpp b/libraries/config/src/state_api_config.cpp index 9b4f1ea8a0..e50dad3560 100644 --- a/libraries/config/src/state_api_config.cpp +++ b/libraries/config/src/state_api_config.cpp @@ -34,6 +34,7 @@ Json::Value enc_json(Config const& obj) { json["execution_options"] = enc_json(obj.execution_options); json["disable_block_rewards"] = obj.disable_block_rewards; json["genesis_balances"] = enc_json(obj.genesis_balances); + json["hardforks"] = enc_json(obj.hardforks); if (obj.dpos) { json["dpos"] = enc_json(*obj.dpos); } @@ -45,6 +46,7 @@ void dec_json(Json::Value const& json, Config& obj) { dec_json(json["execution_options"], obj.execution_options); obj.disable_block_rewards = json["disable_block_rewards"].asBool(); dec_json(json["genesis_balances"], obj.genesis_balances); + dec_json(json["hardforks"], obj.hardforks); if (auto const& dpos = json["dpos"]; !dpos.isNull()) { dec_json(dpos, obj.dpos.emplace()); } @@ -102,7 +104,7 @@ RLP_FIELDS_DEFINE(ExecutionOptions, disable_nonce_check, disable_gas_fee) RLP_FIELDS_DEFINE(ETHChainConfig, homestead_block, dao_fork_block, eip_150_block, eip_158_block, byzantium_block, constantinople_block, petersburg_block) RLP_FIELDS_DEFINE(DPOSConfig, eligibility_balance_threshold, deposit_delay, withdrawal_delay, genesis_state) -RLP_FIELDS_DEFINE(Config, eth_chain_config, disable_block_rewards, execution_options, genesis_balances, dpos) +RLP_FIELDS_DEFINE(Config, eth_chain_config, disable_block_rewards, execution_options, genesis_balances, dpos, hardforks) RLP_FIELDS_DEFINE(Opts, expected_max_trx_per_block, max_trie_full_node_levels_to_cache) RLP_FIELDS_DEFINE(OptsDB, db_path, disable_most_recent_trie_value_views) diff --git a/libraries/core_libs/consensus/include/final_chain/final_chain.hpp b/libraries/core_libs/consensus/include/final_chain/final_chain.hpp index bbce82a067..9d5c3da331 100644 --- a/libraries/core_libs/consensus/include/final_chain/final_chain.hpp +++ b/libraries/core_libs/consensus/include/final_chain/final_chain.hpp @@ -39,6 +39,8 @@ class FinalChain { virtual size_t count() const = 0; virtual h256 get(size_t i) const = 0; }; + + virtual void update_state_config(const state_api::Config& new_config) const = 0; virtual std::shared_ptr transaction_hashes(std::optional n = {}) const = 0; virtual Transactions transactions(std::optional n = {}) const = 0; virtual std::optional transaction_location(h256 const& trx_hash) const = 0; diff --git a/libraries/core_libs/consensus/include/final_chain/state_api.hpp b/libraries/core_libs/consensus/include/final_chain/state_api.hpp index 44eb64abaf..27b2986289 100644 --- a/libraries/core_libs/consensus/include/final_chain/state_api.hpp +++ b/libraries/core_libs/consensus/include/final_chain/state_api.hpp @@ -23,6 +23,8 @@ class StateAPI { OptsDB const& opts_db); ~StateAPI(); + void update_state_config(const Config& new_config) const; + Proof prove(EthBlockNumber blk_num, root_t const& state_root, addr_t const& addr, std::vector const& keys) const; std::optional get_account(EthBlockNumber blk_num, addr_t const& addr) const; diff --git a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp index 95303c2dfd..bbd176aab7 100644 --- a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp +++ b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp @@ -319,6 +319,10 @@ class FinalChainImpl final : public FinalChain { return state_api_.get_account(last_if_absent(blk_n), addr); } + void update_state_config(const state_api::Config& new_config) const override { + state_api_.update_state_config(new_config); + } + u256 get_account_storage(addr_t const& addr, u256 const& key, optional blk_n = {}) const override { return state_api_.get_account_storage(last_if_absent(blk_n), addr, key); } diff --git a/libraries/core_libs/consensus/src/final_chain/state_api.cpp b/libraries/core_libs/consensus/src/final_chain/state_api.cpp index ccf82ba637..4d1fff4780 100644 --- a/libraries/core_libs/consensus/src/final_chain/state_api.cpp +++ b/libraries/core_libs/consensus/src/final_chain/state_api.cpp @@ -133,6 +133,15 @@ StateAPI::~StateAPI() { err_h.check(); } +void StateAPI::update_state_config(const Config& new_config) const { + dev::RLPStream encoding; + util::rlp_tuple(encoding, new_config); + + ErrorHandler err_h; + taraxa_evm_state_api_update_state_config(this_c_, map_bytes(encoding.out()), err_h.cgo_part_); + err_h.check(); +} + Proof StateAPI::prove(EthBlockNumber blk_num, root_t const& state_root, addr_t const& addr, std::vector const& keys) const { return c_method_args_rlp(this_c_, blk_num, state_root, addr, keys); diff --git a/libraries/core_libs/node/include/node/node.hpp b/libraries/core_libs/node/include/node/node.hpp index c80bb3564f..b29a16df5d 100644 --- a/libraries/core_libs/node/include/node/node.hpp +++ b/libraries/core_libs/node/include/node/node.hpp @@ -118,4 +118,14 @@ class FullNode : public std::enable_shared_from_this { void rebuildDb(); }; +class HardforkExecutors { + using ForkExecutor = std::function; + + public: + void registerExecutor(uint64_t block, ForkExecutor exec); + + private: + std::map executors; +}; + } // namespace taraxa diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index 9a70574152..f95d360467 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -185,6 +185,23 @@ void FullNode::start() { } }, *rpc_thread_pool_); + + // Subscription to process hardforks + final_chain_->block_finalized_.subscribe([&](const std::shared_ptr &res) { + // TODO: should have only common hardfork code calling hardfork executor + std::cout << "APPLY CPP PART OF HARDFORK" << std::endl; + const auto block_num = res->final_chain_blk->number; + auto &state_conf = conf_.chain.final_chain.state; + if (state_conf.hardforks.fix_genesis_hardfork_block_num == block_num) { + for (auto &e : state_conf.dpos->genesis_state) { + for (auto &b : e.second) { + b.second = b.second * u256(1e18) - b.second; + } + } + final_chain_->update_state_config(state_conf); + } + }); + trx_mgr_->transaction_accepted_.subscribe( [eth_json_rpc = as_weak(eth_json_rpc), ws = as_weak(jsonrpc_ws_)](auto const &trx_hash) { if (auto _eth_json_rpc = eth_json_rpc.lock()) { diff --git a/submodules/taraxa-evm b/submodules/taraxa-evm index 496b930da9..c26d6c9522 160000 --- a/submodules/taraxa-evm +++ b/submodules/taraxa-evm @@ -1 +1 @@ -Subproject commit 496b930da9d55b6d30a44fe620689d8e499408e3 +Subproject commit c26d6c95226cb1d014938d341963bad3787c5b59 diff --git a/tests/final_chain_test.cpp b/tests/final_chain_test.cpp index 09c3905f5a..99b9473d48 100644 --- a/tests/final_chain_test.cpp +++ b/tests/final_chain_test.cpp @@ -159,6 +159,8 @@ TEST_F(FinalChainTest, genesis_balances) { cfg.state.genesis_balances[addr_t::random()] = 1000; cfg.state.genesis_balances[addr_t::random()] = 100000; init(); + cfg.state.hardforks.fix_genesis_hardfork_block_num = 2222222; + SUT->update_state_config(cfg.state); } TEST_F(FinalChainTest, contract) { @@ -304,6 +306,24 @@ TEST_F(FinalChainTest, coin_transfers) { }); } +TEST_F(FinalChainTest, hardfork_apply_test) { + cfg.state.genesis_balances = {}; + cfg.state.dpos = nullopt; + auto hardfork_block_num = cfg.state.hardforks.fix_genesis_hardfork_block_num = 10; + + cfg.state.execution_options.disable_gas_fee = false; + init(); + for (size_t i = 0; i < hardfork_block_num; ++i) { + advance({}); + } + + const auto mult = u256(1e18); + for (const auto& b : cfg.state.genesis_balances) { + const auto balance_after = SUT->get_account(b.first)->balance; + EXPECT_EQ(b.second * mult, balance_after); + } +} + } // namespace taraxa::final_chain TARAXA_TEST_MAIN({}) diff --git a/tests/state_api_test.cpp b/tests/state_api_test.cpp index a2a30b3bd0..45eb23f2e0 100644 --- a/tests/state_api_test.cpp +++ b/tests/state_api_test.cpp @@ -226,17 +226,18 @@ TEST_F(StateAPITest, DISABLED_eth_mainnet_smoke) { } TEST_F(StateAPITest, increase_balance_hardfork_test) { - const auto hardfork_block_num = 12000; - Config chain_config; - chain_config.genesis_balances.emplace(addr_t(1111), 1000); - chain_config.genesis_balances.emplace(addr_t(1234), 10000); - + Config state_config; + state_config.genesis_balances.emplace(addr_t(1111), 1000); + state_config.genesis_balances.emplace(addr_t(1234), 10000); + state_config.dpos = DPOSConfig(); + state_config.dpos->eligibility_balance_threshold = 10; + auto hardfork_block_num = state_config.hardforks.fix_genesis_hardfork_block_num = 100; Opts opts; opts.expected_max_trx_per_block = 300; opts.max_trie_full_node_levels_to_cache = 4; StateAPI SUT([&](auto) { return h256(); }, // - chain_config, opts, + state_config, opts, { (data_dir / "state").string(), }); @@ -246,10 +247,16 @@ TEST_F(StateAPITest, increase_balance_hardfork_test) { } const auto mult = u256(1e18); - for (const auto& b : chain_config.genesis_balances) { + for (const auto& b : state_config.genesis_balances) { const auto balance_after = SUT.get_account(hardfork_block_num, b.first)->balance; EXPECT_EQ(b.second * mult, balance_after); } + // simulating cpp part hardfork + Config new_config = state_config; + { new_config.dpos->eligibility_balance_threshold *= 1000; } + EXPECT_EQ(SUT.dpos_eligible_total_vote_count(hardfork_block_num), 0); + SUT.update_state_config(new_config); + // EXPECT_EQ(SUT.dpos_eligible_total_vote_count(hardfork_block_num), new_config.dpos->eligibility_balance_threshold); } } // namespace taraxa::state_api