Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #include <gflags/gflags.h>
7 : #include <rapidjson/istreamwrapper.h>
8 : #include <rapidjson/rapidjson.h>
9 : #include <boost/filesystem.hpp>
10 : #include <iostream>
11 :
12 : #include "backend/protobuf/proto_block_json_converter.hpp"
13 : #include "backend/protobuf/queries/proto_query.hpp"
14 : #include "backend/protobuf/transaction.hpp"
15 : #include "client.hpp"
16 : #include "common/result.hpp"
17 : #include "converters/protobuf/json_proto_converter.hpp"
18 : #include "crypto/keys_manager_impl.hpp"
19 : #include "grpc_response_handler.hpp"
20 : #include "interactive/interactive_cli.hpp"
21 : #include "logger/logger.hpp"
22 : #include "logger/logger_manager.hpp"
23 : #include "model/converters/json_block_factory.hpp"
24 : #include "model/converters/json_query_factory.hpp"
25 : #include "model/converters/pb_block_factory.hpp"
26 : #include "model/converters/pb_query_factory.hpp"
27 : #include "model/converters/pb_transaction_factory.hpp"
28 : #include "model/generators/block_generator.hpp"
29 : #include "model/model_crypto_provider_impl.hpp"
30 :
31 : // Account information
32 : DEFINE_bool(new_account,
33 : false,
34 : "Generate and save locally new public/private keys");
35 : DEFINE_string(account_name,
36 : "",
37 : "Name of the account. Must be unique in iroha network");
38 : DEFINE_string(pass_phrase, "", "Account pass-phrase");
39 : DEFINE_string(key_path, ".", "Path to user keys");
40 :
41 : // Iroha peer to connect with
42 : DEFINE_string(peer_ip, "0.0.0.0", "Address of the Iroha node");
43 : DEFINE_int32(torii_port, 50051, "Port of Iroha's Torii");
44 :
45 : // Send already signed and formed transaction to Iroha peer
46 : DEFINE_string(json_transaction, "", "Transaction in json format");
47 : // Send already signed and formed query to Iroha peer
48 : DEFINE_string(json_query, "", "Query in json format");
49 :
50 : // Genesis block generator:
51 : DEFINE_bool(genesis_block,
52 : false,
53 : "Generate genesis block for new Iroha network");
54 : DEFINE_string(genesis_transaction,
55 : "",
56 : "File with transaction in json format for the genesis block");
57 : DEFINE_string(peers_address,
58 : "",
59 : "File with peers address for new Iroha network");
60 :
61 : // Run iroha-cli in interactive mode
62 : DEFINE_bool(interactive, true, "Run iroha-cli in interactive mode");
63 :
64 : using namespace iroha::protocol;
65 : using namespace iroha::model::generators;
66 : using namespace iroha::model::converters;
67 : using namespace iroha_cli::interactive;
68 : namespace fs = boost::filesystem;
69 :
70 : iroha::keypair_t *makeOldModel(const shared_model::crypto::Keypair &keypair) {
71 0 : return new iroha::keypair_t{
72 0 : iroha::pubkey_t::from_string(toBinaryString(keypair.publicKey())),
73 0 : iroha::privkey_t::from_string(toBinaryString(keypair.privateKey()))};
74 0 : }
75 :
76 : int main(int argc, char *argv[]) {
77 0 : gflags::ParseCommandLineFlags(&argc, &argv, true);
78 0 : gflags::ShutDownCommandLineFlags();
79 0 : auto log_manager = std::make_shared<logger::LoggerManagerTree>(
80 0 : logger::LoggerConfig{logger::LogLevel::kInfo,
81 0 : logger::getDefaultLogPatterns()})
82 0 : ->getChild("CLI");
83 0 : const auto logger = log_manager->getChild("Main")->getLogger();
84 : const auto response_handler_log_manager =
85 0 : log_manager->getChild("ResponseHandler");
86 : const auto pb_qry_factory_log =
87 0 : log_manager->getChild("PbQueryFactory")->getLogger();
88 : const auto json_qry_factory_log =
89 0 : log_manager->getChild("JsonQueryFactory")->getLogger();
90 : const auto keys_manager_log =
91 0 : log_manager->getChild("KeysManager")->getLogger();
92 : // Generate new genesis block now Iroha network
93 0 : if (FLAGS_genesis_block) {
94 : BlockGenerator generator;
95 0 : iroha::model::Transaction transaction;
96 0 : if (FLAGS_genesis_transaction.empty()) {
97 0 : if (FLAGS_peers_address.empty()) {
98 0 : logger->error("--peers_address is empty");
99 0 : return EXIT_FAILURE;
100 : }
101 0 : std::ifstream file(FLAGS_peers_address);
102 0 : std::vector<std::string> peers_address;
103 0 : std::copy(std::istream_iterator<std::string>(file),
104 0 : std::istream_iterator<std::string>(),
105 0 : std::back_inserter(peers_address));
106 : // Generate genesis block
107 0 : transaction = TransactionGenerator().generateGenesisTransaction(
108 0 : 0, std::move(peers_address), keys_manager_log);
109 0 : } else {
110 0 : rapidjson::Document doc;
111 0 : std::ifstream file(FLAGS_genesis_transaction);
112 0 : rapidjson::IStreamWrapper isw(file);
113 0 : doc.ParseStream(isw);
114 0 : auto some_tx = JsonTransactionFactory{}.deserialize(doc);
115 0 : if (some_tx) {
116 0 : transaction = *some_tx;
117 0 : } else {
118 0 : logger->error(
119 0 : "Cannot deserialize genesis transaction (problem with file reading "
120 : "or illformed json?)");
121 0 : return EXIT_FAILURE;
122 : }
123 0 : }
124 :
125 0 : auto block = generator.generateGenesisBlock(0, {transaction});
126 : // Convert to json
127 0 : std::ofstream output_file("genesis.block");
128 0 : auto bl = shared_model::proto::Block(
129 0 : iroha::model::converters::PbBlockFactory().serialize(block).block_v1());
130 :
131 0 : shared_model::proto::ProtoBlockJsonConverter().serialize(bl).match(
132 : [&logger,
133 : &output_file](const iroha::expected::Value<std::string> &json) {
134 0 : output_file << json.value;
135 0 : logger->info("File saved to genesis.block");
136 0 : },
137 : [&logger](const auto &error) {
138 : // should not get here
139 0 : logger->error("error while serializing genesis block");
140 0 : std::exit(EXIT_FAILURE);
141 0 : });
142 0 : }
143 : // Create new pub/priv key, register in Iroha Network
144 0 : else if (FLAGS_new_account) {
145 0 : if (FLAGS_account_name.empty()) {
146 0 : logger->error("No account name specified");
147 0 : return EXIT_FAILURE;
148 : }
149 : auto keysManager =
150 0 : iroha::KeysManagerImpl(FLAGS_account_name, keys_manager_log);
151 0 : if (not(FLAGS_pass_phrase.size() == 0
152 0 : ? keysManager.createKeys()
153 0 : : keysManager.createKeys(FLAGS_pass_phrase))) {
154 0 : logger->error("Keys already exist");
155 0 : return EXIT_FAILURE;
156 : }
157 0 : logger->info(
158 0 : "Public and private key has been generated in current directory");
159 :
160 0 : }
161 : // Send to Iroha Peer json transaction/query
162 0 : else if (not FLAGS_json_transaction.empty() or not FLAGS_json_query.empty()) {
163 0 : iroha_cli::CliClient client(
164 0 : FLAGS_peer_ip, FLAGS_torii_port, pb_qry_factory_log);
165 0 : iroha_cli::GrpcResponseHandler response_handler(
166 0 : response_handler_log_manager);
167 0 : if (not FLAGS_json_transaction.empty()) {
168 0 : logger->info(
169 0 : "Send transaction to {}:{} ", FLAGS_peer_ip, FLAGS_torii_port);
170 : // Read from file
171 0 : std::ifstream file(FLAGS_json_transaction);
172 0 : std::string str((std::istreambuf_iterator<char>(file)),
173 0 : std::istreambuf_iterator<char>());
174 0 : iroha::model::converters::JsonTransactionFactory serializer;
175 0 : auto doc = iroha::model::converters::stringToJson(str);
176 0 : if (not doc) {
177 0 : logger->error("Json has wrong format.");
178 0 : return EXIT_FAILURE;
179 : }
180 0 : auto tx_opt = serializer.deserialize(doc.value());
181 0 : if (not tx_opt) {
182 0 : logger->error("Json transaction has wrong format.");
183 0 : return EXIT_FAILURE;
184 : } else {
185 0 : auto tx = shared_model::proto::Transaction(
186 0 : iroha::model::converters::PbTransactionFactory().serialize(
187 0 : *tx_opt));
188 0 : response_handler.handle(client.sendTx(tx));
189 0 : }
190 0 : }
191 0 : if (not FLAGS_json_query.empty()) {
192 0 : logger->info("Send query to {}:{}", FLAGS_peer_ip, FLAGS_torii_port);
193 0 : std::ifstream file(FLAGS_json_query);
194 0 : std::string str((std::istreambuf_iterator<char>(file)),
195 0 : std::istreambuf_iterator<char>());
196 0 : iroha::model::converters::JsonQueryFactory serializer(
197 0 : json_qry_factory_log);
198 0 : auto query_opt = serializer.deserialize(std::move(str));
199 0 : if (not query_opt) {
200 0 : logger->error("Json has wrong format.");
201 0 : return EXIT_FAILURE;
202 : } else {
203 0 : auto query = shared_model::proto::Query(
204 0 : *iroha::model::converters::PbQueryFactory(pb_qry_factory_log)
205 0 : .serialize(*query_opt));
206 0 : auto response = client.sendQuery(query);
207 0 : response_handler.handle(response);
208 0 : }
209 0 : }
210 0 : }
211 : // Run iroha-cli in interactive mode
212 0 : else if (FLAGS_interactive) {
213 0 : if (FLAGS_account_name.empty()) {
214 0 : logger->error("Specify your account name");
215 0 : return EXIT_FAILURE;
216 : }
217 0 : fs::path path(FLAGS_key_path);
218 0 : if (not fs::exists(path)) {
219 0 : logger->error("Path {} not found.", path.string());
220 0 : return EXIT_FAILURE;
221 : }
222 0 : iroha::KeysManagerImpl manager((path / FLAGS_account_name).string(),
223 0 : keys_manager_log);
224 0 : auto keypair = FLAGS_pass_phrase.size() != 0
225 0 : ? manager.loadKeys(FLAGS_pass_phrase)
226 0 : : manager.loadKeys();
227 0 : if (not keypair) {
228 0 : logger->error(
229 0 : "Cannot load specified keypair, or keypair is invalid. Path: {}, "
230 : "keypair name: {}. Use --key_path with path of your keypair. \n"
231 : "Maybe wrong pass phrase (\"{}\")?",
232 0 : path.string(),
233 0 : FLAGS_account_name,
234 0 : FLAGS_pass_phrase);
235 0 : return EXIT_FAILURE;
236 : }
237 : // TODO 13/09/17 grimadas: Init counters from Iroha, or read from disk?
238 : // IR-334
239 0 : InteractiveCli interactiveCli(
240 0 : FLAGS_account_name,
241 0 : FLAGS_peer_ip,
242 0 : FLAGS_torii_port,
243 : 0,
244 0 : std::make_shared<iroha::model::ModelCryptoProviderImpl>(
245 0 : *std::unique_ptr<iroha::keypair_t>(makeOldModel(*keypair))),
246 0 : response_handler_log_manager,
247 0 : pb_qry_factory_log,
248 0 : json_qry_factory_log,
249 0 : log_manager->getChild("InteractiveCli"));
250 0 : interactiveCli.run();
251 0 : } else {
252 0 : logger->error("Invalid flags");
253 0 : return EXIT_FAILURE;
254 : }
255 0 : return 0;
256 0 : }
|