hyperledger/iroha
Iroha - A simple, decentralized ledger http://iroha.tech
transaction_validator.hpp
Go to the documentation of this file.
1 
6 #ifndef IROHA_SHARED_MODEL_TRANSACTION_VALIDATOR_HPP
7 #define IROHA_SHARED_MODEL_TRANSACTION_VALIDATOR_HPP
8 
9 #include <boost/format.hpp>
10 #include <boost/variant.hpp>
11 
33 #include "validators/answer.hpp"
34 
35 namespace shared_model {
36  namespace validation {
37 
44  template <typename FieldValidator>
46  : public boost::static_visitor<ReasonsGroupType> {
48  : validator_(std::move(validator)) {}
49 
50  public:
53  delete;
54 
55  CommandValidatorVisitor(std::shared_ptr<ValidatorsConfig> config)
56  : CommandValidatorVisitor(FieldValidator{std::move(config)}) {}
57 
59  const interface::AddAssetQuantity &aaq) const {
60  ReasonsGroupType reason;
61  addInvalidCommand(reason, "AddAssetQuantity");
62 
63  validator_.validateAssetId(reason, aaq.assetId());
64  validator_.validateAmount(reason, aaq.amount());
65 
66  return reason;
67  }
68 
70  ReasonsGroupType reason;
71  addInvalidCommand(reason, "AddPeer");
72 
73  validator_.validatePeer(reason, ap.peer());
74 
75  return reason;
76  }
77 
79  ReasonsGroupType reason;
80  addInvalidCommand(reason, "AddSignatory");
81 
82  validator_.validateAccountId(reason, as.accountId());
83  validator_.validatePubkey(reason, as.pubkey());
84 
85  return reason;
86  }
87 
89  ReasonsGroupType reason;
90  addInvalidCommand(reason, "AppendRole");
91 
92  validator_.validateAccountId(reason, ar.accountId());
93  validator_.validateRoleId(reason, ar.roleName());
94 
95  return reason;
96  }
97 
99  ReasonsGroupType reason;
100  addInvalidCommand(reason, "CreateAccount");
101 
102  validator_.validatePubkey(reason, ca.pubkey());
103  validator_.validateAccountName(reason, ca.accountName());
104  validator_.validateDomainId(reason, ca.domainId());
105 
106  return reason;
107  }
108 
110  ReasonsGroupType reason;
111  addInvalidCommand(reason, "CreateAsset");
112 
113  validator_.validateAssetName(reason, ca.assetName());
114  validator_.validateDomainId(reason, ca.domainId());
115  validator_.validatePrecision(reason, ca.precision());
116 
117  return reason;
118  }
119 
121  ReasonsGroupType reason;
122  addInvalidCommand(reason, "CreateDomain");
123 
124  validator_.validateDomainId(reason, cd.domainId());
125  validator_.validateRoleId(reason, cd.userDefaultRole());
126 
127  return reason;
128  }
129 
131  ReasonsGroupType reason;
132  addInvalidCommand(reason, "CreateRole");
133 
134  validator_.validateRoleId(reason, cr.roleName());
135  cr.rolePermissions().iterate([&reason, this](auto i) {
136  validator_.validateRolePermission(reason, i);
137  });
138 
139  return reason;
140  }
141 
143  ReasonsGroupType reason;
144  addInvalidCommand(reason, "DetachRole");
145 
146  validator_.validateAccountId(reason, dr.accountId());
147  validator_.validateRoleId(reason, dr.roleName());
148 
149  return reason;
150  }
151 
153  ReasonsGroupType reason;
154  addInvalidCommand(reason, "GrantPermission");
155 
156  validator_.validateAccountId(reason, gp.accountId());
157  validator_.validateGrantablePermission(reason, gp.permissionName());
158 
159  return reason;
160  }
161 
163  ReasonsGroupType reason;
164  addInvalidCommand(reason, "RemovePeer");
165 
166  validator_.validatePubkey(reason, rp.pubkey());
167 
168  return reason;
169  }
170 
172  ReasonsGroupType reason;
173  addInvalidCommand(reason, "RemoveSignatory");
174 
175  validator_.validateAccountId(reason, rs.accountId());
176  validator_.validatePubkey(reason, rs.pubkey());
177 
178  return reason;
179  }
181  ReasonsGroupType reason;
182  addInvalidCommand(reason, "RevokePermission");
183 
184  validator_.validateAccountId(reason, rp.accountId());
185  validator_.validateGrantablePermission(reason, rp.permissionName());
186 
187  return reason;
188  }
189 
191  const interface::SetAccountDetail &sad) const {
192  ReasonsGroupType reason;
193  addInvalidCommand(reason, "SetAccountDetail");
194 
195  validator_.validateAccountId(reason, sad.accountId());
196  validator_.validateAccountDetailKey(reason, sad.key());
197  validator_.validateAccountDetailValue(reason, sad.value());
198 
199  return reason;
200  }
201 
203  ReasonsGroupType reason;
204  addInvalidCommand(reason, "SetQuorum");
205 
206  validator_.validateAccountId(reason, sq.accountId());
207  validator_.validateQuorum(reason, sq.newQuorum());
208 
209  return reason;
210  }
211 
213  const interface::SubtractAssetQuantity &saq) const {
214  ReasonsGroupType reason;
215  addInvalidCommand(reason, "SubtractAssetQuantity");
216 
217  validator_.validateAssetId(reason, saq.assetId());
218  validator_.validateAmount(reason, saq.amount());
219 
220  return reason;
221  }
222 
224  ReasonsGroupType reason;
225  addInvalidCommand(reason, "TransferAsset");
226 
227  if (ta.srcAccountId() == ta.destAccountId()) {
228  reason.second.emplace_back(
229  "Source and destination accounts cannot be the same");
230  }
231 
232  validator_.validateAccountId(reason, ta.srcAccountId());
233  validator_.validateAccountId(reason, ta.destAccountId());
234  validator_.validateAssetId(reason, ta.assetId());
235  validator_.validateAmount(reason, ta.amount());
236  validator_.validateDescription(reason, ta.description());
237 
238  return reason;
239  }
240 
242  const interface::CompareAndSetAccountDetail &casad) const {
243  ReasonsGroupType reason;
244  addInvalidCommand(reason, "CompareAndSetAccountDetail");
245 
246  using iroha::operator|;
247 
248  validator_.validateAccountId(reason, casad.accountId());
249  validator_.validateAccountDetailKey(reason, casad.key());
250  validator_.validateAccountDetailValue(reason, casad.value());
251  casad.oldValue() | [&reason, this](const auto &oldValue) {
252  this->validator_.validateOldAccountDetailValue(reason, oldValue);
253  };
254 
255  return reason;
256  }
257 
258  private:
259  FieldValidator validator_;
260  mutable int command_counter{0};
261 
262  // adds command to a reason, appends and increments counter
263  void addInvalidCommand(ReasonsGroupType &reason,
264  const std::string &command_name) const {
265  reason.first =
266  (boost::format("%d %s") % command_counter % command_name).str();
267  command_counter++;
268  }
269  };
270 
276  template <typename FieldValidator, typename CommandValidator>
278  : public AbstractValidator<interface::Transaction> {
279  private:
280  template <typename CreatedTimeValidator>
281  Answer validateImpl(const interface::Transaction &tx,
282  CreatedTimeValidator &&validator) const {
283  Answer answer;
284  std::string tx_reason_name = "Transaction";
285  ReasonsGroupType tx_reason(tx_reason_name, GroupedReasons());
286 
287  if (tx.commands().empty()) {
288  tx_reason.second.push_back(
289  "Transaction should contain at least one command");
290  }
291 
292  field_validator_.validateCreatorAccountId(tx_reason,
293  tx.creatorAccountId());
294  std::forward<CreatedTimeValidator>(validator)(tx_reason,
295  tx.createdTime());
296  field_validator_.validateQuorum(tx_reason, tx.quorum());
297  if (tx.batchMeta() != boost::none)
298  field_validator_.validateBatchMeta(tx_reason, **tx.batchMeta());
299 
300  if (not tx_reason.second.empty()) {
301  answer.addReason(std::move(tx_reason));
302  }
303 
304  for (const auto &command : tx.commands()) {
305  auto reason = boost::apply_visitor(
306  CommandValidator(validators_config_), command.get());
307  if (not reason.second.empty()) {
308  answer.addReason(std::move(reason));
309  }
310  }
311 
312  return answer;
313  }
314 
315  explicit TransactionValidator(const FieldValidator &field_validator)
316  : field_validator_(field_validator) {}
317 
318  public:
319  explicit TransactionValidator(std::shared_ptr<ValidatorsConfig> config)
321 
327  Answer validate(const interface::Transaction &tx) const override {
328  return validateImpl(tx, [this](auto &reason, auto time) {
329  field_validator_.validateCreatedTime(reason, time);
330  });
331  }
332 
338  interface::types::TimestampType current_timestamp) const {
339  return validateImpl(tx,
340  [this, current_timestamp](auto &reason, auto time) {
341  field_validator_.validateCreatedTime(
342  reason, time, current_timestamp);
343  });
344  }
345 
346  protected:
348  std::shared_ptr<ValidatorsConfig> validators_config_;
349  };
350 
351  } // namespace validation
352 } // namespace shared_model
353 
354 #endif // IROHA_SHARED_MODEL_TRANSACTION_VALIDATOR_HPP
Definition: compare_and_set_account_detail.hpp:21
virtual const types::AccountIdType & accountId() const =0
virtual const types::RoleIdType & roleName() const =0
Definition: add_signatory.hpp:19
virtual const types::AccountIdType & srcAccountId() const =0
ReasonsGroupType operator()(const interface::RevokePermission &rp) const
Definition: transaction_validator.hpp:180
void validateAssetName(ReasonsGroupType &reason, const interface::types::AssetNameType &asset_name) const
Definition: field_validator.cpp:178
virtual const interface::types::PubkeyType & pubkey() const =0
void validateRolePermission(ReasonsGroupType &reason, const interface::permissions::Role &permission) const
Definition: field_validator.cpp:243
void validateAmount(ReasonsGroupType &reason, const interface::Amount &amount) const
Definition: field_validator.cpp:106
virtual const interface::Peer & peer() const =0
void validateDescription(ReasonsGroupType &reason, const interface::types::DescriptionType &description) const
Definition: field_validator.cpp:357
ReasonsGroupType operator()(const interface::CreateRole &cr) const
Definition: transaction_validator.hpp:130
virtual const types::AccountIdType & destAccountId() const =0
virtual types::QuorumType quorum() const =0
void validateAccountId(ReasonsGroupType &reason, const interface::types::AccountIdType &account_id) const
Definition: field_validator.cpp:75
Definition: set_quorum.hpp:18
ReasonsGroupType operator()(const interface::DetachRole &dr) const
Definition: transaction_validator.hpp:142
virtual const types::AccountIdType & accountId() const =0
std::shared_ptr< ValidatorsConfig > validators_config_
Definition: transaction_validator.hpp:348
void validateAccountDetailValue(ReasonsGroupType &reason, const interface::types::AccountDetailValueType &value) const
Definition: field_validator.cpp:203
ReasonsGroupType operator()(const interface::GrantPermission &gp) const
Definition: transaction_validator.hpp:152
void addReason(ReasonsGroupType &&reasons)
Definition: answer.hpp:64
Definition: subtract_asset_quantity.hpp:20
virtual const types::AccountDetailValueType & value() const =0
CommandValidatorVisitor & operator=(const CommandValidatorVisitor &)=delete
Definition: abstract_validator.hpp:16
void validatePubkey(ReasonsGroupType &reason, const interface::types::PubkeyType &pubkey) const
Definition: field_validator.cpp:117
ReasonsGroupType operator()(const interface::TransferAsset &ta) const
Definition: transaction_validator.hpp:223
virtual const types::AccountIdType & accountId() const =0
void validateOldAccountDetailValue(ReasonsGroupType &reason, const boost::optional< interface::types::AccountDetailValueType > &old_value) const
Definition: field_validator.cpp:215
void validatePrecision(ReasonsGroupType &reason, const interface::types::PrecisionType &precision) const
Definition: field_validator.cpp:224
Definition: detach_role.hpp:19
void validateQuorum(ReasonsGroupType &reason, const interface::types::QuorumType &quorum) const
Definition: field_validator.cpp:260
virtual const types::AccountIdType & accountId() const =0
void validateGrantablePermission(ReasonsGroupType &reason, const interface::permissions::Grantable &permission) const
Definition: field_validator.cpp:251
Definition: remove_signatory.hpp:18
Definition: create_asset.hpp:18
ReasonsGroupType operator()(const interface::SubtractAssetQuantity &saq) const
Definition: transaction_validator.hpp:212
virtual const Amount & amount() const =0
virtual const types::AssetIdType & assetId() const =0
void validateAssetId(ReasonsGroupType &reason, const interface::types::AssetIdType &asset_id) const
Definition: field_validator.cpp:88
void iterate(std::function< void(Perm)> f) const
Definition: permissions.cpp:138
ReasonsGroupType operator()(const interface::AppendRole &ar) const
Definition: transaction_validator.hpp:88
Definition: remove_peer.hpp:20
virtual const RolePermissionSet & rolePermissions() const =0
virtual const types::AccountIdType & accountId() const =0
ReasonsGroupType operator()(const interface::SetAccountDetail &sad) const
Definition: transaction_validator.hpp:190
ReasonsGroupType operator()(const interface::CompareAndSetAccountDetail &casad) const
Definition: transaction_validator.hpp:241
Definition: append_role.hpp:19
Definition: transfer_asset.hpp:19
virtual types::TimestampType createdTime() const =0
virtual const types::AssetIdType & assetId() const =0
virtual const types::AccountNameType & accountName() const =0
Answer validate(const interface::Transaction &tx, interface::types::TimestampType current_timestamp) const
Definition: transaction_validator.hpp:337
ReasonsGroupType operator()(const interface::RemoveSignatory &rs) const
Definition: transaction_validator.hpp:171
void validateDomainId(ReasonsGroupType &reason, const interface::types::DomainIdType &domain_id) const
Definition: field_validator.cpp:166
virtual const types::RoleIdType & roleName() const =0
void validateRoleId(ReasonsGroupType &reason, const interface::types::RoleIdType &role_id) const
Definition: field_validator.cpp:141
virtual const types::AccountIdType & accountId() const =0
virtual const PrecisionType & precision() const =0
ReasonsGroupType operator()(const interface::SetQuorum &sq) const
Definition: transaction_validator.hpp:202
ReasonsGroupType operator()(const interface::CreateAsset &ca) const
Definition: transaction_validator.hpp:109
virtual const types::AccountDetailValueType & value() const =0
virtual const types::RoleIdType & roleName() const =0
Answer validate(const interface::Transaction &tx) const override
Definition: transaction_validator.hpp:327
TransactionValidator(std::shared_ptr< ValidatorsConfig > config)
Definition: transaction_validator.hpp:319
virtual const Amount & amount() const =0
virtual const types::AccountDetailKeyType & key() const =0
Definition: create_domain.hpp:18
virtual types::QuorumType newQuorum() const =0
virtual permissions::Grantable permissionName() const =0
Definition: create_account.hpp:19
virtual const types::PubkeyType & pubkey() const =0
virtual const types::DomainIdType & domainId() const =0
virtual const boost::optional< types::AccountDetailValueType > oldValue() const =0
ReasonsGroupType operator()(const interface::CreateAccount &ca) const
Definition: transaction_validator.hpp:98
Definition: grant_permission.hpp:19
ReasonsGroupType operator()(const interface::AddPeer &ap) const
Definition: transaction_validator.hpp:69
virtual const types::RoleIdType & userDefaultRole() const =0
Definition: set_account_detail.hpp:19
virtual const types::AccountDetailKeyType & key() const =0
ReasonsGroupType operator()(const interface::CreateDomain &cd) const
Definition: transaction_validator.hpp:120
virtual CommandsType commands() const =0
Definition: field_validator.hpp:35
virtual const types::AssetNameType & assetName() const =0
Definition: revoke_permission.hpp:19
virtual const types::DescriptionType & description() const =0
virtual const types::AccountIdType & accountId() const =0
Definition: transaction_validator.hpp:45
Definition: transaction_validator.hpp:277
ReasonsGroupType operator()(const interface::AddAssetQuantity &aaq) const
Definition: transaction_validator.hpp:58
std::vector< ConcreteReasonType > GroupedReasons
Definition: answer.hpp:20
virtual const types::AccountIdType & accountId() const =0
Definition: add_asset_quantity.hpp:20
void validateAccountDetailKey(ReasonsGroupType &reason, const interface::types::AccountDetailKeyType &key) const
Definition: field_validator.cpp:191
virtual boost::optional< std::shared_ptr< BatchMeta > > batchMeta() const =0
ReasonsGroupType operator()(const interface::AddSignatory &as) const
Definition: transaction_validator.hpp:78
virtual const Amount & amount() const =0
virtual const types::DomainIdType & domainId() const =0
virtual const types::PubkeyType & pubkey() const =0
std::pair< ReasonsGroupName, GroupedReasons > ReasonsGroupType
Definition: answer.hpp:22
Definition: create_role.hpp:19
virtual const types::AccountIdType & creatorAccountId() const =0
Definition: command_executor.hpp:12
FieldValidator field_validator_
Definition: transaction_validator.hpp:347
virtual permissions::Grantable permissionName() const =0
virtual const types::AccountIdType & accountId() const =0
Definition: transaction.hpp:23
virtual const types::DomainIdType & domainId() const =0
void validateAccountName(ReasonsGroupType &reason, const interface::types::AccountNameType &account_name) const
Definition: field_validator.cpp:153
ReasonsGroupType operator()(const interface::RemovePeer &rp) const
Definition: transaction_validator.hpp:162
Definition: add_peer.hpp:20
Definition: answer.hpp:28
CommandValidatorVisitor(std::shared_ptr< ValidatorsConfig > config)
Definition: transaction_validator.hpp:55
void validatePeer(ReasonsGroupType &reason, const interface::Peer &peer) const
Definition: field_validator.cpp:100
uint64_t TimestampType
Type of timestamp.
Definition: types.hpp:64
virtual const types::PubkeyType & pubkey() const =0
virtual const types::AssetIdType & assetId() const =0