diff --git a/libraries/protocol/get_config.cpp b/libraries/protocol/get_config.cpp index 3d9ffeae2c..6c117c37d7 100644 --- a/libraries/protocol/get_config.cpp +++ b/libraries/protocol/get_config.cpp @@ -20,6 +20,7 @@ fc::variant_object get_config() result[ "STEEM_ENABLE_SMT" ] = true; result["SMT_VESTING_WITHDRAW_INTERVAL_SECONDS"] = SMT_VESTING_WITHDRAW_INTERVAL_SECONDS; result["SMT_UPVOTE_LOCKOUT"] = SMT_UPVOTE_LOCKOUT; + result["SMT_MAX_VOTABLE_ASSETS"] = SMT_MAX_VOTABLE_ASSETS; #else result[ "STEEM_ENABLE_SMT" ] = false; #endif diff --git a/libraries/protocol/include/steem/protocol/config.hpp b/libraries/protocol/include/steem/protocol/config.hpp index 48cfc5d5df..c83b2de178 100644 --- a/libraries/protocol/include/steem/protocol/config.hpp +++ b/libraries/protocol/include/steem/protocol/config.hpp @@ -277,7 +277,9 @@ #ifdef STEEM_ENABLE_SMT +#define SMT_MAX_VOTABLE_ASSETS 2 #define SMT_VESTING_WITHDRAW_INTERVAL_SECONDS (60*60*24*7) /// 1 week per interval #define SMT_UPVOTE_LOCKOUT (60*60*12) /// 12 hours -#endif +#endif /// STEEM_ENABLE_SMT + diff --git a/libraries/protocol/include/steem/protocol/steem_operations.hpp b/libraries/protocol/include/steem/protocol/steem_operations.hpp index 5fdd1b9c57..7f1fa9963e 100644 --- a/libraries/protocol/include/steem/protocol/steem_operations.hpp +++ b/libraries/protocol/include/steem/protocol/steem_operations.hpp @@ -101,6 +101,10 @@ namespace steem { namespace protocol { #ifdef STEEM_ENABLE_SMT struct votable_asset_info_v1 { + votable_asset_info_v1() = default; + votable_asset_info_v1(const share_type& max_payout, bool allow_rewards) : + max_accepted_payout(max_payout), allow_curation_rewards(allow_rewards) {} + share_type max_accepted_payout = 0; bool allow_curation_rewards = false; }; @@ -113,6 +117,54 @@ namespace steem { namespace protocol { */ struct allowed_vote_assets { + /// Helper method to simplify construction of votable_asset_info. + void add_votable_asset(const asset_symbol_type& symbol, const share_type& max_accepted_payout, + bool allow_curation_rewards) + { + votable_asset_info info(votable_asset_info_v1(max_accepted_payout, allow_curation_rewards)); + votable_assets[symbol] = std::move(info); + } + + /** Allows to check if given symbol is allowed votable asset. + * @param symbol - asset symbol to be check against votable feature + * @param max_accepted_payout - optional output parameter which allows to take `max_accepted_payout` + * configured for given asset + * @param allow_curation_rewards - optional output parameter which allows to take `allow_curation_rewards` + * specified for given votable asset. + * @returns true if given asset is allowed votable asset for given comment. + */ + bool is_allowed(const asset_symbol_type& symbol, share_type* max_accepted_payout = nullptr, + bool* allow_curation_rewards = nullptr) const + { + auto foundI = votable_assets.find(symbol); + if(foundI == votable_assets.end()) + { + if(max_accepted_payout != nullptr) + *max_accepted_payout = 0; + if(allow_curation_rewards != nullptr) + *allow_curation_rewards = false; + return false; + } + + if(max_accepted_payout != nullptr) + *max_accepted_payout = foundI->second.get().max_accepted_payout; + if(allow_curation_rewards != nullptr) + *allow_curation_rewards = foundI->second.get().allow_curation_rewards; + + return true; + } + + /** Part of `comment_option_operation` validation process, to be called when allowed_vote_assets object + * has been added as comment option extension. + * @throws fc::assert_exception on failure. + */ + void validate() const + { + FC_ASSERT(votable_assets.size() <= SMT_MAX_VOTABLE_ASSETS, "Too much votable assets specified"); + FC_ASSERT(is_allowed(STEEM_SYMBOL) == false, + "STEEM can not be explicitly specified as one of allowed_vote_assets"); + } + flat_map< asset_symbol_type, votable_asset_info > votable_assets; }; #endif /// STEEM_ENABLE_SMT diff --git a/libraries/protocol/steem_operations.cpp b/libraries/protocol/steem_operations.cpp index 85c7b727ad..47efd9f9cd 100644 --- a/libraries/protocol/steem_operations.cpp +++ b/libraries/protocol/steem_operations.cpp @@ -88,7 +88,7 @@ namespace steem { namespace protocol { #ifdef STEEM_ENABLE_SMT void operator()( const allowed_vote_assets& va) const { - FC_TODO("To be implemented suppport for allowed_vote_assets"); + va.validate(); } #endif void operator()( const comment_payout_beneficiaries& cpb ) const diff --git a/tests/db_fixture/database_fixture.cpp b/tests/db_fixture/database_fixture.cpp index ac2cbe15b7..3c081fe313 100644 --- a/tests/db_fixture/database_fixture.cpp +++ b/tests/db_fixture/database_fixture.cpp @@ -596,11 +596,11 @@ smt_database_fixture::~smt_database_fixture() } -asset_symbol_type smt_database_fixture::create_smt( signed_transaction& tx, const string& account_name, const fc::ecc::private_key& key, +asset_symbol_type smt_database_fixture::create_smt(const string& account_name, const fc::ecc::private_key& key, uint8_t token_decimal_places ) { smt_create_operation op; - + signed_transaction tx; try { fund( account_name, 10 * 1000 * 1000 ); diff --git a/tests/db_fixture/database_fixture.hpp b/tests/db_fixture/database_fixture.hpp index 99887f5c08..8aa325402c 100644 --- a/tests/db_fixture/database_fixture.hpp +++ b/tests/db_fixture/database_fixture.hpp @@ -254,7 +254,7 @@ struct smt_database_fixture : public clean_database_fixture smt_database_fixture(); virtual ~smt_database_fixture(); - asset_symbol_type create_smt( signed_transaction& trx, const string& account_name, const fc::ecc::private_key& key, + asset_symbol_type create_smt( const string& account_name, const fc::ecc::private_key& key, uint8_t token_decimal_places ); /// Creates 3 different SMTs for provided control account, one with 0 precision, the other two with the same non-zero precision. diff --git a/tests/tests/smt_tests.cpp b/tests/tests/smt_tests.cpp index a085f71a20..ab9f9d6537 100644 --- a/tests/tests/smt_tests.cpp +++ b/tests/tests/smt_tests.cpp @@ -617,8 +617,7 @@ BOOST_AUTO_TEST_CASE( smt_transfer_validate ) generate_block(); - signed_transaction tx; - asset_symbol_type alice_symbol = create_smt(tx, "alice", alice_private_key, 0); + asset_symbol_type alice_symbol = create_smt("alice", alice_private_key, 0); transfer_operation op; op.from = "alice"; @@ -643,9 +642,8 @@ BOOST_AUTO_TEST_CASE( smt_transfer_apply ) generate_block(); // Create SMT. - signed_transaction tx, ty; - asset_symbol_type alice_symbol = create_smt(tx, "alice", alice_private_key, 0); - asset_symbol_type bob_symbol = create_smt(ty, "bob", bob_private_key, 1); + asset_symbol_type alice_symbol = create_smt("alice", alice_private_key, 0); + asset_symbol_type bob_symbol = create_smt("bob", bob_private_key, 1); // Give some SMT to creators. asset alice_symbol_supply( 100, alice_symbol ); @@ -677,5 +675,88 @@ BOOST_AUTO_TEST_CASE( smt_transfer_apply ) FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE( comment_votable_assers_validate ) +{ + try + { + BOOST_TEST_MESSAGE( "Test Comment Votable Assets Validate" ); + ACTORS((alice)); + + generate_block(); + + std::array smts; + /// Create one more than limit to test negative cases + for(size_t i = 0; i < SMT_MAX_VOTABLE_ASSETS + 1; ++i) + { + asset_symbol_type smt = create_smt("alice", alice_private_key, 0); + smts[i] = std::move(smt); + } + + { + comment_options_operation op; + + op.author = "alice"; + op.permlink = "test"; + + BOOST_TEST_MESSAGE( "--- Testing valid configuration: no votable_assets" ); + allowed_vote_assets ava; + op.extensions.insert( ava ); + op.validate(); + } + + { + comment_options_operation op; + + op.author = "alice"; + op.permlink = "test"; + + BOOST_TEST_MESSAGE( "--- Testing valid configuration of votable_assets" ); + allowed_vote_assets ava; + for(size_t i = 0; i < SMT_MAX_VOTABLE_ASSETS; ++i) + { + const auto& smt = smts[i]; + ava.add_votable_asset(smt, share_type(10 + i), (i & 2) != 0); + } + + op.extensions.insert( ava ); + op.validate(); + } + + { + comment_options_operation op; + + op.author = "alice"; + op.permlink = "test"; + + BOOST_TEST_MESSAGE( "--- Testing invalid configuration of votable_assets - too much assets specified" ); + allowed_vote_assets ava; + for(size_t i = 0; i < smts.size(); ++i) + { + const auto& smt = smts[i]; + ava.add_votable_asset(smt, share_type(20 + i), (i & 2) != 0); + } + + op.extensions.insert( ava ); + STEEM_REQUIRE_THROW( op.validate(), fc::assert_exception ); + } + + { + comment_options_operation op; + + op.author = "alice"; + op.permlink = "test"; + + BOOST_TEST_MESSAGE( "--- Testing invalid configuration of votable_assets - STEEM added to container" ); + allowed_vote_assets ava; + const auto& smt = smts.front(); + ava.add_votable_asset(smt, share_type(20), false); + ava.add_votable_asset(STEEM_SYMBOL, share_type(20), true); + op.extensions.insert( ava ); + STEEM_REQUIRE_THROW( op.validate(), fc::assert_exception ); + } + } + FC_LOG_AND_RETHROW() +} + BOOST_AUTO_TEST_SUITE_END() #endif