Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

Query Error Responses #1770

Merged
merged 12 commits into from
Oct 17, 2018
1 change: 1 addition & 0 deletions irohad/ametsuchi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ target_link_libraries(ametsuchi
libs_common
common
shared_model_interfaces
shared_model_proto_backend
shared_model_stateless_validation
SOCI::core
SOCI::postgresql
Expand Down
342 changes: 213 additions & 129 deletions irohad/ametsuchi/impl/postgres_query_executor.cpp

Large diffs are not rendered by default.

67 changes: 43 additions & 24 deletions irohad/ametsuchi/impl/postgres_query_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "ametsuchi/impl/soci_utils.hpp"
#include "ametsuchi/key_value_storage.hpp"
#include "ametsuchi/storage.hpp"
#include "builders/protobuf/builder_templates/query_response_template.hpp"
#include "interfaces/commands/add_asset_quantity.hpp"
#include "interfaces/commands/add_peer.hpp"
#include "interfaces/commands/add_signatory.hpp"
Expand All @@ -30,6 +29,7 @@
#include "interfaces/commands/transfer_asset.hpp"
#include "interfaces/common_objects/common_objects_factory.hpp"
#include "interfaces/iroha_internal/block_json_converter.hpp"
#include "interfaces/iroha_internal/query_response_factory.hpp"
#include "interfaces/queries/blocks_query.hpp"
#include "interfaces/queries/query.hpp"
#include "interfaces/query_responses/query_response.hpp"
Expand All @@ -38,11 +38,11 @@
namespace iroha {
namespace ametsuchi {

using QueryResponseBuilderDone =
shared_model::proto::TemplateQueryResponseBuilder<1>;
using QueryErrorType =
shared_model::interface::QueryResponseFactory::ErrorQueryType;

class PostgresQueryExecutorVisitor
: public boost::static_visitor<QueryResponseBuilderDone> {
: public boost::static_visitor<QueryExecutorResult> {
public:
PostgresQueryExecutorVisitor(
soci::session &sql,
Expand All @@ -51,42 +51,46 @@ namespace iroha {
KeyValueStorage &block_store,
std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
std::shared_ptr<shared_model::interface::BlockJsonConverter>
converter);
converter,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory);

void setCreatorId(
const shared_model::interface::types::AccountIdType &creator_id);

QueryResponseBuilderDone operator()(
void setQueryHash(const shared_model::crypto::Hash &query_hash);

QueryExecutorResult operator()(
const shared_model::interface::GetAccount &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetSignatories &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetAccountTransactions &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetTransactions &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetAccountAssetTransactions &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetAccountAssets &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetAccountDetail &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetRoles &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetRolePermissions &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetAssetInfo &q);

QueryResponseBuilderDone operator()(
QueryExecutorResult operator()(
const shared_model::interface::GetPendingTransactions &q);

private:
Expand All @@ -95,23 +99,34 @@ namespace iroha {
* predicate pred
*/
template <typename RangeGen, typename Pred>
auto getTransactionsFromBlock(uint64_t block_id,
RangeGen &&range_gen,
Pred &&pred);
std::vector<std::unique_ptr<shared_model::interface::Transaction>>
getTransactionsFromBlock(uint64_t block_id,
RangeGen &&range_gen,
Pred &&pred);

/**
* Execute query in F and return builder result from B
* Execute query in F and return query response from B
* Q is query tuple, P is permission tuple
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe name Q a QueryTuple instead? Same for the PermissionTuple

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am always for giving template parameters meaningful names :)

*/
template <typename Q, typename P, typename F, typename B>
QueryResponseBuilderDone executeQuery(F &&f, B &&b);
template <typename Q,
typename P,
typename F,
typename B,
typename ErrResponse>
QueryExecutorResult executeQuery(F &&f,
B &&b,
ErrResponse &&err_response);

soci::session &sql_;
KeyValueStorage &block_store_;
shared_model::interface::types::AccountIdType creator_id_;
std::shared_ptr<shared_model::interface::CommonObjectsFactory> factory_;
shared_model::crypto::Hash query_hash_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> HashType?

std::shared_ptr<shared_model::interface::CommonObjectsFactory>
common_objects_factory_;
std::shared_ptr<PendingTransactionStorage> pending_txs_storage_;
std::shared_ptr<shared_model::interface::BlockJsonConverter> converter_;
std::shared_ptr<shared_model::interface::QueryResponseFactory>
query_response_factory_;
logger::Logger log_;
};

Expand All @@ -124,7 +139,9 @@ namespace iroha {
KeyValueStorage &block_store,
std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
std::shared_ptr<shared_model::interface::BlockJsonConverter>
converter);
converter,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory);

QueryExecutorResult validateAndExecute(
const shared_model::interface::Query &query) override;
Expand All @@ -137,6 +154,8 @@ namespace iroha {
std::shared_ptr<shared_model::interface::CommonObjectsFactory> factory_;
std::shared_ptr<PendingTransactionStorage> pending_txs_storage_;
PostgresQueryExecutorVisitor visitor_;
std::shared_ptr<shared_model::interface::QueryResponseFactory>
query_response_factory_;
logger::Logger log_;
};

Expand Down
7 changes: 5 additions & 2 deletions irohad/ametsuchi/impl/storage_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ namespace iroha {

boost::optional<std::shared_ptr<QueryExecutor>>
StorageImpl::createQueryExecutor(
std::shared_ptr<PendingTransactionStorage> pending_txs_storage) const {
std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory) const {
std::shared_lock<std::shared_timed_mutex> lock(drop_mutex);
if (not connection_) {
log_->info("connection to database is not initialised");
Expand All @@ -144,7 +146,8 @@ namespace iroha {
factory_,
*block_store_,
pending_txs_storage,
converter_));
converter_,
std::move(response_factory)));
}

bool StorageImpl::insertBlock(const shared_model::interface::Block &block) {
Expand Down
5 changes: 3 additions & 2 deletions irohad/ametsuchi/impl/storage_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ namespace iroha {
createOsPersistentState() const override;

boost::optional<std::shared_ptr<QueryExecutor>> createQueryExecutor(
std::shared_ptr<PendingTransactionStorage> pending_txs_storage)
const override;
std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory) const override;

/**
* Insert block without validation
Expand Down
7 changes: 5 additions & 2 deletions irohad/ametsuchi/query_executor_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <boost/optional.hpp>

#include "ametsuchi/query_executor.hpp"
#include "interfaces/iroha_internal/query_response_factory.hpp"
#include "pending_txs_storage/pending_txs_storage.hpp"

namespace iroha {
Expand All @@ -19,8 +20,10 @@ namespace iroha {
* Creates a query executor from the current state
*/
virtual boost::optional<std::shared_ptr<QueryExecutor>>
createQueryExecutor(std::shared_ptr<PendingTransactionStorage>
pending_txs_storage) const = 0;
createQueryExecutor(
std::shared_ptr<PendingTransactionStorage> pending_txs_storage,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory) const = 0;

virtual ~QueryExecutorFactory() = default;
};
Expand Down
7 changes: 6 additions & 1 deletion irohad/main/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "backend/protobuf/common_objects/proto_common_objects_factory.hpp"
#include "backend/protobuf/proto_block_json_converter.hpp"
#include "backend/protobuf/proto_proposal_factory.hpp"
#include "backend/protobuf/proto_query_response_factory.hpp"
#include "backend/protobuf/proto_transport_factory.hpp"
#include "backend/protobuf/proto_tx_status_factory.hpp"
#include "consensus/yac/impl/supermajority_checker_impl.hpp"
Expand Down Expand Up @@ -189,6 +190,10 @@ void Irohad::initFactories() {
std::make_shared<shared_model::proto::ProtoTransportFactory<
shared_model::interface::Transaction,
shared_model::proto::Transaction>>(std::move(transaction_validator));

query_response_factory_ =
std::make_shared<shared_model::proto::ProtoQueryResponseFactory>();

log_->info("[Init] => factories");
}

Expand Down Expand Up @@ -363,7 +368,7 @@ void Irohad::initTransactionCommandService() {
*/
void Irohad::initQueryService() {
auto query_processor = std::make_shared<QueryProcessorImpl>(
storage, storage, pending_txs_storage_);
storage, storage, pending_txs_storage_, query_response_factory_);

query_service = std::make_shared<::torii::QueryService>(query_processor);

Expand Down
5 changes: 5 additions & 0 deletions irohad/main/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "cryptography/crypto_provider/crypto_model_signer.hpp"
#include "cryptography/keypair.hpp"
#include "interfaces/common_objects/common_objects_factory.hpp"
#include "interfaces/iroha_internal/query_response_factory.hpp"
#include "interfaces/iroha_internal/transaction_batch_factory.hpp"
#include "logger/logger.hpp"
#include "main/impl/block_loader_init.hpp"
Expand Down Expand Up @@ -221,6 +222,10 @@ class Irohad {
iroha::protocol::Transaction>>
transaction_factory;

// query response factory
std::shared_ptr<shared_model::interface::QueryResponseFactory>
query_response_factory_;

// mst
std::shared_ptr<iroha::MstProcessor> mst_processor;

Expand Down
69 changes: 25 additions & 44 deletions irohad/torii/processor/impl/query_processor_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#include <boost/range/size.hpp>

#include "ametsuchi/wsv_query.hpp"
#include "builders/protobuf/builder_templates/query_response_template.hpp"
#include "builders/protobuf/query_responses/proto_block_query_response_builder.hpp"
#include "interfaces/queries/blocks_query.hpp"
#include "interfaces/queries/query.hpp"
#include "interfaces/query_responses/block_query_response.hpp"
Expand All @@ -19,47 +17,21 @@
namespace iroha {
namespace torii {

/**
* Builds QueryResponse that contains StatefulError
* @param hash - original query hash
* @return QueryRepsonse
*/
auto buildStatefulError(
const shared_model::interface::types::HashType &hash) {
return clone(
shared_model::proto::TemplateQueryResponseBuilder<>()
.queryHash(hash)
.errorQueryResponse<
shared_model::interface::StatefulFailedErrorResponse>()
.build());
}

std::shared_ptr<shared_model::interface::BlockQueryResponse>
buildBlocksQueryError(const std::string &message) {
return clone(shared_model::proto::BlockQueryResponseBuilder()
.errorResponse(message)
.build());
}

std::shared_ptr<shared_model::interface::BlockQueryResponse>
buildBlocksQueryBlock(shared_model::interface::Block &block) {
return clone(shared_model::proto::BlockQueryResponseBuilder()
.blockResponse(block)
.build());
}

QueryProcessorImpl::QueryProcessorImpl(
std::shared_ptr<ametsuchi::Storage> storage,
std::shared_ptr<ametsuchi::QueryExecutorFactory> qry_exec,
std::shared_ptr<iroha::PendingTransactionStorage> pending_transactions)
: storage_(storage),
qry_exec_(qry_exec),
pending_transactions_(pending_transactions),
log_(logger::log("QueryProcessorImpl")) {
std::shared_ptr<iroha::PendingTransactionStorage> pending_transactions,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory)
: storage_{std::move(storage)},
qry_exec_{std::move(qry_exec)},
pending_transactions_{std::move(pending_transactions)},
response_factory_{std::move(response_factory)},
log_{logger::log("QueryProcessorImpl")} {
storage_->on_commit().subscribe(
[this](std::shared_ptr<shared_model::interface::Block> block) {
auto response = buildBlocksQueryBlock(*block);
blocks_query_subject_.get_subscriber().on_next(response);
blocks_query_subject_.get_subscriber().on_next(
Akvinikym marked this conversation as resolved.
Show resolved Hide resolved
response_factory_->createBlockQueryResponse(clone(*block)));
});
}

Expand All @@ -85,10 +57,15 @@ namespace iroha {
std::unique_ptr<shared_model::interface::QueryResponse>
QueryProcessorImpl::queryHandle(const shared_model::interface::Query &qry) {
if (not checkSignatories(qry)) {
return buildStatefulError(qry.hash());
return response_factory_->createErrorQueryResponse(
shared_model::interface::QueryResponseFactory::ErrorQueryType::
kStatefulFailed,
"query signatories did not pass validation",
qry.hash());
}

auto executor = qry_exec_->createQueryExecutor(pending_transactions_);
auto executor = qry_exec_->createQueryExecutor(pending_transactions_,
response_factory_);
if (not executor) {
log_->error("Cannot create query executor");
return nullptr;
Expand All @@ -102,15 +79,19 @@ namespace iroha {
QueryProcessorImpl::blocksQueryHandle(
const shared_model::interface::BlocksQuery &qry) {
if (not checkSignatories(qry)) {
auto response = buildBlocksQueryError("Wrong signatories");
return rxcpp::observable<>::just(response);
std::shared_ptr<shared_model::interface::BlockQueryResponse> response =
response_factory_->createBlockQueryResponse(
"query signatories did not pass validation");
return rxcpp::observable<>::just(std::move(response));
}

auto exec = qry_exec_->createQueryExecutor(pending_transactions_);
auto exec = qry_exec_->createQueryExecutor(pending_transactions_,
response_factory_);
if (not exec or not(exec | [&qry](const auto &executor) {
return executor->validate(qry);
})) {
auto response = buildBlocksQueryError("Stateful invalid");
std::shared_ptr<shared_model::interface::BlockQueryResponse> response =
response_factory_->createBlockQueryResponse("stateful invalid");
return rxcpp::observable<>::just(response);
}
return blocks_query_subject_.get_observable();
Expand Down
7 changes: 6 additions & 1 deletion irohad/torii/processor/query_processor_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define IROHA_QUERY_PROCESSOR_IMPL_HPP

#include "ametsuchi/storage.hpp"
#include "interfaces/iroha_internal/query_response_factory.hpp"
#include "logger/logger.hpp"
#include "torii/processor/query_processor.hpp"

Expand All @@ -22,7 +23,9 @@ namespace iroha {
std::shared_ptr<ametsuchi::Storage> storage,
std::shared_ptr<ametsuchi::QueryExecutorFactory> qry_exec,
std::shared_ptr<iroha::PendingTransactionStorage>
pending_transactions);
pending_transactions,
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory);

/**
* Checks if query has needed signatures
Expand All @@ -47,6 +50,8 @@ namespace iroha {
std::shared_ptr<ametsuchi::Storage> storage_;
std::shared_ptr<ametsuchi::QueryExecutorFactory> qry_exec_;
std::shared_ptr<iroha::PendingTransactionStorage> pending_transactions_;
std::shared_ptr<shared_model::interface::QueryResponseFactory>
response_factory_;

logger::Logger log_;
};
Expand Down
Loading