Merge pull request #340 from peerplays-network/feature/nh5050_winner_id
Feature/nh5050 winner_ticket_id changes
This commit is contained in:
commit
b857603f10
5 changed files with 114 additions and 3 deletions
|
|
@ -23,6 +23,8 @@
|
|||
*/
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
|
@ -185,6 +187,41 @@ vector<account_id_type> asset_object::get_holders( database& db ) const
|
|||
return holders;
|
||||
}
|
||||
|
||||
vector<uint64_t> asset_object::get_ticket_ids( database& db ) const
|
||||
{
|
||||
auto& asset_bal_idx = db.get_index_type< account_balance_index >().indices().get< by_asset_balance >();
|
||||
vector<uint64_t> ids;
|
||||
const auto range = asset_bal_idx.equal_range( boost::make_tuple( get_id() ) );
|
||||
|
||||
for( const account_balance_object& bal : boost::make_iterator_range( range.first, range.second ) )
|
||||
{
|
||||
const auto& stats = bal.owner(db).statistics(db);
|
||||
const account_transaction_history_object* ath = static_cast<const account_transaction_history_object*>(&stats.most_recent_op(db));
|
||||
for( uint64_t balance = bal.balance.value; balance > 0;)
|
||||
{
|
||||
if(ath != nullptr)
|
||||
{
|
||||
const operation_history_object& oho = db.get<operation_history_object>( ath->operation_id );
|
||||
if( oho.op.which() == operation::tag<ticket_purchase_operation>::value && get_id() == oho.op.get<ticket_purchase_operation>().lottery)
|
||||
{
|
||||
uint64_t tickets_count = oho.op.get<ticket_purchase_operation>().tickets_to_buy;
|
||||
ids.insert(ids.end(), tickets_count, oho.id.instance());
|
||||
balance -= tickets_count;
|
||||
assert(balance >= 0);
|
||||
}
|
||||
|
||||
if( ath->next == account_transaction_history_id_type() )
|
||||
{
|
||||
ath = nullptr;
|
||||
break;
|
||||
}
|
||||
else ath = db.find(ath->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void asset_object::distribute_benefactors_part( database& db )
|
||||
{
|
||||
transaction_evaluation_state eval( &db );
|
||||
|
|
@ -206,6 +243,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
|
|||
transaction_evaluation_state eval( &db );
|
||||
|
||||
auto holders = get_holders( db );
|
||||
vector<uint64_t> ticket_ids = get_ticket_ids(db);
|
||||
FC_ASSERT( dynamic_data( db ).current_supply == holders.size() );
|
||||
map<account_id_type, vector<uint16_t> > structurized_participants;
|
||||
for( account_id_type holder : holders )
|
||||
|
|
@ -234,6 +272,11 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
|
|||
reward_op.lottery = get_id();
|
||||
reward_op.is_benefactor_reward = false;
|
||||
reward_op.winner = holders[winner_num];
|
||||
if(db.head_block_time() > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
|
||||
{
|
||||
const static_variant<uint64_t, void_t> tkt_id = ticket_ids[winner_num];
|
||||
reward_op.winner_ticket_id = tkt_id;
|
||||
}
|
||||
reward_op.win_percentage = tickets[c];
|
||||
reward_op.amount = asset( jackpot * tickets[c] * ( 1. - sweeps_distribution_percentage / (double)GRAPHENE_100_PERCENT ) / GRAPHENE_100_PERCENT , db.get_balance(id).asset_id );
|
||||
db.apply_operation(eval, reward_op);
|
||||
|
|
|
|||
4
libraries/chain/hardfork.d/5050-1.hf
Normal file
4
libraries/chain/hardfork.d/5050-1.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// 5050_1 HARDFORK Thursday, 16 April 2020 19:00:00 GMT
|
||||
#ifndef HARDFORK_5050_1_TIME
|
||||
#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1587063600 ))
|
||||
#endif
|
||||
|
|
@ -134,6 +134,7 @@ namespace graphene { namespace chain {
|
|||
optional<lottery_asset_options> lottery_options;
|
||||
time_point_sec get_lottery_expiration() const;
|
||||
vector<account_id_type> get_holders( database& db ) const;
|
||||
vector<uint64_t> get_ticket_ids( database& db ) const;
|
||||
void distribute_benefactors_part( database& db );
|
||||
map< account_id_type, vector< uint16_t > > distribute_winners_part( database& db );
|
||||
void distribute_sweeps_holders_part( database& db );
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ namespace graphene { namespace chain {
|
|||
share_type calculate_fee( const fee_parameters_type& k )const;
|
||||
};
|
||||
|
||||
typedef static_variant<uint64_t, void_t> ticket_num;
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
|
|
@ -73,7 +75,7 @@ namespace graphene { namespace chain {
|
|||
// true if recieved from benefators section of lottery; false otherwise
|
||||
bool is_benefactor_reward;
|
||||
|
||||
extensions_type extensions;
|
||||
ticket_num winner_ticket_id;
|
||||
|
||||
account_id_type fee_payer()const { return account_id_type(); }
|
||||
void validate()const {};
|
||||
|
|
@ -114,7 +116,7 @@ FC_REFLECT( graphene::chain::ticket_purchase_operation,
|
|||
)
|
||||
FC_REFLECT( graphene::chain::ticket_purchase_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::ticket_num )
|
||||
FC_REFLECT( graphene::chain::lottery_reward_operation,
|
||||
(fee)
|
||||
(lottery)
|
||||
|
|
@ -122,7 +124,7 @@ FC_REFLECT( graphene::chain::lottery_reward_operation,
|
|||
(amount)
|
||||
(win_percentage)
|
||||
(is_benefactor_reward)
|
||||
(extensions)
|
||||
(winner_ticket_id)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::lottery_reward_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ BOOST_AUTO_TEST_CASE( create_lottery_asset_test )
|
|||
lottery_options.end_date = db.head_block_time() + fc::minutes(5);
|
||||
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 = { 75 * GRAPHENE_1_PERCENT };
|
||||
lottery_options.is_active = test_asset_id.instance.value % 2;
|
||||
lottery_options.ending_on_soldout = true;
|
||||
|
||||
|
|
@ -482,4 +483,64 @@ BOOST_AUTO_TEST_CASE( try_to_end_empty_lottery_test )
|
|||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( lottery_winner_ticket_id_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);
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
transfer(account_id_type(), account_id_type(i), asset(2000000));
|
||||
}
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
if( i == 4 ) continue;
|
||||
ticket_purchase_operation tpo;
|
||||
tpo.buyer = account_id_type(i);
|
||||
tpo.lottery = test_asset.id;
|
||||
tpo.tickets_to_buy = 1;
|
||||
tpo.amount = asset(100);
|
||||
trx.operations.push_back(std::move(tpo));
|
||||
graphene::chain::test::set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
|
||||
for( int i = 1; i < 4; ++i ) {
|
||||
if( i == 4 ) continue;
|
||||
ticket_purchase_operation tpo;
|
||||
tpo.buyer = account_id_type(i);
|
||||
tpo.lottery = test_asset.id;
|
||||
tpo.tickets_to_buy = 1;
|
||||
tpo.amount = asset(100);
|
||||
trx.operations.push_back(std::move(tpo));
|
||||
graphene::chain::test::set_expiration(db, trx);
|
||||
PUSH_TX( db, trx, ~0 );
|
||||
trx.operations.clear();
|
||||
}
|
||||
generate_block();
|
||||
test_asset = test_asset_id(db);
|
||||
uint64_t creator_balance_before_end = db.get_balance( account_id_type(), asset_id_type() ).amount.value;
|
||||
uint64_t jackpot = db.get_balance( test_asset.get_id() ).amount.value;
|
||||
uint16_t winners_part = 0;
|
||||
for( uint8_t win: test_asset.lottery_options->winning_tickets )
|
||||
winners_part += win;
|
||||
|
||||
while( db.head_block_time() < ( test_asset.lottery_options->end_date ) )
|
||||
generate_block();
|
||||
|
||||
auto op_history = get_operation_history( account_id_type(1) ); //Can observe operation 79 to verify winner ticket number
|
||||
for( auto h: op_history ) {
|
||||
idump((h));
|
||||
}
|
||||
|
||||
BOOST_CHECK( db.get_balance( test_asset.get_id() ).amount.value == 0 );
|
||||
uint64_t creator_recieved = db.get_balance( account_id_type(), asset_id_type() ).amount.value - creator_balance_before_end;
|
||||
test_asset = test_asset_id(db);
|
||||
BOOST_CHECK(jackpot * test_asset.lottery_options->benefactors[0].share / GRAPHENE_100_PERCENT == creator_recieved);
|
||||
} catch (fc::exception& e) {
|
||||
edump((e.to_detail_string()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
Loading…
Reference in a new issue