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