From b2d690e7093e953fe7240865c0e7805bb164bb88 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 25 Jan 2025 15:16:58 -0500 Subject: [PATCH 1/3] Add error category contains(ec) method. --- include/bitcoin/system/error/macros.hpp | 6 ++++++ test/error/error.cpp | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/bitcoin/system/error/macros.hpp b/include/bitcoin/system/error/macros.hpp index bebea1cf94..9bb8b326f4 100644 --- a/include/bitcoin/system/error/macros.hpp +++ b/include/bitcoin/system/error/macros.hpp @@ -57,6 +57,7 @@ class BC_API cat##_category \ static const message_map messages; \ public: \ static const cat##_category singleton; \ + static bool contains(const std::error_code& ec) noexcept; \ virtual const char* name() const noexcept; \ virtual std::string message(int condition) const noexcept; \ virtual std::error_condition default_error_condition(int value) const noexcept; \ @@ -74,6 +75,7 @@ class BC_API cat##_category \ static const message_map messages; \ public: \ static const cat##_category singleton; \ + static bool contains(const std::error_code& ec) noexcept; \ virtual const char* name() const noexcept; \ virtual std::string message(int condition) const noexcept; \ virtual std::error_condition default_error_condition(int value) const noexcept; \ @@ -84,6 +86,10 @@ std::error_condition make_error_condition(cat##_t value) noexcept #define DEFINE_ERROR_T_CATEGORY(cat, category_name, unmapped) \ const cat##_category cat##_category::singleton; \ +bool cat##_category::contains(const std::error_code& ec) noexcept \ +{ \ + return is_zero(std::strcmp(ec.category().name(), category_name)); \ +} \ const char* cat##_category::name() const noexcept \ { \ return category_name; \ diff --git a/test/error/error.cpp b/test/error/error.cpp index 207a8ea702..cf494cf49e 100644 --- a/test/error/error.cpp +++ b/test/error/error.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__message_overflow__default_message) // Overflows can be cast in, and value retained, and yield default message. BOOST_AUTO_TEST_CASE(error_t__code__value_overflow__default_message) { - const auto overflow = static_cast(error::error_last); + constexpr auto overflow = static_cast(error::error_last); const auto ec = code(static_cast(overflow)); BOOST_REQUIRE(ec); BOOST_REQUIRE_EQUAL(ec.message(), default_message); @@ -108,6 +108,14 @@ BOOST_AUTO_TEST_CASE(error_t__code__category_name__expected) { BOOST_REQUIRE_EQUAL(code().category().name(), system_category_name); BOOST_REQUIRE_EQUAL(code(error::success).category().name(), bitcoin_category_name); + BOOST_REQUIRE_NE(code(error::script_success).category().name(), code(error::success).category().name()); +} + +BOOST_AUTO_TEST_CASE(error_t__code__category_contains__expected) +{ + BOOST_REQUIRE(system::error::error_category::contains(system::error::success)); + BOOST_REQUIRE(!system::error::script_error_category::contains(system::error::success)); + BOOST_REQUIRE(system::error::script_error_category::contains(system::error::script_success)); } BOOST_AUTO_TEST_CASE(error_t__code__default_error_condition_category_name__expected) From 53b0e165e3577571670e961af8120c1323b0d289 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 26 Jan 2025 20:41:35 -0500 Subject: [PATCH 2/3] Don't compute optional witness commitment (optimization). --- src/chain/block.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/chain/block.cpp b/src/chain/block.cpp index 6b1b5dc40b..63bc895f79 100644 --- a/src/chain/block.cpp +++ b/src/chain/block.cpp @@ -600,6 +600,10 @@ bool block::is_invalid_witness_commitment() const NOEXCEPT if (coinbase->inputs_ptr()->empty()) return false; + // If no block tx has witness data the commitment is optional (bip141). + if (!is_segregated()) + return false; + // If there is a valid commitment, return false (valid). // Coinbase input witness must be 32 byte witness reserved value (bip141). // Last output of commitment pattern holds the committed value (bip141). @@ -610,10 +614,8 @@ bool block::is_invalid_witness_commitment() const NOEXCEPT if (committed == sha256::double_hash( generate_merkle_root(true), reserved)) return false; - - // If no valid commitment, return true (invalid) if segregated. - // If no block tx has witness data the commitment is optional (bip141). - return is_segregated(); + + return true; } //***************************************************************************** From 7d4a5174ab9df1f7f05b7a7b7b68f49fdfb42b47 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 27 Jan 2025 16:34:24 -0500 Subject: [PATCH 3/3] Provide count of segregated txs. --- include/bitcoin/system/chain/block.hpp | 1 + src/chain/block.cpp | 10 ++++++++++ test/chain/block.cpp | 1 + 3 files changed, 12 insertions(+) diff --git a/include/bitcoin/system/chain/block.hpp b/include/bitcoin/system/chain/block.hpp index 834a1ac91b..c80c406a32 100644 --- a/include/bitcoin/system/chain/block.hpp +++ b/include/bitcoin/system/chain/block.hpp @@ -98,6 +98,7 @@ class BC_API block bool is_segregated() const NOEXCEPT; size_t serialized_size(bool witness) const NOEXCEPT; size_t signature_operations(bool bip16, bool bip141) const NOEXCEPT; + size_t segregated() const NOEXCEPT; /// Computed malleation properties. bool is_malleable() const NOEXCEPT; diff --git a/src/chain/block.cpp b/src/chain/block.cpp index 63bc895f79..33dff1d784 100644 --- a/src/chain/block.cpp +++ b/src/chain/block.cpp @@ -587,6 +587,16 @@ bool block::is_segregated() const NOEXCEPT return std::any_of(txs_->begin(), txs_->end(), segregated); } +size_t block::segregated() const NOEXCEPT +{ + const auto count_segregated = [](const auto& tx) NOEXCEPT + { + return tx->is_segregated(); + }; + + return std::count_if(txs_->begin(), txs_->end(), count_segregated); +} + // The witness merkle root is obtained from wtxids, subject to malleation just // as the txs commitment. However, since tx duplicates are precluded by the // malleable32 (or complete) block check, there is no opportunity for this. diff --git a/test/chain/block.cpp b/test/chain/block.cpp index f177ca3004..1ec88dfa67 100644 --- a/test/chain/block.cpp +++ b/test/chain/block.cpp @@ -460,6 +460,7 @@ BOOST_AUTO_TEST_CASE(block__hash__default__matches_header_hash) // is_malleable // is_segregated // serialized_size +// segregated // validation (public) // ----------------------------------------------------------------------------