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

Commit 8b79ef7

Browse files
authored
Merge pull request #1003 from GolosChain/1002-posts-window
Implement window for posts. #1002
2 parents 751d18e + 197d328 commit 8b79ef7

15 files changed

Lines changed: 204 additions & 103 deletions

File tree

libraries/api/account_api_object.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ account_api_object::account_api_object(const account_object& a, const golos::cha
1616
last_owner_proved(a.last_owner_proved), last_active_proved(a.last_active_proved),
1717
recovery_account(a.recovery_account), reset_account(a.reset_account),
1818
last_account_recovery(a.last_account_recovery), comment_count(a.comment_count),
19-
lifetime_vote_count(a.lifetime_vote_count), post_count(a.post_count), can_vote(a.can_vote),
19+
lifetime_vote_count(a.lifetime_vote_count), post_count(a.post_count),
20+
posts_capacity(a.posts_capacity), comments_capacity(a.comments_capacity), voting_capacity(a.voting_capacity),
21+
can_vote(a.can_vote),
2022
voting_power(a.voting_power), last_vote_time(a.last_vote_time),
2123
balance(a.balance), savings_balance(a.savings_balance),
2224
sbd_balance(a.sbd_balance), sbd_seconds(a.sbd_seconds),

libraries/api/chain_api_properties.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ namespace golos { namespace api {
2020
max_referral_term_sec = src.max_referral_term_sec;
2121
min_referral_break_fee = src.min_referral_break_fee;
2222
max_referral_break_fee = src.max_referral_break_fee;
23+
posts_window = src.posts_window;
24+
posts_per_window = src.posts_per_window;
2325
comments_window = src.comments_window;
2426
comments_per_window = src.comments_per_window;
2527
votes_window = src.votes_window;

libraries/api/include/golos/api/account_api_object.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct account_api_object {
4646
uint32_t comment_count;
4747
uint32_t lifetime_vote_count;
4848
uint32_t post_count;
49+
uint16_t posts_capacity;
50+
uint16_t comments_capacity;
51+
uint16_t voting_capacity;
4952

5053
bool can_vote;
5154
uint16_t voting_power;
@@ -120,7 +123,7 @@ FC_REFLECT((golos::api::account_api_object),
120123
(average_bandwidth)(average_market_bandwidth)(lifetime_bandwidth)(lifetime_market_bandwidth)
121124
(last_bandwidth_update)(last_market_bandwidth_update)
122125
(last_post)(last_root_post)(post_bandwidth)
123-
(witness_votes)(reputation)
126+
(witness_votes)(reputation)(posts_capacity)(comments_capacity)(voting_capacity)
124127
(referrer_account)(referrer_interest_rate)(referral_end_date)(referral_break_fee))
125128

126129
#endif //GOLOS_ACCOUNT_API_OBJ_HPP

libraries/api/include/golos/api/chain_api_properties.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace golos { namespace api {
2626
fc::optional<asset> min_referral_break_fee;
2727
fc::optional<asset> max_referral_break_fee;
2828

29+
fc::optional<uint16_t> posts_window;
30+
fc::optional<uint16_t> posts_per_window;
2931
fc::optional<uint16_t> comments_window;
3032
fc::optional<uint16_t> comments_per_window;
3133
fc::optional<uint16_t> votes_window;
@@ -54,7 +56,7 @@ FC_REFLECT(
5456
(create_account_min_golos_fee)(create_account_min_delegation)
5557
(create_account_delegation_time)(min_delegation)
5658
(max_referral_interest_rate)(max_referral_term_sec)(min_referral_break_fee)(max_referral_break_fee)
57-
(comments_window)(comments_per_window)(votes_window)(votes_per_window)(auction_window_size)
59+
(posts_window)(posts_per_window)(comments_window)(comments_per_window)(votes_window)(votes_per_window)(auction_window_size)
5860
(max_delegated_vesting_interest_rate)(custom_ops_bandwidth_multiplier)
5961
(min_curation_percent)(max_curation_percent)(curation_reward_curve)
6062
(allow_distribute_auction_reward)(allow_return_auction_reward_to_fund))

libraries/chain/database.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,7 @@ namespace golos { namespace chain {
19261926
calc_median(&chain_properties_19::max_referral_term_sec);
19271927
calc_median(&chain_properties_19::min_referral_break_fee);
19281928
calc_median(&chain_properties_19::max_referral_break_fee);
1929+
calc_median_battery(&chain_properties_19::posts_window, &chain_properties_19::posts_per_window);
19291930
calc_median_battery(&chain_properties_19::comments_window, &chain_properties_19::comments_per_window);
19301931
calc_median_battery(&chain_properties_19::votes_window, &chain_properties_19::votes_per_window);
19311932
calc_median(&chain_properties_19::max_delegated_vesting_interest_rate);

libraries/chain/hardfork.d/0_19.hf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define STEEMIT_HARDFORK_0_19 19
33
#define STEEMIT_HARDFORK_0_19__898 (STEEMIT_HARDFORK_0_19) // Add votable auction window size
44
#define STEEMIT_HARDFORK_0_19__295 (STEEMIT_HARDFORK_0_19) // Referral program implemented
5-
#define STEEMIT_HARDFORK_0_19__533 (STEEMIT_HARDFORK_0_19) // Leaky algorithm for comment and vote bandwidth
5+
#define STEEMIT_HARDFORK_0_19__533_1002 (STEEMIT_HARDFORK_0_19) // Leaky algorithm for comment, vote and post bandwidth
66
#define STEEMIT_HARDFORK_0_19__756 (STEEMIT_HARDFORK_0_19) // Vesting shares delegation with interest
77
#define STEEMIT_HARDFORK_0_19__971 (STEEMIT_HARDFORK_0_19) // Withdraw vests to another account resests on account recover
88
#define STEEMIT_HARDFORK_0_19__924 (STEEMIT_HARDFORK_0_19) // Bandwidth for custom_json operations

libraries/chain/include/golos/chain/account_object.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class account_object
5050

5151
bool can_vote = true;
5252
uint16_t voting_power = STEEMIT_100_PERCENT; ///< current voting power of this account, it falls after every vote
53+
uint16_t posts_capacity = STEEMIT_POSTS_WINDOW;
5354
uint16_t comments_capacity = STEEMIT_COMMENTS_WINDOW;
5455
uint16_t voting_capacity = STEEMIT_VOTES_WINDOW;
5556
time_point_sec last_vote_time; ///< used to increase the voting power of this account the longer it goes without voting.

libraries/chain/steem_evaluator.cpp

Lines changed: 147 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,150 @@ namespace golos { namespace chain {
621621
}
622622
}
623623

624+
struct comment_bandwidth final {
625+
database& db;
626+
const time_point_sec& now;
627+
const comment_operation& op;
628+
const chain_properties& mprops;
629+
const account_object& auth;
630+
mutable const account_bandwidth_object* band = nullptr;
631+
632+
uint16_t calc_reward_weight() const {
633+
band = db.find<account_bandwidth_object, by_account_bandwidth_type>(
634+
std::make_tuple(op.author, bandwidth_type::post));
635+
636+
if (nullptr == band) {
637+
band = &db.create<account_bandwidth_object>([&](account_bandwidth_object &b) {
638+
b.account = op.author;
639+
b.type = bandwidth_type::post;
640+
});
641+
}
642+
643+
if (db.has_hardfork(STEEMIT_HARDFORK_0_19__533_1002)) {
644+
hf19();
645+
} else if (db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
646+
hf12();
647+
} else if (db.has_hardfork(STEEMIT_HARDFORK_0_6__113)) {
648+
hf6();
649+
} else {
650+
hf0();
651+
}
652+
653+
return calculate();
654+
}
655+
656+
private:
657+
uint16_t calculate() const {
658+
uint16_t reward_weight = STEEMIT_100_PERCENT;
659+
660+
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
661+
auto pb = band->average_bandwidth;
662+
663+
if (db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
664+
auto post_delta_time = std::min(
665+
now.sec_since_epoch() - band->last_bandwidth_update.sec_since_epoch(),
666+
STEEMIT_POST_AVERAGE_WINDOW);
667+
668+
auto old_weight =
669+
(pb * (STEEMIT_POST_AVERAGE_WINDOW - post_delta_time)) /
670+
STEEMIT_POST_AVERAGE_WINDOW;
671+
672+
pb = (old_weight + STEEMIT_100_PERCENT);
673+
674+
reward_weight = uint16_t(std::min(
675+
(STEEMIT_POST_WEIGHT_CONSTANT * STEEMIT_100_PERCENT) / (pb.value * pb.value),
676+
uint64_t(STEEMIT_100_PERCENT)));
677+
}
678+
679+
db.modify(*band, [&](account_bandwidth_object &b) {
680+
b.last_bandwidth_update = now;
681+
b.average_bandwidth = pb;
682+
});
683+
}
684+
685+
return reward_weight;
686+
}
687+
688+
void hf19() const {
689+
auto elapsed_seconds = (now - auth.last_post).to_seconds();
690+
691+
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
692+
auto consumption = mprops.posts_window / mprops.posts_per_window;
693+
694+
auto regenerated_capacity = std::min(
695+
uint32_t(mprops.posts_window),
696+
uint32_t(elapsed_seconds));
697+
698+
auto current_capacity = std::min(
699+
uint16_t(auth.posts_capacity + regenerated_capacity),
700+
mprops.posts_window);
701+
702+
GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
703+
bandwidth_exception::post_bandwidth,
704+
"You may only post ${posts_per_window} times in ${posts_window} seconds.",
705+
("posts_per_window", mprops.posts_per_window)
706+
("posts_window", mprops.posts_window));
707+
708+
709+
db.modify(auth, [&](account_object& a) {
710+
a.posts_capacity = current_capacity - consumption;
711+
});
712+
713+
} else {
714+
auto consumption = mprops.comments_window / mprops.comments_per_window;
715+
716+
auto regenerated_capacity = std::min(
717+
uint32_t(mprops.comments_window),
718+
uint32_t(elapsed_seconds));
719+
720+
auto current_capacity = std::min(
721+
uint16_t(auth.comments_capacity + regenerated_capacity),
722+
mprops.comments_window);
723+
724+
GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
725+
bandwidth_exception::comment_bandwidth,
726+
"You may only comment ${comments_per_window} times in ${comments_window} seconds.",
727+
("comments_per_window", mprops.comments_per_window)
728+
("comments_window", mprops.comments_window));
729+
730+
db.modify(auth, [&](account_object& a) {
731+
a.comments_capacity = current_capacity - consumption;
732+
});
733+
}
734+
}
735+
736+
void hf12() const {
737+
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
738+
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
739+
bandwidth_exception::post_bandwidth,
740+
"You may only post once every 5 minutes.");
741+
} else {
742+
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
743+
golos::bandwidth_exception::comment_bandwidth,
744+
"You may only comment once every 20 seconds.");
745+
}
746+
}
747+
748+
void hf6() const {
749+
if (op.parent_author == STEEMIT_ROOT_POST_PARENT) {
750+
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
751+
bandwidth_exception::post_bandwidth,
752+
"You may only post once every 5 minutes.");
753+
} else {
754+
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
755+
bandwidth_exception::comment_bandwidth,
756+
"You may only comment once every 20 seconds.");
757+
}
758+
}
759+
760+
void hf0() const {
761+
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + 60,
762+
bandwidth_exception::post_bandwidth,
763+
"You may only post once per minute.");
764+
}
765+
766+
}; // struct check_comment_bandwidth
767+
624768
void comment_evaluator::do_apply(const comment_operation &o) {
625769
try {
626770
if (_db.is_producing() ||
@@ -667,86 +811,7 @@ namespace golos { namespace chain {
667811
"The parent comment has disabled replies.");
668812
}
669813

670-
auto band = _db.find<account_bandwidth_object, by_account_bandwidth_type>(std::make_tuple(o.author, bandwidth_type::post));
671-
if (band == nullptr) {
672-
band = &_db.create<account_bandwidth_object>([&](account_bandwidth_object &b) {
673-
b.account = o.author;
674-
b.type = bandwidth_type::post;
675-
});
676-
}
677-
678-
auto elapsed_seconds = (now - auth.last_post).to_seconds();
679-
680-
if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533)) {
681-
auto consumption = mprops.comments_window / mprops.comments_per_window;
682-
683-
auto regenerated_capacity = std::min(uint32_t(mprops.comments_window), uint32_t(elapsed_seconds));
684-
auto current_capacity = std::min(uint16_t(auth.comments_capacity + regenerated_capacity), mprops.comments_window);
685-
686-
if (o.parent_author == STEEMIT_ROOT_POST_PARENT) {
687-
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
688-
bandwidth_exception::post_bandwidth,
689-
"You may only post once every 5 minutes.");
690-
} else {
691-
GOLOS_CHECK_BANDWIDTH(current_capacity, consumption,
692-
bandwidth_exception::comment_bandwidth,
693-
"You may only comment ${comments_per_window} times in ${comments_window} seconds.",
694-
("comments_per_window", mprops.comments_per_window)("comments_window", mprops.comments_window));
695-
}
696-
697-
db().modify(auth, [&](account_object &a) {
698-
a.comments_capacity = current_capacity - consumption;
699-
});
700-
} else if (_db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
701-
if (o.parent_author == STEEMIT_ROOT_POST_PARENT)
702-
GOLOS_CHECK_BANDWIDTH(now, band->last_bandwidth_update + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
703-
bandwidth_exception::post_bandwidth,
704-
"You may only post once every 5 minutes.");
705-
else
706-
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
707-
golos::bandwidth_exception::comment_bandwidth,
708-
"You may only comment once every 20 seconds.");
709-
} else if (_db.has_hardfork(STEEMIT_HARDFORK_0_6__113)) {
710-
if (o.parent_author == STEEMIT_ROOT_POST_PARENT)
711-
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_ROOT_COMMENT_INTERVAL,
712-
bandwidth_exception::post_bandwidth,
713-
"You may only post once every 5 minutes.");
714-
else
715-
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + STEEMIT_MIN_REPLY_INTERVAL,
716-
bandwidth_exception::comment_bandwidth,
717-
"You may only comment once every 20 seconds.");
718-
} else {
719-
GOLOS_CHECK_BANDWIDTH(now, auth.last_post + 60,
720-
bandwidth_exception::post_bandwidth,
721-
"You may only post once per minute.");
722-
}
723-
724-
uint16_t reward_weight = STEEMIT_100_PERCENT;
725-
726-
if (o.parent_author == STEEMIT_ROOT_POST_PARENT) {
727-
auto post_bandwidth = band->average_bandwidth;
728-
729-
if (_db.has_hardfork(STEEMIT_HARDFORK_0_12__176)) {
730-
auto post_delta_time = std::min(
731-
now.sec_since_epoch() -
732-
band->last_bandwidth_update.sec_since_epoch(), STEEMIT_POST_AVERAGE_WINDOW);
733-
auto old_weight = (post_bandwidth *
734-
(STEEMIT_POST_AVERAGE_WINDOW -
735-
post_delta_time)) /
736-
STEEMIT_POST_AVERAGE_WINDOW;
737-
post_bandwidth = (old_weight + STEEMIT_100_PERCENT);
738-
reward_weight = uint16_t(std::min(
739-
(STEEMIT_POST_WEIGHT_CONSTANT *
740-
STEEMIT_100_PERCENT) /
741-
(post_bandwidth.value *
742-
post_bandwidth.value), uint64_t(STEEMIT_100_PERCENT)));
743-
}
744-
745-
_db.modify(*band, [&](account_bandwidth_object &b) {
746-
b.last_bandwidth_update = now;
747-
b.average_bandwidth = post_bandwidth;
748-
});
749-
}
814+
uint16_t reward_weight = comment_bandwidth{_db, now, o, mprops, auth}.calc_reward_weight();
750815

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

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

1381-
if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533)) {
1446+
if (_db.has_hardfork(STEEMIT_HARDFORK_0_19__533_1002)) {
13821447
auto consumption = mprops.votes_window / mprops.votes_per_window;
13831448

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

1387-
GOLOS_CHECK_BANDWIDTH(current_capacity, consumption,
1452+
GOLOS_CHECK_BANDWIDTH(current_capacity + 1, consumption,
13881453
bandwidth_exception::vote_bandwidth,
13891454
"Can only vote ${votes_per_window} times in ${votes_window} seconds.",
13901455
("votes_per_window", mprops.votes_per_window)("votes_window", mprops.votes_window));

0 commit comments

Comments
 (0)