Start of a plugin to track deleted events (and other deleted objects) needed by the

bookie ui
This commit is contained in:
Eric Frias 2017-04-04 17:02:19 -04:00
parent 6045b8b096
commit 672fad6d40
10 changed files with 654 additions and 7 deletions

View file

@ -126,6 +126,18 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op)
FC_ASSERT(bet_object::get_matching_amount(op.amount_to_bet.amount, op.backer_multiplier, op.back_or_lay) != 0,
"Bet cannot be matched");
#if 0
bet_object simulated_bet;
simulated_bet.bettor_id = op.bettor_id;
simulated_bet.betting_market_id = op.betting_market_id;
simulated_bet.amount_to_bet = op.amount_to_bet;
simulated_bet.backer_multiplier = op.backer_multiplier;
simulated_bet.amount_reserved_for_fees = op.amount_reserved_for_fees;
simulated_bet.back_or_lay = op.back_or_lay;
share_type required_deposit = get_required_deposit_for_bet(simulated_bet);
#endif
// verify they reserved enough to cover the percentage fee
uint16_t percentage_fee = current_params.current_fees->get<bet_place_operation>().percentage_fee;
fc::uint128_t minimum_percentage_fee_calculation = op.amount_to_bet.amount.value;

View file

@ -104,6 +104,13 @@ void database::resolve_betting_market(const betting_market_object& betting_marke
remove(betting_market);
}
#if 0
void database::get_required_deposit_for_bet(const betting_market_object& betting_market,
betting_market_resolution_type resolution)
{
}
#endif
bool maybe_cull_small_bet( database& db, const bet_object& bet_object_to_cull )
{
/**

View file

@ -225,13 +225,160 @@ struct compare_bet_by_odds {
}
};
struct compare_bet_by_bettor_then_odds {
bool operator()(const bet_object& lhs, const bet_object& rhs) const
{
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier, rhs.id);
}
template<typename T0>
bool operator() (const std::tuple<T0>& lhs, const bet_object& rhs) const
{
return compare(std::get<0>(lhs), rhs.betting_market_id);
}
template<typename T0>
bool operator() (const bet_object& lhs, const std::tuple<T0>& rhs) const
{
return compare(lhs.betting_market_id, std::get<0>(rhs));
}
template<typename T0, typename T1>
bool operator() (const std::tuple<T0, T1>& lhs, const bet_object& rhs) const
{
return compare(std::get<0>(lhs), std::get<1>(lhs), rhs.betting_market_id, rhs.bettor_id);
}
template<typename T0, typename T1>
bool operator() (const bet_object& lhs, const std::tuple<T0, T1>& rhs) const
{
return compare(lhs.betting_market_id, lhs.bettor_id, std::get<0>(rhs), std::get<1>(rhs));
}
template<typename T0, typename T1, typename T2>
bool operator() (const std::tuple<T0, T1, T2>& lhs, const bet_object& rhs) const
{
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs),
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay);
}
template<typename T0, typename T1, typename T2>
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2>& rhs) const
{
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay,
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs));
}
template<typename T0, typename T1, typename T2, typename T3>
bool operator() (const std::tuple<T0, T1, T2, T3>& lhs, const bet_object& rhs) const
{
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs), std::get<3>(lhs),
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier);
}
template<typename T0, typename T1, typename T2, typename T3>
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2, T3>& rhs) const
{
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs), std::get<3>(rhs));
}
template<typename T0, typename T1, typename T2, typename T3, typename T4>
bool operator() (const std::tuple<T0, T1, T2, T3, T4>& lhs, const bet_object& rhs) const
{
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs), std::get<3>(lhs), std::get<4>(lhs),
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier, rhs.id);
}
template<typename T0, typename T1, typename T2, typename T3, typename T4>
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2, T3, T4>& rhs) const
{
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs), std::get<3>(rhs), std::get<4>(rhs));
}
bool compare(const betting_market_id_type& lhs_betting_market_id, const betting_market_id_type& rhs_betting_market_id) const
{
return lhs_betting_market_id < rhs_betting_market_id;
}
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id) const
{
if (lhs_betting_market_id < rhs_betting_market_id)
return true;
if (lhs_betting_market_id > rhs_betting_market_id)
return false;
return lhs_bettor_id < rhs_bettor_id;
}
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
bet_type lhs_bet_type,
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
bet_type rhs_bet_type) const
{
if (lhs_betting_market_id < rhs_betting_market_id)
return true;
if (lhs_betting_market_id > rhs_betting_market_id)
return false;
if (lhs_bettor_id < rhs_bettor_id)
return true;
if (lhs_bettor_id > rhs_bettor_id)
return false;
return lhs_bet_type < rhs_bet_type;
}
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
bet_type lhs_bet_type,
bet_multiplier_type lhs_backer_multiplier,
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
bet_type rhs_bet_type,
bet_multiplier_type rhs_backer_multiplier) const
{
if (lhs_betting_market_id < rhs_betting_market_id)
return true;
if (lhs_betting_market_id > rhs_betting_market_id)
return false;
if (lhs_bettor_id < rhs_bettor_id)
return true;
if (lhs_bettor_id > rhs_bettor_id)
return false;
if (lhs_bet_type < rhs_bet_type)
return true;
if (lhs_bet_type > rhs_bet_type)
return false;
return lhs_backer_multiplier < rhs_backer_multiplier;
}
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
bet_type lhs_bet_type,
bet_multiplier_type lhs_backer_multiplier, const bet_id_type& lhs_bet_id,
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
bet_type rhs_bet_type,
bet_multiplier_type rhs_backer_multiplier, const bet_id_type& rhs_bet_id) const
{
if (lhs_betting_market_id < rhs_betting_market_id)
return true;
if (lhs_betting_market_id > rhs_betting_market_id)
return false;
if (lhs_bettor_id < rhs_bettor_id)
return true;
if (lhs_bettor_id > rhs_bettor_id)
return false;
if (lhs_bet_type < rhs_bet_type)
return true;
if (lhs_bet_type > rhs_bet_type)
return false;
if (lhs_backer_multiplier < rhs_backer_multiplier)
return true;
if (lhs_backer_multiplier > rhs_backer_multiplier)
return false;
return lhs_bet_id < rhs_bet_id;
}
};
struct by_odds {};
struct by_bettor_and_odds {};
typedef multi_index_container<
bet_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_odds>, identity<bet_object>, compare_bet_by_odds > > > bet_object_multi_index_type;
ordered_unique< tag<by_odds>, identity<bet_object>, compare_bet_by_odds >,
ordered_unique< tag<by_bettor_and_odds>, identity<bet_object>, compare_bet_by_bettor_then_odds > > > bet_object_multi_index_type;
typedef generic_index<bet_object, bet_object_multi_index_type> bet_object_index;
struct by_bettor_betting_market{};

View file

@ -2,3 +2,4 @@ add_subdirectory( witness )
add_subdirectory( account_history )
add_subdirectory( market_history )
add_subdirectory( delayed_node )
add_subdirectory( bookie )

View file

@ -0,0 +1,21 @@
file(GLOB HEADERS "include/graphene/bookie/*.hpp")
add_library( graphene_bookie
bookie_plugin.cpp
)
target_link_libraries( graphene_bookie graphene_chain graphene_app )
target_include_directories( graphene_bookie
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
if(MSVC)
set_source_files_properties( bookie_plugin.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)
install( TARGETS
graphene_bookie
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View file

@ -0,0 +1,342 @@
/*
* 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 <graphene/bookie/bookie_plugin.hpp>
#include <graphene/app/impacted.hpp>
#include <graphene/chain/account_evaluator.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/operation_history_object.hpp>
#include <graphene/chain/transaction_evaluation_state.hpp>
#include <fc/smart_ref_impl.hpp>
#include <fc/thread/thread.hpp>
#include <boost/polymorphic_cast.hpp>
#if 0
# ifdef DEFAULT_LOGGER
# undef DEFAULT_LOGGER
# endif
# define DEFAULT_LOGGER "bookie_plugin"
#endif
namespace graphene { namespace bookie {
namespace detail
{
class persistent_event_object : public graphene::db::abstract_object<event_object>
{
public:
static const uint8_t space_id = bookie_objects;
static const uint8_t type_id = persistent_event_object_type;
event_id_type event_object_id;
internationalized_string_type name;
internationalized_string_type season;
optional<time_point_sec> start_time;
event_group_id_type event_group_id;
vector<competitor_id_type> competitors;
event_status status;
vector<string> scores;
};
typedef object_id<bookie_objects, persistent_event_object_type, persistent_event_object> persistent_event_id_type;
struct by_event_id;
typedef multi_index_container<
persistent_event_object,
indexed_by<
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
ordered_unique<tag<by_event_id>, member<persistent_event_object, event_id_type, &persistent_event_object::event_object_id> > > > persistent_event_object_multi_index_type;
typedef generic_index<persistent_event_object, persistent_event_object_multi_index_type> persistent_event_object_index;
class events_by_competitor_index : public secondary_index
{
public:
virtual ~events_by_competitor_index() {}
virtual void object_inserted( const object& obj ) override;
virtual void object_removed( const object& obj ) override;
virtual void about_to_modify( const object& before ) override;
virtual void object_modified( const object& after ) override;
protected:
map<competitor_id_type, set<persistent_event_id_type> > competitor_to_events;
};
void events_by_competitor_index::object_inserted( const object& obj )
{
const persistent_event_object& event_obj = *boost::polymorphic_downcast<const persistent_event_object*>(&obj);
for (const competitor_id_type& competitor_id : event_obj.competitors)
competitor_to_events[competitor_id].insert(event_obj.id);
for (const competitor_id_type& competitor_id : event_obj.competitors)
competitor_to_events[competitor_id].insert(event_obj.id);
}
void events_by_competitor_index::object_removed( const object& obj )
{
const persistent_event_object& event_obj = *boost::polymorphic_downcast<const persistent_event_object*>(&obj);
for (const competitor_id_type& competitor_id : event_obj.competitors)
competitor_to_events[competitor_id].erase(event_obj.id);
}
void events_by_competitor_index::about_to_modify( const object& before )
{
object_removed(before);
}
void events_by_competitor_index::object_modified( const object& after )
{
object_inserted(after);
}
class bookie_plugin_impl
{
public:
bookie_plugin_impl(bookie_plugin& _plugin)
: _self( _plugin )
{ }
virtual ~bookie_plugin_impl();
/**
* Called After a block has been applied and committed. The callback
* should not yield and should execute quickly.
*/
void on_objects_changed(const vector<object_id_type>& changed_object_ids);
/** this method is called as a callback after a block is applied
* and will process/index all operations that were applied in the block.
*/
void on_block_applied( const signed_block& b );
graphene::chain::database& database()
{
return _self.database();
}
bookie_plugin& _self;
flat_set<account_id_type> _tracked_accounts;
};
bookie_plugin_impl::~bookie_plugin_impl()
{
return;
}
void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& changed_object_ids)
{
graphene::chain::database& db = database();
auto& event_id_index = db.get_index_type<persistent_event_object_index>().indices().get<by_event_id>();
for (const object_id_type& changed_object_id : changed_object_ids)
{
if (changed_object_id.space() == event_id_type::space_id &&
changed_object_id.type() == event_id_type::type_id)
{
event_id_type changed_event_id = changed_object_id;
const event_object* new_event_obj = nullptr;
try
{
new_event_obj = &changed_event_id(db);
}
catch (fc::exception& e)
{
}
// new_event_obj should point to the now-changed event_object, or null if it was removed from the database
const persistent_event_object* old_event_obj = nullptr;
auto persistent_event_iter = event_id_index.find(changed_event_id);
if (persistent_event_iter != event_id_index.end())
old_event_obj = &*persistent_event_iter;
// and old_event_obj is a pointer to our saved copy, or nullptr if it is a new object
if (old_event_obj && new_event_obj)
{
ilog("Modifying persistent event object ${id}", ("id", changed_event_id));
db.modify(*old_event_obj, [&](persistent_event_object& saved_event_obj) {
saved_event_obj.name = new_event_obj->name;
saved_event_obj.season = new_event_obj->season;
saved_event_obj.start_time = new_event_obj->start_time;;
saved_event_obj.event_group_id = new_event_obj->event_group_id;
saved_event_obj.competitors = new_event_obj->competitors;
saved_event_obj.status = new_event_obj->status;
saved_event_obj.scores = new_event_obj->scores;
});
}
else if (new_event_obj)
{
ilog("Creating new persistent event object ${id}", ("id", changed_event_id));
db.create<persistent_event_object>([&](persistent_event_object& saved_event_obj) {
saved_event_obj.event_object_id = new_event_obj->id;
saved_event_obj.name = new_event_obj->name;
saved_event_obj.season = new_event_obj->season;
saved_event_obj.start_time = new_event_obj->start_time;;
saved_event_obj.event_group_id = new_event_obj->event_group_id;
saved_event_obj.competitors = new_event_obj->competitors;
saved_event_obj.status = new_event_obj->status;
saved_event_obj.scores = new_event_obj->scores;
});
}
}
}
}
void bookie_plugin_impl::on_block_applied( const signed_block& )
{
graphene::chain::database& db = database();
const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
for( const optional< operation_history_object >& o_op : hist )
{
// add to the operation history index
const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h )
{
if( o_op.valid() )
h = *o_op;
} );
if( !o_op.valid() )
{
ilog( "removing failed operation with ID: ${id}", ("id", oho.id) );
db.remove( oho );
continue;
}
const operation_history_object& op = *o_op;
// get the set of accounts this operation applies to
flat_set<account_id_type> impacted;
vector<authority> other;
operation_get_required_authorities( op.op, impacted, impacted, other );
if( op.op.which() == operation::tag< account_create_operation >::value )
impacted.insert( oho.result.get<object_id_type>() );
else
graphene::app::operation_get_impacted_accounts( op.op, impacted );
for( auto& a : other )
for( auto& item : a.account_auths )
impacted.insert( item.first );
// for each operation this account applies to that is in the config link it into the history
if( _tracked_accounts.size() == 0 )
{
for( auto& account_id : impacted )
{
// we don't do index_account_keys here anymore, because
// that indexing now happens in observers' post_evaluate()
// add history
const auto& stats_obj = account_id(db).statistics(db);
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
obj.operation_id = oho.id;
obj.next = stats_obj.most_recent_op;
});
db.modify( stats_obj, [&]( account_statistics_object& obj ){
obj.most_recent_op = ath.id;
});
}
}
else
{
for( auto account_id : _tracked_accounts )
{
if( impacted.find( account_id ) != impacted.end() )
{
// add history
const auto& stats_obj = account_id(db).statistics(db);
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
obj.operation_id = oho.id;
obj.next = stats_obj.most_recent_op;
});
db.modify( stats_obj, [&]( account_statistics_object& obj ){
obj.most_recent_op = ath.id;
});
}
}
}
}
}
} // end namespace detail
bookie_plugin::bookie_plugin() :
my( new detail::bookie_plugin_impl(*this) )
{
}
bookie_plugin::~bookie_plugin()
{
}
std::string bookie_plugin::plugin_name()const
{
return "bookie";
}
void bookie_plugin::plugin_set_program_options(
boost::program_options::options_description& cli,
boost::program_options::options_description& cfg
)
{
cli.add_options()
("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
;
cfg.add(cli);
}
void bookie_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{
database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } );
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids){ my->on_objects_changed(changed_object_ids); });
auto event_index = database().add_index<primary_index<detail::persistent_event_object_index> >();
event_index->add_secondary_index<detail::events_by_competitor_index>();
LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type);
}
void bookie_plugin::plugin_startup()
{
}
flat_set<account_id_type> bookie_plugin::tracked_accounts() const
{
return my->_tracked_accounts;
}
} }
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (event_object_id)(name)(season)(start_time)(event_group_id)(status)(competitors)(scores) )

View file

@ -0,0 +1,79 @@
/*
* 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 <graphene/app/plugin.hpp>
#include <graphene/chain/database.hpp>
#include <fc/thread/future.hpp>
namespace graphene { namespace bookie {
using namespace chain;
//
// Plugins should #define their SPACE_ID's so plugins with
// conflicting SPACE_ID assignments can be compiled into the
// same binary (by simply re-assigning some of the conflicting #defined
// SPACE_ID's in a build script).
//
// Assignment of SPACE_ID's cannot be done at run-time because
// various template automagic depends on them being known at compile
// time.
//
enum spaces {
bookie_objects = 6
};
enum bookie_object_type
{
persistent_event_object_type,
BOOKIE_OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
};
namespace detail
{
class bookie_plugin_impl;
}
class bookie_plugin : public graphene::app::plugin
{
public:
bookie_plugin();
virtual ~bookie_plugin();
std::string plugin_name()const override;
virtual void plugin_set_program_options(
boost::program_options::options_description& cli,
boost::program_options::options_description& cfg) override;
virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
virtual void plugin_startup() override;
flat_set<account_id_type> tracked_accounts()const;
friend class detail::bookie_plugin_impl;
std::unique_ptr<detail::bookie_plugin_impl> my;
};
} } //graphene::bookie

View file

@ -8,25 +8,25 @@ endif()
file(GLOB UNIT_TESTS "tests/*.cpp")
add_executable( chain_test ${UNIT_TESTS} ${COMMON_SOURCES} )
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
if(MSVC)
set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)
file(GLOB PERFORMANCE_TESTS "performance/*.cpp")
add_executable( performance_test ${PERFORMANCE_TESTS} ${COMMON_SOURCES} )
target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
file(GLOB BENCH_MARKS "benchmarks/*.cpp")
add_executable( chain_bench ${BENCH_MARKS} ${COMMON_SOURCES} )
target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_bookie graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
file(GLOB APP_SOURCES "app/*.cpp")
add_executable( app_test ${APP_SOURCES} )
target_link_libraries( app_test graphene_app graphene_account_history graphene_net graphene_chain graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( app_test graphene_app graphene_account_history graphene_bookie graphene_net graphene_chain graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
file(GLOB INTENSE_SOURCES "intense/*.cpp")
add_executable( intense_test ${INTENSE_SOURCES} ${COMMON_SOURCES} )
target_link_libraries( intense_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
target_link_libraries( intense_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
add_subdirectory( generate_empty_blocks )

View file

@ -26,6 +26,7 @@
#include <graphene/account_history/account_history_plugin.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
#include <graphene/bookie/bookie_plugin.hpp>
#include <graphene/db/simple_index.hpp>
@ -79,6 +80,7 @@ database_fixture::database_fixture()
}
auto ahplugin = app.register_plugin<graphene::account_history::account_history_plugin>();
auto mhplugin = app.register_plugin<graphene::market_history::market_history_plugin>();
auto bookieplugin = app.register_plugin<graphene::bookie::bookie_plugin>();
init_account_pub_key = init_account_priv_key.get_public_key();
boost::program_options::variables_map options;
@ -104,9 +106,12 @@ database_fixture::database_fixture()
ahplugin->plugin_initialize(options);
mhplugin->plugin_set_app(&app);
mhplugin->plugin_initialize(options);
bookieplugin->plugin_set_app(&app);
bookieplugin->plugin_initialize(options);
ahplugin->plugin_startup();
mhplugin->plugin_startup();
bookieplugin->plugin_startup();
generate_block();

View file

@ -1891,3 +1891,36 @@ BOOST_AUTO_TEST_CASE( cancel )
BOOST_AUTO_TEST_SUITE_END()
struct simple_bet_test_fixture_2 : database_fixture {
betting_market_id_type capitals_win_betting_market_id;
simple_bet_test_fixture_2()
{
ACTORS( (alice)(bob) );
CREATE_ICE_HOCKEY_BETTING_MARKET();
// give alice and bob 10k each
transfer(account_id_type(), alice_id, asset(10000));
transfer(account_id_type(), bob_id, asset(10000));
// alice backs 1000 at 1:1, matches
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
// now alice lays at 2500 at 1:1. This should require a deposit of 500, with the remaining 200 being funded from exposure
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(2500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 50);
// match the bet bit by bit. bob matches 500 of alice's 2500 bet. This effectively cancels half of bob's lay position
// so he immediately gets 500 back. It reduces alice's back position, but doesn't return any money to her (all 2000 of her exposure
// was already "promised" to her lay bet, so the 500 she would have received is placed in her refundable_unmatched_bets)
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 10);
// match another 500, which will fully cancel bob's lay position and return the other 500 he had locked up in his position.
// alice's back position is now canceled, 1500 remains of her unmatched lay bet, and the 500 from canceling her position has
// been moved to her refundable_unmatched_bets
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 10);
capitals_win_betting_market_id = capitals_win_market.id;
}
};