Skip to content

Commit

Permalink
Merge branch 'feature/const_builder' into feature/shared_model
Browse files Browse the repository at this point in the history
  • Loading branch information
muratovv authored and lebdron committed Dec 19, 2017
2 parents 214a7f3 + ee93e71 commit ba13d6f
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 99 deletions.
2 changes: 0 additions & 2 deletions shared_model/bindings/bindings.i
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@
%include "cryptography/signed.hpp"
%include "backend/protobuf/transaction.hpp"
%include "backend/protobuf/queries/proto_query.hpp"
%include "builders/protobuf/queries.hpp"
%include "builders/protobuf/transaction.hpp"

%include "builders/protobuf/unsigned_proto.hpp"
%include "bindings/model_transaction_builder.hpp"
Expand Down
219 changes: 124 additions & 95 deletions shared_model/builders/protobuf/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

namespace shared_model {
namespace proto {

template <int S = 0, typename SV = validation::DefaultValidator>
class TemplateTransactionBuilder {
private:
Expand All @@ -46,133 +47,162 @@ namespace shared_model {
};

template <int s>
using NextBuilder = TemplateTransactionBuilder<S | (1 << s)>;
using NextBuilder = TemplateTransactionBuilder<S | (1 << s), SV>;

iroha::protocol::Transaction transaction_;
using ProtoTx = iroha::protocol::Transaction;
using ProtoCommand = iroha::protocol::Command;

template <int Sp>
TemplateTransactionBuilder(const TemplateTransactionBuilder<Sp> &o,
SV &&stateless_validator = SV())
TemplateTransactionBuilder(const TemplateTransactionBuilder<Sp> &o)
: transaction_(o.transaction_),
stateless_validator_(std::forward<SV>(stateless_validator)) {}
stateless_validator_(o.stateless_validator_) {}

/**
* Make transformation on copied content
* @tparam Transformation - callable type for changing the copy
* @param f - transform function for proto object
* @return new builder with updated state
*/
template <int Fields, typename Transformation>
auto transform(Transformation t) const {
NextBuilder<Fields> copy = *this;
t(copy.transaction_);
return copy;
}

SV stateless_validator_;
/**
* Make add command transformation on copied object
* @tparam Transformation - callable type for changing command
* @param f - transform function for proto command
* @return new builder with added command
*/
template <typename Transformation>
auto addCommand(Transformation t) const {
NextBuilder<Command> copy = *this;
t(copy.transaction_.mutable_payload()->add_commands());
return copy;
}

public:
TemplateTransactionBuilder() = default;

NextBuilder<CreatorAccountId> creatorAccountId(
const interface::types::AccountIdType &account_id) {
transaction_.mutable_payload()->set_creator_account_id(account_id);
return *this;
TemplateTransactionBuilder(const SV &validator = SV())
: stateless_validator_(validator) {}

auto creatorAccountId(
const interface::types::AccountIdType &account_id) const {
return transform<CreatorAccountId>([&](auto &tx) {
tx.mutable_payload()->set_creator_account_id(account_id);
});
}

NextBuilder<TxCounter> txCounter(
interface::types::CounterType tx_counter) {
transaction_.mutable_payload()->set_tx_counter(tx_counter);
return *this;
auto txCounter(interface::types::CounterType tx_counter) const {
return transform<TxCounter>([&](auto &tx) {
tx.mutable_payload()->set_tx_counter(tx_counter);
});
}

NextBuilder<CreatedTime> createdTime(
interface::types::TimestampType created_time) {
transaction_.mutable_payload()->set_created_time(created_time);
return *this;
auto createdTime(interface::types::TimestampType created_time) const {
return transform<CreatedTime>([&](auto &tx) {
tx.mutable_payload()->set_created_time(created_time);
});
}

NextBuilder<Command> addAssetQuantity(
const interface::types::AccountIdType &account_id,
const interface::types::AssetIdType &asset_id,
const std::string &amount) {
auto command = proto_command()->mutable_add_asset_quantity();
command->set_account_id(account_id);
command->set_asset_id(asset_id);
addAmount(command->mutable_amount(), amount);
return *this;
auto addAssetQuantity(const interface::types::AccountIdType &account_id,
const interface::types::AssetIdType &asset_id,
const std::string &amount) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_add_asset_quantity();
command->set_account_id(account_id);
command->set_asset_id(asset_id);
addAmount(command->mutable_amount(), amount);
});
}

NextBuilder<Command> addPeer(
const interface::types::AddressType &address,
const interface::types::PubkeyType &peer_key) {
auto command = proto_command()->mutable_add_peer();
command->set_address(address);
command->set_peer_key(peer_key.blob());
return *this;
auto addPeer(const interface::types::AddressType &address,
const interface::types::PubkeyType &peer_key) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_add_peer();
command->set_address(address);
command->set_peer_key(peer_key.blob());
});
}

NextBuilder<Command> addSignatory(
const interface::types::AddressType &account_id,
const interface::types::PubkeyType &public_key) {
auto command = proto_command()->mutable_add_signatory();
command->set_account_id(account_id);
command->set_public_key(public_key.blob());
return *this;
auto addSignatory(const interface::types::AddressType &account_id,
const interface::types::PubkeyType &public_key) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_add_signatory();
command->set_account_id(account_id);
command->set_public_key(public_key.blob());
});
}

NextBuilder<Command> removeSignatory(
auto removeSignatory(
const interface::types::AddressType &account_id,
const interface::types::PubkeyType &public_key) {
auto command = proto_command()->mutable_remove_sign();
command->set_account_id(account_id);
command->set_public_key(public_key.blob());
return *this;
const interface::types::PubkeyType &public_key) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_remove_sign();
command->set_account_id(account_id);
command->set_public_key(public_key.blob());
});
}

NextBuilder<Command> createAsset(
const interface::types::AssetNameType &asset_name,
const interface::types::AddressType &domain_id,
interface::types::PrecisionType precision) {
auto command = proto_command()->mutable_create_asset();
command->set_asset_name(asset_name);
command->set_domain_id(domain_id);
command->set_precision(precision);
return *this;
auto createAsset(const interface::types::AssetNameType &asset_name,
const interface::types::AddressType &domain_id,
interface::types::PrecisionType precision) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_create_asset();
command->set_asset_name(asset_name);
command->set_domain_id(domain_id);
command->set_precision(precision);
});
}

NextBuilder<Command> createAccount(
auto createAccount(
const interface::types::AccountNameType &account_name,
const interface::types::AddressType &domain_id,
const interface::types::PubkeyType &main_pubkey) {
auto command = proto_command()->mutable_create_account();
command->set_account_name(account_name);
command->set_domain_id(domain_id);
command->set_main_pubkey(main_pubkey.blob());
return *this;
const interface::types::PubkeyType &main_pubkey) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_create_account();
command->set_account_name(account_name);
command->set_domain_id(domain_id);
command->set_main_pubkey(main_pubkey.blob());
});
}

NextBuilder<Command> createDomain(
auto createDomain(
const interface::types::AddressType &domain_id,
const interface::types::RoleIdType &default_role) {
auto command = proto_command()->mutable_create_domain();
command->set_domain_id(domain_id);
command->set_default_role(default_role);
return *this;
const interface::types::RoleIdType &default_role) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_create_domain();
command->set_domain_id(domain_id);
command->set_default_role(default_role);
});
}

NextBuilder<Command> setAccountQuorum(
const interface::types::AddressType &account_id,
interface::types::QuorumType quorum) {
auto command = proto_command()->mutable_set_quorum();
command->set_account_id(account_id);
command->set_quorum(quorum);
return *this;
auto setAccountQuorum(const interface::types::AddressType &account_id,
interface::types::QuorumType quorum) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_set_quorum();
command->set_account_id(account_id);
command->set_quorum(quorum);
});
}

NextBuilder<Command> transferAsset(
const interface::types::AccountIdType &src_account_id,
const interface::types::AccountIdType &dest_account_id,
const interface::types::AssetIdType &asset_id,
const std::string &description,
const std::string &amount) {
auto command = proto_command()->mutable_transfer_asset();
command->set_src_account_id(src_account_id);
command->set_dest_account_id(dest_account_id);
command->set_asset_id(asset_id);
command->set_description(description);
addAmount(command->mutable_amount(), amount);
return *this;
auto transferAsset(const interface::types::AccountIdType &src_account_id,
const interface::types::AccountIdType &dest_account_id,
const interface::types::AssetIdType &asset_id,
const std::string &description,
const std::string &amount) const {
return addCommand([&](auto proto_command) {
auto command = proto_command->mutable_transfer_asset();
command->set_src_account_id(src_account_id);
command->set_dest_account_id(dest_account_id);
command->set_asset_id(asset_id);
command->set_description(description);
addAmount(command->mutable_amount(), amount);
});
}

UnsignedWrapper<Transaction> build() {
auto build() const {
static_assert(S == (1 << TOTAL) - 1, "Required fields are not set");

auto answer = stateless_validator_.validate(
Expand All @@ -187,9 +217,8 @@ namespace shared_model {
static const int total = RequiredFields::TOTAL;

private:
iroha::protocol::Command *proto_command() {
return transaction_.mutable_payload()->add_commands();
}
ProtoTx transaction_;
SV stateless_validator_;
};

using TransactionBuilder = TemplateTransactionBuilder<>;
Expand Down
2 changes: 2 additions & 0 deletions shared_model/builders/protobuf/unsigned_proto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace shared_model {
*/
explicit UnsignedWrapper(const T &o) : unsigned_(o) {}

explicit UnsignedWrapper(T &&o) : unsigned_(std::move(o)) {}

/**
* Add signature and retrieve signed result
* @param signature - signature to add
Expand Down
5 changes: 3 additions & 2 deletions shared_model/validators/commands_validator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ namespace shared_model {
* @param tx
* @return Answer containing found error if any
*/
Answer validate(detail::PolymorphicWrapper<interface::Transaction> tx) {
Answer validate(
detail::PolymorphicWrapper<interface::Transaction> tx) const {
Answer answer;
std::string tx_reason_name = "Transaction";
ReasonsGroupType tx_reason(tx_reason_name, GroupedReasons());
Expand Down Expand Up @@ -339,7 +340,7 @@ namespace shared_model {

void validateCreatedTime(
ReasonsGroupType &reason,
const interface::types::TimestampType &timestamp) {
const interface::types::TimestampType &timestamp) const {
iroha::ts64_t now = iroha::time::now();
// TODO 06/08/17 Muratov: make future gap for passing timestamp, like
// with old timestamps IR-511 #goodfirstissue
Expand Down

0 comments on commit ba13d6f

Please sign in to comment.