void account_history_plugin_impl::update_account_histories( const signed_block& b )
{
   graphene::chain::database& db = database();
   const vector<operation_history_object>& hist = db.get_applied_operations();
   for( auto op : hist )
   {
      // add to the operation history index
      const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h ){
                                h = op;
                        });

      // get the set of accounts this operation applies to
      flat_set<account_id_type> impacted;
      vector<authority> other;
      operation_get_required_authorities( op.op, impacted, impacted, other );
      op.op.visit( operation_get_impacted_accounts( oho, _self, impacted ) );

      for( auto& a : other )
         for( auto& item : a.account_auths )
            impacted.insert( item.first );

      // for each operation this account applies to that is in the config link it into the history
      if( _tracked_accounts.size() == 0 )
      {
         for( auto& account_id : impacted )
         {
            // we don't do index_account_keys here anymore, because
            // that indexing now happens in observers' post_evaluate()

            // 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.next = stats_obj.most_recent_op;
            });
            db.modify( stats_obj, [&]( account_statistics_object& obj ){
                obj.most_recent_op = ath.id;
            });
         }
      }
      else
      {
         for( auto account_id : _tracked_accounts )
         {
            if( impacted.find( account_id ) != impacted.end() )
            {
               // 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.next = stats_obj.most_recent_op;
               });
               db.modify( stats_obj, [&]( account_statistics_object& obj ){
                   obj.most_recent_op = ath.id;
               });
            }
         }
      }
   }
}
Beispiel #2
0
 vector<account_id_type> get_relevant_accounts( const object* obj )
 {
    vector<account_id_type> result;
    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 result;
         case account_object_type:{
            result.push_back( obj->id );
            break;
         } case asset_object_type:{
            const auto& aobj = dynamic_cast<const asset_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->issuer );
            break;
         } case force_settlement_object_type:{
            const auto& aobj = dynamic_cast<const force_settlement_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->owner );
            break;
         } case committee_member_object_type:{
            const auto& aobj = dynamic_cast<const committee_member_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->committee_member_account );
            break;
         } case witness_object_type:{
            const auto& aobj = dynamic_cast<const witness_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->witness_account );
            break;
         } case limit_order_object_type:{
            const auto& aobj = dynamic_cast<const limit_order_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->seller );
            break;
         } case call_order_object_type:{
            const auto& aobj = dynamic_cast<const call_order_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->borrower );
            break;
         } case custom_object_type:{
         } case proposal_object_type:{
            const auto& aobj = dynamic_cast<const proposal_object*>(obj);
            assert( aobj != nullptr );
            flat_set<account_id_type> impacted;
            transaction_get_impacted_accounts( aobj->proposed_transaction, impacted );
            result.reserve( impacted.size() );
            for( auto& item : impacted ) result.emplace_back(item);
            break;
         } case operation_history_object_type:{
            const auto& aobj = dynamic_cast<const operation_history_object*>(obj);
            assert( aobj != nullptr );
            flat_set<account_id_type> impacted;
            operation_get_impacted_accounts( aobj->op, impacted );
            result.reserve( impacted.size() );
            for( auto& item : impacted ) result.emplace_back(item);
            break;
         } case withdraw_permission_object_type:{
            const auto& aobj = dynamic_cast<const withdraw_permission_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->withdraw_from_account );
            result.push_back( aobj->authorized_account );
            break;
         } case vesting_balance_object_type:{
            const auto& aobj = dynamic_cast<const vesting_balance_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->owner );
            break;
         } case worker_object_type:{
            const auto& aobj = dynamic_cast<const worker_object*>(obj);
            assert( aobj != nullptr );
            result.push_back( aobj->worker_account );
            break;
         } case balance_object_type:{
            /** these are free from any accounts */
         }
       }
    }
    else if( obj->id.space() == implementation_ids )
    {
       switch( (impl_object_type)obj->id.type() )
       {
              case impl_global_property_object_type:{
            } case impl_dynamic_global_property_object_type:{
            } case impl_reserved0_object_type:{
            } case impl_asset_dynamic_data_type:{
            } 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 );
               result.push_back( aobj->owner );
               break;
            } case impl_account_statistics_object_type:{
               const auto& aobj = dynamic_cast<const account_statistics_object*>(obj);
               assert( aobj != nullptr );
               result.push_back( aobj->owner );
               break;
            } case impl_transaction_object_type:{
               const auto& aobj = dynamic_cast<const transaction_object*>(obj);
               assert( aobj != nullptr );
               flat_set<account_id_type> impacted;
               transaction_get_impacted_accounts( aobj->trx, impacted );
               result.reserve( impacted.size() );
               for( auto& item : impacted ) result.emplace_back(item);
               break;
            } case impl_blinded_balance_object_type:{
               const auto& aobj = dynamic_cast<const blinded_balance_object*>(obj);
               assert( aobj != nullptr );
               result.reserve( aobj->owner.account_auths.size() );
               for( const auto& a : aobj->owner.account_auths )
                  result.push_back( a.first );
               break;
            } case impl_block_summary_object_type:{
            } case impl_account_transaction_history_object_type:{
            } case impl_chain_property_object_type: {
            } case impl_witness_schedule_object_type: {
            } case impl_budget_record_object_type: {
            }
       }
    }
    return result;
 } // end get_relevant_accounts( obj )