Clean up some non-determisitic behavior, maybe fix #485

1. Replace ordered_non_unique indexes with composite keys / ordered_unique, using object_id as tiebreaker.
2. Make some casts more explicit.

This commit was rebased by theoreticalbts due to conflicts with the patches for #466 #562 including bugfixes

- Fix flipped comparison operator
- Implement operator> and operator!= for object_id_type
This commit is contained in:
Daniel Larimer 2015-12-17 11:32:22 -05:00 committed by theoreticalbts
parent 2eaa1b553b
commit 146c0c4d8e
14 changed files with 134 additions and 67 deletions

View file

@ -960,8 +960,8 @@ vector<call_order_object> database_api_impl::get_margin_positions( const account
{
const auto& idx = _db.get_index_type<call_order_index>();
const auto& aidx = idx.indices().get<by_account>();
auto start = aidx.lower_bound( boost::make_tuple( id, 0 ) );
auto end = aidx.lower_bound( boost::make_tuple( id+1, 0 ) );
auto start = aidx.lower_bound( boost::make_tuple( id, asset_id_type(0) ) );
auto end = aidx.lower_bound( boost::make_tuple( id+1, asset_id_type(0) ) );
vector<call_order_object> result;
while( start != end )
{

View file

@ -316,7 +316,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = id;
a.registrar = a.lifetime_referrer = a.referrer = account_id_type(id);
a.membership_expiration_date = time_point_sec::maximum();
a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
@ -339,9 +339,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.options.issuer_permissions = 0;
a.issuer = GRAPHENE_NULL_ACCOUNT;
a.options.core_exchange_rate.base.amount = 1;
a.options.core_exchange_rate.base.asset_id = 0;
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
a.options.core_exchange_rate.quote.amount = 1;
a.options.core_exchange_rate.quote.asset_id = 0;
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
a.dynamic_asset_data_id = dyn_asset.id;
});
assert( asset_id_type(core_asset.id) == asset().asset_id );
@ -364,9 +364,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
a.options.issuer_permissions = 0;
a.issuer = GRAPHENE_NULL_ACCOUNT;
a.options.core_exchange_rate.base.amount = 1;
a.options.core_exchange_rate.base.asset_id = 0;
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
a.options.core_exchange_rate.quote.amount = 1;
a.options.core_exchange_rate.quote.asset_id = 0;
a.options.core_exchange_rate.quote.asset_id = asset_id_type(0);
a.dynamic_asset_data_id = dyn_asset.id;
});
FC_ASSERT( asset_obj.get_id() == asset_id_type(id) );
@ -491,7 +491,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
});
total_supplies[ 0 ] += collateral_rec.collateral;
total_supplies[ asset_id_type(0) ] += collateral_rec.collateral;
total_debts[ new_asset_id ] += collateral_rec.debt;
++collateral_holder_number;
}
@ -555,13 +555,13 @@ void database::init_genesis(const genesis_state_type& genesis_state)
total_supplies[ asset_id ] += vest.amount;
}
if( total_supplies[ 0 ] > 0 )
if( total_supplies[ asset_id_type(0) ] > 0 )
{
adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{}));
}
else
{
total_supplies[ 0 ] = GRAPHENE_MAX_SHARE_SUPPLY;
total_supplies[ asset_id_type(0) ] = GRAPHENE_MAX_SHARE_SUPPLY;
}
const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>();
@ -645,7 +645,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
modify(get_global_properties(), [&](global_property_object& p) {
for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i )
{
p.active_witnesses.insert(i);
p.active_witnesses.insert(witness_id_type(i));
}
});

View file

@ -233,7 +233,12 @@ namespace graphene { namespace chain {
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
ordered_non_unique< tag<by_type>, const_mem_fun<asset_object, bool, &asset_object::is_market_issued> >
ordered_unique< tag<by_type>,
composite_key< asset_object,
const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
member< object, object_id_type, &object::id >
>
>
>
> asset_object_multi_index_type;
typedef generic_index<asset_object, asset_object_multi_index_type> asset_index;

View file

@ -72,9 +72,13 @@ struct by_account;
typedef multi_index_container<
limit_order_object,
indexed_by<
ordered_unique< tag<by_id>,
member< object, object_id_type, &object::id > >,
ordered_non_unique< tag<by_expiration>, member< limit_order_object, time_point_sec, &limit_order_object::expiration> >,
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_expiration>,
composite_key< limit_order_object,
member< limit_order_object, time_point_sec, &limit_order_object::expiration>,
member< object, object_id_type, &object::id>
>
>,
ordered_unique< tag<by_price>,
composite_key< limit_order_object,
member< limit_order_object, price, &limit_order_object::sell_price>,
@ -82,7 +86,12 @@ typedef multi_index_container<
>,
composite_key_compare< std::greater<price>, std::less<object_id_type> >
>,
ordered_non_unique< tag<by_account>, member<limit_order_object, account_id_type, &limit_order_object::seller>>
ordered_unique< tag<by_account>,
composite_key< limit_order_object,
member<limit_order_object, account_id_type, &limit_order_object::seller>,
member<object, object_id_type, &object::id>
>
>
>
> limit_order_multi_index_type;
@ -168,19 +177,22 @@ typedef multi_index_container<
force_settlement_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_non_unique< tag<by_account>,
member<force_settlement_object, account_id_type, &force_settlement_object::owner>
ordered_unique< tag<by_account>,
composite_key< force_settlement_object,
member<force_settlement_object, account_id_type, &force_settlement_object::owner>,
member< object, object_id_type, &object::id >
>
>,
ordered_non_unique< tag<by_expiration>,
ordered_unique< tag<by_expiration>,
composite_key< force_settlement_object,
const_mem_fun<force_settlement_object, asset_id_type, &force_settlement_object::settlement_asset_id>,
member<force_settlement_object, time_point_sec, &force_settlement_object::settlement_date>
member<force_settlement_object, time_point_sec, &force_settlement_object::settlement_date>,
member< object, object_id_type, &object::id >
>
>
>
> force_settlement_object_multi_index_type;
typedef generic_index<call_order_object, call_order_multi_index_type> call_order_index;
typedef generic_index<force_settlement_object, force_settlement_object_multi_index_type> force_settlement_index;

View file

@ -24,6 +24,7 @@
#pragma once
#include <graphene/chain/protocol/authority.hpp>
#include <graphene/db/generic_index.hpp>
#include <boost/multi_index/composite_key.hpp>
namespace graphene { namespace chain {
@ -78,9 +79,24 @@ namespace graphene { namespace chain {
withdraw_permission_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_non_unique< tag<by_from>, member<withdraw_permission_object, account_id_type, &withdraw_permission_object::withdraw_from_account> >,
ordered_non_unique< tag<by_authorized>, member<withdraw_permission_object, account_id_type, &withdraw_permission_object::authorized_account> >,
ordered_non_unique< tag<by_expiration>, member<withdraw_permission_object, time_point_sec, &withdraw_permission_object::expiration> >
ordered_unique< tag<by_from>,
composite_key< withdraw_permission_object,
member<withdraw_permission_object, account_id_type, &withdraw_permission_object::withdraw_from_account>,
member< object, object_id_type, &object::id >
>
>,
ordered_unique< tag<by_authorized>,
composite_key< withdraw_permission_object,
member<withdraw_permission_object, account_id_type, &withdraw_permission_object::authorized_account>,
member< object, object_id_type, &object::id >
>
>,
ordered_unique< tag<by_expiration>,
composite_key< withdraw_permission_object,
member<withdraw_permission_object, time_point_sec, &withdraw_permission_object::expiration>,
member< object, object_id_type, &object::id >
>
>
>
> withdraw_permission_object_multi_index_type;

View file

@ -158,7 +158,7 @@ void asset_issue_operation::validate()const
FC_ASSERT( fee.amount >= 0 );
FC_ASSERT( asset_to_issue.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
FC_ASSERT( asset_to_issue.amount.value > 0 );
FC_ASSERT( asset_to_issue.asset_id != 0 );
FC_ASSERT( asset_to_issue.asset_id != asset_id_type(0) );
}
void asset_fund_fee_pool_operation::validate() const

View file

@ -130,7 +130,7 @@ namespace graphene { namespace chain {
scaled /= GRAPHENE_100_PERCENT;
FC_ASSERT( scaled <= GRAPHENE_MAX_SHARE_SUPPLY );
//idump( (base_value)(scaled)(core_exchange_rate) );
auto result = asset( scaled.to_uint64(), 0 ) * core_exchange_rate;
auto result = asset( scaled.to_uint64(), asset_id_type(0) ) * core_exchange_rate;
//FC_ASSERT( result * core_exchange_rate >= asset( scaled.to_uint64()) );
while( result * core_exchange_rate < asset( scaled.to_uint64()) )

View file

@ -51,12 +51,18 @@ namespace graphene { namespace db {
uint16_t space_type()const { return number >> 48; }
uint64_t instance()const { return number & GRAPHENE_DB_MAX_INSTANCE_ID; }
bool is_null()const { return number == 0; }
operator uint64_t()const { return number; }
explicit operator uint64_t()const { return number; }
friend bool operator == ( const object_id_type& a, const object_id_type& b )
{
return a.number == b.number;
}
friend bool operator != ( const object_id_type& a, const object_id_type& b )
{
return a.number != b.number;
}
object_id_type& operator++(int) { ++number; return *this; }
object_id_type& operator++() { ++number; return *this; }
@ -68,11 +74,16 @@ namespace graphene { namespace db {
}
friend size_t hash_value( object_id_type v ) { return std::hash<uint64_t>()(v.number); }
friend bool operator < ( const object_id_type& a, const object_id_type& b )
friend bool operator< ( const object_id_type& a, const object_id_type& b )
{
return a.number < b.number;
}
friend bool operator> ( const object_id_type& a, const object_id_type& b )
{
return a.number > b.number;
}
template< typename T >
bool is() const
{
@ -106,7 +117,7 @@ namespace graphene { namespace db {
object_id(){}
object_id( unsigned_int i ):instance(i){}
object_id( uint64_t i ):instance(i)
explicit object_id( uint64_t i ):instance(i)
{
FC_ASSERT( (i >> 48) == 0 );
}
@ -118,11 +129,25 @@ namespace graphene { namespace db {
friend object_id operator+(const object_id a, int delta ) { return object_id( uint64_t(a.instance.value+delta) ); }
operator object_id_type()const { return object_id_type( SpaceID, TypeID, instance.value ); }
operator uint64_t()const { return object_id_type( *this ).number; }
explicit operator uint64_t()const { return object_id_type( *this ).number; }
template<typename DB>
const T& operator()(const DB& db)const { return db.get(*this); }
friend bool operator != ( const object_id& a, const object_id& b )
{
return a.instance != b.instance;
}
friend bool operator != ( const object_id_type& a, const object_id& b )
{
return a != object_id_type(b);
}
friend bool operator != ( const object_id& a, const object_id_type& b )
{
return object_id_type(a) != b;
}
friend bool operator == ( const object_id& a, const object_id& b )
{
return a.instance == b.instance;
@ -139,6 +164,10 @@ namespace graphene { namespace db {
{
return a.instance.value < b.instance.value;
}
friend bool operator > ( const object_id& a, const object_id& b )
{
return a.instance.value > b.instance.value;
}
friend size_t hash_value( object_id v ) { return std::hash<uint64_t>()(v.instance.value); }
unsigned_int instance;

View file

@ -2324,7 +2324,7 @@ public:
asset_options opts;
opts.flags &= ~(white_list | disable_force_settle | global_settle);
opts.issuer_permissions = opts.flags;
opts.core_exchange_rate = price(asset(1), asset(1,1));
opts.core_exchange_rate = price(asset(1), asset(1,asset_id_type(1)));
create_asset(get_account(creator).name, symbol, 2, opts, {}, true);
}
@ -2333,7 +2333,7 @@ public:
asset_options opts;
opts.flags &= ~white_list;
opts.issuer_permissions = opts.flags;
opts.core_exchange_rate = price(asset(1), asset(1,1));
opts.core_exchange_rate = price(asset(1), asset(1,asset_id_type(1)));
bitasset_options bopts;
create_asset(get_account(creator).name, symbol, 2, opts, bopts, true);
}
@ -3644,8 +3644,8 @@ vector<asset> wallet_api::get_blind_balances( string key_or_label )
auto pub_key = get_public_key( key_or_label );
auto& to_asset_used_idx = my->_wallet.blind_receipts.get<by_to_asset_used>();
auto start = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,0,false) );
auto end = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,uint32_t(0xffffffff),true) );
auto start = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,asset_id_type(0),false) );
auto end = to_asset_used_idx.lower_bound( std::make_tuple(pub_key,asset_id_type(uint32_t(0xffffffff)),true) );
while( start != end )
{
if( !start->used )

View file

@ -439,7 +439,7 @@ const asset_object& database_fixture::create_bitasset(
flags |= witness_fed_asset;
creator.common_options.issuer_permissions = flags;
creator.common_options.flags = flags & ~global_settle;
creator.common_options.core_exchange_rate = price({asset(1,1),asset(1)});
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();
@ -466,7 +466,7 @@ const asset_object& database_fixture::create_prediction_market(
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,1),asset(1)});
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));
@ -484,7 +484,7 @@ const asset_object& database_fixture::create_user_issued_asset( const string& na
creator.symbol = name;
creator.common_options.max_supply = 0;
creator.precision = 2;
creator.common_options.core_exchange_rate = price({asset(1,1),asset(1)});
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;
@ -503,7 +503,7 @@ const asset_object& database_fixture::create_user_issued_asset( const string& na
creator.symbol = name;
creator.common_options.max_supply = 0;
creator.precision = 2;
creator.common_options.core_exchange_rate = price({asset(1,1),asset(1)});
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;

View file

@ -138,28 +138,33 @@ BOOST_AUTO_TEST_CASE( valid_symbol_test )
BOOST_AUTO_TEST_CASE( price_test )
{
BOOST_CHECK( price::max(0,1) > price::min(0,1) );
BOOST_CHECK( price::max(1,0) > price::min(1,0) );
BOOST_CHECK( price::max(0,1) >= price::min(0,1) );
BOOST_CHECK( price::max(1,0) >= price::min(1,0) );
BOOST_CHECK( price::max(0,1) >= price::max(0,1) );
BOOST_CHECK( price::max(1,0) >= price::max(1,0) );
BOOST_CHECK( price::min(0,1) < price::max(0,1) );
BOOST_CHECK( price::min(1,0) < price::max(1,0) );
BOOST_CHECK( price::min(0,1) <= price::max(0,1) );
BOOST_CHECK( price::min(1,0) <= price::max(1,0) );
BOOST_CHECK( price::min(0,1) <= price::min(0,1) );
BOOST_CHECK( price::min(1,0) <= price::min(1,0) );
BOOST_CHECK( price::min(1,0) != price::max(1,0) );
BOOST_CHECK( ~price::max(0,1) != price::min(0,1) );
BOOST_CHECK( ~price::min(0,1) != price::max(0,1) );
BOOST_CHECK( ~price::max(0,1) == price::min(1,0) );
BOOST_CHECK( ~price::min(0,1) == price::max(1,0) );
BOOST_CHECK( ~price::max(0,1) < ~price::min(0,1) );
BOOST_CHECK( ~price::max(0,1) <= ~price::min(0,1) );
price a(asset(1), asset(2,1));
price b(asset(2), asset(2,1));
price c(asset(1), asset(2,1));
auto price_max = []( uint32_t a, uint32_t b )
{ return price::max( asset_id_type(a), asset_id_type(b) ); };
auto price_min = []( uint32_t a, uint32_t b )
{ return price::min( asset_id_type(a), asset_id_type(b) ); };
BOOST_CHECK( price_max(0,1) > price_min(0,1) );
BOOST_CHECK( price_max(1,0) > price_min(1,0) );
BOOST_CHECK( price_max(0,1) >= price_min(0,1) );
BOOST_CHECK( price_max(1,0) >= price_min(1,0) );
BOOST_CHECK( price_max(0,1) >= price_max(0,1) );
BOOST_CHECK( price_max(1,0) >= price_max(1,0) );
BOOST_CHECK( price_min(0,1) < price_max(0,1) );
BOOST_CHECK( price_min(1,0) < price_max(1,0) );
BOOST_CHECK( price_min(0,1) <= price_max(0,1) );
BOOST_CHECK( price_min(1,0) <= price_max(1,0) );
BOOST_CHECK( price_min(0,1) <= price_min(0,1) );
BOOST_CHECK( price_min(1,0) <= price_min(1,0) );
BOOST_CHECK( price_min(1,0) != price_max(1,0) );
BOOST_CHECK( ~price_max(0,1) != price_min(0,1) );
BOOST_CHECK( ~price_min(0,1) != price_max(0,1) );
BOOST_CHECK( ~price_max(0,1) == price_min(1,0) );
BOOST_CHECK( ~price_min(0,1) == price_max(1,0) );
BOOST_CHECK( ~price_max(0,1) < ~price_min(0,1) );
BOOST_CHECK( ~price_max(0,1) <= ~price_min(0,1) );
price a(asset(1), asset(2,asset_id_type(1)));
price b(asset(2), asset(2,asset_id_type(1)));
price c(asset(1), asset(2,asset_id_type(1)));
BOOST_CHECK(a < b);
BOOST_CHECK(b > a);
BOOST_CHECK(a == c);
@ -168,7 +173,7 @@ BOOST_AUTO_TEST_CASE( price_test )
price_feed dummy;
dummy.maintenance_collateral_ratio = 1002;
dummy.maximum_short_squeeze_ratio = 1234;
dummy.settlement_price = price(asset(1000), asset(2000, 1));
dummy.settlement_price = price(asset(1000), asset(2000, asset_id_type(1)));
price_feed dummy2 = dummy;
BOOST_CHECK(dummy == dummy2);
}

View file

@ -48,8 +48,8 @@ BOOST_FIXTURE_TEST_SUITE( operation_tests, database_fixture )
BOOST_AUTO_TEST_CASE( feed_limit_logic_test )
{
try {
asset usd(1000,1);
asset core(1000,0);
asset usd(1000,asset_id_type(1));
asset core(1000,asset_id_type(0));
price_feed feed;
feed.settlement_price = usd / core;
@ -695,7 +695,7 @@ BOOST_AUTO_TEST_CASE( create_uia )
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
creator.common_options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
creator.common_options.flags = charge_market_fee;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,1)});
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
trx.operations.push_back(std::move(creator));
PUSH_TX( db, trx, ~0 );

View file

@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_create )
REQUIRE_OP_VALIDATION_FAILURE(op, periods_until_expiration, 0);
REQUIRE_OP_VALIDATION_FAILURE(op, withdraw_from_account, dan_id);
REQUIRE_OP_VALIDATION_FAILURE(op, withdrawal_period_sec, 0);
REQUIRE_THROW_WITH_VALUE(op, withdrawal_limit, asset(10, 10));
REQUIRE_THROW_WITH_VALUE(op, withdrawal_limit, asset(10, asset_id_type(10)));
REQUIRE_THROW_WITH_VALUE(op, authorized_account, account_id_type(1000));
REQUIRE_THROW_WITH_VALUE(op, period_start_time, fc::time_point_sec(10000));
REQUIRE_THROW_WITH_VALUE(op, withdrawal_period_sec, 1);
@ -281,7 +281,7 @@ BOOST_AUTO_TEST_CASE( withdraw_permission_update )
trx.operations.push_back(op);
REQUIRE_THROW_WITH_VALUE(op, periods_until_expiration, 0);
REQUIRE_THROW_WITH_VALUE(op, withdrawal_period_sec, 0);
REQUIRE_THROW_WITH_VALUE(op, withdrawal_limit, asset(1, 12));
REQUIRE_THROW_WITH_VALUE(op, withdrawal_limit, asset(1, asset_id_type(12)));
REQUIRE_THROW_WITH_VALUE(op, withdrawal_limit, asset(0));
REQUIRE_THROW_WITH_VALUE(op, withdraw_from_account, account_id_type(0));
REQUIRE_THROW_WITH_VALUE(op, authorized_account, account_id_type(0));

View file

@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE( create_advanced_uia )
creator.common_options.market_fee_percent = GRAPHENE_MAX_MARKET_FEE_PERCENT/100; /*1%*/
creator.common_options.issuer_permissions = charge_market_fee|white_list|override_authority|transfer_restricted|disable_confidential;
creator.common_options.flags = charge_market_fee|white_list|override_authority|disable_confidential;
creator.common_options.core_exchange_rate = price({asset(2),asset(1,1)});
creator.common_options.core_exchange_rate = price({asset(2),asset(1,asset_id_type(1))});
creator.common_options.whitelist_authorities = creator.common_options.blacklist_authorities = {account_id_type()};
trx.operations.push_back(std::move(creator));
PUSH_TX( db, trx, ~0 );