3 #include <scorum/rewards_math/curve.hpp>
24 #include <scorum/rewards_math/formulas.hpp>
32 #include <diff_match_patch.h>
33 #include <boost/locale/encoding_utf.hpp>
35 using boost::locale::conv::utf_to_utf;
39 return utf_to_utf<wchar_t>(str.c_str(), str.c_str() + str.size());
44 return utf_to_utf<char>(str.c_str(), str.c_str() + str.size());
49 #include <fc/uint128.hpp>
50 #include <fc/utf8.hpp>
59 FC_ASSERT(permlink.size() > SCORUM_MIN_PERMLINK_LENGTH && permlink.size() < SCORUM_MAX_PERMLINK_LENGTH,
60 "Permlink is not a valid size.");
62 for (
auto ch : permlink)
64 if (!std::islower(ch) && !std::isdigit(ch) && !(ch ==
'-'))
66 FC_ASSERT(
false,
"Invalid permlink character: ${ch}", (
"ch", std::string(1, ch)));
73 bool operator()(
const fc::shared_string& a,
const std::string& b)
75 return a.size() == b.size() && std::strcmp(a.c_str(), b.c_str()) == 0;
79 void witness_update_evaluator::do_apply(
const witness_update_operation& o)
81 account_service_i& account_service = db().account_service();
82 witness_service_i& witness_service = db().witness_service();
84 account_service.check_account_existence(o.owner);
86 FC_ASSERT(o.url.size() <= SCORUM_MAX_WITNESS_URL_LENGTH,
"URL is too long");
87 FC_ASSERT(o.proposed_chain_props.account_creation_fee.symbol() ==
SCORUM_SYMBOL);
89 if (!witness_service.is_exists(o.owner))
91 witness_service.create_witness(o.owner, o.url, o.block_signing_key, o.proposed_chain_props);
95 const auto& witness = witness_service.get(o.owner);
96 witness_service.update_witness(witness, o.url, o.block_signing_key, o.proposed_chain_props);
100 void account_create_evaluator::do_apply(
const account_create_operation& o)
102 account_service_i& account_service = db().account_service();
103 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
105 const auto& creator = account_service.get_account(o.creator);
109 FC_ASSERT(creator.balance >= o.fee,
"Insufficient balance to create account.",
110 (
"creator.balance", creator.balance)(
"required", o.fee));
114 const auto creation_fee
116 FC_ASSERT(o.fee >= creation_fee,
"Insufficient Fee: ${f} required, ${p} provided.",
117 (
"f", creation_fee)(
"p", o.fee));
121 account_service.check_account_existence(o.owner.account_auths);
123 account_service.check_account_existence(o.active.account_auths);
125 account_service.check_account_existence(o.posting.account_auths);
129 account_service.create_account(o.new_account_name, o.creator, o.memo_key, o.json_metadata, o.owner, o.active,
133 void account_create_with_delegation_evaluator::do_apply(
const account_create_with_delegation_operation& o)
135 account_service_i& account_service = db().account_service();
136 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
137 withdraw_scorumpower_service_i& withdraw_scorumpower_service = db().withdraw_scorumpower_service();
139 const auto& creator = account_service.get_account(o.creator);
143 FC_ASSERT(creator.balance >= o.fee,
"Insufficient balance to create account.",
144 (
"creator.balance", creator.balance)(
"required", o.fee));
148 asset withdraw_rest = withdraw_scorumpower_service.get_withdraw_rest(creator.id);
150 FC_ASSERT(creator.scorumpower - creator.delegated_scorumpower - withdraw_rest >= o.delegation,
151 "Insufficient scorumpower to delegate to new account.",
152 (
"creator.scorumpower", creator.scorumpower)(
"creator.delegated_scorumpower",
153 creator.delegated_scorumpower)(
"required", o.delegation));
155 const auto median_creation_fee = dprops_service.get().median_chain_props.account_creation_fee;
163 FC_ASSERT(current_delegation >= target_delegation,
"Inssufficient Delegation ${f} required, ${p} provided.",
164 (
"f", target_delegation)(
"p", current_delegation)(
"account_creation_fee", median_creation_fee)(
165 "o.fee", o.fee)(
"o.delegation", o.delegation));
167 FC_ASSERT(o.fee >= median_creation_fee,
"Insufficient Fee: ${f} required, ${p} provided.",
168 (
"f", median_creation_fee)(
"p", o.fee));
172 account_service.check_account_existence(o.owner.account_auths);
174 account_service.check_account_existence(o.active.account_auths);
176 account_service.check_account_existence(o.posting.account_auths);
178 account_service.create_account_with_delegation(o.new_account_name, o.creator, o.memo_key, o.json_metadata, o.owner,
179 o.active, o.posting, o.fee, o.delegation);
182 void account_update_evaluator::do_apply(
const account_update_operation& o)
185 o.posting->validate();
187 account_service_i& account_service = db().account_service();
189 const auto& account = account_service.get_account(o.account);
190 const auto& account_auth = account_service.get_account_authority(o.account);
194 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
197 "Owner authority can only be updated once an hour.");
199 account_service.check_account_existence(o.owner->account_auths);
201 account_service.update_owner_authority(account, *o.owner);
206 account_service.check_account_existence(o.active->account_auths);
211 account_service.check_account_existence(o.posting->account_auths);
214 account_service.update_acount(account, account_auth, o.memo_key, o.json_metadata, o.owner, o.active, o.posting);
220 void delete_comment_evaluator::do_apply(
const delete_comment_operation& o)
222 account_service_i& account_service = db().account_service();
223 comment_service_i& comment_service = db().comment_service();
224 comment_vote_service_i& comment_vote_service = db().comment_vote_service();
225 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
227 const auto& auth = account_service.get_account(o.author);
228 FC_ASSERT(!(auth.owner_challenged || auth.active_challenged),
229 "Operation cannot be processed because account is currently challenged.");
231 const auto& comment = comment_service.get(o.author, o.permlink);
232 FC_ASSERT(comment.children == 0,
"Cannot delete a comment with replies.");
234 FC_ASSERT(comment.cashout_time != fc::time_point_sec::maximum());
236 FC_ASSERT(comment.net_rshares <= 0,
"Cannot delete a comment with net positive votes.");
238 if (comment.net_rshares > 0)
244 std::string parent_permlink = fc::to_string(comment.parent_permlink);
246 while (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
248 const comment_object& parent = comment_service.get(parent_author, parent_permlink);
250 parent_author = parent.parent_author;
251 parent_permlink = fc::to_string(parent.parent_permlink);
253 auto now = dprops_service.head_block_time();
255 comment_service.update(parent, [&](comment_object& p) {
265 comment_service.remove(comment);
279 FC_ASSERT(
_c.beneficiaries.size() == 0,
"Comment already has beneficiaries specified.");
280 FC_ASSERT(
_c.abs_rshares == 0,
"Comment must not have been voted on before specifying beneficiaries.");
285 _account_service.check_account_existence(b.account,
"Beneficiary");
286 c.beneficiaries.push_back(b);
291 const comment_object&
_c;
302 FC_ASSERT(!(auth.owner_challenged || auth.active_challenged),
303 "Operation cannot be processed because account is currently challenged.");
307 FC_ASSERT(comment.abs_rshares == 0,
308 "One of the included comment options requires the comment to have no rshares allocated to it.");
310 FC_ASSERT(comment.allow_curation_rewards >= o.
allow_curation_rewards,
"Curation rewards cannot be re-enabled.");
311 FC_ASSERT(comment.allow_votes >= o.
allow_votes,
"Voting cannot be re-enabled.");
312 FC_ASSERT(comment.max_accepted_payout >= o.
max_accepted_payout,
"A comment cannot accept a greater payout.");
314 comment_service.
update(comment, [&](comment_object& c) {
322 e.visit(comment_options_extension_visitor(comment, db()));
326 void comment_evaluator::do_apply(
const comment_operation& o)
328 account_service_i& account_service = db().account_service();
329 comment_service_i& comment_service = db().comment_service();
330 comment_statistic_scr_service_i& comment_statistic_scr_service = db().comment_statistic_scr_service();
331 comment_statistic_sp_service_i& comment_statistic_sp_service = db().comment_statistic_sp_service();
332 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
337 FC_ASSERT(o.title.size() + o.body.size() + o.json_metadata.size(),
338 "Cannot update comment because nothing appears to be changing.");
340 const auto& auth = account_service.get_account(o.author);
342 FC_ASSERT(!(auth.owner_challenged || auth.active_challenged),
343 "Operation cannot be processed because account is currently challenged.");
346 std::string parent_permlink = o.parent_permlink;
347 if (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
349 const comment_object& parent = comment_service.get(parent_author, parent_permlink);
351 "Comment is nested ${x} posts deep, maximum depth is ${y}.",
355 auto now = dprops_service.head_block_time();
357 if (!comment_service.is_exists(o.author, o.permlink))
359 if (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
361 const comment_object& parent = comment_service.get(parent_author, parent_permlink);
362 FC_ASSERT(comment_service.get(parent.root_comment).allow_replies,
363 "The parent comment has disabled replies.");
366 if (parent_author == SCORUM_ROOT_POST_PARENT_ACCOUNT)
368 "You may only post once every 5 minutes.",
369 (
"now", now)(
"last_root_post", auth.last_root_post));
372 "You may only comment once every 20 seconds.",
373 (
"now", now)(
"auth.last_post", auth.last_post));
375 account_service.add_post(auth, parent_author);
381 std::string pr_parent_permlink;
382 uint16_t pr_depth = 0;
383 std::string pr_category;
385 if (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
387 const comment_object& parent = comment_service.get(parent_author, parent_permlink);
388 pr_parent_author = parent.author;
389 pr_parent_permlink = fc::to_string(parent.permlink);
390 pr_depth = parent.depth;
391 pr_category = fc::to_string(parent.category);
392 pr_root_comment = parent.root_comment;
395 const comment_object& new_comment = comment_service.create([&](comment_object& com) {
397 com.author = o.author;
398 fc::from_string(com.permlink, o.permlink);
399 com.last_update = now;
400 com.created = com.last_update;
401 com.active = com.last_update;
402 com.last_payout = fc::time_point_sec();
404 if (parent_author == SCORUM_ROOT_POST_PARENT_ACCOUNT)
406 com.parent_author =
"";
407 fc::from_string(com.parent_permlink, parent_permlink);
408 fc::from_string(com.category, parent_permlink);
409 com.root_comment = com.id;
413 com.parent_author = pr_parent_author;
414 fc::from_string(com.parent_permlink, pr_parent_permlink);
415 com.depth = pr_depth + 1;
416 fc::from_string(com.category, pr_category);
417 com.root_comment = pr_root_comment;
423 fc::from_string(com.title, o.title);
424 if (o.body.size() < 1024 * 1024 * 128)
426 fc::from_string(com.body, o.body);
429 fc::from_string(com.json_metadata, o.json_metadata);
433 comment_statistic_scr_service.create(
434 [&](comment_statistic_scr_object& stat) { stat.comment = new_comment.id; });
435 comment_statistic_sp_service.create(
436 [&](comment_statistic_sp_object& stat) { stat.comment = new_comment.id; });
440 account_blogging_statistic_service_i& account_blogging_statistic_service
441 = db().account_blogging_statistic_service();
443 const auto& author_stat = account_blogging_statistic_service.obtain(auth.id);
444 account_blogging_statistic_service.add_post(author_stat);
445 if (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
447 account_blogging_statistic_service.add_comment(author_stat);
452 while (parent_author != SCORUM_ROOT_POST_PARENT_ACCOUNT)
454 const comment_object& parent = comment_service.get(parent_author, parent_permlink);
456 parent_author = parent.parent_author;
457 parent_permlink = fc::to_string(parent.parent_permlink);
459 comment_service.update(parent, [&](comment_object& p) {
470 const comment_object& comment = comment_service.get(o.author, o.permlink);
472 comment_service.update(comment, [&](comment_object& com) {
473 com.last_update = dprops_service.head_block_time();
474 com.active = com.last_update;
477 if (parent_author == SCORUM_ROOT_POST_PARENT_ACCOUNT)
479 FC_ASSERT(com.parent_author ==
account_name_type(),
"The parent of a comment cannot be changed.");
480 FC_ASSERT(equal(com.parent_permlink, parent_permlink),
"The permlink of a comment cannot change.");
484 FC_ASSERT(com.parent_author == o.parent_author,
"The parent of a comment cannot be changed.");
485 FC_ASSERT(equal(com.parent_permlink, parent_permlink),
"The permlink of a comment cannot change.");
490 fc::from_string(com.title, o.title);
491 if (!o.json_metadata.empty())
493 fc::from_string(com.json_metadata, o.json_metadata);
500 diff_match_patch<std::wstring> dmp;
506 if (!fc::is_utf8(patched_body))
508 idump((
"invalid utf8")(patched_body));
509 fc::from_string(com.body, fc::prune_invalid_utf8(patched_body));
513 fc::from_string(com.body, patched_body);
518 fc::from_string(com.body, o.body);
523 fc::from_string(com.body, o.body);
531 FC_CAPTURE_AND_RETHROW((o))
534 void escrow_transfer_evaluator::do_apply(
const escrow_transfer_operation& o)
536 account_service_i& account_service = db().account_service();
537 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
538 escrow_service_i& escrow_service = db().escrow_service();
542 const auto& from_account = account_service.get_account(o.from);
543 account_service.check_account_existence(o.to);
544 account_service.check_account_existence(o.agent);
546 FC_ASSERT(o.ratification_deadline > dprops_service.head_block_time(),
547 "The escorw ratification deadline must be after head block time.");
548 FC_ASSERT(o.escrow_expiration > dprops_service.head_block_time(),
549 "The escrow expiration must be after head block time.");
551 FC_ASSERT(o.fee.symbol() ==
SCORUM_SYMBOL,
"Fee must be in SCR.");
553 asset scorum_spent = o.scorum_amount;
554 scorum_spent += o.fee;
556 FC_ASSERT(from_account.balance >= scorum_spent,
557 "Account cannot cover SCR costs of escrow. Required: ${r} Available: ${a}",
558 (
"r", scorum_spent)(
"a", from_account.balance));
560 account_service.decrease_balance(from_account, scorum_spent);
562 escrow_service.create_escrow(o.escrow_id, o.from, o.to, o.agent, o.ratification_deadline, o.escrow_expiration,
563 o.scorum_amount, o.fee);
565 FC_CAPTURE_AND_RETHROW((o))
568 void escrow_approve_evaluator::do_apply(
const escrow_approve_operation& o)
570 account_service_i& account_service = db().account_service();
571 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
572 escrow_service_i& escrow_service = db().escrow_service();
577 const auto& escrow = escrow_service.get(o.from, o.escrow_id);
579 FC_ASSERT(escrow.to == o.to,
"Operation 'to' (${o}) does not match escrow 'to' (${e}).",
580 (
"o", o.to)(
"e", escrow.to));
581 FC_ASSERT(escrow.agent == o.agent,
"Operation 'agent' (${a}) does not match escrow 'agent' (${e}).",
582 (
"o", o.agent)(
"e", escrow.agent));
583 FC_ASSERT(escrow.ratification_deadline >= dprops_service.head_block_time(),
584 "The escrow ratification deadline has passed. Escrow can no longer be ratified.");
586 bool reject_escrow = !o.approve;
590 FC_ASSERT(!escrow.to_approved,
"Account 'to' (${t}) has already approved the escrow.", (
"t", o.to));
594 escrow_service.update(escrow, [&](escrow_object& esc) { esc.to_approved =
true; });
597 if (o.who == o.agent)
599 FC_ASSERT(!escrow.agent_approved,
"Account 'agent' (${a}) has already approved the escrow.",
604 escrow_service.update(escrow, [&](escrow_object& esc) { esc.agent_approved =
true; });
610 const auto& from_account = account_service.get_account(o.from);
611 account_service.increase_balance(from_account, escrow.scorum_balance);
612 account_service.increase_balance(from_account, escrow.pending_fee);
614 escrow_service.remove(escrow);
616 else if (escrow.to_approved && escrow.agent_approved)
618 const auto& agent_account = account_service.get_account(o.agent);
619 account_service.increase_balance(agent_account, escrow.pending_fee);
621 escrow_service.update(escrow, [&](escrow_object& esc) { esc.pending_fee.amount = 0; });
624 FC_CAPTURE_AND_RETHROW((o))
627 void escrow_dispute_evaluator::do_apply(
const escrow_dispute_operation& o)
629 account_service_i& account_service = db().account_service();
630 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
631 escrow_service_i& escrow_service = db().escrow_service();
635 account_service.check_account_existence(o.from);
637 const auto& e = escrow_service.get(o.from, o.escrow_id);
638 FC_ASSERT(dprops_service.head_block_time() < e.escrow_expiration,
639 "Disputing the escrow must happen before expiration.");
640 FC_ASSERT(e.to_approved && e.agent_approved,
641 "The escrow must be approved by all parties before a dispute can be raised.");
642 FC_ASSERT(!e.disputed,
"The escrow is already under dispute.");
643 FC_ASSERT(e.to == o.to,
"Operation 'to' (${o}) does not match escrow 'to' (${e}).", (
"o", o.to)(
"e", e.to));
644 FC_ASSERT(e.agent == o.agent,
"Operation 'agent' (${a}) does not match escrow 'agent' (${e}).",
645 (
"o", o.agent)(
"e", e.agent));
647 escrow_service.update(e, [&](escrow_object& esc) { esc.disputed =
true; });
649 FC_CAPTURE_AND_RETHROW((o))
652 void escrow_release_evaluator::do_apply(
const escrow_release_operation& o)
654 account_service_i& account_service = db().account_service();
655 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
656 escrow_service_i& escrow_service = db().escrow_service();
660 account_service.check_account_existence(o.from);
661 const auto& receiver_account = account_service.get_account(o.receiver);
663 const auto& e = escrow_service.get(o.from, o.escrow_id);
664 FC_ASSERT(e.scorum_balance >= o.scorum_amount,
665 "Release amount exceeds escrow balance. Amount: ${a}, Balance: ${b}",
666 (
"a", o.scorum_amount)(
"b", e.scorum_balance));
667 FC_ASSERT(e.to == o.to,
"Operation 'to' (${o}) does not match escrow 'to' (${e}).", (
"o", o.to)(
"e", e.to));
668 FC_ASSERT(e.agent == o.agent,
"Operation 'agent' (${a}) does not match escrow 'agent' (${e}).",
669 (
"o", o.agent)(
"e", e.agent));
670 FC_ASSERT(o.receiver == e.from || o.receiver == e.to,
"Funds must be released to 'from' (${f}) or 'to' (${t})",
671 (
"f", e.from)(
"t", e.to));
672 FC_ASSERT(e.to_approved && e.agent_approved,
"Funds cannot be released prior to escrow approval.");
677 FC_ASSERT(o.who == e.agent,
"Only 'agent' (${a}) can release funds in a disputed escrow.", (
"a", e.agent));
681 FC_ASSERT(o.who == e.from || o.who == e.to,
682 "Only 'from' (${f}) and 'to' (${t}) can release funds from a non-disputed escrow",
683 (
"f", e.from)(
"t", e.to));
685 if (e.escrow_expiration > dprops_service.head_block_time())
690 FC_ASSERT(o.receiver == e.to,
"Only 'from' (${f}) can release funds to 'to' (${t}).",
691 (
"f", e.from)(
"t", e.to));
693 else if (o.who == e.to)
695 FC_ASSERT(o.receiver == e.from,
"Only 'to' (${t}) can release funds to 'from' (${t}).",
696 (
"f", e.from)(
"t", e.to));
702 account_service.increase_balance(receiver_account, o.scorum_amount);
704 escrow_service.update(e, [&](escrow_object& esc) { esc.scorum_balance -= o.scorum_amount; });
706 if (e.scorum_balance.amount == 0)
708 escrow_service.remove(e);
711 FC_CAPTURE_AND_RETHROW((o))
714 void transfer_evaluator::do_apply(
const transfer_operation& o)
716 account_service_i& account_service = db().account_service();
718 const auto& from_account = account_service.get_account(o.from);
719 const auto& to_account = account_service.get_account(o.to);
721 account_service.drop_challenged(from_account);
723 FC_ASSERT(from_account.balance >= o.amount,
"Account does not have sufficient funds for transfer.");
724 account_service.decrease_balance(from_account, o.amount);
725 account_service.increase_balance(to_account, o.amount);
728 void transfer_to_scorumpower_evaluator::do_apply(
const transfer_to_scorumpower_operation& o)
730 account_service_i& account_service = db().account_service();
732 const auto& from_account = account_service.get_account(o.from);
733 const auto& to_account = o.to.size() ? account_service.get_account(o.to) : from_account;
735 FC_ASSERT(from_account.balance >= o.amount,
"Account does not have sufficient SCR for transfer.");
736 account_service.decrease_balance(from_account, o.amount);
737 account_service.create_scorumpower(to_account, o.amount);
740 void account_witness_proxy_evaluator::do_apply(
const account_witness_proxy_operation& o)
742 account_service_i& account_service = db().account_service();
744 const auto& account = account_service.get_account(o.account);
745 FC_ASSERT(account.proxy != o.proxy,
"Proxy must change.");
747 FC_ASSERT(account.can_vote,
"Account has declined the ability to vote and cannot proxy votes.");
749 optional<account_object> proxy;
752 proxy = account_service.get_account(o.proxy);
754 account_service.update_voting_proxy(account, proxy);
757 void account_witness_vote_evaluator::do_apply(
const account_witness_vote_operation& o)
759 account_service_i& account_service = db().account_service();
760 witness_service_i& witness_service = db().witness_service();
761 witness_vote_service_i& witness_vote_service = db().witness_vote_service();
763 const auto& voter = account_service.get_account(o.account);
764 FC_ASSERT(voter.proxy.size() == 0,
"A proxy is currently set, please clear the proxy before voting for a witness.");
767 FC_ASSERT(voter.can_vote,
"Account has declined its voting rights.");
769 const auto& witness = witness_service.get(o.witness);
771 if (!witness_vote_service.is_exists(witness.id, voter.id))
773 FC_ASSERT(o.approve,
"Vote doesn't exist, user must indicate a desire to approve witness.");
776 "Account has voted for too many witnesses.");
778 witness_vote_service.create([&](witness_vote_object& v) {
779 v.witness = witness.id;
780 v.account = voter.id;
783 witness_service.adjust_witness_vote(witness, voter.witness_vote_weight());
785 account_service.increase_witnesses_voted_for(voter);
789 FC_ASSERT(!o.approve,
"Vote currently exists, user must indicate a desire to reject witness.");
791 witness_service.adjust_witness_vote(witness, -voter.witness_vote_weight());
793 account_service.decrease_witnesses_voted_for(voter);
795 const witness_vote_object& witness_vote_object = witness_vote_service.get(witness.id, voter.id);
796 witness_vote_service.remove(witness_vote_object);
800 void prove_authority_evaluator::do_apply(
const prove_authority_operation& o)
802 account_service_i& account_service = db().account_service();
804 const auto& challenged = account_service.get_account(o.challenged);
805 FC_ASSERT(challenged.owner_challenged || challenged.active_challenged,
806 "Account is not challeneged. No need to prove authority.");
808 account_service.prove_authority(challenged, o.require_owner);
811 void request_account_recovery_evaluator::do_apply(
const request_account_recovery_operation& o)
813 account_service_i& account_service = db().account_service();
814 witness_service_i& witness_service = db().witness_service();
816 const auto& account_to_recover = account_service.get_account(o.account_to_recover);
818 if (account_to_recover.recovery_account.length())
819 FC_ASSERT(account_to_recover.recovery_account == o.recovery_account,
820 "Cannot recover an account that does not have you as there recovery partner.");
822 FC_ASSERT(witness_service.get_top_witness().owner == o.recovery_account,
823 "Top witness must recover an account with no recovery partner.");
825 account_service.create_account_recovery(o.account_to_recover, o.new_owner_authority);
828 void recover_account_evaluator::do_apply(
const recover_account_operation& o)
830 account_service_i& account_service = db().account_service();
831 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
833 const auto& account_to_recover = account_service.get_account(o.account_to_recover);
836 "Owner authority can only be updated once an hour.");
838 account_service.submit_account_recovery(account_to_recover, o.new_owner_authority, o.recent_owner_authority);
841 void change_recovery_account_evaluator::do_apply(
const change_recovery_account_operation& o)
843 account_service_i& account_service = db().account_service();
845 account_service.check_account_existence(o.new_recovery_account);
846 const auto& account_to_recover = account_service.get_account(o.account_to_recover);
848 account_service.change_recovery_account(account_to_recover, o.new_recovery_account);
851 void decline_voting_rights_evaluator::do_apply(
const decline_voting_rights_operation& o)
853 account_service_i& account_service = db().account_service();
854 decline_voting_rights_request_service_i& dvrr_service = db().decline_voting_rights_request_service();
856 const auto& account = account_service.get_account(o.account);
860 FC_ASSERT(!dvrr_service.is_exists(account.id),
"Cannot create new request because one already exists.");
866 const auto& request = dvrr_service.get(account.id);
868 dvrr_service.remove(request);
872 void delegate_scorumpower_evaluator::do_apply(
const delegate_scorumpower_operation& op)
874 account_service_i& account_service = db().account_service();
875 scorumpower_delegation_service_i& sp_delegation_service = db().scorumpower_delegation_service();
876 dynamic_global_property_service_i& dprops_service = db().dynamic_global_property_service();
877 withdraw_scorumpower_service_i& withdraw_scorumpower_service = db().withdraw_scorumpower_service();
879 const auto& delegator = account_service.get_account(op.delegator);
880 const auto& delegatee = account_service.get_account(op.delegatee);
882 auto available_shares = delegator.scorumpower - delegator.delegated_scorumpower
883 - withdraw_scorumpower_service.get_withdraw_rest(delegator.id);
885 const auto& dprops = dprops_service.get();
886 auto min_delegation = asset(
888 auto min_update = asset(dprops.median_chain_props.account_creation_fee.amount,
SP_SYMBOL);
891 if (!sp_delegation_service.is_exists(op.delegator, op.delegatee))
893 FC_ASSERT(available_shares >= op.scorumpower,
"Account does not have enough scorumpower to delegate.");
894 FC_ASSERT(op.scorumpower >= min_delegation,
"Account must delegate a minimum of ${v}", (
"v", min_delegation));
896 sp_delegation_service.create([&](scorumpower_delegation_object& spdo) {
897 spdo.delegator = op.delegator;
898 spdo.delegatee = op.delegatee;
899 spdo.scorumpower = op.scorumpower;
900 spdo.min_delegation_time = dprops.time;
903 account_service.increase_delegated_scorumpower(delegator, op.scorumpower);
904 account_service.increase_received_scorumpower(delegatee, op.scorumpower);
908 const auto& delegation = sp_delegation_service.get(op.delegator, op.delegatee);
911 if (op.scorumpower >= delegation.scorumpower)
913 auto delta = op.scorumpower - delegation.scorumpower;
915 FC_ASSERT(delta >= min_update,
"Scorum Power increase is not enough of a difference. min_update: ${min}",
916 (
"min", min_update));
917 FC_ASSERT(available_shares >= op.scorumpower - delegation.scorumpower,
918 "Account does not have enough scorumpower to delegate.");
920 account_service.increase_delegated_scorumpower(delegator, delta);
921 account_service.increase_received_scorumpower(delegatee, delta);
923 sp_delegation_service.update(delegation,
924 [&](scorumpower_delegation_object& obj) { obj.scorumpower = op.scorumpower; });
929 auto delta = delegation.scorumpower - op.scorumpower;
931 if (op.scorumpower.amount > 0)
933 FC_ASSERT(delta >= min_update,
934 "Scorum Power decrease is not enough of a difference. min_update: ${min}",
935 (
"min", min_update));
936 FC_ASSERT(op.scorumpower >= min_delegation,
937 "Delegation must be removed or leave minimum delegation amount of ${v}",
938 (
"v", min_delegation));
942 FC_ASSERT(delegation.scorumpower.amount > 0,
943 "Delegation would set scorumpower to zero, but it is already zero");
946 sp_delegation_service.create_expiration(
948 delegation.min_delegation_time));
950 account_service.decrease_received_scorumpower(delegatee, delta);
952 if (op.scorumpower.amount > 0)
954 sp_delegation_service.update(
955 delegation, [&](scorumpower_delegation_object& obj) { obj.scorumpower = op.scorumpower; });
959 sp_delegation_service.remove(delegation);
965 void atomicswap_initiate_evaluator::do_apply(
const atomicswap_initiate_operation& op)
967 atomicswap_service_i& atomicswap_service = db().atomicswap_service();
968 account_service_i& account_service = db().account_service();
970 account_service.check_account_existence(op.owner);
971 account_service.check_account_existence(op.recipient);
973 const auto&
owner = account_service.get_account(op.owner);
974 const auto& recipient = account_service.get_account(op.recipient);
976 optional<std::string> metadata;
977 if (!op.metadata.empty())
979 metadata = op.metadata;
985 atomicswap_service.create_contract(atomicswap_contract_initiator,
owner, recipient, op.amount, op.secret_hash,
989 atomicswap_service.create_contract(atomicswap_contract_participant,
owner, recipient, op.amount, op.secret_hash,
993 FC_ASSERT(
false,
"Invalid operation type.");
997 void atomicswap_redeem_evaluator::do_apply(
const atomicswap_redeem_operation& op)
999 atomicswap_service_i& atomicswap_service = db().atomicswap_service();
1000 account_service_i& account_service = db().account_service();
1002 account_service.check_account_existence(op.from);
1003 account_service.check_account_existence(op.to);
1005 const auto& from = account_service.get_account(op.from);
1006 const auto& to = account_service.get_account(op.to);
1010 const auto& contract = atomicswap_service.get_contract(from, to, secret_hash);
1012 atomicswap_service.redeem_contract(contract, op.secret);
1015 void atomicswap_refund_evaluator::do_apply(
const atomicswap_refund_operation& op)
1017 atomicswap_service_i& atomicswap_service = db().atomicswap_service();
1018 account_service_i& account_service = db().account_service();
1020 account_service.check_account_existence(op.participant);
1021 account_service.check_account_existence(op.initiator);
1023 const auto& from = account_service.get_account(op.participant);
1024 const auto& to = account_service.get_account(op.initiator);
1026 const auto& contract = atomicswap_service.get_contract(from, to, op.secret_hash);
1028 FC_ASSERT(contract.type != atomicswap_contract_initiator,
1029 "Can't refund initiator contract. It is locked on ${h} hours.",
1032 atomicswap_service.refund_contract(contract);
#define SCORUM_OWNER_AUTH_RECOVERY_PERIOD
#define SCORUM_CREATE_ACCOUNT_WITH_SCORUM_MODIFIER
#define SCORUM_ATOMICSWAP_INITIATOR_REFUND_LOCK_SECS
#define SCORUM_MAX_COMMENT_DEPTH
#define SCORUM_MAX_ACCOUNT_WITNESS_VOTES
#define SCORUM_OWNER_UPDATE_LIMIT
#define SCORUM_CASHOUT_WINDOW_SECONDS
#define SCORUM_MIN_ROOT_COMMENT_INTERVAL
#define SCORUM_MIN_REPLY_INTERVAL
#define SCORUM_MIN_DELEGATE_VESTING_SHARES_MODIFIER
#define SCORUM_CREATE_ACCOUNT_DELEGATION_RATIO
oid< comment_object > comment_id_type
void validate_permlink_0_1(const std::string &permlink)
std::string get_secret_hash(const std::string &secret_hex)
fc::fixed_string_16 account_name_type
std::string wstring_to_utf8(const std::wstring &str)
std::wstring utf8_to_wstring(const std::string &str)
virtual const account_object & get_account(const account_name_type &) const =0
virtual void update(const modifier_type &modifier)=0
bool operator()(const fc::shared_string &a, const std::string &b)