2 #include <boost/range/combine.hpp>
6 namespace database_ns {
10 , dgp_service(ctx.services().dynamic_global_property_service())
11 , account_service(ctx.services().account_service())
12 , account_blogging_statistic_service(ctx.services().account_blogging_statistic_service())
13 , comment_service(ctx.services().comment_service())
14 , comment_statistic_scr_service(ctx.services().comment_statistic_scr_service())
15 , comment_statistic_sp_service(ctx.services().comment_statistic_sp_service())
16 , comment_vote_service(ctx.services().comment_vote_service())
17 , hardfork_service(ctx.services().hardfork_property_service())
23 comment_service.
update(comment, [&](comment_object& c) {
26 c.children_abs_rshares = 0;
30 c.total_vote_weight = 0;
32 c.cashout_time = fc::time_point_sec::maximum();
39 auto comment_votes = comment_vote_service.
get_by_comment(comment.id);
40 for (
const comment_vote_object& vote : comment_votes)
42 comment_vote_service.
remove(vote);
47 fc::uint128_t process_comments_cashout_impl::get_total_claims(
const comment_refs_type& comments,
49 fc::uint128_t recent_claims)
const
51 shares_vector_type total_rshares;
52 for (
const comment_object& comment : comments)
54 total_rshares.push_back(comment.net_rshares);
57 fc::uint128_t total_claims = rewards_math::calculate_total_claims(recent_claims, reward_curve, total_rshares);
62 template <
typename TFundService>
65 const auto& fund = fund_service.get();
66 if (fund.activity_reward_balance.amount < 1 || comments.empty())
69 auto total_claims = get_total_claims(comments, fund.author_reward_curve, fund.recent_claims);
72 = calculate_comments_payout(comments, fund.activity_reward_balance, total_claims, fund.author_reward_curve);
74 auto total_reward = hardfork_service.
has_hardfork(SCORUM_HARDFORK_0_3)
79 rfo.recent_claims = total_claims;
80 rfo.activity_reward_balance -= total_reward;
86 const std::vector<asset>& fund_rewards)
88 FC_ASSERT(comments.size() == fund_rewards.size(),
"comments count and comments' rewards count should be equal");
89 FC_ASSERT(!fund_rewards.empty(),
"collection cannot be empty");
91 auto reward_symbol = fund_rewards[0].symbol();
92 auto total_claimed_reward =
asset(0, reward_symbol);
94 for (
const auto& item : boost::combine(comments, fund_rewards))
96 const auto& comment = item.get<0>().get();
97 const auto& fund_reward = item.get<1>();
99 auto rewards = pay_curators(comment, fund_reward);
100 auto beneficiaries_reward = pay_beneficiaries(comment, rewards.author_reward);
102 auto curators_reward = rewards.curators_reward;
103 auto author_reward = rewards.author_reward - beneficiaries_reward;
105 const auto& author = account_service.
get_account(comment.author);
106 pay_account(author, author_reward);
108 auto claimed_reward = curators_reward + author_reward + beneficiaries_reward;
109 total_claimed_reward += claimed_reward;
111 comment_service.
update(comment, [&](comment_object& c) { c.last_payout = dgp_service.
head_block_time(); });
112 if (author_reward.amount > 0)
121 fc::to_string(comment.permlink),
126 asset(0, reward_symbol),
127 asset(0, reward_symbol),
128 beneficiaries_reward));
130 accumulate_statistic(comment,
135 asset(0, reward_symbol),
136 asset(0, reward_symbol),
137 beneficiaries_reward,
142 return total_claimed_reward;
146 const std::vector<asset>& fund_rewards)
148 FC_ASSERT(comments.size() == fund_rewards.size(),
"comments count and comments' rewards count should be equal");
149 FC_ASSERT(fund_rewards.size() > 0,
"collection cannot be empty");
153 struct comment_reward
161 fc::shared_string permlink;
163 auto less = [](
const comment_key& l,
const comment_key& r) {
164 return std::tie(l.author, l.permlink) < std::tie(r.author, r.permlink);
167 std::map<comment_key, comment_reward, decltype(less)> comment_rewards(less);
168 for (
auto i = 0u; i < comments.size(); ++i)
170 comment_rewards.emplace(comment_key{ comments[i].get().author, get_permlink(comments[i].get().permlink) },
171 comment_reward{ fund_rewards[i].amount, 0 });
179 for (
const comment_object& comment : comments_with_parents)
181 const auto&
reward = comment_rewards[comment_key{ comment.author, get_permlink(comment.permlink) }];
191 comment_rewards[comment_key{ comment.parent_author, get_permlink(comment.parent_permlink) }].commenting
199 const comment_object& comment,
const asset& fund_reward,
const asset& payout_from_children)
203 auto reward_symbol = fund_reward.
symbol();
205 if (fund_reward.
amount < 1 && payout_from_children.
amount < 1)
206 return payout_result;
208 auto rewards = pay_curators(comment, fund_reward);
209 auto author_reward = rewards.author_reward;
210 auto curators_reward = rewards.curators_reward;
212 auto payout_to_parent =
asset(0, reward_symbol);
213 if (comment.depth != 0)
216 payout_to_parent = (author_reward + payout_from_children) * fraction;
219 author_reward = (author_reward + payout_from_children) - payout_to_parent;
221 auto beneficiaries_reward = pay_beneficiaries(comment, author_reward);
222 author_reward -= beneficiaries_reward;
224 const auto& author = account_service.
get_account(comment.author);
225 pay_account(author, author_reward);
227 payout_result.total_claimed_reward = curators_reward + author_reward + beneficiaries_reward;
228 payout_result.parent_comment_reward = payout_to_parent;
230 comment_service.
update(comment, [&](comment_object& c) { c.last_payout = dgp_service.
head_block_time(); });
231 if (author_reward.amount > 0 || payout_from_children.
amount > 0)
240 fc::to_string(comment.permlink),
242 payout_result.total_claimed_reward,
245 payout_from_children,
247 beneficiaries_reward));
249 accumulate_statistic(comment,
254 payout_from_children,
256 beneficiaries_reward,
260 return payout_result;
262 FC_CAPTURE_AND_RETHROW((comment))
266 process_comments_cashout_impl::pay_curators(
const comment_object& comment,
const asset& fund_reward)
270 auto reward_symbol = fund_reward.
symbol();
273 if (!comment.allow_curation_rewards)
274 return {
asset(0, reward_symbol), fund_reward - potential_reward };
275 else if (comment.total_vote_weight <= 0)
276 return {
asset(0, reward_symbol), fund_reward };
278 auto rewarded = asset(0, reward_symbol);
280 for (
const comment_vote_object& vote : comment_votes)
282 auto claim = potential_reward * utils::make_fraction(vote.weight, comment.total_vote_weight);
283 if (claim.amount > 0)
287 const auto& voter = account_service.
get(vote.voter);
288 pay_account(voter, claim);
291 curation_reward_operation(voter.name, claim, comment.author, fc::to_string(comment.permlink)));
293 accumulate_statistic(voter, claim);
297 return { rewarded, fund_reward - rewarded };
299 FC_CAPTURE_AND_RETHROW((comment.author)(comment.permlink)(fund_reward))
302 asset process_comments_cashout_impl::pay_beneficiaries(
const comment_object& comment,
const asset& author_reward)
304 auto reward_symbol = author_reward.
symbol();
306 auto beneficiaries_reward = asset(0, reward_symbol);
307 for (
auto& beneficiary : comment.beneficiaries)
309 auto beneficiary_reward = author_reward * utils::make_fraction(beneficiary.weight,
SCORUM_100_PERCENT);
310 pay_account(account_service.
get_account(beneficiary.account), beneficiary_reward);
311 beneficiaries_reward += beneficiary_reward;
314 beneficiary.account, comment.author, fc::to_string(comment.permlink), beneficiary_reward));
317 return beneficiaries_reward;
320 void process_comments_cashout_impl::pay_account(
const account_object& recipient,
const asset& reward)
332 std::vector<asset> process_comments_cashout_impl::calculate_comments_payout(
const comment_refs_type& comments,
333 const asset& reward_fund_balance,
334 fc::uint128_t total_claims,
337 std::vector<asset> rewards;
338 rewards.reserve(comments.size());
340 for (
const comment_object& comment : comments)
342 share_type payout = rewards_math::calculate_payout(
343 comment.net_rshares, total_claims, reward_fund_balance.amount, reward_curve,
346 rewards.emplace_back(payout, reward_fund_balance.symbol());
352 void process_comments_cashout_impl::accumulate_statistic(
const comment_object& comment,
353 const account_object& author,
354 const asset& fund_reward,
355 const asset& author_payout,
356 const asset& curation_payout,
357 const asset& payout_from_children,
358 const asset& payout_to_parent,
359 const asset& beneficiary_payout,
362 FC_ASSERT(author_payout.symbol() == reward_symbol);
363 FC_ASSERT(curation_payout.symbol() == reward_symbol);
364 FC_ASSERT(beneficiary_payout.symbol() == reward_symbol);
366 asset total_payout = author_payout;
367 total_payout += curation_payout;
368 total_payout += beneficiary_payout;
373 accumulate_comment_statistic(comment_statistic_scr_service, comment,
378 payout_from_children,
384 accumulate_comment_statistic(comment_statistic_sp_service, comment,
389 payout_from_children,
397 const auto& author_stat = account_blogging_statistic_service.
obtain(author.id);
403 void process_comments_cashout_impl::accumulate_statistic(
const account_object& voter,
const asset& curation_payout)
406 const auto& voter_stat = account_blogging_statistic_service.
obtain(voter.id);
413 struct by_depth_greater
415 bool operator()(
const comment_object& lhs,
const comment_object& rhs)
417 return std::tie(lhs.depth, lhs.id) > std::tie(rhs.depth, rhs.id);
421 using comment_refs_set = std::set<comment_refs_type::value_type, by_depth_greater>;
422 comment_refs_set ordered_comments(comments.begin(), comments.end());
425 for (
auto it = ordered_comments.begin(); it != ordered_comments.end() && it->get().depth != 0; ++it)
427 const comment_object& comment = it->get();
429 const auto& parent_comment = comment_service.
get(comment.parent_author, fc::to_string(comment.parent_permlink));
433 ordered_comments.insert(parent_comment);
436 comment_refs_type comments_with_parents(ordered_comments.begin(), ordered_comments.end());
438 return comments_with_parents;
441 fc::shared_string process_comments_cashout_impl::get_permlink(
const fc::shared_string& str)
const
446 return fc::shared_string(
"", str.get_allocator());
451 template void process_comments_cashout_impl::reward<content_reward_fund_scr_service_i>(content_reward_fund_scr_service_i&,
const comment_refs_type&);
452 template void process_comments_cashout_impl::reward<content_reward_fund_sp_service_i>(content_reward_fund_sp_service_i&,
const comment_refs_type&);
453 template void process_comments_cashout_impl::reward<content_fifa_world_cup_2018_bounty_reward_fund_service_i>( content_fifa_world_cup_2018_bounty_reward_fund_service_i&,
const comment_refs_type&);
virtual void push_virtual_operation(const operation &op)
#define SCORUM_CURATION_REWARD_PERCENT
#define SCORUM_PARENT_COMMENT_REWARD_PERCENT
#define SCORUM_100_PERCENT
#define SCORUM_MIN_COMMENT_PAYOUT_SHARE
scorum::chain::comment_service_i::comment_refs_type comment_refs_type
fc::safe< share_value_type > share_type
fc::fixed_string_16 account_name_type
uint64_t asset_symbol_type
virtual void increase_curation_rewards(const account_blogging_statistic_object &stat, const asset &amount)=0
virtual void increase_posting_rewards(const account_blogging_statistic_object &stat, const asset &amount)=0
virtual const account_blogging_statistic_object & obtain(const account_id_type &account_id)=0
virtual const asset create_scorumpower(const account_object &to_account, const asset &scorum)=0
virtual const account_object & get_account(const account_name_type &) const =0
virtual void increase_balance(const account_object &account, const asset &amount)=0
virtual const account_object & get(const account_id_type &) const =0
virtual void update(const modifier_type &modifier)=0
virtual fc::time_point_sec head_block_time() const =0
virtual bool has_hardfork(uint32_t hardfork) const =0
asset_symbol_type symbol() const