From 0936c55f626c21a3788545a7fbd6be4424ae3350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Tue, 11 Aug 2026 11:50:11 -0700 Subject: [PATCH 1/2] test: characterize kernel range iterators --- src/test/kernel/test_kernel.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp index d3886ad58ac..10635937fe2 100644 --- a/src/test/kernel/test_kernel.cpp +++ b/src/test/kernel/test_kernel.cpp @@ -745,6 +745,12 @@ BOOST_AUTO_TEST_CASE(btck_block) CheckHandle(block, block_100); Block block_tx{hex_string_to_byte_vec(REGTEST_BLOCK_DATA[205])}; CheckRange(block_tx.Transactions(), block_tx.CountTransactions()); + auto transactions{block_tx.Transactions()}; + auto transactions_copy{transactions}; + BOOST_CHECK(transactions.begin() != transactions_copy.begin()); // TODO: Iterators over the same underlying block should compare equal. + BOOST_CHECK(transactions.begin() != block_tx.Transactions().begin()); // TODO: Iterators over the same underlying block should compare equal. + auto transaction_it{transactions.begin()}; + BOOST_CHECK((*transaction_it).Txid() == block_tx.GetTransaction(0).Txid()); auto invalid_data = hex_string_to_byte_vec("012300"); BOOST_CHECK_THROW(Block{invalid_data}, std::runtime_error); auto empty_data = hex_string_to_byte_vec(""); From fc0dcf950f97ef30930960c39a04ac28dcdadee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Tue, 11 Aug 2026 11:51:13 -0700 Subject: [PATCH 2/2] kernel: keep range iterators tied to their owner `Range` iterators point to the view, so iterators saved from temporary views dangle. Point them to the underlying container, use the range's getter for element access, and remove `operator->`, which returned elements by value and could not support arrow expressions. Co-authored-by: Daniel Pfeifer --- src/kernel/bitcoinkernel_wrapper.h | 13 ++++++------- src/test/kernel/test_kernel.cpp | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h index ed686a9fa47..b929bcc1a13 100644 --- a/src/kernel/bitcoinkernel_wrapper.h +++ b/src/kernel/bitcoinkernel_wrapper.h @@ -190,7 +190,7 @@ T check(T ptr) return ptr; } -template +template class Iterator { public: @@ -209,8 +209,7 @@ public: Iterator(const Collection* ptr, size_t idx) : m_collection{ptr}, m_idx{idx} {} // This is just a view, so return a copy. - auto operator*() const { return (*m_collection)[m_idx]; } - auto operator->() const { return (*m_collection)[m_idx]; } + auto operator*() const { return std::invoke(GetFunc, *m_collection, m_idx); } auto& operator++() { m_idx++; return *this; } auto operator++(int) { Iterator tmp = *this; ++(*this); return tmp; } @@ -226,7 +225,7 @@ public: auto operator-(const Iterator& other) const { return static_cast(m_idx) - static_cast(other.m_idx); } - ValueType operator[](difference_type n) const { return (*m_collection)[m_idx + n]; } + ValueType operator[](difference_type n) const { return *(*this + n); } auto operator<=>(const Iterator& other) const { return m_idx <=> other.m_idx; } @@ -249,7 +248,7 @@ class Range public: using value_type = std::invoke_result_t; using difference_type = std::ptrdiff_t; - using iterator = Iterator; + using iterator = Iterator; using const_iterator = iterator; private: @@ -261,8 +260,8 @@ public: static_assert(std::ranges::random_access_range); } - iterator begin() const { return iterator(this, 0); } - iterator end() const { return iterator(this, size()); } + iterator begin() const { return iterator(m_container, 0); } + iterator end() const { return iterator(m_container, size()); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp index 10635937fe2..8b919c918fb 100644 --- a/src/test/kernel/test_kernel.cpp +++ b/src/test/kernel/test_kernel.cpp @@ -747,8 +747,8 @@ BOOST_AUTO_TEST_CASE(btck_block) CheckRange(block_tx.Transactions(), block_tx.CountTransactions()); auto transactions{block_tx.Transactions()}; auto transactions_copy{transactions}; - BOOST_CHECK(transactions.begin() != transactions_copy.begin()); // TODO: Iterators over the same underlying block should compare equal. - BOOST_CHECK(transactions.begin() != block_tx.Transactions().begin()); // TODO: Iterators over the same underlying block should compare equal. + BOOST_CHECK(transactions.begin() == transactions_copy.begin()); + BOOST_CHECK(transactions.begin() == block_tx.Transactions().begin()); auto transaction_it{transactions.begin()}; BOOST_CHECK((*transaction_it).Txid() == block_tx.GetTransaction(0).Txid()); auto invalid_data = hex_string_to_byte_vec("012300");