From e1faf1e5ef777a8f6f0edaa0205cdc2ecdd2a41f Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 20 Jun 2026 14:55:24 -0400 Subject: [PATCH 1/3] Add capture sequence counter to single sig capture. --- .../bitcoin/node/chasers/chaser_validate.hpp | 4 +- src/chasers/chaser_validate_capture.cpp | 39 ++++++++++--------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index 69a6b23f..ef44605e 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -104,10 +104,10 @@ class BCN_API chaser_validate void do_fire(missed miss, size_t count) NOEXCEPT; bool do_ecdsa(const system::hash_digest& digest, const system::ec_compressed& point, const system::ec_signature& sign, - const header_link& link) NOEXCEPT; + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT; bool do_schnorr(const system::hash_digest& digest, const system::ec_xonly& point, const system::ec_signature& sign, - const header_link& link) NOEXCEPT; + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT; bool do_multisig(const system::hash_digest& digest, const system::ec_compresseds& points, const system::ec_signatures& signs, const header_link& link, diff --git a/src/chasers/chaser_validate_capture.cpp b/src/chasers/chaser_validate_capture.cpp index 09efaa02..ce02a7a5 100644 --- a/src/chasers/chaser_validate_capture.cpp +++ b/src/chasers/chaser_validate_capture.cpp @@ -63,46 +63,47 @@ void chaser_validate::do_fire(missed miss, size_t count) NOEXCEPT bool chaser_validate::do_ecdsa(const hash_digest& digest, const ec_compressed& point, const ec_signature& sign, - const header_link& link) NOEXCEPT + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { ++ecdsa_; - const auto set = archive().set_signature(digest, point, sign, link); + const auto id = (*sequence)++; + const auto set = archive().set_signature(digest, point, sign, id, link); if (!set) fault(error::batch5); return set; } bool chaser_validate::do_schnorr(const hash_digest& digest, const ec_xonly& point, const ec_signature& sign, - const header_link& link) NOEXCEPT + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { ++schnorr_; - const auto set = archive().set_signature(digest, point, sign, link); + const auto id = (*sequence)++; + const auto set = archive().set_signature(digest, point, sign, id, link); if (!set) fault(error::batch6); return set; } -bool chaser_validate::do_multisig(const hash_digest& , - const ec_compresseds& points, const ec_signatures& BC_DEBUG_ONLY(signs), - const header_link& , const atomic_counter_ptr& ) NOEXCEPT +bool chaser_validate::do_multisig(const hash_digest& digest, + const ec_compresseds& points, const ec_signatures& signs, + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { BC_ASSERT(points.size() == signs.size()); multisig_ += points.size(); - ////const auto set = archive().set_signatures(digest, points, signs, - //// (*sequence)++, link); - ////if (!set) fault(error::batch7); - ////return set; - return true; + const auto id = (*sequence)++; + const auto set = archive().set_signatures(digest, points, signs, id, link); + if (!set) fault(error::batch7); + return set; } bool chaser_validate::do_threshold(const threshold_group& group, - const header_link& , const atomic_counter_ptr& ) NOEXCEPT + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { threshold_ += group.entries.size(); - ////const auto set = archive().set_signatures(group, (*sequence)++, link); - ////if (!set) fault(error::batch8); - ////return set; - return true; + const auto id = (*sequence)++; + const auto set = archive().set_signatures(group, id, link); + if (!set) fault(error::batch8); + return set; } std::string chaser_validate::log_rate(const std::string& name, @@ -128,8 +129,8 @@ signatures chaser_validate::get_capture(const header_link& link) NOEXCEPT .enabled = true, .log = BIND_THIS(do_log, _1), .fire = BIND_THIS(do_fire, _1, _2), - .ecdsa = BIND_THIS(do_ecdsa, _1, _2, _3, link), - .schnorr = BIND_THIS(do_schnorr, _1, _2, _3, link), + .ecdsa = BIND_THIS(do_ecdsa, _1, _2, _3, link, sequence), + .schnorr = BIND_THIS(do_schnorr, _1, _2, _3, link, sequence), .multisig = BIND_THIS(do_multisig, _1, _2, _3, link, sequence), .threshold = BIND_THIS(do_threshold, _1, link, sequence) }; From 96469c40411c94cf1c25eb54b8b9030e642d376d Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 21 Jun 2026 01:18:34 -0400 Subject: [PATCH 2/3] Comments. --- src/chasers/chaser_validate_batch.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chasers/chaser_validate_batch.cpp b/src/chasers/chaser_validate_batch.cpp index 244a38af..a269929f 100644 --- a/src/chasers/chaser_validate_batch.cpp +++ b/src/chasers/chaser_validate_batch.cpp @@ -49,6 +49,8 @@ code chaser_validate::start_batch() NOEXCEPT error::batch1 : error::success; } +// batched_ is redundant with the combined set of ecdsa/schnorr unfailed block +// identifiers stored in the two batch tables, so just a sort optimization. void chaser_validate::push_batch(const header_link& link, size_t height) NOEXCEPT { BC_ASSERT(stranded()); From 0500416fef74169b35264c32ea55fa0fbfeb9e8a Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 21 Jun 2026 14:56:02 -0400 Subject: [PATCH 3/3] Delint, handle batch sequence counter overflow. --- .../bitcoin/node/chasers/chaser_validate.hpp | 4 +-- src/chasers/chaser_validate_capture.cpp | 25 ++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index ef44605e..1f0fbbe9 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -91,7 +91,7 @@ class BCN_API chaser_validate static constexpr auto relaxed = std::memory_order_relaxed; using atomic_counter = std::atomic; using atomic_counter_ptr = std::shared_ptr; - using threshold_group = signatures::threshold_group; + using threshold = system::chain::threshold; using missed = signatures::miss; /// Batching helpers. @@ -112,7 +112,7 @@ class BCN_API chaser_validate const system::ec_compresseds& points, const system::ec_signatures& signs, const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT; - bool do_threshold(const threshold_group& group, const header_link& link, + bool do_threshold(const threshold& batch, const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT; // Capture helpers. diff --git a/src/chasers/chaser_validate_capture.cpp b/src/chasers/chaser_validate_capture.cpp index ce02a7a5..85575a33 100644 --- a/src/chasers/chaser_validate_capture.cpp +++ b/src/chasers/chaser_validate_capture.cpp @@ -31,6 +31,9 @@ using namespace system::chain; using namespace database; using namespace std::placeholders; +// Shared pointers required for lifetime in handler parameters. +BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR) +BC_PUSH_WARNING(SMART_PTR_NOT_NEEDED) BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) // Capture handlers. @@ -67,7 +70,9 @@ bool chaser_validate::do_ecdsa(const hash_digest& digest, { ++ecdsa_; const auto id = (*sequence)++; - const auto set = archive().set_signature(digest, point, sign, id, link); + if (is_limited(id)) return false; + const auto group = narrow_cast(id); + const auto set = archive().set_signature(digest, point, sign, group, link); if (!set) fault(error::batch5); return set; } @@ -78,7 +83,9 @@ bool chaser_validate::do_schnorr(const hash_digest& digest, { ++schnorr_; const auto id = (*sequence)++; - const auto set = archive().set_signature(digest, point, sign, id, link); + if (is_limited(id)) return false; + const auto group = narrow_cast(id); + const auto set = archive().set_signature(digest, point, sign, group, link); if (!set) fault(error::batch6); return set; } @@ -91,17 +98,21 @@ bool chaser_validate::do_multisig(const hash_digest& digest, multisig_ += points.size(); const auto id = (*sequence)++; - const auto set = archive().set_signatures(digest, points, signs, id, link); + if (is_limited(id)) return false; + const auto group = narrow_cast(id); + const auto set = archive().set_signatures(digest, points, signs, group, link); if (!set) fault(error::batch7); return set; } -bool chaser_validate::do_threshold(const threshold_group& group, +bool chaser_validate::do_threshold(const threshold& batch, const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { - threshold_ += group.entries.size(); + threshold_ += batch.tuples.size(); const auto id = (*sequence)++; - const auto set = archive().set_signatures(group, id, link); + if (is_limited(id)) return false; + const auto group = narrow_cast(id); + const auto set = archive().set_signatures(batch, group, link); if (!set) fault(error::batch8); return set; } @@ -155,6 +166,8 @@ void chaser_validate::log_captures() const NOEXCEPT LOGV(log_ratio("Capture rate threshold ", threshold_, threshold_ + zero)); } +BC_POP_WARNING() +BC_POP_WARNING() BC_POP_WARNING() } // namespace node