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