From 29f41ec7da13aaa259dee572ad3130cd1f3b8b1c Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Mon, 6 Apr 2020 12:30:55 -0300
Subject: [PATCH 1/8] nh5050:winner ticket id changes
---
libraries/chain/asset_object.cpp | 39 +++++++++++
libraries/chain/hardfork.d/5050-1.hf | 4 ++
.../include/graphene/chain/asset_object.hpp | 1 +
.../graphene/chain/protocol/lottery_ops.hpp | 8 ++-
tests/tests/lottery_tests.cpp | 68 +++++++++++++++++++
5 files changed, 117 insertions(+), 3 deletions(-)
create mode 100644 libraries/chain/hardfork.d/5050-1.hf
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index 88e5dfca..439f5ad4 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -23,6 +23,7 @@
*/
#include
#include
+#include
#include
#include
@@ -185,6 +186,37 @@ vector asset_object::get_holders( database& db ) const
return holders;
}
+vector 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 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(&stats.most_recent_op(db));
+ for( uint64_t balance = bal.balance.value; balance > 0; --balance)
+ {
+ if(ath != nullptr)
+ {
+ const operation_history_object& oho = db.get( ath->operation_id );
+ if( oho.op.which() == operation::tag::value )
+ ids.push_back( oho.id.instance());
+
+ if( ath->next == account_transaction_history_id_type() )
+ {
+ ids.insert(ids.end(), balance-1, oho.id.instance());
+ 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 +238,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
transaction_evaluation_state eval( &db );
auto holders = get_holders( db );
+ vector ticket_ids = get_ticket_ids(db);
FC_ASSERT( dynamic_data( db ).current_supply == holders.size() );
map > structurized_participants;
for( account_id_type holder : holders )
@@ -234,6 +267,12 @@ 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];
+ time_point_sec now = time_point::now();
+ if(now < HARDFORK_GPOS_TIME)
+ {
+ const static_variant 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);
diff --git a/libraries/chain/hardfork.d/5050-1.hf b/libraries/chain/hardfork.d/5050-1.hf
new file mode 100644
index 00000000..db3af2cd
--- /dev/null
+++ b/libraries/chain/hardfork.d/5050-1.hf
@@ -0,0 +1,4 @@
+// 5050_1 HARDFORK Sunday, 5 April 2020 15:00:00 GMT
+#ifndef HARDFORK_5050_1_TIME
+#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1586098800 ))
+#endif
diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp
index 8978a6d1..95d36ed4 100644
--- a/libraries/chain/include/graphene/chain/asset_object.hpp
+++ b/libraries/chain/include/graphene/chain/asset_object.hpp
@@ -134,6 +134,7 @@ namespace graphene { namespace chain {
optional lottery_options;
time_point_sec get_lottery_expiration() const;
vector get_holders( database& db ) const;
+ vector 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 );
diff --git a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
index 32d70a37..5114ad90 100644
--- a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
+++ b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
@@ -52,6 +52,8 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const;
};
+ typedef static_variant 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) )
diff --git a/tests/tests/lottery_tests.cpp b/tests/tests/lottery_tests.cpp
index b0f234e2..9499136a 100644
--- a/tests/tests/lottery_tests.cpp
+++ b/tests/tests/lottery_tests.cpp
@@ -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,71 @@ 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().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;
+
+ auto participants = test_asset.distribute_winners_part( db );
+ test_asset.distribute_benefactors_part( db );
+ test_asset.distribute_sweeps_holders_part( db );
+ generate_block();
+ for( auto p: participants ) {
+ idump(( get_operation_history(p.first) ));
+ }
+ auto benefactor_history = get_operation_history( account_id_type() );
+ for( auto h: benefactor_history ) {
+ idump((h));
+ }
+
+ while( db.head_block_time() < ( test_asset.lottery_options->end_date + fc::seconds(30) ) )
+ generate_block();
+
+ 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()
From 9ffce8f33c92d60d5acf695bb6ac5b022c6d1795 Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Mon, 6 Apr 2020 14:45:50 -0300
Subject: [PATCH 2/8] update HF check
---
libraries/chain/asset_object.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index 439f5ad4..29c0db1e 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
@@ -268,7 +269,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
reward_op.is_benefactor_reward = false;
reward_op.winner = holders[winner_num];
time_point_sec now = time_point::now();
- if(now < HARDFORK_GPOS_TIME)
+ if(now < HARDFORK_5050_1_TIME)
{
const static_variant tkt_id = ticket_ids[winner_num];
reward_op.winner_ticket_id = tkt_id;
From e445e1a11c2350c3e7d6f8ab12050819e9660ea3 Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Mon, 6 Apr 2020 14:47:38 -0300
Subject: [PATCH 3/8] update HF-check
---
libraries/chain/asset_object.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index 29c0db1e..989c417a 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -269,7 +269,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
reward_op.is_benefactor_reward = false;
reward_op.winner = holders[winner_num];
time_point_sec now = time_point::now();
- if(now < HARDFORK_5050_1_TIME)
+ if(now > HARDFORK_5050_1_TIME)
{
const static_variant tkt_id = ticket_ids[winner_num];
reward_op.winner_ticket_id = tkt_id;
From cb7429e8188a570182cebf1bded52940d612781d Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Tue, 7 Apr 2020 01:31:17 -0300
Subject: [PATCH 4/8] code improvement with edge case handling
---
libraries/chain/asset_object.cpp | 7 ++++---
.../graphene/chain/protocol/lottery_ops.hpp | 2 +-
tests/tests/lottery_tests.cpp | 17 +++++------------
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index 989c417a..f6585075 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -207,7 +207,8 @@ vector asset_object::get_ticket_ids( database& db ) const
if( ath->next == account_transaction_history_id_type() )
{
- ids.insert(ids.end(), balance-1, oho.id.instance());
+ if(balance > 1 && oho.op.which() == operation::tag::value)
+ ids.insert(ids.end(), balance-1, oho.id.instance());
ath = nullptr;
break;
}
@@ -269,9 +270,9 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
reward_op.is_benefactor_reward = false;
reward_op.winner = holders[winner_num];
time_point_sec now = time_point::now();
- if(now > HARDFORK_5050_1_TIME)
+ if(now > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
{
- const static_variant tkt_id = ticket_ids[winner_num];
+ const static_variant tkt_id = ticket_ids[winner_num];
reward_op.winner_ticket_id = tkt_id;
}
reward_op.win_percentage = tickets[c];
diff --git a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
index 5114ad90..0bc64129 100644
--- a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
+++ b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
@@ -52,7 +52,7 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const;
};
- typedef static_variant ticket_num;
+ typedef static_variant ticket_num;
/**
* @ingroup operations
diff --git a/tests/tests/lottery_tests.cpp b/tests/tests/lottery_tests.cpp
index 9499136a..063c15c1 100644
--- a/tests/tests/lottery_tests.cpp
+++ b/tests/tests/lottery_tests.cpp
@@ -525,21 +525,14 @@ BOOST_AUTO_TEST_CASE( lottery_winner_ticket_id_test )
for( uint8_t win: test_asset.lottery_options->winning_tickets )
winners_part += win;
- auto participants = test_asset.distribute_winners_part( db );
- test_asset.distribute_benefactors_part( db );
- test_asset.distribute_sweeps_holders_part( db );
- generate_block();
- for( auto p: participants ) {
- idump(( get_operation_history(p.first) ));
- }
- auto benefactor_history = get_operation_history( account_id_type() );
- for( auto h: benefactor_history ) {
+ 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));
}
- while( db.head_block_time() < ( test_asset.lottery_options->end_date + fc::seconds(30) ) )
- generate_block();
-
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);
From dd88b8f1ffcc59b133471fd5830eb3f8155e9758 Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Wed, 8 Apr 2020 09:05:39 -0300
Subject: [PATCH 5/8] update HF check
---
libraries/chain/asset_object.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index f6585075..288d7db9 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -269,8 +269,7 @@ 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];
- time_point_sec now = time_point::now();
- if(now > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
+ if(db.head_block_time() > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
{
const static_variant tkt_id = ticket_ids[winner_num];
reward_op.winner_ticket_id = tkt_id;
From e3cf4ab9e2d26945cc90af751898530e32fe8cab Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Thu, 9 Apr 2020 22:05:18 -0300
Subject: [PATCH 6/8] changes to fetch operations based on lottery asset
---
libraries/chain/asset_object.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index 288d7db9..f357e541 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -197,18 +197,21 @@ vector asset_object::get_ticket_ids( database& db ) const
{
const auto& stats = bal.owner(db).statistics(db);
const account_transaction_history_object* ath = static_cast(&stats.most_recent_op(db));
- for( uint64_t balance = bal.balance.value; balance > 0; --balance)
+ for( uint64_t balance = bal.balance.value; balance > 0;)
{
if(ath != nullptr)
{
const operation_history_object& oho = db.get( ath->operation_id );
- if( oho.op.which() == operation::tag::value )
- ids.push_back( oho.id.instance());
+ if( oho.op.which() == operation::tag::value && get_id() == oho.op.get().lottery)
+ {
+ uint64_t tickets_count = oho.op.get().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() )
{
- if(balance > 1 && oho.op.which() == operation::tag::value)
- ids.insert(ids.end(), balance-1, oho.id.instance());
ath = nullptr;
break;
}
From f701f03401ada001453e3e4984fb11af57492fa7 Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Fri, 10 Apr 2020 08:53:25 -0300
Subject: [PATCH 7/8] update HF date 16th April 2020
---
libraries/chain/hardfork.d/5050-1.hf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libraries/chain/hardfork.d/5050-1.hf b/libraries/chain/hardfork.d/5050-1.hf
index db3af2cd..4b5fa382 100644
--- a/libraries/chain/hardfork.d/5050-1.hf
+++ b/libraries/chain/hardfork.d/5050-1.hf
@@ -1,4 +1,4 @@
-// 5050_1 HARDFORK Sunday, 5 April 2020 15:00:00 GMT
+// 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( 1586098800 ))
+#define HARDFORK_5050_1_TIME (fc::time_point_sec( 1587063600 ))
#endif
From 03ebcc6f3beecf332b6a98156eda3270b8291fda Mon Sep 17 00:00:00 2001
From: pbattu123
Date: Fri, 10 Apr 2020 09:39:09 -0300
Subject: [PATCH 8/8] update variable type to uint64
---
libraries/chain/asset_object.cpp | 8 ++++----
libraries/chain/include/graphene/chain/asset_object.hpp | 2 +-
.../chain/include/graphene/chain/protocol/lottery_ops.hpp | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp
index f357e541..82951d79 100644
--- a/libraries/chain/asset_object.cpp
+++ b/libraries/chain/asset_object.cpp
@@ -187,10 +187,10 @@ vector asset_object::get_holders( database& db ) const
return holders;
}
-vector asset_object::get_ticket_ids( database& db ) const
+vector 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 ids;
+ vector 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 ) )
@@ -243,7 +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 ticket_ids = get_ticket_ids(db);
+ vector ticket_ids = get_ticket_ids(db);
FC_ASSERT( dynamic_data( db ).current_supply == holders.size() );
map > structurized_participants;
for( account_id_type holder : holders )
@@ -274,7 +274,7 @@ map< account_id_type, vector< uint16_t > > asset_object::distribute_winners_part
reward_op.winner = holders[winner_num];
if(db.head_block_time() > HARDFORK_5050_1_TIME && ticket_ids.size() >= winner_num)
{
- const static_variant tkt_id = ticket_ids[winner_num];
+ const static_variant tkt_id = ticket_ids[winner_num];
reward_op.winner_ticket_id = tkt_id;
}
reward_op.win_percentage = tickets[c];
diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp
index 95d36ed4..d8c65e89 100644
--- a/libraries/chain/include/graphene/chain/asset_object.hpp
+++ b/libraries/chain/include/graphene/chain/asset_object.hpp
@@ -134,7 +134,7 @@ namespace graphene { namespace chain {
optional lottery_options;
time_point_sec get_lottery_expiration() const;
vector get_holders( database& db ) const;
- vector get_ticket_ids( database& db ) const;
+ vector 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 );
diff --git a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
index 0bc64129..4f512bce 100644
--- a/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
+++ b/libraries/chain/include/graphene/chain/protocol/lottery_ops.hpp
@@ -52,7 +52,7 @@ namespace graphene { namespace chain {
share_type calculate_fee( const fee_parameters_type& k )const;
};
- typedef static_variant ticket_num;
+ typedef static_variant ticket_num;
/**
* @ingroup operations