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