From 2d79dc36470d1f6bca1160d813f046bd432460fa Mon Sep 17 00:00:00 2001 From: Ruslan Tushov Date: Thu, 31 Aug 2023 17:21:01 +0300 Subject: [PATCH 1/3] beefy types (#1773) Signed-off-by: turuslan Co-authored-by: kamilsa --- core/consensus/beefy/sig.hpp | 53 ++++++++ core/consensus/beefy/types.hpp | 114 ++++++++++++++++++ .../binaryen/module/module_instance_impl.cpp | 5 +- .../binaryen/module/module_instance_impl.hpp | 1 - .../common/runtime_transaction_error.cpp | 2 + .../common/runtime_transaction_error.hpp | 1 + core/runtime/runtime_api/beefy.hpp | 21 ++++ core/runtime/runtime_api/impl/CMakeLists.txt | 8 ++ core/runtime/runtime_api/impl/beefy.cpp | 29 +++++ core/runtime/runtime_api/impl/beefy.hpp | 23 ++++ core/runtime/runtime_api/impl/lru.hpp | 2 +- core/runtime/wavm/module_instance.cpp | 5 +- core/runtime/wavm/module_instance.hpp | 3 +- core/utils/lru_encoded.hpp | 2 +- 14 files changed, 258 insertions(+), 11 deletions(-) create mode 100644 core/consensus/beefy/sig.hpp create mode 100644 core/consensus/beefy/types.hpp create mode 100644 core/runtime/runtime_api/beefy.hpp create mode 100644 core/runtime/runtime_api/impl/beefy.cpp create mode 100644 core/runtime/runtime_api/impl/beefy.hpp diff --git a/core/consensus/beefy/sig.hpp b/core/consensus/beefy/sig.hpp new file mode 100644 index 0000000000..dc68b9e301 --- /dev/null +++ b/core/consensus/beefy/sig.hpp @@ -0,0 +1,53 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "consensus/beefy/types.hpp" +#include "crypto/ecdsa_provider.hpp" +#include "crypto/hasher/hasher_impl.hpp" + +namespace kagome::consensus::beefy { + inline common::Hash256 prehash(const Commitment &commitment) { + // TODO(turuslan): #1768, scale encode to hash + return crypto::HasherImpl{}.keccak_256(scale::encode(commitment).value()); + } + + inline bool verify(const crypto::EcdsaProvider &ecdsa, + const VoteMessage &vote) { + auto r = ecdsa.verifyPrehashed( + prehash(vote.commitment), vote.signature, vote.id); + return r and r.value(); + } + + inline size_t threshold(size_t n) { + return n == 0 ? 0 : n - (n - 1) / 3; + } + + inline bool verify(const crypto::EcdsaProvider &ecdsa, + const BeefyJustification &justification_v1, + const ValidatorSet &validators) { + auto &justification = boost::get(justification_v1); + if (justification.commitment.validator_set_id != validators.id) { + return false; + } + auto total = validators.validators.size(); + if (justification.signatures.size() != total) { + return false; + } + auto prehashed = prehash(justification.commitment); + size_t valid = 0; + for (size_t i = 0; i < total; ++i) { + if (auto &sig = justification.signatures[i]) { + if (auto r = ecdsa.verifyPrehashed( + prehashed, *sig, validators.validators[i]); + r and r.value()) { + ++valid; + } + } + } + return valid >= threshold(total); + } +} // namespace kagome::consensus::beefy diff --git a/core/consensus/beefy/types.hpp b/core/consensus/beefy/types.hpp new file mode 100644 index 0000000000..387851e705 --- /dev/null +++ b/core/consensus/beefy/types.hpp @@ -0,0 +1,114 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/unused.hpp" +#include "crypto/ecdsa_types.hpp" +#include "primitives/authority.hpp" + +/** + * Test + * ConsensusDigest + * 0x0108020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a10390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f270700000000000000 + * BeefyJustification + * 0x01046d68803af1ad0102f711a7c08e589a1006e4f20c8853b12b5214a57a08cbb4c72cf2ce47000000070000000000000004c002000000080e0fa849fcd9ecfed1b1312e7a17bb4db4ec02761ac760b01a9fc7365c2f55a059125b6217943b561aa27c8b1f990eee1cc9b72ff6f4d6ddde467e33dd02142500f016a7aa597346546f0e799016c8a5302c7a6dce286c513bd69c60e1e77b1e2f6bff5c269369b4ede6fd6e41b32186faff8773158708b16a35d2afcdc9aeeaa500 + */ + +namespace kagome::consensus::beefy { + using MmrRootHash = common::Hash256; + + struct ValidatorSet { + SCALE_TIE(2); + + std::vector validators; + primitives::AuthoritySetId id; + }; + + using ConsensusDigest = + boost::variant, + ValidatorSet, // AuthoritiesChange + primitives::AuthorityIndex, // OnDisabled + MmrRootHash>; + + using PayloadId = common::Blob<2>; + + struct Commitment { + SCALE_TIE(3); + + std::vector> payload; + primitives::BlockNumber block_number; + primitives::AuthoritySetId validator_set_id; + }; + + struct VoteMessage { + SCALE_TIE(3); + + Commitment commitment; + crypto::EcdsaPublicKey id; + crypto::EcdsaSignature signature; + }; + + struct SignedCommitment { + Commitment commitment; + std::vector> signatures; + }; + scale::ScaleEncoderStream &operator<<(scale::ScaleEncoderStream &s, + const SignedCommitment &v) { + s << v.commitment; + size_t count = 0; + common::Buffer bits; + // https://github.com/paritytech/substrate/blob/55bb6298e74d86be12732fd0f120185ee8fbfe97/primitives/consensus/beefy/src/commitment.rs#L149-L152 + bits.resize(v.signatures.size() / 8 + 1); + auto i = 0; + for (auto &sig : v.signatures) { + if (sig) { + ++count; + bits[i / 8] |= 1 << (7 - i % 8); + } + ++i; + } + s << bits; + s << static_cast(v.signatures.size()); + s << scale::CompactInteger{count}; + for (auto &sig : v.signatures) { + if (sig) { + s << *sig; + } + } + return s; + } + scale::ScaleDecoderStream &operator>>(scale::ScaleDecoderStream &s, + SignedCommitment &v) { + s >> v.commitment; + common::Buffer bits; + s >> bits; + size_t expected_count = 0; + for (auto byte : bits) { + for (; byte; byte >>= 1) { + expected_count += byte & 1; + } + } + uint32_t total = 0; + s >> total; + if (bits.size() * 8 < total) { + scale::raise(scale::DecodeError::NOT_ENOUGH_DATA); + } + scale::CompactInteger actual_count; + s >> actual_count; + if (actual_count != expected_count) { + scale::raise(scale::DecodeError::TOO_MANY_ITEMS); + } + v.signatures.resize(total); + for (size_t i = 0; i < total; ++i) { + if ((bits[i / 8] & (1 << (7 - i % 8))) != 0) { + s >> v.signatures[i].emplace(); + } + } + return s; + } + + using BeefyJustification = boost::variant, SignedCommitment>; +} // namespace kagome::consensus::beefy diff --git a/core/runtime/binaryen/module/module_instance_impl.cpp b/core/runtime/binaryen/module/module_instance_impl.cpp index 555448cd46..cfef88b8d3 100644 --- a/core/runtime/binaryen/module/module_instance_impl.cpp +++ b/core/runtime/binaryen/module/module_instance_impl.cpp @@ -12,6 +12,7 @@ #include "runtime/binaryen/memory_impl.hpp" #include "runtime/binaryen/module/module_impl.hpp" +#include "runtime/common/runtime_transaction_error.hpp" #include "runtime/memory_provider.hpp" #include @@ -68,8 +69,6 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime::binaryen, return "An error occurred during an export call execution"; case ModuleInstanceImpl::Error::CAN_NOT_OBTAIN_GLOBAL: return "Failed to obtain a global value"; - case ModuleInstanceImpl::Error::NO_EXPORT_FUNCTION: - return "No export function"; } return "Unknown ModuleInstance error"; } @@ -110,7 +109,7 @@ namespace kagome::runtime::binaryen { module_instance_->wasm.getExportOrNull(wasm::Name{name.data()}); nullptr == res) { SL_DEBUG(logger_, "The requested function {} not found", name); - return Error::NO_EXPORT_FUNCTION; + return RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND; } try { diff --git a/core/runtime/binaryen/module/module_instance_impl.hpp b/core/runtime/binaryen/module/module_instance_impl.hpp index 84a299f8e9..6a33b018e4 100644 --- a/core/runtime/binaryen/module/module_instance_impl.hpp +++ b/core/runtime/binaryen/module/module_instance_impl.hpp @@ -27,7 +27,6 @@ namespace kagome::runtime::binaryen { UNEXPECTED_EXIT = 1, EXECUTION_ERROR, CAN_NOT_OBTAIN_GLOBAL, - NO_EXPORT_FUNCTION }; ModuleInstanceImpl(InstanceEnvironment &&env, diff --git a/core/runtime/common/runtime_transaction_error.cpp b/core/runtime/common/runtime_transaction_error.cpp index 2d51895493..7a0d1b8d7b 100644 --- a/core/runtime/common/runtime_transaction_error.cpp +++ b/core/runtime/common/runtime_transaction_error.cpp @@ -10,6 +10,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime, RuntimeTransactionError, e) { switch (e) { case E::NO_TRANSACTIONS_WERE_STARTED: return "no transactions were started"; + case E::EXPORT_FUNCTION_NOT_FOUND: + return "Export function not found"; } return "unknown TransactionError"; } diff --git a/core/runtime/common/runtime_transaction_error.hpp b/core/runtime/common/runtime_transaction_error.hpp index dc55a43f9b..e0ea4f2c39 100644 --- a/core/runtime/common/runtime_transaction_error.hpp +++ b/core/runtime/common/runtime_transaction_error.hpp @@ -16,6 +16,7 @@ namespace kagome::runtime { */ enum class RuntimeTransactionError { // 0 is reserved for success NO_TRANSACTIONS_WERE_STARTED = 1, + EXPORT_FUNCTION_NOT_FOUND, }; } // namespace kagome::runtime diff --git a/core/runtime/runtime_api/beefy.hpp b/core/runtime/runtime_api/beefy.hpp new file mode 100644 index 0000000000..15ce76b403 --- /dev/null +++ b/core/runtime/runtime_api/beefy.hpp @@ -0,0 +1,21 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "consensus/beefy/types.hpp" + +namespace kagome::runtime { + class BeefyApi { + public: + virtual ~BeefyApi() = default; + + /** + * Get validator set if beefy is supported. + */ + virtual outcome::result> + validatorSet(const primitives::BlockHash &block) = 0; + }; +} // namespace kagome::runtime diff --git a/core/runtime/runtime_api/impl/CMakeLists.txt b/core/runtime/runtime_api/impl/CMakeLists.txt index 40877c2e61..e900b5ea1d 100644 --- a/core/runtime/runtime_api/impl/CMakeLists.txt +++ b/core/runtime/runtime_api/impl/CMakeLists.txt @@ -27,6 +27,14 @@ target_link_libraries(babe_api executor ) +add_library(beefy_api + beefy.cpp + ) +target_link_libraries(beefy_api + executor + runtime_transaction_error + ) + add_library(block_builder_api block_builder.cpp ) diff --git a/core/runtime/runtime_api/impl/beefy.cpp b/core/runtime/runtime_api/impl/beefy.cpp new file mode 100644 index 0000000000..5f46eee36a --- /dev/null +++ b/core/runtime/runtime_api/impl/beefy.cpp @@ -0,0 +1,29 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "runtime/runtime_api/impl/beefy.hpp" + +#include "runtime/common/runtime_transaction_error.hpp" +#include "runtime/executor.hpp" + +namespace kagome::runtime { + BeefyApiImpl::BeefyApiImpl(std::shared_ptr executor) + : executor_{std::move(executor)} { + BOOST_ASSERT(executor_); + } + + outcome::result> + BeefyApiImpl::validatorSet(const primitives::BlockHash &block) { + auto r = executor_->callAt( + block, "BeefyApi_validator_set"); + if (r) { + return std::move(r.value()); + } + if (r.error() == RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND) { + return std::nullopt; + } + return r.error(); + } +} // namespace kagome::runtime diff --git a/core/runtime/runtime_api/impl/beefy.hpp b/core/runtime/runtime_api/impl/beefy.hpp new file mode 100644 index 0000000000..ff632db2b5 --- /dev/null +++ b/core/runtime/runtime_api/impl/beefy.hpp @@ -0,0 +1,23 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "runtime/runtime_api/beefy.hpp" + +namespace kagome::runtime { + class Executor; + + class BeefyApiImpl : public BeefyApi { + public: + BeefyApiImpl(std::shared_ptr executor); + + outcome::result> validatorSet( + const primitives::BlockHash &block) override; + + private: + std::shared_ptr executor_; + }; +} // namespace kagome::runtime diff --git a/core/runtime/runtime_api/impl/lru.hpp b/core/runtime/runtime_api/impl/lru.hpp index 66344b1592..b0d6139b36 100644 --- a/core/runtime/runtime_api/impl/lru.hpp +++ b/core/runtime/runtime_api/impl/lru.hpp @@ -12,7 +12,7 @@ #include "utils/safe_object.hpp" namespace kagome::runtime { - constexpr auto DISABLE_RUNTIME_LRU = true; + constexpr auto DISABLE_RUNTIME_LRU = false; /** * Cache runtime calls without arguments. diff --git a/core/runtime/wavm/module_instance.cpp b/core/runtime/wavm/module_instance.cpp index 118d027e67..dedad1d325 100644 --- a/core/runtime/wavm/module_instance.cpp +++ b/core/runtime/wavm/module_instance.cpp @@ -10,6 +10,7 @@ #include "host_api/host_api.hpp" #include "log/profiling_logger.hpp" +#include "runtime/common/runtime_transaction_error.hpp" #include "runtime/memory_provider.hpp" #include "runtime/module_repository.hpp" #include "runtime/trie_storage_provider.hpp" @@ -70,8 +71,6 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::runtime::wavm, switch (e) { case E::WRONG_ARG_COUNT: return "The provided function argument count should equal to 2"; - case E::FUNC_NOT_FOUND: - return "The requested function not found"; case E::EXECUTION_ERROR: return "An error occurred during wasm call execution; Check the logs for " "more information"; @@ -117,7 +116,7 @@ namespace kagome::runtime::wavm { WAVM::Runtime::getInstanceExport(instance_, name.data())); if (!function) { SL_DEBUG(logger_, "The requested function {} not found", name); - return Error::FUNC_NOT_FOUND; + return RuntimeTransactionError::EXPORT_FUNCTION_NOT_FOUND; } const WAVM::IR::FunctionType functionType = WAVM::Runtime::getFunctionType(function); diff --git a/core/runtime/wavm/module_instance.hpp b/core/runtime/wavm/module_instance.hpp index 43e62ed3b2..b959593961 100644 --- a/core/runtime/wavm/module_instance.hpp +++ b/core/runtime/wavm/module_instance.hpp @@ -32,8 +32,7 @@ namespace kagome::runtime::wavm { public std::enable_shared_from_this { public: enum class Error { - FUNC_NOT_FOUND = 1, - WRONG_ARG_COUNT, + WRONG_ARG_COUNT = 1, EXECUTION_ERROR, WRONG_RETURN_TYPE }; diff --git a/core/utils/lru_encoded.hpp b/core/utils/lru_encoded.hpp index 55a6ade635..3a1b53e637 100644 --- a/core/utils/lru_encoded.hpp +++ b/core/utils/lru_encoded.hpp @@ -41,7 +41,7 @@ namespace kagome { if (weak) { shared = weak->get().lock(); // check collisions (size_t is weak hash) - if (*shared != v) { + if (shared and *shared != v) { shared.reset(); } } From 3a74028a3a429ab4e0f8e042fb7ce30b97c92038 Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov Date: Thu, 31 Aug 2023 19:46:36 +0300 Subject: [PATCH 2/3] Fix null-stream chash (#1777) Signed-off-by: Dmitriy Khaustov aka xDimon --- .../impl/protocols/protocol_base_impl.hpp | 69 +++++----- .../protocols/request_response_protocol.hpp | 122 ++++++++++++------ .../impl/protocols/send_dispute_protocol.hpp | 22 ++-- core/network/impl/router_libp2p.cpp | 2 +- core/network/protocol_base.hpp | 7 +- 5 files changed, 133 insertions(+), 89 deletions(-) diff --git a/core/network/impl/protocols/protocol_base_impl.hpp b/core/network/impl/protocols/protocol_base_impl.hpp index 35736f0dd1..9fb1ca84e6 100644 --- a/core/network/impl/protocols/protocol_base_impl.hpp +++ b/core/network/impl/protocols/protocol_base_impl.hpp @@ -3,8 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef KAGOME_NETWORK_PROTOCOLBASEIMPL -#define KAGOME_NETWORK_PROTOCOLBASEIMPL +#pragma once #include "network/protocol_base.hpp" @@ -46,26 +45,34 @@ namespace kagome::network { } template - bool start(std::weak_ptr wptr) { + bool start(std::weak_ptr wp) { host_.setProtocolHandler( protocols_, - [log{logger()}, wp(std::move(wptr))](auto &&stream_and_proto) { - network::streamReadBuffer(stream_and_proto); - if (auto peer_id = stream_and_proto.stream->remotePeerId()) { - SL_TRACE(log, - "Handled {} protocol stream from: {}", - stream_and_proto.protocol, - peer_id.value().toBase58()); - if (auto self = wp.lock()) { - self->onIncomingStream(std::move(stream_and_proto.stream)); + [wp = std::move(wp), log = logger()](auto &&stream_and_proto) { + if (auto self = wp.lock()) { + BOOST_ASSERT(stream_and_proto.stream); + + network::streamReadBuffer(stream_and_proto); + + auto &[stream, protocol] = stream_and_proto; + BOOST_ASSERT(stream); + + if (auto peer_id = stream->remotePeerId()) { + SL_TRACE(log, + "Handled {} protocol stream from {}", + protocol, + peer_id); + BOOST_ASSERT(stream); + self->onIncomingStream(std::move(stream)); return; } - } else { - log->warn("Handled {} protocol stream from unknown peer", - stream_and_proto.protocol); + + SL_WARN(log, + "Handled {} protocol stream from unknown peer", + protocol); + BOOST_ASSERT(stream); + stream->close([](auto &&) {}); } - stream_and_proto.stream->close( - [stream{stream_and_proto.stream}](auto &&) {}); }); return true; } @@ -87,22 +94,24 @@ namespace kagome::network { } template - void closeStream(std::weak_ptr wptr, std::shared_ptr stream) { + void closeStream(std::weak_ptr wp, std::shared_ptr stream) { BOOST_ASSERT(stream); - stream->close([log{logger()}, wptr, stream](auto &&result) { - if (auto self = wptr.lock()) { - if (!result) { + stream->close([wp = std::move(wp), + log = logger(), + peer_id = stream->remotePeerId().value()](auto &&result) { + if (auto self = wp.lock()) { + if (result.has_value()) { SL_DEBUG(log, - "Stream {} was not closed successfully with {}", + "Stream {} with {} was closed.", self->protocolName(), - stream->remotePeerId().value()); - - } else { - SL_VERBOSE(log, - "Stream {} with {} was closed.", - self->protocolName(), - stream->remotePeerId().value()); + peer_id); + return; } + SL_DEBUG(log, + "Stream {} was not closed successfully with {}: {}", + self->protocolName(), + peer_id, + result.error()); } }); } @@ -115,5 +124,3 @@ namespace kagome::network { }; } // namespace kagome::network - -#endif // KAGOME_NETWORK_PROTOCOLBASEIMPL diff --git a/core/network/impl/protocols/request_response_protocol.hpp b/core/network/impl/protocols/request_response_protocol.hpp index 79fcacee2a..c4df6a93ab 100644 --- a/core/network/impl/protocols/request_response_protocol.hpp +++ b/core/network/impl/protocols/request_response_protocol.hpp @@ -3,8 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef KAGOME_NETWORK_REQUESTRESPONSEPROTOCOL -#define KAGOME_NETWORK_REQUESTRESPONSEPROTOCOL +#pragma once #include "network/impl/protocols/protocol_base_impl.hpp" @@ -58,17 +57,18 @@ namespace kagome::network { newOutgoingStream( peer_info, [wptr{this->weak_from_this()}, - response_handler{std::move(response_handler)}, - request{std::move(request)}](auto &&stream_res) mutable { - if (!stream_res.has_value()) { - response_handler(stream_res.as_failure()); + request{std::move(request)}, + response_handler{std::move(response_handler)}](auto &&res) mutable { + if (res.has_error()) { + response_handler(res.as_failure()); return; } + auto &stream = res.value(); + BOOST_ASSERT(stream); - auto stream = std::move(stream_res.value()); auto self = wptr.lock(); if (!self) { - stream->close([stream](auto &&) {}); + self->base_.closeStream(std::move(wptr), std::move(stream)); response_handler(ProtocolError::GONE); return; } @@ -96,11 +96,12 @@ namespace kagome::network { friend class ProtocolBaseImpl; void onIncomingStream(std::shared_ptr stream) override { + BOOST_ASSERT(stream); BOOST_ASSERT(stream->remotePeerId().has_value()); - SL_INFO(base_.logger(), - "New incoming {} stream with {}", - protocolName(), - stream->remotePeerId().value()); + SL_DEBUG(base_.logger(), + "New incoming {} stream with {}", + protocolName(), + stream->remotePeerId().value()); readRequest(std::move(stream)); } @@ -124,11 +125,13 @@ namespace kagome::network { return; } - auto stream = std::move(stream_and_proto.value().stream); + auto &stream = stream_and_proto.value().stream; + BOOST_ASSERT(stream); + auto self = wptr.lock(); - if (!self) { + if (not self) { cb(ProtocolError::GONE); - stream->close([stream](auto &&) {}); + self->base_.closeStream(std::move(wptr), std::move(stream)); return; } @@ -146,6 +149,8 @@ namespace kagome::network { M msg, std::function, std::shared_ptr)> &&cb) { + BOOST_ASSERT(stream); + static_assert(std::is_same_v || std::is_same_v); SL_DEBUG(base_.logger(), @@ -159,14 +164,16 @@ namespace kagome::network { [stream{std::move(stream)}, wptr{this->weak_from_this()}, cb{std::move(cb)}](auto &&write_res) mutable { + BOOST_ASSERT(stream); + auto self = wptr.lock(); if (not self) { cb(ProtocolError::GONE, nullptr); - stream->close([stream](auto &&) {}); + self->base_.closeStream(std::move(wptr), std::move(stream)); return; } - if (!write_res.has_value()) { + if (write_res.has_error()) { SL_VERBOSE(self->base_.logger(), "Error at write into {} stream with {}: {}", self->protocolName(), @@ -190,34 +197,49 @@ namespace kagome::network { void writeRequest(std::shared_ptr stream, RequestType request, std::function)> &&cb) { + BOOST_ASSERT(stream); + return write( std::move(stream), std::move(request), [wptr{this->weak_from_this()}, cb{std::move(cb)}]( auto &&write_res, std::shared_ptr stream) mutable { + BOOST_ASSERT_MSG(write_res.has_value() ? stream != nullptr : true, + "Invariant is broken: " + "stream must not be null with success result"); + auto self = wptr.lock(); if (!self) { cb(ProtocolError::GONE); return; } - if (!write_res.has_value()) { + + if (write_res.has_error()) { cb(write_res.as_failure()); return; } + self->readResponse(std::move(stream), std::move(cb)); }); } void writeResponse(std::shared_ptr stream, ResponseType response) { + BOOST_ASSERT(stream); return write( std::move(stream), std::move(response), [wptr{this->weak_from_this()}](auto &&result, std::shared_ptr stream) { - if (result) { + BOOST_ASSERT_MSG(result.has_value() ? stream != nullptr : true, + "Invariant is broken: " + "stream must not be null with success result"); + + if (result.has_value()) { auto self = wptr.lock(); BOOST_ASSERT_MSG( self, "If self not exists then we can not get result as OK."); + + BOOST_ASSERT(stream); self->base_.closeStream(std::move(wptr), std::move(stream)); } }); @@ -227,6 +249,8 @@ namespace kagome::network { void read( std::shared_ptr stream, std::function, std::shared_ptr)> &&cb) { + BOOST_ASSERT(stream); + SL_DEBUG(base_.logger(), "Read from {} stream with {}", protocolName(), @@ -237,19 +261,21 @@ namespace kagome::network { [stream{std::move(stream)}, wptr{this->weak_from_this()}, cb{std::move(cb)}](auto &&read_result) mutable { + BOOST_ASSERT(stream); + auto self = wptr.lock(); if (!self) { cb(ProtocolError::GONE, nullptr); - stream->close([stream](auto &&) {}); + self->base_.closeStream(std::move(wptr), std::move(stream)); return; } - if (!read_result.has_value()) { - SL_VERBOSE(self->base_.logger(), - "Error at read from outgoing {} stream with {}: {}", - self->protocolName(), - stream->remotePeerId().value(), - read_result.error()); + if (read_result.has_error()) { + SL_DEBUG(self->base_.logger(), + "Error at read from outgoing {} stream with {}: {}", + self->protocolName(), + stream->remotePeerId().value(), + read_result.error()); cb(read_result.as_failure(), nullptr); self->base_.closeStream(std::move(wptr), std::move(stream)); @@ -266,43 +292,57 @@ namespace kagome::network { void readResponse(std::shared_ptr stream, std::function)> &&cb) { + BOOST_ASSERT(stream); return read( std::move(stream), [cb{std::move(cb)}, wptr{this->weak_from_this()}]( auto &&result, std::shared_ptr stream) { + BOOST_ASSERT_MSG(result.has_value() ? stream != nullptr : true, + "Invariant is broken: " + "stream must not be null with success result"); + cb(result); - if (result) { + if (result.has_value()) { auto self = wptr.lock(); - assert( - self - && !!"If self not exists then we can not get result as OK."); + BOOST_ASSERT_MSG( + self, "If self not exists then we can not get result as OK."); + self->base_.closeStream(std::move(wptr), std::move(stream)); } }); } void readRequest(std::shared_ptr stream) { + BOOST_ASSERT(stream); return read( std::move(stream), - [wptr{this->weak_from_this()}](outcome::result result, - std::shared_ptr stream) { - if (!result) { - return; - } + [wptr{this->weak_from_this()}]( + outcome::result request_res, + std::shared_ptr stream) { + BOOST_ASSERT_MSG(request_res.has_value() ? stream != nullptr : true, + "Invariant is broken: " + "stream must not be null with success result"); auto self = wptr.lock(); - assert(self - && !!"If self not exists then we can not get result as OK."); + BOOST_ASSERT_MSG( + self, "If self not exists then we can not get result as OK."); - auto request = std::move(result.value()); - auto response_opt = self->onRxRequest(request, stream); + if (request_res.has_error()) { + SL_WARN(self->base_.logger(), + "Can't read incoming request from stream: {}", + request_res.error()); + return; + } + auto &request = request_res.value(); + + auto response_opt = self->onRxRequest(std::move(request), stream); if (not response_opt) { // Request processing asynchronously return; } auto &response_result = response_opt.value(); - if (!response_result) { + if (response_result.has_error()) { SL_VERBOSE(self->base_.logger(), "Error at execute request from incoming {} stream " "with {}: {}", @@ -322,5 +362,3 @@ namespace kagome::network { }; } // namespace kagome::network - -#endif // KAGOME_NETWORK_REQUESTRESPONSEPROTOCOL diff --git a/core/network/impl/protocols/send_dispute_protocol.hpp b/core/network/impl/protocols/send_dispute_protocol.hpp index cd3a3a40e9..79019b62a5 100644 --- a/core/network/impl/protocols/send_dispute_protocol.hpp +++ b/core/network/impl/protocols/send_dispute_protocol.hpp @@ -3,8 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef KAGOME_NETWORK_SENDDISPUTEPROTOCOLIMPL -#define KAGOME_NETWORK_SENDDISPUTEPROTOCOLIMPL +#pragma once #include "network/impl/protocols/request_response_protocol.hpp" @@ -65,25 +64,30 @@ namespace kagome::network { request.candidate_receipt.commitments_hash, request.session_index); + BOOST_ASSERT(stream); BOOST_ASSERT(stream->remotePeerId().has_value()); + auto peer_id = stream->remotePeerId().value(); dispute_request_observer_->onDisputeRequest( - stream->remotePeerId().value(), + peer_id, std::move(request), [wp = weak_from_this(), - &logger = base().logger(), + base = &SendDisputeProtocol::base, write = &SendDisputeProtocol::writeResponse, - stream{std::move(stream)}](outcome::result res) { + stream = std::move(stream)](outcome::result res) mutable { + BOOST_ASSERT(stream); + if (auto self = wp.lock()) { if (res.has_error()) { - SL_WARN(logger, + SL_WARN(((*self).*base)().logger(), "Processing dispute request failed: {}", res.error()); - stream->reset(); + ((*self).*base)().closeStream(wp, std::move(stream)); return; } - SL_TRACE(logger, "Processing dispute request successful."); + SL_TRACE(((*self).*base)().logger(), + "Processing dispute request successful"); ((*self).*write)(std::move(stream), ResponseType{kagome::Empty{}}); } @@ -104,5 +108,3 @@ namespace kagome::network { }; } // namespace kagome::network - -#endif // KAGOME_NETWORK_SENDDISPUTEPROTOCOLIMPL diff --git a/core/network/impl/router_libp2p.cpp b/core/network/impl/router_libp2p.cpp index 119832afa5..83cfcf979f 100644 --- a/core/network/impl/router_libp2p.cpp +++ b/core/network/impl/router_libp2p.cpp @@ -97,7 +97,7 @@ namespace kagome::network { auto &stream = stream_and_proto.stream; if (auto peer_id = stream->remotePeerId()) { SL_TRACE(self->log_, - "Handled {} protocol stream from: {}", + "Handled {} protocol stream from {}", self->ping_protocol_.get()->getProtocolId(), peer_id.value().toBase58()); self->ping_protocol_.get()->handle( diff --git a/core/network/protocol_base.hpp b/core/network/protocol_base.hpp index aeb0c54758..2760307a16 100644 --- a/core/network/protocol_base.hpp +++ b/core/network/protocol_base.hpp @@ -3,8 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef KAGOME_NETWORK_PROTOCOLBASE -#define KAGOME_NETWORK_PROTOCOLBASE +#pragma once #include "outcome/outcome.hpp" @@ -30,7 +29,7 @@ namespace kagome::network { ProtocolBase(const ProtocolBase &) = delete; virtual ~ProtocolBase() = default; ProtocolBase &operator=(ProtocolBase &&) noexcept = delete; - ProtocolBase &operator=(ProtocolBase const &) = delete; + ProtocolBase &operator=(const ProtocolBase &) = delete; virtual const ProtocolName &protocolName() const = 0; @@ -43,5 +42,3 @@ namespace kagome::network { }; } // namespace kagome::network - -#endif // KAGOME_NETWORK_PEERING_CONFIG From a218191f01be9bf7b082d61ebf0e9fc38d1322fc Mon Sep 17 00:00:00 2001 From: kamilsa Date: Fri, 1 Sep 2023 00:27:08 +0600 Subject: [PATCH 3/3] Update README.md (#1778) --- README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b83d66dddf..9076550ec5 100644 --- a/README.md +++ b/README.md @@ -11,23 +11,79 @@ KAGOME is a [Polkadot Host](https://github.com/w3f/polkadot-spec/tree/master/hos ## Status -- [x] Syncing node - - Polkadot, Kusama and Rococo compatibility -- [x] Validating node -- [x] Polkadot JS apps support -- [ ] Parachains support +![kagome-components-Host drawio-light](https://github.com/soramitsu/kagome/assets/9370151/323c1677-b628-468c-adb8-5c09c2164fc3) + + +- [x] JSON-RPC (compatible with Polkadot JS) + - [ ] New [unstable JSON-RPC](https://paritytech.github.io/json-rpc-interface-spec/) +- [x] Scale codec +- [x] Synchronizer + - [x] Full sync + - [x] Fast sync + - [x] Warp sync +- [x] Transaction pool +- [x] Consensus + - [x] BABE + - [x] GRANDPA + - [ ] SASSAFRAS (Q4 2023) +- [x] Storage + - [x] Blockchain + - [x] Block storage + - [x] Block tree + - [x] Digest tracker + - [x] Trie storage (merkle trie) + - [x] RocksDB + - [x] Dynamic pruning + - [ ] Trie nodes caches (Q4 2023) + - [ ] State caches (Q4 2023) +- [x] Runtime + - [x] Host API + - [x] WASM engine + - [x] Binaryen + - [x] WAVM + - [ ] WasmEdge (planned for Q3 2023) +- [x] Parachains core - [x] Non-asynchronous Backing - [x] Data availability - [x] Approval voting - - [ ] Disputes resolution + - [x] Disputes resolution + - [ ] Async-Backing (planned for Q3 2023) +- [x] Networking + - [x] Peer manager + - [x] /dot/block-announces/1 + - [x] /paritytech/grandpa/1 + - [x] /polkadot/validation/1 + - [x] /polkadot/collation/1 + - [x] /dot/transactions/1 + - [x] /polkadot/req_collation/1 + - [x] /dot/light/2 + - [x] /polkadot/req_pov/1 + - [x] /dot/state/2 + - [x] /dot/sync/warp + - [x] /polkadot/req_statement/1 + - [x] /dot/sync/2 + - [x] /polkadot/req_available_data/1 + - [x] /polkadot/req_chunk/1 + - [x] /polkadot/send_dispute/1 + - [x] Libp2p + - [x] Transport + - [x] TCP + - [ ] QUIC (Q4 2023) + - [ ] WebRTC (Q4 2023) + - [x] Secure connection + - [x] Noise + - [x] TLS + - [x] Multiplexing + - [x] Yamux + - [x] Multiselect protocol + - [x] Peer discovery + - [x] Kademlia + - [x] Ping protocol + - [x] Identify protocol - [x] Offchain workers +- [x] Keystore - [x] Telemetry support - [x] Prometheus metrics -- [x] Fast sync -- [ ] Warp sync - - [x] Incoming connections - - [ ] Outcoming connections -- [x] Light client protocol More details of KAGOME development can be found within the [supported features](./README.md/#supported-features) section and in [projects board](https://github.com/soramitsu/kagome/projects/2) @@ -201,4 +257,5 @@ You can find more information about the components by checking [reference docume * Press-release: [Soramitsu to implement Polkadot Runtime Environment in C++](https://medium.com/web3foundation/w3f-grants-soramitsu-to-implement-polkadot-runtime-environment-in-c-cf3baa08cbe6) * [KAGOME: C++ implementation of PRE](https://www.youtube.com/watch?v=181mk2xvBZ4&t=) presentation at DOTCon (18.08.19) * [KAGOME and consensus in Polkadot](https://www.youtube.com/watch?v=5OrevTjaiPA) presentation (in Russian) during Innopolis blockchain meetup (28.10.19) -* [Web3 Builders: Soramitsu | C++ Implementation of Polkadot Host](https://www.youtube.com/watch?v=We3kiGzg60w) Polkadot's Web3 builders online presentation +* [Web3 Builders: Soramitsu | C++ Implementation of Polkadot Host](https://www.youtube.com/watch?v=We3kiGzg60w) Polkadot's Web3 builders online presentation +* [Building alternative clients](https://youtu.be/TnENz6I9l8A?si=yF4oo2zQ6LdPW13N) Polkadot Decoded 2023 presentation