diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 8443ec102e..5f2a4bf020 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -3090,6 +3090,7 @@ namespace golos { namespace chain { _my->_evaluator_registry.register_evaluator(); _my->_evaluator_registry.register_evaluator(); _my->_evaluator_registry.register_evaluator(); + _my->_evaluator_registry.register_evaluator(); _my->_evaluator_registry.register_evaluator(); _my->_evaluator_registry.register_evaluator(); _my->_evaluator_registry.register_evaluator(); diff --git a/libraries/chain/hardfork.d/0_21.hf b/libraries/chain/hardfork.d/0_21.hf index 2be5d222b5..ebd684a256 100644 --- a/libraries/chain/hardfork.d/0_21.hf +++ b/libraries/chain/hardfork.d/0_21.hf @@ -5,6 +5,7 @@ #define STEEMIT_HARDFORK_0_21__1009 (STEEMIT_HARDFORK_0_21) // Remove limit on min curation percent witness prop #define STEEMIT_HARDFORK_0_21__1010 (STEEMIT_HARDFORK_0_21) // Fix post bandwidth #define STEEMIT_HARDFORK_0_21__1045 (STEEMIT_HARDFORK_0_21) // Two payout strategies for vesting delegations with interest +#define STEEMIT_HARDFORK_0_21__1014 (STEEMIT_HARDFORK_0_21) // Curator remain rate #ifdef STEEMIT_BUILD_TESTNET #define STEEMIT_HARDFORK_0_21_TIME 1547787600 // 18 jan 2019 12:00:00 MSK diff --git a/libraries/chain/include/golos/chain/comment_object.hpp b/libraries/chain/include/golos/chain/comment_object.hpp index c7b0cbb856..eeafe517ad 100644 --- a/libraries/chain/include/golos/chain/comment_object.hpp +++ b/libraries/chain/include/golos/chain/comment_object.hpp @@ -147,6 +147,8 @@ namespace golos { int8_t num_changes = 0; ///< Count of vote changes (while consensus). If = -1 then related post is archived & vote no more needed for consensus bip::vector> delegator_vote_interest_rates; + + uint16_t curator_remain_rate = GOLOS_MAX_CURATOR_REMAIN_RATE; }; struct by_comment_voter; diff --git a/libraries/chain/include/golos/chain/steem_evaluator.hpp b/libraries/chain/include/golos/chain/steem_evaluator.hpp index 89d24dfe89..7ddc1951dd 100644 --- a/libraries/chain/include/golos/chain/steem_evaluator.hpp +++ b/libraries/chain/include/golos/chain/steem_evaluator.hpp @@ -55,6 +55,7 @@ namespace golos { namespace chain { DEFINE_EVALUATOR(break_free_referral) DEFINE_EVALUATOR(delegate_vesting_shares_with_interest) DEFINE_EVALUATOR(reject_vesting_shares_delegation) + DEFINE_EVALUATOR(vote_options) class proposal_create_evaluator: public evaluator_impl { public: diff --git a/libraries/chain/steem_evaluator.cpp b/libraries/chain/steem_evaluator.cpp index 0e0c7ebbc9..7cf4a503f0 100644 --- a/libraries/chain/steem_evaluator.cpp +++ b/libraries/chain/steem_evaluator.cpp @@ -1786,6 +1786,41 @@ namespace golos { namespace chain { } FC_CAPTURE_AND_RETHROW((o)) } + struct vote_options_extension_visitor { + vote_options_extension_visitor(const comment_vote_object& vote, database& db) + : _vote(vote), _db(db) { + } + + const comment_vote_object& _vote; + database& _db; + + using result_type = void; + + void operator()(const vote_curator_remain_rate& vcrr) const { + _db.modify(_vote, [&](comment_vote_object& c) { + c.curator_remain_rate = vcrr.rate; + }); + } + }; + + void vote_options_evaluator::do_apply(const vote_options_operation& o) { + ASSERT_REQ_HF(STEEMIT_HARDFORK_0_21__1014, "vote_options_operation"); + + const auto& comment = _db.get_comment(o.author, o.permlink); + const auto& voter = _db.get_account(o.voter); + + const auto& vote_idx = _db.get_index(); + const auto vote_itr = vote_idx.find(std::make_tuple(comment.id, voter.id)); + + if (vote_itr == vote_idx.end()) { + GOLOS_THROW_MISSING_OBJECT("comment_vote_object", fc::mutable_variant_object()("voter",o.voter)("author",o.author)("permlink",o.permlink)); + } + + for (auto& e : o.extensions) { + e.visit(vote_options_extension_visitor(*vote_itr, _db)); + } + } + void custom_evaluator::do_apply(const custom_operation &o) { } diff --git a/libraries/protocol/include/golos/protocol/config.hpp b/libraries/protocol/include/golos/protocol/config.hpp index 395321b673..6b94c8e1fb 100644 --- a/libraries/protocol/include/golos/protocol/config.hpp +++ b/libraries/protocol/include/golos/protocol/config.hpp @@ -167,6 +167,8 @@ #define STEEMIT_DEF_CURATION_PERCENT (25*STEEMIT_1_PERCENT) // 25% #define STEEMIT_MAX_CURATION_PERCENT STEEMIT_100_PERCENT +#define GOLOS_MAX_CURATOR_REMAIN_RATE (100*STEEMIT_1_PERCENT) + #define STEEMIT_ACTIVE_CHALLENGE_FEE asset(2000, STEEM_SYMBOL) #define STEEMIT_OWNER_CHALLENGE_FEE asset(30000, STEEM_SYMBOL) #define STEEMIT_ACTIVE_CHALLENGE_COOLDOWN fc::days(1) @@ -410,6 +412,8 @@ #define STEEMIT_DEF_CURATION_PERCENT (25*STEEMIT_1_PERCENT) // 25% #define STEEMIT_MAX_CURATION_PERCENT STEEMIT_100_PERCENT +#define GOLOS_MAX_CURATOR_REMAIN_RATE (100*STEEMIT_1_PERCENT) + #define STEEMIT_ACTIVE_CHALLENGE_FEE asset(2000, STEEM_SYMBOL) #define STEEMIT_OWNER_CHALLENGE_FEE asset(30000, STEEM_SYMBOL) #define STEEMIT_ACTIVE_CHALLENGE_COOLDOWN fc::days(1) diff --git a/libraries/protocol/include/golos/protocol/operations.hpp b/libraries/protocol/include/golos/protocol/operations.hpp index a7b2e8e54b..ddf5fa41a9 100644 --- a/libraries/protocol/include/golos/protocol/operations.hpp +++ b/libraries/protocol/include/golos/protocol/operations.hpp @@ -70,6 +70,7 @@ namespace golos { namespace protocol { break_free_referral_operation, delegate_vesting_shares_with_interest_operation, reject_vesting_shares_delegation_operation, + vote_options_operation, worker_proposal_operation, worker_proposal_delete_operation, worker_techspec_operation, diff --git a/libraries/protocol/include/golos/protocol/steem_operations.hpp b/libraries/protocol/include/golos/protocol/steem_operations.hpp index 20cef98702..cc77391e2c 100644 --- a/libraries/protocol/include/golos/protocol/steem_operations.hpp +++ b/libraries/protocol/include/golos/protocol/steem_operations.hpp @@ -265,6 +265,38 @@ namespace golos { namespace protocol { } }; + struct vote_curator_remain_rate { + vote_curator_remain_rate() { + } + + vote_curator_remain_rate(uint16_t r) + : rate(r) { + } + + uint16_t rate = GOLOS_MAX_CURATOR_REMAIN_RATE; + + void validate() const; + }; + + using vote_options_extension = static_variant < + vote_curator_remain_rate + >; + + using vote_options_extensions_type = flat_set; + + struct vote_options_operation : public base_operation { + account_name_type voter; + account_name_type author; + string permlink; + vote_options_extensions_type extensions; + + void validate() const; + + void get_required_posting_authorities(flat_set &a) const { + a.insert(voter); + } + }; + /** * @ingroup operations @@ -1476,6 +1508,11 @@ FC_REFLECT((golos::protocol::account_witness_vote_operation), (account)(witness) FC_REFLECT((golos::protocol::account_witness_proxy_operation), (account)(proxy)) FC_REFLECT((golos::protocol::comment_operation), (parent_author)(parent_permlink)(author)(permlink)(title)(body)(json_metadata)) FC_REFLECT((golos::protocol::vote_operation), (voter)(author)(permlink)(weight)) + +FC_REFLECT((golos::protocol::vote_curator_remain_rate), (rate)); +FC_REFLECT_TYPENAME((golos::protocol::vote_options_extension)); +FC_REFLECT((golos::protocol::vote_options_operation), (voter)(author)(permlink)(extensions)) + FC_REFLECT((golos::protocol::custom_operation), (required_auths)(id)(data)) FC_REFLECT((golos::protocol::custom_json_operation), (required_auths)(required_posting_auths)(id)(json)) FC_REFLECT((golos::protocol::custom_binary_operation), (required_owner_auths)(required_active_auths)(required_posting_auths)(required_auths)(id)(data)) diff --git a/libraries/protocol/steem_operations.cpp b/libraries/protocol/steem_operations.cpp index a9b66ed265..e4cfab6d5e 100644 --- a/libraries/protocol/steem_operations.cpp +++ b/libraries/protocol/steem_operations.cpp @@ -212,6 +212,32 @@ namespace golos { namespace protocol { GOLOS_CHECK_PARAM(permlink, validate_permlink(permlink)); } + struct vote_options_extension_validate_visitor { + vote_options_extension_validate_visitor() { + } + + using result_type = void; + + void operator()(const vote_curator_remain_rate& vcrr) const { + vcrr.validate(); + } + }; + + void vote_curator_remain_rate::validate() const { + GOLOS_CHECK_PARAM(rate, { + GOLOS_CHECK_VALUE_LE(rate, GOLOS_MAX_CURATOR_REMAIN_RATE); + }); + } + + void vote_options_operation::validate() const { + GOLOS_CHECK_PARAM(voter, validate_account_name(voter)); + GOLOS_CHECK_PARAM(author, validate_account_name(author)); + GOLOS_CHECK_PARAM(permlink, validate_permlink(permlink)); + for (auto& e : extensions) { + e.visit(vote_options_extension_validate_visitor()); + } + } + void transfer_operation::validate() const { try { GOLOS_CHECK_PARAM(from, validate_account_name(from)); diff --git a/plugins/account_history/plugin.cpp b/plugins/account_history/plugin.cpp index 2f40f5e1b4..13d21a8f33 100644 --- a/plugins/account_history/plugin.cpp +++ b/plugins/account_history/plugin.cpp @@ -328,6 +328,10 @@ if (options.count(name)) { \ insert_pair(op.voter, op.author); } + void operator()(const vote_options_operation& op) { + insert_pair(op.voter, op.author); + } + void operator()(const author_reward_operation& op) { insert_receiver(op.author); } diff --git a/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_operations.hpp b/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_operations.hpp index 46b7c8f9be..9a076c860f 100644 --- a/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_operations.hpp +++ b/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_operations.hpp @@ -17,6 +17,7 @@ namespace mongo_db { operation_writer(); result_type operator()(const vote_operation& op); + result_type operator()(const vote_options_operation& op); result_type operator()(const comment_operation& op); result_type operator()(const transfer_operation& op); result_type operator()(const transfer_to_vesting_operation& op); diff --git a/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_state.hpp b/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_state.hpp index 5e1a2a0480..e51106e32d 100644 --- a/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_state.hpp +++ b/plugins/mongo_db/include/golos/plugins/mongo_db/mongo_db_state.hpp @@ -23,6 +23,7 @@ namespace mongo_db { state_writer(db_map& bmi_to_add, const signed_block& block); result_type operator()(const vote_operation& op); + result_type operator()(const vote_options_operation& op); result_type operator()(const comment_operation& op); result_type operator()(const transfer_operation& op); result_type operator()(const transfer_to_vesting_operation& op); diff --git a/plugins/mongo_db/mongo_db_operations.cpp b/plugins/mongo_db/mongo_db_operations.cpp index 5d746846d6..21e85a88fa 100644 --- a/plugins/mongo_db/mongo_db_operations.cpp +++ b/plugins/mongo_db/mongo_db_operations.cpp @@ -77,6 +77,12 @@ namespace mongo_db { return body; } + auto operation_writer::operator()(const vote_options_operation& op) -> result_type { + result_type body; + + return body; + } + auto operation_writer::operator()(const comment_operation& op) -> result_type { result_type body; diff --git a/plugins/mongo_db/mongo_db_state.cpp b/plugins/mongo_db/mongo_db_state.cpp index 845be0df21..dc077de5d2 100644 --- a/plugins/mongo_db/mongo_db_state.cpp +++ b/plugins/mongo_db/mongo_db_state.cpp @@ -789,6 +789,10 @@ namespace mongo_db { } } + auto state_writer::operator()(const vote_options_operation& op) -> result_type { + + } + auto state_writer::operator()(const comment_operation& op) -> result_type { format_comment(op.author, op.permlink); format_account(op.author);