diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c7e49b5d..375c8d2f 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -74,6 +74,7 @@ add_library( graphene_chain proposal_evaluator.cpp market_evaluator.cpp vesting_balance_evaluator.cpp + tournament_evaluator.cpp withdraw_permission_evaluator.cpp worker_evaluator.cpp confidential_evaluator.cpp diff --git a/libraries/chain/include/graphene/chain/tournament_evaluator.hpp b/libraries/chain/include/graphene/chain/tournament_evaluator.hpp new file mode 100644 index 00000000..825f1d60 --- /dev/null +++ b/libraries/chain/include/graphene/chain/tournament_evaluator.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include + +namespace graphene { namespace chain { + + class tournament_create_evaluator : public evaluator + { + public: + typedef tournament_create_operation operation_type; + + void_result do_evaluate( const tournament_create_operation& o ); + object_id_type do_apply( const tournament_create_operation& o ); + }; + + class tournament_join_evaluator : public evaluator + { + public: + typedef tournament_join_operation operation_type; + + void_result do_evaluate( const tournament_join_operation& o ); + object_id_type do_apply( const tournament_join_operation& o ); + }; + +} } diff --git a/libraries/chain/tournament_evaluator.cpp b/libraries/chain/tournament_evaluator.cpp new file mode 100644 index 00000000..093f0227 --- /dev/null +++ b/libraries/chain/tournament_evaluator.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +namespace graphene { namespace chain { + + void_result tournament_create_evaluator::do_evaluate( const tournament_create_operation& op ) + { try { + database& d = db(); + FC_ASSERT(op.options.type_of_game == rock_paper_scissors, "Unsupported game type ${type}", ("type", op.options.type_of_game)); + + FC_ASSERT(op.options.registration_deadline >= d.head_block_time(), "Registration deadline has already passed"); + + // TODO: make this committee-set + const fc::time_point_sec maximum_registration_deadline = d.head_block_time() + fc::days(30); + FC_ASSERT(op.options.registration_deadline <= maximum_registration_deadline, + "Registration deadline must be before ${maximum_registration_deadline}", + ("maximum_registration_deadline", maximum_registration_deadline)); + + FC_ASSERT(op.options.number_of_players > 1, "If you're going to play with yourself, do it off-chain"); + // TODO: make this committee-set + const uint32_t maximum_players_in_tournament = 256; + FC_ASSERT(op.options.number_of_players <= maximum_players_in_tournament, + "Tournaments may not have more than ${maximum_players_in_tournament} players", + ("maximum_players_in_tournament", maximum_players_in_tournament)); + + // TODO: make this committee-set + const uint32_t maximum_tournament_whitelist_length = 1000; + FC_ASSERT(op.options.whitelist.size() != 1, "Can't create a tournament for one player"); + FC_ASSERT(op.options.whitelist.size() < maximum_tournament_whitelist_length, + "Whitelist must not be longer than ${maximum_tournament_whitelist_length}", + ("maximum_tournament_whitelist_length", maximum_tournament_whitelist_length)); + + if (op.options.start_time) + { + FC_ASSERT(!op.options.start_delay, "Cannot specify both a fixed start time and a delay"); + FC_ASSERT(*op.options.start_time >= op.options.registration_deadline, + "Cannot start before registration deadline expires"); + // TODO: make this committee-set + const uint32_t maximum_start_time_in_future = 60 * 60 * 24 * 7 * 4; // 1 month + FC_ASSERT((*op.options.start_time - d.head_block_time()).to_seconds() <= maximum_start_time_in_future, + "Start time is too far in the future"); + } + else if (op.options.start_delay) + { + FC_ASSERT(!op.options.start_time, "Cannot specify both a fixed start time and a delay"); + // TODO: make this committee-set + const uint32_t maximum_start_delay = 60 * 60 * 24 * 7; // 1 week + FC_ASSERT(*op.options.start_delay < maximum_start_delay, + "Start delay is too long"); + } + else + FC_THROW("Must specify either a fixed start time or a delay"); + + // TODO: make this committee-set + const uint32_t maximum_round_delay = 60 * 60; // one hour + FC_ASSERT(op.options.round_delay < maximum_round_delay, + "Round delay is too long"); + + // TODO: make this committee-set + const uint32_t maximum_tournament_number_of_wins = 100; + FC_ASSERT(op.options.number_of_wins > 0); + FC_ASSERT(op.options.number_of_wins <= maximum_tournament_number_of_wins, + "Matches may not require more than ${number_of_wins} wins", + ("number_of_wins", maximum_tournament_number_of_wins)); + + return void_result(); + } FC_CAPTURE_AND_RETHROW( (op) ) } + + object_id_type tournament_create_evaluator::do_apply( const tournament_create_operation& op ) + { try { + } FC_CAPTURE_AND_RETHROW( (op) ) } + + void_result tournament_join_evaluator::do_evaluate( const tournament_join_operation& op ) + { try { + return void_result(); + } FC_CAPTURE_AND_RETHROW( (op) ) } + + object_id_type tournament_join_evaluator::do_apply( const tournament_join_operation& op ) + { try { + } FC_CAPTURE_AND_RETHROW( (op) ) } + +} } + + diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 90e1ea13..3d44a4d9 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1407,9 +1407,18 @@ class wallet_api /** 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 + * @return the signed version of the transaction */ signed_transaction tournament_create( string creator, tournament_options options, bool broadcast = false ); + /** Join an existing tournament + * @param paying_account the account that is paying the buy-in and the fee to join the tournament + * @param playing_account the account that will be playing in the tournament + * @param tournament_id the tournament the user wishes to join + * @return the signed version of the transaction + */ + signed_transaction tournament_join( string payer_account, string player_account, tournament_id_type tournament_id, string buy_in_amount, string buy_in_asset_symbol, 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); diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index e0656595..61da70d2 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -62,6 +62,7 @@ #include #include +#include #include #include #include @@ -4108,6 +4109,35 @@ signed_transaction wallet_api::tournament_create( string creator, tournament_opt return my->sign_transaction( tx, broadcast ); } +signed_transaction wallet_api::tournament_join( string payer_account, + string player_account, + tournament_id_type tournament_id, + string buy_in_amount, + string buy_in_asset_symbol, + bool broadcast ) +{ + FC_ASSERT( !is_locked() ); + account_object payer_account_obj = get_account(payer_account); + account_object player_account_obj = get_account(player_account); + graphene::chain::tournament_object tournament_obj = my->get_object(tournament_id); + + fc::optional buy_in_asset_obj = get_asset(buy_in_asset_symbol); + FC_ASSERT(buy_in_asset_obj, "Could not find asset matching ${asset}", ("asset", buy_in_asset_symbol)); + + signed_transaction tx; + tournament_join_operation op; + op.payer_account_id = payer_account_obj.get_id(); + op.player_account_id = player_account_obj.get_id(); + op.tournament_id = tournament_id; + op.buy_in = buy_in_asset_obj->amount_from_string(buy_in_amount); + + 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() {