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

Commit

Permalink
Implement non-copyable block (#1542)
Browse files Browse the repository at this point in the history
Implement non-copyable block

Signed-off-by: Nikita Alekseev <n.alekseev2104@gmail.com>
  • Loading branch information
nickaleks authored and l4l committed Jul 25, 2018
1 parent 8954675 commit 18edb18
Show file tree
Hide file tree
Showing 15 changed files with 339 additions and 150 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ include_directories(

SET(IROHA_ROOT_PROJECT ON)

# Boost uses RTTI to perform some actions (such as type erasure).
# This is slow. This flag forces boost to use other methods,
# which are generally faster
add_definitions(-DBOOST_NO_RTTI)

include(FeatureSummary)
include(cmake/functions.cmake)
include(cmake/dependencies.cmake)
Expand Down
24 changes: 10 additions & 14 deletions irohad/ametsuchi/impl/postgres_block_query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,17 @@ namespace iroha {
}
return rxcpp::observable<>::range(height, to)
.flat_map([this](const auto &i) {
auto block = block_store_.get(i) | [](const auto &bytes) {
return shared_model::converters::protobuf::jsonToModel<
shared_model::proto::Block>(bytesToString(bytes));
};
if (not block) {
log_->error("error while converting from JSON");
}

return rxcpp::observable<>::create<PostgresBlockQuery::wBlock>(
[block{std::move(block)}](const auto &s) {
if (block) {
s.on_next(std::make_shared<shared_model::proto::Block>(
block.value()));
}
s.on_completed();
[i, this](const auto &block_subscriber) {
block_store_.get(i) | [](const auto &bytes) {
return shared_model::converters::protobuf::jsonToModel<
shared_model::proto::Block>(bytesToString(bytes));
} | [&block_subscriber](auto &&block) {
block_subscriber.on_next(
std::make_shared<shared_model::proto::Block>(
std::move(block)));
};
block_subscriber.on_completed();
});
});
}
Expand Down
7 changes: 3 additions & 4 deletions irohad/network/impl/block_loader_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,15 @@ rxcpp::observable<std::shared_ptr<Block>> BlockLoaderImpl::retrieveBlocks(
.build(block)
.match(
// success case
[&subscriber](
const iroha::expected::Value<shared_model::proto::Block>
[&subscriber](iroha::expected::Value<shared_model::proto::Block>
&result) {
subscriber.on_next(
std::move(std::make_shared<shared_model::proto::Block>(
result.value)));
std::move(result.value))));
},
// fail case
[this,
&context](const iroha::expected::Error<std::string> &error) {
&context](iroha::expected::Error<std::string> &error) {
log_->error(error.error);
context.TryCancel();
});
Expand Down
1 change: 1 addition & 0 deletions shared_model/backend/protobuf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#

add_library(shared_model_proto_backend
impl/block.cpp
impl/permissions.cpp
commands/impl/proto_add_asset_quantity.cpp
commands/impl/proto_add_peer.cpp
Expand Down
100 changes: 31 additions & 69 deletions shared_model/backend/protobuf/block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,111 +23,73 @@
#include "backend/protobuf/common_objects/signature.hpp"
#include "backend/protobuf/transaction.hpp"
#include "backend/protobuf/util.hpp"
#include "common_objects/trivial_proto.hpp"
#include "common_objects/noncopyable_proto.hpp"
#include "interfaces/common_objects/types.hpp"

#include "block.pb.h"
#include "utils/lazy_initializer.hpp"

namespace shared_model {
namespace proto {
class Block final : public CopyableProto<interface::Block,
iroha::protocol::Block,
Block> {
class Block final : public NonCopyableProto<interface::Block,
iroha::protocol::Block,
Block> {
public:
template <class BlockType>
explicit Block(BlockType &&block)
: CopyableProto(std::forward<BlockType>(block)) {}
using NonCopyableProto::NonCopyableProto;

Block(const Block &o) : Block(o.proto_) {}

Block(Block &&o) noexcept : Block(std::move(o.proto_)) {}
Block(Block &&o) noexcept;
Block &operator=(Block &&o) noexcept;

interface::types::TransactionsCollectionType transactions()
const override {
return *transactions_;
}
const override;

interface::types::HeightType height() const override {
return payload_.height();
}
interface::types::HeightType height() const override;

const interface::types::HashType &prevHash() const override {
return *prev_hash_;
}
const interface::types::HashType &prevHash() const override;

const interface::types::BlobType &blob() const override {
return *blob_;
}
const interface::types::BlobType &blob() const override;

interface::types::SignatureRangeType signatures() const override {
return *signatures_;
}
interface::types::SignatureRangeType signatures() const override;

// TODO Alexey Chernyshov - 2018-03-28 -
// rework code duplication after fix protobuf
// https://soramitsu.atlassian.net/browse/IR-1175
bool addSignature(const crypto::Signed &signed_blob,
const crypto::PublicKey &public_key) override {
// if already has such signature
if (std::find_if(signatures_->begin(),
signatures_->end(),
[&public_key](const auto &signature) {
return signature.publicKey() == public_key;
})
!= signatures_->end()) {
return false;
}

auto sig = proto_->add_signatures();
sig->set_signature(crypto::toBinaryString(signed_blob));
sig->set_pubkey(crypto::toBinaryString(public_key));

signatures_.invalidate();
return true;
}

interface::types::TimestampType createdTime() const override {
return payload_.created_time();
}

interface::types::TransactionsNumberType txsNumber() const override {
return payload_.tx_number();
}

const interface::types::BlobType &payload() const override {
return *payload_blob_;
}
const crypto::PublicKey &public_key) override;

interface::types::TimestampType createdTime() const override;

interface::types::TransactionsNumberType txsNumber() const override;

const interface::types::BlobType &payload() const override;

private:
// lazy
template <typename T>
using Lazy = detail::LazyInitializer<T>;

const iroha::protocol::Block::Payload &payload_{proto_->payload()};
iroha::protocol::Block::Payload &payload_{*proto_.mutable_payload()};

const Lazy<std::vector<proto::Transaction>> transactions_{[this] {
return std::vector<proto::Transaction>(payload_.transactions().begin(),
payload_.transactions().end());
Lazy<std::vector<proto::Transaction>> transactions_{[this] {
return std::vector<proto::Transaction>(
payload_.mutable_transactions()->begin(),
payload_.mutable_transactions()->end());
}};

const Lazy<interface::types::BlobType> blob_{
[this] { return makeBlob(*proto_); }};
Lazy<interface::types::BlobType> blob_{
[this] { return makeBlob(proto_); }};

const Lazy<interface::types::HashType> prev_hash_{[this] {
return interface::types::HashType(proto_->payload().prev_block_hash());
Lazy<interface::types::HashType> prev_hash_{[this] {
return interface::types::HashType(proto_.payload().prev_block_hash());
}};

const Lazy<SignatureSetType<proto::Signature>> signatures_{[this] {
auto signatures = proto_->signatures()
Lazy<SignatureSetType<proto::Signature>> signatures_{[this] {
auto signatures = proto_.signatures()
| boost::adaptors::transformed([](const auto &x) {
return proto::Signature(x);
});
return SignatureSetType<proto::Signature>(signatures.begin(),
signatures.end());
}};

const Lazy<interface::types::BlobType> payload_blob_{
Lazy<interface::types::BlobType> payload_blob_{
[this] { return makeBlob(payload_); }};
};
} // namespace proto
Expand Down
41 changes: 41 additions & 0 deletions shared_model/backend/protobuf/common_objects/noncopyable_proto.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef IROHA_NONCOPYABLE_PROTO_HPP
#define IROHA_NONCOPYABLE_PROTO_HPP

/**
* Generic class for handling proto objects which are not intended to be copied.
* @tparam Iface is interface to inherit from
* @tparam Proto is protobuf container
* @tparam Impl is implementation of Iface
*/
template <typename Iface, typename Proto, typename Impl>
class NonCopyableProto : public Iface {
public:
using TransportType = Proto;

/*
* Construct object from transport. Transport can be moved or copied.
*/
template <typename Transport>
NonCopyableProto(Transport &&ref) : proto_(std::forward<Transport>(ref)){}

NonCopyableProto(const NonCopyableProto &o) = delete;
NonCopyableProto &operator=(const NonCopyableProto &o) = delete;

const Proto &getTransport() const {
return proto_;
}

protected:
typename Iface::ModelType *clone() const override final {
return new Impl(proto_);
}

Proto proto_;
};

#endif // IROHA_NONCOPYABLE_PROTO_HPP
80 changes: 80 additions & 0 deletions shared_model/backend/protobuf/impl/block.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

#include "backend/protobuf/block.hpp"

namespace shared_model {
namespace proto {
Block::Block(Block &&o) noexcept : NonCopyableProto(std::move(o.proto_)) {}

Block &Block::operator=(Block &&o) noexcept {
proto_ = std::move(o.proto_);
payload_ = *proto_.mutable_payload();

transactions_.invalidate();
blob_.invalidate();
prev_hash_.invalidate();
signatures_.invalidate();
payload_blob_.invalidate();

return *this;
}

interface::types::TransactionsCollectionType Block::transactions() const {
return *transactions_;
}

interface::types::HeightType Block::height() const {
return payload_.height();
}

const interface::types::HashType &Block::prevHash() const {
return *prev_hash_;
}

const interface::types::BlobType &Block::blob() const {
return *blob_;
}

interface::types::SignatureRangeType Block::signatures() const {
return *signatures_;
}

// TODO Alexey Chernyshov - 2018-03-28 -
// rework code duplication from transaction, block after fix protobuf
// https://soramitsu.atlassian.net/browse/IR-1175
bool Block::addSignature(const crypto::Signed &signed_blob,
const crypto::PublicKey &public_key) {
// if already has such signature
if (std::find_if(signatures_->begin(),
signatures_->end(),
[&public_key](const auto &signature) {
return signature.publicKey() == public_key;
})
!= signatures_->end()) {
return false;
}

auto sig = proto_.add_signatures();
sig->set_signature(crypto::toBinaryString(signed_blob));
sig->set_pubkey(crypto::toBinaryString(public_key));

signatures_.invalidate();
return true;
}

interface::types::TimestampType Block::createdTime() const {
return payload_.created_time();
}

interface::types::TransactionsNumberType Block::txsNumber() const {
return payload_.tx_number();
}

const interface::types::BlobType &Block::payload() const {
return *payload_blob_;
}
} // namespace proto
} // namespace shared_model
Loading

0 comments on commit 18edb18

Please sign in to comment.