From 2d388452d92cd5c4c9fa8f38f80c213167218582 Mon Sep 17 00:00:00 2001 From: dimfred Date: Fri, 1 Mar 2019 14:10:07 +0100 Subject: [PATCH] manager sport, event_grp, event, bett_grp, bett_mark --- libraries/chain/CMakeLists.txt | 2 +- libraries/chain/betting_market_evaluator.cpp | 69 +++++++++++++++++-- libraries/chain/event_evaluator.cpp | 53 +++++++++++--- libraries/chain/event_group_evaluator.cpp | 48 +++++++++++-- libraries/chain/event_object.cpp | 3 + .../graphene/chain/event_group_object.hpp | 5 +- .../include/graphene/chain/event_object.hpp | 4 +- .../chain/include/graphene/chain/manager.hpp | 25 +++++++ .../chain/protocol/betting_market.hpp | 61 ++++++++++++---- .../include/graphene/chain/protocol/event.hpp | 39 +++++++++-- .../graphene/chain/protocol/event_group.hpp | 39 +++++++++-- .../include/graphene/chain/protocol/sport.hpp | 23 +++++-- .../include/graphene/chain/sport_object.hpp | 4 +- libraries/chain/manager.cpp | 44 ++++++++++++ libraries/chain/sport_evaluator.cpp | 34 +++++++-- 15 files changed, 391 insertions(+), 62 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/manager.hpp create mode 100644 libraries/chain/manager.cpp diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index a328cf1f..e5dbf3f0 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -108,7 +108,7 @@ add_library( graphene_chain betting_market_evaluator.cpp betting_market_object.cpp betting_market_group_object.cpp - + manager.cpp affiliate_payout.cpp ${HEADERS} diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index e1d64e3c..6bab2e2f 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -75,8 +76,6 @@ void_result betting_market_group_create_evaluator::do_evaluate(const betting_mar { try { database& d = db(); FC_ASSERT(d.head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); - // the event_id in the operation can be a relative id. If it is, // resolve it and verify that it is truly an event object_id_type resolved_event_id = op.event_id; @@ -89,6 +88,15 @@ void_result betting_market_group_create_evaluator::do_evaluate(const betting_mar _event_id = resolved_event_id; FC_ASSERT(d.find_object(_event_id), "Invalid event specified"); + if( d.head_block_time() < HARDFORK_MANAGER_TIME ) { + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), _event_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + FC_ASSERT(d.find_object(op.asset_id), "Invalid asset specified"); // the rules_id in the operation can be a relative id. If it is, @@ -123,7 +131,16 @@ void_result betting_market_group_update_evaluator::do_evaluate(const betting_mar { try { database& d = db(); FC_ASSERT(d.head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); + + if( d.head_block_time() < HARDFORK_MANAGER_TIME ) { + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.betting_market_group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + _betting_market_group = &op.betting_market_group_id(d); FC_ASSERT(op.new_description || op.new_rules_id || op.status, "nothing to change"); @@ -197,7 +214,6 @@ void_result betting_market_group_update_evaluator::do_apply(const betting_market void_result betting_market_create_evaluator::do_evaluate(const betting_market_create_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); // the betting_market_group_id in the operation can be a relative id. If it is, // resolve it and verify that it is truly an betting_market_group @@ -211,6 +227,15 @@ void_result betting_market_create_evaluator::do_evaluate(const betting_market_cr _group_id = resolved_betting_market_group_id; FC_ASSERT(db().find_object(_group_id), "Invalid betting_market_group specified"); + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), _group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -229,7 +254,16 @@ void_result betting_market_update_evaluator::do_evaluate(const betting_market_up { try { database& d = db(); FC_ASSERT(d.head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); + + if( d.head_block_time() < HARDFORK_MANAGER_TIME ) { + FC_ASSERT(trx_state->_is_proposed_trx); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.betting_market_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + _betting_market = &op.betting_market_id(d); FC_ASSERT(op.new_group_id.valid() || op.new_description.valid() || op.new_payout_condition.valid(), "nothing to change"); @@ -245,6 +279,13 @@ void_result betting_market_update_evaluator::do_evaluate(const betting_market_up resolved_betting_market_group_id.type() == betting_market_group_id_type::type_id, "betting_market_group_id must refer to a betting_market_group_id_type"); _group_id = resolved_betting_market_group_id; + + if( db().head_block_time() >= HARDFORK_MANAGER_TIME ) + { + FC_ASSERT( is_manager( db(), _group_id, op.fee_payer() ), + "no manager permission for the new_betting_market_group_id" ); + } + FC_ASSERT(d.find_object(_group_id), "invalid betting_market_group specified"); } @@ -365,6 +406,16 @@ void_result betting_market_group_resolve_evaluator::do_evaluate(const betting_ma { try { database& d = db(); FC_ASSERT(d.head_block_time() >= HARDFORK_1000_TIME); + + if( d.head_block_time() <= HARDFORK_MANAGER_TIME ) { + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( d, op.betting_market_group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + _betting_market_group = &op.betting_market_group_id(d); d.validate_betting_market_group_resolutions(*_betting_market_group, op.resolutions); return void_result(); @@ -379,6 +430,14 @@ void_result betting_market_group_resolve_evaluator::do_apply(const betting_marke void_result betting_market_group_cancel_unmatched_bets_evaluator::do_evaluate(const betting_market_group_cancel_unmatched_bets_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); + if( db().head_block_time() <= HARDFORK_MANAGER_TIME ) { + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.betting_market_group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } _betting_market_group = &op.betting_market_group_id(db()); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/chain/event_evaluator.cpp b/libraries/chain/event_evaluator.cpp index 28e7476d..ce23cfca 100644 --- a/libraries/chain/event_evaluator.cpp +++ b/libraries/chain/event_evaluator.cpp @@ -24,18 +24,19 @@ #include #include #include +#include #include #include #include #include #include +#include namespace graphene { namespace chain { void_result event_create_evaluator::do_evaluate(const event_create_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); //database& d = db(); // the event_group_id in the operation can be a relative id. If it is, @@ -48,7 +49,15 @@ void_result event_create_evaluator::do_evaluate(const event_create_operation& op resolved_event_group_id.type() == event_group_id_type::type_id, "event_group_id must refer to a event_group_id_type"); event_group_id = resolved_event_group_id; - //const event_group_object& event_group = event_group_id(d); + + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.new_manager && !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), event_group_id, op.fee_payer() ), + "trx is not proposed and fee_payer is not the manager of this object" ); + } return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -62,7 +71,10 @@ object_id_type event_create_evaluator::do_apply(const event_create_operation& op event_obj.season = op.season; event_obj.start_time = op.start_time; event_obj.event_group_id = event_group_id; + if( op.extensions.value.new_manager ) + event_obj.manager = *op.extensions.value.new_manager; }); + //increment number of active events in global betting statistics object const global_betting_statistics_object& betting_statistics = global_betting_statistics_id_type()(d); d.modify( betting_statistics, [&](global_betting_statistics_object& bso) { @@ -74,10 +86,20 @@ object_id_type event_create_evaluator::do_apply(const event_create_operation& op void_result event_update_evaluator::do_evaluate(const event_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); - FC_ASSERT(op.new_event_group_id || op.new_name || op.new_season || - op.new_start_time || op.new_status, "nothing to change"); - + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.new_manager && !op.extensions.value.fee_paying_account ); + FC_ASSERT( op.new_event_group_id || op.new_name || op.new_season || + op.new_start_time || op.new_status, "nothing to change"); + } + else { + FC_ASSERT( is_manager( db(), op.event_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + FC_ASSERT( op.new_event_group_id || op.new_name || op.new_season || + op.new_start_time || op.new_status || op.extensions.value.new_manager, + "nothing to change" ); + } + if (op.new_event_group_id) { object_id_type resolved_event_group_id = *op.new_event_group_id; @@ -88,6 +110,12 @@ void_result event_update_evaluator::do_evaluate(const event_update_operation& op resolved_event_group_id.type() == event_group_id_type::type_id, "event_group_id must refer to a event_group_id_type"); event_group_id = resolved_event_group_id; + + if( db().head_block_time() >= HARDFORK_MANAGER_TIME ) + { + FC_ASSERT( is_manager( db(), event_group_id, *op.extensions.value.fee_paying_account ), + "no manager permission for the new_event_group_id" ); + } } return void_result(); @@ -108,16 +136,25 @@ void_result event_update_evaluator::do_apply(const event_update_operation& op) eo.event_group_id = event_group_id; if( op.new_status ) eo.dispatch_new_status(_db, *op.new_status); + if( op.extensions.value.new_manager ) + eo.manager = *op.extensions.value.new_manager; }); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } void_result event_update_status_evaluator::do_evaluate(const event_update_status_operation& op) { try { - FC_ASSERT(trx_state->_is_proposed_trx); - database& d = db(); FC_ASSERT(d.head_block_time() >= HARDFORK_1000_TIME); + if( d.head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.event_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + //check that the event to update exists _event_to_update = &op.event_id(d); diff --git a/libraries/chain/event_group_evaluator.cpp b/libraries/chain/event_group_evaluator.cpp index b337017b..6a3dfba0 100644 --- a/libraries/chain/event_group_evaluator.cpp +++ b/libraries/chain/event_group_evaluator.cpp @@ -24,18 +24,19 @@ #include #include #include +#include #include #include #include #include #include +#include namespace graphene { namespace chain { void_result event_group_create_evaluator::do_evaluate(const event_group_create_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); // the sport id in the operation can be a relative id. If it is, // resolve it and verify that it is truly a sport @@ -49,6 +50,15 @@ void_result event_group_create_evaluator::do_evaluate(const event_group_create_o FC_ASSERT( db().find_object(sport_id), "Invalid sport specified" ); + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.new_manager && !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), sport_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -58,6 +68,8 @@ object_id_type event_group_create_evaluator::do_apply(const event_group_create_o db().create( [&]( event_group_object& event_group_obj ) { event_group_obj.name = op.name; event_group_obj.sport_id = sport_id; + if( op.extensions.value.new_manager ) + event_group_obj.manager = *op.extensions.value.new_manager; }); return new_event_group.id; } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -65,9 +77,18 @@ object_id_type event_group_create_evaluator::do_apply(const event_group_create_o void_result event_group_update_evaluator::do_evaluate(const event_group_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); - FC_ASSERT(op.new_sport_id.valid() || op.new_name.valid(), "nothing to change"); - if( op.new_sport_id.valid() ) + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.new_manager && !op.extensions.value.fee_paying_account ); + FC_ASSERT( op.new_sport_id || op.new_name, "nothing to change" ); + } + else { + FC_ASSERT( is_manager( db(), op.event_group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + FC_ASSERT( op.new_sport_id || op.new_name || op.extensions.value.new_manager, "nothing to change" ); + } + + if( op.new_sport_id ) { object_id_type resolved_id = *op.new_sport_id; if (is_relative(*op.new_sport_id)) @@ -78,6 +99,12 @@ void_result event_group_update_evaluator::do_evaluate(const event_group_update_o sport_id = resolved_id; FC_ASSERT( db().find_object(sport_id), "invalid sport specified" ); + + if( db().head_block_time() >= HARDFORK_MANAGER_TIME ) + { + FC_ASSERT( is_manager( db(), sport_id, op.fee_payer() ), + "no manager permission for the new_sport_id" ); + } } return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -93,6 +120,8 @@ void_result event_group_update_evaluator::do_apply(const event_group_update_oper ego.name = *op.new_name; if( op.new_sport_id.valid() ) ego.sport_id = sport_id; + if( op.extensions.value.new_manager ) + ego.manager = *op.extensions.value.new_manager; }); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -101,8 +130,15 @@ void_result event_group_update_evaluator::do_apply(const event_group_update_oper void_result event_group_delete_evaluator::do_evaluate(const event_group_delete_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1001_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); - + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.event_group_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } + //check for event group existence _event_group = &op.event_group_id(db()); diff --git a/libraries/chain/event_object.cpp b/libraries/chain/event_object.cpp index 99caf904..6cf73279 100644 --- a/libraries/chain/event_object.cpp +++ b/libraries/chain/event_object.cpp @@ -370,6 +370,7 @@ namespace graphene { namespace chain { at_least_one_betting_market_group_settled(false), my(new impl(this)) { + manager = account_id_type(1); } event_object::event_object(const event_object& rhs) : @@ -380,6 +381,7 @@ namespace graphene { namespace chain { event_group_id(rhs.event_group_id), at_least_one_betting_market_group_settled(rhs.at_least_one_betting_market_group_settled), scores(rhs.scores), + manager(rhs.manager), my(new impl(this)) { my->state_machine = rhs.my->state_machine; @@ -396,6 +398,7 @@ namespace graphene { namespace chain { event_group_id = rhs.event_group_id; at_least_one_betting_market_group_settled = rhs.at_least_one_betting_market_group_settled; scores = rhs.scores; + manager = rhs.manager; my->state_machine = rhs.my->state_machine; my->state_machine.event_obj = this; diff --git a/libraries/chain/include/graphene/chain/event_group_object.hpp b/libraries/chain/include/graphene/chain/event_group_object.hpp index c618ba2a..6e0ed0b1 100644 --- a/libraries/chain/include/graphene/chain/event_group_object.hpp +++ b/libraries/chain/include/graphene/chain/event_group_object.hpp @@ -41,7 +41,8 @@ class event_group_object : public graphene::db::abstract_object< event_group_obj internationalized_string_type name; sport_id_type sport_id; - + account_id_type manager = account_id_type(1); + void cancel_events(database& db) const; }; @@ -55,4 +56,4 @@ typedef multi_index_container< typedef generic_index event_group_object_index; } } // graphene::chain -FC_REFLECT_DERIVED( graphene::chain::event_group_object, (graphene::db::object), (name)(sport_id) ) +FC_REFLECT_DERIVED( graphene::chain::event_group_object, (graphene::db::object), (name)(sport_id)(manager) ) diff --git a/libraries/chain/include/graphene/chain/event_object.hpp b/libraries/chain/include/graphene/chain/event_object.hpp index 7682addc..ac0c4c7d 100644 --- a/libraries/chain/include/graphene/chain/event_object.hpp +++ b/libraries/chain/include/graphene/chain/event_object.hpp @@ -60,6 +60,8 @@ class event_object : public graphene::db::abstract_object< event_object > event_group_id_type event_group_id; + account_id_type manager = account_id_type(1); + bool at_least_one_betting_market_group_settled; event_status get_status() const; @@ -151,5 +153,5 @@ typedef generic_index event_object_ return s; } } } // graphene::chain -FC_REFLECT(graphene::chain::event_object, (name)) +FC_REFLECT(graphene::chain::event_object, (name) (manager) ) diff --git a/libraries/chain/include/graphene/chain/manager.hpp b/libraries/chain/include/graphene/chain/manager.hpp new file mode 100644 index 00000000..22c4e456 --- /dev/null +++ b/libraries/chain/include/graphene/chain/manager.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +namespace graphene { namespace chain { + +/** + * Determine whether the fee_paying_account for certain operations, in the context of + * sport_obj, event_group_obj, event_obj, betting_market_group_obj and betting_market_obj + * is the manager of this, or of the objects hierarchically above. + */ + +bool is_manager( const database& db, const sport_id_type& sport_id, const account_id_type& manager_id ); + +bool is_manager( const database& db, const event_group_id_type& event_group_id, const account_id_type& manager_id ); + +bool is_manager( const database& db, const event_id_type& event_id, const account_id_type& manager_id ); + +bool is_manager( const database& db, const betting_market_group_id_type& betting_market_group_id_type, + const account_id_type& manager_id ); + +bool is_manager( const database& db, const betting_market_id_type& betting_market_id_type, + const account_id_type& manager_id ); + +} } // graphene::chain \ No newline at end of file diff --git a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp index 26b6f263..5aedd8c8 100644 --- a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp @@ -25,6 +25,7 @@ #include #include +#include namespace graphene { namespace chain { @@ -100,6 +101,11 @@ enum class betting_market_group_status struct betting_market_group_create_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -140,14 +146,19 @@ struct betting_market_group_create_operation : public base_operation */ uint32_t delay_before_settling; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; struct betting_market_group_update_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -159,14 +170,19 @@ struct betting_market_group_update_operation : public base_operation optional status; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; struct betting_market_create_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -180,14 +196,19 @@ struct betting_market_create_operation : public base_operation internationalized_string_type payout_condition; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; struct betting_market_update_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -199,9 +220,9 @@ struct betting_market_update_operation : public base_operation optional new_payout_condition; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; @@ -214,6 +235,11 @@ enum class betting_market_resolution_type { struct betting_market_group_resolve_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -221,9 +247,9 @@ struct betting_market_group_resolve_operation : public base_operation std::map resolutions; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; @@ -262,14 +288,19 @@ struct betting_market_group_resolved_operation : public base_operation struct betting_market_group_cancel_unmatched_bets_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; betting_market_group_id_type betting_market_group_id; - extensions_type extensions; + extension extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; } void validate()const; }; @@ -448,24 +479,29 @@ FC_REFLECT( graphene::chain::betting_market_group_create_operation, (fee)(description)(event_id)(rules_id)(asset_id) (never_in_play)(delay_before_settling) (extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_create_operation::ext, (fee_paying_account) ); FC_REFLECT( graphene::chain::betting_market_group_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_group_update_operation, (fee)(betting_market_group_id)(new_description)(new_rules_id)(status)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_update_operation::ext, (fee_paying_account) ); FC_REFLECT( graphene::chain::betting_market_create_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_create_operation, (fee)(group_id)(description)(payout_condition)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_create_operation::ext, (fee_paying_account) ); FC_REFLECT( graphene::chain::betting_market_update_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_update_operation, (fee)(betting_market_id)(new_group_id)(new_description)(new_payout_condition)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_update_operation::ext, (fee_paying_account) ); FC_REFLECT_ENUM( graphene::chain::betting_market_resolution_type, (win)(not_win)(cancel)(BETTING_MARKET_RESOLUTION_COUNT) ) FC_REFLECT( graphene::chain::betting_market_group_resolve_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_group_resolve_operation, (fee)(betting_market_group_id)(resolutions)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_resolve_operation::ext, (fee_paying_account) ); FC_REFLECT( graphene::chain::betting_market_group_resolved_operation::fee_parameters_type, ) FC_REFLECT( graphene::chain::betting_market_group_resolved_operation, @@ -474,6 +510,7 @@ FC_REFLECT( graphene::chain::betting_market_group_resolved_operation, FC_REFLECT( graphene::chain::betting_market_group_cancel_unmatched_bets_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_group_cancel_unmatched_bets_operation, (fee)(betting_market_group_id)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_cancel_unmatched_bets_operation::ext, (fee_paying_account) ); FC_REFLECT_ENUM( graphene::chain::bet_type, (back)(lay) ) FC_REFLECT( graphene::chain::bet_place_operation::fee_parameters_type, (fee) ) diff --git a/libraries/chain/include/graphene/chain/protocol/event.hpp b/libraries/chain/include/graphene/chain/protocol/event.hpp index 5934ad89..7fab385d 100644 --- a/libraries/chain/include/graphene/chain/protocol/event.hpp +++ b/libraries/chain/include/graphene/chain/protocol/event.hpp @@ -25,11 +25,18 @@ #include #include +#include namespace graphene { namespace chain { struct event_create_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport || event_group + optional< account_id_type > new_manager; // new manager to set + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -48,9 +55,11 @@ struct event_create_operation : public base_operation */ object_id_type event_group_id; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; @@ -76,6 +85,12 @@ enum class event_status struct event_update_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport || event_group || event + optional< account_id_type > new_manager; // new manager to set + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -91,9 +106,11 @@ struct event_update_operation : public base_operation optional new_status; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; @@ -107,6 +124,11 @@ struct event_update_operation : public base_operation */ struct event_update_status_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport || event_group || event + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -124,24 +146,29 @@ struct event_update_status_operation : public base_operation */ vector scores; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; } } FC_REFLECT( graphene::chain::event_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_create_operation::ext, (fee_paying_account)(new_manager) ) FC_REFLECT( graphene::chain::event_create_operation, (fee)(name)(season)(start_time)(event_group_id)(extensions) ) FC_REFLECT( graphene::chain::event_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_update_operation::ext, (fee_paying_account)(new_manager) ) FC_REFLECT( graphene::chain::event_update_operation, (fee)(event_id)(new_event_group_id)(new_name)(new_season)(new_start_time)(new_status)(extensions) ) FC_REFLECT_ENUM( graphene::chain::event_status, (upcoming)(in_progress)(frozen)(finished)(canceled)(settled)(STATUS_COUNT) ) FC_REFLECT( graphene::chain::event_update_status_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_update_status_operation::ext, (fee_paying_account) ) FC_REFLECT( graphene::chain::event_update_status_operation, (fee)(event_id)(status)(scores)(extensions) ) diff --git a/libraries/chain/include/graphene/chain/protocol/event_group.hpp b/libraries/chain/include/graphene/chain/protocol/event_group.hpp index ad88ed35..026ab87b 100644 --- a/libraries/chain/include/graphene/chain/protocol/event_group.hpp +++ b/libraries/chain/include/graphene/chain/protocol/event_group.hpp @@ -25,11 +25,18 @@ #include #include +#include namespace graphene { namespace chain { struct event_group_create_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport + optional< account_id_type > new_manager; // the new_manager for this object + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -44,14 +51,22 @@ struct event_group_create_operation : public base_operation */ object_id_type sport_id; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; struct event_group_update_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport || event_group + optional< account_id_type > new_manager; + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; @@ -65,35 +80,47 @@ struct event_group_update_operation : public base_operation optional new_name; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; struct event_group_delete_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport || event_group + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; event_group_id_type event_group_id; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; } } FC_REFLECT( graphene::chain::event_group_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_group_create_operation::ext, (new_manager) (fee_paying_account) ) FC_REFLECT( graphene::chain::event_group_create_operation, (fee)(name)(sport_id)(extensions) ) FC_REFLECT( graphene::chain::event_group_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_group_update_operation::ext, (new_manager) (fee_paying_account) ) FC_REFLECT( graphene::chain::event_group_update_operation, (fee)(new_sport_id)(new_name)(event_group_id)(extensions) ) FC_REFLECT( graphene::chain::event_group_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::event_group_delete_operation::ext, (fee_paying_account) ) FC_REFLECT( graphene::chain::event_group_delete_operation, (fee)(event_group_id)(extensions) ) diff --git a/libraries/chain/include/graphene/chain/protocol/sport.hpp b/libraries/chain/include/graphene/chain/protocol/sport.hpp index 3c710d83..20db1a72 100644 --- a/libraries/chain/include/graphene/chain/protocol/sport.hpp +++ b/libraries/chain/include/graphene/chain/protocol/sport.hpp @@ -33,7 +33,7 @@ struct sport_create_operation : public base_operation { struct ext { - optional< account_id_type > manager; + optional< account_id_type > manager; }; struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -54,7 +54,8 @@ struct sport_update_operation : public base_operation { struct ext { - optional< account_id_type > manager; + optional< account_id_type > fee_paying_account; // manager of sport + optional< account_id_type > new_manager; }; struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -66,20 +67,29 @@ struct sport_update_operation : public base_operation extension< ext > extensions; - account_id_type fee_payer()const { return extensions.value.manager.valid() ? *extensions.value.manager : GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; struct sport_delete_operation : public base_operation { + struct ext + { + optional< account_id_type > fee_paying_account; // manager of sport + }; + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; sport_id_type sport_id; - extensions_type extensions; + extension< ext > extensions; - account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + account_id_type fee_payer()const { + return extensions.value.fee_paying_account ? *extensions.value.fee_paying_account : GRAPHENE_WITNESS_ACCOUNT; + } void validate()const; }; @@ -91,10 +101,11 @@ FC_REFLECT( graphene::chain::sport_create_operation, (fee)(name)(extensions) ) FC_REFLECT( graphene::chain::sport_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::sport_update_operation::ext, (manager) ) +FC_REFLECT( graphene::chain::sport_update_operation::ext, (new_manager) (fee_paying_account) ) FC_REFLECT( graphene::chain::sport_update_operation, (fee)(sport_id)(new_name)(extensions) ) FC_REFLECT( graphene::chain::sport_delete_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::sport_delete_operation::ext, (fee_paying_account) ) FC_REFLECT( graphene::chain::sport_delete_operation, (fee)(sport_id)(extensions) ) diff --git a/libraries/chain/include/graphene/chain/sport_object.hpp b/libraries/chain/include/graphene/chain/sport_object.hpp index 1bd25443..63c4f684 100644 --- a/libraries/chain/include/graphene/chain/sport_object.hpp +++ b/libraries/chain/include/graphene/chain/sport_object.hpp @@ -41,7 +41,7 @@ class sport_object : public graphene::db::abstract_object< sport_object > /// manager account can modify the sportobject without the permission /// of the witness_account, also he can modify all objects beneath (event_group etc.) - account_id_type manager; + account_id_type manager = account_id_type(1); }; typedef multi_index_container< @@ -52,4 +52,4 @@ typedef multi_index_container< typedef generic_index sport_object_index; } } // graphene::chain -FC_REFLECT_DERIVED( graphene::chain::sport_object, (graphene::db::object), (name) ) +FC_REFLECT_DERIVED( graphene::chain::sport_object, (graphene::db::object), (name) (manager) ) diff --git a/libraries/chain/manager.cpp b/libraries/chain/manager.cpp new file mode 100644 index 00000000..939321e9 --- /dev/null +++ b/libraries/chain/manager.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +namespace graphene { namespace chain { + +bool is_manager( const database& db, const sport_id_type& sport_id, const account_id_type& manager_id ) +{ + return sport_id(db).manager == manager_id || GRAPHENE_WITNESS_ACCOUNT == manager_id; +} + +bool is_manager( const database& db, const event_group_id_type& event_group_id, const account_id_type& manager_id ) +{ + const event_group_object& event_group_obj = event_group_id(db); + if( event_group_obj.manager == manager_id || GRAPHENE_WITNESS_ACCOUNT == manager_id ) + return true; + + return is_manager( db, event_group_obj.sport_id, manager_id ); +} + +bool is_manager( const database& db, const event_id_type& event_id, const account_id_type& manager_id ) +{ + const event_object& event_obj = event_id(db); + if( event_obj.manager == manager_id || GRAPHENE_WITNESS_ACCOUNT == manager_id ) + return true; + + return is_manager( db, event_obj.event_group_id, manager_id ); +} + +bool is_manager( const database& db, const betting_market_group_id_type& betting_market_group_id, + const account_id_type& manager_id ) +{ + return GRAPHENE_WITNESS_ACCOUNT == manager_id || is_manager( db, betting_market_group_id(db).event_id, manager_id ); +} + +bool is_manager( const database& db, const betting_market_id_type& betting_market_id, + const account_id_type& manager_id ) +{ + return GRAPHENE_WITNESS_ACCOUNT == manager_id || is_manager( db, betting_market_id(db).group_id, manager_id ); +} + +} } // graphene::chain \ No newline at end of file diff --git a/libraries/chain/sport_evaluator.cpp b/libraries/chain/sport_evaluator.cpp index b074168b..ce777109 100644 --- a/libraries/chain/sport_evaluator.cpp +++ b/libraries/chain/sport_evaluator.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace graphene { namespace chain { @@ -40,7 +41,9 @@ bool is_manager( const database& db, const sport_id_type sport_id, const account void_result sport_create_evaluator::do_evaluate(const sport_create_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); + FC_ASSERT( trx_state->_is_proposed_trx ); + if( db().head_block_time() <= HARDFORK_MANAGER_TIME ) + FC_ASSERT( !op.extensions.value.manager ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -50,7 +53,7 @@ object_id_type sport_create_evaluator::do_apply(const sport_create_operation& op const sport_object& new_sport = db().create( [&]( sport_object& sport_obj ) { sport_obj.name = op.name; - if( op.extensions.value.manager.valid() ) + if( op.extensions.value.manager ) sport_obj.manager = *op.extensions.value.manager; }); return new_sport.id; @@ -60,10 +63,18 @@ object_id_type sport_create_evaluator::do_apply(const sport_create_operation& op void_result sport_update_evaluator::do_evaluate(const sport_update_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1000_TIME); - FC_ASSERT(trx_state->_is_proposed_trx - || ( op.extensions.value.manager.valid() ? is_manager( db(), op.sport_id, *op.extensions.value.manager ) : false ) ); - - FC_ASSERT(op.new_name.valid()); + + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( op.new_name, "nothing to change"); + FC_ASSERT( !op.extensions.value.new_manager && !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.sport_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + FC_ASSERT( op.new_name || op.extensions.value.new_manager, "nothing to change" ); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -76,6 +87,8 @@ void_result sport_update_evaluator::do_apply(const sport_update_operation& op) { if( op.new_name.valid() ) spo.name = *op.new_name; + if( op.extensions.value.new_manager ) + spo.manager = *op.extensions.value.new_manager; }); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -84,7 +97,14 @@ void_result sport_update_evaluator::do_apply(const sport_update_operation& op) void_result sport_delete_evaluator::do_evaluate( const sport_delete_operation& op ) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_1001_TIME); - FC_ASSERT(trx_state->_is_proposed_trx); + if( db().head_block_time() < HARDFORK_MANAGER_TIME ) { // remove after HARDFORK_MANAGER_TIME + FC_ASSERT( trx_state->_is_proposed_trx ); + FC_ASSERT( !op.extensions.value.fee_paying_account ); + } + else { + FC_ASSERT( is_manager( db(), op.sport_id, op.fee_payer() ), + "fee_payer is not the manager of this object" ); + } //check for sport existence _sport = &op.sport_id(db());