Merge commit '9466d2096a370e15aff70842b48feeca4a941e5c' into betting
This commit is contained in:
commit
51fb13f8ba
11 changed files with 527 additions and 167 deletions
|
|
@ -36,8 +36,11 @@ To build after all dependencies are installed:
|
|||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .
|
||||
make
|
||||
|
||||
Alternate Boost versions can be specified using the `DBOOST_ROOT` CMake argument. After building, the witness node can
|
||||
be launched with:
|
||||
**NOTE:** BitShares requires a [Boost](http://www.boost.org/) version in the range [1.57, 1.60]. Versions earlier than
|
||||
1.57 or newer than 1.60 are NOT supported. If your system Boost version is newer, then you will need to manually build
|
||||
an older version of Boost and specify it to CMake using `DBOOST_ROOT`.
|
||||
|
||||
After building, the witness node can be launched with:
|
||||
|
||||
./programs/witness_node/witness_node
|
||||
|
||||
|
|
|
|||
2
docs
2
docs
|
|
@ -1 +1 @@
|
|||
Subproject commit 474c28bc7181739f25229b45b76646a693cad998
|
||||
Subproject commit 981d1ef1eb35e89bb9a9423c1762427fe8ef07cc
|
||||
|
|
@ -1 +1 @@
|
|||
2.0.170224
|
||||
2.0.170328
|
||||
|
|
|
|||
|
|
@ -173,6 +173,16 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
return _subscribe_filter.contains( i );
|
||||
}
|
||||
|
||||
bool is_impacted_account( const flat_set<account_id_type>& accounts)
|
||||
{
|
||||
if( !_subscribed_accounts.size() || !accounts.size() )
|
||||
return false;
|
||||
|
||||
return std::any_of(accounts.begin(), accounts.end(), [this](const account_id_type& account) {
|
||||
return _subscribed_accounts.find(account) != _subscribed_accounts.end();
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void enqueue_if_subscribed_to_market(const object* obj, market_queue_type& queue, bool full_object=true)
|
||||
{
|
||||
|
|
@ -189,16 +199,17 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
|||
|
||||
void broadcast_updates( const vector<variant>& updates );
|
||||
void broadcast_market_updates( const market_queue_type& queue);
|
||||
void handle_object_changed(bool force_notify, const vector<object_id_type>& ids, std::function<const object*(object_id_type id)> find_object);
|
||||
|
||||
void handle_object_changed(bool force_notify, bool full_object, const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts, std::function<const object*(object_id_type id)> find_object);
|
||||
|
||||
/** called every time a block is applied to report the objects that were changed */
|
||||
void on_objects_new(const vector<object_id_type>& ids);
|
||||
void on_objects_changed(const vector<object_id_type>& ids);
|
||||
void on_objects_removed(const vector<object_id_type>& ids, const vector<const object*>& objs);
|
||||
void on_objects_new(const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts);
|
||||
void on_objects_changed(const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts);
|
||||
void on_objects_removed(const vector<object_id_type>& ids, const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts);
|
||||
void on_applied_block();
|
||||
|
||||
bool _notify_remove_create = false;
|
||||
mutable fc::bloom_filter _subscribe_filter;
|
||||
std::set<account_id_type> _subscribed_accounts;
|
||||
std::function<void(const fc::variant&)> _subscribe_callback;
|
||||
std::function<void(const fc::variant&)> _pending_trx_callback;
|
||||
std::function<void(const fc::variant&)> _block_applied_callback;
|
||||
|
|
@ -226,14 +237,14 @@ database_api::~database_api() {}
|
|||
database_api_impl::database_api_impl( graphene::chain::database& db ):_db(db)
|
||||
{
|
||||
wlog("creating database api ${x}", ("x",int64_t(this)) );
|
||||
_new_connection = _db.new_objects.connect([this](const vector<object_id_type>& ids) {
|
||||
on_objects_new(ids);
|
||||
_new_connection = _db.new_objects.connect([this](const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts) {
|
||||
on_objects_new(ids, impacted_accounts);
|
||||
});
|
||||
_change_connection = _db.changed_objects.connect([this](const vector<object_id_type>& ids) {
|
||||
on_objects_changed(ids);
|
||||
_change_connection = _db.changed_objects.connect([this](const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts) {
|
||||
on_objects_changed(ids, impacted_accounts);
|
||||
});
|
||||
_removed_connection = _db.removed_objects.connect([this](const vector<object_id_type>& ids, const vector<const object*>& objs) {
|
||||
on_objects_removed(ids, objs);
|
||||
_removed_connection = _db.removed_objects.connect([this](const vector<object_id_type>& ids, const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts) {
|
||||
on_objects_removed(ids, objs, impacted_accounts);
|
||||
});
|
||||
_applied_block_connection = _db.applied_block.connect([this](const signed_block&){ on_applied_block(); });
|
||||
|
||||
|
|
@ -299,10 +310,11 @@ void database_api_impl::set_subscribe_callback( std::function<void(const variant
|
|||
//edump((clear_filter));
|
||||
_subscribe_callback = cb;
|
||||
_notify_remove_create = notify_remove_create;
|
||||
_subscribed_accounts.clear();
|
||||
|
||||
static fc::bloom_parameters param;
|
||||
param.projected_element_count = 10000;
|
||||
param.false_positive_probability = 1.0/10000;
|
||||
param.false_positive_probability = 1.0/100;
|
||||
param.maximum_size = 1024*8*8*2;
|
||||
param.compute_optimal_parameters();
|
||||
_subscribe_filter = fc::bloom_filter(param);
|
||||
|
|
@ -609,6 +621,8 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
|
|||
|
||||
if( subscribe )
|
||||
{
|
||||
FC_ASSERT( std::distance(_subscribed_accounts.begin(), _subscribed_accounts.end()) < 100 );
|
||||
_subscribed_accounts.insert( account->get_id() );
|
||||
subscribe_to_item( account->id );
|
||||
}
|
||||
|
||||
|
|
@ -670,22 +684,22 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
|
|||
[&acnt] (const call_order_object& call) {
|
||||
acnt.call_orders.emplace_back(call);
|
||||
});
|
||||
|
||||
|
||||
// get assets issued by user
|
||||
auto asset_range = _db.get_index_type<asset_index>().indices().get<by_issuer>().equal_range(account->id);
|
||||
std::for_each(asset_range.first, asset_range.second,
|
||||
[&acnt] (const asset_object& asset) {
|
||||
acnt.assets.emplace_back(asset.id);
|
||||
});
|
||||
|
||||
|
||||
// get withdraws permissions
|
||||
auto withdraw_range = _db.get_index_type<withdraw_permission_index>().indices().get<by_from>().equal_range(account->id);
|
||||
std::for_each(withdraw_range.first, withdraw_range.second,
|
||||
[&acnt] (const withdraw_permission_object& withdraw) {
|
||||
acnt.withdraws.emplace_back(withdraw);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
results[account_name_or_id] = acnt;
|
||||
}
|
||||
return results;
|
||||
|
|
@ -1129,120 +1143,84 @@ void database_api_impl::unsubscribe_from_market(asset_id_type a, asset_id_type b
|
|||
|
||||
market_ticker database_api::get_ticker( const string& base, const string& quote )const
|
||||
{
|
||||
return my->get_ticker( base, quote );
|
||||
return my->get_ticker( base, quote );
|
||||
}
|
||||
|
||||
market_ticker database_api_impl::get_ticker( const string& base, const string& quote )const
|
||||
{
|
||||
auto assets = lookup_asset_symbols( {base, quote} );
|
||||
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
|
||||
FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) );
|
||||
const auto assets = lookup_asset_symbols( {base, quote} );
|
||||
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
|
||||
FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) );
|
||||
|
||||
auto base_id = assets[0]->id;
|
||||
auto quote_id = assets[1]->id;
|
||||
market_ticker result;
|
||||
result.base = base;
|
||||
result.quote = quote;
|
||||
result.latest = 0;
|
||||
result.lowest_ask = 0;
|
||||
result.highest_bid = 0;
|
||||
result.percent_change = 0;
|
||||
result.base_volume = 0;
|
||||
result.quote_volume = 0;
|
||||
|
||||
market_ticker result;
|
||||
try {
|
||||
const fc::time_point_sec now = fc::time_point::now();
|
||||
const fc::time_point_sec yesterday = fc::time_point_sec( now.sec_since_epoch() - 86400 );
|
||||
const auto batch_size = 100;
|
||||
|
||||
result.base = base;
|
||||
result.quote = quote;
|
||||
result.base_volume = 0;
|
||||
result.quote_volume = 0;
|
||||
result.percent_change = 0;
|
||||
result.lowest_ask = 0;
|
||||
result.highest_bid = 0;
|
||||
vector<market_trade> trades = get_trade_history( base, quote, now, yesterday, batch_size );
|
||||
if( !trades.empty() )
|
||||
{
|
||||
result.latest = trades[0].price;
|
||||
|
||||
auto price_to_real = [&]( const share_type a, int p ) { return double( a.value ) / pow( 10, p ); };
|
||||
|
||||
try {
|
||||
if( base_id > quote_id ) std::swap(base_id, quote_id);
|
||||
|
||||
uint32_t day = 86400;
|
||||
auto now = fc::time_point_sec( fc::time_point::now() );
|
||||
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
|
||||
|
||||
if ( trades.size() )
|
||||
{
|
||||
result.latest = trades[0].price;
|
||||
|
||||
for ( market_trade t: trades )
|
||||
{
|
||||
result.base_volume += t.value;
|
||||
result.quote_volume += t.amount;
|
||||
}
|
||||
|
||||
while (trades.size() == 100)
|
||||
{
|
||||
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - day ), 100 );
|
||||
|
||||
for ( market_trade t: trades )
|
||||
while( !trades.empty() )
|
||||
{
|
||||
result.base_volume += t.value;
|
||||
result.quote_volume += t.amount;
|
||||
for( const market_trade& t: trades )
|
||||
{
|
||||
result.base_volume += t.value;
|
||||
result.quote_volume += t.amount;
|
||||
}
|
||||
|
||||
trades = get_trade_history( base, quote, trades.back().date, yesterday, batch_size );
|
||||
}
|
||||
}
|
||||
|
||||
trades = get_trade_history( base, quote, trades.back().date, fc::time_point_sec(), 1 );
|
||||
result.percent_change = trades.size() > 0 ? ( ( result.latest / trades.back().price ) - 1 ) * 100 : 0;
|
||||
}
|
||||
const auto last_trade_yesterday = get_trade_history( base, quote, yesterday, fc::time_point_sec(), 1 );
|
||||
if( !last_trade_yesterday.empty() )
|
||||
{
|
||||
const auto price_yesterday = last_trade_yesterday[0].price;
|
||||
result.percent_change = ( (result.latest / price_yesterday) - 1 ) * 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto last_trade = get_trade_history( base, quote, now, fc::time_point_sec(), 1 );
|
||||
if( !last_trade.empty() )
|
||||
result.latest = last_trade[0].price;
|
||||
}
|
||||
|
||||
auto orders = get_order_book( base, quote, 1 );
|
||||
if( orders.asks.size() )
|
||||
result.lowest_ask = orders.asks[0].price;
|
||||
if( orders.bids.size() )
|
||||
result.highest_bid = orders.bids[0].price;
|
||||
const auto orders = get_order_book( base, quote, 1 );
|
||||
if( !orders.asks.empty() ) result.lowest_ask = orders.asks[0].price;
|
||||
if( !orders.bids.empty() ) result.highest_bid = orders.bids[0].price;
|
||||
} FC_CAPTURE_AND_RETHROW( (base)(quote) )
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (base)(quote) )
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
market_volume database_api::get_24_volume( const string& base, const string& quote )const
|
||||
{
|
||||
return my->get_24_volume( base, quote );
|
||||
return my->get_24_volume( base, quote );
|
||||
}
|
||||
|
||||
market_volume database_api_impl::get_24_volume( const string& base, const string& quote )const
|
||||
{
|
||||
auto assets = lookup_asset_symbols( {base, quote} );
|
||||
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
|
||||
FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) );
|
||||
const auto ticker = get_ticker( base, quote );
|
||||
|
||||
auto base_id = assets[0]->id;
|
||||
auto quote_id = assets[1]->id;
|
||||
market_volume result;
|
||||
result.base = ticker.base;
|
||||
result.quote = ticker.quote;
|
||||
result.base_volume = ticker.base_volume;
|
||||
result.quote_volume = ticker.quote_volume;
|
||||
|
||||
market_volume result;
|
||||
result.base = base;
|
||||
result.quote = quote;
|
||||
result.base_volume = 0;
|
||||
result.quote_volume = 0;
|
||||
|
||||
try {
|
||||
if( base_id > quote_id ) std::swap(base_id, quote_id);
|
||||
|
||||
uint32_t bucket_size = 86400;
|
||||
auto now = fc::time_point_sec( fc::time_point::now() );
|
||||
|
||||
auto trades = get_trade_history( base, quote, now, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
||||
|
||||
for ( market_trade t: trades )
|
||||
{
|
||||
result.base_volume += t.value;
|
||||
result.quote_volume += t.amount;
|
||||
}
|
||||
|
||||
while (trades.size() == 100)
|
||||
{
|
||||
trades = get_trade_history( base, quote, trades[99].date, fc::time_point_sec( now.sec_since_epoch() - bucket_size ), 100 );
|
||||
|
||||
for ( market_trade t: trades )
|
||||
{
|
||||
result.base_volume += t.value;
|
||||
result.quote_volume += t.amount;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} FC_CAPTURE_AND_RETHROW( (base)(quote) )
|
||||
return result;
|
||||
}
|
||||
|
||||
order_book database_api::get_order_book( const string& base, const string& quote, unsigned limit )const
|
||||
|
|
@ -1914,50 +1892,57 @@ void database_api_impl::broadcast_market_updates( const market_queue_type& queue
|
|||
}
|
||||
}
|
||||
|
||||
void database_api_impl::on_objects_removed( const vector<object_id_type>& ids, const vector<const object*>& objs )
|
||||
void database_api_impl::on_objects_removed( const vector<object_id_type>& ids, const vector<const object*>& objs, const flat_set<account_id_type>& impacted_accounts)
|
||||
{
|
||||
handle_object_changed(_notify_remove_create, ids, [objs](object_id_type id) -> const object* {
|
||||
handle_object_changed(_notify_remove_create, false, ids, impacted_accounts,
|
||||
[objs](object_id_type id) -> const object* {
|
||||
auto it = std::find_if(
|
||||
objs.begin(), objs.end(),
|
||||
[id](const object* o) {return o != nullptr && o->id == id;});
|
||||
|
||||
auto it = std::find_if(
|
||||
objs.begin(), objs.end(),
|
||||
[id](const object* o) {return o != nullptr && o->id == id;});
|
||||
if (it != objs.end())
|
||||
return *it;
|
||||
|
||||
if (it != objs.end())
|
||||
return *it;
|
||||
|
||||
return nullptr;
|
||||
});
|
||||
return nullptr;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void database_api_impl::on_objects_new(const vector<object_id_type>& ids)
|
||||
void database_api_impl::on_objects_new(const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts)
|
||||
{
|
||||
handle_object_changed(_notify_remove_create, ids,
|
||||
handle_object_changed(_notify_remove_create, true, ids, impacted_accounts,
|
||||
std::bind(&object_database::find_object, &_db, std::placeholders::_1)
|
||||
);
|
||||
}
|
||||
|
||||
void database_api_impl::on_objects_changed(const vector<object_id_type>& ids)
|
||||
void database_api_impl::on_objects_changed(const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts)
|
||||
{
|
||||
handle_object_changed(false, ids,
|
||||
handle_object_changed(false, true, ids, impacted_accounts,
|
||||
std::bind(&object_database::find_object, &_db, std::placeholders::_1)
|
||||
);
|
||||
}
|
||||
|
||||
void database_api_impl::handle_object_changed(bool force_notify, const vector<object_id_type>& ids, std::function<const object*(object_id_type id)> find_object)
|
||||
void database_api_impl::handle_object_changed(bool force_notify, bool full_object, const vector<object_id_type>& ids, const flat_set<account_id_type>& impacted_accounts, std::function<const object*(object_id_type id)> find_object)
|
||||
{
|
||||
if( _subscribe_callback )
|
||||
{
|
||||
vector<variant> updates;
|
||||
|
||||
|
||||
for(auto id : ids)
|
||||
{
|
||||
const object* obj = nullptr;
|
||||
if( force_notify || is_subscribed_to_item(id) )
|
||||
if( force_notify || is_subscribed_to_item(id) || is_impacted_account(impacted_accounts) )
|
||||
{
|
||||
obj = find_object(id);
|
||||
if( obj )
|
||||
if( full_object )
|
||||
{
|
||||
updates.emplace_back( obj->to_variant() );
|
||||
auto obj = find_object(id);
|
||||
if( obj )
|
||||
{
|
||||
updates.emplace_back( obj->to_variant() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
updates.emplace_back( id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1973,11 +1958,11 @@ void database_api_impl::handle_object_changed(bool force_notify, const vector<ob
|
|||
{
|
||||
if( id.is<call_order_object>() )
|
||||
{
|
||||
enqueue_if_subscribed_to_market<call_order_object>( find_object(id), broadcast_queue );
|
||||
enqueue_if_subscribed_to_market<call_order_object>( find_object(id), broadcast_queue, full_object );
|
||||
}
|
||||
else if( id.is<limit_order_object>() )
|
||||
{
|
||||
enqueue_if_subscribed_to_market<limit_order_object>( find_object(id), broadcast_queue );
|
||||
enqueue_if_subscribed_to_market<limit_order_object>( find_object(id), broadcast_queue, full_object );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,3 +33,4 @@
|
|||
#include "db_market.cpp"
|
||||
#include "db_update.cpp"
|
||||
#include "db_witness_schedule.cpp"
|
||||
#include "db_notify.cpp"
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include <graphene/chain/block_summary_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
|
|
@ -544,31 +545,7 @@ void database::_apply_block( const signed_block& next_block )
|
|||
notify_changed_objects();
|
||||
} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }
|
||||
|
||||
void database::notify_changed_objects()
|
||||
{ try {
|
||||
if( _undo_db.enabled() )
|
||||
{
|
||||
const auto& head_undo = _undo_db.head();
|
||||
|
||||
vector<object_id_type> new_ids; new_ids.reserve(head_undo.new_ids.size());
|
||||
for( const auto& item : head_undo.new_ids ) new_ids.push_back(item);
|
||||
|
||||
vector<object_id_type> changed_ids; changed_ids.reserve(head_undo.old_values.size());
|
||||
for( const auto& item : head_undo.old_values ) changed_ids.push_back(item.first);
|
||||
|
||||
vector<object_id_type> removed_ids; removed_ids.reserve( head_undo.removed.size() );
|
||||
vector<const object*> removed; removed.reserve( head_undo.removed.size() );
|
||||
for( const auto& item : head_undo.removed )
|
||||
{
|
||||
removed_ids.emplace_back( item.first );
|
||||
removed.emplace_back( item.second.get() );
|
||||
}
|
||||
|
||||
new_objects(new_ids);
|
||||
changed_objects(changed_ids);
|
||||
removed_objects(removed_ids, removed);
|
||||
}
|
||||
} FC_CAPTURE_AND_LOG( () ) }
|
||||
|
||||
processed_transaction database::apply_transaction(const signed_transaction& trx, uint32_t skip)
|
||||
{
|
||||
|
|
|
|||
392
libraries/chain/db_notify.cpp
Normal file
392
libraries/chain/db_notify.cpp
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
#include <fc/container/flat.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/authority.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
#include <graphene/chain/confidential_object.hpp>
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
#include <graphene/chain/committee_member_object.hpp>
|
||||
|
||||
using namespace fc;
|
||||
using namespace graphene::chain;
|
||||
|
||||
// TODO: Review all of these, especially no-ops
|
||||
struct get_impacted_account_visitor
|
||||
{
|
||||
flat_set<account_id_type>& _impacted;
|
||||
get_impacted_account_visitor( flat_set<account_id_type>& impact ):_impacted(impact) {}
|
||||
typedef void result_type;
|
||||
|
||||
void operator()( const transfer_operation& op )
|
||||
{
|
||||
_impacted.insert( op.to );
|
||||
}
|
||||
|
||||
void operator()( const asset_claim_fees_operation& op ){}
|
||||
void operator()( const limit_order_create_operation& op ) {}
|
||||
void operator()( const limit_order_cancel_operation& op )
|
||||
{
|
||||
_impacted.insert( op.fee_paying_account );
|
||||
}
|
||||
void operator()( const call_order_update_operation& op ) {}
|
||||
void operator()( const fill_order_operation& op )
|
||||
{
|
||||
_impacted.insert( op.account_id );
|
||||
}
|
||||
|
||||
void operator()( const account_create_operation& op )
|
||||
{
|
||||
_impacted.insert( op.registrar );
|
||||
_impacted.insert( op.referrer );
|
||||
add_authority_accounts( _impacted, op.owner );
|
||||
add_authority_accounts( _impacted, op.active );
|
||||
}
|
||||
|
||||
void operator()( const account_update_operation& op )
|
||||
{
|
||||
_impacted.insert( op.account );
|
||||
if( op.owner )
|
||||
add_authority_accounts( _impacted, *(op.owner) );
|
||||
if( op.active )
|
||||
add_authority_accounts( _impacted, *(op.active) );
|
||||
}
|
||||
|
||||
void operator()( const account_whitelist_operation& op )
|
||||
{
|
||||
_impacted.insert( op.account_to_list );
|
||||
}
|
||||
|
||||
void operator()( const account_upgrade_operation& op ) {}
|
||||
void operator()( const account_transfer_operation& op )
|
||||
{
|
||||
_impacted.insert( op.new_owner );
|
||||
}
|
||||
|
||||
void operator()( const asset_create_operation& op ) {}
|
||||
void operator()( const asset_update_operation& op )
|
||||
{
|
||||
if( op.new_issuer )
|
||||
_impacted.insert( *(op.new_issuer) );
|
||||
}
|
||||
|
||||
void operator()( const asset_update_bitasset_operation& op ) {}
|
||||
void operator()( const asset_update_feed_producers_operation& op ) {}
|
||||
|
||||
void operator()( const asset_issue_operation& op )
|
||||
{
|
||||
_impacted.insert( op.issue_to_account );
|
||||
}
|
||||
|
||||
void operator()( const asset_reserve_operation& op ) {}
|
||||
void operator()( const asset_fund_fee_pool_operation& op ) {}
|
||||
void operator()( const asset_settle_operation& op ) {}
|
||||
void operator()( const asset_global_settle_operation& op ) {}
|
||||
void operator()( const asset_publish_feed_operation& op ) {}
|
||||
void operator()( const witness_create_operation& op )
|
||||
{
|
||||
_impacted.insert( op.witness_account );
|
||||
}
|
||||
void operator()( const witness_update_operation& op )
|
||||
{
|
||||
_impacted.insert( op.witness_account );
|
||||
}
|
||||
|
||||
void operator()( const proposal_create_operation& op )
|
||||
{
|
||||
vector<authority> other;
|
||||
for( const auto& proposed_op : op.proposed_ops )
|
||||
operation_get_required_authorities( proposed_op.op, _impacted, _impacted, other );
|
||||
for( auto& o : other )
|
||||
add_authority_accounts( _impacted, o );
|
||||
}
|
||||
|
||||
void operator()( const proposal_update_operation& op ) {}
|
||||
void operator()( const proposal_delete_operation& op ) {}
|
||||
|
||||
void operator()( const withdraw_permission_create_operation& op )
|
||||
{
|
||||
_impacted.insert( op.authorized_account );
|
||||
}
|
||||
|
||||
void operator()( const withdraw_permission_update_operation& op )
|
||||
{
|
||||
_impacted.insert( op.authorized_account );
|
||||
}
|
||||
|
||||
void operator()( const withdraw_permission_claim_operation& op )
|
||||
{
|
||||
_impacted.insert( op.withdraw_from_account );
|
||||
}
|
||||
|
||||
void operator()( const withdraw_permission_delete_operation& op )
|
||||
{
|
||||
_impacted.insert( op.authorized_account );
|
||||
}
|
||||
|
||||
void operator()( const committee_member_create_operation& op )
|
||||
{
|
||||
_impacted.insert( op.committee_member_account );
|
||||
}
|
||||
void operator()( const committee_member_update_operation& op )
|
||||
{
|
||||
_impacted.insert( op.committee_member_account );
|
||||
}
|
||||
void operator()( const committee_member_update_global_parameters_operation& op ) {}
|
||||
|
||||
void operator()( const vesting_balance_create_operation& op )
|
||||
{
|
||||
_impacted.insert( op.owner );
|
||||
}
|
||||
|
||||
void operator()( const vesting_balance_withdraw_operation& op ) {}
|
||||
void operator()( const worker_create_operation& op ) {}
|
||||
void operator()( const custom_operation& op ) {}
|
||||
void operator()( const assert_operation& op ) {}
|
||||
void operator()( const balance_claim_operation& op ) {}
|
||||
|
||||
void operator()( const override_transfer_operation& op )
|
||||
{
|
||||
_impacted.insert( op.to );
|
||||
_impacted.insert( op.from );
|
||||
_impacted.insert( op.issuer );
|
||||
}
|
||||
|
||||
void operator()( const transfer_to_blind_operation& op )
|
||||
{
|
||||
_impacted.insert( op.from );
|
||||
for( const auto& out : op.outputs )
|
||||
add_authority_accounts( _impacted, out.owner );
|
||||
}
|
||||
|
||||
void operator()( const blind_transfer_operation& op )
|
||||
{
|
||||
for( const auto& in : op.inputs )
|
||||
add_authority_accounts( _impacted, in.owner );
|
||||
for( const auto& out : op.outputs )
|
||||
add_authority_accounts( _impacted, out.owner );
|
||||
}
|
||||
|
||||
void operator()( const transfer_from_blind_operation& op )
|
||||
{
|
||||
_impacted.insert( op.to );
|
||||
for( const auto& in : op.inputs )
|
||||
add_authority_accounts( _impacted, in.owner );
|
||||
}
|
||||
|
||||
void operator()( const asset_settle_cancel_operation& op )
|
||||
{
|
||||
_impacted.insert( op.account );
|
||||
}
|
||||
|
||||
void operator()( const fba_distribute_operation& op )
|
||||
{
|
||||
_impacted.insert( op.account_id );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||
{
|
||||
get_impacted_account_visitor vtor = get_impacted_account_visitor( result );
|
||||
op.visit( vtor );
|
||||
}
|
||||
|
||||
void transaction_get_impacted_accounts( const transaction& tx, flat_set<account_id_type>& result )
|
||||
{
|
||||
for( const auto& op : tx.operations )
|
||||
operation_get_impacted_accounts( op, result );
|
||||
}
|
||||
|
||||
void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
|
||||
{
|
||||
if( obj->id.space() == protocol_ids )
|
||||
{
|
||||
switch( (object_type)obj->id.type() )
|
||||
{
|
||||
case null_object_type:
|
||||
case base_object_type:
|
||||
case OBJECT_TYPE_COUNT:
|
||||
return;
|
||||
case account_object_type:{
|
||||
accounts.insert( obj->id );
|
||||
break;
|
||||
} case asset_object_type:{
|
||||
const auto& aobj = dynamic_cast<const asset_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->issuer );
|
||||
break;
|
||||
} case force_settlement_object_type:{
|
||||
const auto& aobj = dynamic_cast<const force_settlement_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->owner );
|
||||
break;
|
||||
} case committee_member_object_type:{
|
||||
const auto& aobj = dynamic_cast<const committee_member_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->committee_member_account );
|
||||
break;
|
||||
} case witness_object_type:{
|
||||
const auto& aobj = dynamic_cast<const witness_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->witness_account );
|
||||
break;
|
||||
} case limit_order_object_type:{
|
||||
const auto& aobj = dynamic_cast<const limit_order_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->seller );
|
||||
break;
|
||||
} case call_order_object_type:{
|
||||
const auto& aobj = dynamic_cast<const call_order_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->borrower );
|
||||
break;
|
||||
} case custom_object_type:{
|
||||
break;
|
||||
} case proposal_object_type:{
|
||||
const auto& aobj = dynamic_cast<const proposal_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
transaction_get_impacted_accounts( aobj->proposed_transaction, accounts );
|
||||
break;
|
||||
} case operation_history_object_type:{
|
||||
const auto& aobj = dynamic_cast<const operation_history_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
operation_get_impacted_accounts( aobj->op, accounts );
|
||||
break;
|
||||
} case withdraw_permission_object_type:{
|
||||
const auto& aobj = dynamic_cast<const withdraw_permission_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->withdraw_from_account );
|
||||
accounts.insert( aobj->authorized_account );
|
||||
break;
|
||||
} case vesting_balance_object_type:{
|
||||
const auto& aobj = dynamic_cast<const vesting_balance_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->owner );
|
||||
break;
|
||||
} case worker_object_type:{
|
||||
const auto& aobj = dynamic_cast<const worker_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->worker_account );
|
||||
break;
|
||||
} case balance_object_type:{
|
||||
/** these are free from any accounts */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( obj->id.space() == implementation_ids )
|
||||
{
|
||||
switch( (impl_object_type)obj->id.type() )
|
||||
{
|
||||
case impl_global_property_object_type:
|
||||
break;
|
||||
case impl_dynamic_global_property_object_type:
|
||||
break;
|
||||
case impl_reserved0_object_type:
|
||||
break;
|
||||
case impl_asset_dynamic_data_type:
|
||||
break;
|
||||
case impl_asset_bitasset_data_type:
|
||||
break;
|
||||
case impl_account_balance_object_type:{
|
||||
const auto& aobj = dynamic_cast<const account_balance_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->owner );
|
||||
break;
|
||||
} case impl_account_statistics_object_type:{
|
||||
const auto& aobj = dynamic_cast<const account_statistics_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
accounts.insert( aobj->owner );
|
||||
break;
|
||||
} case impl_transaction_object_type:{
|
||||
const auto& aobj = dynamic_cast<const transaction_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
transaction_get_impacted_accounts( aobj->trx, accounts );
|
||||
break;
|
||||
} case impl_blinded_balance_object_type:{
|
||||
const auto& aobj = dynamic_cast<const blinded_balance_object*>(obj);
|
||||
assert( aobj != nullptr );
|
||||
for( const auto& a : aobj->owner.account_auths )
|
||||
accounts.insert( a.first );
|
||||
break;
|
||||
} case impl_block_summary_object_type:
|
||||
break;
|
||||
case impl_account_transaction_history_object_type:
|
||||
break;
|
||||
case impl_chain_property_object_type:
|
||||
break;
|
||||
case impl_witness_schedule_object_type:
|
||||
break;
|
||||
case impl_budget_record_object_type:
|
||||
break;
|
||||
case impl_special_authority_object_type:
|
||||
break;
|
||||
case impl_buyback_object_type:
|
||||
break;
|
||||
case impl_fba_accumulator_object_type:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void database::notify_changed_objects()
|
||||
{ try {
|
||||
if( _undo_db.enabled() )
|
||||
{
|
||||
const auto& head_undo = _undo_db.head();
|
||||
|
||||
// New
|
||||
if( !new_objects.empty() )
|
||||
{
|
||||
vector<object_id_type> new_ids; new_ids.reserve(head_undo.new_ids.size());
|
||||
flat_set<account_id_type> new_accounts_impacted;
|
||||
for( const auto& item : head_undo.new_ids )
|
||||
{
|
||||
new_ids.push_back(item);
|
||||
auto obj = find_object(item);
|
||||
if(obj != nullptr)
|
||||
get_relevant_accounts(obj, new_accounts_impacted);
|
||||
}
|
||||
|
||||
new_objects(new_ids, new_accounts_impacted);
|
||||
}
|
||||
|
||||
// Changed
|
||||
if( !changed_objects.empty() )
|
||||
{
|
||||
vector<object_id_type> changed_ids; changed_ids.reserve(head_undo.old_values.size());
|
||||
flat_set<account_id_type> changed_accounts_impacted;
|
||||
for( const auto& item : head_undo.old_values )
|
||||
{
|
||||
changed_ids.push_back(item.first);
|
||||
get_relevant_accounts(item.second.get(), changed_accounts_impacted);
|
||||
}
|
||||
|
||||
changed_objects(changed_ids, changed_accounts_impacted);
|
||||
}
|
||||
|
||||
// Removed
|
||||
if( !removed_objects.empty() )
|
||||
{
|
||||
vector<object_id_type> removed_ids; removed_ids.reserve( head_undo.removed.size() );
|
||||
vector<const object*> removed; removed.reserve( head_undo.removed.size() );
|
||||
flat_set<account_id_type> removed_accounts_impacted;
|
||||
for( const auto& item : head_undo.removed )
|
||||
{
|
||||
removed_ids.emplace_back( item.first );
|
||||
auto obj = item.second.get();
|
||||
removed.emplace_back( obj );
|
||||
get_relevant_accounts(obj, removed_accounts_impacted);
|
||||
}
|
||||
|
||||
removed_objects(removed_ids, removed, removed_accounts_impacted);
|
||||
}
|
||||
}
|
||||
} FC_CAPTURE_AND_LOG( () ) }
|
||||
|
||||
} }
|
||||
|
|
@ -193,18 +193,18 @@ namespace graphene { namespace chain {
|
|||
* Emitted After a block has been applied and committed. The callback
|
||||
* should not yield and should execute quickly.
|
||||
*/
|
||||
fc::signal<void(const vector<object_id_type>&)> new_objects;
|
||||
fc::signal<void(const vector<object_id_type>&, const flat_set<account_id_type>&)> new_objects;
|
||||
|
||||
/**
|
||||
* Emitted After a block has been applied and committed. The callback
|
||||
* should not yield and should execute quickly.
|
||||
*/
|
||||
fc::signal<void(const vector<object_id_type>&)> changed_objects;
|
||||
fc::signal<void(const vector<object_id_type>&, const flat_set<account_id_type>&)> changed_objects;
|
||||
|
||||
/** this signal is emitted any time an object is removed and contains a
|
||||
* pointer to the last value of every object that was removed.
|
||||
*/
|
||||
fc::signal<void(const vector<object_id_type>&, const vector<const object*>&)> removed_objects;
|
||||
fc::signal<void(const vector<object_id_type>&, const vector<const object*>&, const flat_set<account_id_type>&)> removed_objects;
|
||||
|
||||
//////////////////// db_witness_schedule.cpp ////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -98,13 +98,13 @@ void debug_witness_plugin::plugin_startup()
|
|||
// connect needed signals
|
||||
|
||||
_applied_block_conn = db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); });
|
||||
_changed_objects_conn = db.changed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids){ on_changed_objects(ids); });
|
||||
_removed_objects_conn = db.removed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*>& objs){ on_removed_objects(ids, objs); });
|
||||
_changed_objects_conn = db.changed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ on_changed_objects(ids, impacted_accounts); });
|
||||
_removed_objects_conn = db.removed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*>& objs, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ on_removed_objects(ids, objs, impacted_accounts); });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void debug_witness_plugin::on_changed_objects( const std::vector<graphene::db::object_id_type>& ids )
|
||||
void debug_witness_plugin::on_changed_objects( const std::vector<graphene::db::object_id_type>& ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts )
|
||||
{
|
||||
if( _json_object_stream && (ids.size() > 0) )
|
||||
{
|
||||
|
|
@ -120,7 +120,7 @@ void debug_witness_plugin::on_changed_objects( const std::vector<graphene::db::o
|
|||
}
|
||||
}
|
||||
|
||||
void debug_witness_plugin::on_removed_objects( const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*> objs )
|
||||
void debug_witness_plugin::on_removed_objects( const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*> objs, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts )
|
||||
{
|
||||
if( _json_object_stream )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@
|
|||
|
||||
#include <graphene/app/plugin.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
#include <fc/thread/future.hpp>
|
||||
#include <fc/container/flat.hpp>
|
||||
|
||||
namespace graphene { namespace debug_witness_plugin {
|
||||
|
||||
|
|
@ -50,8 +52,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void on_changed_objects( const std::vector<graphene::db::object_id_type>& ids );
|
||||
void on_removed_objects( const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*> objs );
|
||||
void on_changed_objects( const std::vector<graphene::db::object_id_type>& ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts );
|
||||
void on_removed_objects( const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*> objs, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts );
|
||||
void on_applied_block( const graphene::chain::signed_block& b );
|
||||
|
||||
boost::program_options::variables_map _options;
|
||||
|
|
|
|||
Loading…
Reference in a new issue