diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 35cf3880..c6408bf4 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -292,6 +292,20 @@ namespace graphene { namespace app { } case balance_object_type:{ /** these are free from any accounts */ break; + } + case sport_object_type: + case competitor_object_type: + case event_group_object_type: + case event_object_type: + case betting_market_group_object_type: + case betting_market_object_type: + /** these are free from any accounts */ + break; + case bet_object_type:{ + const auto& aobj = dynamic_cast(obj); + assert( aobj != nullptr ); + result.push_back( aobj->bettor_id ); + break; } } } @@ -350,6 +364,8 @@ namespace graphene { namespace app { break; case impl_fba_accumulator_object_type: break; + case impl_betting_market_position_object_type: + break; } } return result; diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index 5e83adb3..0087d63a 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -97,6 +97,22 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op) FC_ASSERT( db().find_object(op.bettor_id), "Invalid betting_market_group specified" ); FC_ASSERT( db().find_object(op.betting_market_id), "Invalid betting_market specified" ); + const chain_parameters& current_params = db().get_global_properties().parameters; + FC_ASSERT( op.backer_multiplier >= current_params.min_bet_multiplier && + op.backer_multiplier <= current_params.max_bet_multiplier, + "Bet odds are outside the blockchain's limits" ); + + if (!current_params.permitted_betting_odds_increments.empty()) + { + bet_multiplier_type allowed_increment; + const auto iter = current_params.permitted_betting_odds_increments.upper_bound(op.backer_multiplier); + if (iter == current_params.permitted_betting_odds_increments.end()) + allowed_increment = std::prev(current_params.permitted_betting_odds_increments.end())->second; + else + allowed_increment = iter->second; + FC_ASSERT(op.backer_multiplier % allowed_increment == 0, "Bet odds must be a multiple of ${allowed_increment}", ("allowed_increment", allowed_increment)); + } + return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index dc926cb9..56e698ae 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -159,6 +159,9 @@ const uint8_t betting_market_object::type_id; const uint8_t bet_object::space_id; const uint8_t bet_object::type_id; +const uint8_t betting_market_position_object::space_id; +const uint8_t betting_market_position_object::type_id; + void database::initialize_evaluators() { @@ -263,6 +266,7 @@ void database::initialize_indexes() add_index< primary_index< buyback_index > >(); add_index< primary_index< simple_index< fba_accumulator_object > > >(); + add_index< primary_index< betting_market_position_multi_index > >(); } void database::init_genesis(const genesis_state_type& genesis_state) diff --git a/libraries/chain/include/graphene/chain/betting_market_object.hpp b/libraries/chain/include/graphene/chain/betting_market_object.hpp index ac080b22..023358e0 100644 --- a/libraries/chain/include/graphene/chain/betting_market_object.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_object.hpp @@ -77,6 +77,22 @@ class bet_object : public graphene::db::abstract_object< bet_object > bet_type back_or_lay; }; +class betting_market_position_object : public graphene::db::abstract_object< betting_market_position_object > +{ + public: + static const uint8_t space_id = implementation_ids; + static const uint8_t type_id = impl_betting_market_position_object_type; + + account_id_type bettor_id; + + betting_market_id_type betting_market_id; + + share_type pay_if_payout_condition; + share_type pay_if_not_payout_condition; + share_type pay_if_canceled; + share_type pay_if_not_canceled; +}; + typedef multi_index_container< betting_market_group_object, indexed_by< @@ -100,8 +116,17 @@ typedef multi_index_container< ordered_unique< tag, member< object, object_id_type, &object::id > > > > bet_object_multi_index_type; typedef generic_index bet_object_index; + +typedef multi_index_container< + betting_market_position_object, + indexed_by< + ordered_unique< tag, member< object, object_id_type, &object::id > > > > betting_market_position_multi_index_type; + +typedef generic_index betting_market_position_multi_index; } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (event_id)(options) ) FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(payout_condition)(asset_id) ) FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(amount_reserved_for_fees)(back_or_lay) ) + +FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled) ) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index f5c4b556..1dcd756b 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -186,3 +186,16 @@ /// the largest bet multiplier we will accept #define GRAPHENE_BETTING_MAX_MULTIPLIER 100010000 ///@} +#define GRAPHENE_DEFAULT_MIN_BET_MULTIPLIER 10100 +#define GRAPHENE_DEFAULT_MAX_BET_MULTIPLIER 10000000 +#define GRAPHENE_DEFAULT_PERMITTED_BETTING_ODDS_INCREMENTS { { 20000, 100}, /* <= 2: 0.01 */ \ + { 30000, 200}, /* <= 3: 0.02 */ \ + { 40000, 500}, /* <= 4: 0.05 */ \ + { 60000, 1000}, /* <= 6: 0.10 */ \ + { 100000, 2000}, /* <= 10: 0.20 */ \ + { 200000, 5000}, /* <= 20: 0.50 */ \ + { 300000, 10000}, /* <= 30: 1.00 */ \ + { 500000, 20000}, /* <= 50: 2.00 */ \ + { 1000000, 50000}, /* <= 100: 5.00 */ \ + { 10000000, 100000} } /* <= 1000: 10.00 */ + diff --git a/libraries/chain/include/graphene/chain/event_object.hpp b/libraries/chain/include/graphene/chain/event_object.hpp index 247e3636..74673e5a 100644 --- a/libraries/chain/include/graphene/chain/event_object.hpp +++ b/libraries/chain/include/graphene/chain/event_object.hpp @@ -37,15 +37,6 @@ class event_object : public graphene::db::abstract_object< event_object > static const uint8_t space_id = protocol_ids; static const uint8_t type_id = event_object_type; - enum status - { - upcoming, - in_progress, - completed, - canceled, - STATUS_COUNT - }; - internationalized_string_type name; internationalized_string_type season; @@ -55,6 +46,9 @@ class event_object : public graphene::db::abstract_object< event_object > event_group_id_type event_group_id; vector competitors; + + event_status status; + vector scores; }; typedef multi_index_container< @@ -65,5 +59,4 @@ typedef multi_index_container< typedef generic_index event_object_index; } } // graphene::chain -FC_REFLECT_ENUM( graphene::chain::event_object::status, (upcoming)(in_progress)(completed)(canceled)(STATUS_COUNT) ) -FC_REFLECT_DERIVED( graphene::chain::event_object, (graphene::db::object), (name)(season)(start_time)(event_group_id)(competitors) ) +FC_REFLECT_DERIVED( graphene::chain::event_object, (graphene::db::object), (name)(season)(start_time)(event_group_id)(status)(competitors)(scores) ) diff --git a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp index 5da23817..0b42b8db 100644 --- a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp @@ -111,7 +111,6 @@ struct betting_market_resolve_operation : public base_operation }; enum class bet_type { back, lay }; -typedef uint32_t bet_multiplier_type; struct bet_place_operation : public base_operation { diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 4dbd6c15..5252f982 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -69,6 +69,11 @@ namespace graphene { namespace chain { uint16_t accounts_per_fee_scale = GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE; ///< number of accounts between fee scalings uint8_t account_fee_scale_bitshifts = GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS; ///< number of times to left bitshift account registration fee at each scaling uint8_t max_authority_depth = GRAPHENE_MAX_SIG_CHECK_DEPTH; + + bet_multiplier_type min_bet_multiplier = GRAPHENE_DEFAULT_MIN_BET_MULTIPLIER; + bet_multiplier_type max_bet_multiplier = GRAPHENE_DEFAULT_MAX_BET_MULTIPLIER; + flat_map permitted_betting_odds_increments = GRAPHENE_DEFAULT_PERMITTED_BETTING_ODDS_INCREMENTS; + extensions_type extensions; /** defined in fee_schedule.cpp */ @@ -106,5 +111,8 @@ FC_REFLECT( graphene::chain::chain_parameters, (accounts_per_fee_scale) (account_fee_scale_bitshifts) (max_authority_depth) + (min_bet_multiplier) + (max_bet_multiplier) + (permitted_betting_odds_increments) (extensions) ) diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 904324b8..4c7a0501 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -162,7 +162,8 @@ namespace graphene { namespace chain { impl_budget_record_object_type, impl_special_authority_object_type, impl_buyback_object_type, - impl_fba_accumulator_object_type + impl_fba_accumulator_object_type, + impl_betting_market_position_object_type }; //typedef fc::unsigned_int object_id_type; @@ -228,6 +229,7 @@ namespace graphene { namespace chain { class special_authority_object; class buyback_object; class fba_accumulator_object; + class betting_market_position_object; typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type; typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type; @@ -248,6 +250,7 @@ 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_betting_market_position_object_type, betting_market_position_object > betting_market_position_id_type; typedef fc::array symbol_type; typedef fc::ripemd160 block_id_type; @@ -327,6 +330,8 @@ namespace graphene { namespace chain { }; typedef flat_map internationalized_string_type; + + typedef uint32_t bet_multiplier_type; } } // graphene::chain namespace fc @@ -390,6 +395,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type, (impl_special_authority_object_type) (impl_buyback_object_type) (impl_fba_accumulator_object_type) + (impl_betting_market_position_object_type) ) FC_REFLECT_TYPENAME( graphene::chain::share_type ) @@ -428,6 +434,7 @@ FC_REFLECT_TYPENAME( graphene::chain::budget_record_id_type ) FC_REFLECT_TYPENAME( graphene::chain::special_authority_id_type ) FC_REFLECT_TYPENAME( graphene::chain::buyback_id_type ) FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type ) FC_REFLECT( graphene::chain::void_t, ) diff --git a/libraries/chain/protocol/fee_schedule.cpp b/libraries/chain/protocol/fee_schedule.cpp index ab8f6532..81bbbf07 100644 --- a/libraries/chain/protocol/fee_schedule.cpp +++ b/libraries/chain/protocol/fee_schedule.cpp @@ -188,6 +188,12 @@ namespace graphene { namespace chain { "Maximum transaction expiration time must be greater than a block interval" ); FC_ASSERT( maximum_proposal_lifetime - committee_proposal_review_period > block_interval, "Committee proposal review period must be less than the maximum proposal lifetime" ); + + FC_ASSERT( min_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER && + min_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER ); + FC_ASSERT( max_bet_multiplier >= GRAPHENE_BETTING_MIN_MULTIPLIER && + max_bet_multiplier <= GRAPHENE_BETTING_MAX_MULTIPLIER ); + FC_ASSERT( min_bet_multiplier < max_bet_multiplier ); } } } // graphene::chain