diff --git a/Makefile.am b/Makefile.am
index 7c15cfbc..d4bffa1b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -151,6 +151,10 @@ include_bitcoin_node_impl_chasersdir = ${includedir}/bitcoin/node/impl/chasers
include_bitcoin_node_impl_chasers_HEADERS = \
include/bitcoin/node/impl/chasers/chaser_organize.ipp
+include_bitcoin_node_impl_sessionsdir = ${includedir}/bitcoin/node/impl/sessions
+include_bitcoin_node_impl_sessions_HEADERS = \
+ include/bitcoin/node/impl/sessions/session_peer.ipp
+
include_bitcoin_node_messagesdir = ${includedir}/bitcoin/node/messages
include_bitcoin_node_messages_HEADERS = \
include/bitcoin/node/messages/block.hpp \
diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
index 6a9d4dfb..6d595fe3 100644
--- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
@@ -216,6 +216,7 @@
+
diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
index 3b8d601c..6b4100d0 100644
--- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
@@ -28,6 +28,9 @@
{5FFB5F52-0772-4404-0000-00000000000F}
+
+ {5FFB5F52-0772-4404-0000-000000000001}
+
{5FFB5F52-0772-4404-0000-00000000000C}
@@ -38,7 +41,7 @@
{5FFB5F52-0772-4404-0000-00000000000E}
- {5FFB5F52-0772-4404-0000-000000000001}
+ {5FFB5F52-0772-4404-0000-000000000002}
{5FFB5F52-0772-4404-0000-000000000000}
@@ -337,6 +340,9 @@
include\bitcoin\node\impl\chasers
+
+ include\bitcoin\node\impl\sessions
+
diff --git a/include/bitcoin/node/impl/sessions/session_peer.ipp b/include/bitcoin/node/impl/sessions/session_peer.ipp
new file mode 100644
index 00000000..03c668c6
--- /dev/null
+++ b/include/bitcoin/node/impl/sessions/session_peer.ipp
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2011-2026 libbitcoin developers (see AUTHORS)
+ *
+ * This file is part of libbitcoin.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef LIBBITCOIN_NODE_SESSIONS_SESSION_PEER_IPP
+#define LIBBITCOIN_NODE_SESSIONS_SESSION_PEER_IPP
+
+namespace libbitcoin {
+namespace node {
+
+// this-> is required for dependent base access in CRTP.
+
+TEMPLATE
+inline CLASS::channel_ptr CLASS::create_channel(
+ const socket_ptr& socket) NOEXCEPT
+{
+ BC_ASSERT(this->stranded());
+
+ const auto channel = system::emplace_shared(
+ this->get_memory(), this->log, socket, this->create_key(),
+ this->node_config(), this->options());
+
+ return std::static_pointer_cast(channel);
+}
+
+TEMPLATE
+inline void CLASS::attach_handshake(const channel_ptr& channel,
+ network::result_handler&& handler) NOEXCEPT
+{
+ BC_ASSERT(channel->stranded());
+ BC_ASSERT(channel->paused());
+
+ // Set the current top for version protocol, before handshake.
+ const auto top = this->archive().get_top_confirmed();
+ const auto peer = std::dynamic_pointer_cast(channel);
+ peer->set_start_height(top);
+
+ // Attach and execute appropriate version protocol.
+ NetworkSession::attach_handshake(channel, std::move(handler));
+}
+
+TEMPLATE
+inline void CLASS::attach_protocols(const channel_ptr& channel) NOEXCEPT
+{
+ BC_ASSERT(channel->stranded());
+ BC_ASSERT(channel->paused());
+
+ using namespace system;
+ using namespace network;
+ using namespace network::messages::peer;
+ using base = session_peer;
+
+ const auto self = this->template shared_from_base();
+ const auto relay = this->network_settings().enable_relay;
+ const auto delay = this->node_settings().delay_inbound;
+ const auto headers = this->node_settings().headers_first;
+ const auto node_network = to_bool(bit_and
+ (
+ this->network_settings().services_maximum,
+ service::node_network
+ ));
+ const auto node_client_filters = to_bool(bit_and
+ (
+ this->network_settings().services_maximum,
+ service::node_client_filters
+ ));
+
+ // Attach appropriate alert, reject, ping, and/or address protocols.
+ NetworkSession::attach_protocols(channel);
+
+ // Channel suspensions.
+ channel->attach(self)->start();
+
+ // Ready to relay blocks or block filters.
+ const auto blocks_out = !delay || this->is_recent();
+
+ ///////////////////////////////////////////////////////////////////////
+ // bip152: "Upon receipt of a `sendcmpct` message with the first and
+ // second integers set to 1, the node SHOULD announce new blocks by
+ // sending a cmpctblock message." IOW at 70014 bip152 is optional.
+ // This allows the node to support bip157 without supporting bip152.
+ ///////////////////////////////////////////////////////////////////////
+
+ const auto peer = std::dynamic_pointer_cast(channel);
+
+ // Node must advertise node_client_filters or no out filters.
+ if (node_client_filters && blocks_out &&
+ peer->is_negotiated(level::bip157))
+ channel->attach(self)->start();
+
+ // Node must advertise node_network or no in|out blocks|txs.
+ if (!node_network)
+ return;
+
+ // Ready to relay transactions.
+ const auto txs_in_out = relay && peer->is_negotiated(level::bip37) &&
+ (!delay || is_current(true));
+
+ // Peer advertises chain (blocks in).
+ if (peer->is_peer_service(service::node_network))
+ {
+ if (headers && peer->is_negotiated(level::bip130))
+ {
+ channel->attach(self)->start();
+ channel->attach(self)->start();
+
+ }
+ else if (headers && peer->is_negotiated(level::headers_protocol))
+ {
+ channel->attach(self)->start();
+ channel->attach(self)->start();
+ }
+ else
+ {
+ // Very hard to find < 31800 peer to connect with.
+ // Blocks-first synchronization (not base of block_in_31800).
+ channel->attach(self)->start();
+ }
+ }
+
+ // Blocks are ready (blocks out).
+ if (blocks_out)
+ {
+ if (headers && peer->is_negotiated(level::bip130))
+ {
+ channel->attach(self)->start();
+ channel->attach(self)->start();
+ }
+ else if (headers && peer->is_negotiated(level::headers_protocol))
+ {
+ channel->attach(self)->start();
+ channel->attach(self)->start();
+ }
+ else
+ {
+ channel->attach(self)->start();
+ }
+ }
+
+ // Relay is configured, active, and txs are ready (txs in/out).
+ if (txs_in_out)
+ {
+ if (peer->peer_version()->relay)
+ channel->attach(self)->start();
+ }
+}
+
+} // namespace node
+} // namespace libbitcoin
+
+#endif
diff --git a/include/bitcoin/node/protocols/protocol_performer.hpp b/include/bitcoin/node/protocols/protocol_performer.hpp
index 8caf09ca..4ed192f7 100644
--- a/include/bitcoin/node/protocols/protocol_performer.hpp
+++ b/include/bitcoin/node/protocols/protocol_performer.hpp
@@ -42,7 +42,7 @@ class BCN_API protocol_performer
: node::protocol_peer(session, channel),
deviation_(session->node_settings().allowed_deviation > 0.0),
enabled_(enabled && to_bool(session->node_settings().sample_period_seconds)),
- performance_timer_(std::make_shared(session->log,
+ performance_timer_(system::emplace_shared(session->log,
channel->strand(), session->node_settings().sample_period())),
network::tracker(session->log)
{
diff --git a/include/bitcoin/node/sessions/session_peer.hpp b/include/bitcoin/node/sessions/session_peer.hpp
index 22c103d0..6b4a967d 100644
--- a/include/bitcoin/node/sessions/session_peer.hpp
+++ b/include/bitcoin/node/sessions/session_peer.hpp
@@ -54,141 +54,26 @@ class session_peer
using socket_ptr = network::socket::ptr;
using channel_ptr = network::channel::ptr;
- // this-> is required for dependent base access in CRTP.
-
- channel_ptr create_channel(const socket_ptr& socket) NOEXCEPT override
- {
- BC_ASSERT(this->stranded());
-
- const auto channel = std::make_shared(
- this->get_memory(), this->log, socket, this->create_key(),
- this->node_config(), this->options());
-
- return std::static_pointer_cast(channel);
- }
-
- void attach_handshake(const channel_ptr& channel,
- network::result_handler&& handler) NOEXCEPT override
- {
- BC_ASSERT(channel->stranded());
- BC_ASSERT(channel->paused());
-
- // Set the current top for version protocol, before handshake.
- const auto top = this->archive().get_top_confirmed();
- const auto peer = std::dynamic_pointer_cast(channel);
- peer->set_start_height(top);
-
- // Attach and execute appropriate version protocol.
- NetworkSession::attach_handshake(channel, std::move(handler));
- }
-
- void attach_protocols(const channel_ptr& channel) NOEXCEPT override
- {
- BC_ASSERT(channel->stranded());
- BC_ASSERT(channel->paused());
-
- using namespace system;
- using namespace network;
- using namespace network::messages::peer;
- using base = session_peer;
-
- const auto self = this->template shared_from_base();
- const auto relay = this->network_settings().enable_relay;
- const auto delay = this->node_settings().delay_inbound;
- const auto headers = this->node_settings().headers_first;
- const auto node_network = to_bool(bit_and
- (
- this->network_settings().services_maximum,
- service::node_network
- ));
- const auto node_client_filters = to_bool(bit_and
- (
- this->network_settings().services_maximum,
- service::node_client_filters
- ));
-
- // Attach appropriate alert, reject, ping, and/or address protocols.
- NetworkSession::attach_protocols(channel);
-
- // Channel suspensions.
- channel->attach(self)->start();
-
- // Ready to relay blocks or block filters.
- const auto blocks_out = !delay || this->is_recent();
-
- ///////////////////////////////////////////////////////////////////////
- // bip152: "Upon receipt of a `sendcmpct` message with the first and
- // second integers set to 1, the node SHOULD announce new blocks by
- // sending a cmpctblock message." IOW at 70014 bip152 is optional.
- // This allows the node to support bip157 without supporting bip152.
- ///////////////////////////////////////////////////////////////////////
-
- const auto peer = std::dynamic_pointer_cast(channel);
-
- // Node must advertise node_client_filters or no out filters.
- if (node_client_filters && blocks_out &&
- peer->is_negotiated(level::bip157))
- channel->attach(self)->start();
-
- // Node must advertise node_network or no in|out blocks|txs.
- if (!node_network)
- return;
+ inline channel_ptr create_channel(
+ const socket_ptr& socket) NOEXCEPT override;
+ inline void attach_handshake(const channel_ptr& channel,
+ network::result_handler&& handler) NOEXCEPT override;
+ inline void attach_protocols(const channel_ptr& channel) NOEXCEPT override;
+};
- // Ready to relay transactions.
- const auto txs_in_out = relay && peer->is_negotiated(level::bip37) &&
- (!delay || is_current(true));
+} // namespace node
+} // namespace libbitcoin
- // Peer advertises chain (blocks in).
- if (peer->is_peer_service(service::node_network))
- {
- if (headers && peer->is_negotiated(level::bip130))
- {
- channel->attach(self)->start();
- channel->attach(self)->start();
+#define TEMPLATE template
+#define CLASS session_peer
- }
- else if (headers && peer->is_negotiated(level::headers_protocol))
- {
- channel->attach(self)->start();
- channel->attach(self)->start();
- }
- else
- {
- // Very hard to find < 31800 peer to connect with.
- // Blocks-first synchronization (not base of block_in_31800).
- channel->attach(self)->start();
- }
- }
+////BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
- // Blocks are ready (blocks out).
- if (blocks_out)
- {
- if (headers && peer->is_negotiated(level::bip130))
- {
- channel->attach(self)->start();
- channel->attach(self)->start();
- }
- else if (headers && peer->is_negotiated(level::headers_protocol))
- {
- channel->attach(self)->start();
- channel->attach(self)->start();
- }
- else
- {
- channel->attach(self)->start();
- }
- }
+#include
- // Relay is configured, active, and txs are ready (txs in/out).
- if (txs_in_out)
- {
- if (peer->peer_version()->relay)
- channel->attach(self)->start();
- }
- }
-};
+////BC_POP_WARNING()
-} // namespace node
-} // namespace libbitcoin
+#undef CLASS
+#undef TEMPLATE
#endif