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

Implement non-copyable block #1542

Merged
merged 17 commits into from
Jul 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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