From d4140340f652102e6dd6300f251ca2d6b5618d0e Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Jun 2026 01:18:16 -0400 Subject: [PATCH 1/4] Improve batch logging. --- src/chasers/chaser_validate_batch.cpp | 33 +++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/chasers/chaser_validate_batch.cpp b/src/chasers/chaser_validate_batch.cpp index 840e8406..04fc7bab 100644 --- a/src/chasers/chaser_validate_batch.cpp +++ b/src/chasers/chaser_validate_batch.cpp @@ -56,13 +56,9 @@ void chaser_validate::process_batch() NOEXCEPT // tables to be fully purged upon completion, and ensuring that evaluation // does not operate over partial block records in the batch tables. std::unique_lock lock(mutex_); - auto& query = archive(); - LOGN("Batch signature verify begin (" - << query.ecdsa_records() << ") ecdsa (" - << query.schnorr_records() << ") schnorr."); - // set_block_unconfirmable + // set_block_unconfirmable(ecdsa) // ------------------------------------------------------------------------ header_links invalids{}; @@ -72,7 +68,14 @@ void chaser_validate::process_batch() NOEXCEPT fault(error::batch2); return; } - span(events::ecdsa_msecs, start); + + if (!invalids.empty()) + { + span(events::ecdsa_msecs, start); + const auto elapsed = steady_clock::now() - start; + LOGN("Batch signature verify ecdsa (" << query.ecdsa_records() + << "/" << duration_cast(elapsed).count() << ") "); + } if (!process_invalids(invalids) || !query.purge_ecdsa_signatures()) { @@ -80,6 +83,9 @@ void chaser_validate::process_batch() NOEXCEPT return; } + // set_block_unconfirmable(schnorr) + // ------------------------------------------------------------------------ + invalids.clear(); start = network::logger::now(); if (!query.verify_schnorr_signatures(invalids)) @@ -87,7 +93,14 @@ void chaser_validate::process_batch() NOEXCEPT fault(error::batch4); return; } - span(events::schnorr_msecs, start); + + if (!invalids.empty()) + { + span(events::schnorr_msecs, start); + const auto elapsed = steady_clock::now() - start; + LOGN("Batch signature verify schnorr (" << query.schnorr_records() + << "/" << duration_cast(elapsed).count() << ") "); + } if (!process_invalids(invalids) || !query.purge_schnorr_signatures()) { @@ -95,7 +108,7 @@ void chaser_validate::process_batch() NOEXCEPT return; } - // set_block_valid + // set_block_valid(batched_ excluding ecdsa/schnorr failures) // ------------------------------------------------------------------------ if (!process_valids()) @@ -103,10 +116,6 @@ void chaser_validate::process_batch() NOEXCEPT fault(error::batch6); return; } - - // ------------------------------------------------------------------------ - - LOGN("Batch signature verify end."); } void chaser_validate::push_batch(const header_link& link, size_t height) NOEXCEPT From c6c747814148ed497d838a4747fd8fbe2d3ec2e4 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Jun 2026 18:06:04 -0400 Subject: [PATCH 2/4] Increase signature batch control and fix residual processing. --- include/bitcoin/node/chase.hpp | 4 - .../bitcoin/node/chasers/chaser_validate.hpp | 10 +- include/bitcoin/node/events.hpp | 4 +- include/bitcoin/node/settings.hpp | 3 +- src/chasers/chaser_check.cpp | 3 - src/chasers/chaser_validate.cpp | 26 ++-- src/chasers/chaser_validate_batch.cpp | 132 ++++++++++-------- src/settings.cpp | 7 +- test/settings.cpp | 3 +- 9 files changed, 96 insertions(+), 96 deletions(-) diff --git a/include/bitcoin/node/chase.hpp b/include/bitcoin/node/chase.hpp index d2416cf2..891be398 100644 --- a/include/bitcoin/node/chase.hpp +++ b/include/bitcoin/node/chase.hpp @@ -96,10 +96,6 @@ enum class chase /// Issued by 'organize' and handled by 'check', 'validate', 'confirm'. disorganized, - /// Download concurrency window completed, advancing to next (height_t). - /// Issued by 'check' and handled by 'validate'. - advanced, - /// Check/Identify. /// ----------------------------------------------------------------------- diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index b1ac864d..58147d53 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -60,7 +60,6 @@ class BCN_API chaser_validate event_value value) NOEXCEPT; virtual void do_regressed(height_t branch_point) NOEXCEPT; - virtual void do_advanced(height_t height) NOEXCEPT; virtual void do_checked(height_t height) NOEXCEPT; virtual void do_bumped(height_t height) NOEXCEPT; virtual void do_bump(height_t height) NOEXCEPT; @@ -81,8 +80,8 @@ class BCN_API chaser_validate /// Batching. virtual code start_batch() NOEXCEPT; - virtual void process_batch() NOEXCEPT; virtual bool process_valids() NOEXCEPT; + virtual void process_batch(bool residual) NOEXCEPT; virtual void push_batch(const header_link& link, size_t height) NOEXCEPT; virtual bool process_invalids(const header_links& invalids) NOEXCEPT; virtual signatures get_capture(const header_link& link) NOEXCEPT; @@ -118,8 +117,8 @@ class BCN_API chaser_validate const atomic_counter_ptr& sequence) NOEXCEPT; // Capture helpers. - void log_capture(const std::string_view& name, - size_t captured, size_t missed) const NOEXCEPT; + std::string log_ratio(const std::string& name, size_t numerator, + size_t denominator) const NOEXCEPT; void log_captures() const NOEXCEPT; // These are protected by strand. @@ -146,7 +145,8 @@ class BCN_API chaser_validate const uint32_t subsidy_interval_; const uint64_t initial_subsidy_; const size_t maximum_backlog_; - const bool batch_signatures_; + const uint64_t batch_target_; + const bool batch_enabled_; const bool node_witness_; const bool filter_; }; diff --git a/include/bitcoin/node/events.hpp b/include/bitcoin/node/events.hpp index a4f5f5e2..8ef112ac 100644 --- a/include/bitcoin/node/events.hpp +++ b/include/bitcoin/node/events.hpp @@ -62,8 +62,8 @@ enum events : uint8_t filter_msecs, // getfilter timespan in milliseconds. filterhashes_msecs, // getfilterhashes timespan in milliseconds. filterchecks_msecs, // getcfcheckpt timespan in milliseconds. - ecdsa_msecs, // process_batch ecdsa timespan in milliseconds. - schnorr_msecs, // process_batch schnorr timespan in milliseconds. + ecdsa_secs, // process_batch ecdsa timespan in seconds. + schnorr_secs, // process_batch schnorr timespan in seconds. unknown }; diff --git a/include/bitcoin/node/settings.hpp b/include/bitcoin/node/settings.hpp index 9e887f03..678f4243 100644 --- a/include/bitcoin/node/settings.hpp +++ b/include/bitcoin/node/settings.hpp @@ -40,10 +40,10 @@ class BCN_API settings bool thread_priority; bool memory_priority; bool allow_overlapped; - bool batch_signatures; float allowed_deviation; float minimum_fee_rate; float minimum_bump_rate; + uint64_t batch_signatures; uint16_t announcement_cache; uint16_t fee_estimate_horizon; uint32_t maximum_height; @@ -62,6 +62,7 @@ class BCN_API settings virtual size_t maximum_concurrency_() const NOEXCEPT; virtual size_t fee_estimate_horizon_() const NOEXCEPT; virtual bool fee_estimate_enabled() const NOEXCEPT; + virtual bool batch_signatures_enabled() const NOEXCEPT; virtual network::steady_clock::duration sample_period() const NOEXCEPT; virtual network::wall_clock::duration currency_window() const NOEXCEPT; virtual network::processing_priority thread_priority_() const NOEXCEPT; diff --git a/src/chasers/chaser_check.cpp b/src/chasers/chaser_check.cpp index fee1745c..7fb8d739 100644 --- a/src/chasers/chaser_check.cpp +++ b/src/chasers/chaser_check.cpp @@ -364,10 +364,7 @@ void chaser_check::do_advanced(height_t) NOEXCEPT // The full count of requested hashes has been validated. if (advanced_ == requested_) - { - notify(error::success, chase::advanced, advanced_); do_headers({}); - } } void chaser_check::do_checked(height_t height) NOEXCEPT diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp index 068fdf12..dab881c4 100644 --- a/src/chasers/chaser_validate.cpp +++ b/src/chasers/chaser_validate.cpp @@ -42,7 +42,8 @@ chaser_validate::chaser_validate(full_node& node) NOEXCEPT subsidy_interval_(node.system_settings().subsidy_interval_blocks), initial_subsidy_(node.system_settings().initial_subsidy()), maximum_backlog_(node.node_settings().maximum_concurrency_()), - batch_signatures_(node.node_settings().batch_signatures), + batch_target_(node.node_settings().batch_signatures), + batch_enabled_(node.node_settings().batch_signatures_enabled()), node_witness_(node.network_settings().witness_node()), filter_(node.archive().filter_enabled()) { @@ -88,16 +89,6 @@ bool chaser_validate::handle_chase(const code&, chase event_, POST(do_checked, std::get(value)); break; } - case chase::advanced: - { - if (!batch_signatures_) - break; - - // value is checked block height. - BC_ASSERT(std::holds_alternative(value)); - POST(do_advanced, std::get(value)); - break; - } case chase::regressed: case chase::disorganized: { @@ -131,12 +122,6 @@ void chaser_validate::do_regressed(height_t branch_point) NOEXCEPT set_position(branch_point); } -void chaser_validate::do_advanced(height_t) NOEXCEPT -{ - BC_ASSERT(stranded()); - process_batch(); -} - void chaser_validate::do_checked(height_t height) NOEXCEPT { BC_ASSERT(stranded()); @@ -386,6 +371,13 @@ void chaser_validate::complete_block(const code& ec, const header_link& link, // Not failed/invalid/batched/faulted, so block is complete (maybe valid). notify_block({}, height, link, bypass); + + // Arriving here with batch enabled implies that the block is current and + // was not batched. Each such block triggers residual batch processing. + if (batch_enabled_) + { + POST(process_batch, true); + } } void chaser_validate::notify_block(const code& ec, size_t height, diff --git a/src/chasers/chaser_validate_batch.cpp b/src/chasers/chaser_validate_batch.cpp index 04fc7bab..4bb61dc4 100644 --- a/src/chasers/chaser_validate_batch.cpp +++ b/src/chasers/chaser_validate_batch.cpp @@ -42,70 +42,88 @@ BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR) code chaser_validate::start_batch() NOEXCEPT { auto& query = archive(); - return (batch_signatures_ && (!query.purge_ecdsa_signatures() || + return (batch_enabled_ && (!query.purge_ecdsa_signatures() || !query.purge_schnorr_signatures())) ? error::batch1 : error::success; } -// TODO: This is only invoked by check chaser advancement. But it is possible -// that entries may be captured after that point. So this must be bumped. -void chaser_validate::process_batch() NOEXCEPT +void chaser_validate::push_batch(const header_link& link, size_t height) NOEXCEPT { BC_ASSERT(stranded()); + batched_.push_back(link); + + // chase portion of notify_block(success). + notify({}, chase::valid, possible_wide_cast(height)); + + // Process both tables when one hits target, allowing batched_ clearance + // and therefore forward confirmation progress. + process_batch(false); +} + +void chaser_validate::process_batch(bool residual) NOEXCEPT +{ + BC_ASSERT(stranded()); + + // Test outside of lock to prevent reader contention for nearly all calls. + // Will retest inside the lock, as table updates are running concurrently. + auto& query = archive(); + if (!residual && + (query.ecdsa_records() < batch_target_) && + (query.schnorr_records() < batch_target_)) + return; // Unique lock prevents batch table updates during evaluation, allowing the // tables to be fully purged upon completion, and ensuring that evaluation // does not operate over partial block records in the batch tables. std::unique_lock lock(mutex_); - auto& query = archive(); // set_block_unconfirmable(ecdsa) // ------------------------------------------------------------------------ - header_links invalids{}; - auto start = network::logger::now(); - if (!query.verify_ecdsa_signatures(invalids)) + if (const auto records = query.ecdsa_records(); is_nonzero(records)) { - fault(error::batch2); - return; - } + header_links invalids{}; + const auto start = network::logger::now(); + if (!query.verify_ecdsa_signatures(invalids)) + { + fault(error::batch2); + return; + } - if (!invalids.empty()) - { - span(events::ecdsa_msecs, start); - const auto elapsed = steady_clock::now() - start; - LOGN("Batch signature verify ecdsa (" << query.ecdsa_records() - << "/" << duration_cast(elapsed).count() << ") "); - } + const auto end = network::logger::now(); + const auto elapsed = duration_cast(end - start).count(); + fire(events::ecdsa_secs, elapsed); + LOGN(log_ratio("Batch verify rate ecdsa.... ", records, elapsed)); - if (!process_invalids(invalids) || !query.purge_ecdsa_signatures()) - { - fault(error::batch3); - return; + if (!process_invalids(invalids) || !query.purge_ecdsa_signatures()) + { + fault(error::batch3); + return; + } } // set_block_unconfirmable(schnorr) // ------------------------------------------------------------------------ - invalids.clear(); - start = network::logger::now(); - if (!query.verify_schnorr_signatures(invalids)) + if (const auto records = query.schnorr_records(); is_nonzero(records)) { - fault(error::batch4); - return; - } + header_links invalids{}; + const auto start = network::logger::now(); + if (!query.verify_schnorr_signatures(invalids)) + { + fault(error::batch4); + return; + } - if (!invalids.empty()) - { - span(events::schnorr_msecs, start); - const auto elapsed = steady_clock::now() - start; - LOGN("Batch signature verify schnorr (" << query.schnorr_records() - << "/" << duration_cast(elapsed).count() << ") "); - } + const auto end = network::logger::now(); + const auto elapsed = duration_cast(end - start).count(); + fire(events::schnorr_secs, elapsed); + LOGN(log_ratio("Batch verify rate schnorr.. ", records, elapsed)); - if (!process_invalids(invalids) || !query.purge_schnorr_signatures()) - { - fault(error::batch5); - return; + if (!process_invalids(invalids) || !query.purge_schnorr_signatures()) + { + fault(error::batch5); + return; + } } // set_block_valid(batched_ excluding ecdsa/schnorr failures) @@ -118,15 +136,6 @@ void chaser_validate::process_batch() NOEXCEPT } } -void chaser_validate::push_batch(const header_link& link, size_t height) NOEXCEPT -{ - BC_ASSERT(stranded()); - batched_.push_back(link); - - // chase portion of notify_block(success). - notify({}, chase::valid, possible_wide_cast(height)); -} - // Invalids might not be included in batched, as link push is a race. // Collected links are only required to set valid, not invalid, and do not // need to coincide with the batch that is currently being processed (!). @@ -189,7 +198,7 @@ bool chaser_validate::process_valids() NOEXCEPT signatures chaser_validate::get_capture(const header_link& link) NOEXCEPT { - if (!batch_signatures_ || is_current(link)) + if (!batch_enabled_ || is_current(link)) return { false }; // This call is blocked during signature batch evaluation and all @@ -282,24 +291,23 @@ bool chaser_validate::do_threshold(const threshold_group& group, return true; } -void chaser_validate::log_capture(const std::string_view& name, - size_t captured, size_t missed) const NOEXCEPT +std::string chaser_validate::log_ratio(const std::string& name, + size_t numerator, size_t denominator) const NOEXCEPT { - if (to_bool(captured) || to_bool(missed)) - { - const auto rate = (100.0f * captured) / (captured + missed); - const auto text = (boost_format("%.4f") % rate).str(); - LOGV("Capture rate " << name << text << "% = " << captured - << "/(" << captured << "+" << missed << ")"); - } + if (is_zero(denominator)) + return name; + + const auto ratio = (100.0 * numerator) / denominator; + return (boost_format("%1% (%2% / %3%) = %4$.4f%%") % + name % numerator % denominator % ratio).str(); } void chaser_validate::log_captures() const NOEXCEPT { - log_capture("ecdsa.... ", ecdsa_, missed_ecdsa_); - log_capture("multisig. ", multisig_, missed_multisig_); - log_capture("schnorr.. ", schnorr_, missed_schnorr_); - log_capture("threshold ", threshold_, zero); + LOGV(log_ratio("Capture rate ecdsa.... ", ecdsa_, ecdsa_ + missed_ecdsa_)); + LOGV(log_ratio("Capture rate multisig. ", multisig_, multisig_ + missed_multisig_)); + LOGV(log_ratio("Capture rate schnorr.. ", schnorr_, schnorr_ + missed_schnorr_)); + LOGV(log_ratio("Capture rate threshold ", threshold_, threshold_ + zero)); } BC_POP_WARNING() diff --git a/src/settings.cpp b/src/settings.cpp index c8787c3f..f26c8c4a 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -36,7 +36,7 @@ settings::settings() NOEXCEPT memory_priority{ true }, thread_priority{ true }, allow_overlapped{ true }, - batch_signatures{ false }, // <-- update when ready. + batch_signatures{ 100'000 }, minimum_fee_rate{ 0.0 }, minimum_bump_rate{ 0.0 }, allowed_deviation{ 1.5 }, @@ -85,6 +85,11 @@ bool settings::fee_estimate_enabled() const NOEXCEPT return to_bool(fee_estimate_horizon_()); } +bool settings::batch_signatures_enabled() const NOEXCEPT +{ + return to_bool(batch_signatures); +} + network::steady_clock::duration settings::sample_period() const NOEXCEPT { return network::seconds(sample_period_seconds); diff --git a/test/settings.cpp b/test/settings.cpp index 5479c7e5..6ec65ca0 100644 --- a/test/settings.cpp +++ b/test/settings.cpp @@ -36,10 +36,10 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected) BOOST_REQUIRE_EQUAL(node.memory_priority, true); BOOST_REQUIRE_EQUAL(node.thread_priority, true); BOOST_REQUIRE_EQUAL(node.allow_overlapped, true); - BOOST_REQUIRE_EQUAL(node.batch_signatures, false); BOOST_REQUIRE_EQUAL(node.minimum_fee_rate, 0.0); BOOST_REQUIRE_EQUAL(node.minimum_bump_rate, 0.0); BOOST_REQUIRE_EQUAL(node.allowed_deviation, 1.5); + BOOST_REQUIRE_EQUAL(node.batch_signatures, 100'000_u64); BOOST_REQUIRE_EQUAL(node.announcement_cache, 42_u16); BOOST_REQUIRE_EQUAL(node.fee_estimate_horizon, 0u); BOOST_REQUIRE_EQUAL(node.maximum_height, 0_u32); @@ -59,6 +59,7 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected) BOOST_REQUIRE_EQUAL(node.maximum_concurrency_(), 50'000_size); BOOST_REQUIRE_EQUAL(node.fee_estimate_horizon_(), 0_size); BOOST_REQUIRE(!node.fee_estimate_enabled()); + BOOST_REQUIRE(node.batch_signatures_enabled()); BOOST_REQUIRE(node.sample_period() == steady_clock::duration(seconds(10))); BOOST_REQUIRE(node.currency_window() == steady_clock::duration(minutes(1440))); BOOST_REQUIRE(node.thread_priority_() == network::processing_priority::high); From 28ca61f14c542cc17023b1b846939ae3b4cf4a10 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Jun 2026 23:24:54 -0400 Subject: [PATCH 3/4] Update batch logging. --- include/bitcoin/node/chasers/chaser_validate.hpp | 2 ++ src/chasers/chaser_validate_batch.cpp | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index 58147d53..bcca6cfd 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -117,6 +117,8 @@ class BCN_API chaser_validate const atomic_counter_ptr& sequence) NOEXCEPT; // Capture helpers. + std::string log_rate(const std::string& name, size_t numerator, + size_t denominator) const NOEXCEPT; std::string log_ratio(const std::string& name, size_t numerator, size_t denominator) const NOEXCEPT; void log_captures() const NOEXCEPT; diff --git a/src/chasers/chaser_validate_batch.cpp b/src/chasers/chaser_validate_batch.cpp index 4bb61dc4..1850fbec 100644 --- a/src/chasers/chaser_validate_batch.cpp +++ b/src/chasers/chaser_validate_batch.cpp @@ -76,6 +76,8 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT // does not operate over partial block records in the batch tables. std::unique_lock lock(mutex_); + log_captures(); + // set_block_unconfirmable(ecdsa) // ------------------------------------------------------------------------ @@ -92,7 +94,7 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT const auto end = network::logger::now(); const auto elapsed = duration_cast(end - start).count(); fire(events::ecdsa_secs, elapsed); - LOGN(log_ratio("Batch verify rate ecdsa.... ", records, elapsed)); + LOGN(log_rate("Batch verify rate ecdsa.... ", records, elapsed)); if (!process_invalids(invalids) || !query.purge_ecdsa_signatures()) { @@ -117,7 +119,7 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT const auto end = network::logger::now(); const auto elapsed = duration_cast(end - start).count(); fire(events::schnorr_secs, elapsed); - LOGN(log_ratio("Batch verify rate schnorr.. ", records, elapsed)); + LOGN(log_rate("Batch verify rate schnorr.. ", records, elapsed)); if (!process_invalids(invalids) || !query.purge_schnorr_signatures()) { @@ -291,6 +293,14 @@ bool chaser_validate::do_threshold(const threshold_group& group, return true; } +std::string chaser_validate::log_rate(const std::string& name, + size_t numerator, size_t denominator) const NOEXCEPT +{ + const auto rate = numerator / greater(denominator, one); + return (boost_format("%1% (%2% / %3%) = %4% sps") % + name % numerator % denominator % rate).str(); +} + std::string chaser_validate::log_ratio(const std::string& name, size_t numerator, size_t denominator) const NOEXCEPT { From 2f36636c28805d3df605516b6768b50aaa1ce3e1 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Jun 2026 15:39:33 -0400 Subject: [PATCH 4/4] Bump NuGet ultrafast to 4.3.0.3. --- .../vs2026/libbitcoin-node-test/libbitcoin-node-test.vcxproj | 4 ++-- builds/msvc/vs2026/libbitcoin-node-test/packages.config | 2 +- builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj | 4 ++-- builds/msvc/vs2026/libbitcoin-node/packages.config | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/builds/msvc/vs2026/libbitcoin-node-test/libbitcoin-node-test.vcxproj b/builds/msvc/vs2026/libbitcoin-node-test/libbitcoin-node-test.vcxproj index 357cd5ed..c3cea976 100644 --- a/builds/msvc/vs2026/libbitcoin-node-test/libbitcoin-node-test.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-node-test/libbitcoin-node-test.vcxproj @@ -161,7 +161,7 @@ - + @@ -177,7 +177,7 @@ - + diff --git a/builds/msvc/vs2026/libbitcoin-node-test/packages.config b/builds/msvc/vs2026/libbitcoin-node-test/packages.config index 97aed24f..869589f8 100644 --- a/builds/msvc/vs2026/libbitcoin-node-test/packages.config +++ b/builds/msvc/vs2026/libbitcoin-node-test/packages.config @@ -6,7 +6,7 @@ | --> - + diff --git a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj index 000aacdb..0f61c134 100644 --- a/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj +++ b/builds/msvc/vs2026/libbitcoin-node/libbitcoin-node.vcxproj @@ -239,7 +239,7 @@ - + @@ -254,7 +254,7 @@ - + diff --git a/builds/msvc/vs2026/libbitcoin-node/packages.config b/builds/msvc/vs2026/libbitcoin-node/packages.config index 3a09727c..093b73c1 100644 --- a/builds/msvc/vs2026/libbitcoin-node/packages.config +++ b/builds/msvc/vs2026/libbitcoin-node/packages.config @@ -6,7 +6,7 @@ | --> - +