Merge commit '568ceb189eca96e77e38c4059b83a504008d7e91' into betting

This commit is contained in:
Eric Frias 2017-06-21 16:42:27 -04:00
commit 3238ea735f
19 changed files with 229 additions and 104 deletions

View file

@ -129,6 +129,10 @@ else( WIN32 ) # Apple AND Linux
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp" )
elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" )
endif()
endif()
if( "${CMAKE_GENERATOR}" STREQUAL "Ninja" )

0
CONTRIBUTORS.txt Normal file
View file

View file

@ -1,5 +1,5 @@
Copyright (c) 2015-2016 Cryptonomex Inc.
Copyright (c) 2015-2017 contributors
Copyright (c) 2015-2016 Cryptonomex Inc. <contact@cryptonomex.com>
Copyright (c) 2015-2017 contributors <CONTRIBUTORS.txt>
The MIT License

View file

@ -27,6 +27,11 @@ Getting Started
Build instructions and additional documentation are available in the
[wiki](https://github.com/bitshares/bitshares-core/wiki).
We recommend building on Ubuntu 16.04 LTS, and the build dependencies may be installed with:
sudo apt-get update
sudo apt-get install autoconf cmake git libboost-all-dev libssl-dev
To build after all dependencies are installed:
git clone https://github.com/bitshares/bitshares-core.git
@ -220,5 +225,5 @@ FAQ
License
-------
BitShares Core is under the MIT license. See [LICENSE](https://github.com/bitshares/bitshares-core/blob/master/LICENSE)
BitShares Core is under the MIT license. See [LICENSE](https://github.com/bitshares/bitshares-core/blob/master/LICENSE.txt)
for more information.

2
docs

@ -1 +1 @@
Subproject commit 981d1ef1eb35e89bb9a9423c1762427fe8ef07cc
Subproject commit d99948280c6ae98a337be8ae93ab7182896d525c

View file

@ -1 +1 @@
2.0.170410
2.0.170522

View file

@ -512,21 +512,26 @@ namespace graphene { namespace app {
FC_ASSERT(limit <= 100);
vector<operation_history_object> result;
if( start == 0 )
start = account(db).statistics(db).total_ops;
else start = min( account(db).statistics(db).total_ops, start );
const auto& hist_idx = db.get_index_type<account_transaction_history_index>();
const auto& by_seq_idx = hist_idx.indices().get<by_seq>();
auto itr = by_seq_idx.upper_bound( boost::make_tuple( account, start ) );
auto itr_stop = by_seq_idx.lower_bound( boost::make_tuple( account, stop ) );
--itr;
while ( itr != itr_stop && result.size() < limit )
start = account(db).statistics(db).total_ops;
else
start = min( account(db).statistics(db).total_ops, start );
if( start >= stop && start > 0 && limit > 0 )
{
result.push_back( itr->operation_id(db) );
--itr;
const auto& hist_idx = db.get_index_type<account_transaction_history_index>();
const auto& by_seq_idx = hist_idx.indices().get<by_seq>();
auto itr = by_seq_idx.upper_bound( boost::make_tuple( account, start ) );
auto itr_stop = by_seq_idx.lower_bound( boost::make_tuple( account, stop ) );
do
{
--itr;
result.push_back( itr->operation_id(db) );
}
while ( itr != itr_stop && result.size() < limit );
}
return result;
}

View file

@ -164,9 +164,12 @@ namespace detail {
vector<string> seeds = {
"104.236.144.84:1777", // puppies (USA)
"128.199.143.47:2015", // Harvey (Singapore)
"212.47.249.84:50696", // iHashFury (France)
"23.92.53.182:1776", // sahkan (USA)
"192.121.166.162:1776", // sahkan (UK)
"51.15.61.160:1776", // lafona (France)
"bts-seed1.abit-more.com:62015", // abit (China)
"node.blckchnd.com:4243", // blckchnd (Germany)
"seed.bitsharesdex.com:50696", // iHashFury (Europe)
"seed.bitsharesnodes.com:1776", // wackou (Netherlands)
"seed.blocktrades.us:1776", // BlockTrades (USA)
"seed.cubeconnex.com:1777", // cube (USA)
@ -384,79 +387,67 @@ namespace detail {
}
_chain_db->add_checkpoints( loaded_checkpoints );
if( _options->count("replay-blockchain") )
bool replay = false;
std::string replay_reason = "reason not provided";
// never replay if data dir is empty
if( fc::exists( _data_dir ) && fc::directory_iterator( _data_dir ) != fc::directory_iterator() )
{
ilog("Replaying blockchain on user request.");
_chain_db->reindex(_data_dir/"blockchain", initial_state());
} else if( clean ) {
auto is_new = [&]() -> bool
if( _options->count("replay-blockchain") )
{
// directory doesn't exist
if( !fc::exists( _data_dir ) )
return true;
// if directory exists but is empty, return true; else false.
return ( fc::directory_iterator( _data_dir ) == fc::directory_iterator() );
};
auto is_outdated = [&]() -> bool
replay = true;
replay_reason = "replay-blockchain argument specified";
}
else if( !clean )
{
if( !fc::exists( _data_dir / "db_version" ) )
return true;
std::string version_str;
fc::read_file_contents( _data_dir / "db_version", version_str );
return (version_str != GRAPHENE_CURRENT_DB_VERSION);
};
bool need_reindex = (!is_new() && is_outdated());
std::string reindex_reason = "version upgrade";
if( !need_reindex )
replay = true;
replay_reason = "unclean shutdown detected";
}
else if( !fc::exists( _data_dir / "db_version" ) )
{
try
replay = true;
replay_reason = "db_version file not found";
}
else
{
std::string version_string;
fc::read_file_contents( _data_dir / "db_version", version_string );
if( version_string != GRAPHENE_CURRENT_DB_VERSION )
{
_chain_db->open(_data_dir / "blockchain", initial_state);
}
catch( const fc::exception& e )
{
ilog( "caught exception ${e} in open()", ("e", e.to_detail_string()) );
need_reindex = true;
reindex_reason = "exception in open()";
replay = true;
replay_reason = "db_version file content mismatch";
}
}
if( need_reindex )
{
ilog("Replaying blockchain due to ${reason}", ("reason", reindex_reason) );
fc::remove_all( _data_dir / "db_version" );
_chain_db->reindex(_data_dir / "blockchain", initial_state());
// doing this down here helps ensure that DB will be wiped
// if any of the above steps were interrupted on a previous run
if( !fc::exists( _data_dir / "db_version" ) )
{
std::ofstream db_version(
(_data_dir / "db_version").generic_string().c_str(),
std::ios::out | std::ios::binary | std::ios::trunc );
std::string version_string = GRAPHENE_CURRENT_DB_VERSION;
db_version.write( version_string.c_str(), version_string.size() );
db_version.close();
}
}
} else {
wlog("Detected unclean shutdown. Replaying blockchain...");
_chain_db->reindex(_data_dir / "blockchain", initial_state());
}
if (!_options->count("genesis-json") &&
_chain_db->get_chain_id() != graphene::egenesis::get_egenesis_chain_id()) {
elog("Detected old database. Nuking and starting over.");
_chain_db->wipe(_data_dir / "blockchain", true);
_chain_db.reset();
_chain_db = std::make_shared<chain::database>();
_chain_db->add_checkpoints(loaded_checkpoints);
_chain_db->open(_data_dir / "blockchain", initial_state);
if( !replay )
{
try
{
_chain_db->open( _data_dir / "blockchain", initial_state );
}
catch( const fc::exception& e )
{
ilog( "Caught exception ${e} in open()", ("e", e.to_detail_string()) );
replay = true;
replay_reason = "exception in open()";
}
}
if( replay )
{
ilog( "Replaying blockchain due to: ${reason}", ("reason", replay_reason) );
fc::remove_all( _data_dir / "db_version" );
_chain_db->reindex( _data_dir / "blockchain", initial_state() );
const auto mode = std::ios::out | std::ios::binary | std::ios::trunc;
std::ofstream db_version( (_data_dir / "db_version").generic_string().c_str(), mode );
std::string version_string = GRAPHENE_CURRENT_DB_VERSION;
db_version.write( version_string.c_str(), version_string.size() );
db_version.close();
}
if( _options->count("force-validate") )
@ -844,6 +835,9 @@ namespace detail {
return synopsis; // we have no blocks
}
if( low_block_num == 0)
low_block_num = 1;
// at this point:
// low_block_num is the block before the first block we can undo,
// non_fork_high_block_num is the block before the fork (if the peer is on a fork, or otherwise it is the same as high_block_num)

View file

@ -65,6 +65,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
// Blocks and transactions
optional<block_header> get_block_header(uint32_t block_num)const;
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums)const;
optional<signed_block> get_block(uint32_t block_num)const;
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
@ -369,6 +370,20 @@ optional<block_header> database_api_impl::get_block_header(uint32_t block_num) c
return *result;
return {};
}
map<uint32_t, optional<block_header>> database_api::get_block_header_batch(const vector<uint32_t> block_nums)const
{
return my->get_block_header_batch( block_nums );
}
map<uint32_t, optional<block_header>> database_api_impl::get_block_header_batch(const vector<uint32_t> block_nums) const
{
map<uint32_t, optional<block_header>> results;
for (const uint32_t block_num : block_nums)
{
results[block_num] = get_block_header(block_num);
}
return results;
}
optional<signed_block> database_api::get_block(uint32_t block_num)const
{

View file

@ -163,6 +163,14 @@ class database_api
*/
optional<block_header> get_block_header(uint32_t block_num)const;
/**
* @brief Retrieve multiple block header by block numbers
* @param block_num vector containing heights of the block whose header should be returned
* @return array of headers of the referenced blocks, or null if no matching block was found
*/
map<uint32_t, optional<block_header>> get_block_header_batch(const vector<uint32_t> block_nums)const;
/**
* @brief Retrieve a full, signed block
* @param block_num Height of the block to be returned
@ -622,6 +630,7 @@ FC_API(graphene::app::database_api,
// Blocks and transactions
(get_block_header)
(get_block_header_batch)
(get_block)
(get_transaction)
(get_recent_transaction_by_id)

View file

@ -509,7 +509,7 @@ void database::_apply_block( const signed_block& next_block )
* for transactions when validating broadcast transactions or
* when building a block.
*/
apply_transaction( trx, skip | skip_transaction_signatures );
apply_transaction( trx, skip );
++_current_trx_in_block;
}

View file

@ -66,7 +66,7 @@ void database::reindex(fc::path data_dir, const genesis_state_type& initial_allo
_undo_db.disable();
for( uint32_t i = 1; i <= last_block_num; ++i )
{
if( i % 5000 == 0 ) std::cerr << " " << double(i*100)/last_block_num << "% "<<i << " of " <<last_block_num<<" \n";
if( i % 10000 == 0 ) std::cerr << " " << double(i*100)/last_block_num << "% "<<i << " of " <<last_block_num<<" \n";
fc::optional< signed_block > block = _block_id_to_block.fetch_by_number(i);
if( !block.valid() )
{

View file

@ -185,7 +185,18 @@ struct get_impacted_account_visitor
{
_impacted.insert( op.account_id );
}
void operator()(const sport_create_operation&){}
void operator()(const competitor_create_operation&){}
void operator()(const event_group_create_operation&){}
void operator()(const event_create_operation&){}
void operator()(const betting_market_group_create_operation&){}
void operator()(const betting_market_create_operation&){}
void operator()(const bet_place_operation&){}
void operator()(const betting_market_resolve_operation&){}
void operator()(const betting_market_resolved_operation &){}
void operator()(const bet_matched_operation &){}
void operator()(const bet_cancel_operation&){}
void operator()(const bet_canceled_operation &){}
};
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
@ -389,4 +400,4 @@ void database::notify_changed_objects()
}
} FC_CAPTURE_AND_LOG( () ) }
} }
} }

@ -1 +1 @@
Subproject commit 8eb2ccc1803e82a8312b08566b2cdda8b68dc249
Subproject commit 7c88a95df11c16970412786e06d9b94b1aafddc4

View file

@ -4490,7 +4490,8 @@ namespace graphene { namespace net { namespace detail {
error_message_stream << "\nStill waiting for port " << listen_endpoint.port() << " to become available\n";
}
std::string error_message = error_message_stream.str();
ulog(error_message);
wlog(error_message);
std::cout << "\033[31m" << error_message;
_delegate->error_encountered( error_message, fc::oexception() );
fc::usleep( fc::seconds(5 ) );
}

View file

@ -64,6 +64,8 @@ class account_history_plugin_impl
account_history_plugin& _self;
flat_set<account_id_type> _tracked_accounts;
bool _partial_operations = false;
primary_index< simple_index< operation_history_object > >* _oho_index;
};
account_history_plugin_impl::~account_history_plugin_impl()
@ -77,18 +79,35 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
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;
} );
optional<operation_history_object> oho;
if( !o_op.valid() )
auto create_oho = [&]() {
return optional<operation_history_object>( db.create<operation_history_object>( [&]( operation_history_object& h )
{
if( o_op.valid() )
h = *o_op;
} ) );
};
if (_partial_operations)
{
ilog( "removing failed operation with ID: ${id}", ("id", oho.id) );
db.remove( oho );
continue;
if( !o_op.valid() )
{
_oho_index->use_next_id();
continue;
}
}
else
{
// add to the operation history index
oho = create_oho();
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;
@ -99,7 +118,10 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
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>() );
{
if (!oho.valid()) { oho = create_oho(); }
impacted.insert( oho->result.get<object_id_type>() );
}
else
graphene::app::operation_get_impacted_accounts( op.op, impacted );
@ -110,6 +132,7 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
// for each operation this account applies to that is in the config link it into the history
if( _tracked_accounts.size() == 0 )
{
if (!impacted.empty() && !oho.valid()) { oho = create_oho(); }
for( auto& account_id : impacted )
{
// we don't do index_account_keys here anymore, because
@ -118,7 +141,7 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
// 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.operation_id = oho->id;
obj.account = account_id;
obj.sequence = stats_obj.total_ops+1;
obj.next = stats_obj.most_recent_op;
@ -135,10 +158,11 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
{
if( impacted.find( account_id ) != impacted.end() )
{
if (!oho.valid()) { oho = create_oho(); }
// 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.operation_id = oho->id;
obj.account = account_id;
obj.sequence = stats_obj.total_ops+1;
obj.next = stats_obj.most_recent_op;
@ -150,6 +174,8 @@ void account_history_plugin_impl::update_account_histories( const signed_block&
}
}
}
if (_partial_operations && ! oho.valid())
_oho_index->use_next_id();
}
}
} // end namespace detail
@ -180,6 +206,7 @@ void account_history_plugin::plugin_set_program_options(
{
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)")
("partial-operations", boost::program_options::value<bool>(), "Keep only those operations in memory that are related to account history tracking")
;
cfg.add(cli);
}
@ -187,10 +214,13 @@ void account_history_plugin::plugin_set_program_options(
void account_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{
database().applied_block.connect( [&]( const signed_block& b){ my->update_account_histories(b); } );
database().add_index< primary_index< simple_index< operation_history_object > > >();
my->_oho_index = database().add_index< primary_index< simple_index< operation_history_object > > >();
database().add_index< primary_index< account_transaction_history_index > >();
LOAD_VALUE_SET(options, "track-account", my->_tracked_accounts, graphene::chain::account_id_type);
if (options.count("partial-operations")) {
my->_partial_operations = options["partial-operations"].as<bool>();
}
}
void account_history_plugin::plugin_startup()

View file

@ -321,7 +321,7 @@ void bookie_plugin::plugin_set_program_options(
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); });
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ 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>();

View file

@ -356,6 +356,15 @@ class wallet_api
*/
vector<operation_detail> get_account_history(string name, int limit)const;
/** Returns the relative operations on the named account from start number.
*
* @param name the name or id of the account
* @param stop Sequence number of earliest operation.
* @param limit the number of entries to return
* @param start the sequence number where to start looping back throw the history
* @returns a list of \c operation_history_objects
*/
vector<operation_detail> get_relative_account_history(string name, uint32_t stop, int limit, uint32_t start)const;
vector<bucket_object> get_market_history(string symbol, string symbol2, uint32_t bucket, fc::time_point_sec start, fc::time_point_sec end)const;
vector<limit_order_object> get_limit_orders(string a, string b, uint32_t limit)const;
@ -1718,6 +1727,7 @@ FC_API( graphene::wallet::wallet_api,
(get_block)
(get_account_count)
(get_account_history)
(get_relative_account_history)
(is_public_key_registered)
(get_market_history)
(get_global_properties)

View file

@ -2088,6 +2088,23 @@ public:
return ss.str();
};
m["get_relative_account_history"] = [this](variant result, const fc::variants& a)
{
auto r = result.as<vector<operation_detail>>();
std::stringstream ss;
for( operation_detail& d : r )
{
operation_history_object& i = d.op;
auto b = _remote_db->get_block_header(i.block_num);
FC_ASSERT(b);
ss << b->timestamp.to_iso_string() << " ";
i.op.visit(operation_printer(ss, *this, i.result));
ss << " \n";
}
return ss.str();
};
m["list_account_balances"] = [this](variant result, const fc::variants& a)
{
@ -2818,6 +2835,30 @@ vector<operation_detail> wallet_api::get_account_history(string name, int limit)
return result;
}
vector<operation_detail> wallet_api::get_relative_account_history(string name, uint32_t stop, int limit, uint32_t start)const
{
FC_ASSERT( start > 0 || limit <= 100 );
vector<operation_detail> result;
auto account_id = get_account(name).get_id();
while( limit > 0 )
{
vector <operation_history_object> current = my->_remote_hist->get_relative_account_history(account_id, stop, std::min<uint32_t>(100, limit), start);
for (auto &o : current) {
std::stringstream ss;
auto memo = o.op.visit(detail::operation_printer(ss, *my, o.result));
result.push_back(operation_detail{memo, ss.str(), o});
}
if (current.size() < std::min<uint32_t>(100, limit))
break;
limit -= current.size();
start -= 100;
if( start == 0 ) break;
}
return result;
}
vector<bucket_object> wallet_api::get_market_history( string symbol1, string symbol2, uint32_t bucket , fc::time_point_sec start, fc::time_point_sec end )const
{