Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #ifndef IROHA_PROTO_TRANSACTION_BUILDER_TEMPLATE_HPP
7 : #define IROHA_PROTO_TRANSACTION_BUILDER_TEMPLATE_HPP
8 :
9 : #include "backend/protobuf/transaction.hpp"
10 :
11 : #include <boost/range/algorithm/for_each.hpp>
12 :
13 : #include "commands.pb.h"
14 : #include "primitive.pb.h"
15 : #include "transaction.pb.h"
16 :
17 : #include "backend/protobuf/permissions.hpp"
18 : #include "builders/protobuf/unsigned_proto.hpp"
19 : #include "interfaces/common_objects/types.hpp"
20 : #include "interfaces/permissions.hpp"
21 : #include "validators/default_validator.hpp"
22 :
23 : namespace shared_model {
24 : namespace proto {
25 :
26 : /**
27 : * Template tx builder for creating new types of transaction builders by
28 : * means of replacing template parameters
29 : * @tparam S -- field counter for checking that all required fields are set
30 : * @tparam SV -- stateless validator called when build method is invoked
31 : * @tparam BT -- build type of built object returned by build method
32 : */
33 : template <int S = 0,
34 : typename SV = validation::DefaultUnsignedTransactionValidator,
35 : typename BT = UnsignedWrapper<Transaction>>
36 : class DEPRECATED TemplateTransactionBuilder {
37 : private:
38 : template <int, typename, typename>
39 : friend class TemplateTransactionBuilder;
40 :
41 : enum RequiredFields {
42 : Command,
43 : CreatorAccountId,
44 : CreatedTime,
45 : Quorum,
46 : TOTAL
47 : };
48 :
49 : template <int s>
50 : using NextBuilder = TemplateTransactionBuilder<S | (1 << s), SV, BT>;
51 :
52 : using ProtoTx = iroha::protocol::Transaction;
53 : using ProtoCommand = iroha::protocol::Command;
54 :
55 : template <int Sp>
56 : TemplateTransactionBuilder(
57 : const TemplateTransactionBuilder<Sp, SV, BT> &o)
58 383 : : transaction_(o.transaction_),
59 383 : stateless_validator_(o.stateless_validator_) {}
60 :
61 : /**
62 : * Make transformation on copied content
63 : * @tparam Transformation - callable type for changing the copy
64 : * @param f - transform function for proto object
65 : * @return new builder with updated state
66 : */
67 : template <int Fields, typename Transformation>
68 : auto transform(Transformation t) const {
69 5816 : NextBuilder<Fields> copy = *this;
70 5816 : t(copy.transaction_);
71 5816 : return copy;
72 5816 : }
73 :
74 : /**
75 : * Make add command transformation on copied object
76 : * @tparam Transformation - callable type for changing command
77 : * @param f - transform function for proto command
78 : * @return new builder with added command
79 : */
80 : template <typename Transformation>
81 : auto addCommand(Transformation t) const {
82 5969 : NextBuilder<Command> copy = *this;
83 5969 : t(copy.transaction_.mutable_payload()
84 5969 : ->mutable_reduced_payload()
85 5969 : ->add_commands());
86 5969 : return copy;
87 5969 : }
88 :
89 : public:
90 : TemplateTransactionBuilder(const SV &validator = SV())
91 6420 : : stateless_validator_(validator) {}
92 :
93 : auto creatorAccountId(
94 : const interface::types::AccountIdType &account_id) const {
95 : return transform<CreatorAccountId>([&](auto &tx) {
96 5627 : tx.mutable_payload()
97 5627 : ->mutable_reduced_payload()
98 5627 : ->set_creator_account_id(account_id);
99 5627 : });
100 : }
101 :
102 : auto batchMeta(interface::types::BatchType type,
103 : std::vector<interface::types::HashType> hashes) const {
104 : return transform<0>([&](auto &tx) {
105 2190 : tx.mutable_payload()->mutable_batch()->set_type(
106 : static_cast<
107 : iroha::protocol::Transaction::Payload::BatchMeta::BatchType>(
108 2190 : type));
109 4781 : for (const auto &hash : hashes) {
110 2591 : tx.mutable_payload()->mutable_batch()->add_reduced_hashes(
111 2591 : crypto::toBinaryString(hash));
112 : }
113 2190 : });
114 : }
115 :
116 : auto createdTime(interface::types::TimestampType created_time) const {
117 : return transform<CreatedTime>([&](auto &tx) {
118 5421 : tx.mutable_payload()->mutable_reduced_payload()->set_created_time(
119 5421 : created_time);
120 5421 : });
121 : }
122 :
123 : auto quorum(interface::types::QuorumType quorum) const {
124 : return transform<Quorum>([&](auto &tx) {
125 5427 : tx.mutable_payload()->mutable_reduced_payload()->set_quorum(quorum);
126 5427 : });
127 : }
128 :
129 : auto addAssetQuantity(const interface::types::AssetIdType &asset_id,
130 : const std::string &amount) const {
131 : return addCommand([&](auto proto_command) {
132 144 : auto command = proto_command->mutable_add_asset_quantity();
133 144 : command->set_asset_id(asset_id);
134 144 : command->set_amount(amount);
135 144 : });
136 : }
137 :
138 : auto addPeer(const interface::types::AddressType &address,
139 : const interface::types::PubkeyType &peer_key) const {
140 : return addCommand([&](auto proto_command) {
141 261 : auto command = proto_command->mutable_add_peer();
142 261 : auto peer = command->mutable_peer();
143 261 : peer->set_address(address);
144 261 : peer->set_peer_key(crypto::toBinaryString(peer_key));
145 261 : });
146 : }
147 :
148 : auto addSignatory(const interface::types::AccountIdType &account_id,
149 : const interface::types::PubkeyType &public_key) const {
150 : return addCommand([&](auto proto_command) {
151 115 : auto command = proto_command->mutable_add_signatory();
152 115 : command->set_account_id(account_id);
153 115 : command->set_public_key(crypto::toBinaryString(public_key));
154 115 : });
155 : }
156 :
157 : auto removeSignatory(
158 : const interface::types::AccountIdType &account_id,
159 : const interface::types::PubkeyType &public_key) const {
160 : return addCommand([&](auto proto_command) {
161 21 : auto command = proto_command->mutable_remove_signatory();
162 21 : command->set_account_id(account_id);
163 21 : command->set_public_key(crypto::toBinaryString(public_key));
164 21 : });
165 : }
166 :
167 : auto appendRole(const interface::types::AccountIdType &account_id,
168 : const interface::types::RoleIdType &role_name) const {
169 : return addCommand([&](auto proto_command) {
170 670 : auto command = proto_command->mutable_append_role();
171 670 : command->set_account_id(account_id);
172 670 : command->set_role_name(role_name);
173 670 : });
174 : }
175 :
176 : auto createAsset(const interface::types::AssetNameType &asset_name,
177 : const interface::types::DomainIdType &domain_id,
178 : interface::types::PrecisionType precision) const {
179 : return addCommand([&](auto proto_command) {
180 440 : auto command = proto_command->mutable_create_asset();
181 440 : command->set_asset_name(asset_name);
182 440 : command->set_domain_id(domain_id);
183 440 : command->set_precision(precision);
184 440 : });
185 : }
186 :
187 : auto createAccount(
188 : const interface::types::AccountNameType &account_name,
189 : const interface::types::DomainIdType &domain_id,
190 : const interface::types::PubkeyType &main_pubkey) const {
191 : return addCommand([&](auto proto_command) {
192 872 : auto command = proto_command->mutable_create_account();
193 872 : command->set_account_name(account_name);
194 872 : command->set_domain_id(domain_id);
195 872 : command->set_public_key(crypto::toBinaryString(main_pubkey));
196 872 : });
197 : }
198 :
199 : auto createDomain(
200 : const interface::types::DomainIdType &domain_id,
201 : const interface::types::RoleIdType &default_role) const {
202 : return addCommand([&](auto proto_command) {
203 509 : auto command = proto_command->mutable_create_domain();
204 509 : command->set_domain_id(domain_id);
205 509 : command->set_default_role(default_role);
206 509 : });
207 : }
208 :
209 : auto createRole(const interface::types::RoleIdType &role_name,
210 : const interface::RolePermissionSet &permissions) const {
211 : return addCommand([&](auto proto_command) {
212 1076 : auto command = proto_command->mutable_create_role();
213 1076 : command->set_role_name(role_name);
214 47344 : for (size_t i = 0; i < permissions.size(); ++i) {
215 46268 : auto perm = static_cast<interface::permissions::Role>(i);
216 46268 : if (permissions.test(perm)) {
217 13266 : command->add_permissions(permissions::toTransport(perm));
218 13266 : }
219 46268 : }
220 1076 : });
221 : }
222 :
223 : auto detachRole(const interface::types::AccountIdType &account_id,
224 : const interface::types::RoleIdType &role_name) const {
225 : return addCommand([&](auto proto_command) {
226 572 : auto command = proto_command->mutable_detach_role();
227 572 : command->set_account_id(account_id);
228 572 : command->set_role_name(role_name);
229 572 : });
230 : }
231 :
232 : auto grantPermission(const interface::types::AccountIdType &account_id,
233 : interface::permissions::Grantable permission) const {
234 : return addCommand([&](auto proto_command) {
235 35 : auto command = proto_command->mutable_grant_permission();
236 35 : command->set_account_id(account_id);
237 35 : command->set_permission(permissions::toTransport(permission));
238 35 : });
239 : }
240 :
241 : auto revokePermission(
242 : const interface::types::AccountIdType &account_id,
243 : interface::permissions::Grantable permission) const {
244 : return addCommand([&](auto proto_command) {
245 11 : auto command = proto_command->mutable_revoke_permission();
246 11 : command->set_account_id(account_id);
247 11 : command->set_permission(permissions::toTransport(permission));
248 11 : });
249 : }
250 :
251 : auto setAccountDetail(
252 : const interface::types::AccountIdType &account_id,
253 : const interface::types::AccountDetailKeyType &key,
254 : const interface::types::AccountDetailValueType &value) const {
255 : return addCommand([&](auto proto_command) {
256 94 : auto command = proto_command->mutable_set_account_detail();
257 94 : command->set_account_id(account_id);
258 94 : command->set_key(key);
259 94 : command->set_value(value);
260 94 : });
261 : }
262 :
263 : auto setAccountQuorum(const interface::types::AddressType &account_id,
264 : interface::types::QuorumType quorum) const {
265 : return addCommand([&](auto proto_command) {
266 4322 : auto command = proto_command->mutable_set_account_quorum();
267 4322 : command->set_account_id(account_id);
268 4322 : command->set_quorum(quorum);
269 4322 : });
270 : }
271 :
272 : auto subtractAssetQuantity(const interface::types::AssetIdType &asset_id,
273 : const std::string &amount) const {
274 : return addCommand([&](auto proto_command) {
275 11 : auto command = proto_command->mutable_subtract_asset_quantity();
276 11 : command->set_asset_id(asset_id);
277 11 : command->set_amount(amount);
278 11 : });
279 : }
280 :
281 : auto transferAsset(const interface::types::AccountIdType &src_account_id,
282 : const interface::types::AccountIdType &dest_account_id,
283 : const interface::types::AssetIdType &asset_id,
284 : const interface::types::DescriptionType &description,
285 : const std::string &amount) const {
286 : return addCommand([&](auto proto_command) {
287 105 : auto command = proto_command->mutable_transfer_asset();
288 105 : command->set_src_account_id(src_account_id);
289 105 : command->set_dest_account_id(dest_account_id);
290 105 : command->set_asset_id(asset_id);
291 105 : command->set_description(description);
292 105 : command->set_amount(amount);
293 105 : });
294 : }
295 :
296 : auto build() const {
297 : static_assert(S == (1 << TOTAL) - 1, "Required fields are not set");
298 6516 : auto result = Transaction(iroha::protocol::Transaction(transaction_));
299 6516 : auto answer = stateless_validator_.validate(result);
300 6518 : if (answer.hasErrors()) {
301 1 : throw std::invalid_argument(answer.reason());
302 : }
303 6517 : return BT(std::move(result));
304 6517 : }
305 :
306 : static const int total = RequiredFields::TOTAL;
307 :
308 : private:
309 : ProtoTx transaction_;
310 : SV stateless_validator_;
311 : };
312 :
313 : } // namespace proto
314 : } // namespace shared_model
315 :
316 : #endif // IROHA_PROTO_TRANSACTION_BUILDER_TEMPLATE_HPP
|