Skip to content
This repository has been archived by the owner on Oct 4, 2019. It is now read-only.

Commit

Permalink
Merge pull request #1003 from GolosChain/1002-posts-window
Browse files Browse the repository at this point in the history
Implement window for posts. #1002
  • Loading branch information
afalaleev authored Nov 29, 2018
2 parents 751d18e + 197d328 commit 8b79ef7
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 103 deletions.
4 changes: 3 additions & 1 deletion libraries/api/account_api_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ account_api_object::account_api_object(const account_object& a, const golos::cha
last_owner_proved(a.last_owner_proved), last_active_proved(a.last_active_proved),
recovery_account(a.recovery_account), reset_account(a.reset_account),
last_account_recovery(a.last_account_recovery), comment_count(a.comment_count),
lifetime_vote_count(a.lifetime_vote_count), post_count(a.post_count), can_vote(a.can_vote),
lifetime_vote_count(a.lifetime_vote_count), post_count(a.post_count),
posts_capacity(a.posts_capacity), comments_capacity(a.comments_capacity), voting_capacity(a.voting_capacity),
can_vote(a.can_vote),
voting_power(a.voting_power), last_vote_time(a.last_vote_time),
balance(a.balance), savings_balance(a.savings_balance),
sbd_balance(a.sbd_balance), sbd_seconds(a.sbd_seconds),
Expand Down
2 changes: 2 additions & 0 deletions libraries/api/chain_api_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace golos { namespace api {
max_referral_term_sec = src.max_referral_term_sec;
min_referral_break_fee = src.min_referral_break_fee;
max_referral_break_fee = src.max_referral_break_fee;
posts_window = src.posts_window;
posts_per_window = src.posts_per_window;
comments_window = src.comments_window;
comments_per_window = src.comments_per_window;
votes_window = src.votes_window;
Expand Down
5 changes: 4 additions & 1 deletion libraries/api/include/golos/api/account_api_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ struct account_api_object {
uint32_t comment_count;
uint32_t lifetime_vote_count;
uint32_t post_count;
uint16_t posts_capacity;
uint16_t comments_capacity;
uint16_t voting_capacity;

bool can_vote;
uint16_t voting_power;
Expand Down Expand Up @@ -120,7 +123,7 @@ FC_REFLECT((golos::api::account_api_object),
(average_bandwidth)(average_market_bandwidth)(lifetime_bandwidth)(lifetime_market_bandwidth)
(last_bandwidth_update)(last_market_bandwidth_update)
(last_post)(last_root_post)(post_bandwidth)
(witness_votes)(reputation)
(witness_votes)(reputation)(posts_capacity)(comments_capacity)(voting_capacity)
(referrer_account)(referrer_interest_rate)(referral_end_date)(referral_break_fee))

#endif //GOLOS_ACCOUNT_API_OBJ_HPP
4 changes: 3 additions & 1 deletion libraries/api/include/golos/api/chain_api_properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace golos { namespace api {
fc::optional<asset> min_referral_break_fee;
fc::optional<asset> max_referral_break_fee;

fc::optional<uint16_t> posts_window;
fc::optional<uint16_t> posts_per_window;
fc::optional<uint16_t> comments_window;
fc::optional<uint16_t> comments_per_window;
fc::optional<uint16_t> votes_window;
Expand Down Expand Up @@ -54,7 +56,7 @@ FC_REFLECT(
(create_account_min_golos_fee)(create_account_min_delegation)
(create_account_delegation_time)(min_delegation)
(max_referral_interest_rate)(max_referral_term_sec)(min_referral_break_fee)(max_referral_break_fee)
(comments_window)(comments_per_window)(votes_window)(votes_per_window)(auction_window_size)
(posts_window)(posts_per_window)(comments_window)(comments_per_window)(votes_window)(votes_per_window)(auction_window_size)
(max_delegated_vesting_interest_rate)(custom_ops_bandwidth_multiplier)
(min_curation_percent)(max_curation_percent)(curation_reward_curve)
(allow_distribute_auction_reward)(allow_return_auction_reward_to_fund))
1 change: 1 addition & 0 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1926,6 +1926,7 @@ namespace golos { namespace chain {
calc_median(&chain_properties_19::max_referral_term_sec);
calc_median(&chain_properties_19::min_referral_break_fee);
calc_median(&chain_properties_19::max_referral_break_fee);
calc_median_battery(&chain_properties_19::posts_window, &chain_properties_19::posts_per_window);
calc_median_battery(&chain_properties_19::comments_window, &chain_properties_19::comments_per_window);
calc_median_battery(&chain_properties_19::votes_window, &chain_properties_19::votes_per_window);
calc_median(&chain_properties_19::max_delegated_vesting_interest_rate);
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/hardfork.d/0_19.hf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define STEEMIT_HARDFORK_0_19 19
#define STEEMIT_HARDFORK_0_19__898 (STEEMIT_HARDFORK_0_19) // Add votable auction window size
#define STEEMIT_HARDFORK_0_19__295 (STEEMIT_HARDFORK_0_19) // Referral program implemented
#define STEEMIT_HARDFORK_0_19__533 (STEEMIT_HARDFORK_0_19) // Leaky algorithm for comment and vote bandwidth
#define STEEMIT_HARDFORK_0_19__533_1002 (STEEMIT_HARDFORK_0_19) // Leaky algorithm for comment, vote and post bandwidth
#define STEEMIT_HARDFORK_0_19__756 (STEEMIT_HARDFORK_0_19) // Vesting shares delegation with interest
#define STEEMIT_HARDFORK_0_19__971 (STEEMIT_HARDFORK_0_19) // Withdraw vests to another account resests on account recover
#define STEEMIT_HARDFORK_0_19__924 (STEEMIT_HARDFORK_0_19) // Bandwidth for custom_json operations
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/golos/chain/account_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class account_object

bool can_vote = true;
uint16_t voting_power = STEEMIT_100_PERCENT; ///< current voting power of this account, it falls after every vote
uint16_t posts_capacity = STEEMIT_POSTS_WINDOW;
uint16_t comments_capacity = STEEMIT_COMMENTS_WINDOW;
uint16_t voting_capacity = STEEMIT_VOTES_WINDOW;
time_point_sec last_vote_time; ///< used to increase the voting power of this account the longer it goes without voting.
Expand Down
229 changes: 147 additions & 82 deletions libraries/chain/steem_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,150 @@ namespace golos { namespace chain {
}
}

struct comment_bandwidth final {
database& db;
const time_point_sec& now;
const comment_operation& op;
const chain_properties& mprops;
const account_object& auth;
mutable const account_bandwidth_object* band = nullptr;

uint16_t calc_reward_weight() const {
band = db.find<account_bandwidth_object, by_account_bandwidth_type>(
std::make_tuple(op.author, bandwidth_type::post));

if (nullptr == band) {
band = &db.create<account_bandwidth_object>([&](account_bandwidth_object &b) {
b.account = op.author;
b.type = bandwidth_type::post;
});
}

if (db.has_hardfork(STEEMIT_HARDFORK_0_19__533_1002)) {
hf19();
} else if (db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
hf12();
} else if (db.has_hardfork(STEEMIT_HARDFORK_0_6__113)) {
hf6();
} else {
hf0();
}

return calculate();
}

private:
uint16_t calculate() const {
uint16_t reward_weight = STEEMIT_100_PERCENT;

if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
auto pb = band->average_bandwidth;

if (db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
auto post_delta_time = std::min(
now.sec_since_epoch() - band->last_bandwidth_update.sec_since_epoch(),
STEEMIT_POST_AVERAGE_WINDOW);

auto old_weight =
(pb * (STEEMIT_POST_AVERAGE_WINDOW - post_delta_time)) /
STEEMIT_POST_AVERAGE_WINDOW;

pb = (old_weight + STEEMIT_100_PERCENT);

reward_weight = uint16_t(std::min(
(STEEMIT_POST_WEIGHT_CONSTANT * STEEMIT_100_PERCENT) / (pb.value * pb.value),
uint64_t(STEEMIT_100_PERCENT)));
}

db.modify(*band, [&](account_bandwidth_object &b) {
b.last_bandwidth_update = now;
b.average_bandwidth = pb;
});
}

return reward_weight;
}

void hf19() const {
auto elapsed_seconds = (now - auth.last_post).to_seconds();

if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
auto consumption = mprops.posts_window / mprops.posts_per_window;

auto regenerated_capacity = std::min(
uint32_t(mprops.posts_window),
uint32_t(elapsed_seconds));

auto current_capacity = std::min(
uint16_t(auth.posts_capacity + regenerated_capacity),
mprops.posts_window);

GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
bandwidth_exception::post_bandwidth,
"You may only post ${posts_per_window} times in ${posts_window} seconds.",
("posts_per_window", mprops.posts_per_window)
("posts_window", mprops.posts_window));


db.modify(auth, [&](account_object& a) {
a.posts_capacity = current_capacity - consumption;
});

} else {
auto consumption = mprops.comments_window / mprops.comments_per_window;

auto regenerated_capacity = std::min(
uint32_t(mprops.comments_window),
uint32_t(elapsed_seconds));

auto current_capacity = std::min(
uint16_t(auth.comments_capacity + regenerated_capacity),
mprops.comments_window);

GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
bandwidth_exception::comment_bandwidth,
"You may only comment ${comments_per_window} times in ${comments_window} seconds.",
("comments_per_window", mprops.comments_per_window)
("comments_window", mprops.comments_window));

db.modify(auth, [&](account_object& a) {
a.comments_capacity = current_capacity - consumption;
});
}
}

void hf12() const {
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
bandwidth_exception::post_bandwidth,
"You may only post once every 5 minutes.");
} else {
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
golos::bandwidth_exception::comment_bandwidth,
"You may only comment once every 20 seconds.");
}
}

void hf6() const {
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
bandwidth_exception::post_bandwidth,
"You may only post once every 5 minutes.");
} else {
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
bandwidth_exception::comment_bandwidth,
"You may only comment once every 20 seconds.");
}
}

void hf0() const {
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + 60,
bandwidth_exception::post_bandwidth,
"You may only post once per minute.");
}

}; // struct check_comment_bandwidth

void comment_evaluator::do_apply(const comment_operation &o) {
try {
if (_db.is_producing() ||
Expand Down Expand Up @@ -667,86 +811,7 @@ namespace golos { namespace chain {
"The parent comment has disabled replies.");
}

auto band = _db.find<account_bandwidth_object, by_account_bandwidth_type>(std::make_tuple(o.author, bandwidth_type::post));
if (band == nullptr) {
band = &_db.create<account_bandwidth_object>([&](account_bandwidth_object &b) {
b.account = o.author;
b.type = bandwidth_type::post;
});
}

auto elapsed_seconds = (now - auth.last_post).to_seconds();

if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533)) {
auto consumption = mprops.comments_window / mprops.comments_per_window;

auto regenerated_capacity = std::min(uint32_t(mprops.comments_window), uint32_t(elapsed_seconds));
auto current_capacity = std::min(uint16_t(auth.comments_capacity + regenerated_capacity), mprops.comments_window);

if (o.parent_author == STEEMIT_ROOT_POST_PARENT) {
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
bandwidth_exception::post_bandwidth,
"You may only post once every 5 minutes.");
} else {
GOLOS_CHECK_BANDWIDTH(current_capacity, consumption,
bandwidth_exception::comment_bandwidth,
"You may only comment ${comments_per_window} times in ${comments_window} seconds.",
("comments_per_window", mprops.comments_per_window)("comments_window", mprops.comments_window));
}

db().modify(auth, [&](account_object &a) {
a.comments_capacity = current_capacity - consumption;
});
} else if (_db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
if (o.parent_author == STEEMIT_ROOT_POST_PARENT)
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
bandwidth_exception::post_bandwidth,
"You may only post once every 5 minutes.");
else
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
golos::bandwidth_exception::comment_bandwidth,
"You may only comment once every 20 seconds.");
} else if (_db.has_hardfork(STEEMIT_HARDFORK_0_6__113)) {
if (o.parent_author == STEEMIT_ROOT_POST_PARENT)
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
bandwidth_exception::post_bandwidth,
"You may only post once every 5 minutes.");
else
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
bandwidth_exception::comment_bandwidth,
"You may only comment once every 20 seconds.");
} else {
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + 60,
bandwidth_exception::post_bandwidth,
"You may only post once per minute.");
}

uint16_t reward_weight = STEEMIT_100_PERCENT;

if (o.parent_author == STEEMIT_ROOT_POST_PARENT) {
auto post_bandwidth = band->average_bandwidth;

if (_db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
auto post_delta_time = std::min(
now.sec_since_epoch() -
band->last_bandwidth_update.sec_since_epoch(), STEEMIT_POST_AVERAGE_WINDOW);
auto old_weight = (post_bandwidth *
(STEEMIT_POST_AVERAGE_WINDOW -
post_delta_time)) /
STEEMIT_POST_AVERAGE_WINDOW;
post_bandwidth = (old_weight + STEEMIT_100_PERCENT);
reward_weight = uint16_t(std::min(
(STEEMIT_POST_WEIGHT_CONSTANT *
STEEMIT_100_PERCENT) /
(post_bandwidth.value *
post_bandwidth.value), uint64_t(STEEMIT_100_PERCENT)));
}

_db.modify(*band, [&](account_bandwidth_object &b) {
b.last_bandwidth_update = now;
b.average_bandwidth = post_bandwidth;
});
}
uint16_t reward_weight = comment_bandwidth{_db, now, o, mprops, auth}.calc_reward_weight();

db().modify(auth, [&](account_object &a) {
a.last_post = now;
Expand Down Expand Up @@ -1378,13 +1443,13 @@ namespace golos { namespace chain {

auto elapsed_seconds = (_db.head_block_time() - voter.last_vote_time).to_seconds();

if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533)) {
if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533_1002)) {
auto consumption = mprops.votes_window / mprops.votes_per_window;

auto regenerated_capacity = std::min(uint32_t(mprops.votes_window), uint32_t(elapsed_seconds));
auto current_capacity = std::min(uint16_t(voter.voting_capacity + regenerated_capacity), mprops.votes_window);

GOLOS_CHECK_BANDWIDTH(current_capacity, consumption,
GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
bandwidth_exception::vote_bandwidth,
"Can only vote ${votes_per_window} times in ${votes_window} seconds.",
("votes_per_window", mprops.votes_per_window)("votes_window", mprops.votes_window));
Expand Down
Loading

0 comments on commit 8b79ef7

Please sign in to comment.