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_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
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;
@ -174,7 +182,6 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
if( !is_subscribed_to_item(i) )
{
idump((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)
{
idump((names_or_ids));
std::map<std::string, full_account> results;
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;
}
////////////////////
// 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 //
//////////////////////////////////////////////////////////////////////

View file

@ -348,7 +348,23 @@ class database_api
* This function has semantics identical to @ref get_objects
*/
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 //
/////////////////////
@ -733,7 +749,11 @@ FC_API(graphene::app::database_api,
(list_betting_markets)
(get_unmatched_bets_for_bettor)
(get_all_unmatched_bets_for_bettor)
// Lottery assets
(get_lotteries)
(get_lottery_balance)
// Markets / feeds
(get_order_book)
(get_limit_orders)

View file

@ -90,7 +90,6 @@ add_library( graphene_chain
account_object.cpp
asset_object.cpp
lottery.cpp
fba_object.cpp
proposal_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 )
{
idump(( "end_lottery" ));
transaction_evaluation_state eval(&db);
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 );
if( participants.size() > 0) {

View file

@ -142,8 +142,6 @@ void database::open(
if( last_block.valid() )
{
_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() )
{
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()
{
const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>();
for( auto checking_asset: lotteries_idx )
{
if( !checking_asset.is_lottery() ) break;
if( !checking_asset.lottery_options->is_active ) break;
if( checking_asset.lottery_options->end_date >= head_block_time() ) break;
checking_asset.end_lottery(*this);
}
try {
const auto& lotteries_idx = get_index_type<asset_index>().indices().get<active_lotteries>();
for( auto checking_asset: lotteries_idx )
{
FC_ASSERT( checking_asset.is_lottery() );
FC_ASSERT( checking_asset.lottery_options->is_active );
FC_ASSERT( checking_asset.lottery_options->end_date < head_block_time() );
checking_asset.end_lottery(*this);
}
} catch( ... ) {}
}
void database::check_lottery_end_by_participants( asset_id_type asset_id )
{
asset_object asset_to_check = asset_id( *this );
if( !asset_to_check.is_lottery() ) return;
if( !asset_to_check.lottery_options->ending_on_soldout ) return;
asset_to_check.end_lottery( *this );
try {
asset_object asset_to_check = asset_id( *this );
auto asset_dyn_props = asset_to_check.dynamic_data( *this );
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 );
} catch( ... ) {}
}
} }

View file

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

View file

@ -147,7 +147,7 @@ namespace graphene { namespace chain {
optional<asset_dividend_data_id_type> dividend_data_id;
asset_id_type get_id()const { return id; }
void validate()const
{
// UIAs may not be prediction markets, have force settlement, or global settlements
@ -255,7 +255,7 @@ namespace graphene { namespace chain {
bool operator()(const asset_object& lhs, const asset_object& rhs) const
{
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;
return lhs.get_lottery_expiration() > rhs.get_lottery_expiration();
}
@ -265,6 +265,7 @@ namespace graphene { namespace chain {
struct by_type;
struct by_issuer;
struct active_lotteries;
struct by_lottery;
typedef multi_index_container<
asset_object,
indexed_by<
@ -275,6 +276,17 @@ namespace graphene { namespace chain {
identity< asset_object >,
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>,
composite_key< asset_object,
const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,

View file

@ -95,7 +95,7 @@ namespace graphene { namespace chain {
flat_set<asset_id_type> whitelist_markets;
/** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */
flat_set<asset_id_type> blacklist_markets;
/**
* data that describes the meaning/purpose of this asset, fee will be charged proportional to
* size of description.

View file

@ -52,6 +52,9 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const;
};
/**
* @ingroup operations
*/
struct lottery_reward_operation : public base_operation
{
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; };
};
/**
* @ingroup operations
*/
struct lottery_end_operation : public base_operation
{
struct fee_parameters_type {
@ -86,9 +92,7 @@ namespace graphene { namespace chain {
asset fee;
// from what lottery is ticket
asset_id_type lottery;
// std::vector<account_id_type> participants;
map<account_id_type, vector< uint16_t> > participants;
extensions_type extensions;

View file

@ -43,7 +43,8 @@ void_result ticket_purchase_evaluator::do_evaluate( const ticket_purchase_operat
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.value + op.tickets_to_buy) <= lottery->options.max_supply );
auto lottery_options = *lottery->lottery_options;
FC_ASSERT( lottery_options.is_active );
FC_ASSERT( lottery_options.ticket_price.asset_id == op.amount.asset_id );

View file

@ -108,8 +108,6 @@ namespace graphene { namespace db {
const object& get( object_id_type id )const
{
auto maybe_found = find( id );
if (maybe_found == nullptr)
idump(("fail"));
FC_ASSERT( maybe_found != nullptr, "Unable to find Object", ("id",id) );
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>() );
else
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& item : a.account_auths )
impacted.insert( item.first );

View file

@ -348,7 +348,13 @@ class wallet_api
* @returns the list of asset objects, ordered by symbol
*/
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.
*
* This returns a list of operation history objects, which describe activity on the account.
@ -1009,12 +1015,13 @@ class wallet_api
fc::optional<bitasset_options> bitasset_opts,
bool broadcast = false);
signed_transaction create_lottery(string issuer,
string symbol,
uint8_t precision,
asset_options common,
fc::optional<bitasset_options> bitasset_opts,
bool broadcast = false);
signed_transaction create_lottery( string issuer,
string symbol,
asset_options common,
lottery_asset_options lottery_opts,
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.
*
@ -1956,6 +1963,8 @@ FC_API( graphene::wallet::wallet_api,
(issue_asset)
(get_asset)
(get_bitasset_data)
(get_lotteries)
(get_lottery_balance)
(fund_asset_fee_pool)
(reserve_asset)
(global_settle_asset)
@ -2064,4 +2073,6 @@ 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

@ -1447,9 +1447,8 @@ public:
signed_transaction create_lottery(string issuer,
string symbol,
uint8_t precision,
asset_options common,
fc::optional<bitasset_options> bitasset_opts,
lottery_asset_options lottery_opts,
bool broadcast = false)
{ try {
account_object issuer_account = get_account( issuer );
@ -1458,17 +1457,10 @@ public:
asset_create_operation create_op;
create_op.issuer = issuer_account.id;
create_op.symbol = symbol;
create_op.precision = precision;
create_op.precision = 0;
create_op.common_options = common;
create_op.bitasset_opts = bitasset_opts;
lottery_asset_options lottery_options;
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;
create_op.extension = lottery_opts;
signed_transaction tx;
tx.operations.push_back( create_op );
@ -1476,8 +1468,28 @@ public:
tx.validate();
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,
optional<string> new_issuer,
asset_options new_options,
@ -3494,6 +3506,18 @@ vector<asset_object> wallet_api::list_assets(const string& lowerbound, uint32_t
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> result;
@ -3917,17 +3941,21 @@ signed_transaction wallet_api::create_asset(string issuer,
}
signed_transaction wallet_api::create_lottery(string issuer,
string symbol,
uint8_t precision,
asset_options common,
fc::optional<bitasset_options> bitasset_opts,
bool broadcast)
string symbol,
asset_options common,
lottery_asset_options lottery_opts,
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,
optional<string> new_issuer,
asset_options new_options,

View file

@ -43,7 +43,6 @@ BOOST_AUTO_TEST_CASE( create_lottery_asset_test )
{
try {
generate_block();
idump((db.head_block_time()));
asset_id_type test_asset_id = db.get_index<asset_object>().get_next_id();
asset_create_operation creator;
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.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.ending_on_soldout = true;
creator.extension = lottery_options;
trx.operations.push_back(std::move(creator));
PUSH_TX( db, trx, ~0 );
idump((lottery_options.end_date));
idump((db.head_block_time()));
generate_block();
auto test_asset = test_asset_id(db);
@ -334,7 +332,7 @@ BOOST_AUTO_TEST_CASE( claim_sweeps_vesting_balance_test )
sweeps_vesting_claim_operation claim;
claim.account = benefactor;
claim.amount_to_claim = available_for_claim;
trx.clear();
trx.clear();
graphene::chain::test::set_expiration(db, trx);
trx.operations.push_back(claim);
PUSH_TX( db, trx, ~0 );
@ -373,13 +371,10 @@ BOOST_AUTO_TEST_CASE( more_winners_then_participants_test )
generate_block();
test_asset = test_asset_id(db);
auto holders = test_asset.get_holders(db);
idump(( db.get_balance(test_asset.get_id()) ));
auto participants = test_asset.distribute_winners_part( db );
test_asset.distribute_benefactors_part( db );
test_asset.distribute_sweeps_holders_part( db );
generate_block();
idump(( db.get_balance(test_asset.get_id()) ));
idump(( participants ));
for( auto p: participants ) {
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 )
{
try {