/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "database_fixture.hpp" using namespace graphene::chain::test; uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP = 1431700002; namespace graphene { namespace chain { using std::cout; using std::cerr; database_fixture::database_fixture() : app(), db( *app.chain_database() ) { try { int argc = boost::unit_test::framework::master_test_suite().argc; char** argv = boost::unit_test::framework::master_test_suite().argv; for( int i=1; i(); auto mhplugin = app.register_plugin(); auto bookieplugin = app.register_plugin(); auto affiliateplugin = app.register_plugin(); init_account_pub_key = init_account_priv_key.get_public_key(); boost::program_options::variables_map options; genesis_state.initial_timestamp = time_point_sec( GRAPHENE_TESTING_GENESIS_TIMESTAMP ); //int back_to_the_past = 0; //back_to_the_past = 7 * 24 * 60 * 60; // week //genesis_state.initial_timestamp = time_point_sec( (fc::time_point::now().sec_since_epoch() - back_to_the_past) / GRAPHENE_DEFAULT_BLOCK_INTERVAL * GRAPHENE_DEFAULT_BLOCK_INTERVAL ); genesis_state.initial_parameters.witness_schedule_algorithm = GRAPHENE_WITNESS_SHUFFLED_ALGORITHM; genesis_state.initial_active_witnesses = 10; for( unsigned i = 0; i < genesis_state.initial_active_witnesses; ++i ) { auto name = "init"+fc::to_string(i); genesis_state.initial_accounts.emplace_back(name, init_account_priv_key.get_public_key(), init_account_priv_key.get_public_key(), true); genesis_state.initial_committee_candidates.push_back({name}); genesis_state.initial_witness_candidates.push_back({name, init_account_priv_key.get_public_key()}); } genesis_state.initial_parameters.current_fees->zero_all_fees(); open_database(); // add account tracking for ahplugin for special test case with track-account enabled if( !options.count("track-account") && boost::unit_test::framework::current_test_case().p_name.value == "track_account") { std::vector track_account; std::string track = "\"1.2.18\""; track_account.push_back(track); options.insert(std::make_pair("track-account", boost::program_options::variable_value(track_account, false))); options.insert(std::make_pair("partial-operations", boost::program_options::variable_value(true, false))); } // account tracking 2 accounts if( !options.count("track-account") && boost::unit_test::framework::current_test_case().p_name.value == "track_account2") { std::vector track_account; std::string track = "\"1.2.0\""; track_account.push_back(track); track = "\"1.2.17\""; track_account.push_back(track); options.insert(std::make_pair("track-account", boost::program_options::variable_value(track_account, false))); } // app.initialize(); ahplugin->plugin_set_app(&app); ahplugin->plugin_initialize(options); mhplugin->plugin_set_app(&app); mhplugin->plugin_initialize(options); bookieplugin->plugin_set_app(&app); bookieplugin->plugin_initialize(options); affiliateplugin->plugin_set_app(&app); affiliateplugin->plugin_initialize(options); ahplugin->plugin_startup(); mhplugin->plugin_startup(); bookieplugin->plugin_startup(); affiliateplugin->plugin_startup(); generate_block(); set_expiration( db, trx ); } catch ( const fc::exception& e ) { edump( (e.to_detail_string()) ); throw; } return; } database_fixture::~database_fixture() { try { // If we're unwinding due to an exception, don't do any more checks. // This way, boost test's last checkpoint tells us approximately where the error was. if( !std::uncaught_exception() ) { verify_asset_supplies(db); verify_account_history_plugin_index(); BOOST_CHECK( db.get_node_properties().skip_flags == database::skip_nothing ); } if( data_dir ) db.close(); return; } FC_CAPTURE_AND_RETHROW() } fc::ecc::private_key database_fixture::generate_private_key(string seed) { static const fc::ecc::private_key committee = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); if( seed == "null_key" ) return committee; return fc::ecc::private_key::regenerate(fc::sha256::hash(seed)); } string database_fixture::generate_anon_acct_name() { // names of the form "anon-acct-x123" ; the "x" is necessary // to workaround issue #46 return "anon-acct-x" + std::to_string( anon_acct_count++ ); } void database_fixture::verify_asset_supplies( const database& db ) { //wlog("*** Begin asset supply verification ***"); const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db); BOOST_CHECK(core_asset_data.fee_pool == 0); const simple_index& statistics_index = db.get_index_type>(); const auto& balance_index = db.get_index_type().indices(); const auto& settle_index = db.get_index_type().indices(); const auto& tournaments_index = db.get_index_type().indices(); const auto& asst_index = db.get_index_type().indices(); map total_balances; map total_debts; share_type core_in_orders; share_type reported_core_in_orders; for( const tournament_object& t : tournaments_index ) if (t.get_state() != tournament_state::concluded && t.get_state() != tournament_state::registration_period_expired) total_balances[t.options.buy_in.asset_id] += t.prize_pool; for( const asset_object& ai : asst_index) if (ai.is_lottery()) { asset balance = db.get_balance( ai.get_id() ); total_balances[ balance.asset_id ] += balance.amount; } for( const account_balance_object& b : balance_index ) total_balances[b.asset_type] += b.balance; for( const force_settlement_object& s : settle_index ) total_balances[s.balance.asset_id] += s.balance.amount; for( const account_statistics_object& a : statistics_index ) { reported_core_in_orders += a.total_core_in_orders; total_balances[asset_id_type()] += a.pending_fees + a.pending_vested_fees; } for( const limit_order_object& o : db.get_index_type().indices() ) { asset for_sale = o.amount_for_sale(); if( for_sale.asset_id == asset_id_type() ) core_in_orders += for_sale.amount; total_balances[for_sale.asset_id] += for_sale.amount; total_balances[asset_id_type()] += o.deferred_fee; } for( const call_order_object& o : db.get_index_type().indices() ) { asset col = o.get_collateral(); if( col.asset_id == asset_id_type() ) core_in_orders += col.amount; total_balances[col.asset_id] += col.amount; total_debts[o.get_debt().asset_id] += o.get_debt().amount; } for( const asset_object& asset_obj : db.get_index_type().indices() ) { const auto& dasset_obj = asset_obj.dynamic_asset_data_id(db); total_balances[asset_obj.id] += dasset_obj.accumulated_fees; total_balances[asset_id_type()] += dasset_obj.fee_pool; if( asset_obj.is_market_issued() ) { const auto& bad = asset_obj.bitasset_data(db); total_balances[bad.options.short_backing_asset] += bad.settlement_fund; } total_balances[asset_obj.id] += dasset_obj.confidential_supply.value; } for( const vesting_balance_object& vbo : db.get_index_type< vesting_balance_index >().indices() ) total_balances[ vbo.balance.asset_id ] += vbo.balance.amount; for( const fba_accumulator_object& fba : db.get_index_type< simple_index< fba_accumulator_object > >() ) total_balances[ asset_id_type() ] += fba.accumulated_fba_fees; for (const bet_object& o : db.get_index_type().indices()) { total_balances[o.amount_to_bet.asset_id] += o.amount_to_bet.amount; } for (const betting_market_position_object& o : db.get_index_type().indices()) { const betting_market_object& betting_market = o.betting_market_id(db); const betting_market_group_object& betting_market_group = betting_market.group_id(db); total_balances[betting_market_group.asset_id] += o.pay_if_canceled; total_balances[betting_market_group.asset_id] += o.fees_collected; } uint64_t sweeps_vestings = 0; for( const sweeps_vesting_balance_object& svbo: db.get_index_type< sweeps_vesting_balance_index >().indices() ) sweeps_vestings += svbo.balance; total_balances[db.get_global_properties().parameters.sweeps_distribution_asset()] += sweeps_vestings / SWEEPS_VESTING_BALANCE_MULTIPLIER; total_balances[asset_id_type()] += db.get_dynamic_global_properties().witness_budget; for( const auto& item : total_debts ) { BOOST_CHECK_EQUAL(item.first(db).dynamic_asset_data_id(db).current_supply.value, item.second.value); } for( const asset_object& asset_obj : db.get_index_type().indices() ) { BOOST_CHECK_EQUAL(total_balances[asset_obj.id].value, asset_obj.dynamic_asset_data_id(db).current_supply.value); } BOOST_CHECK_EQUAL( core_in_orders.value , reported_core_in_orders.value ); // wlog("*** End asset supply verification ***"); } void database_fixture::verify_account_history_plugin_index( )const { return; if( skip_key_index_test ) return; const std::shared_ptr pin = app.get_plugin("account_history"); if( pin->tracked_accounts().size() == 0 ) { /* vector< pair< account_id_type, address > > tuples_from_db; const auto& primary_account_idx = db.get_index_type().indices().get(); flat_set< public_key_type > acct_addresses; acct_addresses.reserve( 2 * GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP + 2 ); for( const account_object& acct : primary_account_idx ) { account_id_type account_id = acct.id; acct_addresses.clear(); for( const pair< account_id_type, weight_type >& auth : acct.owner.account_auths ) { if( auth.first.type() == key_object_type ) acct_addresses.insert( auth.first ); } for( const pair< object_id_type, weight_type >& auth : acct.active.auths ) { if( auth.first.type() == key_object_type ) acct_addresses.insert( auth.first ); } acct_addresses.insert( acct.options.get_memo_key()(db).key_address() ); for( const address& addr : acct_addresses ) tuples_from_db.emplace_back( account_id, addr ); } vector< pair< account_id_type, address > > tuples_from_index; tuples_from_index.reserve( tuples_from_db.size() ); const auto& key_account_idx = db.get_index_type() .indices().get(); for( const graphene::account_history::key_account_object& key_account : key_account_idx ) { address addr = key_account.key; for( const account_id_type& account_id : key_account.account_ids ) tuples_from_index.emplace_back( account_id, addr ); } // TODO: use function for common functionality { // due to hashed index, account_id's may not be in sorted order... std::sort( tuples_from_db.begin(), tuples_from_db.end() ); size_t size_before_uniq = tuples_from_db.size(); auto last = std::unique( tuples_from_db.begin(), tuples_from_db.end() ); tuples_from_db.erase( last, tuples_from_db.end() ); // but they should be unique (multiple instances of the same // address within an account should have been de-duplicated // by the flat_set above) BOOST_CHECK( tuples_from_db.size() == size_before_uniq ); } { // (address, account) should be de-duplicated by flat_set<> // in key_account_object std::sort( tuples_from_index.begin(), tuples_from_index.end() ); auto last = std::unique( tuples_from_index.begin(), tuples_from_index.end() ); size_t size_before_uniq = tuples_from_db.size(); tuples_from_index.erase( last, tuples_from_index.end() ); BOOST_CHECK( tuples_from_index.size() == size_before_uniq ); } //BOOST_CHECK_EQUAL( tuples_from_db, tuples_from_index ); bool is_equal = true; is_equal &= (tuples_from_db.size() == tuples_from_index.size()); for( size_t i=0,n=tuples_from_db.size(); ipath(), [this]{return genesis_state;}, "test"); } } signed_block database_fixture::generate_block(uint32_t skip, const fc::ecc::private_key& key, int miss_blocks) { skip |= database::skip_undo_history_check; // skip == ~0 will skip checks specified in database::validation_steps auto block = db.generate_block(db.get_slot_time(miss_blocks + 1), db.get_scheduled_witness(miss_blocks + 1), key, skip); db.clear_pending(); return block; } void database_fixture::generate_blocks( uint32_t block_count ) { for( uint32_t i = 0; i < block_count; ++i ) generate_block(); } void database_fixture::generate_blocks(fc::time_point_sec timestamp, bool miss_intermediate_blocks, uint32_t skip) { if( miss_intermediate_blocks ) { generate_block(skip); auto slots_to_miss = db.get_slot_at_time(timestamp); if( slots_to_miss <= 1 ) return; --slots_to_miss; generate_block(skip, init_account_priv_key, slots_to_miss); return; } while( db.head_block_time() < timestamp ) generate_block(skip); } account_create_operation database_fixture::make_account( const std::string& name /* = "nathan" */, public_key_type key /* = key_id_type() */ ) { try { account_create_operation create_account; create_account.registrar = account_id_type(); create_account.name = name; create_account.owner = authority(123, key, 123); create_account.active = authority(321, key, 321); create_account.options.memo_key = key; create_account.options.voting_account = GRAPHENE_PROXY_TO_SELF_ACCOUNT; auto& active_committee_members = db.get_global_properties().active_committee_members; if( active_committee_members.size() > 0 ) { set votes; votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); create_account.options.votes = flat_set(votes.begin(), votes.end()); } create_account.options.num_committee = create_account.options.votes.size(); create_account.fee = db.current_fee_schedule().calculate_fee( create_account ); return create_account; } FC_CAPTURE_AND_RETHROW() } account_create_operation database_fixture::make_account( const std::string& name, const account_object& registrar, const account_object& referrer, uint8_t referrer_percent /* = 100 */, public_key_type key /* = public_key_type() */ ) { try { account_create_operation create_account; create_account.registrar = registrar.id; create_account.referrer = referrer.id; create_account.referrer_percent = referrer_percent; create_account.name = name; create_account.owner = authority(123, key, 123); create_account.active = authority(321, key, 321); create_account.options.memo_key = key; create_account.options.voting_account = GRAPHENE_PROXY_TO_SELF_ACCOUNT; const vector& active_committee_members = db.get_global_properties().active_committee_members; if( active_committee_members.size() > 0 ) { set votes; votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); votes.insert(active_committee_members[rand() % active_committee_members.size()](db).vote_id); create_account.options.votes = flat_set(votes.begin(), votes.end()); } create_account.options.num_committee = create_account.options.votes.size(); create_account.fee = db.current_fee_schedule().calculate_fee( create_account ); return create_account; } FC_CAPTURE_AND_RETHROW((name)(referrer_percent)) } const asset_object& database_fixture::get_asset( const string& symbol )const { const auto& idx = db.get_index_type().indices().get(); const auto itr = idx.find(symbol); FC_ASSERT( itr != idx.end() ); return *itr; } const account_object& database_fixture::get_account( const string& name )const { const auto& idx = db.get_index_type().indices().get(); const auto itr = idx.find(name); FC_ASSERT( itr != idx.end() ); return *itr; } const asset_object& database_fixture::create_bitasset( const string& name, account_id_type issuer /* = GRAPHENE_WITNESS_ACCOUNT */, uint16_t market_fee_percent /* = 100 */ /* 1% */, uint16_t flags /* = charge_market_fee */ ) { try { asset_create_operation creator; creator.issuer = issuer; creator.fee = asset(); creator.symbol = name; creator.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; creator.precision = 2; creator.common_options.market_fee_percent = market_fee_percent; if( issuer == GRAPHENE_WITNESS_ACCOUNT ) flags |= witness_fed_asset; creator.common_options.issuer_permissions = flags; creator.common_options.flags = flags & ~global_settle & ~witness_fed_asset; creator.common_options.core_exchange_rate = price({asset(1,asset_id_type(1)),asset(1)}); creator.bitasset_opts = bitasset_options(); trx.operations.push_back(std::move(creator)); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW( (name)(flags) ) } const asset_object& database_fixture::create_prediction_market( const string& name, account_id_type issuer /* = GRAPHENE_WITNESS_ACCOUNT */, uint16_t market_fee_percent /* = 100 */ /* 1% */, uint16_t flags /* = charge_market_fee */ ) { try { asset_create_operation creator; creator.issuer = issuer; creator.fee = asset(); creator.symbol = name; creator.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; creator.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS; creator.common_options.market_fee_percent = market_fee_percent; creator.common_options.issuer_permissions = flags | global_settle; creator.common_options.flags = flags & ~global_settle; if( issuer == GRAPHENE_WITNESS_ACCOUNT ) creator.common_options.flags |= witness_fed_asset; creator.common_options.core_exchange_rate = price({asset(1,asset_id_type(1)),asset(1)}); creator.bitasset_opts = bitasset_options(); creator.is_prediction_market = true; trx.operations.push_back(std::move(creator)); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW( (name)(flags) ) } const asset_object& database_fixture::create_user_issued_asset( const string& name ) { asset_create_operation creator; creator.issuer = account_id_type(); creator.fee = asset(); creator.symbol = name; creator.common_options.max_supply = 0; creator.precision = 2; creator.common_options.core_exchange_rate = price({asset(1,asset_id_type(1)),asset(1)}); creator.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; creator.common_options.flags = charge_market_fee; creator.common_options.issuer_permissions = charge_market_fee; trx.operations.push_back(std::move(creator)); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); return db.get(ptx.operation_results[0].get()); } const asset_object& database_fixture::create_user_issued_asset( const string& name, const account_object& issuer, uint16_t flags ) { asset_create_operation creator; creator.issuer = issuer.id; creator.fee = asset(); creator.symbol = name; creator.common_options.max_supply = 0; creator.precision = 2; creator.common_options.core_exchange_rate = price({asset(1,asset_id_type(1)),asset(1)}); creator.common_options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY; creator.common_options.flags = flags; creator.common_options.issuer_permissions = flags; trx.operations.clear(); trx.operations.push_back(std::move(creator)); set_expiration( db, trx ); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); return db.get(ptx.operation_results[0].get()); } void database_fixture::issue_uia( const account_object& recipient, asset amount ) { BOOST_TEST_MESSAGE( "Issuing UIA" ); asset_issue_operation op; op.issuer = amount.asset_id(db).issuer; op.asset_to_issue = amount; op.issue_to_account = recipient.id; trx.operations.push_back(op); db.push_transaction( trx, ~0 ); trx.operations.clear(); } void database_fixture::issue_uia( account_id_type recipient_id, asset amount ) { issue_uia( recipient_id(db), amount ); } void database_fixture::change_fees( const flat_set< fee_parameters >& new_params, uint32_t new_scale /* = 0 */ ) { const chain_parameters& current_chain_params = db.get_global_properties().parameters; const fee_schedule& current_fees = *(current_chain_params.current_fees); flat_map< int, fee_parameters > fee_map; fee_map.reserve( current_fees.parameters.size() ); for( const fee_parameters& op_fee : current_fees.parameters ) fee_map[ op_fee.which() ] = op_fee; for( const fee_parameters& new_fee : new_params ) fee_map[ new_fee.which() ] = new_fee; fee_schedule_type new_fees; for( const std::pair< int, fee_parameters >& item : fee_map ) new_fees.parameters.insert( item.second ); if( new_scale != 0 ) new_fees.scale = new_scale; chain_parameters new_chain_params = current_chain_params; new_chain_params.current_fees = new_fees; db.modify(db.get_global_properties(), [&](global_property_object& p) { p.parameters = new_chain_params; }); } const account_object& database_fixture::create_account( const string& name, const public_key_type& key /* = public_key_type() */ ) { trx.operations.push_back(make_account(name, key)); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); auto& result = db.get(ptx.operation_results[0].get()); trx.operations.clear(); return result; } const account_object& database_fixture::create_account( const string& name, const account_object& registrar, const account_object& referrer, uint8_t referrer_percent /* = 100 */, const public_key_type& key /*= public_key_type()*/ ) { try { trx.operations.resize(1); trx.operations.back() = (make_account(name, registrar, referrer, referrer_percent, key)); trx.validate(); auto r = db.push_transaction(trx, ~0); const auto& result = db.get(r.operation_results[0].get()); trx.operations.clear(); return result; } FC_CAPTURE_AND_RETHROW( (name)(registrar)(referrer) ) } const account_object& database_fixture::create_account( const string& name, const private_key_type& key, const account_id_type& registrar_id /* = account_id_type() */, const account_id_type& referrer_id /* = account_id_type() */, uint8_t referrer_percent /* = 100 */ ) { try { trx.operations.clear(); account_create_operation account_create_op; account_create_op.registrar = registrar_id; account_create_op.name = name; account_create_op.owner = authority(1234, public_key_type(key.get_public_key()), 1234); account_create_op.active = authority(5678, public_key_type(key.get_public_key()), 5678); account_create_op.options.memo_key = key.get_public_key(); account_create_op.options.voting_account = GRAPHENE_PROXY_TO_SELF_ACCOUNT; trx.operations.push_back( account_create_op ); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); //wdump( (ptx) ); const account_object& result = db.get(ptx.operation_results[0].get()); trx.operations.clear(); return result; } FC_CAPTURE_AND_RETHROW( (name)(registrar_id)(referrer_id) ) } const committee_member_object& database_fixture::create_committee_member( const account_object& owner ) { committee_member_create_operation op; op.committee_member_account = owner.id; trx.operations.push_back(op); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); return db.get(ptx.operation_results[0].get()); } const witness_object&database_fixture::create_witness(account_id_type owner, const fc::ecc::private_key& signing_private_key) { return create_witness(owner(db), signing_private_key); } const witness_object& database_fixture::create_witness( const account_object& owner, const fc::ecc::private_key& signing_private_key ) { try { witness_create_operation op; op.witness_account = owner.id; op.block_signing_key = signing_private_key.get_public_key(); secret_hash_type::encoder enc; fc::raw::pack(enc, signing_private_key); fc::raw::pack(enc, secret_hash_type()); op.initial_secret = secret_hash_type::hash(enc.result()); trx.operations.push_back(op); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.clear(); return db.get(ptx.operation_results[0].get()); } FC_CAPTURE_AND_RETHROW() } uint64_t database_fixture::fund( const account_object& account, const asset& amount /* = asset(500000) */ ) { transfer(account_id_type()(db), account, amount); return get_balance(account, amount.asset_id(db)); } void database_fixture::sign(signed_transaction& trx, const fc::ecc::private_key& key) { trx.sign( key, db.get_chain_id() ); } digest_type database_fixture::digest( const transaction& tx ) { return tx.digest(); } const limit_order_object*database_fixture::create_sell_order(account_id_type user, const asset& amount, const asset& recv) { auto r = create_sell_order(user(db), amount, recv); verify_asset_supplies(db); return r; } const limit_order_object* database_fixture::create_sell_order( const account_object& user, const asset& amount, const asset& recv ) { //wdump((amount)(recv)); limit_order_create_operation buy_order; buy_order.seller = user.id; buy_order.amount_to_sell = amount; buy_order.min_to_receive = recv; trx.operations.push_back(buy_order); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); auto processed = db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); //wdump((processed)); return db.find( processed.operation_results[0].get() ); } asset database_fixture::cancel_limit_order( const limit_order_object& order ) { limit_order_cancel_operation cancel_order; cancel_order.fee_paying_account = order.seller; cancel_order.order = order.id; trx.operations.push_back(cancel_order); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); auto processed = db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); return processed.operation_results[0].get(); } void database_fixture::transfer( account_id_type from, account_id_type to, const asset& amount, const asset& fee /* = asset() */ ) { transfer(from(db), to(db), amount, fee); } void database_fixture::transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee /* = asset() */ ) { try { set_expiration( db, trx ); transfer_operation trans; trans.from = from.id; trans.to = to.id; trans.amount = amount; trx.operations.push_back(trans); if( fee == asset() ) { for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); } trx.validate(); db.push_transaction(trx, ~0); verify_asset_supplies(db); trx.operations.clear(); } FC_CAPTURE_AND_RETHROW( (from.id)(to.id)(amount)(fee) ) } void database_fixture::update_feed_producers( const asset_object& mia, flat_set producers ) { try { set_expiration( db, trx ); trx.operations.clear(); asset_update_feed_producers_operation op; op.asset_to_update = mia.id; op.issuer = mia.issuer; op.new_feed_producers = std::move(producers); trx.operations = {std::move(op)}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (mia)(producers) ) } void database_fixture::publish_feed( const asset_object& mia, const account_object& by, const price_feed& f ) { set_expiration( db, trx ); trx.operations.clear(); asset_publish_feed_operation op; op.publisher = by.id; op.asset_id = mia.id; op.feed = f; if( op.feed.core_exchange_rate.is_null() ) op.feed.core_exchange_rate = op.feed.settlement_price; trx.operations.emplace_back( std::move(op) ); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); } void database_fixture::force_global_settle( const asset_object& what, const price& p ) { try { set_expiration( db, trx ); trx.operations.clear(); asset_global_settle_operation sop; sop.issuer = what.issuer; sop.asset_to_settle = what.id; sop.settle_price = p; trx.operations.push_back(sop); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (what)(p) ) } operation_result database_fixture::force_settle( const account_object& who, asset what ) { try { set_expiration( db, trx ); trx.operations.clear(); asset_settle_operation sop; sop.account = who.id; sop.amount = what; trx.operations.push_back(sop); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); const operation_result& op_result = ptx.operation_results.front(); trx.operations.clear(); verify_asset_supplies(db); return op_result; } FC_CAPTURE_AND_RETHROW( (who)(what) ) } const call_order_object* database_fixture::borrow(const account_object& who, asset what, asset collateral) { try { set_expiration( db, trx ); trx.operations.clear(); call_order_update_operation update; update.funding_account = who.id; update.delta_collateral = collateral; update.delta_debt = what; trx.operations.push_back(update); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); auto& call_idx = db.get_index_type().indices().get(); auto itr = call_idx.find( boost::make_tuple(who.id, what.asset_id) ); const call_order_object* call_obj = nullptr; if( itr != call_idx.end() ) call_obj = &*itr; return call_obj; } FC_CAPTURE_AND_RETHROW( (who.name)(what)(collateral) ) } void database_fixture::cover(const account_object& who, asset what, asset collateral) { try { set_expiration( db, trx ); trx.operations.clear(); call_order_update_operation update; update.funding_account = who.id; update.delta_collateral = -collateral; update.delta_debt = -what; trx.operations.push_back(update); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW( (who.name)(what)(collateral) ) } void database_fixture::fund_fee_pool( const account_object& from, const asset_object& asset_to_fund, const share_type amount ) { asset_fund_fee_pool_operation fund; fund.from_account = from.id; fund.asset_id = asset_to_fund.id; fund.amount = amount; trx.operations.push_back( fund ); for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); db.push_transaction(trx, ~0); trx.operations.clear(); verify_asset_supplies(db); } void database_fixture::enable_fees() { db.modify(global_property_id_type()(db), [](global_property_object& gpo) { gpo.parameters.current_fees = fee_schedule::get_default(); }); } void database_fixture::upgrade_to_lifetime_member(account_id_type account) { upgrade_to_lifetime_member(account(db)); } void database_fixture::upgrade_to_lifetime_member( const account_object& account ) { try { account_upgrade_operation op; op.account_to_upgrade = account.get_id(); op.upgrade_to_lifetime_member = true; op.fee = db.get_global_properties().parameters.current_fees->calculate_fee(op); trx.operations = {op}; db.push_transaction(trx, ~0); FC_ASSERT( op.account_to_upgrade(db).is_lifetime_member() ); trx.clear(); verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW((account)) } void database_fixture::upgrade_to_annual_member(account_id_type account) { upgrade_to_annual_member(account(db)); } void database_fixture::upgrade_to_annual_member(const account_object& account) { try { account_upgrade_operation op; op.account_to_upgrade = account.get_id(); op.fee = db.get_global_properties().parameters.current_fees->calculate_fee(op); trx.operations = {op}; db.push_transaction(trx, ~0); FC_ASSERT( op.account_to_upgrade(db).is_member(db.head_block_time()) ); trx.clear(); verify_asset_supplies(db); } FC_CAPTURE_AND_RETHROW((account)) } void database_fixture::print_market( const string& syma, const string& symb )const { const auto& limit_idx = db.get_index_type(); const auto& price_idx = limit_idx.indices().get(); cerr << std::fixed; cerr.precision(5); cerr << std::setw(10) << std::left << "NAME" << " "; cerr << std::setw(16) << std::right << "FOR SALE" << " "; cerr << std::setw(16) << std::right << "FOR WHAT" << " "; cerr << std::setw(10) << std::right << "PRICE (S/W)" << " "; cerr << std::setw(10) << std::right << "1/PRICE (W/S)" << "\n"; cerr << string(70, '=') << std::endl; auto cur = price_idx.begin(); while( cur != price_idx.end() ) { cerr << std::setw( 10 ) << std::left << cur->seller(db).name << " "; cerr << std::setw( 10 ) << std::right << cur->for_sale.value << " "; cerr << std::setw( 5 ) << std::left << cur->amount_for_sale().asset_id(db).symbol << " "; cerr << std::setw( 10 ) << std::right << cur->amount_to_receive().amount.value << " "; cerr << std::setw( 5 ) << std::left << cur->amount_to_receive().asset_id(db).symbol << " "; cerr << std::setw( 10 ) << std::right << cur->sell_price.to_real() << " "; cerr << std::setw( 10 ) << std::right << (~cur->sell_price).to_real() << " "; cerr << "\n"; ++cur; } } string database_fixture::pretty( const asset& a )const { std::stringstream ss; ss << a.amount.value << " "; ss << a.asset_id(db).symbol; return ss.str(); } void database_fixture::print_limit_order( const limit_order_object& cur )const { std::cout << std::setw(10) << cur.seller(db).name << " "; std::cout << std::setw(10) << "LIMIT" << " "; std::cout << std::setw(16) << pretty( cur.amount_for_sale() ) << " "; std::cout << std::setw(16) << pretty( cur.amount_to_receive() ) << " "; std::cout << std::setw(16) << cur.sell_price.to_real() << " "; } void database_fixture::print_call_orders()const { cout << std::fixed; cout.precision(5); cout << std::setw(10) << std::left << "NAME" << " "; cout << std::setw(10) << std::right << "TYPE" << " "; cout << std::setw(16) << std::right << "DEBT" << " "; cout << std::setw(16) << std::right << "COLLAT" << " "; cout << std::setw(16) << std::right << "CALL PRICE(D/C)" << " "; cout << std::setw(16) << std::right << "~CALL PRICE(C/D)" << " "; cout << std::setw(16) << std::right << "SWAN(D/C)" << " "; cout << std::setw(16) << std::right << "SWAN(C/D)" << "\n"; cout << string(70, '='); for( const call_order_object& o : db.get_index_type().indices() ) { std::cout << "\n"; cout << std::setw( 10 ) << std::left << o.borrower(db).name << " "; cout << std::setw( 16 ) << std::right << pretty( o.get_debt() ) << " "; cout << std::setw( 16 ) << std::right << pretty( o.get_collateral() ) << " "; cout << std::setw( 16 ) << std::right << o.call_price.to_real() << " "; cout << std::setw( 16 ) << std::right << (~o.call_price).to_real() << " "; cout << std::setw( 16 ) << std::right << (o.get_debt()/o.get_collateral()).to_real() << " "; cout << std::setw( 16 ) << std::right << (~(o.get_debt()/o.get_collateral())).to_real() << " "; } std::cout << "\n"; } void database_fixture::print_joint_market( const string& syma, const string& symb )const { cout << std::fixed; cout.precision(5); cout << std::setw(10) << std::left << "NAME" << " "; cout << std::setw(10) << std::right << "TYPE" << " "; cout << std::setw(16) << std::right << "FOR SALE" << " "; cout << std::setw(16) << std::right << "FOR WHAT" << " "; cout << std::setw(16) << std::right << "PRICE (S/W)" << "\n"; cout << string(70, '='); const auto& limit_idx = db.get_index_type(); const auto& limit_price_idx = limit_idx.indices().get(); auto limit_itr = limit_price_idx.begin(); while( limit_itr != limit_price_idx.end() ) { std::cout << std::endl; print_limit_order( *limit_itr ); ++limit_itr; } } int64_t database_fixture::get_balance( account_id_type account, asset_id_type a )const { return db.get_balance(account, a).amount.value; } int64_t database_fixture::get_balance( const account_object& account, const asset_object& a )const { return db.get_balance(account.get_id(), a.get_id()).amount.value; } int64_t database_fixture::get_dividend_pending_payout_balance(asset_id_type dividend_holder_asset_type, account_id_type dividend_holder_account_id, asset_id_type dividend_payout_asset_type) const { const pending_dividend_payout_balance_for_holder_object_index& pending_payout_balance_index = db.get_index_type(); auto pending_payout_iter = pending_payout_balance_index.indices().get().find(boost::make_tuple(dividend_holder_asset_type, dividend_payout_asset_type, dividend_holder_account_id)); if (pending_payout_iter == pending_payout_balance_index.indices().get().end()) return 0; else return pending_payout_iter->pending_balance.value; } vector< operation_history_object > database_fixture::get_operation_history( account_id_type account_id )const { vector< operation_history_object > result; const auto& stats = account_id(db).statistics(db); if(stats.most_recent_op == account_transaction_history_id_type()) return result; const account_transaction_history_object* node = &stats.most_recent_op(db); while( true ) { result.push_back( node->operation_id(db) ); if(node->next == account_transaction_history_id_type()) break; node = db.find(node->next); } return result; } void database_fixture::process_operation_by_witnesses(operation op) { const flat_set& active_witnesses = db.get_global_properties().active_witnesses; proposal_create_operation proposal_op; proposal_op.fee_paying_account = (*active_witnesses.begin())(db).witness_account; proposal_op.proposed_ops.emplace_back(op); proposal_op.expiration_time = db.head_block_time() + fc::days(1); signed_transaction tx; tx.operations.push_back(proposal_op); set_expiration(db, tx); sign(tx, init_account_priv_key); processed_transaction processed_tx = db.push_transaction(tx); proposal_id_type proposal_id = processed_tx.operation_results[0].get(); for (const witness_id_type& witness_id : active_witnesses) { const witness_object& witness = witness_id(db); const account_object& witness_account = witness.witness_account(db); proposal_update_operation pup; pup.proposal = proposal_id; pup.fee_paying_account = witness_account.id; pup.active_approvals_to_add.insert(witness_account.id); signed_transaction tx; tx.operations.push_back( pup ); set_expiration( db, tx ); sign(tx, init_account_priv_key); db.push_transaction(tx, ~0); const auto& proposal_idx = db.get_index_type().indices().get(); if (proposal_idx.find(proposal_id) == proposal_idx.end()) break; } } void database_fixture::process_operation_by_committee(operation op) { const vector& active_committee_members = db.get_global_properties().active_committee_members; proposal_create_operation proposal_op; proposal_op.fee_paying_account = (*active_committee_members.begin())(db).committee_member_account; proposal_op.proposed_ops.emplace_back(op); proposal_op.expiration_time = db.head_block_time() + fc::days(1); signed_transaction tx; tx.operations.push_back(proposal_op); set_expiration(db, tx); sign(tx, init_account_priv_key); processed_transaction processed_tx = db.push_transaction(tx); proposal_id_type proposal_id = processed_tx.operation_results[0].get(); for (const committee_member_id_type& committee_member_id : active_committee_members) { const committee_member_object& committee_member = committee_member_id(db); const account_object& committee_member_account = committee_member.committee_member_account(db); proposal_update_operation pup; pup.proposal = proposal_id; pup.fee_paying_account = committee_member_account.id; pup.active_approvals_to_add.insert(committee_member_account.id); signed_transaction tx; tx.operations.push_back( pup ); set_expiration( db, tx ); sign(tx, init_account_priv_key); db.push_transaction(tx, ~0); const auto& proposal_idx = db.get_index_type().indices().get(); if (proposal_idx.find(proposal_id) == proposal_idx.end()) break; } } void database_fixture::force_operation_by_witnesses(operation op) { const chain_parameters& params = db.get_global_properties().parameters; signed_transaction trx; trx.operations = {op}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); trx.set_expiration(db.head_block_time() + fc::seconds( params.block_interval * (params.maintenance_skip_slots + 1) * 3)); sign(trx, init_account_priv_key); PUSH_TX(db, trx); } void database_fixture::set_is_proposed_trx(operation op) { const flat_set& active_witnesses = db.get_global_properties().active_witnesses; proposal_create_operation proposal_op; proposal_op.fee_paying_account = (*active_witnesses.begin())(db).witness_account; proposal_op.proposed_ops.emplace_back(op); proposal_op.expiration_time = db.head_block_time() + fc::days(1); signed_transaction tx; tx.operations.push_back(proposal_op); set_expiration(db, tx); sign(tx, init_account_priv_key); processed_transaction processed_tx = db.push_transaction(tx); proposal_id_type proposal_id = processed_tx.operation_results[0].get(); for (const witness_id_type& witness_id : active_witnesses) { const witness_object& witness = witness_id(db); const account_object& witness_account = witness.witness_account(db); proposal_update_operation pup; pup.proposal = proposal_id; pup.fee_paying_account = witness_account.id; pup.active_approvals_to_add.insert(witness_account.id); db.push_proposal(pup.proposal(db)); break; } } proposal_id_type database_fixture::propose_operation(operation op) { const flat_set& active_witnesses = db.get_global_properties().active_witnesses; proposal_create_operation proposal_op; proposal_op.fee_paying_account = (*active_witnesses.begin())(db).witness_account; proposal_op.proposed_ops.emplace_back(op); proposal_op.expiration_time = db.head_block_time() + fc::days(1); signed_transaction tx; tx.operations.push_back(proposal_op); set_expiration(db, tx); sign(tx, init_account_priv_key); processed_transaction processed_tx = db.push_transaction(tx); proposal_id_type proposal_id = processed_tx.operation_results[0].get(); return proposal_id; } void database_fixture::process_proposal_by_witnesses(const std::vector& witnesses, proposal_id_type proposal_id, bool remove) { const auto& proposal_idx = db.get_index_type().indices().get(); for (const witness_id_type& witness_id : witnesses) { if (proposal_idx.find(proposal_id) == proposal_idx.end()) break; const witness_object& witness = witness_id(db); const account_object& witness_account = witness.witness_account(db); proposal_update_operation pup; pup.proposal = proposal_id; pup.fee_paying_account = witness_account.id; if (remove) pup.active_approvals_to_remove.insert(witness_account.id); else pup.active_approvals_to_add.insert(witness_account.id); signed_transaction tx; tx.operations.push_back( pup ); set_expiration( db, tx ); sign(tx, init_account_priv_key); db.push_transaction(tx, ~0); } } const sport_object& database_fixture::create_sport(internationalized_string_type name) { try { sport_create_operation sport_create_op; sport_create_op.name = name; process_operation_by_witnesses(sport_create_op); const auto& sport_index = db.get_index_type().indices().get(); return *sport_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (name) ) } void database_fixture::update_sport(sport_id_type sport_id, internationalized_string_type name) { try { sport_update_operation sport_update_op; sport_update_op.sport_id = sport_id; sport_update_op.new_name = name; process_operation_by_witnesses(sport_update_op); } FC_CAPTURE_AND_RETHROW( (sport_id)(name) ) } void database_fixture::delete_sport(sport_id_type sport_id) { try { sport_delete_operation sport_delete_op; sport_delete_op.sport_id = sport_id; process_operation_by_witnesses(sport_delete_op); } FC_CAPTURE_AND_RETHROW( (sport_id) ) } const event_group_object& database_fixture::create_event_group(internationalized_string_type name, sport_id_type sport_id) { try { event_group_create_operation event_group_create_op; event_group_create_op.name = name; event_group_create_op.sport_id = sport_id; process_operation_by_witnesses(event_group_create_op); const auto& event_group_index = db.get_index_type().indices().get(); return *event_group_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (name) ) } void database_fixture::update_event_group(event_group_id_type event_group_id, fc::optional sport_id, fc::optional name) { try { event_group_update_operation event_group_update_op; event_group_update_op.new_name = name; event_group_update_op.new_sport_id = sport_id; event_group_update_op.event_group_id = event_group_id; process_operation_by_witnesses(event_group_update_op); } FC_CAPTURE_AND_RETHROW( (name) ) } void database_fixture::delete_event_group(event_group_id_type event_group_id) { try { event_group_delete_operation event_group_delete_op; event_group_delete_op.event_group_id = event_group_id; process_operation_by_witnesses(event_group_delete_op); } FC_CAPTURE_AND_RETHROW( (event_group_id) ) } void database_fixture::try_update_event_group(event_group_id_type event_group_id, fc::optional sport_id, fc::optional name, bool dont_set_is_proposed_trx /* = false */) { event_group_update_operation event_group_update_op; event_group_update_op.new_name = name; event_group_update_op.new_sport_id = sport_id; event_group_update_op.event_group_id = event_group_id; if (!dont_set_is_proposed_trx) set_is_proposed_trx(event_group_update_op); const chain_parameters& params = db.get_global_properties().parameters; signed_transaction trx; trx.operations = {event_group_update_op}; for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); trx.validate(); trx.set_expiration(db.head_block_time() + fc::seconds( params.block_interval * (params.maintenance_skip_slots + 1) * 3)); sign(trx, init_account_priv_key); PUSH_TX(db, trx); } const event_object& database_fixture::create_event(internationalized_string_type name, internationalized_string_type season, event_group_id_type event_group_id) { try { event_create_operation event_create_op; event_create_op.name = name; event_create_op.season = season; event_create_op.event_group_id = event_group_id; process_operation_by_witnesses(event_create_op); const auto& event_index = db.get_index_type().indices().get(); return *event_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (event_group_id) ) } void database_fixture::update_event_impl(event_id_type event_id, fc::optional event_group_id, fc::optional name, fc::optional season, fc::optional status, bool force) { try { event_update_operation event_update_op; event_update_op.event_id = event_id; event_update_op.new_event_group_id = event_group_id; event_update_op.new_name = name; event_update_op.new_season = season; event_update_op.new_status = status; if (force) force_operation_by_witnesses(event_update_op); else process_operation_by_witnesses(event_update_op); } FC_CAPTURE_AND_RETHROW( (event_id) ) } const betting_market_rules_object& database_fixture::create_betting_market_rules(internationalized_string_type name, internationalized_string_type description) { try { betting_market_rules_create_operation betting_market_rules_create_op; betting_market_rules_create_op.name = name; betting_market_rules_create_op.description = description; process_operation_by_witnesses(betting_market_rules_create_op); const auto& betting_market_rules_index = db.get_index_type().indices().get(); return *betting_market_rules_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (name) ) } void database_fixture::update_betting_market_rules(betting_market_rules_id_type rules_id, fc::optional name, fc::optional description) { try { betting_market_rules_update_operation betting_market_rules_update_op; betting_market_rules_update_op.betting_market_rules_id = rules_id; betting_market_rules_update_op.new_name = name; betting_market_rules_update_op.new_description = description; process_operation_by_witnesses(betting_market_rules_update_op); } FC_CAPTURE_AND_RETHROW( (name)(description) ) } const betting_market_group_object& database_fixture::create_betting_market_group(internationalized_string_type description, event_id_type event_id, betting_market_rules_id_type rules_id, asset_id_type asset_id, bool never_in_play, uint32_t delay_before_settling) { try { betting_market_group_create_operation betting_market_group_create_op; betting_market_group_create_op.description = description; betting_market_group_create_op.event_id = event_id; betting_market_group_create_op.rules_id = rules_id; betting_market_group_create_op.asset_id = asset_id; betting_market_group_create_op.never_in_play = never_in_play; betting_market_group_create_op.delay_before_settling = delay_before_settling; process_operation_by_witnesses(betting_market_group_create_op); const auto& betting_market_group_index = db.get_index_type().indices().get(); return *betting_market_group_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (event_id) ) } void database_fixture::update_betting_market_group_impl(betting_market_group_id_type betting_market_group_id, fc::optional description, fc::optional rules_id, fc::optional status, bool force) { try { betting_market_group_update_operation betting_market_group_update_op; betting_market_group_update_op.betting_market_group_id = betting_market_group_id; betting_market_group_update_op.new_description = description; betting_market_group_update_op.new_rules_id = rules_id; betting_market_group_update_op.status = status; if (force) force_operation_by_witnesses(betting_market_group_update_op); else process_operation_by_witnesses(betting_market_group_update_op); } FC_CAPTURE_AND_RETHROW( (betting_market_group_id)(description)(rules_id)(status)) } const betting_market_object& database_fixture::create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition) { try { betting_market_create_operation betting_market_create_op; betting_market_create_op.group_id = group_id; betting_market_create_op.payout_condition = payout_condition; process_operation_by_witnesses(betting_market_create_op); const auto& betting_market_index = db.get_index_type().indices().get(); return *betting_market_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (payout_condition) ) } void database_fixture::update_betting_market(betting_market_id_type betting_market_id, fc::optional group_id, /*fc::optional description,*/ fc::optional payout_condition) { try { betting_market_update_operation betting_market_update_op; betting_market_update_op.betting_market_id = betting_market_id; betting_market_update_op.new_group_id = group_id; //betting_market_update_op.new_description = description; betting_market_update_op.new_payout_condition = payout_condition; process_operation_by_witnesses(betting_market_update_op); } FC_CAPTURE_AND_RETHROW( (betting_market_id) (group_id) (payout_condition) ) } bet_id_type database_fixture::place_bet(account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, asset amount_to_bet, bet_multiplier_type backer_multiplier) { try { bet_place_operation bet_place_op; bet_place_op.bettor_id = bettor_id; bet_place_op.betting_market_id = betting_market_id; bet_place_op.amount_to_bet = amount_to_bet; bet_place_op.backer_multiplier = backer_multiplier; bet_place_op.back_or_lay = back_or_lay; trx.operations.push_back(bet_place_op); trx.validate(); processed_transaction ptx = db.push_transaction(trx, ~0); trx.operations.clear(); BOOST_CHECK_MESSAGE(ptx.operation_results.size() == 1, "Place Bet Transaction should have had exactly one operation result"); return ptx.operation_results.front().get().as(); } FC_CAPTURE_AND_RETHROW( (bettor_id)(back_or_lay)(amount_to_bet) ) } void database_fixture::resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, std::map resolutions) { try { betting_market_group_resolve_operation betting_market_group_resolve_op; betting_market_group_resolve_op.betting_market_group_id = betting_market_group_id; betting_market_group_resolve_op.resolutions = resolutions; process_operation_by_witnesses(betting_market_group_resolve_op); } FC_CAPTURE_AND_RETHROW( (betting_market_group_id)(resolutions) ) } void database_fixture::cancel_unmatched_bets(betting_market_group_id_type betting_market_group_id) { try { betting_market_group_cancel_unmatched_bets_operation betting_market_group_cancel_unmatched_bets_op; betting_market_group_cancel_unmatched_bets_op.betting_market_group_id = betting_market_group_id; process_operation_by_witnesses(betting_market_group_cancel_unmatched_bets_op); } FC_CAPTURE_AND_RETHROW( (betting_market_group_id) ) } namespace test { void set_expiration( const database& db, transaction& tx ) { const chain_parameters& params = db.get_global_properties().parameters; tx.set_reference_block(db.head_block_id()); tx.set_expiration( db.head_block_time() + fc::seconds( params.block_interval * (params.maintenance_skip_slots + 1) * 3 ) ); } bool _push_block( database& db, const signed_block& b, uint32_t skip_flags /* = 0 */ ) { return db.push_block( b, skip_flags); } processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags /* = 0 */ ) { try { auto pt = db.push_transaction( tx, skip_flags ); database_fixture::verify_asset_supplies(db); return pt; } FC_CAPTURE_AND_RETHROW((tx)) } } // graphene::chain::test } } // graphene::chain