more fixes to get tournament_create/join working in cli wallet

This commit is contained in:
Eric Frias 2016-09-12 18:28:45 -04:00
parent 9b101cefcf
commit dd0ad9e759
10 changed files with 163 additions and 24 deletions

View file

@ -540,6 +540,7 @@ void database::_apply_block( const signed_block& next_block )
clear_expired_orders();
update_expired_feeds();
update_withdraw_permissions();
update_tournaments();
// n.b., update_maintenance_flag() happens this late
// because get_slot_time() / get_slot_at_time() is needed above

View file

@ -62,6 +62,7 @@
#include <graphene/chain/withdraw_permission_evaluator.hpp>
#include <graphene/chain/witness_evaluator.hpp>
#include <graphene/chain/worker_evaluator.hpp>
#include <graphene/chain/tournament_evaluator.hpp>
#include <graphene/chain/protocol/fee_schedule.hpp>
@ -172,6 +173,8 @@ void database::initialize_evaluators()
register_evaluator<transfer_from_blind_evaluator>();
register_evaluator<blind_transfer_evaluator>();
register_evaluator<asset_claim_fees_evaluator>();
register_evaluator<tournament_create_evaluator>();
register_evaluator<tournament_join_evaluator>();
}
void database::initialize_indexes()
@ -202,6 +205,7 @@ void database::initialize_indexes()
add_index< primary_index<blinded_balance_index> >();
add_index< primary_index<tournament_index> >();
add_index< primary_index<tournament_details_index> >();
//Implementation object indexes
add_index< primary_index<transaction_index > >();

View file

@ -482,7 +482,7 @@ void database::update_tournaments()
auto& registration_deadline_index = get_index_type<tournament_index>().indices().get<by_registration_deadline>();
// this index is sorted on state and deadline, so the tournaments awaiting registrations with the earliest
// deadlines will be at the beginning
while (registration_deadline_index.empty() &&
while (!registration_deadline_index.empty() &&
registration_deadline_index.begin()->get_state() == tournament_state::accepting_registrations &&
registration_deadline_index.begin()->options.registration_deadline <= head_block_time())
{

View file

@ -162,6 +162,7 @@ FC_REFLECT( graphene::chain::tournament_options,
(start_delay)
(round_delay)
(number_of_wins)
(meta)
(game_options))
FC_REFLECT( graphene::chain::tournament_create_operation,
(fee)

View file

@ -135,6 +135,7 @@ namespace graphene { namespace chain {
worker_object_type,
balance_object_type,
tournament_object_type,
tournament_details_object_type,
match_object_type,
game_object_type,
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
@ -158,8 +159,7 @@ namespace graphene { namespace chain {
impl_budget_record_object_type,
impl_special_authority_object_type,
impl_buyback_object_type,
impl_fba_accumulator_object_type,
impl_tournament_details_object_type
impl_fba_accumulator_object_type
};
//typedef fc::unsigned_int object_id_type;
@ -180,6 +180,7 @@ namespace graphene { namespace chain {
class balance_object;
class blinded_balance_object;
class tournament_object;
class tournament_details_object;
class match_object;
class game_object;
@ -198,6 +199,7 @@ namespace graphene { namespace chain {
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;
typedef object_id< protocol_ids, tournament_details_object_type, tournament_details_object> tournament_details_id_type;
typedef object_id< protocol_ids, match_object_type, match_object> match_id_type;
typedef object_id< protocol_ids, game_object_type, game_object> game_id_type;
@ -238,7 +240,6 @@ namespace graphene { namespace chain {
typedef object_id< implementation_ids, impl_special_authority_object_type, special_authority_object > special_authority_id_type;
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
typedef object_id< implementation_ids, impl_fba_accumulator_object_type, fba_accumulator_object > fba_accumulator_id_type;
typedef object_id< implementation_ids, impl_tournament_details_object_type, tournament_details_object > tournament_details_id_type;
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
typedef fc::ripemd160 block_id_type;
@ -354,6 +355,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
(worker_object_type)
(balance_object_type)
(tournament_object_type)
(tournament_details_object_type)
(match_object_type)
(game_object_type)
(OBJECT_TYPE_COUNT)
@ -376,7 +378,6 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
(impl_special_authority_object_type)
(impl_buyback_object_type)
(impl_fba_accumulator_object_type)
(impl_tournament_details_object_type)
)
FC_REFLECT_TYPENAME( graphene::chain::share_type )

View file

@ -3,6 +3,8 @@
#include <boost/multi_index/composite_key.hpp>
#include <graphene/db/flat_index.hpp>
#include <graphene/db/generic_index.hpp>
#include <sstream>
namespace graphene { namespace chain {
class database;
using namespace graphene::db;
@ -14,7 +16,7 @@ namespace graphene { namespace chain {
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = impl_tournament_details_object_type;
static const uint8_t type_id = tournament_details_object_type;
/// List of players registered for this tournament
flat_set<account_id_type> registered_players;
@ -74,6 +76,18 @@ namespace graphene { namespace chain {
time_point_sec get_registration_deadline() const { return options.registration_deadline; }
// serialization functions:
// for serializing to raw, go through a temporary sstream object to avoid
// having to implement serialization in the header file
template<typename Stream>
friend Stream& operator<<( Stream& s, const tournament_object& tournament_obj );
template<typename Stream>
friend Stream& operator>>( Stream& s, tournament_object& tournament_obj );
void pack_impl(std::ostream& stream) const;
void unpack_impl(std::istream& stream);
/// called by database maintenance code when registration for this contest has expired
void on_registration_deadline_passed(database& db);
void on_player_registered(database& db, account_id_type payer_id, account_id_type player_id);
@ -128,18 +142,66 @@ namespace graphene { namespace chain {
> tournament_object_multi_index_type;
typedef generic_index<tournament_object, tournament_object_multi_index_type> tournament_index;
typedef multi_index_container<
tournament_details_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > > >
> tournament_details_object_multi_index_type;
typedef generic_index<tournament_details_object, tournament_details_object_multi_index_type> tournament_details_index;
template<typename Stream>
inline Stream& operator<<( Stream& s, const tournament_object& tournament_obj )
{
fc_elog(fc::logger::get("tournament"), "In tournament_obj to_raw");
// pack all fields exposed in the header in the usual way
// instead of calling the derived pack, just serialize the one field in the base class
// fc::raw::pack<Stream, const graphene::db::abstract_object<tournament_object> >(s, tournament_obj);
fc::raw::pack(s, tournament_obj.id);
fc::raw::pack(s, tournament_obj.creator);
fc::raw::pack(s, tournament_obj.options);
fc::raw::pack(s, tournament_obj.start_time);
fc::raw::pack(s, tournament_obj.end_time);
fc::raw::pack(s, tournament_obj.prize_pool);
fc::raw::pack(s, tournament_obj.registered_players);
fc::raw::pack(s, tournament_obj.tournament_details_id);
// fc::raw::pack the contents hidden in the impl class
std::ostringstream stream;
tournament_obj.pack_impl(stream);
fc::raw::pack(s, stream.str());
return s;
}
template<typename Stream>
inline Stream& operator>>( Stream& s, tournament_object& tournament_obj )
{
fc_elog(fc::logger::get("tournament"), "In tournament_obj from_raw");
// unpack all fields exposed in the header in the usual way
//fc::raw::unpack<Stream, graphene::db::abstract_object<tournament_object> >(s, tournament_obj);
fc::raw::unpack(s, tournament_obj.id);
fc::raw::unpack(s, tournament_obj.creator);
fc::raw::unpack(s, tournament_obj.options);
fc::raw::unpack(s, tournament_obj.start_time);
fc::raw::unpack(s, tournament_obj.end_time);
fc::raw::unpack(s, tournament_obj.prize_pool);
fc::raw::unpack(s, tournament_obj.registered_players);
fc::raw::unpack(s, tournament_obj.tournament_details_id);
// fc::raw::unpack the contents hidden in the impl class
std::string stringified_stream;
fc::raw::unpack(s, stringified_stream);
std::istringstream stream(stringified_stream);
tournament_obj.unpack_impl(stream);
return s;
}
} }
FC_REFLECT_DERIVED(graphene::chain::tournament_details_object, (graphene::db::object),
(registered_players)
(payers))
FC_REFLECT_DERIVED(graphene::chain::tournament_object, (graphene::db::object),
(creator)
(options)
(start_time)
(end_time)
(prize_pool)
(tournament_details_id))
FC_REFLECT_TYPENAME(graphene::chain::tournament_object) // manually serialized
FC_REFLECT_ENUM(graphene::chain::tournament_state,
(accepting_registrations)
(awaiting_start)
@ -147,3 +209,41 @@ FC_REFLECT_ENUM(graphene::chain::tournament_state,
(registration_period_expired)
(concluded))
namespace fc {
// Manually reflect tournament_object to variant to properly reflect "state"
inline void to_variant(const graphene::chain::tournament_object& tournament_obj, fc::variant& v)
{
fc_elog(fc::logger::get("tournament"), "In tournament_obj to_variant");
elog("In tournament_obj to_variant");
fc::mutable_variant_object o;
o("id", tournament_obj.id)
("creator", tournament_obj.creator)
("options", tournament_obj.options)
("start_time", tournament_obj.start_time)
("end_time", tournament_obj.end_time)
("prize_pool", tournament_obj.prize_pool)
("registered_players", tournament_obj.registered_players)
("tournament_details_id", tournament_obj.tournament_details_id)
("state", tournament_obj.get_state());
v = o;
}
// Manually reflect tournament_object to variant to properly reflect "state"
inline void from_variant(const fc::variant& v, graphene::chain::tournament_object& tournament_obj)
{
fc_elog(fc::logger::get("tournament"), "In tournament_obj from_variant");
tournament_obj.id = v["id"].as<graphene::chain::tournament_id_type>();
tournament_obj.creator = v["creator"].as<graphene::chain::account_id_type>();
tournament_obj.options = v["options"].as<graphene::chain::tournament_options>();
tournament_obj.start_time = v["start_time"].as<optional<time_point_sec> >();
tournament_obj.end_time = v["end_time"].as<optional<time_point_sec> >();
tournament_obj.prize_pool = v["prize_pool"].as<graphene::chain::share_type>();
tournament_obj.registered_players = v["registered_players"].as<uint32_t>();
tournament_obj.tournament_details_id = v["tournament_details_id"].as<graphene::chain::tournament_details_id_type>();
// TODO deserialize "State"
}
} //end namespace fc

View file

@ -29,7 +29,9 @@ namespace graphene { namespace chain {
// TODO: make this committee-set
const uint32_t maximum_tournament_whitelist_length = 1000;
FC_ASSERT(op.options.whitelist.size() >= op.options.number_of_players, "Whitelist must allow enough players to fill the tournament");
FC_ASSERT(op.options.whitelist.empty() ||
op.options.whitelist.size() >= op.options.number_of_players,
"Whitelist must allow enough players to fill the tournament");
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));
@ -72,66 +74,88 @@ namespace graphene { namespace chain {
object_id_type tournament_create_evaluator::do_apply( const tournament_create_operation& op )
{ try {
const tournament_details_object& tournament_details =
db().create<tournament_details_object>( [&]( tournament_details_object& a ) {
});
const tournament_details_object& tournament_details =
db().create<tournament_details_object>( [&]( tournament_details_object& a ) {
});
const tournament_object& new_tournament =
db().create<tournament_object>( [&]( tournament_object& t ) {
t.options = op.options;
t.creator = op.creator;
t.tournament_details_id = tournament_details.id;
const tournament_object& new_tournament =
db().create<tournament_object>( [&]( tournament_object& t ) {
t.options = op.options;
t.creator = op.creator;
t.tournament_details_id = tournament_details.id;
});
return new_tournament.id;
fc_ilog(fc::logger::get("tournament"),
"Created tournament ${id} with details id ${details_id}",
("id", new_tournament.id)("details_id", tournament_details.id));
return new_tournament.id;
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result tournament_join_evaluator::do_evaluate( const tournament_join_operation& op )
{ try {
fc_ilog(fc::logger::get("tournament"), ".",);
const database& d = db();
fc_ilog(fc::logger::get("tournament"), ".",);
_tournament_obj = &op.tournament_id(d);
fc_ilog(fc::logger::get("tournament"), "details_id = ${id}",("id", _tournament_obj->tournament_details_id));
_tournament_details_obj = &_tournament_obj->tournament_details_id(d);
fc_ilog(fc::logger::get("tournament"), ".",);
_payer_account = &op.payer_account_id(d);
fc_ilog(fc::logger::get("tournament"), ".",);
//const account_object& player_account = op.player_account_id(d);
_buy_in_asset_type = &op.buy_in.asset_id(d);
fc_ilog(fc::logger::get("tournament"), ".",);
// TODO FC_ASSERT(_tournament_obj->state == tournament_state::accepting_registrations);
FC_ASSERT(_tournament_details_obj->registered_players.size() < _tournament_obj->options.number_of_players,
"Tournament is already full");
fc_ilog(fc::logger::get("tournament"), ".",);
FC_ASSERT(d.head_block_time() <= _tournament_obj->options.registration_deadline,
"Registration deadline has already passed");
fc_ilog(fc::logger::get("tournament"), ".",);
FC_ASSERT(_tournament_obj->options.whitelist.empty() ||
_tournament_obj->options.whitelist.find(op.player_account_id) == _tournament_obj->options.whitelist.end(),
"Player is not on the whitelist for this tournament");
fc_ilog(fc::logger::get("tournament"), ".",);
FC_ASSERT(_tournament_details_obj->registered_players.find(op.player_account_id) == _tournament_details_obj->registered_players.end(),
"Player is already registered for this tournament");
fc_ilog(fc::logger::get("tournament"), ".",);
FC_ASSERT(op.buy_in == _tournament_obj->options.buy_in, "Buy-in is incorrect");
fc_ilog(fc::logger::get("tournament"), ".",);
GRAPHENE_ASSERT(!_buy_in_asset_type->is_transfer_restricted(),
transfer_restricted_transfer_asset,
"Asset {asset} has transfer_restricted flag enabled",
("asset", op.buy_in.asset_id));
fc_ilog(fc::logger::get("tournament"), ".",);
GRAPHENE_ASSERT(is_authorized_asset(d, *_payer_account, *_buy_in_asset_type),
transfer_from_account_not_whitelisted,
"payer account ${payer} is not whitelisted for asset ${asset}",
("payer", op.payer_account_id)
("asset", op.buy_in.asset_id));
fc_ilog(fc::logger::get("tournament"), ".",);
bool sufficient_balance = d.get_balance(*_payer_account, *_buy_in_asset_type).amount >= op.buy_in.amount;
fc_ilog(fc::logger::get("tournament"), ".",);
FC_ASSERT(sufficient_balance,
"Insufficient Balance: paying account '${payer}' has insufficient balance to pay buy-in of ${buy_in} (balance is ${balance})",
("payer", _payer_account->name)
("buy_in", d.to_pretty_string(op.buy_in))
("balance",d.to_pretty_string(d.get_balance(*_payer_account, *_buy_in_asset_type))));
fc_ilog(fc::logger::get("tournament"), ".",);
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result tournament_join_evaluator::do_apply( const tournament_join_operation& op )
{ try {
fc_ilog(fc::logger::get("tournament"), "in do_apply",);
db().modify(*_tournament_obj, [&](tournament_object& tournament_obj){
fc_ilog(fc::logger::get("tournament"), "in do_apply's modify",);
tournament_obj.on_player_registered(db(), op.payer_account_id, op.player_account_id);
fc_ilog(fc::logger::get("tournament"), "in do_apply's modify after event",);
});
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -29,6 +29,8 @@
#include <graphene/utilities/key_conversion.hpp>
#include <boost/range/algorithm_ext/insert.hpp>
#include <fc/smart_ref_impl.hpp>
#include <fc/thread/thread.hpp>
@ -67,11 +69,14 @@ void witness_plugin::plugin_set_program_options(
{
auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
string witness_id_example = fc::json::to_string(chain::witness_id_type(5));
string witness_id_example2 = fc::json::to_string(chain::witness_id_type(6));
command_line_options.add_options()
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale.")
("required-participation", bpo::bool_switch()->notifier([this](int e){_required_witness_participation = uint32_t(e*GRAPHENE_1_PERCENT);}), "Percent of witnesses (0-99) that must be participating in order to produce blocks")
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
("witness-ids,W", bpo::value<string>(),
("IDs of multiple witnesses controlled by this node (e.g. [" + witness_id_example + ", " + witness_id_example2 + "], quotes are required)").c_str())
("private-key", bpo::value<vector<string>>()->composing()->multitoken()->
DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
"Tuple of [PublicKey, WIF private key] (may specify multiple times)")
@ -89,6 +94,8 @@ void witness_plugin::plugin_initialize(const boost::program_options::variables_m
ilog("witness plugin: plugin_initialize() begin");
_options = &options;
LOAD_VALUE_SET(options, "witness-id", _witnesses, chain::witness_id_type)
if (options.count("witness-ids"))
boost::insert(_witnesses, fc::json::from_string(options.at("witness-ids").as<string>()).as<vector<chain::witness_id_type>>());
if( options.count("private-key") )
{

View file

@ -62,7 +62,7 @@ struct static_variant_map_visitor
template< typename T >
result_type operator()( const T& dummy )
{
assert( which == m.which_to_name.size() );
assert( which == (int)m.which_to_name.size() );
std::string name = clean_name( fc::get_typename<T>::name() );
m.name_to_which[ name ] = which;
m.which_to_name.push_back( name );

View file

@ -1607,4 +1607,5 @@ FC_API( graphene::wallet::wallet_api,
(blind_history)
(receive_blind_transfer)
(tournament_create)
(tournament_join)
)