diff --git a/include/bitcoin/network/boost.hpp b/include/bitcoin/network/boost.hpp index 8c3b11343..414e917e1 100644 --- a/include/bitcoin/network/boost.hpp +++ b/include/bitcoin/network/boost.hpp @@ -24,9 +24,13 @@ // Must pull in any base boost configuration before including boost. #include +// MSVC false positive in boost.optional 1.91.0. +BC_PUSH_WARNING(UNREACHABLE_CODE) #include #include #include +BC_POP_WARNING() + #include #include diff --git a/include/bitcoin/network/interfaces/peer_dispatch.hpp b/include/bitcoin/network/interfaces/peer_dispatch.hpp index 8150261ac..94c14cb7b 100644 --- a/include/bitcoin/network/interfaces/peer_dispatch.hpp +++ b/include/bitcoin/network/interfaces/peer_dispatch.hpp @@ -86,15 +86,15 @@ struct peer_dispatch /// TODO: this moves to peer::body::reader /// Type-erased implementation of peer::deserialize. - static inline any_t deserialize(memory& allocator, - messages::peer::identifier identifier, const system::data_chunk& data, - uint32_t version_, bool witness) NOEXCEPT + static inline any_t deserialize(messages::peer::identifier identifier, + const system::data_chunk& data, uint32_t version_, + bool witness) NOEXCEPT { switch (identifier) { RETURN_DESERIALIZED_PTR(address) RETURN_DESERIALIZED_PTR(alert) - RETURN_DESERIALIZED_PTR(block, witness, *allocator.get_arena()) + RETURN_DESERIALIZED_PTR(block, witness) RETURN_DESERIALIZED_PTR(bloom_filter_add) RETURN_DESERIALIZED_PTR(bloom_filter_clear) RETURN_DESERIALIZED_PTR(bloom_filter_load) diff --git a/include/bitcoin/network/messages/peer/detail/block.hpp b/include/bitcoin/network/messages/peer/detail/block.hpp index ba9fe7e0c..86c19643c 100644 --- a/include/bitcoin/network/messages/peer/detail/block.hpp +++ b/include/bitcoin/network/messages/peer/detail/block.hpp @@ -39,10 +39,6 @@ struct BCT_API block static const uint32_t version_minimum; static const uint32_t version_maximum; - /// Custom deserializer to accomodate memory allocator (arena). - static cptr deserialize(uint32_t version, const system::data_chunk& data, - bool witness, arena& arena) NOEXCEPT; - static cptr deserialize(uint32_t version, const system::data_chunk& data, bool witness=true) NOEXCEPT; static block deserialize(uint32_t version, system::reader& source, @@ -55,7 +51,7 @@ struct BCT_API block size_t size(uint32_t version, bool witness=true) const NOEXCEPT; - system::chain::block::cptr block_ptr; + system::chain::block_view block; }; } // namespace peer diff --git a/src/channels/channel_peer.cpp b/src/channels/channel_peer.cpp index 7c995b4af..eeb442109 100644 --- a/src/channels/channel_peer.cpp +++ b/src/channels/channel_peer.cpp @@ -284,8 +284,8 @@ void channel_peer::handle_read_payload(const code& ec, size_t payload_size, // Notify subscribers of the new message. /////////////////////////////////////////////////////////////////////////// // TODO: hack, move into peer::body::reader. - if (auto any = interface::deserialize(allocator_, head->id(), - payload_buffer_, negotiated_version(), settings().witness_node())) + if (auto any = interface::deserialize(head->id(), payload_buffer_, + negotiated_version(), settings().witness_node())) { // If object passes to another thread destruction cost is very high. if (const auto code = dispatcher_.notify(rpc::request_t diff --git a/src/messages/peer/detail/block.cpp b/src/messages/peer/detail/block.cpp index 84b77bb3a..729880533 100644 --- a/src/messages/peer/detail/block.cpp +++ b/src/messages/peer/detail/block.cpp @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include #include #include @@ -43,56 +42,15 @@ const uint32_t block::version_maximum = level::maximum_protocol; // static typename block::cptr block::deserialize(uint32_t version, - const data_chunk& data, bool witness, arena& arena) NOEXCEPT + const data_chunk& data, bool witness) NOEXCEPT { if (version < version_minimum || version > version_maximum) return {}; - // Set starting address of block allocation (nullptr if not detachable). - const auto memory = pointer_cast(arena.start(data.size())); - - istream source{ data }; - byte_reader reader{ source, &arena }; - auto& allocator = reader.get_allocator(); - const auto block = allocator.new_object(reader, witness); - - // Destruct block if created but failed to deserialize. - if (!reader && !is_null(block)) - byte_allocator::deleter(&arena); - - // Release memory if block construction or deserialization failed. - if (!reader || is_null(block)) - { - arena.release(memory); - return {}; - } - - // Cache hashes as extracted from serialized block. - block->set_hashes(data); - - // Set size of block allocation owned by memory (zero if non-detachable). - block->set_allocation(arena.detach()); - - // All block and contained object destructors should be optimized out. - return to_shared(std::shared_ptr(block, - [&arena, memory](auto ptr) NOEXCEPT - { - // Destruct and deallocate objects (nop deallocate if detachable). - byte_allocator::deleter(&arena)(ptr); + const auto message = emplace_shared( + chain::block_view{ move_copy(data), witness }); - // Deallocate detached memory (nop if not detachable). - arena.release(memory); - })); -} - -// static -typename block::cptr block::deserialize(uint32_t version, - const data_chunk& data, bool witness) NOEXCEPT -{ - // default_arena::get() returns pointer to static instance of - // system::default_arena, which is not detachable and calls into - // std::malloc() and std::free() for each individual allocation. - return deserialize(version, data, witness, *default_arena::get()); + return message->block.is_valid() ? message : nullptr; } // static @@ -100,13 +58,13 @@ block block::deserialize(uint32_t version, reader& source, bool witness) NOEXCEPT { if (version < version_minimum || version > version_maximum) - source.invalidate(); + return { chain::block_view{ data_chunk{}, witness } }; - return { to_shared(source, witness) }; + return { chain::block_view{ source.read_bytes(), witness } }; } -bool block::serialize(uint32_t version, - const system::data_slab& data, bool witness) const NOEXCEPT +bool block::serialize(uint32_t version, const data_slab& data, + bool witness) const NOEXCEPT { system::ostream sink{ data }; system::byte_writer writer{ sink }; @@ -120,15 +78,13 @@ void block::serialize(uint32_t BC_DEBUG_ONLY(version), writer& sink, BC_DEBUG_ONLY(const auto bytes = size(version, witness);) BC_DEBUG_ONLY(const auto start = sink.get_write_position();) - if (block_ptr) - block_ptr->to_data(sink, witness); - + sink.write_bytes(block.to_data(witness)); BC_ASSERT(sink && (sink.get_write_position() - start) == bytes); } size_t block::size(uint32_t, bool witness) const NOEXCEPT { - return block_ptr ? block_ptr->serialized_size(witness) : zero; + return block.is_valid() ? block.serialized_size(witness) : zero; } BC_POP_WARNING() diff --git a/test/messages/peer/detail/block.cpp b/test/messages/peer/detail/block.cpp index 5a0f30718..058d41e33 100644 --- a/test/messages/peer/detail/block.cpp +++ b/test/messages/peer/detail/block.cpp @@ -32,8 +32,9 @@ BOOST_AUTO_TEST_CASE(block__properties__always__expected) BOOST_AUTO_TEST_CASE(block__size__default__zero) { - BOOST_REQUIRE_EQUAL(peer::block{}.size(peer::level::canonical, true), zero); - BOOST_REQUIRE_EQUAL(peer::block{}.size(peer::level::canonical, false), zero); + const peer::block default_block{ { {}, {} } }; + BOOST_REQUIRE_EQUAL(default_block.size(peer::level::canonical, true), zero); + BOOST_REQUIRE_EQUAL(default_block.size(peer::level::canonical, false), zero); } BOOST_AUTO_TEST_SUITE_END()