diff --git a/Makefile.am b/Makefile.am
index 4190b9d13..4c4228838 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -83,6 +83,7 @@ src_libbitcoin_network_la_SOURCES = \
src/messages/ping.cpp \
src/messages/pong.cpp \
src/messages/reject.cpp \
+ src/messages/send_address_v2.cpp \
src/messages/send_compact.cpp \
src/messages/send_headers.cpp \
src/messages/transaction.cpp \
@@ -182,6 +183,7 @@ test_libbitcoin_network_test_SOURCES = \
test/messages/ping.cpp \
test/messages/pong.cpp \
test/messages/reject.cpp \
+ test/messages/send_address_v2.cpp \
test/messages/send_compact.cpp \
test/messages/send_headers.cpp \
test/messages/transaction.cpp \
@@ -323,6 +325,7 @@ include_bitcoin_network_messages_HEADERS = \
include/bitcoin/network/messages/ping.hpp \
include/bitcoin/network/messages/pong.hpp \
include/bitcoin/network/messages/reject.hpp \
+ include/bitcoin/network/messages/send_address_v2.hpp \
include/bitcoin/network/messages/send_compact.hpp \
include/bitcoin/network/messages/send_headers.hpp \
include/bitcoin/network/messages/transaction.hpp \
diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt
index d2d6afc2b..b246788a2 100644
--- a/builds/cmake/CMakeLists.txt
+++ b/builds/cmake/CMakeLists.txt
@@ -265,6 +265,7 @@ add_library( ${CANONICAL_LIB_NAME}
"../../src/messages/ping.cpp"
"../../src/messages/pong.cpp"
"../../src/messages/reject.cpp"
+ "../../src/messages/send_address_v2.cpp"
"../../src/messages/send_compact.cpp"
"../../src/messages/send_headers.cpp"
"../../src/messages/transaction.cpp"
@@ -388,6 +389,7 @@ if (with-tests)
"../../test/messages/ping.cpp"
"../../test/messages/pong.cpp"
"../../test/messages/reject.cpp"
+ "../../test/messages/send_address_v2.cpp"
"../../test/messages/send_compact.cpp"
"../../test/messages/send_headers.cpp"
"../../test/messages/transaction.cpp"
diff --git a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj
index 00cd4e710..0c795067c 100644
--- a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj
@@ -176,6 +176,7 @@
+
diff --git a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters
index 7f6368f6f..c4ae92dbe 100644
--- a/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-network-test/libbitcoin-network-test.vcxproj.filters
@@ -198,6 +198,9 @@
src\messages
+
+ src\messages
+
src\messages
diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj
index 7e20ff9f9..24890a483 100644
--- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj
+++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj
@@ -171,6 +171,7 @@
+
@@ -277,6 +278,7 @@
+
diff --git a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters
index ed1332aa9..7be69461f 100644
--- a/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters
+++ b/builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters
@@ -219,6 +219,9 @@
src\messages
+
+ src\messages
+
src\messages
@@ -533,6 +536,9 @@
include\bitcoin\network\messages
+
+ include\bitcoin\network\messages
+
include\bitcoin\network\messages
diff --git a/include/bitcoin/network.hpp b/include/bitcoin/network.hpp
index 7f4726cbb..cf9b11382 100644
--- a/include/bitcoin/network.hpp
+++ b/include/bitcoin/network.hpp
@@ -85,6 +85,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/include/bitcoin/network/messages/enums/identifier.hpp b/include/bitcoin/network/messages/enums/identifier.hpp
index 217e7d8ea..3ce3e3e1f 100644
--- a/include/bitcoin/network/messages/enums/identifier.hpp
+++ b/include/bitcoin/network/messages/enums/identifier.hpp
@@ -56,6 +56,7 @@ enum class identifier
ping,
pong,
reject,
+ send_address_v2,
send_compact,
send_headers,
transaction,
diff --git a/include/bitcoin/network/messages/enums/level.hpp b/include/bitcoin/network/messages/enums/level.hpp
index 6c6e64d28..f5f71001f 100644
--- a/include/bitcoin/network/messages/enums/level.hpp
+++ b/include/bitcoin/network/messages/enums/level.hpp
@@ -148,6 +148,9 @@ enum level: uint32_t
/// client filters protocol
bip157 = 70015,
+ /// send_address_v2
+ bip155 = 70016,
+
/// We require at least this of peers (for current address structure).
minimum_protocol = address_time,
diff --git a/include/bitcoin/network/messages/messages.hpp b/include/bitcoin/network/messages/messages.hpp
index 5a5a904d4..dbfb237b6 100644
--- a/include/bitcoin/network/messages/messages.hpp
+++ b/include/bitcoin/network/messages/messages.hpp
@@ -57,6 +57,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/include/bitcoin/network/messages/send_address_v2.hpp b/include/bitcoin/network/messages/send_address_v2.hpp
new file mode 100644
index 000000000..503345fdc
--- /dev/null
+++ b/include/bitcoin/network/messages/send_address_v2.hpp
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2011-2025 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_NETWORK_MESSAGES_SEND_ADDRESS_V2_HPP
+#define LIBBITCOIN_NETWORK_MESSAGES_SEND_ADDRESS_V2_HPP
+
+#include
+#include
+#include
+#include
+
+namespace libbitcoin {
+namespace network {
+namespace messages {
+
+struct BCT_API send_address_v2
+{
+ typedef std::shared_ptr cptr;
+
+ static const identifier id;
+ static const std::string command;
+ static const uint32_t version_minimum;
+ static const uint32_t version_maximum;
+
+ static size_t size(uint32_t version) NOEXCEPT;
+
+ static cptr deserialize(uint32_t version,
+ const system::data_chunk& data) NOEXCEPT;
+ static send_address_v2 deserialize(uint32_t version,
+ system::reader& source) NOEXCEPT;
+
+ bool serialize(uint32_t version,
+ const system::data_slab& data) const NOEXCEPT;
+ void serialize(uint32_t version,
+ system::writer& sink) const NOEXCEPT;
+};
+
+} // namespace messages
+} // namespace network
+} // namespace libbitcoin
+
+#endif
diff --git a/include/bitcoin/network/net/broadcaster.hpp b/include/bitcoin/network/net/broadcaster.hpp
index af5fbe9a9..aee5b1bcb 100644
--- a/include/bitcoin/network/net/broadcaster.hpp
+++ b/include/bitcoin/network/net/broadcaster.hpp
@@ -81,6 +81,7 @@ class BCT_API broadcaster
DEFINE_SUBSCRIBER(ping);
DEFINE_SUBSCRIBER(pong);
DEFINE_SUBSCRIBER(reject);
+ DEFINE_SUBSCRIBER(send_address_v2);
DEFINE_SUBSCRIBER(send_compact);
DEFINE_SUBSCRIBER(send_headers);
DEFINE_SUBSCRIBER(transaction);
@@ -128,6 +129,7 @@ class BCT_API broadcaster
NOTIFY_OVERLOAD(ping);
NOTIFY_OVERLOAD(pong);
NOTIFY_OVERLOAD(reject);
+ NOTIFY_OVERLOAD(send_address_v2);
NOTIFY_OVERLOAD(send_compact);
NOTIFY_OVERLOAD(send_headers);
NOTIFY_OVERLOAD(transaction);
@@ -171,6 +173,7 @@ class BCT_API broadcaster
SUBSCRIBER_OVERLOAD(ping);
SUBSCRIBER_OVERLOAD(pong);
SUBSCRIBER_OVERLOAD(reject);
+ SUBSCRIBER_OVERLOAD(send_address_v2);
SUBSCRIBER_OVERLOAD(send_compact);
SUBSCRIBER_OVERLOAD(send_headers);
SUBSCRIBER_OVERLOAD(transaction);
@@ -206,6 +209,7 @@ class BCT_API broadcaster
DECLARE_SUBSCRIBER(ping);
DECLARE_SUBSCRIBER(pong);
DECLARE_SUBSCRIBER(reject);
+ DECLARE_SUBSCRIBER(send_address_v2);
DECLARE_SUBSCRIBER(send_compact);
DECLARE_SUBSCRIBER(send_headers);
DECLARE_SUBSCRIBER(transaction);
diff --git a/include/bitcoin/network/net/distributor.hpp b/include/bitcoin/network/net/distributor.hpp
index 23b444c65..14bbbf58a 100644
--- a/include/bitcoin/network/net/distributor.hpp
+++ b/include/bitcoin/network/net/distributor.hpp
@@ -77,6 +77,7 @@ class BCT_API distributor
DEFINE_SUBSCRIBER(ping);
DEFINE_SUBSCRIBER(pong);
DEFINE_SUBSCRIBER(reject);
+ DEFINE_SUBSCRIBER(send_address_v2);
DEFINE_SUBSCRIBER(send_compact);
DEFINE_SUBSCRIBER(send_headers);
DEFINE_SUBSCRIBER(transaction);
@@ -153,6 +154,7 @@ class BCT_API distributor
SUBSCRIBER_OVERLOAD(ping);
SUBSCRIBER_OVERLOAD(pong);
SUBSCRIBER_OVERLOAD(reject);
+ SUBSCRIBER_OVERLOAD(send_address_v2);
SUBSCRIBER_OVERLOAD(send_compact);
SUBSCRIBER_OVERLOAD(send_headers);
SUBSCRIBER_OVERLOAD(transaction);
@@ -188,6 +190,7 @@ class BCT_API distributor
DECLARE_SUBSCRIBER(ping);
DECLARE_SUBSCRIBER(pong);
DECLARE_SUBSCRIBER(reject);
+ DECLARE_SUBSCRIBER(send_address_v2);
DECLARE_SUBSCRIBER(send_compact);
DECLARE_SUBSCRIBER(send_headers);
DECLARE_SUBSCRIBER(transaction);
diff --git a/src/messages/heading.cpp b/src/messages/heading.cpp
index 40ccb2bc9..8e3f5992e 100644
--- a/src/messages/heading.cpp
+++ b/src/messages/heading.cpp
@@ -50,6 +50,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -194,6 +195,7 @@ identifier heading::id() const NOEXCEPT
COMMAND_ID(ping),
COMMAND_ID(pong),
COMMAND_ID(reject),
+ COMMAND_ID(send_address_v2),
COMMAND_ID(send_compact),
COMMAND_ID(send_headers),
COMMAND_ID(transaction),
diff --git a/src/messages/send_address_v2.cpp b/src/messages/send_address_v2.cpp
new file mode 100644
index 000000000..473ba20bb
--- /dev/null
+++ b/src/messages/send_address_v2.cpp
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2011-2025 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
+#include
+#include
+#include
+
+namespace libbitcoin {
+namespace network {
+namespace messages {
+
+using namespace system;
+
+const std::string send_address_v2::command = "sendaddrv2";
+const identifier send_address_v2::id = identifier::send_address_v2;
+const uint32_t send_address_v2::version_minimum = level::bip155;
+const uint32_t send_address_v2::version_maximum = level::maximum_protocol;
+
+// static
+size_t send_address_v2::size(uint32_t) NOEXCEPT
+{
+ return zero;
+}
+
+// static
+typename send_address_v2::cptr send_address_v2::deserialize(uint32_t version,
+ const system::data_chunk& data) NOEXCEPT
+{
+ system::istream source{ data };
+ system::byte_reader reader{ source };
+ const auto message = to_shared(deserialize(version, reader));
+ return reader ? message : nullptr;
+}
+
+bool send_address_v2::serialize(uint32_t version,
+ const system::data_slab& data) const NOEXCEPT
+{
+ system::ostream sink{ data };
+ system::byte_writer writer{ sink };
+ serialize(version, writer);
+ return writer;
+}
+
+send_address_v2 send_address_v2::deserialize(uint32_t version, reader& source) NOEXCEPT
+{
+ if (version < version_minimum || version > version_maximum)
+ source.invalidate();
+
+ return {};
+}
+
+void send_address_v2::serialize(uint32_t BC_DEBUG_ONLY(version),
+ writer& BC_DEBUG_ONLY(sink)) const NOEXCEPT
+{
+ BC_DEBUG_ONLY(const auto bytes = size(version);)
+ BC_DEBUG_ONLY(const auto start = sink.get_write_position();)
+ BC_ASSERT(sink && sink.get_write_position() - start == bytes);
+}
+
+} // namespace messages
+} // namespace network
+} // namespace libbitcoin
diff --git a/src/net/broadcaster.cpp b/src/net/broadcaster.cpp
index debbf1f5d..521de3f47 100644
--- a/src/net/broadcaster.cpp
+++ b/src/net/broadcaster.cpp
@@ -62,6 +62,7 @@ broadcaster::broadcaster(asio::strand& strand) NOEXCEPT
MAKE_SUBSCRIBER(ping),
MAKE_SUBSCRIBER(pong),
MAKE_SUBSCRIBER(reject),
+ MAKE_SUBSCRIBER(send_address_v2),
MAKE_SUBSCRIBER(send_compact),
MAKE_SUBSCRIBER(send_headers),
MAKE_SUBSCRIBER(transaction),
@@ -100,6 +101,7 @@ void broadcaster::unsubscribe(channel_id subscriber) NOEXCEPT
UNSUBSCRIBER(ping);
UNSUBSCRIBER(pong);
UNSUBSCRIBER(reject);
+ UNSUBSCRIBER(send_address_v2);
UNSUBSCRIBER(send_compact);
UNSUBSCRIBER(send_headers);
UNSUBSCRIBER(transaction);
@@ -137,6 +139,7 @@ void broadcaster::stop(const code& ec) NOEXCEPT
STOP_SUBSCRIBER(ping);
STOP_SUBSCRIBER(pong);
STOP_SUBSCRIBER(reject);
+ STOP_SUBSCRIBER(send_address_v2);
STOP_SUBSCRIBER(send_compact);
STOP_SUBSCRIBER(send_headers);
STOP_SUBSCRIBER(transaction);
diff --git a/src/net/distributor.cpp b/src/net/distributor.cpp
index ae62fcfc1..91694634f 100644
--- a/src/net/distributor.cpp
+++ b/src/net/distributor.cpp
@@ -69,6 +69,7 @@ distributor::distributor(memory& memory, asio::strand& strand) NOEXCEPT
MAKE_SUBSCRIBER(ping),
MAKE_SUBSCRIBER(pong),
MAKE_SUBSCRIBER(reject),
+ MAKE_SUBSCRIBER(send_address_v2),
MAKE_SUBSCRIBER(send_compact),
MAKE_SUBSCRIBER(send_headers),
MAKE_SUBSCRIBER(transaction),
@@ -111,6 +112,7 @@ code distributor::notify(messages::identifier id, uint32_t version,
CASE_NOTIFY(ping);
CASE_NOTIFY(pong);
CASE_NOTIFY(reject);
+ CASE_NOTIFY(send_address_v2);
CASE_NOTIFY(send_compact);
CASE_NOTIFY(send_headers);
CASE_NOTIFY(transaction);
@@ -153,6 +155,7 @@ void distributor::stop(const code& ec) NOEXCEPT
STOP_SUBSCRIBER(ping);
STOP_SUBSCRIBER(pong);
STOP_SUBSCRIBER(reject);
+ STOP_SUBSCRIBER(send_address_v2);
STOP_SUBSCRIBER(send_compact);
STOP_SUBSCRIBER(send_headers);
STOP_SUBSCRIBER(transaction);
diff --git a/test/messages/heading.cpp b/test/messages/heading.cpp
index f0652904d..f2ebd82c0 100644
--- a/test/messages/heading.cpp
+++ b/test/messages/heading.cpp
@@ -211,6 +211,12 @@ BOOST_AUTO_TEST_CASE(heading__reject_id__always__expected)
BOOST_REQUIRE(instance.id() == reject::id);
}
+BOOST_AUTO_TEST_CASE(heading__send_address_v2_id__always__expected)
+{
+ const auto instance = heading{ 0u, send_address_v2::command, 0u, 0u };
+ BOOST_REQUIRE(instance.id() == send_address_v2::id);
+}
+
BOOST_AUTO_TEST_CASE(heading__send_compact_id__always__expected)
{
const auto instance = heading{ 0u, send_compact::command, 0u, 0u };
diff --git a/test/messages/send_address_v2.cpp b/test/messages/send_address_v2.cpp
new file mode 100644
index 000000000..55d6a53f0
--- /dev/null
+++ b/test/messages/send_address_v2.cpp
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2011-2025 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 "../test.hpp"
+
+BOOST_AUTO_TEST_SUITE(send_address_v2_tests)
+
+using namespace bc::network::messages;
+
+BOOST_AUTO_TEST_CASE(send_address_v2__properties__always__expected)
+{
+ BOOST_REQUIRE_EQUAL(send_address_v2::command, "sendaddrv2");
+ BOOST_REQUIRE(send_address_v2::id == identifier::send_address_v2);
+ BOOST_REQUIRE_EQUAL(send_address_v2::version_minimum, level::bip155);
+ BOOST_REQUIRE_EQUAL(send_address_v2::version_maximum, level::maximum_protocol);
+}
+
+BOOST_AUTO_TEST_CASE(send_address_v2__size__always__expected)
+{
+ BOOST_REQUIRE_EQUAL(send_address_v2::size(level::canonical), zero);
+}
+
+BOOST_AUTO_TEST_SUITE_END()