LCOV - code coverage report
Current view: top level - irohad/ametsuchi/impl - postgres_block_index.cpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 63 68 92.6 %
Date: 2019-03-07 14:46:43 Functions: 29 29 100.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #include "ametsuchi/impl/postgres_block_index.hpp"
       7             : 
       8             : #include <boost/range/adaptor/indexed.hpp>
       9             : 
      10             : #include "ametsuchi/tx_cache_response.hpp"
      11             : #include "common/visitor.hpp"
      12             : #include "interfaces/commands/command_variant.hpp"
      13             : #include "interfaces/commands/transfer_asset.hpp"
      14             : #include "interfaces/iroha_internal/block.hpp"
      15             : #include "logger/logger.hpp"
      16             : 
      17             : namespace {
      18             :   // Return transfer asset if command contains it
      19             :   boost::optional<const shared_model::interface::TransferAsset &>
      20             :   getTransferAsset(const shared_model::interface::Command &cmd) noexcept {
      21             :     using ReturnType =
      22             :         boost::optional<const shared_model::interface::TransferAsset &>;
      23        5967 :     return iroha::visit_in_place(
      24        5967 :         cmd.get(),
      25             :         [](const shared_model::interface::TransferAsset &c) {
      26          87 :           return ReturnType(c);
      27             :         },
      28             :         [](const auto &) -> ReturnType { return boost::none; });
      29             :   }
      30             : 
      31             :   // make index tx hash -> block where hash is stored
      32             :   std::string makeHashIndex(
      33             :       const shared_model::interface::types::HashType &hash,
      34             :       shared_model::interface::types::HeightType height,
      35             :       size_t index) {
      36        1315 :     boost::format base(
      37             :         "INSERT INTO position_by_hash(hash, height, index) VALUES ('%s', "
      38             :         "'%s', '%s');");
      39        1315 :     return (base % hash.hex() % height % index).str();
      40        1315 :   }
      41             : 
      42             :   std::string makeCommittedTxHashIndex(
      43             :       const shared_model::interface::types::HashType &rejected_tx_hash) {
      44        1315 :     boost::format base(
      45             :         "INSERT INTO tx_status_by_hash(hash, status) VALUES ('%s', "
      46             :         "TRUE);");
      47        1315 :     return (base % rejected_tx_hash.hex()).str();
      48        1315 :   }
      49             : 
      50             :   std::string makeRejectedTxHashIndex(
      51             :       const shared_model::interface::types::HashType &rejected_tx_hash) {
      52          68 :     boost::format base(
      53             :         "INSERT INTO tx_status_by_hash(hash, status) VALUES ('%s', "
      54             :         "FALSE);");
      55          68 :     return (base % rejected_tx_hash.hex()).str();
      56          68 :   }
      57             : 
      58             :   // make index account_id:height -> list of tx indexes
      59             :   // (where tx is placed in the block)
      60             :   std::string makeCreatorHeightIndex(
      61             :       const shared_model::interface::types::AccountIdType creator,
      62             :       shared_model::interface::types::HeightType height,
      63             :       size_t tx_index) {
      64        1315 :     boost::format base(
      65             :         "INSERT INTO index_by_creator_height(creator_id, height, index) VALUES "
      66             :         "('%s', '%s', '%s');");
      67        1315 :     return (base % creator % height % tx_index).str();
      68        1315 :   }
      69             : 
      70             :   // Make index account_id -> list of blocks where his txs exist
      71             :   std::string makeAccountHeightIndex(
      72             :       const shared_model::interface::types::AccountIdType &account_id,
      73             :       shared_model::interface::types::HeightType height) {
      74        1489 :     boost::format base(
      75             :         "INSERT INTO height_by_account_set(account_id, "
      76             :         "height) VALUES "
      77             :         "('%s', '%s');");
      78        1489 :     return (base % account_id % height).str();
      79        1489 :   }
      80             : 
      81             :   // Collect all assets belonging to creator, sender, and receiver
      82             :   // to make account_id:height:asset_id -> list of tx indexes
      83             :   // for transfer asset in command
      84             :   std::string makeAccountAssetIndex(
      85             :       const shared_model::interface::types::AccountIdType &account_id,
      86             :       shared_model::interface::types::HeightType height,
      87             :       size_t index,
      88             :       const shared_model::interface::Transaction::CommandsType &commands) {
      89        1315 :     return std::accumulate(
      90        1315 :         commands.begin(),
      91        1315 :         commands.end(),
      92        1315 :         std::string{},
      93             :         [&](auto query, const auto &cmd) {
      94        5967 :           auto transfer = getTransferAsset(cmd);
      95        5967 :           if (not transfer) {
      96        5880 :             return query;
      97             :           }
      98          87 :           const auto &src_id = transfer.value().srcAccountId();
      99          87 :           const auto &dest_id = transfer.value().destAccountId();
     100             : 
     101          87 :           query += makeAccountHeightIndex(src_id, height);
     102          87 :           query += makeAccountHeightIndex(dest_id, height);
     103             : 
     104        1315 :           const auto ids = {account_id, src_id, dest_id};
     105          87 :           const auto &asset_id = transfer.value().assetId();
     106             :           // flat map accounts to unindexed keys
     107         348 :           for (const auto &id : ids) {
     108         261 :             boost::format base(
     109             :                 "INSERT INTO position_by_account_asset(account_id, "
     110             :                 "height, asset_id, "
     111             :                 "index) "
     112             :                 "VALUES ('%s', '%s', '%s', '%s');");
     113         261 :             query += (base % id % height % asset_id % index).str();
     114         261 :           }
     115          87 :           return query;
     116        5967 :         });
     117           0 :   }
     118             : }  // namespace
     119             : 
     120             : namespace iroha {
     121             :   namespace ametsuchi {
     122             :     PostgresBlockIndex::PostgresBlockIndex(soci::session &sql,
     123             :                                            logger::LoggerPtr log)
     124        1281 :         : sql_(sql), log_(std::move(log)) {}
     125             : 
     126             :     void PostgresBlockIndex::index(
     127             :         const shared_model::interface::Block &block) {
     128        1297 :       auto height = block.height();
     129        1297 :       auto indexed_txs = block.transactions() | boost::adaptors::indexed(0);
     130        1297 :       auto rejected_txs_hashes = block.rejected_transactions_hashes();
     131        1297 :       std::string tx_index_query = std::accumulate(
     132        1297 :           indexed_txs.begin(),
     133        1297 :           indexed_txs.end(),
     134        1297 :           std::string{},
     135             :           [height](auto query, const auto &tx) {
     136        1315 :             const auto &creator_id = tx.value().creatorAccountId();
     137        1315 :             const auto index = tx.index();
     138             : 
     139        1315 :             query += makeAccountHeightIndex(creator_id, height);
     140        1315 :             query += makeAccountAssetIndex(
     141        1315 :                 creator_id, height, index, tx.value().commands());
     142        1315 :             query += makeHashIndex(tx.value().hash(), height, index);
     143        1315 :             query += makeCommittedTxHashIndex(tx.value().hash());
     144        1315 :             query += makeCreatorHeightIndex(creator_id, height, index);
     145        1315 :             return query;
     146           0 :           });
     147             : 
     148             :       std::string rejected_tx_index_query =
     149        1297 :           std::accumulate(rejected_txs_hashes.begin(),
     150        1297 :                           rejected_txs_hashes.end(),
     151        1297 :                           std::string{},
     152             :                           [](auto query, const auto &rejected_tx_hash) {
     153          68 :                             query += makeRejectedTxHashIndex(rejected_tx_hash);
     154          68 :                             return query;
     155           0 :                           });
     156             : 
     157        1297 :       auto index_query = tx_index_query + rejected_tx_index_query;
     158             :       try {
     159        1297 :         sql_ << index_query;
     160        1297 :       } catch (const std::exception &e) {
     161           0 :         log_->error(e.what());
     162           0 :       }
     163        1297 :     }
     164             :   }  // namespace ametsuchi
     165             : }  // namespace iroha

Generated by: LCOV version 1.13