Skip to content

Commit

Permalink
feat(hardfork): fix issues including dpos contract config updation. a…
Browse files Browse the repository at this point in the history
…dd coins_per_vote field to the config
  • Loading branch information
kstdl committed Jan 18, 2022
1 parent 269dedc commit 0f8a367
Show file tree
Hide file tree
Showing 23 changed files with 99 additions and 81 deletions.
2 changes: 1 addition & 1 deletion libraries/cli/include/cli/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Config {
// Retrieves loaded node configuration
FullNodeConfig getNodeConfiguration();

static void addNewHardforks(Json::Value& config);
static void addNewHardforks(Json::Value& config, const Json::Value& default_config);

enum class NetworkIdType { Mainnet = 1, Testnet, Devnet };
static constexpr NetworkIdType DEFAULT_NETWORK_ID = NetworkIdType::Mainnet;
Expand Down
1 change: 1 addition & 0 deletions libraries/cli/include/cli/default_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const char *default_json = R"foo({
"deposit_delay": "0x5",
"withdrawal_delay": "0x5",
"eligibility_balance_threshold": "0x186A0",
"coins_per_vote": "0x186A0",
"genesis_state": {
"0x0274cfffea9fa850e54c93a23042f12a87358a82": {
"0x1f8333245650a19a0683891b7afe7787a3ce9f00": "0x989680",
Expand Down
1 change: 1 addition & 0 deletions libraries/cli/include/cli/devnet_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const char *devnet_json = R"foo({
"deposit_delay": "0x5",
"withdrawal_delay": "0x5",
"eligibility_balance_threshold": "0xf4240",
"coins_per_vote": "0xf4240",
"genesis_state": {
"0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": {
"0x780fe8b2226cf212c55635de399ee4c2a860810c": "0xf4240",
Expand Down
1 change: 1 addition & 0 deletions libraries/cli/include/cli/testnet_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const char *testnet_json = R"foo({
"deposit_delay": "0x5",
"withdrawal_delay": "0x5",
"eligibility_balance_threshold": "0xf4240",
"coins_per_vote": "0xf4240",
"genesis_state": {
"0x6c05d6e367a8c798308efbf4cefc1a18921a6f89": {
"0x18551e353aa65bc0ffbdf9d93b7ad4a8fe29cf95": "0xf4240",
Expand Down
21 changes: 13 additions & 8 deletions libraries/cli/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,15 @@ Config::Config(int argc, const char* argv[]) {
Tools::writeJsonToFile(wallet, wallet_json);
};

network_id = dev::getUInt(config_json["chain_config"]["chain_id"]);
auto default_config_json = Tools::generateConfig((Config::NetworkIdType)network_id);
// override hardforks data with one from default json
addNewHardforks(config_json);
addNewHardforks(config_json, default_config_json);
// add coins_per_vote field if it is missing in the config
if (config_json["chain_config"]["final_chain"]["state"]["dpos"]["coins_per_vote"].isNull()) {
config_json["chain_config"]["final_chain"]["state"]["dpos"]["coins_per_vote"] =
default_config_json["chain_config"]["final_chain"]["state"]["dpos"]["coins_per_vote"];
}
override();

// Override config values with values from CLI
Expand Down Expand Up @@ -223,15 +230,13 @@ bool Config::nodeConfigured() { return node_configured_; }

FullNodeConfig Config::getNodeConfiguration() { return node_config_; }

void Config::addNewHardforks(Json::Value& config) {
void Config::addNewHardforks(Json::Value& config, const Json::Value& default_config) {
// network_id is exactly the same thing as chain_id. So get it from config
auto network_id = Config::NetworkIdType(dev::getUInt(config["chain_config"]["chain_id"]));
auto network_config = Tools::generateConfig(network_id);
auto& new_hardforks_json = network_config["chain_config"]["final_chain"]["state"]["hardforks"];
auto& new_hardforks_json = default_config["chain_config"]["final_chain"]["state"]["hardforks"];
auto& local_hardforks_json = config["chain_config"]["final_chain"]["state"]["hardforks"];
if (new_hardforks_json.isNull()) {
std::cout << "is null so override all" << std::endl;
new_hardforks_json = local_hardforks_json;

if (local_hardforks_json.isNull()) {
local_hardforks_json = new_hardforks_json;
}
for (auto itr = new_hardforks_json.begin(); itr != new_hardforks_json.end(); ++itr) {
auto& local = local_hardforks_json[itr.key().asString()];
Expand Down
1 change: 1 addition & 0 deletions libraries/common/include/common/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ GLOBAL_CONST(h64, EmptyNonce);
GLOBAL_CONST(u256, ZeroU256);

constexpr uint16_t kOnePercent = 100;
constexpr uint64_t kOneTara = 1e18;
} // namespace taraxa
1 change: 1 addition & 0 deletions libraries/config/include/config/state_api_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void dec_json(Json::Value const& json, BalanceMap& obj);

struct DPOSConfig {
u256 eligibility_balance_threshold;
u256 coins_per_vote;
EthBlockNumber deposit_delay = 0;
EthBlockNumber withdrawal_delay = 0;
std::unordered_map<addr_t, BalanceMap> genesis_state;
Expand Down
1 change: 1 addition & 0 deletions libraries/config/src/chain_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ decltype(ChainConfig::predefined_) const ChainConfig::predefined_([] {
cfg.final_chain.state.genesis_balances[root_node_addr] = 9007199254740991;
auto& dpos = cfg.final_chain.state.dpos.emplace();
dpos.eligibility_balance_threshold = 1000000000;
dpos.coins_per_vote = 1000000000;
dpos.genesis_state[root_node_addr][root_node_addr] = dpos.eligibility_balance_threshold;
// VDF config
cfg.sortition.vrf.threshold_upper = 0x8000;
Expand Down
5 changes: 4 additions & 1 deletion libraries/config/src/state_api_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Json::Value enc_json(DPOSConfig const& obj) {
json["eligibility_balance_threshold"] = dev::toJS(obj.eligibility_balance_threshold);
json["deposit_delay"] = dev::toJS(obj.deposit_delay);
json["withdrawal_delay"] = dev::toJS(obj.withdrawal_delay);
json["coins_per_vote"] = dev::toJS(obj.coins_per_vote);
auto& genesis_state = json["genesis_state"] = Json::Value(Json::objectValue);
for (auto const& [k, v] : obj.genesis_state) {
genesis_state[dev::toJS(k)] = enc_json(v);
Expand All @@ -82,6 +83,7 @@ void dec_json(Json::Value const& json, DPOSConfig& obj) {
obj.eligibility_balance_threshold = dev::jsToU256(json["eligibility_balance_threshold"].asString());
obj.deposit_delay = dev::jsToInt(json["deposit_delay"].asString());
obj.withdrawal_delay = dev::jsToInt(json["withdrawal_delay"].asString());
obj.coins_per_vote = dev::jsToInt(json["coins_per_vote"].asString());
auto const& genesis_state = json["genesis_state"];
for (auto const& k : genesis_state.getMemberNames()) {
dec_json(genesis_state[k], obj.genesis_state[addr_t(k)]);
Expand All @@ -103,7 +105,8 @@ void dec_json(Json::Value const& json, ExecutionOptions& obj) {
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(DPOSConfig, eligibility_balance_threshold, coins_per_vote, deposit_delay, withdrawal_delay,
genesis_state)
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class FinalChain {

virtual std::optional<state_api::Account> get_account(addr_t const& addr,
std::optional<EthBlockNumber> blk_n = {}) const = 0;
virtual u256 get_staking_balance(addr_t const& addr, std::optional<EthBlockNumber> blk_n = {}) const = 0;
virtual u256 get_account_storage(addr_t const& addr, u256 const& key,
std::optional<EthBlockNumber> blk_n = {}) const = 0;
virtual bytes get_code(addr_t const& addr, std::optional<EthBlockNumber> blk_n = {}) const = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class StateAPI {
uint64_t dpos_eligible_vote_count(EthBlockNumber blk_num, addr_t const& addr) const;

bool dpos_is_eligible(EthBlockNumber blk_num, addr_t const& addr) const;
u256 get_staking_balance(EthBlockNumber blk_num, addr_t const& addr) const;

DPOSQueryResult dpos_query(EthBlockNumber blk_num, DPOSQuery const& q) const;
static addr_t const& dpos_contract_addr();
struct DPOSTransactionPrototype {
Expand Down
4 changes: 4 additions & 0 deletions libraries/core_libs/consensus/src/final_chain/final_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ class FinalChainImpl final : public FinalChain {
return state_api_.get_account(last_if_absent(blk_n), addr);
}

virtual u256 get_staking_balance(addr_t const& addr, std::optional<EthBlockNumber> blk_n = {}) const override {
return state_api_.get_staking_balance(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);
}
Expand Down
4 changes: 4 additions & 0 deletions libraries/core_libs/consensus/src/final_chain/state_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ bool StateAPI::dpos_is_eligible(EthBlockNumber blk_num, addr_t const& addr) cons
return ret;
}

u256 StateAPI::get_staking_balance(EthBlockNumber blk_num, addr_t const& addr) const {
return c_method_args_rlp<u256, to_u256, taraxa_evm_state_api_dpos_get_staking_balance>(this_c_, blk_num, addr);
}

DPOSQueryResult StateAPI::dpos_query(EthBlockNumber blk_num, DPOSQuery const& q) const {
return c_method_args_rlp<DPOSQueryResult, from_rlp, taraxa_evm_state_api_dpos_query>(this_c_, blk_num, q);
}
Expand Down
2 changes: 1 addition & 1 deletion libraries/core_libs/network/rpc/Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ Json::Value Test::get_all_nodes() {
return res;
}

Json::Value Test::get_vote_weight(const Json::Value &param1) {
Json::Value Test::get_coins_per_vote(const Json::Value &param1) {
Json::Value res;
try {
if (auto node = full_node_.lock()) {
Expand Down
2 changes: 1 addition & 1 deletion libraries/core_libs/network/rpc/Test.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Test : public TestFace {
virtual Json::Value get_node_count() override;
virtual Json::Value get_all_peers() override;
virtual Json::Value get_all_nodes() override;
virtual Json::Value get_vote_weight(const Json::Value& param1) override;
virtual Json::Value get_coins_per_vote(const Json::Value& param1) override;
virtual Json::Value place_vote(const Json::Value& param1) override;
virtual Json::Value get_votes(const Json::Value& param1) override;
virtual Json::Value draw_graph(const Json::Value& param1) override;
Expand Down
2 changes: 1 addition & 1 deletion libraries/core_libs/network/rpc/Test.jsonrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"returns": {}
},
{
"name": "get_vote_weight",
"name": "get_coins_per_vote",
"params": [
{}
],
Expand Down
4 changes: 2 additions & 2 deletions libraries/core_libs/network/rpc/TestClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ class TestClient : public jsonrpc::Client {
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value get_vote_weight(const Json::Value& param1) throw(jsonrpc::JsonRpcException) {
Json::Value get_coins_per_vote(const Json::Value& param1) throw(jsonrpc::JsonRpcException) {
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("get_vote_weight", p);
Json::Value result = this->CallMethod("get_coins_per_vote", p);
if (result.isObject())
return result;
else
Expand Down
10 changes: 5 additions & 5 deletions libraries/core_libs/network/rpc/TestFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ class TestFace : public ServerInterface<TestFace> {
&taraxa::net::TestFace::get_all_peersI);
this->bindAndAddMethod(jsonrpc::Procedure("get_all_nodes", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, NULL),
&taraxa::net::TestFace::get_all_nodesI);
this->bindAndAddMethod(jsonrpc::Procedure("get_vote_weight", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT,
this->bindAndAddMethod(jsonrpc::Procedure("get_coins_per_vote", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT,
"param1", jsonrpc::JSON_OBJECT, NULL),
&taraxa::net::TestFace::get_vote_weightI);
&taraxa::net::TestFace::get_coins_per_voteI);
this->bindAndAddMethod(jsonrpc::Procedure("place_vote", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",
jsonrpc::JSON_OBJECT, NULL),
&taraxa::net::TestFace::place_voteI);
Expand Down Expand Up @@ -140,8 +140,8 @@ class TestFace : public ServerInterface<TestFace> {
(void)request;
response = this->get_all_nodes();
}
inline virtual void get_vote_weightI(const Json::Value &request, Json::Value &response) {
response = this->get_vote_weight(request[0u]);
inline virtual void get_coins_per_voteI(const Json::Value &request, Json::Value &response) {
response = this->get_coins_per_vote(request[0u]);
}
inline virtual void place_voteI(const Json::Value &request, Json::Value &response) {
response = this->place_vote(request[0u]);
Expand Down Expand Up @@ -192,7 +192,7 @@ class TestFace : public ServerInterface<TestFace> {
virtual Json::Value get_node_version() = 0;
virtual Json::Value get_all_peers() = 0;
virtual Json::Value get_all_nodes() = 0;
virtual Json::Value get_vote_weight(const Json::Value &param1) = 0;
virtual Json::Value get_coins_per_vote(const Json::Value &param1) = 0;
virtual Json::Value place_vote(const Json::Value &param1) = 0;
virtual Json::Value get_votes(const Json::Value &param1) = 0;
virtual Json::Value draw_graph(const Json::Value &param1) = 0;
Expand Down
12 changes: 10 additions & 2 deletions libraries/core_libs/node/src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,20 @@ void FullNode::start() {
// TODO: should have only common hardfork code calling hardfork executor
auto &state_conf = conf_.chain.final_chain.state;
if (state_conf.hardforks.fix_genesis_hardfork_block_num == block_num) {
std::cout << "APPLY CPP PART OF HARDFORK" << std::endl;
for (auto &e : state_conf.dpos->genesis_state) {
for (auto &b : e.second) {
b.second = b.second * u256(1e18) - b.second;
b.second = b.second * kOneTara;
}
}
for (auto &b : state_conf.genesis_balances) {
b.second = b.second * kOneTara;
}
// we are multiplying it by TARA precision
state_conf.dpos->eligibility_balance_threshold *= kOneTara;
// amount of stake per vote should be 10 times smaller than eligibility threshold
state_conf.dpos->coins_per_vote = state_conf.dpos->eligibility_balance_threshold;
state_conf.dpos->eligibility_balance_threshold *= 10;

final_chain_->update_state_config(state_conf);
}
});
Expand Down
17 changes: 0 additions & 17 deletions tests/final_chain_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,23 +307,6 @@ TEST_F(FinalChainTest, coin_transfers) {
});
}

TEST_F(FinalChainTest, hardfork_apply_test) {
cfg.state.genesis_balances[addr_t::random()] = 100000;
cfg.state.dpos = state_api::DPOSConfig();
cfg.state.dpos->eligibility_balance_threshold = 1000;
auto hardfork_block_num = cfg.state.hardforks.fix_genesis_hardfork_block_num = 10;
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({})
48 changes: 41 additions & 7 deletions tests/full_node_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ TEST_F(FullNodeTest, chain_config_json) {
"dpos": {
"deposit_delay": "0x0",
"eligibility_balance_threshold": "0x3b9aca00",
"coins_per_vote": "0x3b9aca00",
"genesis_state": {
"0xde2b1203d72d3549ee2f733b00b2789414c7cea5": {
"0xde2b1203d72d3549ee2f733b00b2789414c7cea5": "0x3b9aca00"
Expand Down Expand Up @@ -1536,24 +1537,42 @@ TEST_F(FullNodeTest, hardfork_override) {
Json::Value config = default_json;
auto &state_cfg = config["chain_config"]["final_chain"]["state"];
state_cfg["hardforks"].removeMember("fix_genesis_hardfork_block_num");

EXPECT_TRUE(state_cfg["hardforks"]["fix_genesis_hardfork_block_num"].isNull());
cli::Config::addNewHardforks(config);
cli::Config::addNewHardforks(config, default_json);
EXPECT_EQ(state_cfg["hardforks"], default_hardforks);

state_cfg.removeMember("hardforks");
EXPECT_TRUE(state_cfg["hardforks"].isNull());
cli::Config::addNewHardforks(config);

cli::Config::addNewHardforks(config, default_json);
EXPECT_EQ(state_cfg["hardforks"], default_hardforks);
}

TEST_F(FullNodeTest, fix_genesis_hardfork_block_num_is_zero) {
auto node_cfgs = make_node_cfgs(1);
auto &cfg = node_cfgs.front().chain.final_chain;
cfg.state.hardforks.fix_genesis_hardfork_block_num = 0;
auto node = launch_nodes(node_cfgs).front();
}

TEST_F(FullNodeTest, hardfork) {
auto node_cfgs = make_node_cfgs(1);
auto &cfg = node_cfgs.front().chain.final_chain;
cfg.state.hardforks.fix_genesis_hardfork_block_num = 2;
cfg.state.dpos->eligibility_balance_threshold = 100000;
cfg.state.dpos->coins_per_vote = cfg.state.dpos->eligibility_balance_threshold;
for (auto &gs : cfg.state.dpos->genesis_state) {
for (auto &b : gs.second) {
b.second = 1100000;
}
}
const auto init_votes_count = 11;

auto node = launch_nodes(node_cfgs).front();
bool hardfork_applied = false;
auto nonce = 0;
auto dummy_trx = [&nonce, node]() {
std::cout << "dummy trx" << std::endl;
Transaction dummy_trx(nonce++, 0, 0, 0, bytes(), node->getSecretKey(), node->getAddress());
// broadcast dummy transaction
node->getTransactionManager()->insertTransaction(dummy_trx);
Expand All @@ -1572,19 +1591,34 @@ TEST_F(FullNodeTest, hardfork) {
auto balance = node->getFinalChain()->get_account(b.first)->balance;
balances_before.emplace(b.first, balance);
}

EXPECT_EQ(1, node->getFinalChain()->dpos_eligible_count(0));
EXPECT_EQ(init_votes_count, node->getFinalChain()->dpos_eligible_total_vote_count(0));

wait({100s, 500ms}, [&](auto &ctx) {
if (!hardfork_applied) {
ctx.fail();
}
});

const auto mult = u256(1e18);
u256 dpos_genesis_sum = 0;
// Verify DPOS initial balances increasing
for (const auto &gs : node->getConfig().chain.final_chain.state.dpos->genesis_state) {
for (const auto &b : gs.second) {
EXPECT_EQ(b.second, node->getFinalChain()->get_staking_balance(b.first));
dpos_genesis_sum += b.second;
}
}

for (const auto &b : node->getConfig().chain.final_chain.state.genesis_balances) {
auto balance_after = node->getFinalChain()->get_account(b.first)->balance;
// correction for what was spent before the fork
balance_after += b.second - balances_before.at(b.first);
EXPECT_EQ(b.second * mult, balance_after);
auto res = b.second - dpos_genesis_sum;
EXPECT_EQ(res, balance_after);
}

auto block = node->getFinalChain()->last_block_number();
EXPECT_EQ(1, node->getFinalChain()->dpos_eligible_count(block));
EXPECT_EQ(2, node->getFinalChain()->dpos_eligible_total_vote_count(block));
}

} // namespace taraxa::core_tests
Expand Down
Loading

0 comments on commit 0f8a367

Please sign in to comment.