Skip to content

Commit

Permalink
feat: add option to change rewards distribution frequency with hardfork
Browse files Browse the repository at this point in the history
  • Loading branch information
kstdl committed May 11, 2023
1 parent 363dc8e commit 184a7a2
Show file tree
Hide file tree
Showing 18 changed files with 350 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@
"7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0x1027e72f1f12813088000000",
"ee1326fbf7d9322e5ea02c6fe5eb63535fceccd1": "0x52b7d2dcc80cd2e4000000"
},
"hardforks": {
"rewards_distribution_frequency": {
}
},
"gas_price": {
"blocks": 200,
"percentile": 60,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@
}
]
},
"hardforks": {
"rewards_distribution_frequency": {
}
},
"initial_balances": {
"723304d1357a2334fcf902aa3d232f5139080a1b": "0xd53323b7ca3737afbb45000",
"b0800c7af0a6aec0ff8dbe01708bd8e300c6305b": "0x208b1d135e4a8000",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,10 @@
"a903715b57d3bf62e098a6a643c6924d9bdacec4": "0x170a0f5040e50400000",
"5bd47fef8e8dcb6677c2957ecd78b8232354f145": "0x191cf61eb2bec223400"
},
"hardforks": {
"rewards_distribution_frequency": {
}
},
"gas_price": {
"blocks": 200,
"percentile": 60,
Expand Down
4 changes: 2 additions & 2 deletions libraries/config/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ set(HEADERS
include/config/dag_config.hpp
include/config/pbft_config.hpp
include/config/state_config.hpp
# include/config/hardfork.hpp
include/config/hardfork.hpp
)

set(SOURCES
Expand All @@ -18,7 +18,7 @@ set(SOURCES
src/dag_config.cpp
src/pbft_config.cpp
src/state_config.cpp
# src/hardfork.cpp
src/hardfork.cpp
)

# Configure file with version
Expand Down
13 changes: 12 additions & 1 deletion libraries/config/include/config/hardfork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@
#include "common/encoding_rlp.hpp"

struct Hardforks {
uint64_t fix_genesis_fork_block = 0;
/*
* @brief key is block number at which change is applied and value is new distribution interval.
* Default distribution frequency is every block
* To change rewards distribution frequency we should add a new element in map below.
* For example {{101, 20}, {201, 10}} means:
* 1. for blocks [1,100] we are distributing rewards every block
* 2. for blocks [101, 200] rewards are distributed every 20 block. On blocks 120, 140, etc.
* 3. for blocks after 201 rewards are distributed every 10 block. On blocks 210, 220, etc.
*/
using RewardsDistributionMap = std::map<uint64_t, uint32_t>;
RewardsDistributionMap rewards_distribution_frequency;

HAS_RLP_FIELDS
};

Expand Down
4 changes: 2 additions & 2 deletions libraries/config/include/config/state_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "common/encoding_rlp.hpp"
#include "common/types.hpp"
#include "common/vrf_wrapper.hpp"
// #include "config/hardfork.hpp"
#include "config/hardfork.hpp"

namespace taraxa::state_api {

Expand Down Expand Up @@ -61,7 +61,7 @@ struct Config {
EVMChainConfig evm_chain_config;
BalanceMap initial_balances;
DPOSConfig dpos;
// Hardforks hardforks;
Hardforks hardforks;

HAS_RLP_FIELDS
};
Expand Down
17 changes: 13 additions & 4 deletions libraries/config/src/hardfork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

Json::Value enc_json(const Hardforks& obj) {
Json::Value json(Json::objectValue);
json["fix_genesis_fork_block"] = dev::toJS(obj.fix_genesis_fork_block);

auto& rewards = json["rewards_distribution_frequency"];
rewards = Json::objectValue;
for (auto i = obj.rewards_distribution_frequency.begin(); i != obj.rewards_distribution_frequency.end(); ++i) {
rewards[std::to_string(i->first)] = i->second;
}
return json;
}

void dec_json(const Json::Value& json, Hardforks& obj) {
if (auto const& e = json["fix_genesis_fork_block"]) {
obj.fix_genesis_fork_block = dev::getUInt(e);
if (const auto& e = json["rewards_distribution_frequency"]) {
assert(e.isObject());

for (auto itr = e.begin(); itr != e.end(); ++itr) {
obj.rewards_distribution_frequency[itr.key().asUInt64()] = itr->asUInt64();
}
}
}

RLP_FIELDS_DEFINE(Hardforks, fix_genesis_fork_block)
RLP_FIELDS_DEFINE(Hardforks, rewards_distribution_frequency)
4 changes: 2 additions & 2 deletions libraries/config/src/state_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ void dec_json(const Json::Value& /*json*/, uint64_t chain_id, EVMChainConfig& ob
void append_json(Json::Value& json, const Config& obj) {
json["evm_chain_config"] = enc_json(obj.evm_chain_config);
json["initial_balances"] = enc_json(obj.initial_balances);
// json["hardforks"] = enc_json(obj.hardforks);
json["hardforks"] = enc_json(obj.hardforks);
json["dpos"] = enc_json(obj.dpos);
}

void dec_json(const Json::Value& json, Config& obj) {
dec_json(json["evm_chain_config"], json["chain_id"].asUInt(), obj.evm_chain_config);
dec_json(json["initial_balances"], obj.initial_balances);
// dec_json(json["hardforks"], obj.hardforks);
dec_json(json["hardforks"], obj.hardforks);
dec_json(json["dpos"], obj.dpos);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace taraxa::rewards {
*/
class BlockStats {
public:
// Needed for RLP
BlockStats() = default;
/**
* @brief setting block_author_, max_votes_weight_ and calls processStats function
*
Expand Down Expand Up @@ -58,7 +60,7 @@ class BlockStats {
*/
bool addVote(const std::shared_ptr<Vote>& vote);

private:
protected:
struct ValidatorStats {
// count of rewardable(with 1 or more unique transactions) DAG blocks produced by this validator
uint32_t dag_blocks_count_ = 0;
Expand Down
43 changes: 40 additions & 3 deletions libraries/core_libs/consensus/include/rewards/rewards_stats.hpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,54 @@
#include "config/hardfork.hpp"
#include "rewards/block_stats.hpp"
#include "storage/storage.hpp"

namespace taraxa::rewards {
/*
* @brief class that is managing rewards stats processing and hardforks(intervals changes)
* So intermediate blocks stats are stored in the vector in data(to restore on the node restart)
* and full list of interval stats is returned in the end of interval
*/
class Stats {
public:
Stats(uint32_t committee_size, std::function<uint64_t(EthBlockNumber)>&& dpos_eligible_total_vote_count);
Stats(uint32_t committee_size, const Hardforks::RewardsDistributionMap& rdm, std::shared_ptr<DB> db,
std::function<uint64_t(EthBlockNumber)>&& dpos_eligible_total_vote_count);

std::vector<BlockStats> getStats(const PeriodData& current_blk);
/*
* @brief processing passed block and returns stats that should be processed at this block
* @param current_blk block to process
* @return vector<BlockStats> that should be processed at current block
*/
std::vector<BlockStats> processStats(const PeriodData& current_blk);

private:
protected:
/*
* @brief load current interval stats from database
*/
void loadFromDb();
/*
* @brief returns rewards distribution frequency for specified period
*/
uint32_t getCurrentDistributionFrequency(uint64_t current_period) const;
/*
* @brief gets all needed data and makes(processes) BlocksStats
* @param current_blk block to process
* @return block statistics needed for rewards distribution
*/
BlockStats getBlockStats(const PeriodData& current_blk);
/*
* @brief saves stats to database to not lose this data in case of node restart
*/
void saveBlockStats(uint64_t number, const BlockStats& stats);
/*
* @brief called on start of new rewards interval. clears blocks_stats_ collection
* and removes all data saved in db column
*/
void clear();

const uint32_t kCommitteeSize;
const Hardforks::RewardsDistributionMap kRewardsDistributionFrequency;
std::shared_ptr<DB> db_;
const std::function<uint64_t(EthBlockNumber)> dpos_eligible_total_vote_count_;
std::vector<BlockStats> blocks_stats_;
};
} // namespace taraxa::rewards
4 changes: 2 additions & 2 deletions libraries/core_libs/consensus/src/final_chain/final_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class FinalChainImpl final : public FinalChain {
kLightNode(config.is_light_node),
kLightNodeHistory(config.light_node_history),
kMaxLevelsPerPeriod(config.max_levels_per_period),
rewards_(config.genesis.pbft.committee_size,
rewards_(config.genesis.pbft.committee_size, config.genesis.state.hardforks.rewards_distribution_frequency, db_,
[this](EthBlockNumber n) { return dpos_eligible_total_vote_count(n); }),
block_headers_cache_(config.final_chain_cache_in_blocks,
[this](uint64_t blk) { return get_block_header(blk); }),
Expand Down Expand Up @@ -151,7 +151,7 @@ class FinalChainImpl final : public FinalChain {
std::shared_ptr<DagBlock>&& anchor) {
auto batch = db_->createWriteBatch();

auto rewards_stats = rewards_.getStats(new_blk);
auto rewards_stats = rewards_.processStats(new_blk);

block_applying_emitter_.emit(block_header()->number + 1);

Expand Down
80 changes: 57 additions & 23 deletions libraries/core_libs/consensus/src/rewards/rewards_stats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,41 @@
#include "storage/storage.hpp"

namespace taraxa::rewards {
Stats::Stats(uint32_t committee_size, std::function<uint64_t(EthBlockNumber)>&& dpos_eligible_total_vote_count)
: kCommitteeSize(committee_size), dpos_eligible_total_vote_count_(dpos_eligible_total_vote_count) {}

// std::vector<RewardsStats> processBlockHardfork(const PeriodData& current_blk, uint32_t interval) {
// const auto current = current_blk.pbft_blk->getPeriod();
// // skip for intermediate blocks
// if (current % interval != 0) {
// return {};
// }

// std::vector<RewardsStats> rewards_stats;
// rewards_stats.reserve(interval);
// // add rewards stats for (last_distribution_block, current_block)
// for (auto p = current - interval + 1; p < current; ++p) {
// auto blk = PeriodData(db_->getPeriodDataRaw(p));
// rewards_stats.emplace_back(get_block_rewards_stats(blk));
// }
// // add current block rewards stats
// rewards_stats.emplace_back(get_block_rewards_stats(current_blk));

// return rewards_stats;
// }
Stats::Stats(uint32_t committee_size, const Hardforks::RewardsDistributionMap& rdm, std::shared_ptr<DB> db,
std::function<uint64_t(EthBlockNumber)>&& dpos_eligible_total_vote_count)
: kCommitteeSize(committee_size),
kRewardsDistributionFrequency(rdm),
db_(std::move(db)),
dpos_eligible_total_vote_count_(dpos_eligible_total_vote_count) {
loadFromDb();
}

void Stats::loadFromDb() {
auto i = db_->getColumnIterator(DB::Columns::block_rewards_stats);
for (i->SeekToFirst(); i->Valid(); i->Next()) {
blocks_stats_.push_back(util::rlp_dec<BlockStats>(dev::RLP(i->value().ToString())));
}
}

void Stats::saveBlockStats(uint64_t period, const BlockStats& stats) {
dev::RLPStream encoding;
stats.rlp(encoding);

db_->insert(DB::Columns::block_rewards_stats, period, encoding.out());
}

uint32_t Stats::getCurrentDistributionFrequency(uint64_t current_block) const {
auto itr = kRewardsDistributionFrequency.upper_bound(current_block);
if (kRewardsDistributionFrequency.empty() || itr == kRewardsDistributionFrequency.begin()) {
return 1;
}
return (--itr)->second;
}

void Stats::clear() {
blocks_stats_.clear();
db_->deleteColumnData(DB::Columns::block_rewards_stats);
}

BlockStats Stats::getBlockStats(const PeriodData& blk) {
uint64_t dpos_vote_count = kCommitteeSize;
Expand All @@ -37,5 +50,26 @@ BlockStats Stats::getBlockStats(const PeriodData& blk) {
return BlockStats{blk, dpos_vote_count, kCommitteeSize};
}

std::vector<BlockStats> Stats::getStats(const PeriodData& current_blk) { return {getBlockStats(current_blk)}; }
std::vector<BlockStats> Stats::processStats(const PeriodData& current_blk) {
const auto current_period = current_blk.pbft_blk->getPeriod();
const auto frequency = getCurrentDistributionFrequency(current_period);

// Distribute rewards every block
if (frequency == 1) {
return {getBlockStats(current_blk)};
}

blocks_stats_.push_back(getBlockStats(current_blk));
// Blocks between distribution. Process and save for future processing
if (current_period % frequency != 0) {
// Save to db, so in case of restart data could be just loaded for the period
saveBlockStats(current_period, *blocks_stats_.rbegin());
return {};
}

std::vector<BlockStats> res(std::move(blocks_stats_));
clear();
return res;
}

} // namespace taraxa::rewards
3 changes: 3 additions & 0 deletions libraries/core_libs/storage/include/storage/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ class DbStorage : public std::enable_shared_from_this<DbStorage> {
COLUMN(final_chain_log_blooms_index);
COLUMN_W_COMP(sortition_params_change, getIntComparator<PbftPeriod>());

COLUMN_W_COMP(block_rewards_stats, getIntComparator<uint64_t>());

#undef COLUMN
#undef COLUMN_W_COMP
};
Expand Down Expand Up @@ -177,6 +179,7 @@ class DbStorage : public std::enable_shared_from_this<DbStorage> {
void disableSnapshots();
void enableSnapshots();
void updateDbVersions();
void deleteColumnData(const Column& c);

uint32_t getMajorVersion() const;
std::unique_ptr<rocksdb::Iterator> getColumnIterator(const Column& c);
Expand Down
10 changes: 10 additions & 0 deletions libraries/core_libs/storage/src/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ void DbStorage::updateDbVersions() {
saveStatusField(StatusDbField::DbMinorVersion, TARAXA_DB_MINOR_VERSION);
}

void DbStorage::deleteColumnData(const Column& c) {
checkStatus(db_->DropColumnFamily(handle(c)));

auto options = rocksdb::ColumnFamilyOptions();
if (c.comparator_) {
options.comparator = c.comparator_;
}
checkStatus(db_->CreateColumnFamily(options, c.name(), &handles_[c.ordinal_]));
}

void DbStorage::rebuildColumns(const rocksdb::Options& options) {
std::unique_ptr<rocksdb::DB> db;
std::vector<std::string> column_families;
Expand Down
3 changes: 3 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ add_executable(vote_test vote_test.cpp)
target_link_libraries(vote_test test_util)
add_test(vote_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/vote_test)

add_executable(rewards_stats_test rewards_stats_test.cpp)
target_link_libraries(rewards_stats_test test_util)
add_test(rewards_stats_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rewards_stats_test)

add_executable(tarcap_threadpool_test tarcap_threadpool_test.cpp)
target_link_libraries(tarcap_threadpool_test test_util)
Expand Down
Loading

0 comments on commit 184a7a2

Please sign in to comment.