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/range/adaptor/indexed.hpp>
10 #include <boost/variant.hpp>
11 
12 #include "common/bind.hpp"
38 
39 namespace shared_model {
40  namespace validation {
41 
42  struct ValidatorsConfig;
43 
50  template <typename FieldValidator>
52  : public boost::static_visitor<std::optional<ValidationError>> {
54  : validator_(std::move(validator)) {}
55 
56  public:
57  CommandValidatorVisitor(std::shared_ptr<ValidatorsConfig> config)
58  : CommandValidatorVisitor(FieldValidator{std::move(config)}) {}
59 
60  std::optional<ValidationError> operator()(
61  const interface::AddAssetQuantity &add_asset_quantity) const {
62  return aggregateErrors(
63  "AddAssetQuantity",
64  {},
65  {validator_.validateAssetId(add_asset_quantity.assetId()),
66  validator_.validateAmount(add_asset_quantity.amount())});
67  }
68 
69  std::optional<ValidationError> operator()(
70  const interface::AddPeer &add_peer) const {
71  return aggregateErrors(
72  "AddPeer", {}, {validator_.validatePeer(add_peer.peer())});
73  }
74 
75  std::optional<ValidationError> operator()(
76  const interface::AddSignatory &add_signatory) const {
77  return aggregateErrors(
78  "AddSignatory",
79  {},
80  {validator_.validateAccountId(add_signatory.accountId()),
81  validator_.validatePubkey(add_signatory.pubkey())});
82  }
83 
84  std::optional<ValidationError> operator()(
85  const interface::CallEngine &call_engine) const {
86  ValidationErrorCreator error_creator;
87  error_creator |= validator_.validateAccountId(call_engine.caller());
88  if (call_engine.callee()) {
89  error_creator |= validator_.validateEvmHexAddress(
90  call_engine.callee().value().get());
91  }
92  error_creator |= validator_.validateBytecode(
93  interface::types::EvmCodeHexStringView{call_engine.input()});
94  return std::move(error_creator).getValidationError("CallEngine");
95  }
96 
97  std::optional<ValidationError> operator()(
98  const interface::AppendRole &append_role) const {
99  return aggregateErrors(
100  "AppendRole",
101  {},
102  {validator_.validateAccountId(append_role.accountId()),
103  validator_.validateRoleId(append_role.roleName())});
104  }
105 
106  std::optional<ValidationError> operator()(
107  const interface::CreateAccount &create_account) const {
108  return aggregateErrors(
109  "CreateAccount",
110  {},
111  {validator_.validatePubkey(create_account.pubkey()),
112  validator_.validateAccountName(create_account.accountName()),
113  validator_.validateDomainId(create_account.domainId())});
114  }
115 
116  std::optional<ValidationError> operator()(
117  const interface::CreateAsset &create_asset) const {
118  return aggregateErrors(
119  "CreateAsset",
120  {},
121  {validator_.validateAssetName(create_asset.assetName()),
122  validator_.validateDomainId(create_asset.domainId()),
123  validator_.validatePrecision(create_asset.precision())});
124  }
125 
126  std::optional<ValidationError> operator()(
127  const interface::CreateDomain &create_domain) const {
128  return aggregateErrors(
129  "CreateDomain",
130  {},
131  {validator_.validateDomainId(create_domain.domainId()),
132  validator_.validateRoleId(create_domain.userDefaultRole())});
133  }
134 
135  std::optional<ValidationError> operator()(
136  const interface::CreateRole &create_role) const {
137  ValidationErrorCreator error_creator;
138  error_creator |= validator_.validateRoleId(create_role.roleName());
139 
140  create_role.rolePermissions().iterate([&error_creator, this](auto i) {
141  error_creator |= validator_.validateRolePermission(i);
142  });
143  return std::move(error_creator).getValidationError("CreateRole");
144  }
145 
146  std::optional<ValidationError> operator()(
147  const interface::DetachRole &detach_role) const {
148  return aggregateErrors(
149  "DetachRole",
150  {},
151  {validator_.validateAccountId(detach_role.accountId()),
152  validator_.validateRoleId(detach_role.roleName())});
153  }
154 
155  std::optional<ValidationError> operator()(
156  const interface::GrantPermission &grant_permission) const {
157  return aggregateErrors(
158  "GrantPermission",
159  {},
160  {validator_.validateAccountId(grant_permission.accountId()),
161  validator_.validateGrantablePermission(
162  grant_permission.permissionName())});
163  }
164 
165  std::optional<ValidationError> operator()(
166  const interface::RemovePeer &remove_peer) const {
167  return aggregateErrors(
168  "RemovePeer",
169  {},
170  {validator_.validatePubkey(remove_peer.pubkey())});
171  }
172 
173  std::optional<ValidationError> operator()(
174  const interface::RemoveSignatory &remove_signatory) const {
175  return aggregateErrors(
176  "RemoveSignatory",
177  {},
178  {validator_.validateAccountId(remove_signatory.accountId()),
179  validator_.validatePubkey(remove_signatory.pubkey())});
180  }
181 
182  std::optional<ValidationError> operator()(
183  const interface::RevokePermission &revoke_permission) const {
184  return aggregateErrors(
185  "RevokePermission",
186  {},
187  {validator_.validateAccountId(revoke_permission.accountId()),
188  validator_.validateGrantablePermission(
189  revoke_permission.permissionName())});
190  }
191 
192  std::optional<ValidationError> operator()(
193  const interface::SetAccountDetail &set_account_detail) const {
194  return aggregateErrors(
195  "SetAccountDetail",
196  {},
197  {validator_.validateAccountId(set_account_detail.accountId()),
198  validator_.validateAccountDetailKey(set_account_detail.key()),
199  validator_.validateAccountDetailValue(
200  set_account_detail.value())});
201  }
202 
203  std::optional<ValidationError> operator()(
204  const interface::SetQuorum &set_quorum) const {
205  return aggregateErrors(
206  "SetQuorum",
207  {},
208  {validator_.validateAccountId(set_quorum.accountId()),
209  validator_.validateQuorum(set_quorum.newQuorum())});
210  }
211 
212  std::optional<ValidationError> operator()(
213  const interface::SubtractAssetQuantity &subtract_asset_quantity)
214  const {
215  return aggregateErrors(
216  "SubtractAssetQuantity",
217  {},
218  {validator_.validateAssetId(subtract_asset_quantity.assetId()),
219  validator_.validateAmount(subtract_asset_quantity.amount())});
220  }
221 
222  std::optional<ValidationError> operator()(
223  const interface::TransferAsset &transfer_asset) const {
224  return aggregateErrors(
225  "TransferAsset",
226  {[&]() -> std::optional<std::string> {
227  if (transfer_asset.srcAccountId()
228  == transfer_asset.destAccountId()) {
229  return std::string{
230  "Source and destination accounts are the same."};
231  }
232  return std::nullopt;
233  }()},
234  {validator_.validateAccountId(transfer_asset.srcAccountId()),
235  validator_.validateAccountId(transfer_asset.destAccountId()),
236  validator_.validateAssetId(transfer_asset.assetId()),
237  validator_.validateAmount(transfer_asset.amount()),
238  validator_.validateDescription(transfer_asset.description())});
239  }
240 
241  std::optional<ValidationError> operator()(
243  &compare_and_set_account_detail) const {
244  using iroha::operator|;
245  return aggregateErrors(
246  "CompareAndSetAccountDetail",
247  {},
248  {validator_.validateAccountId(
249  compare_and_set_account_detail.accountId()),
250  validator_.validateAccountDetailKey(
251  compare_and_set_account_detail.key()),
252  validator_.validateAccountDetailValue(
253  compare_and_set_account_detail.value()),
254  compare_and_set_account_detail.oldValue() |
255  [this](
256  const auto &oldValue) -> std::optional<ValidationError> {
257  return this->validator_.validateOldAccountDetailValue(oldValue);
258  }});
259  }
260 
261  std::optional<ValidationError> operator()(
262  const interface::SetSettingValue &set_setting_value) const {
263  return std::nullopt;
264  }
265 
266  private:
267  FieldValidator validator_;
268  };
269 
275  template <typename FieldValidator, typename CommandValidator>
277  : public AbstractValidator<interface::Transaction> {
278  private:
279  template <typename CreatedTimeValidator>
280  std::optional<ValidationError> validateImpl(
281  const interface::Transaction &tx,
282  CreatedTimeValidator &&validator) const {
283  using iroha::operator|;
284 
285  ValidationErrorCreator error_creator;
286 
287  if (tx.commands().empty()) {
288  error_creator.addReason(
289  "Transaction must contain at least one command.");
290  }
291 
292  error_creator |=
293  field_validator_.validateCreatorAccountId(tx.creatorAccountId());
294  error_creator |=
295  std::forward<CreatedTimeValidator>(validator)(tx.createdTime());
296  error_creator |= field_validator_.validateQuorum(tx.quorum());
297  error_creator |= tx.batchMeta() | [this](const auto &batch_meta) {
298  return field_validator_.validateBatchMeta(*batch_meta);
299  };
300 
301  for (const auto &cmd : tx.commands() | boost::adaptors::indexed(1)) {
302  boost::apply_visitor(command_validator_visitor_, cmd.value().get()) |
303  [&cmd, &error_creator](auto error) {
304  error_creator.addChildError(ValidationError{
305  std::string{"Command #"} + std::to_string(cmd.index()),
306  {},
307  {error}});
308  };
309  }
310 
311  return std::move(error_creator).getValidationError("Transaction");
312  }
313 
314  public:
316  const std::shared_ptr<ValidatorsConfig> &config)
317  : field_validator_(config), command_validator_visitor_(config) {}
318 
324  std::optional<ValidationError> validate(
325  const interface::Transaction &tx) const override {
326  return validateImpl(tx, [this](auto time) {
327  return field_validator_.validateCreatedTime(time);
328  });
329  }
330 
335  std::optional<ValidationError> validate(
336  const interface::Transaction &tx,
337  interface::types::TimestampType current_timestamp) const {
338  return validateImpl(tx, [this, current_timestamp](auto time) {
339  return field_validator_.validateCreatedTime(time, current_timestamp);
340  });
341  }
342 
343  protected:
345  CommandValidator command_validator_visitor_;
346  };
347 
348  } // namespace validation
349 } // namespace shared_model
350 
351 #endif // IROHA_SHARED_MODEL_TRANSACTION_VALIDATOR_HPP
std::optional< ValidationError > validatePubkey(std::string_view pubkey) const
Definition: field_validator.cpp:167
Definition: compare_and_set_account_detail.hpp:21
virtual const types::AccountIdType & accountId() const =0
virtual const types::RoleIdType & roleName() const =0
std::optional< ValidationError > validateEvmHexAddress(std::string_view address) const
Definition: field_validator.cpp:139
Definition: add_signatory.hpp:19
virtual const types::AccountIdType & srcAccountId() const =0
std::optional< ValidationError > operator()(const interface::CreateRole &create_role) const
Definition: transaction_validator.hpp:135
ValidationErrorCreator & addChildError(ValidationError error)
Add a child error.
Definition: validation_error_helpers.cpp:28
std::optional< ValidationError > operator()(const interface::AddPeer &add_peer) const
Definition: transaction_validator.hpp:69
virtual const interface::Peer & peer() const =0
Represents a validation error.
Definition: validation_error.hpp:19
std::optional< ValidationError > validateAssetName(const interface::types::AssetNameType &asset_name) const
Definition: field_validator.cpp:200
virtual const types::AccountIdType & destAccountId() const =0
virtual types::QuorumType quorum() const =0
std::optional< ValidationError > validatePeer(const interface::Peer &peer) const
Definition: field_validator.cpp:150
Definition: set_quorum.hpp:18
std::optional< ValidationError > operator()(const interface::CompareAndSetAccountDetail &compare_and_set_account_detail) const
Definition: transaction_validator.hpp:241
std::optional< ValidationError > operator()(const interface::CreateAccount &create_account) const
Definition: transaction_validator.hpp:106
virtual const types::AccountIdType & accountId() const =0
Definition: subtract_asset_quantity.hpp:20
virtual const types::AccountDetailValueType & value() const =0
std::optional< ValidationError > operator()(const interface::RevokePermission &revoke_permission) const
Definition: transaction_validator.hpp:182
std::optional< ValidationError > validate(const interface::Transaction &tx) const override
Definition: transaction_validator.hpp:324
TransactionValidator(const std::shared_ptr< ValidatorsConfig > &config)
Definition: transaction_validator.hpp:315
std::optional< ValidationError > operator()(const interface::CreateAsset &create_asset) const
Definition: transaction_validator.hpp:116
Definition: abstract_validator.hpp:17
std::optional< ValidationError > validateGrantablePermission(const interface::permissions::Grantable &permission) const
Definition: field_validator.cpp:246
Definition: set_setting_value.hpp:19
std::optional< ValidationError > operator()(const interface::AddSignatory &add_signatory) const
Definition: transaction_validator.hpp:75
virtual const std::string & caller() const =0
virtual const types::AccountIdType & accountId() const =0
std::optional< ValidationError > operator()(const interface::RemoveSignatory &remove_signatory) const
Definition: transaction_validator.hpp:173
Definition: detach_role.hpp:19
virtual const types::AccountIdType & accountId() const =0
std::optional< ValidationError > validateQuorum(const interface::types::QuorumType &quorum) const
Definition: field_validator.cpp:256
Definition: remove_signatory.hpp:18
Definition: create_asset.hpp:18
virtual const Amount & amount() const =0
virtual const std::string & pubkey() const =0
virtual const types::AssetIdType & assetId() const =0
Definition: call_engine.hpp:20
std::optional< ValidationError > validateAccountDetailKey(const interface::types::AccountDetailKeyType &key) const
Definition: field_validator.cpp:205
std::optional< ValidationError > aggregateErrors(const ReasonName &name, std::vector< std::optional< ReasonType >> optional_reasons, std::vector< std::optional< ValidationError >> optional_child_errors)
Definition: validation_error_helpers.cpp:57
Definition: remove_peer.hpp:19
virtual const RolePermissionSet & rolePermissions() const =0
virtual const types::AccountIdType & accountId() const =0
Definition: append_role.hpp:19
std::optional< ValidationError > validateDomainId(const interface::types::DomainIdType &domain_id) const
Definition: field_validator.cpp:187
std::optional< ValidationError > operator()(const interface::GrantPermission &grant_permission) const
Definition: transaction_validator.hpp:155
std::optional< ValidationError > validateAccountId(const interface::types::AccountIdType &account_id) const
Definition: field_validator.cpp:129
virtual const std::optional< types::AccountDetailValueType > oldValue() const =0
Definition: transfer_asset.hpp:19
virtual types::TimestampType createdTime() const =0
virtual std::optional< std::reference_wrapper< const std::string > > callee() const =0
std::optional< ValidationError > operator()(const interface::SetQuorum &set_quorum) const
Definition: transaction_validator.hpp:203
virtual const types::AssetIdType & assetId() const =0
std::optional< ValidationError > operator()(const interface::RemovePeer &remove_peer) const
Definition: transaction_validator.hpp:165
ValidationErrorCreator & addReason(ReasonType reason)
Add a reason to error.
Definition: validation_error_helpers.cpp:23
virtual const types::AccountNameType & accountName() const =0
virtual const types::RoleIdType & roleName() const =0
virtual const types::AccountIdType & accountId() const =0
virtual const PrecisionType & precision() const =0
std::optional< ValidationError > getValidationError(const ReasonName &name) &&
Definition: validation_error_helpers.cpp:15
virtual const std::string & pubkey() const =0
std::optional< ValidationError > operator()(const interface::CreateDomain &create_domain) const
Definition: transaction_validator.hpp:126
virtual const types::AccountDetailValueType & value() const =0
virtual const types::RoleIdType & roleName() const =0
std::optional< ValidationError > validateBytecode(interface::types::EvmCodeHexStringView input) const
Definition: field_validator.cpp:144
virtual const Amount & amount() const =0
virtual const types::AccountDetailKeyType & key() const =0
std::optional< ValidationError > operator()(const interface::AddAssetQuantity &add_asset_quantity) const
Definition: transaction_validator.hpp:60
virtual std::optional< std::shared_ptr< BatchMeta > > batchMeta() 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::DomainIdType & domainId() const =0
virtual const std::string & pubkey() const =0
Definition: grant_permission.hpp:19
virtual const types::RoleIdType & userDefaultRole() const =0
std::optional< ValidationError > operator()(const interface::DetachRole &detach_role) const
Definition: transaction_validator.hpp:146
Definition: set_account_detail.hpp:19
virtual const types::AccountDetailKeyType & key() const =0
virtual CommandsType commands() const =0
std::optional< ValidationError > validateDescription(const interface::types::DescriptionType &description) const
Definition: field_validator.cpp:357
Definition: field_validator.hpp:41
std::optional< ValidationError > operator()(const interface::AppendRole &append_role) const
Definition: transaction_validator.hpp:97
virtual const types::AssetNameType & assetName() const =0
virtual const std::string & pubkey() const =0
Definition: revoke_permission.hpp:19
std::optional< ValidationError > operator()(const interface::CallEngine &call_engine) const
Definition: transaction_validator.hpp:84
virtual const types::DescriptionType & description() const =0
virtual const types::AccountIdType & accountId() const =0
Definition: transaction_validator.hpp:51
CommandValidator command_validator_visitor_
Definition: transaction_validator.hpp:345
std::optional< ValidationError > validateAccountDetailValue(const interface::types::AccountDetailValueType &value) const
Definition: field_validator.cpp:210
Helper class for ValidationError creation.
Definition: validation_error_helpers.hpp:16
std::optional< ValidationError > validate(const interface::Transaction &tx, interface::types::TimestampType current_timestamp) const
Definition: transaction_validator.hpp:335
Definition: transaction_validator.hpp:276
std::optional< ValidationError > validateAmount(const interface::Amount &amount) const
Definition: field_validator.cpp:158
void iterate(std::function< void(Perm)> f) const
Definition: permissions.cpp:140
std::optional< ValidationError > operator()(const interface::SubtractAssetQuantity &subtract_asset_quantity) const
Definition: transaction_validator.hpp:212
std::optional< ValidationError > operator()(const interface::SetSettingValue &set_setting_value) const
Definition: transaction_validator.hpp:261
std::optional< ValidationError > validateAccountName(const interface::types::AccountNameType &account_name) const
Definition: field_validator.cpp:182
virtual const types::AccountIdType & accountId() const =0
Definition: add_asset_quantity.hpp:20
virtual const Amount & amount() const =0
virtual const types::DomainIdType & domainId() const =0
Definition: create_role.hpp:19
std::optional< ValidationError > validateOldAccountDetailValue(const std::optional< interface::types::AccountDetailValueType > &old_value) const
Definition: field_validator.cpp:223
std::optional< ValidationError > operator()(const interface::SetAccountDetail &set_account_detail) const
Definition: transaction_validator.hpp:192
virtual const types::AccountIdType & creatorAccountId() const =0
Definition: command_executor.hpp:12
FieldValidator field_validator_
Definition: transaction_validator.hpp:344
std::optional< ValidationError > operator()(const interface::TransferAsset &transfer_asset) const
Definition: transaction_validator.hpp:222
std::optional< ValidationError > validateRoleId(const interface::types::RoleIdType &role_id) const
Definition: field_validator.cpp:177
virtual permissions::Grantable permissionName() const =0
virtual const types::AccountIdType & accountId() const =0
Definition: transaction.hpp:23
virtual const types::DomainIdType & domainId() const =0
std::optional< ValidationError > validateRolePermission(const interface::permissions::Role &permission) const
Definition: field_validator.cpp:237
virtual const std::string & input() const =0
std::optional< ValidationError > validateAssetId(const interface::types::AssetIdType &asset_id) const
Definition: field_validator.cpp:134
std::optional< ValidationError > validatePrecision(const interface::types::PrecisionType &precision) const
Definition: field_validator.cpp:232
Definition: add_peer.hpp:20
CommandValidatorVisitor(std::shared_ptr< ValidatorsConfig > config)
Definition: transaction_validator.hpp:57
uint64_t TimestampType
Type of timestamp.
Definition: types.hpp:67
virtual const types::AssetIdType & assetId() const =0