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