Merged beatrice into 5050

This commit is contained in:
Prabhjot Singh 2019-07-30 11:43:31 -04:00 committed by gladcow
parent 75f16752d2
commit 26786d33a9
21 changed files with 1244 additions and 468 deletions

2
.gitignore vendored
View file

@ -43,4 +43,4 @@ object_database/*
*.pyo
.vscode
.DS_Store
.idea
.idea

View file

@ -681,6 +681,20 @@ namespace graphene { namespace app {
crypto_api::crypto_api(){};
blind_signature crypto_api::blind_sign( const extended_private_key_type& key, const blinded_hash& hash, int i )
{
return fc::ecc::extended_private_key( key ).blind_sign( hash, i );
}
signature_type crypto_api::unblind_signature( const extended_private_key_type& key,
const extended_public_key_type& bob,
const blind_signature& sig,
const fc::sha256& hash,
int i )
{
return fc::ecc::extended_private_key( key ).unblind_signature( extended_public_key( bob ), sig, hash, i );
}
commitment_type crypto_api::blind( const blind_factor_type& blind, uint64_t value )
{
return fc::ecc::blind( blind, value );

View file

@ -162,11 +162,10 @@ namespace detail {
{
// t.me/peerplays #seednodes
vector<string> seeds = {
// BEATRICE SEEDS:
// "ppy-beatrice-seed.blckchnd.com:6666",
// "159.69.223.206:7777",
// "51.38.237.243:9666",
// "pbsa-beatrice.blockchainprojectsbv.com:9195"
"ppy-beatrice-seed.blckchnd.com:6666",
"159.69.223.206:7777",
"51.38.237.243:9666",
"pbsa-beatrice.blockchainprojectsbv.com:9195"
// OTTHER SEEDS:
// "seed.ppy.blckchnd.com:6112", // blckchnd
// "ppy.esteem.ws:7777", // good-karma

View file

@ -113,7 +113,6 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<bet_object> get_unmatched_bets_for_bettor(betting_market_id_type, account_id_type) const;
vector<bet_object> get_all_unmatched_bets_for_bettor(account_id_type) const;
// Lottery Assets
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
unsigned limit = 100,

View file

@ -737,7 +737,7 @@ FC_API(graphene::app::database_api,
(list_betting_markets)
(get_unmatched_bets_for_bettor)
(get_all_unmatched_bets_for_bettor)
// Sweeps
(get_lotteries)
(get_account_lotteries)

View file

@ -26,7 +26,7 @@
#include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/database.hpp>
#include <boost/integer/common_factor_rt.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>

View file

@ -25,7 +25,7 @@
#define DEFAULT_LOGGER "betting"
#include <graphene/chain/betting_market_object.hpp>
#include <graphene/chain/database.hpp>
#include <boost/integer/common_factor_rt.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
@ -101,7 +101,7 @@ share_type bet_object::get_exact_matching_amount() const
/* static */ std::pair<share_type, share_type> bet_object::get_ratio(bet_multiplier_type backer_multiplier)
{
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
return std::make_pair(GRAPHENE_BETTING_ODDS_PRECISION / gcd, (backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd);
}
@ -112,13 +112,13 @@ std::pair<share_type, share_type> bet_object::get_ratio() const
share_type bet_object::get_minimum_matchable_amount() const
{
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
return (back_or_lay == bet_type::back ? GRAPHENE_BETTING_ODDS_PRECISION : backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd;
}
share_type bet_object::get_minimum_matching_amount() const
{
share_type gcd = boost::integer::gcd(GRAPHENE_BETTING_ODDS_PRECISION, static_cast<int32_t>(backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION));
share_type gcd = boost::math::gcd<bet_multiplier_type>(GRAPHENE_BETTING_ODDS_PRECISION, backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION);
return (back_or_lay == bet_type::lay ? GRAPHENE_BETTING_ODDS_PRECISION : backer_multiplier - GRAPHENE_BETTING_ODDS_PRECISION) / gcd;
}

View file

@ -35,8 +35,7 @@ namespace graphene { namespace chain {
void_result do_evaluate( const asset_create_operation& o );
object_id_type do_apply( const asset_create_operation& o );
// copied from bitshares. (https://github.com/bitshares/bitshares-core/issues/429)
/** override the default behavior defined by generic_evalautor which is to
* post the fee to fee_paying_account_stats.pending_fees
*/

View file

@ -27,6 +27,7 @@
#include <graphene/db/object.hpp>
#include <graphene/db/generic_index.hpp>
#include <boost/multi_index/composite_key.hpp>
namespace graphene { namespace chain {

View file

@ -28,6 +28,7 @@
#include <graphene/db/generic_index.hpp>
#include <graphene/chain/protocol/event.hpp>
#include <boost/multi_index/composite_key.hpp>
namespace graphene { namespace chain {
class event_object;

View file

@ -30,7 +30,7 @@
namespace graphene { namespace chain { struct fee_schedule; } }
namespace graphene { namespace chain {
struct parameter_extension
struct bet_parameter_extension
{
optional< bet_multiplier_type > min_bet_multiplier;
optional< bet_multiplier_type > max_bet_multiplier;
@ -44,7 +44,9 @@ namespace graphene { namespace chain {
asset_id_type sweeps_distribution_asset = SWEEPS_DEFAULT_DISTRIBUTION_ASSET;
account_id_type sweeps_vesting_accumulator_account = SWEEPS_ACCUMULATOR_ACCOUNT;
};
typedef static_variant<void_t,sweeps_parameters_extension> parameter_extension;
typedef static_variant<void_t,sweeps_parameters_extension,bet_parameter_extension> parameter_extension;
struct chain_parameters
{
/** using a smart ref breaks the circular dependency created between operations and the fee schedule */
@ -120,7 +122,7 @@ namespace graphene { namespace chain {
} } // graphene::chain
FC_REFLECT( graphene::chain::parameter_extension,
FC_REFLECT( graphene::chain::bet_parameter_extension,
(min_bet_multiplier)
(max_bet_multiplier)
(betting_rake_fee_percentage)

View file

@ -0,0 +1,28 @@
file(GLOB headers "include/graphene/utilities/*.hpp")
set(sources deterministic_openssl_rand.cpp
${headers})
add_library( deterministic_openssl_rand
${sources}
${HEADERS} )
target_link_libraries( deterministic_openssl_rand fc )
target_include_directories( deterministic_openssl_rand
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../blockchain/include"
)
if (USE_PCH)
set_target_properties(deterministic_openssl_rand PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
cotire(deterministic_openssl_rand)
endif(USE_PCH)
install( TARGETS
deterministic_openssl_rand
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install( FILES ${headers} DESTINATION "include/graphene/deterministic_openssl_rand" )

View file

@ -2063,6 +2063,5 @@ FC_API( graphene::wallet::wallet_api,
(get_binned_order_book)
(get_matched_bets_for_bettor)
(get_all_matched_bets_for_bettor)
(buy_ticket)
)

View file

@ -128,6 +128,17 @@ int main(int argc, char** argv) {
std::cout << app_options << "\n";
return 0;
}
if (options.count("version"))
{
std::string witness_version(graphene::utilities::git_revision_description);
const size_t pos = witness_version.find('/');
if( pos != std::string::npos && witness_version.size() > pos )
witness_version = witness_version.substr( pos + 1 );
std::cerr << "Version: " << witness_version << "\n";
std::cerr << "Git Revision: " << graphene::utilities::git_revision_sha << "\n";
std::cerr << "Built: " << __DATE__ " at " __TIME__ << "\n";
return 0;
}
fc::path data_dir;
if( options.count("data-dir") )
@ -193,3 +204,109 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
}
// logging config is too complicated to be parsed by boost::program_options,
// so we do it by hand
//
// Currently, you can only specify the filenames and logging levels, which
// are all most users would want to change. At a later time, options can
// be added to control rotation intervals, compression, and other seldom-
// used features
void write_default_logging_config_to_stream(std::ostream& out)
{
out << "# declare an appender named \"stderr\" that writes messages to the console\n"
"[log.console_appender.stderr]\n"
"stream=std_error\n\n"
"# declare an appender named \"p2p\" that writes messages to p2p.log\n"
"[log.file_appender.p2p]\n"
"filename=logs/p2p/p2p.log\n"
"# filename can be absolute or relative to this config file\n\n"
"# route any messages logged to the default logger to the \"stderr\" logger we\n"
"# declared above, if they are info level are higher\n"
"[logger.default]\n"
"level=info\n"
"appenders=stderr\n\n"
"# route messages sent to the \"p2p\" logger to the p2p appender declared above\n"
"[logger.p2p]\n"
"level=info\n"
"appenders=p2p\n\n";
}
fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::path& config_ini_filename)
{
try
{
fc::logging_config logging_config;
bool found_logging_config = false;
boost::property_tree::ptree config_ini_tree;
boost::property_tree::ini_parser::read_ini(config_ini_filename.preferred_string().c_str(), config_ini_tree);
for (const auto& section : config_ini_tree)
{
const std::string& section_name = section.first;
const boost::property_tree::ptree& section_tree = section.second;
const std::string console_appender_section_prefix = "log.console_appender.";
const std::string file_appender_section_prefix = "log.file_appender.";
const std::string logger_section_prefix = "logger.";
if (boost::starts_with(section_name, console_appender_section_prefix))
{
std::string console_appender_name = section_name.substr(console_appender_section_prefix.length());
std::string stream_name = section_tree.get<std::string>("stream");
// construct a default console appender config here
// stdout/stderr will be taken from ini file, everything else hard-coded here
fc::console_appender::config console_appender_config;
console_appender_config.level_colors.emplace_back(
fc::console_appender::level_color(fc::log_level::debug,
fc::console_appender::color::green));
console_appender_config.level_colors.emplace_back(
fc::console_appender::level_color(fc::log_level::warn,
fc::console_appender::color::brown));
console_appender_config.level_colors.emplace_back(
fc::console_appender::level_color(fc::log_level::error,
fc::console_appender::color::cyan));
console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>();
logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config)));
found_logging_config = true;
}
else if (boost::starts_with(section_name, file_appender_section_prefix))
{
std::string file_appender_name = section_name.substr(file_appender_section_prefix.length());
fc::path file_name = section_tree.get<std::string>("filename");
if (file_name.is_relative())
file_name = fc::absolute(config_ini_filename).parent_path() / file_name;
// construct a default file appender config here
// filename will be taken from ini file, everything else hard-coded here
fc::file_appender::config file_appender_config;
file_appender_config.filename = file_name;
file_appender_config.flush = true;
file_appender_config.rotate = true;
file_appender_config.rotation_interval = fc::hours(1);
file_appender_config.rotation_limit = fc::days(1);
logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config)));
found_logging_config = true;
}
else if (boost::starts_with(section_name, logger_section_prefix))
{
std::string logger_name = section_name.substr(logger_section_prefix.length());
std::string level_string = section_tree.get<std::string>("level");
std::string appenders_string = section_tree.get<std::string>("appenders");
fc::logger_config logger_config(logger_name);
logger_config.level = fc::variant(level_string).as<fc::log_level>();
boost::split(logger_config.appenders, appenders_string,
boost::is_any_of(" ,"),
boost::token_compress_on);
logging_config.loggers.push_back(logger_config);
found_logging_config = true;
}
}
if (found_logging_config)
return logging_config;
else
return fc::optional<fc::logging_config>();
}
}

View file

@ -377,41 +377,49 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
// place lay bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
// these bets will get rounded down, actual amounts are 99, 99, 91, 99, and 67
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
//
// binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
// idump((binned_orders_point_one));
//
// // the binned orders returned should be chosen so that we if we assume those orders are real and we place
// // matching lay orders, we will completely consume the underlying orders and leave no orders on the books
// //
// // for the bets bob placed above, we shoudl get 356 @ 1.6, 99 @ 1.5
// BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_back_bets.size(), 0u);
// BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_lay_bets.size(), 2u);
// for (const graphene::bookie::order_bin& binned_order : binned_orders_point_one.aggregated_lay_bets)
// {
// // compute the matching lay order
// share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, true /* round up */);
// ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
// place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier);
//
// }
//
//
// bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
// while (bet_iter != bet_odds_idx.end() &&
// bet_iter->betting_market_id == capitals_win_market.id)
// {
// idump((*bet_iter));
// ++bet_iter;
// }
//
// BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
//
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10);
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
idump((binned_orders_point_one));
// the binned orders returned should be chosen so that we if we assume those orders are real and we place
// matching lay orders, we will completely consume the underlying orders and leave no orders on the books
//
// for the bets bob placed above, we shoudl get 356 @ 1.6, 99 @ 1.5
BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_back_bets.size(), 0u);
BOOST_CHECK_EQUAL(binned_orders_point_one.aggregated_lay_bets.size(), 2u);
for (const graphene::bookie::order_bin& binned_order : binned_orders_point_one.aggregated_lay_bets)
{
// compute the matching lay order
share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, true /* round up */);
ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier);
ilog("After alice's bet, order book is:");
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
while (bet_iter != bet_odds_idx.end() &&
bet_iter->betting_market_id == capitals_win_market.id)
{
idump((*bet_iter));
++bet_iter;
}
}
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
while (bet_iter != bet_odds_idx.end() &&
bet_iter->betting_market_id == capitals_win_market.id)
{
idump((*bet_iter));
++bet_iter;
}
BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
} FC_LOG_AND_RETHROW()
}
@ -898,43 +906,42 @@ BOOST_AUTO_TEST_CASE(bet_reversal_test)
FC_LOG_AND_RETHROW()
}
//This test case need some analysis and commneting out for the time being
// BOOST_AUTO_TEST_CASE(bet_against_exposure_test)
// {
// // test whether we can bet our entire balance in one direction, have it match, then reverse our bet (while having zero balance)
// try
// {
// generate_blocks(1);
// ACTORS( (alice)(bob) );
// CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
//
// transfer(account_id_type(), alice_id, asset(10000000));
// transfer(account_id_type(), bob_id, asset(10000000));
// int64_t alice_expected_balance = 10000000;
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
// int64_t bob_expected_balance = 10000000;
// BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
//
// // back with alice's entire balance
// place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
// alice_expected_balance -= 10000000;
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
//
// // lay with bob's entire balance, which fully matches bob's bet
// place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
// bob_expected_balance -= 10000000;
// BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
//
// // reverse the bet
// place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(20000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
//
// // try to re-reverse it, but go too far
// BOOST_CHECK_THROW( place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(30000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION), fc::exception);
// BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
// }
// FC_LOG_AND_RETHROW()
// }
BOOST_AUTO_TEST_CASE(bet_against_exposure_test)
{
// test whether we can bet our entire balance in one direction, have it match, then reverse our bet (while having zero balance)
try
{
generate_blocks(1);
ACTORS( (alice)(bob) );
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
transfer(account_id_type(), alice_id, asset(10000000));
transfer(account_id_type(), bob_id, asset(10000000));
int64_t alice_expected_balance = 10000000;
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
int64_t bob_expected_balance = 10000000;
BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
// back with alice's entire balance
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
alice_expected_balance -= 10000000;
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
// lay with bob's entire balance, which fully matches bob's bet
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(10000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
bob_expected_balance -= 10000000;
BOOST_REQUIRE_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance);
// reverse the bet
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(20000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
// try to re-reverse it, but go too far
BOOST_CHECK_THROW( place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(30000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION), fc::exception);
BOOST_REQUIRE_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance);
}
FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(persistent_objects_test)
{
@ -1527,18 +1534,17 @@ BOOST_AUTO_TEST_CASE(sport_delete_test_not_proposal)
} FC_LOG_AND_RETHROW()
}
// No need for the below test as it shows in failed test case list. Should enable when sports related changes applied
// BOOST_AUTO_TEST_CASE(sport_delete_test_not_existed_sport)
// {
// try
// {
// CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
//
// delete_sport(ice_hockey.id);
//
// BOOST_CHECK_THROW(delete_sport(ice_hockey.id), fc::exception);
// } FC_LOG_AND_RETHROW()
// }
BOOST_AUTO_TEST_CASE(sport_delete_test_not_existed_sport)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
delete_sport(ice_hockey.id);
BOOST_CHECK_THROW(delete_sport(ice_hockey.id), fc::exception);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_group_update_test)
{
@ -2776,26 +2782,24 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
update_event_group(nhl.id, fc::optional<object_id_type>(), name);
update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>());
update_event_group(nhl.id, sport_id, name);
//Disabling the below 4 TRY_EXPECT_THROW lines to not throw anything beacuse functioning as expected
// trx_state->_is_proposed_trx
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception);
// TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception, "_is_proposed_trx");
TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>(), true), fc::exception, "_is_proposed_trx");
// #! nothing to change
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception);
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception, "nothing to change");
TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional<object_id_type>(), fc::optional<internationalized_string_type>()), fc::exception, "nothing to change");
// #! sport_id must refer to a sport_id_type
sport_id = capitals_win_market.id;
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "sport_id must refer to a sport_id_type");
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "sport_id must refer to a sport_id_type");
// #! invalid sport specified
sport_id = sport_id_type(13);
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
//TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
@ -2938,65 +2942,60 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
// reworked check_transasction for duplicate
// now should not through an exception when there are different events with the same betting_market_group
// and or the same betting_market
// Need to revisit the following test, commeting for time being******
// BOOST_AUTO_TEST_CASE( check_transaction_for_duplicate_reworked_test )
// {
// try
// {
// std::vector<internationalized_string_type> names_vec(104);
//
// // create 104 pattern for first name
// for( char co = 'A'; co <= 'D'; ++co ) {
// for( char ci = 'A'; ci <= 'Z'; ++ci ) {
// std::string first_name = std::to_string(co) + std::to_string(ci);
// std::string second_name = first_name + first_name;
// names_vec.push_back( {{ first_name, second_name }} );
// }
// }
//
// sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id;
//
// event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id;
//
// betting_market_rules_id_type betting_market_rules_id =
// create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id;
//
// for( const auto& name : names_vec )
// {
// proposal_create_operation pcop = proposal_create_operation::committee_proposal(
// db.get_global_properties().parameters,
// db.head_block_time()
// );
// pcop.review_period_seconds.reset();
// pcop.review_period_seconds = db.get_global_properties().parameters.committee_proposal_review_period * 2;
//
// event_create_operation evcop;
// evcop.event_group_id = event_group_id;
// evcop.name = name;
// evcop.season = name;
//
// betting_market_group_create_operation bmgcop;
// bmgcop.description = name;
// bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0);
// bmgcop.rules_id = betting_market_rules_id;
// bmgcop.asset_id = asset_id_type();
//
// betting_market_create_operation bmcop;
// bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1);
// bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) );
//
// pcop.proposed_ops.emplace_back( evcop );
// pcop.proposed_ops.emplace_back( bmgcop );
// pcop.proposed_ops.emplace_back( bmcop );
//
// signed_transaction trx;
// set_expiration( db, trx );
// trx.operations.push_back( pcop );
//
// process_operation_by_witnesses( pcop );
// }
// }FC_LOG_AND_RETHROW()
// }
BOOST_AUTO_TEST_CASE( check_transaction_for_duplicate_reworked_test )
{
std::vector<internationalized_string_type> names_vec(104);
// create 104 pattern for first name
for( char co = 'A'; co <= 'D'; ++co ) {
for( char ci = 'A'; ci <= 'Z'; ++ci ) {
std::string first_name = std::to_string(co) + std::to_string(ci);
std::string second_name = first_name + first_name;
names_vec.push_back( {{ first_name, second_name }} );
}
}
sport_id_type sport_id = create_sport( {{"SN","SPORT_NAME"}} ).id;
event_group_id_type event_group_id = create_event_group( {{"EG", "EVENT_GROUP"}}, sport_id ).id;
betting_market_rules_id_type betting_market_rules_id =
create_betting_market_rules( {{"EN", "Rules"}}, {{"EN", "Some rules"}} ).id;
for( const auto& name : names_vec )
{
proposal_create_operation pcop = proposal_create_operation::committee_proposal(
db.get_global_properties().parameters,
db.head_block_time()
);
pcop.review_period_seconds.reset();
event_create_operation evcop;
evcop.event_group_id = event_group_id;
evcop.name = name;
evcop.season = name;
betting_market_group_create_operation bmgcop;
bmgcop.description = name;
bmgcop.event_id = object_id_type(relative_protocol_ids, 0, 0);
bmgcop.rules_id = betting_market_rules_id;
bmgcop.asset_id = asset_id_type();
betting_market_create_operation bmcop;
bmcop.group_id = object_id_type(relative_protocol_ids, 0, 1);
bmcop.payout_condition.insert( internationalized_string_type::value_type( "CN", "CONDI_NAME" ) );
pcop.proposed_ops.emplace_back( evcop );
pcop.proposed_ops.emplace_back( bmgcop );
pcop.proposed_ops.emplace_back( bmcop );
signed_transaction trx;
set_expiration( db, trx );
trx.operations.push_back( pcop );
process_operation_by_witnesses( pcop );
}
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -89,9 +89,11 @@ database_fixture::database_fixture()
boost::program_options::variables_map options;
// genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
genesis_state.initial_timestamp = time_point_sec( (fc::time_point::now().sec_since_epoch() / GRAPHENE_DEFAULT_BLOCK_INTERVAL) * GRAPHENE_DEFAULT_BLOCK_INTERVAL );
// genesis_state.initial_parameters.witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM;
genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP );
//int back_to_the_past = 0;
//back_to_the_past = 7 * 24 * 60 * 60; // week
//genesis_state.initial_timestamp = time_point_sec( (fc::time_point::now().sec_since_epoch() - back_to_the_past) / GRAPHENE_DEFAULT_BLOCK_INTERVAL * GRAPHENE_DEFAULT_BLOCK_INTERVAL );
genesis_state.initial_parameters.witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM;
genesis_state.initial_active_witnesses = 10;
for( unsigned i = 0; i < genesis_state.initial_active_witnesses; ++i )
@ -713,8 +715,7 @@ const witness_object& database_fixture::create_witness( const account_object& ow
secret_hash_type::encoder enc;
fc::raw::pack(enc, signing_private_key);
fc::raw::pack(enc, secret_hash_type());
op.initial_secret = enc.result();
op.initial_secret = secret_hash_type::hash(enc.result());
trx.operations.push_back(op);
trx.validate();
processed_transaction ptx = db.push_transaction(trx, ~0);

View file

@ -842,7 +842,7 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
sign( trx, get_account("init7" ).active.get_keys().front(),init_account_priv_key);
*/
db.push_transaction(trx);
// BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
}
BOOST_TEST_MESSAGE( "Verifying that the interval didn't change immediately" );
@ -863,12 +863,12 @@ BOOST_FIXTURE_TEST_CASE( change_block_interval, database_fixture )
generate_block(); // get the maintenance skip slots out of the way
BOOST_TEST_MESSAGE( "Verify that the new block interval is 1 second" );
// BOOST_CHECK_EQUAL(db.get_global_properties().parameters.block_interval, 1);
BOOST_CHECK_EQUAL(db.get_global_properties().parameters.block_interval, 1);
past_time = db.head_block_time().sec_since_epoch();
generate_block();
// BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 1);
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 1);
generate_block();
// BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
BOOST_CHECK_EQUAL(db.head_block_time().sec_since_epoch() - past_time, 2);
} FC_LOG_AND_RETHROW() }
BOOST_FIXTURE_TEST_CASE( pop_block_twice, database_fixture )
@ -1087,7 +1087,6 @@ BOOST_FIXTURE_TEST_CASE( rsf_missed_blocks, database_fixture )
// the test written in 2015 should be revised, currently it is not possible to push block to db2
// without skip_witness_signature | skip_witness_schedule_check | skip_authority_check
/*
BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
{
try
@ -1112,9 +1111,7 @@ BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
while( db2.head_block_num() < db.head_block_num() )
{
optional< signed_block > b = db.fetch_block_by_number( db2.head_block_num()+1 );
db2.push_block(*b, database::skip_witness_signature|
database::skip_authority_check|
database::skip_witness_schedule_check);
db2.push_block(*b, database::skip_witness_signature);
}
BOOST_CHECK( db2.get( alice_id ).name == "alice" );
BOOST_CHECK( db2.get( bob_id ).name == "bob" );
@ -1238,7 +1235,6 @@ BOOST_FIXTURE_TEST_CASE( transaction_invalidated_in_cache, database_fixture )
throw;
}
}
*/
BOOST_AUTO_TEST_CASE( genesis_reserve_ids )
{

View file

@ -79,16 +79,17 @@ BOOST_AUTO_TEST_CASE( nonzero_fee_test )
}
}
// fails
// BOOST_AUTO_TEST_CASE(asset_claim_fees_test)
// {
// try
// {
// ACTORS((alice)(bob)(izzy)(jill));
// // Izzy issues asset to Alice
// // Jill issues asset to Bob
// // Alice and Bob trade in the market and pay fees
// // Verify that Izzy and Jill can claim the fees
// assertion if "No asset in the trade is CORE." in market_evaluator.cpp
#if 0
BOOST_AUTO_TEST_CASE(asset_claim_fees_test)
{
try
{
ACTORS((alice)(bob)(izzy)(jill));
// Izzy issues asset to Alice
// Jill issues asset to Bob
// Alice and Bob trade in the market and pay fees
// Verify that Izzy and Jill can claim the fees
// const share_type core_prec = asset::scaled_precision( asset_id_type()(db).precision );
@ -203,16 +204,17 @@ BOOST_AUTO_TEST_CASE( nonzero_fee_test )
// GRAPHENE_REQUIRE_THROW( claim_fees( izzy_id, izzy_satoshi ), fc::exception );
// BOOST_CHECK( izzycoin.dynamic_asset_data_id(db).accumulated_fees == _izzy(0).amount );
// // can claim in multiple goes
// claim_fees( jill_id, _jill(4) );
// BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(2).amount );
// GRAPHENE_REQUIRE_THROW( claim_fees( jill_id, _jill(2) + jill_satoshi ), fc::exception );
// claim_fees( jill_id, _jill(2) );
// BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(0).amount );
// }
// }
// FC_LOG_AND_RETHROW()
// }
// can claim in multiple goes
claim_fees( jill_id, _jill(4) );
BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(2).amount );
GRAPHENE_REQUIRE_THROW( claim_fees( jill_id, _jill(2) + jill_satoshi ), fc::exception );
claim_fees( jill_id, _jill(2) );
BOOST_CHECK( jillcoin.dynamic_asset_data_id(db).accumulated_fees == _jill(0).amount );
}
}
FC_LOG_AND_RETHROW()
}
#endif
///////////////////////////////////////////////////////////////
// cashback_test infrastructure //
@ -266,313 +268,314 @@ struct actor_audit
int64_t ref_pct = 0; // referrer percentage should be this
};
// BOOST_AUTO_TEST_CASE( cashback_test )
// { try {
// /* Account Structure used in this test *
// * *
// * /-----------------\ /-------------------\ *
// * | life (Lifetime) | | rog (Lifetime) | *
// * \-----------------/ \-------------------/ *
// * | Ref&Reg | Refers | Registers | Registers *
// * | | 75 | 25 | *
// * v v v | *
// * /----------------\ /----------------\ | *
// * | ann (Annual) | | dumy (basic) | | *
// * \----------------/ \----------------/ |-------------. *
// * 80 | Refers L--------------------------------. | | *
// * v Refers 80 v v 20 | *
// * /----------------\ /----------------\ | *
// * | scud (basic) |<------------------------| stud (basic) | | *
// * \----------------/ 20 Registers | (Upgrades to | | 5 *
// * | Lifetime) | v *
// * \----------------/ /--------------\ *
// * L------->| pleb (Basic) | *
// * 95 Refers \--------------/ *
// * *
// * Fee distribution chains (80-20 referral/net split, 50-30 referrer/LTM split) *
// * life : 80% -> life, 20% -> net *
// * rog: 80% -> rog, 20% -> net *
// * ann (before upg): 80% -> life, 20% -> net *
// * ann (after upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% -> net *
// * stud (before upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> rog, *
// * 20% -> net *
// * stud (after upg): 80% -> stud, 20% -> net *
// * dumy : 75% * 80% -> life, 25% * 80% -> rog, 20% -> net *
// * scud : 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> stud, 20% -> net *
// * pleb : 95% * 80% -> stud, 5% * 80% -> rog, 20% -> net *
// */
BOOST_AUTO_TEST_CASE( cashback_test )
{ try {
/* Account Structure used in this test *
* *
* /-----------------\ /-------------------\ *
* | life (Lifetime) | | rog (Lifetime) | *
* \-----------------/ \-------------------/ *
* | Ref&Reg | Refers | Registers | Registers *
* | | 75 | 25 | *
* v v v | *
* /----------------\ /----------------\ | *
* | ann (Annual) | | dumy (basic) | | *
* \----------------/ \----------------/ |-------------. *
* 80 | Refers L--------------------------------. | | *
* v Refers 80 v v 20 | *
* /----------------\ /----------------\ | *
* | scud (basic) |<------------------------| stud (basic) | | *
* \----------------/ 20 Registers | (Upgrades to | | 5 *
* | Lifetime) | v *
* \----------------/ /--------------\ *
* L------->| pleb (Basic) | *
* 95 Refers \--------------/ *
* *
* Fee distribution chains (80-20 referral/net split, 50-30 referrer/LTM split) *
* life : 80% -> life, 20% -> net *
* rog: 80% -> rog, 20% -> net *
* ann (before upg): 80% -> life, 20% -> net *
* ann (after upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% -> net *
* stud (before upg): 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> rog, *
* 20% -> net *
* stud (after upg): 80% -> stud, 20% -> net *
* dumy : 75% * 80% -> life, 25% * 80% -> rog, 20% -> net *
* scud : 80% * 5/8 -> ann, 80% * 3/8 -> life, 20% * 80% -> stud, 20% -> net *
* pleb : 95% * 80% -> stud, 5% * 80% -> rog, 20% -> net *
*/
// BOOST_TEST_MESSAGE("Creating actors");
BOOST_TEST_MESSAGE("Creating actors");
// ACTOR(life);
// ACTOR(rog);
// PREP_ACTOR(ann);
// PREP_ACTOR(scud);
// PREP_ACTOR(dumy);
// PREP_ACTOR(stud);
// PREP_ACTOR(pleb);
ACTOR(life);
ACTOR(rog);
PREP_ACTOR(ann);
PREP_ACTOR(scud);
PREP_ACTOR(dumy);
PREP_ACTOR(stud);
PREP_ACTOR(pleb);
// account_id_type ann_id, scud_id, dumy_id, stud_id, pleb_id;
// actor_audit alife, arog, aann, ascud, adumy, astud, apleb;
account_id_type ann_id, scud_id, dumy_id, stud_id, pleb_id;
actor_audit alife, arog, aann, ascud, adumy, astud, apleb;
// alife.b0 = 100000000;
// arog.b0 = 100000000;
// aann.b0 = 1000000;
// astud.b0 = 1000000;
// astud.ref_pct = 80 * GRAPHENE_1_PERCENT;
// ascud.ref_pct = 80 * GRAPHENE_1_PERCENT;
// adumy.ref_pct = 75 * GRAPHENE_1_PERCENT;
// apleb.ref_pct = 95 * GRAPHENE_1_PERCENT;
alife.b0 = 100000000;
arog.b0 = 100000000;
aann.b0 = 1000000;
astud.b0 = 1000000;
astud.ref_pct = 80 * GRAPHENE_1_PERCENT;
ascud.ref_pct = 80 * GRAPHENE_1_PERCENT;
adumy.ref_pct = 75 * GRAPHENE_1_PERCENT;
apleb.ref_pct = 95 * GRAPHENE_1_PERCENT;
// transfer(account_id_type(), life_id, asset(alife.b0));
// alife.bal += alife.b0;
// transfer(account_id_type(), rog_id, asset(arog.b0));
// arog.bal += arog.b0;
// upgrade_to_lifetime_member(life_id);
// upgrade_to_lifetime_member(rog_id);
transfer(account_id_type(), life_id, asset(alife.b0));
alife.bal += alife.b0;
transfer(account_id_type(), rog_id, asset(arog.b0));
arog.bal += arog.b0;
upgrade_to_lifetime_member(life_id);
upgrade_to_lifetime_member(rog_id);
// BOOST_TEST_MESSAGE("Enable fees");
// const auto& fees = db.get_global_properties().parameters.current_fees;
BOOST_TEST_MESSAGE("Enable fees");
const auto& fees = db.get_global_properties().parameters.current_fees;
// #define CustomRegisterActor(actor_name, registrar_name, referrer_name, referrer_rate) \
// { \
// account_create_operation op; \
// op.registrar = registrar_name ## _id; \
// op.referrer = referrer_name ## _id; \
// op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \
// op.name = BOOST_PP_STRINGIZE(actor_name); \
// op.options.memo_key = actor_name ## _private_key.get_public_key(); \
// op.active = authority(1, public_key_type(actor_name ## _private_key.get_public_key()), 1); \
// op.owner = op.active; \
// op.fee = fees->calculate_fee(op); \
// trx.operations = {op}; \
// sign( trx, registrar_name ## _private_key ); \
// actor_name ## _id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(); \
// trx.clear(); \
// }
// #define CustomAuditActor(actor_name) \
// if( actor_name ## _id != account_id_type() ) \
// { \
// CHECK_BALANCE( actor_name, a ## actor_name.bal ); \
// CHECK_VESTED_CASHBACK( actor_name, a ## actor_name.vcb ); \
// CHECK_UNVESTED_CASHBACK( actor_name, a ## actor_name.ucb ); \
// CHECK_CASHBACK_VBO( actor_name, a ## actor_name.ubal ); \
// }
#define CustomRegisterActor(actor_name, registrar_name, referrer_name, referrer_rate) \
{ \
account_create_operation op; \
op.registrar = registrar_name ## _id; \
op.referrer = referrer_name ## _id; \
op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \
op.name = BOOST_PP_STRINGIZE(actor_name); \
op.options.memo_key = actor_name ## _private_key.get_public_key(); \
op.active = authority(1, public_key_type(actor_name ## _private_key.get_public_key()), 1); \
op.owner = op.active; \
op.fee = fees->calculate_fee(op); \
trx.operations = {op}; \
sign( trx, registrar_name ## _private_key ); \
actor_name ## _id = PUSH_TX( db, trx ).operation_results.front().get<object_id_type>(); \
trx.clear(); \
}
#define CustomAuditActor(actor_name) \
if( actor_name ## _id != account_id_type() ) \
{ \
CHECK_BALANCE( actor_name, a ## actor_name.bal ); \
CHECK_VESTED_CASHBACK( actor_name, a ## actor_name.vcb ); \
CHECK_UNVESTED_CASHBACK( actor_name, a ## actor_name.ucb ); \
CHECK_CASHBACK_VBO( actor_name, a ## actor_name.ubal ); \
}
// #define CustomAudit() \
// { \
// CustomAuditActor( life ); \
// CustomAuditActor( rog ); \
// CustomAuditActor( ann ); \
// CustomAuditActor( stud ); \
// CustomAuditActor( dumy ); \
// CustomAuditActor( scud ); \
// CustomAuditActor( pleb ); \
// }
#define CustomAudit() \
{ \
CustomAuditActor( life ); \
CustomAuditActor( rog ); \
CustomAuditActor( ann ); \
CustomAuditActor( stud ); \
CustomAuditActor( dumy ); \
CustomAuditActor( scud ); \
CustomAuditActor( pleb ); \
}
// int64_t reg_fee = fees->get< account_create_operation >().premium_fee;
// int64_t xfer_fee = fees->get< transfer_operation >().fee;
// int64_t upg_an_fee = fees->get< account_upgrade_operation >().membership_annual_fee;
// int64_t upg_lt_fee = fees->get< account_upgrade_operation >().membership_lifetime_fee;
// // all percentages here are cut from whole pie!
// uint64_t network_pct = 20 * P1;
// uint64_t lt_pct = 375 * P100 / 1000;
int64_t reg_fee = fees->get< account_create_operation >().premium_fee;
int64_t xfer_fee = fees->get< transfer_operation >().fee;
int64_t upg_an_fee = fees->get< account_upgrade_operation >().membership_annual_fee;
int64_t upg_lt_fee = fees->get< account_upgrade_operation >().membership_lifetime_fee;
// all percentages here are cut from whole pie!
uint64_t network_pct = 20 * P1;
uint64_t lt_pct = 375 * P100 / 1000;
// BOOST_TEST_MESSAGE("Register and upgrade Ann");
// {
// CustomRegisterActor(ann, life, life, 75);
// alife.vcb += reg_fee; alife.bal += -reg_fee;
// CustomAudit();
BOOST_TEST_MESSAGE("Register and upgrade Ann");
{
CustomRegisterActor(ann, life, life, 75);
alife.vcb += reg_fee; alife.bal += -reg_fee;
CustomAudit();
// transfer(life_id, ann_id, asset(aann.b0));
// alife.vcb += xfer_fee; alife.bal += -xfer_fee -aann.b0; aann.bal += aann.b0;
// CustomAudit();
transfer(life_id, ann_id, asset(aann.b0));
alife.vcb += xfer_fee; alife.bal += -xfer_fee -aann.b0; aann.bal += aann.b0;
CustomAudit();
// upgrade_to_annual_member(ann_id);
// aann.ucb += upg_an_fee; aann.bal += -upg_an_fee;
upgrade_to_annual_member(ann_id);
aann.ucb += upg_an_fee; aann.bal += -upg_an_fee;
// // audit distribution of fees from Ann
// alife.ubal += pct( P100-network_pct, aann.ucb );
// alife.bal += pct( P100-network_pct, aann.vcb );
// aann.ucb = 0; aann.vcb = 0;
// CustomAudit();
// }
// audit distribution of fees from Ann
alife.ubal += pct( P100-network_pct, aann.ucb );
alife.bal += pct( P100-network_pct, aann.vcb );
aann.ucb = 0; aann.vcb = 0;
CustomAudit();
}
// BOOST_TEST_MESSAGE("Register dumy and stud");
// CustomRegisterActor(dumy, rog, life, 75);
// arog.vcb += reg_fee; arog.bal += -reg_fee;
// CustomAudit();
BOOST_TEST_MESSAGE("Register dumy and stud");
CustomRegisterActor(dumy, rog, life, 75);
arog.vcb += reg_fee; arog.bal += -reg_fee;
CustomAudit();
// CustomRegisterActor(stud, rog, ann, 80);
// arog.vcb += reg_fee; arog.bal += -reg_fee;
// CustomAudit();
CustomRegisterActor(stud, rog, ann, 80);
arog.vcb += reg_fee; arog.bal += -reg_fee;
CustomAudit();
// BOOST_TEST_MESSAGE("Upgrade stud to lifetime member");
BOOST_TEST_MESSAGE("Upgrade stud to lifetime member");
// transfer(life_id, stud_id, asset(astud.b0));
// alife.vcb += xfer_fee; alife.bal += -astud.b0 -xfer_fee; astud.bal += astud.b0;
// CustomAudit();
transfer(life_id, stud_id, asset(astud.b0));
alife.vcb += xfer_fee; alife.bal += -astud.b0 -xfer_fee; astud.bal += astud.b0;
CustomAudit();
// upgrade_to_lifetime_member(stud_id);
// astud.ucb += upg_lt_fee; astud.bal -= upg_lt_fee;
upgrade_to_lifetime_member(stud_id);
astud.ucb += upg_lt_fee; astud.bal -= upg_lt_fee;
// /*
// network_cut: 20000
// referrer_cut: 40000 -> ann
// registrar_cut: 10000 -> rog
// lifetime_cut: 30000 -> life
/*
network_cut: 20000
referrer_cut: 40000 -> ann
registrar_cut: 10000 -> rog
lifetime_cut: 30000 -> life
// NET : net
// LTM : net' ltm
// REF : net' ltm' ref
// REG : net' ltm' ref'
// */
NET : net
LTM : net' ltm
REF : net' ltm' ref
REG : net' ltm' ref'
*/
// // audit distribution of fees from stud
// alife.ubal += pct( P100-network_pct, lt_pct, astud.ucb );
// aann.ubal += pct( P100-network_pct, P100-lt_pct, astud.ref_pct, astud.ucb );
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-astud.ref_pct, astud.ucb );
// astud.ucb = 0;
// CustomAudit();
// audit distribution of fees from stud
alife.ubal += pct( P100-network_pct, lt_pct, astud.ucb );
aann.ubal += pct( P100-network_pct, P100-lt_pct, astud.ref_pct, astud.ucb );
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-astud.ref_pct, astud.ucb );
astud.ucb = 0;
CustomAudit();
// BOOST_TEST_MESSAGE("Register pleb and scud");
BOOST_TEST_MESSAGE("Register pleb and scud");
// CustomRegisterActor(pleb, rog, stud, 95);
// arog.vcb += reg_fee; arog.bal += -reg_fee;
// CustomAudit();
CustomRegisterActor(pleb, rog, stud, 95);
arog.vcb += reg_fee; arog.bal += -reg_fee;
CustomAudit();
// CustomRegisterActor(scud, stud, ann, 80);
// astud.vcb += reg_fee; astud.bal += -reg_fee;
// CustomAudit();
CustomRegisterActor(scud, stud, ann, 80);
astud.vcb += reg_fee; astud.bal += -reg_fee;
CustomAudit();
// generate_block();
generate_block();
// BOOST_TEST_MESSAGE("Wait for maintenance interval");
BOOST_TEST_MESSAGE("Wait for maintenance interval");
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// // audit distribution of fees from life
// alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
// alife.ucb = 0; alife.vcb = 0;
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// audit distribution of fees from life
alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
alife.ucb = 0; alife.vcb = 0;
// // audit distribution of fees from rog
// arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
// arog.ucb = 0; arog.vcb = 0;
// audit distribution of fees from rog
arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
arog.ucb = 0; arog.vcb = 0;
// // audit distribution of fees from ann
// alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
// aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
// alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
// aann.ucb = 0; aann.vcb = 0;
// audit distribution of fees from ann
alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
aann.ucb = 0; aann.vcb = 0;
// // audit distribution of fees from stud
// astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
// astud.ucb = 0; astud.vcb = 0;
// audit distribution of fees from stud
astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
astud.ucb = 0; astud.vcb = 0;
// // audit distribution of fees from dumy
// alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
// alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
// adumy.ucb = 0; adumy.vcb = 0;
// audit distribution of fees from dumy
alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
adumy.ucb = 0; adumy.vcb = 0;
// // audit distribution of fees from scud
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
// aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
// ascud.ucb = 0; ascud.vcb = 0;
// audit distribution of fees from scud
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
ascud.ucb = 0; ascud.vcb = 0;
// // audit distribution of fees from pleb
// astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
// astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
// apleb.ucb = 0; apleb.vcb = 0;
// audit distribution of fees from pleb
astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
apleb.ucb = 0; apleb.vcb = 0;
// CustomAudit();
CustomAudit();
// BOOST_TEST_MESSAGE("Doing some transfers");
BOOST_TEST_MESSAGE("Doing some transfers");
// transfer(stud_id, scud_id, asset(500000));
// astud.bal += -500000-xfer_fee; astud.vcb += xfer_fee; ascud.bal += 500000;
// CustomAudit();
transfer(stud_id, scud_id, asset(500000));
astud.bal += -500000-xfer_fee; astud.vcb += xfer_fee; ascud.bal += 500000;
CustomAudit();
// transfer(scud_id, pleb_id, asset(400000));
// ascud.bal += -400000-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 400000;
// CustomAudit();
transfer(scud_id, pleb_id, asset(400000));
ascud.bal += -400000-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 400000;
CustomAudit();
// transfer(pleb_id, dumy_id, asset(300000));
// apleb.bal += -300000-xfer_fee; apleb.vcb += xfer_fee; adumy.bal += 300000;
// CustomAudit();
transfer(pleb_id, dumy_id, asset(300000));
apleb.bal += -300000-xfer_fee; apleb.vcb += xfer_fee; adumy.bal += 300000;
CustomAudit();
// transfer(dumy_id, rog_id, asset(200000));
// adumy.bal += -200000-xfer_fee; adumy.vcb += xfer_fee; arog.bal += 200000;
// CustomAudit();
transfer(dumy_id, rog_id, asset(200000));
adumy.bal += -200000-xfer_fee; adumy.vcb += xfer_fee; arog.bal += 200000;
CustomAudit();
// BOOST_TEST_MESSAGE("Waiting for maintenance time");
BOOST_TEST_MESSAGE("Waiting for maintenance time");
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// // audit distribution of fees from life
// alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
// alife.ucb = 0; alife.vcb = 0;
// audit distribution of fees from life
alife.ubal += pct( P100-network_pct, alife.ucb +alife.vcb );
alife.ucb = 0; alife.vcb = 0;
// // audit distribution of fees from rog
// arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
// arog.ucb = 0; arog.vcb = 0;
// audit distribution of fees from rog
arog.ubal += pct( P100-network_pct, arog.ucb + arog.vcb );
arog.ucb = 0; arog.vcb = 0;
// // audit distribution of fees from ann
// alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
// aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
// alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
// aann.ucb = 0; aann.vcb = 0;
// audit distribution of fees from ann
alife.ubal += pct( P100-network_pct, lt_pct, aann.ucb+aann.vcb );
aann.ubal += pct( P100-network_pct, P100-lt_pct, aann.ref_pct, aann.ucb+aann.vcb );
alife.ubal += pct( P100-network_pct, P100-lt_pct, P100-aann.ref_pct, aann.ucb+aann.vcb );
aann.ucb = 0; aann.vcb = 0;
// // audit distribution of fees from stud
// astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
// astud.ucb = 0; astud.vcb = 0;
// audit distribution of fees from stud
astud.ubal += pct( P100-network_pct, astud.ucb+astud.vcb );
astud.ucb = 0; astud.vcb = 0;
// // audit distribution of fees from dumy
// alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
// alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
// adumy.ucb = 0; adumy.vcb = 0;
// audit distribution of fees from dumy
alife.ubal += pct( P100-network_pct, lt_pct, adumy.ucb+adumy.vcb );
alife.ubal += pct( P100-network_pct, P100-lt_pct, adumy.ref_pct, adumy.ucb+adumy.vcb );
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-adumy.ref_pct, adumy.ucb+adumy.vcb );
adumy.ucb = 0; adumy.vcb = 0;
// // audit distribution of fees from scud
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
// aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
// ascud.ucb = 0; ascud.vcb = 0;
// audit distribution of fees from scud
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
aann.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
ascud.ucb = 0; ascud.vcb = 0;
// // audit distribution of fees from pleb
// astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
// astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
// arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
// apleb.ucb = 0; apleb.vcb = 0;
// audit distribution of fees from pleb
astud.ubal += pct( P100-network_pct, lt_pct, apleb.ucb+apleb.vcb );
astud.ubal += pct( P100-network_pct, P100-lt_pct, apleb.ref_pct, apleb.ucb+apleb.vcb );
arog.ubal += pct( P100-network_pct, P100-lt_pct, P100-apleb.ref_pct, apleb.ucb+apleb.vcb );
apleb.ucb = 0; apleb.vcb = 0;
// CustomAudit();
CustomAudit();
// BOOST_TEST_MESSAGE("Waiting for annual membership to expire");
BOOST_TEST_MESSAGE("Waiting for annual membership to expire");
BOOST_TEST_MESSAGE("Count of block to generate " + std::to_string(ann_id(db).membership_expiration_date.sec_since_epoch()));
// generate_blocks(ann_id(db).membership_expiration_date);
// generate_block();
generate_blocks(ann_id(db).membership_expiration_date);
generate_block();
// BOOST_TEST_MESSAGE("Transferring from scud to pleb");
BOOST_TEST_MESSAGE("Transferring from scud to pleb");
// //ann's membership has expired, so scud's fee should go up to life instead.
// transfer(scud_id, pleb_id, asset(10));
// ascud.bal += -10-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 10;
// CustomAudit();
//ann's membership has expired, so scud's fee should go up to life instead.
transfer(scud_id, pleb_id, asset(10));
ascud.bal += -10-xfer_fee; ascud.vcb += xfer_fee; apleb.bal += 10;
CustomAudit();
// BOOST_TEST_MESSAGE("Waiting for maint interval");
BOOST_TEST_MESSAGE("Waiting for maint interval");
// generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
// // audit distribution of fees from scud
// alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
// alife.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
// astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
// ascud.ucb = 0; ascud.vcb = 0;
// audit distribution of fees from scud
alife.ubal += pct( P100-network_pct, lt_pct, ascud.ucb+ascud.vcb );
alife.ubal += pct( P100-network_pct, P100-lt_pct, ascud.ref_pct, ascud.ucb+ascud.vcb );
astud.ubal += pct( P100-network_pct, P100-lt_pct, P100-ascud.ref_pct, ascud.ucb+ascud.vcb );
ascud.ucb = 0; ascud.vcb = 0;
// CustomAudit();
CustomAudit();
// } FC_LOG_AND_RETHROW() }
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE( account_create_fee_scaling )
{ try {
@ -1033,7 +1036,6 @@ BOOST_AUTO_TEST_CASE( issue_429_test )
verify_asset_supplies( db );
generate_blocks( HARDFORK_CORE_429_TIME + 10 );
{
signed_transaction tx;
asset_create_operation op;
@ -1046,7 +1048,7 @@ BOOST_AUTO_TEST_CASE( issue_429_test )
sign( tx, alice_private_key );
PUSH_TX( db, tx );
}
verify_asset_supplies( db );
}
catch( const fc::exception& e )

View file

@ -99,8 +99,7 @@ BOOST_AUTO_TEST_CASE( test_exception_throwing_for_the_same_operation_proposed_tw
create_proposal(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))});
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{
@ -153,8 +152,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplication_in_transaction_with_several_op
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{
@ -174,8 +172,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)),
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{
@ -194,8 +191,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_duplicated_operation_in_existed_proposal_w
make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(500))}); //duplicated one
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{
@ -229,8 +225,7 @@ BOOST_AUTO_TEST_CASE( check_fails_for_same_member_create_operations )
create_proposal(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_committee_member_create_operation(asset(1000), account_id_type(), "test url")});
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{
@ -269,9 +264,7 @@ BOOST_AUTO_TEST_CASE( check_failes_for_several_operations_of_mixed_type )
auto trx = make_signed_transaction_with_proposed_operation(*this, {make_transfer_operation(account_id_type(), alice_id, asset(501)), //duplicate
make_committee_member_create_operation(asset(1002), account_id_type(), "test url")});
//Modifying from BOOST_CHECK to BOOST_WARN just to make sure users might confuse about this error. If any changes in network_boradcast, would recommend to revert the changes
BOOST_WARN_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
BOOST_CHECK_THROW(db.check_tansaction_for_duplicated_operations(trx), fc::exception);
}
catch( const fc::exception& e )
{

View file

@ -1112,6 +1112,633 @@ BOOST_AUTO_TEST_CASE( uia_fees )
}
}
BOOST_FIXTURE_TEST_SUITE( dividend_tests, database_fixture )
BOOST_AUTO_TEST_CASE( create_dividend_uia )
{
using namespace graphene;
try {
BOOST_TEST_MESSAGE("Creating dividend holder asset");
{
asset_create_operation creator;
creator.issuer = account_id_type();
creator.fee = asset();
creator.symbol = "DIVIDEND";
creator.common_options.max_supply = 100000000;
creator.precision = 2;
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
creator.common_options.flags = charge_market_fee;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
trx.operations.push_back(std::move(creator));
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
BOOST_TEST_MESSAGE("Creating test accounts");
create_account("alice");
create_account("bob");
create_account("carol");
create_account("dave");
create_account("frank");
BOOST_TEST_MESSAGE("Creating test asset");
{
asset_create_operation creator;
creator.issuer = account_id_type();
creator.fee = asset();
creator.symbol = "TEST";
creator.common_options.max_supply = 100000000;
creator.precision = 2;
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
creator.common_options.flags = charge_market_fee;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
trx.operations.push_back(std::move(creator));
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
generate_block();
BOOST_TEST_MESSAGE("Funding asset fee pool");
{
asset_fund_fee_pool_operation fund_op;
fund_op.from_account = account_id_type();
fund_op.asset_id = get_asset("TEST").id;
fund_op.amount = 500000000;
trx.operations.push_back(std::move(fund_op));
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
// our DIVIDEND asset should not yet be a divdend asset
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
BOOST_CHECK(!dividend_holder_asset_object.dividend_data_id);
BOOST_TEST_MESSAGE("Converting the new asset to a dividend holder asset");
{
asset_update_dividend_operation op;
op.issuer = dividend_holder_asset_object.issuer;
op.asset_to_update = dividend_holder_asset_object.id;
op.new_options.next_payout_time = db.head_block_time() + fc::minutes(1);
op.new_options.payout_interval = 60 * 60 * 24 * 3;
trx.operations.push_back(op);
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
generate_block();
BOOST_TEST_MESSAGE("Verifying the dividend holder asset options");
BOOST_REQUIRE(dividend_holder_asset_object.dividend_data_id);
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
{
BOOST_REQUIRE(dividend_data.options.payout_interval);
BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 60 * 60 * 24 * 3);
}
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
BOOST_CHECK_EQUAL(dividend_distribution_account.name, "dividend-dividend-distribution");
// db.modify( db.get_global_properties(), [&]( global_property_object& _gpo )
// {
// _gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_base_fee = 100;
// _gpo.parameters.current_fees->get<asset_dividend_distribution_operation>().distribution_fee_per_holder = 100;
// } );
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( test_update_dividend_interval )
{
using namespace graphene;
try {
INVOKE( create_dividend_uia );
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
auto advance_to_next_payout_time = [&]() {
// Advance to the next upcoming payout time
BOOST_REQUIRE(dividend_data.options.next_payout_time);
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
// generate blocks up to the next scheduled time
generate_blocks(next_payout_scheduled_time);
// if the scheduled time fell on a maintenance interval, then we should have paid out.
// if not, we need to advance to the next maintenance interval to trigger the payout
if (dividend_data.options.next_payout_time)
{
// we know there was a next_payout_time set when we entered this, so if
// it has been cleared, we must have already processed payouts, no need to
// further advance time.
BOOST_REQUIRE(dividend_data.options.next_payout_time);
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
}
};
BOOST_TEST_MESSAGE("Updating the payout interval");
{
asset_update_dividend_operation op;
op.issuer = dividend_holder_asset_object.issuer;
op.asset_to_update = dividend_holder_asset_object.id;
op.new_options.next_payout_time = fc::time_point::now() + fc::minutes(1);
op.new_options.payout_interval = 60 * 60 * 24; // 1 days
trx.operations.push_back(op);
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
generate_block();
BOOST_TEST_MESSAGE("Verifying the updated dividend holder asset options");
{
BOOST_REQUIRE(dividend_data.options.payout_interval);
BOOST_CHECK_EQUAL(*dividend_data.options.payout_interval, 60 * 60 * 24);
}
BOOST_TEST_MESSAGE("Removing the payout interval");
{
asset_update_dividend_operation op;
op.issuer = dividend_holder_asset_object.issuer;
op.asset_to_update = dividend_holder_asset_object.id;
op.new_options.next_payout_time = dividend_data.options.next_payout_time;
op.new_options.payout_interval = fc::optional<uint32_t>();
trx.operations.push_back(op);
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
generate_block();
BOOST_CHECK(!dividend_data.options.payout_interval);
advance_to_next_payout_time();
BOOST_REQUIRE_MESSAGE(!dividend_data.options.next_payout_time, "A new payout was scheduled, but none should have been");
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( test_basic_dividend_distribution )
{
using namespace graphene;
try {
INVOKE( create_dividend_uia );
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
const account_object& alice = get_account("alice");
const account_object& bob = get_account("bob");
const account_object& carol = get_account("carol");
const account_object& dave = get_account("dave");
const account_object& frank = get_account("frank");
const auto& test_asset_object = get_asset("TEST");
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
{
asset_issue_operation op;
op.issuer = asset_to_issue.issuer;
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
op.issue_to_account = destination_account.id;
trx.operations.push_back( op );
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
};
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
holder_account_obj.id,
payout_asset_obj.id);
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
};
auto advance_to_next_payout_time = [&]() {
// Advance to the next upcoming payout time
BOOST_REQUIRE(dividend_data.options.next_payout_time);
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
// generate blocks up to the next scheduled time
generate_blocks(next_payout_scheduled_time);
// if the scheduled time fell on a maintenance interval, then we should have paid out.
// if not, we need to advance to the next maintenance interval to trigger the payout
if (dividend_data.options.next_payout_time)
{
// we know there was a next_payout_time set when we entered this, so if
// it has been cleared, we must have already processed payouts, no need to
// further advance time.
BOOST_REQUIRE(dividend_data.options.next_payout_time);
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
}
};
// the first test will be testing pending balances, so we need to hit a
// maintenance interval that isn't the payout interval. Payout is
// every 3 days, maintenance interval is every 1 day.
advance_to_next_payout_time();
// Set up the first test, issue alice, bob, and carol each 100 DIVIDEND.
// Then deposit 300 TEST in the distribution account, and see that they
// each are credited 100 TEST.
issue_asset_to_account(dividend_holder_asset_object, alice, 100000);
issue_asset_to_account(dividend_holder_asset_object, bob, 100000);
issue_asset_to_account(dividend_holder_asset_object, carol, 100000);
BOOST_TEST_MESSAGE("Issuing 300 TEST to the dividend account");
issue_asset_to_account(test_asset_object, dividend_distribution_account, 30000);
generate_block();
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
verify_pending_balance(alice, test_asset_object, 10000);
verify_pending_balance(bob, test_asset_object, 10000);
verify_pending_balance(carol, test_asset_object, 10000);
// For the second test, issue carol more than the other two, so it's
// alice: 100 DIVIDND, bob: 100 DIVIDEND, carol: 200 DIVIDEND
// Then deposit 400 TEST in the distribution account, and see that alice
// and bob are credited with 100 TEST, and carol gets 200 TEST
BOOST_TEST_MESSAGE("Issuing carol twice as much of the holder asset");
issue_asset_to_account(dividend_holder_asset_object, carol, 100000); // one thousand at two digits of precision
issue_asset_to_account(test_asset_object, dividend_distribution_account, 40000); // one thousand at two digits of precision
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
verify_pending_balance(alice, test_asset_object, 20000);
verify_pending_balance(bob, test_asset_object, 20000);
verify_pending_balance(carol, test_asset_object, 30000);
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
advance_to_next_payout_time();
BOOST_REQUIRE_MESSAGE(dividend_data.options.next_payout_time, "No new payout was scheduled");
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time != *dividend_data.options.next_payout_time,
"New payout was scheduled for the same time as the last payout");
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
"New payout was not scheduled for the expected time");
auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout)
{
BOOST_TEST_MESSAGE("Verifying the virtual op was created");
const account_transaction_history_index& hist_idx = db.get_index_type<account_transaction_history_index>();
auto account_history_range = hist_idx.indices().get<by_seq>().equal_range(boost::make_tuple(destination_account.id));
BOOST_REQUIRE(account_history_range.first != account_history_range.second);
const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db);
const asset_dividend_distribution_operation& distribution_operation = history_object.op.get<asset_dividend_distribution_operation>();
BOOST_CHECK(distribution_operation.account_id == destination_account.id);
BOOST_CHECK(std::find(distribution_operation.amounts.begin(), distribution_operation.amounts.end(), expected_payout)
!= distribution_operation.amounts.end());
};
BOOST_TEST_MESSAGE("Verifying the payouts");
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
verify_dividend_payout_operations(alice, asset(20000, test_asset_object.id));
verify_pending_balance(alice, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
verify_dividend_payout_operations(bob, asset(20000, test_asset_object.id));
verify_pending_balance(bob, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 30000);
verify_dividend_payout_operations(carol, asset(30000, test_asset_object.id));
verify_pending_balance(carol, test_asset_object, 0);
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( test_basic_dividend_distribution_to_core_asset )
{
using namespace graphene;
try {
BOOST_TEST_MESSAGE("Creating test accounts");
create_account("alice");
create_account("bob");
create_account("carol");
create_account("dave");
create_account("frank");
BOOST_TEST_MESSAGE("Creating test asset");
{
asset_create_operation creator;
creator.issuer = account_id_type();
creator.fee = asset();
creator.symbol = "TEST";
creator.common_options.max_supply = 100000000;
creator.precision = 2;
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
creator.common_options.flags = charge_market_fee;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
trx.operations.push_back(std::move(creator));
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
}
generate_block();
const auto& dividend_holder_asset_object = asset_id_type(0)(db);
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
const account_object& alice = get_account("alice");
const account_object& bob = get_account("bob");
const account_object& carol = get_account("carol");
const account_object& dave = get_account("dave");
const account_object& frank = get_account("frank");
const auto& test_asset_object = get_asset("TEST");
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
{
asset_issue_operation op;
op.issuer = asset_to_issue.issuer;
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
op.issue_to_account = destination_account.id;
trx.operations.push_back( op );
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
};
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
holder_account_obj.id,
payout_asset_obj.id);
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
};
auto advance_to_next_payout_time = [&]() {
// Advance to the next upcoming payout time
BOOST_REQUIRE(dividend_data.options.next_payout_time);
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
idump((next_payout_scheduled_time));
// generate blocks up to the next scheduled time
generate_blocks(next_payout_scheduled_time);
// if the scheduled time fell on a maintenance interval, then we should have paid out.
// if not, we need to advance to the next maintenance interval to trigger the payout
if (dividend_data.options.next_payout_time)
{
// we know there was a next_payout_time set when we entered this, so if
// it has been cleared, we must have already processed payouts, no need to
// further advance time.
BOOST_REQUIRE(dividend_data.options.next_payout_time);
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
}
idump((db.head_block_time()));
};
// the first test will be testing pending balances, so we need to hit a
// maintenance interval that isn't the payout interval. Payout is
// every 3 days, maintenance interval is every 1 day.
advance_to_next_payout_time();
// Set up the first test, issue alice, bob, and carol, and dave each 1/4 of the total
// supply of the core asset.
// Then deposit 400 TEST in the distribution account, and see that they
// each are credited 100 TEST.
transfer( committee_account(db), alice, asset( 250000000000000 ) );
transfer( committee_account(db), bob, asset( 250000000000000 ) );
transfer( committee_account(db), carol, asset( 250000000000000 ) );
transfer( committee_account(db), dave, asset( 250000000000000 ) );
BOOST_TEST_MESSAGE("Issuing 300 TEST to the dividend account");
issue_asset_to_account(test_asset_object, dividend_distribution_account, 40000);
generate_block();
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
verify_pending_balance(alice, test_asset_object, 10000);
verify_pending_balance(bob, test_asset_object, 10000);
verify_pending_balance(carol, test_asset_object, 10000);
verify_pending_balance(dave, test_asset_object, 10000);
// For the second test, issue dave more than the other two, so it's
// alice: 1/5 CORE, bob: 1/5 CORE, carol: 1/5 CORE, dave: 2/5 CORE
// Then deposit 500 TEST in the distribution account, and see that alice
// bob, and carol are credited with 100 TEST, and dave gets 200 TEST
BOOST_TEST_MESSAGE("Issuing dave twice as much of the holder asset");
transfer( alice, dave, asset( 50000000000000 ) );
transfer( bob, dave, asset( 50000000000000 ) );
transfer( carol, dave, asset( 50000000000000 ) );
issue_asset_to_account(test_asset_object, dividend_distribution_account, 50000); // 500 at two digits of precision
BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
verify_pending_balance(alice, test_asset_object, 20000);
verify_pending_balance(bob, test_asset_object, 20000);
verify_pending_balance(carol, test_asset_object, 20000);
verify_pending_balance(dave, test_asset_object, 30000);
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
advance_to_next_payout_time();
BOOST_REQUIRE_MESSAGE(dividend_data.options.next_payout_time, "No new payout was scheduled");
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time != *dividend_data.options.next_payout_time,
"New payout was scheduled for the same time as the last payout");
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
"New payout was not scheduled for the expected time");
auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout)
{
BOOST_TEST_MESSAGE("Verifying the virtual op was created");
const account_transaction_history_index& hist_idx = db.get_index_type<account_transaction_history_index>();
auto account_history_range = hist_idx.indices().get<by_seq>().equal_range(boost::make_tuple(destination_account.id));
BOOST_REQUIRE(account_history_range.first != account_history_range.second);
const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db);
const asset_dividend_distribution_operation& distribution_operation = history_object.op.get<asset_dividend_distribution_operation>();
BOOST_CHECK(distribution_operation.account_id == destination_account.id);
BOOST_CHECK(std::find(distribution_operation.amounts.begin(), distribution_operation.amounts.end(), expected_payout)
!= distribution_operation.amounts.end());
};
BOOST_TEST_MESSAGE("Verifying the payouts");
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
verify_dividend_payout_operations(alice, asset(20000, test_asset_object.id));
verify_pending_balance(alice, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
verify_dividend_payout_operations(bob, asset(20000, test_asset_object.id));
verify_pending_balance(bob, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 20000);
verify_dividend_payout_operations(carol, asset(20000, test_asset_object.id));
verify_pending_balance(carol, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(dave, test_asset_object), 30000);
verify_dividend_payout_operations(dave, asset(30000, test_asset_object.id));
verify_pending_balance(dave, test_asset_object, 0);
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( test_dividend_distribution_interval )
{
using namespace graphene;
try {
INVOKE( create_dividend_uia );
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
const account_object& alice = get_account("alice");
const account_object& bob = get_account("bob");
const account_object& carol = get_account("carol");
const account_object& dave = get_account("dave");
const account_object& frank = get_account("frank");
const auto& test_asset_object = get_asset("TEST");
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( check_dividend_corner_cases )
{
using namespace graphene;
try {
INVOKE( create_dividend_uia );
const auto& dividend_holder_asset_object = get_asset("DIVIDEND");
const auto& dividend_data = dividend_holder_asset_object.dividend_data(db);
const account_object& dividend_distribution_account = dividend_data.dividend_distribution_account(db);
const account_object& alice = get_account("alice");
const account_object& bob = get_account("bob");
const account_object& carol = get_account("carol");
const account_object& dave = get_account("dave");
const account_object& frank = get_account("frank");
const auto& test_asset_object = get_asset("TEST");
auto issue_asset_to_account = [&](const asset_object& asset_to_issue, const account_object& destination_account, int64_t amount_to_issue)
{
asset_issue_operation op;
op.issuer = asset_to_issue.issuer;
op.asset_to_issue = asset(amount_to_issue, asset_to_issue.id);
op.issue_to_account = destination_account.id;
trx.operations.push_back( op );
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
};
auto verify_pending_balance = [&](const account_object& holder_account_obj, const asset_object& payout_asset_obj, int64_t expected_balance) {
int64_t pending_balance = get_dividend_pending_payout_balance(dividend_holder_asset_object.id,
holder_account_obj.id,
payout_asset_obj.id);
BOOST_CHECK_EQUAL(pending_balance, expected_balance);
};
auto reserve_asset_from_account = [&](const asset_object& asset_to_reserve, const account_object& from_account, int64_t amount_to_reserve)
{
asset_reserve_operation reserve_op;
reserve_op.payer = from_account.id;
reserve_op.amount_to_reserve = asset(amount_to_reserve, asset_to_reserve.id);
trx.operations.push_back(reserve_op);
set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
};
auto advance_to_next_payout_time = [&]() {
// Advance to the next upcoming payout time
BOOST_REQUIRE(dividend_data.options.next_payout_time);
fc::time_point_sec next_payout_scheduled_time = *dividend_data.options.next_payout_time;
// generate blocks up to the next scheduled time
generate_blocks(next_payout_scheduled_time);
// if the scheduled time fell on a maintenance interval, then we should have paid out.
// if not, we need to advance to the next maintenance interval to trigger the payout
if (dividend_data.options.next_payout_time)
{
// we know there was a next_payout_time set when we entered this, so if
// it has been cleared, we must have already processed payouts, no need to
// further advance time.
BOOST_REQUIRE(dividend_data.options.next_payout_time);
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
}
};
// the first test will be testing pending balances, so we need to hit a
// maintenance interval that isn't the payout interval. Payout is
// every 3 days, maintenance interval is every 1 day.
advance_to_next_payout_time();
BOOST_TEST_MESSAGE("Testing a payout interval when there are no users holding the dividend asset");
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 0);
issue_asset_to_account(test_asset_object, dividend_distribution_account, 1000);
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
BOOST_TEST_MESSAGE("Verify that no pending payments were scheduled");
verify_pending_balance(alice, test_asset_object, 0);
verify_pending_balance(bob, test_asset_object, 0);
verify_pending_balance(carol, test_asset_object, 0);
advance_to_next_payout_time();
BOOST_TEST_MESSAGE("Verify that no actual payments took place");
verify_pending_balance(alice, test_asset_object, 0);
verify_pending_balance(bob, test_asset_object, 0);
verify_pending_balance(carol, test_asset_object, 0);
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 0);
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 0);
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 0);
BOOST_CHECK_EQUAL(get_balance(dividend_distribution_account, test_asset_object), 1000);
BOOST_TEST_MESSAGE("Now give alice a small balance and see that she takes it all");
issue_asset_to_account(dividend_holder_asset_object, alice, 1);
generate_block();
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
BOOST_TEST_MESSAGE("Verify that no alice received her payment of the entire amount");
verify_pending_balance(alice, test_asset_object, 1000);
// Test that we can pay out the dividend asset itself
issue_asset_to_account(dividend_holder_asset_object, bob, 1);
issue_asset_to_account(dividend_holder_asset_object, carol, 1);
issue_asset_to_account(dividend_holder_asset_object, dividend_distribution_account, 300);
generate_block();
BOOST_CHECK_EQUAL(get_balance(alice, dividend_holder_asset_object), 1);
BOOST_CHECK_EQUAL(get_balance(bob, dividend_holder_asset_object), 1);
BOOST_CHECK_EQUAL(get_balance(carol, dividend_holder_asset_object), 1);
BOOST_TEST_MESSAGE("Generating blocks until next maintenance interval");
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
generate_block(); // get the maintenance skip slots out of the way
BOOST_TEST_MESSAGE("Verify that the dividend asset was shared out");
verify_pending_balance(alice, dividend_holder_asset_object, 100);
verify_pending_balance(bob, dividend_holder_asset_object, 100);
verify_pending_balance(carol, dividend_holder_asset_object, 100);
} catch(fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_SUITE_END() // end dividend_tests suite
BOOST_AUTO_TEST_CASE( cancel_limit_order_test )
{ try {
INVOKE( issue_uia );

View file

@ -1400,7 +1400,6 @@ BOOST_AUTO_TEST_CASE( vbo_withdraw_different )
create_op.owner = alice_id;
create_op.amount = asset(100, stuff_id);
create_op.policy = pinit;
create_op.balance_type = vesting_balance_type::unspecified;
signed_transaction create_tx;
create_tx.operations.push_back( create_op );