From c2f3beb5d6c895086b0620dd9522932b5f7661c5 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Thu, 1 Sep 2016 14:28:46 -0400 Subject: [PATCH] Initial data structures for creating/joining tournaments --- libraries/app/impacted.cpp | 10 + libraries/chain/CMakeLists.txt | 1 + libraries/chain/db_init.cpp | 3 + .../graphene/chain/protocol/operations.hpp | 5 +- .../chain/protocol/rock_paper_scissors.hpp | 55 ++++++ .../graphene/chain/protocol/tournament.hpp | 172 ++++++++++++++++++ .../include/graphene/chain/protocol/types.hpp | 5 + .../graphene/chain/tournament_object.hpp | 45 +++++ libraries/chain/protocol/tournament.cpp | 56 ++++++ libraries/fc | 2 +- .../wallet/include/graphene/wallet/wallet.hpp | 7 + libraries/wallet/wallet.cpp | 16 ++ 12 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/protocol/rock_paper_scissors.hpp create mode 100644 libraries/chain/include/graphene/chain/protocol/tournament.hpp create mode 100644 libraries/chain/include/graphene/chain/tournament_object.hpp create mode 100644 libraries/chain/protocol/tournament.cpp diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 85787423..b7e3a3d6 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -202,6 +202,16 @@ struct get_impacted_account_visitor { _impacted.insert( op.account_id ); } + void operator()( const tournament_create_operation& op ) + { + _impacted.insert( op.creator ); + _impacted.insert( op.options.whitelist.begin(), op.options.whitelist.end() ); + } + void operator()( const tournament_join_operation& op ) + { + _impacted.insert( op.payer_account_id ); + _impacted.insert( op.player_account_id ); + } }; diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 9cc4285d..c7e49b5d 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -56,6 +56,7 @@ add_library( graphene_chain protocol/fee_schedule.cpp protocol/confidential.cpp protocol/vote.cpp + protocol/tournament.cpp genesis_state.cpp get_config.cpp diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index ffe52715..68b8c583 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -200,6 +201,8 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index >(); + add_index< primary_index >(); + //Implementation object indexes add_index< primary_index >(); add_index< primary_index >(); diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 7f2639f1..c5d1a084 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -91,7 +92,9 @@ namespace graphene { namespace chain { transfer_from_blind_operation, asset_settle_cancel_operation, // VIRTUAL asset_claim_fees_operation, - fba_distribute_operation // VIRTUAL + fba_distribute_operation, // VIRTUAL + tournament_create_operation, + tournament_join_operation > operation; /// @} // operations group diff --git a/libraries/chain/include/graphene/chain/protocol/rock_paper_scissors.hpp b/libraries/chain/include/graphene/chain/protocol/rock_paper_scissors.hpp new file mode 100644 index 00000000..da43627e --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/rock_paper_scissors.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace graphene { namespace chain { + + struct rock_paper_scissors_game_options + { + /// If true and a user fails to commit their move before the time_per_commit_move expires, + /// the blockchain will randomly choose a move for the user + bool insurance_enabled; + /// The number of seconds users are given to commit their next move, counted from the beginning + /// of the hand (during the game, a hand begins immediately on the block containing the + /// second player's reveal or where the time_per_reveal move has expired) + uint32_t time_per_commit_move; + + /// The number of seconds users are given to reveal their move, counted from the time of the + /// block containing the second commit or the where the time_per_commit_move expired + uint32_t time_per_reveal_move; + }; + +} } + +FC_REFLECT( graphene::chain::rock_paper_scissors_game_options, (insurance_enabled)(time_per_commit_move)(time_per_reveal_move) ) + + diff --git a/libraries/chain/include/graphene/chain/protocol/tournament.hpp b/libraries/chain/include/graphene/chain/protocol/tournament.hpp new file mode 100644 index 00000000..fbc4099f --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/tournament.hpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace graphene { namespace chain { + + /** + * @brief List of games currently supported on the blockchain + */ + enum game_type + { + rock_paper_scissors, + GAME_TYPE_COUNT + }; + + typedef fc::static_variant game_specific_options; + + /** + * @brief Options specified when creating a new tournament + */ + struct tournament_options + { + /// The type of game in this tournament + uint16_t type_of_game; /* actually a game_type, but that doesn't reflect properly */ + + /// If there aren't enough players registered for the tournament before this time, + /// the tournament is canceled + fc::time_point_sec registration_deadline; + + /// Number of players in the tournament. This must be a power of 2. + uint32_t number_of_players; + + /// Each player must pay this much to join the tournament. This can be + /// in any asset supported by the blockchain. If the tournament is canceled, + /// the buy-in will be returned. + asset buy_in; + + /// A list of all accounts allowed to register for this tournament. If empty, + /// anyone can register for the tournament + flat_set whitelist; + + /// If specified, this is the time the tourament will start (must not be before the registration + /// deadline). If this is not specified, the creator must specify `start_delay` instead. + optional start_time; + + /// If specified, this is the number of seconds after the final player registers before the + /// tournament begins. If this is not specified, the creator must specify an absolute `start_time` + optional start_delay; + + /// The delay, in seconds, between the end of the last game in one round of the tournament and the + /// start of all the games in the next round + uint32_t round_delay; + + /// The winner of a round in the tournament is the first to reach this number of wins + uint32_t number_of_wins; + + /// Parameters that are specific to the type_of_game in this tournament + game_specific_options game_options; + + void validate() const; + }; + + struct tournament_create_operation : public base_operation + { + struct fee_parameters_type { + share_type fee = GRAPHENE_BLOCKCHAIN_PRECISION; + uint32_t price_per_kbyte = 10; + }; + + asset fee; + + /// The account that created the tournament + account_id_type creator; + + /// Options for the tournament + tournament_options options; + + extensions_type extensions; + + account_id_type fee_payer()const { return creator; } + share_type calculate_fee(const fee_parameters_type& k)const; + void validate()const; + }; + + struct tournament_join_operation : public base_operation + { + struct fee_parameters_type { + share_type fee = GRAPHENE_BLOCKCHAIN_PRECISION; + }; + + asset fee; + + /// The account that is paying the buy-in for the tournament, if the tournament is + /// canceled, will be refunded the buy-in. + account_id_type payer_account_id; + + /// The account that will play in the tournament, will receive any winnings. + account_id_type player_account_id; + + /// The tournament `player_account_id` is joining + tournament_id_type tournament_id; + + /// The buy-in paid by the `payer_account_id` + asset buy_in; + + extensions_type extensions; + account_id_type fee_payer()const { return payer_account_id; } + share_type calculate_fee(const fee_parameters_type& k)const; + void validate()const; + }; + +} } + +FC_REFLECT_ENUM( graphene::chain::game_type, (rock_paper_scissors)(GAME_TYPE_COUNT) ) +FC_REFLECT_TYPENAME( graphene::chain::game_specific_options ) +FC_REFLECT( graphene::chain::tournament_options, + (type_of_game) + (registration_deadline) + (number_of_players) + (buy_in) + (whitelist) + (start_time) + (start_delay) + (round_delay) + (number_of_wins) + (game_options)) +FC_REFLECT( graphene::chain::tournament_create_operation, + (fee) + (creator) + (options) + (extensions)) +FC_REFLECT( graphene::chain::tournament_join_operation, + (fee) + (payer_account_id) + (player_account_id) + (buy_in) + (extensions)) +FC_REFLECT( graphene::chain::tournament_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::tournament_join_operation::fee_parameters_type, (fee) ) + diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index d7864f90..12524329 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -134,6 +134,7 @@ namespace graphene { namespace chain { vesting_balance_object_type, worker_object_type, balance_object_type, + tournament_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -175,6 +176,7 @@ namespace graphene { namespace chain { class worker_object; class balance_object; class blinded_balance_object; + class tournament_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -190,6 +192,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type; typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type; typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type; + typedef object_id< protocol_ids, tournament_object_type, tournament_object> tournament_id_type; // implementation types class global_property_object; @@ -340,6 +343,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (vesting_balance_object_type) (worker_object_type) (balance_object_type) + (tournament_object_type) (OBJECT_TYPE_COUNT) ) FC_REFLECT_ENUM( graphene::chain::impl_object_type, @@ -378,6 +382,7 @@ FC_REFLECT_TYPENAME( graphene::chain::withdraw_permission_id_type ) FC_REFLECT_TYPENAME( graphene::chain::vesting_balance_id_type ) FC_REFLECT_TYPENAME( graphene::chain::worker_id_type ) FC_REFLECT_TYPENAME( graphene::chain::balance_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::tournament_id_type ) FC_REFLECT_TYPENAME( graphene::chain::global_property_id_type ) FC_REFLECT_TYPENAME( graphene::chain::dynamic_global_property_id_type ) FC_REFLECT_TYPENAME( graphene::chain::asset_dynamic_data_id_type ) diff --git a/libraries/chain/include/graphene/chain/tournament_object.hpp b/libraries/chain/include/graphene/chain/tournament_object.hpp new file mode 100644 index 00000000..2f4bcc41 --- /dev/null +++ b/libraries/chain/include/graphene/chain/tournament_object.hpp @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +namespace graphene { namespace chain { + class database; + using namespace graphene::db; + + class tournament_object : public graphene::db::abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = tournament_object_type; + + /// the options set when creating the tournament + tournament_options options; + + /// If the tournament has started, the time it started + optional start_time; + /// If the tournament has ended, the time it ended + optional end_time; + + /// List of players registered for this tournament + flat_set registered_players; + + /// Total prize pool accumulated ((sum of buy_ins, usually registered_players.size() * buy_in_amount) + asset prize_pool; + }; + + typedef multi_index_container< + tournament_object, + indexed_by< + ordered_unique< tag, member< object, object_id_type, &object::id > > + > + > tournament_object_multi_index_type; + typedef generic_index tournament_index; + +} } + +FC_REFLECT_DERIVED( graphene::chain::tournament_object, (graphene::db::object), + (options) + (start_time) + (end_time) ) + diff --git a/libraries/chain/protocol/tournament.cpp b/libraries/chain/protocol/tournament.cpp new file mode 100644 index 00000000..6f46f217 --- /dev/null +++ b/libraries/chain/protocol/tournament.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +namespace graphene { namespace chain { + +void tournament_options::validate() const +{ + FC_ASSERT( number_of_players >= 2 && (number_of_players & (number_of_players - 1)) == 0, + "Number of players must be a power of two" ); +} + +share_type tournament_create_operation::calculate_fee(const fee_parameters_type& k)const +{ + return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte ); +} + +void tournament_create_operation::validate()const +{ + FC_ASSERT( fee.amount >= 0 ); + options.validate(); +} + +share_type tournament_join_operation::calculate_fee(const fee_parameters_type& k)const +{ + return k.fee; +} + +void tournament_join_operation::validate()const +{ + FC_ASSERT( fee.amount >= 0 ); +} + + +} } // namespace graphene::chain diff --git a/libraries/fc b/libraries/fc index 57d14c7d..622ff580 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 57d14c7de849c567d753fc5cab5465d68602ff95 +Subproject commit 622ff58039f2388433272a44fe416f5b8025589a diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index fa57461e..90e1ea13 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1404,6 +1404,12 @@ class wallet_api bool broadcast /* = false */ ); + /** Creates a new tournament + * @param creator the accout that is paying the fee to create the tournament + * @param options the options detailing the specifics of the tournament + */ + signed_transaction tournament_create( string creator, tournament_options options, bool broadcast = false ); + void dbg_make_uia(string creator, string symbol); void dbg_make_mia(string creator, string symbol); void flood_network(string prefix, uint32_t number_of_transactions); @@ -1591,4 +1597,5 @@ FC_API( graphene::wallet::wallet_api, (blind_transfer) (blind_history) (receive_blind_transfer) + (tournament_create) ) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 9e1654e8..e0656595 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4092,6 +4092,22 @@ vector wallet_api::blind_history( string key_or_account ) return result; } +signed_transaction wallet_api::tournament_create( string creator, tournament_options options, bool broadcast ) +{ + FC_ASSERT( !is_locked() ); + account_object creator_account_obj = get_account(creator); + + signed_transaction tx; + tournament_create_operation op; + op.creator = creator_account_obj.get_id(); + op.options = options; + tx.operations = {op}; + my->set_operation_fees( tx, my->_remote_db->get_global_properties().parameters.current_fees ); + tx.validate(); + + return my->sign_transaction( tx, broadcast ); +} + // default ctor necessary for FC_REFLECT signed_block_with_info::signed_block_with_info() {