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 374 : : transaction_(o.transaction_),
59 374 : 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 1778 : NextBuilder<Fields> copy = *this;
70 1778 : t(copy.transaction_);
71 1778 : return copy;
72 1778 : }
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 1726 : NextBuilder<Command> copy = *this;
83 1726 : t(copy.transaction_.mutable_payload()
84 1726 : ->mutable_reduced_payload()
85 1726 : ->add_commands());
86 1726 : return copy;
87 1726 : }
88 :
89 : public:
90 : TemplateTransactionBuilder(const SV &validator = SV())
91 1566 : : stateless_validator_(validator) {}
92 :
93 : auto creatorAccountId(
94 : const interface::types::AccountIdType &account_id) const {
95 : return transform<CreatorAccountId>([&](auto &tx) {
96 1579 : tx.mutable_payload()
97 1579 : ->mutable_reduced_payload()
98 1579 : ->set_creator_account_id(account_id);
99 1579 : });
100 : }
101 :
102 : auto batchMeta(interface::types::BatchType type,
103 : std::vector<interface::types::HashType> hashes) const {
104 : return transform<0>([&](auto &tx) {
105 176 : tx.mutable_payload()->mutable_batch()->set_type(
106 : static_cast<
107 : iroha::protocol::Transaction::Payload::BatchMeta::BatchType>(
108 176 : type));
109 665 : for (const auto &hash : hashes) {
110 489 : tx.mutable_payload()->mutable_batch()->add_reduced_hashes(
111 489 : hash.hex());
112 : }
113 176 : });
114 : }
115 :
116 : auto createdTime(interface::types::TimestampType created_time) const {
117 : return transform<CreatedTime>([&](auto &tx) {
118 1432 : tx.mutable_payload()->mutable_reduced_payload()->set_created_time(
119 1432 : created_time);
120 1432 : });
121 : }
122 :
123 : auto quorum(interface::types::QuorumType quorum) const {
124 : return transform<Quorum>([&](auto &tx) {
125 1405 : tx.mutable_payload()->mutable_reduced_payload()->set_quorum(quorum);
126 1405 : });
127 : }
128 :
129 : auto addAssetQuantity(const interface::types::AssetIdType &asset_id,
130 : const std::string &amount) const {
131 : return addCommand([&](auto proto_command) {
132 131 : auto command = proto_command->mutable_add_asset_quantity();
133 131 : command->set_asset_id(asset_id);
134 131 : command->set_amount(amount);
135 131 : });
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(peer_key.hex());
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 99 : auto command = proto_command->mutable_add_signatory();
152 99 : command->set_account_id(account_id);
153 99 : command->set_public_key(public_key.hex());
154 99 : });
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 13 : auto command = proto_command->mutable_remove_signatory();
162 13 : command->set_account_id(account_id);
163 13 : command->set_public_key(public_key.hex());
164 13 : });
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 584 : auto command = proto_command->mutable_append_role();
171 584 : command->set_account_id(account_id);
172 584 : command->set_role_name(role_name);
173 584 : });
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 407 : auto command = proto_command->mutable_create_asset();
181 407 : command->set_asset_name(asset_name);
182 407 : command->set_domain_id(domain_id);
183 407 : command->set_precision(precision);
184 407 : });
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 669 : auto command = proto_command->mutable_create_account();
193 669 : command->set_account_name(account_name);
194 669 : command->set_domain_id(domain_id);
195 669 : command->set_public_key(main_pubkey.hex());
196 669 : });
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 341 : auto command = proto_command->mutable_create_domain();
204 341 : command->set_domain_id(domain_id);
205 341 : command->set_default_role(default_role);
206 341 : });
207 : }
208 :
209 : auto createRole(const interface::types::RoleIdType &role_name,
210 : const interface::RolePermissionSet &permissions) const {
211 : return addCommand([&](auto proto_command) {
212 873 : auto command = proto_command->mutable_create_role();
213 873 : command->set_role_name(role_name);
214 40158 : for (size_t i = 0; i < permissions.size(); ++i) {
215 39285 : auto perm = static_cast<interface::permissions::Role>(i);
216 39285 : if (permissions.test(perm)) {
217 11706 : command->add_permissions(permissions::toTransport(perm));
218 11706 : }
219 39285 : }
220 873 : });
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 576 : auto command = proto_command->mutable_detach_role();
227 576 : command->set_account_id(account_id);
228 576 : command->set_role_name(role_name);
229 576 : });
230 : }
231 :
232 : auto grantPermission(const interface::types::AccountIdType &account_id,
233 : interface::permissions::Grantable permission) const {
234 : return addCommand([&](auto proto_command) {
235 26 : auto command = proto_command->mutable_grant_permission();
236 26 : command->set_account_id(account_id);
237 26 : command->set_permission(permissions::toTransport(permission));
238 26 : });
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 10 : auto command = proto_command->mutable_revoke_permission();
246 10 : command->set_account_id(account_id);
247 10 : command->set_permission(permissions::toTransport(permission));
248 10 : });
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 68 : auto command = proto_command->mutable_set_account_detail();
257 68 : command->set_account_id(account_id);
258 68 : command->set_key(key);
259 68 : command->set_value(value);
260 68 : });
261 : }
262 :
263 : auto setAccountQuorum(const interface::types::AddressType &account_id,
264 : interface::types::QuorumType quorum) const {
265 : return addCommand([&](auto proto_command) {
266 286 : auto command = proto_command->mutable_set_account_quorum();
267 286 : command->set_account_id(account_id);
268 286 : command->set_quorum(quorum);
269 286 : });
270 : }
271 :
272 : auto subtractAssetQuantity(const interface::types::AssetIdType &asset_id,
273 : const std::string &amount) const {
274 : return addCommand([&](auto proto_command) {
275 6 : auto command = proto_command->mutable_subtract_asset_quantity();
276 6 : command->set_asset_id(asset_id);
277 6 : command->set_amount(amount);
278 6 : });
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 101 : auto command = proto_command->mutable_transfer_asset();
288 101 : command->set_src_account_id(src_account_id);
289 101 : command->set_dest_account_id(dest_account_id);
290 101 : command->set_asset_id(asset_id);
291 101 : command->set_description(description);
292 101 : command->set_amount(amount);
293 101 : });
294 : }
295 :
296 : auto build() const {
297 : static_assert(S == (1 << TOTAL) - 1, "Required fields are not set");
298 1678 : auto result = Transaction(iroha::protocol::Transaction(transaction_));
299 1678 : auto answer = stateless_validator_.validate(result);
300 1678 : if (answer.hasErrors()) {
301 1 : throw std::invalid_argument(answer.reason());
302 : }
303 1677 : return BT(std::move(result));
304 1677 : }
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
|