diff --git a/Makefile.am b/Makefile.am
index f9f99f84..7c15cfbc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,8 @@ src_libbitcoin_node_la_SOURCES = \
src/chasers/chaser_template.cpp \
src/chasers/chaser_transaction.cpp \
src/chasers/chaser_validate.cpp \
+ src/messages/block.cpp \
+ src/messages/transaction.cpp \
src/protocols/protocol.cpp \
src/protocols/protocol_block_in_106.cpp \
src/protocols/protocol_block_in_31800.cpp \
@@ -149,6 +151,12 @@ 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_messagesdir = ${includedir}/bitcoin/node/messages
+include_bitcoin_node_messages_HEADERS = \
+ include/bitcoin/node/messages/block.hpp \
+ include/bitcoin/node/messages/messages.hpp \
+ include/bitcoin/node/messages/transaction.hpp
+
include_bitcoin_node_protocolsdir = ${includedir}/bitcoin/node/protocols
include_bitcoin_node_protocols_HEADERS = \
include/bitcoin/node/protocols/protocol.hpp \
diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
index 5e7f49b2..6a9d4dfb 100644
--- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj
@@ -137,6 +137,8 @@
+
+
@@ -183,6 +185,9 @@
+
+
+
diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
index 7ca22c13..3b8d601c 100644
--- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters
@@ -8,34 +8,37 @@
- {5FFB5F52-0772-4404-0000-000000000005}
+ {5FFB5F52-0772-4404-0000-000000000006}
- {5FFB5F52-0772-4404-0000-000000000006}
+ {5FFB5F52-0772-4404-0000-000000000007}
- {5FFB5F52-0772-4404-0000-000000000007}
+ {5FFB5F52-0772-4404-0000-000000000008}
- {5FFB5F52-0772-4404-0000-000000000008}
+ {5FFB5F52-0772-4404-0000-000000000009}
- {5FFB5F52-0772-4404-0000-000000000009}
+ {5FFB5F52-0772-4404-0000-00000000000A}
- {5FFB5F52-0772-4404-0000-00000000000A}
+ {5FFB5F52-0772-4404-0000-00000000000B}
- {5FFB5F52-0772-4404-0000-00000000000D}
+ {5FFB5F52-0772-4404-0000-00000000000F}
+
+
+ {5FFB5F52-0772-4404-0000-00000000000C}
- {5FFB5F52-0772-4404-0000-00000000000B}
+ {5FFB5F52-0772-4404-0000-00000000000D}
- {5FFB5F52-0772-4404-0000-00000000000C}
+ {5FFB5F52-0772-4404-0000-00000000000E}
- {5FFB5F52-0772-4404-0000-00000000000E}
+ {5FFB5F52-0772-4404-0000-000000000001}
{5FFB5F52-0772-4404-0000-000000000000}
@@ -46,12 +49,15 @@
{5FFB5F52-0772-4404-0000-000000000002}
-
+
{5FFB5F52-0772-4404-0000-000000000003}
-
+
{5FFB5F52-0772-4404-0000-000000000004}
+
+ {5FFB5F52-0772-4404-0000-000000000005}
+
@@ -102,6 +108,12 @@
src
+
+ src\messages
+
+
+ src\messages
+
src\protocols
@@ -236,6 +248,15 @@
include\bitcoin\node
+
+ include\bitcoin\node\messages
+
+
+ include\bitcoin\node\messages
+
+
+ include\bitcoin\node\messages
+
include\bitcoin\node\protocols
diff --git a/include/bitcoin/node.hpp b/include/bitcoin/node.hpp
index 064c8ee9..cef48d1b 100644
--- a/include/bitcoin/node.hpp
+++ b/include/bitcoin/node.hpp
@@ -41,6 +41,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
diff --git a/include/bitcoin/node/define.hpp b/include/bitcoin/node/define.hpp
index c6e1ba4a..ac433205 100644
--- a/include/bitcoin/node/define.hpp
+++ b/include/bitcoin/node/define.hpp
@@ -123,5 +123,6 @@ using type_id = network::messages::peer::inventory_item::type_id;
// /channels : define configuration
// full_node : define /chasers
// session : define [forward: full_node]
+// /messages : define
// /protocols : define /channels [session.hpp]
// /sessions : define /protocols [forward: full_node]
\ No newline at end of file
diff --git a/include/bitcoin/node/messages/block.hpp b/include/bitcoin/node/messages/block.hpp
new file mode 100644
index 00000000..9e57a419
--- /dev/null
+++ b/include/bitcoin/node/messages/block.hpp
@@ -0,0 +1,62 @@
+/**
+ * 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_MESSAGES_BLOCK_HPP
+#define LIBBITCOIN_NODE_MESSAGES_BLOCK_HPP
+
+#include
+
+namespace libbitcoin {
+namespace node {
+namespace messages {
+
+/// Based on network::messages::peer::block.
+struct BCN_API block
+{
+ typedef std::shared_ptr cptr;
+
+ static const network::messages::peer::identifier id;
+ static const std::string command;
+ static const uint32_t version_minimum;
+ static const uint32_t version_maximum;
+
+ // TODO: optimized translation direct to store.
+ ////static cptr deserialize(uint32_t version, const system::data_chunk& data,
+ //// bool witness=true) NOEXCEPT;
+ ////static block deserialize(uint32_t version, system::reader& source,
+ //// bool witness=true) NOEXCEPT;
+
+ /// These return false if witness or version is inconsistent with block data.
+ bool serialize(uint32_t version, const system::data_slab& data,
+ bool witness=true) const NOEXCEPT;
+ void serialize(uint32_t version, system::writer& sink,
+ bool witness=true) const NOEXCEPT;
+ size_t size(uint32_t version, bool witness=true) const NOEXCEPT;
+
+ /// Wire serialized block.
+ system::data_chunk block_data{};
+
+ /// Block contains witness data (if applicable).
+ const bool witnessed_{};
+};
+
+} // namespace messages
+} // namespace node
+} // namespace libbitcoin
+
+#endif
diff --git a/include/bitcoin/node/messages/messages.hpp b/include/bitcoin/node/messages/messages.hpp
new file mode 100644
index 00000000..3424295b
--- /dev/null
+++ b/include/bitcoin/node/messages/messages.hpp
@@ -0,0 +1,25 @@
+/**
+ * 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_MESSAGES_MESSAGES_HPP
+#define LIBBITCOIN_NODE_MESSAGES_MESSAGES_HPP
+
+#include
+#include
+
+#endif
diff --git a/include/bitcoin/node/messages/transaction.hpp b/include/bitcoin/node/messages/transaction.hpp
new file mode 100644
index 00000000..49d8f614
--- /dev/null
+++ b/include/bitcoin/node/messages/transaction.hpp
@@ -0,0 +1,66 @@
+/**
+ * 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_MESSAGES_TRANSACTION_HPP
+#define LIBBITCOIN_NODE_MESSAGES_TRANSACTION_HPP
+
+#include
+#include
+
+namespace libbitcoin {
+namespace node {
+namespace messages {
+
+/// Based on network::messages::peer::transaction.
+struct BCN_API transaction
+{
+ typedef std::shared_ptr cptr;
+
+ static const network::messages::peer::identifier id;
+ static const std::string command;
+ static const uint32_t version_minimum;
+ static const uint32_t version_maximum;
+
+ // TODO: optimized translation direct to store.
+ ////static cptr deserialize(uint32_t version, const system::data_chunk& data,
+ //// bool witness=true) NOEXCEPT;
+ ////static transaction deserialize(uint32_t version, system::reader& source,
+ //// bool witness=true) NOEXCEPT;
+
+ /// These return false if witness or version is inconsistent with tx data.
+ bool serialize(uint32_t version, const system::data_slab& data,
+ bool witness=true) const NOEXCEPT;
+ void serialize(uint32_t version, system::writer& sink,
+ bool witness=true) const NOEXCEPT;
+ size_t size(uint32_t version, bool witness=true) const NOEXCEPT;
+
+ /// Wire serialized transaction.
+ system::data_chunk tx_data{};
+
+ /// Non-witness hash of the transaction (for non-witness send optimize).
+ system::hash_digest hash{};
+
+ /// Transaction contains witness data (if applicable).
+ const bool witnessed_{};
+};
+
+} // namespace messages
+} // namespace node
+} // namespace libbitcoin
+
+#endif
diff --git a/include/bitcoin/node/sessions/session_peer.hpp b/include/bitcoin/node/sessions/session_peer.hpp
index b630f913..22c103d0 100644
--- a/include/bitcoin/node/sessions/session_peer.hpp
+++ b/include/bitcoin/node/sessions/session_peer.hpp
@@ -89,7 +89,7 @@ class session_peer
using namespace system;
using namespace network;
- using namespace messages::peer;
+ using namespace network::messages::peer;
using base = session_peer;
const auto self = this->template shared_from_base();
diff --git a/src/messages/block.cpp b/src/messages/block.cpp
new file mode 100644
index 00000000..9409442e
--- /dev/null
+++ b/src/messages/block.cpp
@@ -0,0 +1,65 @@
+/**
+ * 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 .
+ */
+#include
+
+#include
+
+namespace libbitcoin {
+namespace node {
+namespace messages {
+
+using namespace system;
+using namespace network::messages::peer;
+
+const std::string block::command = "block";
+const identifier block::id = identifier::block;
+const uint32_t block::version_minimum = level::minimum_protocol;
+const uint32_t block::version_maximum = level::maximum_protocol;
+
+// data_slab is preallocated after the message header using size().
+bool block::serialize(uint32_t version, const data_slab& data,
+ bool witness) const NOEXCEPT
+{
+ if (witness != witnessed_)
+ return false;
+
+ system::stream::out::fast out{ data };
+ system::write::bytes::fast writer{ out };
+ serialize(version, writer, witness);
+ return writer;
+}
+
+// Sender must ensure that version/witness are consistent with channel.
+void block::serialize(uint32_t, writer& sink,
+ bool BC_DEBUG_ONLY(witness)) const NOEXCEPT
+{
+ BC_ASSERT(witness == witnessed_);
+ sink.write_bytes(block_data);
+}
+
+// Sender must ensure that version/witness are consistent with channel.
+size_t block::size(uint32_t, bool BC_DEBUG_ONLY(witness)) const NOEXCEPT
+{
+ BC_ASSERT(witness == witnessed_);
+ return block_data.size();
+}
+
+} // namespace messages
+} // namespace node
+} // namespace libbitcoin
diff --git a/src/messages/transaction.cpp b/src/messages/transaction.cpp
new file mode 100644
index 00000000..17131d95
--- /dev/null
+++ b/src/messages/transaction.cpp
@@ -0,0 +1,65 @@
+/**
+ * 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 .
+ */
+#include
+
+#include
+
+namespace libbitcoin {
+namespace node {
+namespace messages {
+
+using namespace system;
+using namespace network::messages::peer;
+
+const std::string transaction::command = "tx";
+const identifier transaction::id = identifier::transaction;
+const uint32_t transaction::version_minimum = level::minimum_protocol;
+const uint32_t transaction::version_maximum = level::maximum_protocol;
+
+// data_slab is preallocated after the message header using size().
+bool transaction::serialize(uint32_t version, const data_slab& data,
+ bool witness) const NOEXCEPT
+{
+ if (witness != witnessed_)
+ return false;
+
+ system::stream::out::fast out{ data };
+ system::write::bytes::fast writer{ out };
+ serialize(version, writer, witness);
+ return writer;
+}
+
+// Sender must ensure that version/witness are consistent with channel.
+void transaction::serialize(uint32_t, writer& sink,
+ bool BC_DEBUG_ONLY(witness)) const NOEXCEPT
+{
+ BC_ASSERT(witness == witnessed_);
+ sink.write_bytes(tx_data);
+}
+
+// Sender must ensure that version/witness are consistent with channel.
+size_t transaction::size(uint32_t, bool BC_DEBUG_ONLY(witness)) const NOEXCEPT
+{
+ BC_ASSERT(witness == witnessed_);
+ return tx_data.size();
+}
+
+} // namespace messages
+} // namespace node
+} // namespace libbitcoin
diff --git a/src/protocols/protocol_block_out_106.cpp b/src/protocols/protocol_block_out_106.cpp
index d3664461..32a906e5 100644
--- a/src/protocols/protocol_block_out_106.cpp
+++ b/src/protocols/protocol_block_out_106.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
namespace libbitcoin {
namespace node {
@@ -158,7 +159,7 @@ bool protocol_block_out_106::handle_receive_get_data(const code& ec,
return true;
const auto total = ceilinged_add(backlog_.size(), size);
- if (total > messages::peer::max_inventory)
+ if (total > network::messages::peer::max_inventory)
{
LOGR("Blocks requested (" << total << ") exceeds inv limit ["
<< opposite() << "].");
@@ -210,8 +211,10 @@ void protocol_block_out_106::send_block(const code& ec) NOEXCEPT
const auto& query = archive();
const auto start = logger::now();
- const auto ptr = query.get_block(query.to_header(item.hash), witness);
- if (!ptr)
+ const auto link = query.to_header(item.hash);
+
+ node::messages::block out{ query.get_wire_block(link, witness), witness };
+ if (out.block_data.empty())
{
LOGR("Requested block " << encode_hash(item.hash) << " from ["
<< opposite() << "] not found.");
@@ -223,7 +226,7 @@ void protocol_block_out_106::send_block(const code& ec) NOEXCEPT
backlog_.pop_front();
span(events::block_usecs, start);
- SEND(messages::peer::block{ ptr }, send_block, _1);
+ SEND(std::move(out), send_block, _1);
}
// utilities
@@ -247,7 +250,7 @@ protocol_block_out_106::inventory protocol_block_out_106::create_inventory(
return inventory::factory
(
archive().get_blocks(locator.start_hashes, locator.stop_hash,
- messages::peer::max_get_blocks), type_id::block
+ network::messages::peer::max_get_blocks), type_id::block
);
}