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
|