minor logic changes. added db_api and cli_wallet methods

This commit is contained in:
kstdl 2017-12-11 17:42:55 +03:00 committed by gladcow
parent 0ba8f95f49
commit 7ba965c860
15 changed files with 220 additions and 64 deletions

View file

@ -113,6 +113,14 @@ 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_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; 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,
asset_id_type start = asset_id_type() )const;
asset get_lottery_balance( asset_id_type lottery_id )const;
// Markets / feeds // Markets / feeds
vector<limit_order_object> get_limit_orders(asset_id_type a, asset_id_type b, uint32_t limit)const; vector<limit_order_object> get_limit_orders(asset_id_type a, asset_id_type b, uint32_t limit)const;
vector<call_order_object> get_call_orders(asset_id_type a, uint32_t limit)const; vector<call_order_object> get_call_orders(asset_id_type a, uint32_t limit)const;
@ -174,7 +182,6 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
if( !is_subscribed_to_item(i) ) if( !is_subscribed_to_item(i) )
{ {
idump((i));
_subscribe_filter.insert( vec.data(), vec.size() );//(vecconst char*)&i, sizeof(i) ); _subscribe_filter.insert( vec.data(), vec.size() );//(vecconst char*)&i, sizeof(i) );
} }
} }
@ -630,7 +637,6 @@ std::map<string,full_account> database_api::get_full_accounts( const vector<stri
std::map<std::string, full_account> database_api_impl::get_full_accounts( const vector<std::string>& names_or_ids, bool subscribe) std::map<std::string, full_account> database_api_impl::get_full_accounts( const vector<std::string>& names_or_ids, bool subscribe)
{ {
idump((names_or_ids));
std::map<std::string, full_account> results; std::map<std::string, full_account> results;
for (const std::string& account_name_or_id : names_or_ids) for (const std::string& account_name_or_id : names_or_ids)
@ -1014,6 +1020,49 @@ vector<optional<asset_object>> database_api_impl::lookup_asset_symbols(const vec
return result; return result;
} }
////////////////////
// Lottery Assets //
////////////////////
vector<asset_object> database_api::get_lotteries( asset_id_type stop,
unsigned limit,
asset_id_type start )const
{
return my->get_lotteries( stop, limit, start );
}
vector<asset_object> database_api_impl::get_lotteries(asset_id_type stop,
unsigned limit,
asset_id_type start )const
{
vector<asset_object> result;
const auto& assets = _db.get_index_type<asset_index>().indices().get<by_lottery>();
const auto range = assets.equal_range( boost::make_tuple( true ) );
for( const auto& a : boost::make_iterator_range( range.first, range.second ) )
{
if( start == asset_id_type() || (a.get_id().instance.value <= start.instance.value) )
result.push_back( a );
if( a.get_id().instance.value < stop.instance.value || result.size() >= limit )
break;
}
return result;
}
asset database_api::get_lottery_balance( asset_id_type lottery_id )const
{
return my->get_lottery_balance( lottery_id );
}
asset database_api_impl::get_lottery_balance( asset_id_type lottery_id )const
{
auto lottery_asset = lottery_id( _db );
FC_ASSERT( lottery_asset.is_lottery() );
return _db.get_balance( lottery_id );
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Peerplays // // Peerplays //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View file

@ -349,6 +349,22 @@ class database_api
*/ */
vector<optional<asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const; vector<optional<asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const;
////////////////////
// Lottery Assets //
////////////////////
/**
* @brief Get a list of lottery assets
* @return The lottery assets between start and stop ids
*/
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
unsigned limit = 100,
asset_id_type start = asset_id_type() )const;
/**
* @brief Get balance of lottery assets
*/
asset get_lottery_balance( asset_id_type lottery_id ) const;
///////////////////// /////////////////////
// Peerplays // // Peerplays //
///////////////////// /////////////////////
@ -734,6 +750,10 @@ FC_API(graphene::app::database_api,
(get_unmatched_bets_for_bettor) (get_unmatched_bets_for_bettor)
(get_all_unmatched_bets_for_bettor) (get_all_unmatched_bets_for_bettor)
// Lottery assets
(get_lotteries)
(get_lottery_balance)
// Markets / feeds // Markets / feeds
(get_order_book) (get_order_book)
(get_limit_orders) (get_limit_orders)

View file

@ -90,7 +90,6 @@ add_library( graphene_chain
account_object.cpp account_object.cpp
asset_object.cpp asset_object.cpp
lottery.cpp
fba_object.cpp fba_object.cpp
proposal_object.cpp proposal_object.cpp
vesting_balance_object.cpp vesting_balance_object.cpp

View file

@ -262,11 +262,10 @@ void asset_object::distribute_sweeps_holders_part( database& db )
void asset_object::end_lottery( database& db ) void asset_object::end_lottery( database& db )
{ {
idump(( "end_lottery" ));
transaction_evaluation_state eval(&db); transaction_evaluation_state eval(&db);
FC_ASSERT( is_lottery() ); FC_ASSERT( is_lottery() );
FC_ASSERT( lottery_options->is_active && ( lottery_options->end_date <= db.head_block_time() ) ); FC_ASSERT( lottery_options->is_active && ( lottery_options->end_date <= db.head_block_time() || lottery_options->ending_on_soldout ) );
auto participants = distribute_winners_part( db ); auto participants = distribute_winners_part( db );
if( participants.size() > 0) { if( participants.size() > 0) {

View file

@ -142,8 +142,6 @@ void database::open(
if( last_block.valid() ) if( last_block.valid() )
{ {
_fork_db.start_block( *last_block ); _fork_db.start_block( *last_block );
idump((last_block->id())(last_block->block_num()));
idump((head_block_id())(head_block_num()));
if( last_block->id() != head_block_id() ) if( last_block->id() != head_block_id() )
{ {
FC_ASSERT( head_block_num() == 0, "last block ID does not match current chain state", FC_ASSERT( head_block_num() == 0, "last block ID does not match current chain state",
@ -210,22 +208,28 @@ void database::force_slow_replays()
void database::check_ending_lotteries() void database::check_ending_lotteries()
{ {
try {
const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>(); const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>();
for( auto checking_asset: lotteries_idx ) for( auto checking_asset: lotteries_idx )
{ {
if( !checking_asset.is_lottery() ) break; FC_ASSERT( checking_asset.is_lottery() );
if( !checking_asset.lottery_options->is_active ) break; FC_ASSERT( checking_asset.lottery_options->is_active );
if( checking_asset.lottery_options->end_date >= head_block_time() ) break; FC_ASSERT( checking_asset.lottery_options->end_date < head_block_time() );
checking_asset.end_lottery(*this); checking_asset.end_lottery(*this);
} }
} catch( ... ) {}
} }
void database::check_lottery_end_by_participants( asset_id_type asset_id ) void database::check_lottery_end_by_participants( asset_id_type asset_id )
{ {
try {
asset_object asset_to_check = asset_id( *this ); asset_object asset_to_check = asset_id( *this );
if( !asset_to_check.is_lottery() ) return; auto asset_dyn_props = asset_to_check.dynamic_data( *this );
if( !asset_to_check.lottery_options->ending_on_soldout ) return; FC_ASSERT( asset_dyn_props.current_supply == asset_to_check.options.max_supply );
FC_ASSERT( asset_to_check.is_lottery() );
FC_ASSERT( asset_to_check.lottery_options->ending_on_soldout );
asset_to_check.end_lottery( *this ); asset_to_check.end_lottery( *this );
} catch( ... ) {}
} }
} } } }

View file

@ -1,3 +1,3 @@
#ifndef HARDFORK_SWEEPS_TIME #ifndef HARDFORK_SWEEPS_TIME
#define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1510320000 )) #define HARDFORK_SWEEPS_TIME (fc::time_point_sec( 1515000764 ))
#endif #endif

View file

@ -255,7 +255,7 @@ namespace graphene { namespace chain {
bool operator()(const asset_object& lhs, const asset_object& rhs) const bool operator()(const asset_object& lhs, const asset_object& rhs) const
{ {
if ( !lhs.is_lottery() ) return false; if ( !lhs.is_lottery() ) return false;
if ( !lhs.lottery_options->is_active && !rhs.is_lottery()) return true; // not active lotteries first if ( !lhs.lottery_options->is_active && !rhs.is_lottery()) return true; // not active lotteries first, just assets then
if ( !lhs.lottery_options->is_active ) return false; if ( !lhs.lottery_options->is_active ) return false;
return lhs.get_lottery_expiration() > rhs.get_lottery_expiration(); return lhs.get_lottery_expiration() > rhs.get_lottery_expiration();
} }
@ -265,6 +265,7 @@ namespace graphene { namespace chain {
struct by_type; struct by_type;
struct by_issuer; struct by_issuer;
struct active_lotteries; struct active_lotteries;
struct by_lottery;
typedef multi_index_container< typedef multi_index_container<
asset_object, asset_object,
indexed_by< indexed_by<
@ -275,6 +276,17 @@ namespace graphene { namespace chain {
identity< asset_object >, identity< asset_object >,
lottery_asset_comparer lottery_asset_comparer
>, >,
ordered_unique< tag<by_lottery>,
composite_key<
asset_object,
const_mem_fun<asset_object, bool, &asset_object::is_lottery>,
member<object, object_id_type, &object::id>
>,
composite_key_compare<
std::greater< bool >,
std::greater< object_id_type >
>
>,
ordered_unique< tag<by_type>, ordered_unique< tag<by_type>,
composite_key< asset_object, composite_key< asset_object,
const_mem_fun<asset_object, bool, &asset_object::is_market_issued>, const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,

View file

@ -52,6 +52,9 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const; share_type calculate_fee( const fee_parameters_type& k )const;
}; };
/**
* @ingroup operations
*/
struct lottery_reward_operation : public base_operation struct lottery_reward_operation : public base_operation
{ {
struct fee_parameters_type { struct fee_parameters_type {
@ -77,6 +80,9 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const { return k.fee; }; share_type calculate_fee( const fee_parameters_type& k )const { return k.fee; };
}; };
/**
* @ingroup operations
*/
struct lottery_end_operation : public base_operation struct lottery_end_operation : public base_operation
{ {
struct fee_parameters_type { struct fee_parameters_type {
@ -87,8 +93,6 @@ namespace graphene { namespace chain {
// from what lottery is ticket // from what lottery is ticket
asset_id_type lottery; asset_id_type lottery;
// std::vector<account_id_type> participants;
map<account_id_type, vector< uint16_t> > participants; map<account_id_type, vector< uint16_t> > participants;
extensions_type extensions; extensions_type extensions;

View file

@ -43,6 +43,7 @@ void_result ticket_purchase_evaluator::do_evaluate( const ticket_purchase_operat
asset_dynamic_data = &lottery->dynamic_asset_data_id(db()); asset_dynamic_data = &lottery->dynamic_asset_data_id(db());
FC_ASSERT( asset_dynamic_data->current_supply < lottery->options.max_supply ); FC_ASSERT( asset_dynamic_data->current_supply < lottery->options.max_supply );
FC_ASSERT( (asset_dynamic_data->current_supply.value + op.tickets_to_buy) <= lottery->options.max_supply );
auto lottery_options = *lottery->lottery_options; auto lottery_options = *lottery->lottery_options;
FC_ASSERT( lottery_options.is_active ); FC_ASSERT( lottery_options.is_active );

View file

@ -108,8 +108,6 @@ namespace graphene { namespace db {
const object& get( object_id_type id )const const object& get( object_id_type id )const
{ {
auto maybe_found = find( id ); auto maybe_found = find( id );
if (maybe_found == nullptr)
idump(("fail"));
FC_ASSERT( maybe_found != nullptr, "Unable to find Object", ("id",id) ); FC_ASSERT( maybe_found != nullptr, "Unable to find Object", ("id",id) );
return *maybe_found; return *maybe_found;
} }

View file

@ -117,7 +117,14 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
impacted.insert( op.result.get<object_id_type>() ); impacted.insert( op.result.get<object_id_type>() );
else else
graphene::app::operation_get_impacted_accounts( op.op, impacted ); graphene::app::operation_get_impacted_accounts( op.op, impacted );
if( op.op.which() == operation::tag< lottery_end_operation >::value )
{
auto lop = op.op.get< lottery_end_operation >();
auto asset_object = lop.lottery( db );
impacted.insert( asset_object.issuer );
for( auto benefactor : asset_object.lottery_options->benefactors )
impacted.insert( benefactor.id );
}
for( auto& a : other ) for( auto& a : other )
for( auto& item : a.account_auths ) for( auto& item : a.account_auths )
impacted.insert( item.first ); impacted.insert( item.first );

View file

@ -349,6 +349,12 @@ class wallet_api
*/ */
vector<asset_object> list_assets(const string& lowerbound, uint32_t limit)const; vector<asset_object> list_assets(const string& lowerbound, uint32_t limit)const;
vector<asset_object> get_lotteries( asset_id_type stop = asset_id_type(),
unsigned limit = 100,
asset_id_type start = asset_id_type() )const;
asset get_lottery_balance( asset_id_type lottery_id ) const;
/** Returns the most recent operations on the named account. /** Returns the most recent operations on the named account.
* *
* This returns a list of operation history objects, which describe activity on the account. * This returns a list of operation history objects, which describe activity on the account.
@ -1009,13 +1015,14 @@ class wallet_api
fc::optional<bitasset_options> bitasset_opts, fc::optional<bitasset_options> bitasset_opts,
bool broadcast = false); bool broadcast = false);
signed_transaction create_lottery(string issuer, signed_transaction create_lottery( string issuer,
string symbol, string symbol,
uint8_t precision,
asset_options common, asset_options common,
fc::optional<bitasset_options> bitasset_opts, lottery_asset_options lottery_opts,
bool broadcast = false); bool broadcast = false);
signed_transaction buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy );
/** Issue new shares of an asset. /** Issue new shares of an asset.
* *
* @param to_account the name or id of the account to receive the new shares * @param to_account the name or id of the account to receive the new shares
@ -1956,6 +1963,8 @@ FC_API( graphene::wallet::wallet_api,
(issue_asset) (issue_asset)
(get_asset) (get_asset)
(get_bitasset_data) (get_bitasset_data)
(get_lotteries)
(get_lottery_balance)
(fund_asset_fee_pool) (fund_asset_fee_pool)
(reserve_asset) (reserve_asset)
(global_settle_asset) (global_settle_asset)
@ -2064,4 +2073,6 @@ FC_API( graphene::wallet::wallet_api,
(get_binned_order_book) (get_binned_order_book)
(get_matched_bets_for_bettor) (get_matched_bets_for_bettor)
(get_all_matched_bets_for_bettor) (get_all_matched_bets_for_bettor)
(buy_ticket)
) )

View file

@ -1447,9 +1447,8 @@ public:
signed_transaction create_lottery(string issuer, signed_transaction create_lottery(string issuer,
string symbol, string symbol,
uint8_t precision,
asset_options common, asset_options common,
fc::optional<bitasset_options> bitasset_opts, lottery_asset_options lottery_opts,
bool broadcast = false) bool broadcast = false)
{ try { { try {
account_object issuer_account = get_account( issuer ); account_object issuer_account = get_account( issuer );
@ -1458,17 +1457,10 @@ public:
asset_create_operation create_op; asset_create_operation create_op;
create_op.issuer = issuer_account.id; create_op.issuer = issuer_account.id;
create_op.symbol = symbol; create_op.symbol = symbol;
create_op.precision = precision; create_op.precision = 0;
create_op.common_options = common; create_op.common_options = common;
create_op.bitasset_opts = bitasset_opts;
lottery_asset_options lottery_options; create_op.extension = lottery_opts;
lottery_options.benefactors.push_back( benefactor( issuer_account.id, 0.5 ) );
lottery_options.end_date = _remote_db->get_dynamic_global_properties().time + fc::minutes(120);
lottery_options.ticket_price = asset(100);
lottery_options.winning_tickets.push_back(0.5);
create_op.extension = lottery_options;
signed_transaction tx; signed_transaction tx;
tx.operations.push_back( create_op ); tx.operations.push_back( create_op );
@ -1476,7 +1468,27 @@ public:
tx.validate(); tx.validate();
return sign_transaction( tx, broadcast ); return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW( (issuer)(symbol)(precision)(common)(bitasset_opts)(broadcast) ) } } FC_CAPTURE_AND_RETHROW( (issuer)(symbol)(common)(broadcast) ) }
signed_transaction buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy )
{ try {
auto asset_obj = get_asset( lottery );
FC_ASSERT( asset_obj.is_lottery() );
ticket_purchase_operation top;
top.lottery = lottery;
top.buyer = buyer;
top.tickets_to_buy = tickets_to_buy;
top.amount = asset( asset_obj.lottery_options->ticket_price.amount * tickets_to_buy, asset_obj.lottery_options->ticket_price.asset_id );
signed_transaction tx;
tx.operations.push_back( top );
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees);
tx.validate();
return sign_transaction( tx, true );
} FC_CAPTURE_AND_RETHROW( (lottery)(tickets_to_buy) ) }
signed_transaction update_asset(string symbol, signed_transaction update_asset(string symbol,
optional<string> new_issuer, optional<string> new_issuer,
@ -3494,6 +3506,18 @@ vector<asset_object> wallet_api::list_assets(const string& lowerbound, uint32_t
return my->_remote_db->list_assets( lowerbound, limit ); return my->_remote_db->list_assets( lowerbound, limit );
} }
vector<asset_object> wallet_api::get_lotteries( asset_id_type stop,
unsigned limit,
asset_id_type start )const
{
return my->_remote_db->get_lotteries( stop, limit, start );
}
asset wallet_api::get_lottery_balance( asset_id_type lottery_id )const
{
return my->_remote_db->get_lottery_balance( lottery_id );
}
vector<operation_detail> wallet_api::get_account_history(string name, int limit)const vector<operation_detail> wallet_api::get_account_history(string name, int limit)const
{ {
vector<operation_detail> result; vector<operation_detail> result;
@ -3918,16 +3942,20 @@ signed_transaction wallet_api::create_asset(string issuer,
signed_transaction wallet_api::create_lottery(string issuer, signed_transaction wallet_api::create_lottery(string issuer,
string symbol, string symbol,
uint8_t precision,
asset_options common, asset_options common,
fc::optional<bitasset_options> bitasset_opts, lottery_asset_options lottery_opts,
bool broadcast) bool broadcast)
{ {
return my->create_lottery(issuer, symbol, precision, common, bitasset_opts, broadcast); return my->create_lottery(issuer, symbol, common, lottery_opts, broadcast);
} }
signed_transaction wallet_api::buy_ticket( asset_id_type lottery, account_id_type buyer, uint64_t tickets_to_buy )
{
return my->buy_ticket(lottery, buyer, tickets_to_buy);
}
signed_transaction wallet_api::update_asset(string symbol, signed_transaction wallet_api::update_asset(string symbol,
optional<string> new_issuer, optional<string> new_issuer,
asset_options new_options, asset_options new_options,

View file

@ -43,7 +43,6 @@ BOOST_AUTO_TEST_CASE( create_lottery_asset_test )
{ {
try { try {
generate_block(); generate_block();
idump((db.head_block_time()));
asset_id_type test_asset_id = db.get_index<asset_object>().get_next_id(); asset_id_type test_asset_id = db.get_index<asset_object>().get_next_id();
asset_create_operation creator; asset_create_operation creator;
creator.issuer = account_id_type(); creator.issuer = account_id_type();
@ -65,13 +64,12 @@ BOOST_AUTO_TEST_CASE( create_lottery_asset_test )
lottery_options.ticket_price = asset(100); lottery_options.ticket_price = asset(100);
lottery_options.winning_tickets = { 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT }; lottery_options.winning_tickets = { 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 5 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT, 10 * GRAPHENE_1_PERCENT };
lottery_options.is_active = test_asset_id.instance.value % 2; lottery_options.is_active = test_asset_id.instance.value % 2;
lottery_options.ending_on_soldout = true;
creator.extension = lottery_options; creator.extension = lottery_options;
trx.operations.push_back(std::move(creator)); trx.operations.push_back(std::move(creator));
PUSH_TX( db, trx, ~0 ); PUSH_TX( db, trx, ~0 );
idump((lottery_options.end_date));
idump((db.head_block_time()));
generate_block(); generate_block();
auto test_asset = test_asset_id(db); auto test_asset = test_asset_id(db);
@ -373,13 +371,10 @@ BOOST_AUTO_TEST_CASE( more_winners_then_participants_test )
generate_block(); generate_block();
test_asset = test_asset_id(db); test_asset = test_asset_id(db);
auto holders = test_asset.get_holders(db); auto holders = test_asset.get_holders(db);
idump(( db.get_balance(test_asset.get_id()) ));
auto participants = test_asset.distribute_winners_part( db ); auto participants = test_asset.distribute_winners_part( db );
test_asset.distribute_benefactors_part( db ); test_asset.distribute_benefactors_part( db );
test_asset.distribute_sweeps_holders_part( db ); test_asset.distribute_sweeps_holders_part( db );
generate_block(); generate_block();
idump(( db.get_balance(test_asset.get_id()) ));
idump(( participants ));
for( auto p: participants ) { for( auto p: participants ) {
idump(( get_operation_history(p.first) )); idump(( get_operation_history(p.first) ));
} }
@ -442,6 +437,35 @@ BOOST_AUTO_TEST_CASE( ending_by_date_test )
} }
} }
BOOST_AUTO_TEST_CASE( ending_by_participants_count_test )
{
try {
asset_id_type test_asset_id = db.get_index<asset_object>().get_next_id();
INVOKE( create_lottery_asset_test );
auto test_asset = test_asset_id(db);
FC_ASSERT( test_asset.lottery_options->is_active );
account_id_type buyer(3);
transfer(account_id_type(), buyer, asset(10000000));
ticket_purchase_operation tpo;
tpo.fee = asset();
tpo.buyer = buyer;
tpo.lottery = test_asset.id;
tpo.tickets_to_buy = 200;
tpo.amount = asset(200 * 100);
trx.operations.push_back(tpo);
graphene::chain::test::set_expiration(db, trx);
PUSH_TX( db, trx, ~0 );
trx.operations.clear();
generate_block();
test_asset = test_asset_id(db);
FC_ASSERT( !test_asset.lottery_options->is_active );
} catch( fc::exception& e ) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( try_to_end_empty_lottery_test ) BOOST_AUTO_TEST_CASE( try_to_end_empty_lottery_test )
{ {
try { try {