From 100a659369225f1825b3559cd0f416d61a53f0fc Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:44:35 -0400 Subject: [PATCH 01/12] Split out protocol_native_configuration. --- Makefile.am | 1 + .../libbitcoin-server.vcxproj | 1 + .../libbitcoin-server.vcxproj.filters | 3 + .../libbitcoin-server.vcxproj | 1 + .../libbitcoin-server.vcxproj.filters | 3 + .../native/protocol_native_configuration.cpp | 82 +++++++++++++++++++ 6 files changed, 91 insertions(+) create mode 100644 src/protocols/native/protocol_native_configuration.cpp diff --git a/Makefile.am b/Makefile.am index 9f5b7bed..6310a45e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,7 @@ src_libbitcoin_server_la_SOURCES = \ src/protocols/native/protocol_native.cpp \ src/protocols/native/protocol_native_address.cpp \ src/protocols/native/protocol_native_block.cpp \ + src/protocols/native/protocol_native_configuration.cpp \ src/protocols/native/protocol_native_input.cpp \ src/protocols/native/protocol_native_output.cpp \ src/protocols/native/protocol_native_tx.cpp \ diff --git a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj index feb21832..1cb33e91 100644 --- a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj @@ -147,6 +147,7 @@ + diff --git a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters index e1ca819f..61c5e7cb 100644 --- a/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -141,6 +141,9 @@ src\protocols\native + + src\protocols\native + src\protocols\native diff --git a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj index bd7a8a8c..2146c850 100644 --- a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj @@ -147,6 +147,7 @@ + diff --git a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters index e1ca819f..61c5e7cb 100644 --- a/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2026/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -141,6 +141,9 @@ src\protocols\native + + src\protocols\native + src\protocols\native diff --git a/src/protocols/native/protocol_native_configuration.cpp b/src/protocols/native/protocol_native_configuration.cpp new file mode 100644 index 00000000..a1496279 --- /dev/null +++ b/src/protocols/native/protocol_native_configuration.cpp @@ -0,0 +1,82 @@ +/** + * 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 +#include + +namespace libbitcoin { +namespace server { + +bool protocol_native::handle_get_configuration(const code& ec, + interface::configuration, uint8_t, uint8_t media) NOEXCEPT +{ + if (stopped(ec)) + return false; + + if (media != json) + { + send_not_acceptable(); + return true; + } + + BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) + boost::json::object object + { + { "address", archive().address_enabled() }, + { "filter", archive().filter_enabled() }, + { "turbo", database_settings().turbo }, + { "witness", network_settings().witness_node() }, + { "retarget", system_settings().forks.retarget }, + { "difficult", system_settings().forks.difficult }, + }; + BC_POP_WARNING() + + send_json(std::move(object), 64); + return true; +} + +// TODO: add log level(s) param. +bool protocol_native::handle_get_log_subscribe(const code& ec, + interface::log_subscribe, uint8_t , uint8_t , + bool stop) NOEXCEPT +{ + if (stopped(ec)) + return false; + + // TODO: return enumeration (on stop?). + log_subscribe_.store(stop); + return {}; +} + +// TODO: add event(s) param. +bool protocol_native::handle_get_event_subscribe(const code& ec, + interface::event_subscribe, uint8_t , uint8_t , + bool stop) NOEXCEPT +{ + if (stopped(ec)) + return false; + + // TODO: return enumeration (on stop?). + event_subscribe_.store(stop); + return {}; +} + +} // namespace server +} // namespace libbitcoin From 4538a297dc7c5d552af00939642ba4c21f4ed11b Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:45:41 -0400 Subject: [PATCH 02/12] Define notification strand. --- include/bitcoin/server/protocols/protocol_native.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/bitcoin/server/protocols/protocol_native.hpp b/include/bitcoin/server/protocols/protocol_native.hpp index 3b913402..09cbef6b 100644 --- a/include/bitcoin/server/protocols/protocol_native.hpp +++ b/include/bitcoin/server/protocols/protocol_native.hpp @@ -43,6 +43,7 @@ class BCS_API protocol_native const network::channel::ptr& channel, const options_t& options) NOEXCEPT : protocol_html(session, channel, options), + notification_strand_(channel->service().get_executor()), network::tracker(session->log) { } @@ -230,6 +231,9 @@ class BCS_API protocol_native database::header_link to_header(const std::optional& height, const std::optional& hash) NOEXCEPT; + // This is thread safe, uses network threadpool. + network::asio::strand notification_strand_; + // These are thread safe. std::atomic_bool stopping_{}; From 111b86289e6bcd7ded42405bf7eb0541d99105a2 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:53:06 -0400 Subject: [PATCH 03/12] Implement protocol_native chaser event handlers. --- .../server/protocols/protocol_native.hpp | 25 ++- src/protocols/native/protocol_native.cpp | 149 +++++++++++++----- .../native/protocol_native_block.cpp | 11 +- src/protocols/native/protocol_native_tx.cpp | 7 +- 4 files changed, 139 insertions(+), 53 deletions(-) diff --git a/include/bitcoin/server/protocols/protocol_native.hpp b/include/bitcoin/server/protocols/protocol_native.hpp index 09cbef6b..118d622d 100644 --- a/include/bitcoin/server/protocols/protocol_native.hpp +++ b/include/bitcoin/server/protocols/protocol_native.hpp @@ -64,7 +64,14 @@ class BCS_API protocol_native void dispatch_websocket( const network::http::request& request) NOEXCEPT override; - /// REST interface handlers. + + /// Event handlers. + /// ----------------------------------------------------------------------- + + bool handle_event(const code&, node::chase event_, + node::event_value) NOEXCEPT; + + /// Interface handlers. /// ----------------------------------------------------------------------- bool handle_get_configuration(const code& ec, interface::configuration, @@ -175,8 +182,16 @@ class BCS_API protocol_native bool handle_get_event_subscribe(const code& ec, interface::event_subscribe, uint8_t version, uint8_t media, bool stop) NOEXCEPT; -private: +protected: using media_type = network::http::media_type; + + /// Notification event handlers. + /// ----------------------------------------------------------------------- + void do_top(node::header_t link, media_type media) NOEXCEPT; + void do_block(node::header_t link, media_type media) NOEXCEPT; + void do_transaction(node::transaction_t link, media_type media) NOEXCEPT; + +private: static constexpr uint8_t text = to_value(media_type::text_plain); static constexpr uint8_t json = to_value(media_type::application_json); static constexpr uint8_t data = to_value( @@ -238,9 +253,9 @@ class BCS_API protocol_native std::atomic_bool stopping_{}; // Unconditional (all). - std::atomic_bool top_subscribe_{}; - std::atomic_bool block_subscribe_{}; - std::atomic_bool tx_subscribe_{}; + std::atomic top_subscribe_{ media_type::unknown }; + std::atomic block_subscribe_{ media_type::unknown }; + std::atomic tx_subscribe_{ media_type::unknown }; // TODO: map of outpoints (notify on spenders). std::atomic_bool output_subscribe_{}; diff --git a/src/protocols/native/protocol_native.cpp b/src/protocols/native/protocol_native.cpp index c82cc620..b9b3ec8b 100644 --- a/src/protocols/native/protocol_native.cpp +++ b/src/protocols/native/protocol_native.cpp @@ -28,6 +28,7 @@ namespace server { using namespace system; using namespace network; using namespace std::placeholders; +constexpr auto relaxed = std::memory_order_relaxed; #define CLASS protocol_native #define SUBSCRIBE_NATIVE(method, ...) \ @@ -166,63 +167,135 @@ void protocol_native::dispatch_websocket(const http::request& request) NOEXCEPT } } -// Handlers. +// Event handlers. // ---------------------------------------------------------------------------- -bool protocol_native::handle_get_configuration(const code& ec, - interface::configuration, uint8_t, uint8_t media) NOEXCEPT +// capture chaser events +bool protocol_native::handle_event(const code&, node::chase event_, + node::event_value value) NOEXCEPT { - if (stopped(ec)) + // Do not pass ec to stopped as it is not a call status. + if (stopped()) return false; - if (media != json) + switch (event_) { - send_not_acceptable(); - return true; + case node::chase::organized: + { + auto media = top_subscribe_.load(relaxed); + if (media != media_type::unknown) + { + // Increments height above a fork point (start/reorg). + BC_ASSERT(std::holds_alternative(value)); + POST(do_top, std::get(value), media); + } + + media = block_subscribe_.load(relaxed); + if (media != media_type::unknown) + { + // No block emission for a fork point (start/reorg). + BC_ASSERT(std::holds_alternative(value)); + POST(do_block, std::get(value), media); + } + + break; + } + case node::chase::reorganized: + { + const auto media = top_subscribe_.load(relaxed); + if (media != media_type::unknown) + { + // Resets subscriber height to the fork point. + BC_ASSERT(std::holds_alternative(value)); + POST(do_top, std::get(value), media); + break; + } + } + case node::chase::transaction: + { + const auto media = tx_subscribe_.load(relaxed); + if (media != media_type::unknown) + { + BC_ASSERT(std::holds_alternative(value)); + POST(do_transaction, std::get(value), media); + } + + break; + } + default: + { + break; + } } - BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) - boost::json::object object - { - { "address", archive().address_enabled() }, - { "filter", archive().filter_enabled() }, - { "turbo", database_settings().turbo }, - { "witness", network_settings().witness_node() }, - { "retarget", system_settings().forks.retarget }, - { "difficult", system_settings().forks.difficult }, - }; - BC_POP_WARNING() - - send_json(std::move(object), 64); return true; } -// TODO: add log level(s) param. -bool protocol_native::handle_get_log_subscribe(const code& ec, - interface::log_subscribe, uint8_t , uint8_t , - bool stop) NOEXCEPT +BC_PUSH_WARNING(NO_INCOMPLETE_SWITCH) + +void protocol_native::do_top(node::header_t link, media_type media) NOEXCEPT { - if (stopped(ec)) - return false; + BC_ASSERT(stranded()); - // TODO: return enumeration (on stop?). - log_subscribe_.store(stop); - return {}; + // TODO: notification. + const auto height = archive().get_height(link).value; + switch (to_value(media)) + { + case data: + send_chunk(to_little_endian_size(height)); + return; + case text: + send_text(encode_base16(to_little_endian_size(height))); + return; + case json: + send_json(height, two * sizeof(height)); + return; + } } -// TODO: add event(s) param. -bool protocol_native::handle_get_event_subscribe(const code& ec, - interface::event_subscribe, uint8_t , uint8_t , - bool stop) NOEXCEPT +void protocol_native::do_block(node::header_t link, media_type media) NOEXCEPT { - if (stopped(ec)) - return false; + BC_ASSERT(stranded()); - // TODO: return enumeration (on stop?). - event_subscribe_.store(stop); - return {}; + // TODO: notification. + const auto hash = archive().get_header_key(link); + switch (to_value(media)) + { + case data: + send_chunk(to_chunk(hash)); + return; + case text: + send_text(encode_base16(hash)); + return; + case json: + send_json(value_from(encode_base16(hash)), two * hash_size); + return; + } +} + +void protocol_native::do_transaction(node::transaction_t link, + media_type media) NOEXCEPT +{ + BC_ASSERT(stranded()); + + // TODO: notification. + const auto hash = archive().get_tx_key(link); + switch (to_value(media)) + { + case data: + send_chunk(to_chunk(hash)); + return; + case text: + send_text(encode_base16(hash)); + return; + case json: + send_json(value_from(encode_base16(hash)), two * hash_size); + return; + } } +BC_POP_WARNING() + // Utilities. // ---------------------------------------------------------------------------- // private diff --git a/src/protocols/native/protocol_native_block.cpp b/src/protocols/native/protocol_native_block.cpp index bf9a5344..75251a9e 100644 --- a/src/protocols/native/protocol_native_block.cpp +++ b/src/protocols/native/protocol_native_block.cpp @@ -64,8 +64,8 @@ bool protocol_native::handle_get_top_subscribe(const code& ec, if (stopped(ec)) return false; - // TODO: return only bool (previous state) if stop. - top_subscribe_.store(stop); + // TODO: return only bool (previous state) if stop? + top_subscribe_.store(stop ? media_type::unknown : (media_type)media); return handle_get_top(ec, {}, version, media); } @@ -500,14 +500,13 @@ bool protocol_native::handle_get_block_tx(const code& ec, interface::block_tx, } bool protocol_native::handle_get_block_subscribe(const code& ec, - interface::block_subscribe, uint8_t version, uint8_t media, - bool stop) NOEXCEPT + interface::block_subscribe, uint8_t, uint8_t media, bool stop) NOEXCEPT { if (stopped(ec)) return false; - // TODO: return only bool (previous state) if stop. - block_subscribe_.store(stop); + // TODO: return only bool (previous state) if stop? + block_subscribe_.store(stop ? media_type::unknown : (media_type)media); // Return top block hash upon block subscription. const auto& query = archive(); diff --git a/src/protocols/native/protocol_native_tx.cpp b/src/protocols/native/protocol_native_tx.cpp index 006d78fb..f977bd2d 100644 --- a/src/protocols/native/protocol_native_tx.cpp +++ b/src/protocols/native/protocol_native_tx.cpp @@ -171,15 +171,14 @@ bool protocol_native::handle_get_tx_details(const code& ec, } bool protocol_native::handle_get_tx_subscribe(const code& ec, - interface::tx_subscribe, uint8_t , uint8_t , - bool stop) NOEXCEPT + interface::tx_subscribe, uint8_t, uint8_t media, bool stop) NOEXCEPT { if (stopped(ec)) return false; - tx_subscribe_.store(stop); + // TODO: return bool (previous state) only? + tx_subscribe_.store(stop ? media_type::unknown : (media_type)media); - // TODO: return bool (previous state) only. send_ok(); return true; } From e61b35b6a607d6e4cb8cdd9ed22432c3fbd6a098 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:53:25 -0400 Subject: [PATCH 04/12] Style. --- .../bitcoin/server/protocols/protocol_electrum.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/bitcoin/server/protocols/protocol_electrum.hpp b/include/bitcoin/server/protocols/protocol_electrum.hpp index 05236111..622e63a3 100644 --- a/include/bitcoin/server/protocols/protocol_electrum.hpp +++ b/include/bitcoin/server/protocols/protocol_electrum.hpp @@ -314,6 +314,13 @@ class BCS_API protocol_electrum } private: + // Aliases. + using array_t = network::rpc::array_t; + using object_t = network::rpc::object_t; + using version_t = protocol_electrum_version; + static constexpr electrum::version minimum = version_t::minimum; + static constexpr electrum::version maximum = version_t::maximum; + // Post to notification strand. template inline auto notify(Method&& method, Args&&... args) NOEXCEPT @@ -322,13 +329,6 @@ class BCS_API protocol_electrum BIND_SAFE(BIND_SHARED(method, args))); } - // Aliases. - using array_t = network::rpc::array_t; - using object_t = network::rpc::object_t; - using version_t = protocol_electrum_version; - static constexpr electrum::version minimum = version_t::minimum; - static constexpr electrum::version maximum = version_t::maximum; - // Transformations. static array_t transform(const unspents& unspents) NOEXCEPT; static array_t transform(const histories& histories) NOEXCEPT; From 62e3b7a97c24557fefe564cac825aeedbe3c837c Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:53:36 -0400 Subject: [PATCH 05/12] Fix variant type mismatch in protocol_electrum do_reorganized(). --- src/protocols/electrum/protocol_electrum.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocols/electrum/protocol_electrum.cpp b/src/protocols/electrum/protocol_electrum.cpp index 1cbefb15..6de22b33 100644 --- a/src/protocols/electrum/protocol_electrum.cpp +++ b/src/protocols/electrum/protocol_electrum.cpp @@ -170,9 +170,9 @@ bool protocol_electrum::handle_event(const code&, node::chase event_, } case node::chase::reorganized: { - // value is regression branch_point. - BC_ASSERT(std::holds_alternative(value)); - POST_NOTIFY(do_reorganized, std::get(value)); + // Value is regression branch_point. + BC_ASSERT(std::holds_alternative(value)); + POST_NOTIFY(do_reorganized, std::get(value)); break; } default: @@ -195,7 +195,7 @@ void protocol_electrum::do_reorganized(node::header_t) NOEXCEPT for (auto& [key, sub]: address_subscriptions_) { - // flush resets hash accumulator, sub.type remains unchanged. + // Flush resets hash accumulator, sub.type remains unchanged. sub.accumulator.flush(); sub.status = {}; sub.cursor = {}; From b1425b911189f2ded9d19b0e828d7273098b38b4 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:54:01 -0400 Subject: [PATCH 06/12] Add protocol_native::notify<>(). --- include/bitcoin/server/protocols/protocol_native.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/bitcoin/server/protocols/protocol_native.hpp b/include/bitcoin/server/protocols/protocol_native.hpp index 118d622d..e9bb5150 100644 --- a/include/bitcoin/server/protocols/protocol_native.hpp +++ b/include/bitcoin/server/protocols/protocol_native.hpp @@ -194,8 +194,15 @@ class BCS_API protocol_native private: static constexpr uint8_t text = to_value(media_type::text_plain); static constexpr uint8_t json = to_value(media_type::application_json); - static constexpr uint8_t data = to_value( - media_type::application_octet_stream); + static constexpr uint8_t data = to_value(media_type::application_octet_stream); + + // Post to notification strand. + template + inline auto notify(Method&& method, Args&&... args) NOEXCEPT + { + return boost::asio::post(notification_strand_, + BIND_SAFE(BIND_SHARED(method, args))); + } // Serializers. // ------------------------------------------------------------------------ From eb123aea46c84f89c51d56d2c668efe8d6d787f2 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 01:54:29 -0400 Subject: [PATCH 07/12] Add protocol_native subscriber stop test case. --- test/protocols/native/native_block.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/protocols/native/native_block.cpp b/test/protocols/native/native_block.cpp index c62ffcc1..61ea6a4b 100644 --- a/test/protocols/native/native_block.cpp +++ b/test/protocols/native/native_block.cpp @@ -118,4 +118,13 @@ BOOST_AUTO_TEST_CASE(native__ws_top_subscribe__json__expected) BOOST_REQUIRE_EQUAL(response.as_int64(), 9); } +BOOST_AUTO_TEST_CASE(native__ws_top_subscribe__stop__expected) +{ + BOOST_REQUIRE(!ws_upgrade()); + + const auto response = ws_get_json("/v1/top/subscribe?stop=true"); + BOOST_REQUIRE(response.is_int64()); + BOOST_REQUIRE_EQUAL(response.as_int64(), 9); +} + BOOST_AUTO_TEST_SUITE_END() From a8a1426f07921001305de4dbd00417d23a1cb342 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 02:44:35 -0400 Subject: [PATCH 08/12] Style, delint. --- src/protocols/native/protocol_native.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/protocols/native/protocol_native.cpp b/src/protocols/native/protocol_native.cpp index b9b3ec8b..1d88a2e7 100644 --- a/src/protocols/native/protocol_native.cpp +++ b/src/protocols/native/protocol_native.cpp @@ -208,8 +208,9 @@ bool protocol_native::handle_event(const code&, node::chase event_, // Resets subscriber height to the fork point. BC_ASSERT(std::holds_alternative(value)); POST(do_top, std::get(value), media); - break; } + + break; } case node::chase::transaction: { @@ -268,7 +269,9 @@ void protocol_native::do_block(node::header_t link, media_type media) NOEXCEPT send_text(encode_base16(hash)); return; case json: + BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) send_json(value_from(encode_base16(hash)), two * hash_size); + BC_POP_WARNING() return; } } @@ -289,7 +292,9 @@ void protocol_native::do_transaction(node::transaction_t link, send_text(encode_base16(hash)); return; case json: + BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) send_json(value_from(encode_base16(hash)), two * hash_size); + BC_POP_WARNING() return; } } From 06b5762b14e7a6f0f63f75ef7e53156c3d7c4096 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 03:22:35 -0400 Subject: [PATCH 09/12] Add typed notification senders to protocol.html. --- .../server/protocols/protocol_html.hpp | 8 +++++ src/protocols/protocol_html.cpp | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/bitcoin/server/protocols/protocol_html.hpp b/include/bitcoin/server/protocols/protocol_html.hpp index 3e530b4d..747d2691 100644 --- a/include/bitcoin/server/protocols/protocol_html.hpp +++ b/include/bitcoin/server/protocols/protocol_html.hpp @@ -75,6 +75,14 @@ class BCS_API protocol_html network::http::media_type type, const network::http::request& request={}) NOEXCEPT; + /// Notifiers (websocket). + virtual void notify_json(boost::json::value&& model, size_t size_hint, + const network::http::request& request = {}) NOEXCEPT; + virtual void notify_text(std::string&& hexidecimal, + const network::http::request& request = {}) NOEXCEPT; + virtual void notify_chunk(system::data_chunk&& bytes, + const network::http::request& request = {}) NOEXCEPT; + /// Utilities. std::filesystem::path to_path( const std::string& target = "/") const NOEXCEPT; diff --git a/src/protocols/protocol_html.cpp b/src/protocols/protocol_html.cpp index 26e04e61..1dabca42 100644 --- a/src/protocols/protocol_html.cpp +++ b/src/protocols/protocol_html.cpp @@ -257,6 +257,40 @@ void protocol_html::send_buffer(buffer_body::value_type&& buffer, SEND(std::move(response), handle_complete, _1, error::success); } +// Notifiers (websocket). +// ---------------------------------------------------------------------------- + +void protocol_html::notify_json(boost::json::value&& model, size_t size_hint, + const request& request) NOEXCEPT +{ + BC_ASSERT(stranded()); + response response{ status::ok, request.version() }; + response.body() = json_value + { + .model = std::move(model), + .size_hint = size_hint + }; + NOTIFY(std::move(response), handle_complete, _1, error::success); +} + +void protocol_html::notify_text(std::string&& hexidecimal, + const request& request) NOEXCEPT +{ + BC_ASSERT(stranded()); + response response{ status::ok, request.version() }; + response.body() = std::move(hexidecimal); + NOTIFY(std::move(response), handle_complete, _1, error::success); +} + +void protocol_html::notify_chunk(system::data_chunk&& bytes, + const request& request) NOEXCEPT +{ + BC_ASSERT(stranded()); + response response{ status::ok, request.version() }; + response.body() = std::move(bytes); + NOTIFY(std::move(response), handle_complete, _1, error::success); +} + // Utilities. // ---------------------------------------------------------------------------- From 665d52613920cd3f9bff7eb91621d6bc47f19d22 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 03:24:05 -0400 Subject: [PATCH 10/12] Use new notify senders for notifications. --- src/protocols/native/protocol_native.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/protocols/native/protocol_native.cpp b/src/protocols/native/protocol_native.cpp index 1d88a2e7..63f8d238 100644 --- a/src/protocols/native/protocol_native.cpp +++ b/src/protocols/native/protocol_native.cpp @@ -243,13 +243,13 @@ void protocol_native::do_top(node::header_t link, media_type media) NOEXCEPT switch (to_value(media)) { case data: - send_chunk(to_little_endian_size(height)); + notify_chunk(to_little_endian_size(height)); return; case text: - send_text(encode_base16(to_little_endian_size(height))); + notify_text(encode_base16(to_little_endian_size(height))); return; case json: - send_json(height, two * sizeof(height)); + notify_json(height, two * sizeof(height)); return; } } @@ -263,14 +263,14 @@ void protocol_native::do_block(node::header_t link, media_type media) NOEXCEPT switch (to_value(media)) { case data: - send_chunk(to_chunk(hash)); + notify_chunk(to_chunk(hash)); return; case text: - send_text(encode_base16(hash)); + notify_text(encode_base16(hash)); return; case json: BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) - send_json(value_from(encode_base16(hash)), two * hash_size); + notify_json(value_from(encode_base16(hash)), two * hash_size); BC_POP_WARNING() return; } @@ -286,14 +286,14 @@ void protocol_native::do_transaction(node::transaction_t link, switch (to_value(media)) { case data: - send_chunk(to_chunk(hash)); + notify_chunk(to_chunk(hash)); return; case text: - send_text(encode_base16(hash)); + notify_text(encode_base16(hash)); return; case json: BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) - send_json(value_from(encode_base16(hash)), two * hash_size); + notify_json(value_from(encode_base16(hash)), two * hash_size); BC_POP_WARNING() return; } From f4dc213c7edd49a6c3916a3165f8bc4ac69e5695 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 03:24:15 -0400 Subject: [PATCH 11/12] Disable unused code. --- .../bitcoin/server/protocols/protocol_native.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/bitcoin/server/protocols/protocol_native.hpp b/include/bitcoin/server/protocols/protocol_native.hpp index e9bb5150..5620466a 100644 --- a/include/bitcoin/server/protocols/protocol_native.hpp +++ b/include/bitcoin/server/protocols/protocol_native.hpp @@ -196,13 +196,13 @@ class BCS_API protocol_native static constexpr uint8_t json = to_value(media_type::application_json); static constexpr uint8_t data = to_value(media_type::application_octet_stream); - // Post to notification strand. - template - inline auto notify(Method&& method, Args&&... args) NOEXCEPT - { - return boost::asio::post(notification_strand_, - BIND_SAFE(BIND_SHARED(method, args))); - } + ////// Post to notification strand (use POST_NOTIFY()). + ////template + ////inline auto notify(Method&& method, Args&&... args) NOEXCEPT + ////{ + //// return boost::asio::post(notification_strand_, + //// BIND_SAFE(BIND_SHARED(method, args))); + ////} // Serializers. // ------------------------------------------------------------------------ From d5eeafd5876807962c5bdcb7edf4033c3c63e442 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 16 May 2026 04:09:57 -0400 Subject: [PATCH 12/12] Make handle_get_tx_subscribe send_ok a proper empty notify. --- src/protocols/native/protocol_native_tx.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/protocols/native/protocol_native_tx.cpp b/src/protocols/native/protocol_native_tx.cpp index f977bd2d..1eef593a 100644 --- a/src/protocols/native/protocol_native_tx.cpp +++ b/src/protocols/native/protocol_native_tx.cpp @@ -25,6 +25,9 @@ namespace libbitcoin { namespace server { using namespace system; +using namespace std::placeholders; + +#define CLASS protocol_native BC_PUSH_WARNING(NO_INCOMPLETE_SWITCH) BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) @@ -179,7 +182,11 @@ bool protocol_native::handle_get_tx_subscribe(const code& ec, // TODO: return bool (previous state) only? tx_subscribe_.store(stop ? media_type::unknown : (media_type)media); - send_ok(); + // TODO: move to send/notify_empty(). + using namespace network::http; + response out{}; + out.body() = empty_value{}; + NOTIFY(std::move(out), handle_complete, _1, error::success); return true; }