36 #include <graphene/chain/hardfork.hpp> 40 namespace graphene {
namespace account_history {
75 void add_account_history(
const account_id_type account_id,
const operation_history_id_type op_id );
89 auto skip_oho_id = [&is_first,&db,
this]() {
90 if( is_first && db._undo_db.enabled() )
103 auto create_oho = [&]() {
110 h.result = o_op->result;
111 h.block_num = o_op->block_num;
112 h.trx_in_block = o_op->trx_in_block;
113 h.op_in_trx = o_op->op_in_trx;
114 h.virtual_op = o_op->virtual_op;
133 flat_set<account_id_type> impacted;
134 vector<authority> other;
137 MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
143 MUST_IGNORE_CUSTOM_OP_REQD_AUTHS( db.head_block_time() ) );
145 for(
auto& a : other )
146 for(
auto& item : a.account_auths )
147 impacted.insert( item.first );
160 if (!impacted.empty() && !oho.
valid()) { oho = create_oho(); }
167 for(
auto& account_id : impacted )
173 add_account_history( account_id, oho->id );
189 if( impacted.find( account_id ) != impacted.end() )
191 if (!oho.
valid()) { oho = create_oho(); }
193 add_account_history( account_id, oho->id );
203 void account_history_plugin_impl::add_account_history(
const account_id_type account_id,
const operation_history_id_type op_id )
206 const auto& stats_obj = account_id(db).statistics(db);
209 obj.operation_id = op_id;
210 obj.account = account_id;
211 obj.sequence = stats_obj.total_ops + 1;
212 obj.next = stats_obj.most_recent_op;
219 bool extended_hist =
false;
221 extended_hist |= (account_id == eh_account_id);
224 const account_id_type registrar_id = account_id(db).registrar;
226 extended_hist |= (registrar_id == eh_registrar_id);
236 if( stats_obj.total_ops - stats_obj.removed_ops > max_ops_to_keep )
240 const auto& by_seq_idx = his_idx.
indices().get<by_seq>();
241 auto itr = by_seq_idx.lower_bound( boost::make_tuple( account_id, 0 ) );
243 if( itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath.id )
246 const auto remove_op_id = itr->operation_id;
247 const auto itr_remove = itr;
255 if( itr != by_seq_idx.end() && itr->account == account_id )
258 obj.
next = account_transaction_history_id_type();
267 const auto& by_opid_idx = his_idx.indices().get<by_opid>();
268 if( by_opid_idx.find( remove_op_id ) == by_opid_idx.end() )
271 db.
remove( remove_op_id(db) );
296 return "account_history";
300 boost::program_options::options_description& cli,
301 boost::program_options::options_description& cfg
305 (
"track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(),
306 "Account ID to track history for (may specify multiple times; if unset will track all accounts)")
307 (
"partial-operations", boost::program_options::value<bool>(),
308 "Keep only those operations in memory that are related to account history tracking")
309 (
"max-ops-per-account", boost::program_options::value<uint64_t>(),
310 "Maximum number of operations per account that will be kept in memory")
311 (
"extended-max-ops-per-account", boost::program_options::value<uint64_t>(),
312 "Maximum number of operations to keep for accounts for which extended history is kept")
313 (
"extended-history-by-account",
314 boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(),
315 "Track longer history for these accounts (may specify multiple times)")
316 (
"extended-history-by-registrar",
317 boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(),
318 "Track longer history for accounts with this registrar (may specify multiple times)")
329 LOAD_VALUE_SET(options,
"track-account",
my->_tracked_accounts, graphene::chain::account_id_type);
330 if (options.count(
"partial-operations") > 0) {
331 my->_partial_operations = options[
"partial-operations"].as<
bool>();
333 if (options.count(
"max-ops-per-account") > 0) {
334 my->_max_ops_per_account = options[
"max-ops-per-account"].as<uint64_t>();
336 if (options.count(
"extended-max-ops-per-account") > 0) {
337 auto emopa = options[
"extended-max-ops-per-account"].as<uint64_t>();
338 my->_extended_max_ops_per_account = (emopa >
my->_max_ops_per_account) ? emopa :
my->_max_ops_per_account;
340 LOAD_VALUE_SET(options,
"extended-history-by-account",
my->_extended_history_accounts,
341 graphene::chain::account_id_type);
342 LOAD_VALUE_SET(options,
"extended-history-by-registrar",
my->_extended_history_registrars,
343 graphene::chain::account_id_type);
352 return my->_tracked_accounts;
account_history_plugin_impl(account_history_plugin &_plugin)
virtual void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
void modify(const T &obj, const Lambda &m)
Wraps a derived index to intercept calls to create, modify, and remove so that callbacks may be fired...
virtual void plugin_set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) override
Fill in command line parameters used by the plugin.
fc::signal< void(const signed_block &)> applied_block
tracks the history of all logical operations on blockchain stateAll operations and virtual operations...
tracks the blockchain state in an extensible manner
primary_index< operation_history_index > * _oho_index
a node in a linked list of operation_history_objectsAccount history is important for users and wallet...
void update_account_histories(const signed_block &b)
virtual void plugin_startup() override
Begin normal runtime operations.
std::unique_ptr< detail::account_history_plugin_impl > my
flat_set< account_id_type > _extended_history_accounts
provides stack-based nullable value similar to boost::optional
flat_set< account_id_type > tracked_accounts() const
virtual ~account_history_plugin_impl()
const vector< optional< operation_history_object > > & get_applied_operations() const
flat_set< account_id_type > _extended_history_registrars
chain::database & database()
graphene::chain::database & database()
#define LOAD_VALUE_SET(options, name, container, type)
uint64_t _extended_max_ops_per_account
std::string plugin_name() const override
account_history_plugin & _self
account_transaction_history_id_type next
the operation position within the given account
void remove(const object &obj)
uint64_t _max_ops_per_account
virtual ~account_history_plugin()
void operation_get_required_authorities(const operation &op, flat_set< account_id_type > &active, flat_set< account_id_type > &owner, vector< authority > &other, bool ignore_custom_operation_required_auths)
const T & create(F &&constructor)
flat_set< account_id_type > _tracked_accounts
void operation_get_impacted_accounts(const operation &op, flat_set< account_id_type > &result, bool ignore_custom_operation_required_auths)
account_transaction_history_id_type most_recent_op
const IndexType & get_index_type() const
const index_type & indices() const