Skip to content

Commit

Permalink
Fix/query signatures (hyperledger-iroha#1625)
Browse files Browse the repository at this point in the history
* Fix query validators;
Add descriptions for types
Add missed signed block query validator
Rework transaction and query builder with default signed validator

Signed-off-by: Fedor Muratov <[email protected]>

* Fix typo in validator using name

Signed-off-by: Igor Egorov <[email protected]>

* Make validators naming consistent

Signed-off-by: Igor Egorov <[email protected]>

* Use unsined validators where it is required

Signed-off-by: Igor Egorov <[email protected]>

* add test for query signature

Signed-off-by: Fedor Muratov <[email protected]>

* Add review fixes:
* clean up code
* remove normal case
* add additional check for stateless error

Signed-off-by: Fedor Muratov <[email protected]>
  • Loading branch information
muratovv authored and bakhtin committed Aug 2, 2018
1 parent f2ba287 commit 67c450e
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 36 deletions.
2 changes: 1 addition & 1 deletion irohad/torii/impl/command_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ namespace torii {
void CommandService::Torii(const iroha::protocol::Transaction &request) {
shared_model::proto::TransportBuilder<
shared_model::proto::Transaction,
shared_model::validation::DefaultSignableTransactionValidator>()
shared_model::validation::DefaultSignedTransactionValidator>()
.build(request)
.match(
[this](
Expand Down
4 changes: 2 additions & 2 deletions irohad/torii/impl/query_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace torii {

shared_model::proto::TransportBuilder<
shared_model::proto::Query,
shared_model::validation::DefaultQueryValidator>()
shared_model::validation::DefaultSignableQueryValidator>()
.build(request)
.match(
[this, &hash, &response](
Expand Down Expand Up @@ -80,7 +80,7 @@ namespace torii {
log_->debug("Fetching commits");
shared_model::proto::TransportBuilder<
shared_model::proto::BlocksQuery,
shared_model::validation::DefaultBlocksQueryValidator>()
shared_model::validation::DefaultSignableBlocksQueryValidator>()
.build(*request)
.match(
[this, context, request, writer](
Expand Down
2 changes: 1 addition & 1 deletion shared_model/bindings/client_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace shared_model {
void validateTransaction(const Blob &b) {
auto blob = convert(b);
auto s = get<iroha::protocol::Transaction>(blob) | [](auto tx) {
static validation::DefaultSignableTransactionValidator val;
static validation::DefaultSignedTransactionValidator val;
return boost::make_optional(
val.validate(proto::Transaction(tx)).reason());
};
Expand Down
8 changes: 4 additions & 4 deletions shared_model/builders/protobuf/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ namespace shared_model {

using BlockBuilder = TemplateBlockBuilder<>;

using UnsignedBlockBuilder =
TemplateBlockBuilder<0,
shared_model::validation::DefaultBlockValidator,
shared_model::proto::Block>;
using UnsignedBlockBuilder = TemplateBlockBuilder<
0,
shared_model::validation::DefaultUnsignedBlockValidator,
shared_model::proto::Block>;
} // namespace proto
} // namespace shared_model

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace shared_model {
* @tparam BT -- build type of built object returned by build method
*/
template <int S = 0,
typename SV = validation::DefaultBlockValidator,
typename SV = validation::DefaultUnsignedBlockValidator,
typename BT = UnsignedWrapper<Block>>
class DEPRECATED TemplateBlockBuilder {
private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace shared_model {
* @tparam BT -- build type of built object returned by build method
*/
template <int S = 0,
typename SV = validation::DefaultBlocksQueryValidator,
typename SV = validation::DefaultUnsignedBlocksQueryValidator,
typename BT = UnsignedWrapper<BlocksQuery>>
class DEPRECATED TemplateBlocksQueryBuilder {
private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace shared_model {
* @tparam BT -- build type of built object returned by build method
*/
template <int S = 0,
typename SV = validation::DefaultQueryValidator,
typename SV = validation::DefaultUnsignedQueryValidator,
typename BT = UnsignedWrapper<Query>>
class DEPRECATED TemplateQueryBuilder {
private:
Expand Down
98 changes: 78 additions & 20 deletions shared_model/validators/default_validator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,45 +33,103 @@

namespace shared_model {
namespace validation {

// -----------------------| Transaction validation |------------------------

/**
* Transaction validator which checks stateless validation WITHOUT
* signatures
*/
using DefaultTransactionValidator =
TransactionValidator<FieldValidator,
CommandValidatorVisitor<FieldValidator>>;

using DefaultQueryValidator =
/**
* Transaction validator which checks stateless validation
*/
using DefaultSignedTransactionValidator =
SignableModelValidator<DefaultTransactionValidator,
const interface::Transaction &,
FieldValidator>;

// --------------------------| Query validation |---------------------------

/**
* Query validator which checks stateless validation WITHOUT signatures
*/
using DefaultUnsignedQueryValidator =
QueryValidator<FieldValidator, QueryValidatorVisitor<FieldValidator>>;

using DefaultBlocksQueryValidator = BlocksQueryValidator<FieldValidator>;
/**
* Block query validator checks stateless validation WITHOUT signatures
*/
using DefaultUnsignedBlocksQueryValidator =
BlocksQueryValidator<FieldValidator>;

using DefaultProposalValidator = ProposalValidator<
FieldValidator,
DefaultTransactionValidator,
UnsignedTransactionsCollectionValidator<DefaultTransactionValidator>>;
/**
* Query validator which checks stateless validation including signatures
*/
using DefaultSignableQueryValidator =
SignableModelValidator<DefaultUnsignedQueryValidator,
const interface::Query &,
FieldValidator>;

/**
* Block query validator which checks stateless validation including
* signatures
*/
using DefaultSignableBlocksQueryValidator =
SignableModelValidator<DefaultUnsignedBlocksQueryValidator,
const interface::BlocksQuery &,
FieldValidator>;

// --------------------------| Block validation |---------------------------

using DefaultBlockValidator = BlockValidator<
/**
* Block validator which checks blocks WITHOUT signatures
*/
using DefaultUnsignedBlockValidator = BlockValidator<
FieldValidator,
DefaultTransactionValidator,
SignedTransactionsCollectionValidator<DefaultTransactionValidator>>;

/**
* Block validator which checks blocks including signatures
*/
using DefaultSignableBlockValidator =
SignableModelValidator<DefaultUnsignedBlockValidator,
const interface::Block &,
FieldValidator>;

/**
* @deprecated
* In https://soramitsu.atlassian.net/browse/IR-1418 should be removed
*/
using DefaultEmptyBlockValidator = EmptyBlockValidator<FieldValidator>;

/**
* @deprecated
* In https://soramitsu.atlassian.net/browse/IR-1418 should be removed
*/
using DefaultAnyBlockValidator =
AnyBlockValidator<DefaultBlockValidator, DefaultEmptyBlockValidator>;
AnyBlockValidator<DefaultUnsignedBlockValidator,
DefaultEmptyBlockValidator>;

using DefaultSignableTransactionValidator =
SignableModelValidator<DefaultTransactionValidator,
const interface::Transaction &,
FieldValidator>;
// ------------------------| Proposal validation |--------------------------

using DefaultSignableQueryValidator =
SignableModelValidator<DefaultQueryValidator,
const interface::Query &,
FieldValidator>;
/**
* Proposal validator which checks stateless validation of proposal
*/
using DefaultProposalValidator = ProposalValidator<
FieldValidator,
DefaultTransactionValidator,
UnsignedTransactionsCollectionValidator<DefaultTransactionValidator>>;

using DefaultSignableBlockValidator =
SignableModelValidator<DefaultBlockValidator,
const interface::Block &,
FieldValidator>;
// -----------------| Transaction collection validation |-------------------

/**
* Check sequence of transactions without signatures
*/
using DefaultUnsignedTxCollectionValidator =
UnsignedTransactionsCollectionValidator<DefaultTransactionValidator,
BatchOrderValidator>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class TransportBuilderTest : public ::testing::Test {
*/
TEST_F(TransportBuilderTest, TransactionCreationTest) {
auto orig_model = createTransaction();
testTransport<validation::DefaultSignableTransactionValidator>(
testTransport<validation::DefaultSignedTransactionValidator>(
orig_model,
[&orig_model](const Value<decltype(orig_model)> &model) {
ASSERT_EQ(model.value.getTransport().SerializeAsString(),
Expand All @@ -237,7 +237,7 @@ TEST_F(TransportBuilderTest, TransactionCreationTest) {
*/
TEST_F(TransportBuilderTest, InvalidTransactionCreationTest) {
auto orig_model = createInvalidTransaction();
testTransport<validation::DefaultSignableTransactionValidator>(
testTransport<validation::DefaultSignedTransactionValidator>(
orig_model,
[](const Value<decltype(orig_model)>) { FAIL(); },
[](const Error<std::string> &) { SUCCEED(); });
Expand Down Expand Up @@ -283,7 +283,7 @@ TEST_F(TransportBuilderTest, InvalidQueryCreationTest) {
*/
TEST_F(TransportBuilderTest, BlockCreationTest) {
auto orig_model = createBlock();
testTransport<validation::DefaultBlockValidator>(
testTransport<validation::DefaultUnsignedBlockValidator>(
orig_model,
[&orig_model](const Value<decltype(orig_model)> &model) {
ASSERT_EQ(model.value.getTransport().SerializeAsString(),
Expand All @@ -299,7 +299,7 @@ TEST_F(TransportBuilderTest, BlockCreationTest) {
*/
TEST_F(TransportBuilderTest, InvalidBlockCreationTest) {
auto orig_model = createInvalidBlock();
testTransport<validation::DefaultBlockValidator>(
testTransport<validation::DefaultUnsignedBlockValidator>(
orig_model,
[](const Value<std::decay_t<decltype(orig_model)>> &) { FAIL(); },
[](const Error<const std::string> &) { SUCCEED(); });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

class QueryValidatorTest : public ValidatorsTest {
public:
shared_model::validation::DefaultQueryValidator query_validator;
shared_model::validation::DefaultUnsignedQueryValidator query_validator;
};

using namespace shared_model;
Expand Down
7 changes: 7 additions & 0 deletions test/regression/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ target_link_libraries(regression_test
application
integration_framework
)

addtest(query_regression_test query_test.cpp)

target_link_libraries(query_regression_test
application
integration_framework
)
69 changes: 69 additions & 0 deletions test/regression/query_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include <gtest/gtest.h>

#include "builders/protobuf/queries.hpp"
#include "cryptography/crypto_provider/crypto_defaults.hpp"
#include "framework/integration_framework/integration_test_framework.hpp"
#include "framework/specified_visitor.hpp"
#include "module/shared_model/builders/protobuf/test_query_builder.hpp"

template <typename BaseType>
auto makeQuery() {
return BaseType()
.createdTime(iroha::time::now())
.creatorAccountId("admin@test")
.queryCounter(1)
.getAccount("admin@test")
.build();
}

template <typename Query>
auto createInvalidQuery(Query query,
const shared_model::crypto::Keypair &keypair) {
query.addSignature(shared_model::crypto::Signed(std::string(32, 'a')),
keypair.publicKey());
return query;
}

/**
* @given itf instance
* @when pass query with invalid signature
* @then assure that query with invalid signature is failed with stateless
* error
*/
TEST(QueryTest, FailedQueryTest) {
const auto key_pair =
shared_model::crypto::DefaultCryptoAlgorithmType::generateKeypair();

auto query_with_broken_signature =
createInvalidQuery(makeQuery<TestQueryBuilder>(), key_pair);
auto stateless_invalid_query_response = [](auto &status) {
auto &resp =
boost::apply_visitor(framework::SpecifiedVisitor<
shared_model::interface::ErrorQueryResponse>(),
status.get());
boost::apply_visitor(
framework::SpecifiedVisitor<
shared_model::interface::StatelessFailedErrorResponse>(),
resp.get());
};

integration_framework::IntegrationTestFramework itf(1);

itf.setInitialState(key_pair).sendQuery(query_with_broken_signature,
stateless_invalid_query_response);
}

/**
* @given itf instance
* @when pass block query with invalid signature
* @then assure that query with invalid signature is failed with stateless
* error
*/
TEST(QueryTest, FailedBlockQueryTest) {
// TODO: 01/08/2018 @muratovv Implement test since IR-1569 will be completed
}

0 comments on commit 67c450e

Please sign in to comment.