From ed62b99cdeda08e472d5e97faa5fa41cda021e0b Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Thu, 15 Oct 2026 16:30:04 -0400 Subject: [PATCH] Add get_block_prevouts for all spends of a block view. --- .../database/impl/query/batch/silent.ipp | 22 +++++++++++++++--- include/bitcoin/database/query.hpp | 11 +++++++++ test/query/batch/silent.cpp | 23 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/bitcoin/database/impl/query/batch/silent.ipp b/include/bitcoin/database/impl/query/batch/silent.ipp index 8ac11f370..3cfcdc89e 100644 --- a/include/bitcoin/database/impl/query/batch/silent.ipp +++ b/include/bitcoin/database/impl/query/batch/silent.ipp @@ -298,11 +298,27 @@ bool CLASS::set_silents(size_t& rows, const header_link& link, return set_silents_(rows, link, block, block.views().size(), bank); } -// Pooled txs linked below the coinbase are not selected (see set_silent). TEMPLATE bool CLASS::get_silent_prevouts(data_chunk& prevouts, std::vector& selected, const header_link& link, const block_view& block) const NOEXCEPT +{ + return get_prevouts_(prevouts, selected, link, block, true); +} + +TEMPLATE +bool CLASS::get_block_prevouts(data_chunk& prevouts, + std::vector& selected, const header_link& link, + const block_view& block) const NOEXCEPT +{ + return get_prevouts_(prevouts, selected, link, block, false); +} + +// Pooled txs linked below the coinbase are not silent selected (see set_silent). +TEMPLATE +bool CLASS::get_prevouts_(data_chunk& prevouts, std::vector& selected, + const header_link& link, const block_view& block, + bool silent) const NOEXCEPT { using namespace system; const auto& txs = block.views(); @@ -318,8 +334,8 @@ bool CLASS::get_silent_prevouts(data_chunk& prevouts, const auto first = links.front(); for (auto index = one; index < txs.size(); ++index) { - if (!is_silent_selected(links.at(index), first) || - !silent_payment::has_outputs(txs.at(index))) + if (silent && (!is_silent_selected(links.at(index), first) || + !silent_payment::has_outputs(txs.at(index)))) continue; table::transaction::get_puts record{}; diff --git a/include/bitcoin/database/query.hpp b/include/bitcoin/database/query.hpp index 1984d6d4b..5c40cfb06 100644 --- a/include/bitcoin/database/query.hpp +++ b/include/bitcoin/database/query.hpp @@ -764,6 +764,11 @@ class query bool get_silent_prevouts(data_chunk& prevouts, std::vector& selected, const header_link& link, const block_view& block) const NOEXCEPT; + /// The wire prevouts of the spends of all of the block's txs in block + /// order, with the selection of those txs (all but the coinbase). + bool get_block_prevouts(data_chunk& prevouts, std::vector& selected, + const header_link& link, const block_view& block) const NOEXCEPT; + /// Compute a bank's silent payment batch, then set its scan records. code compute_silents(const stopper& cancel, bool& use_gpu, bool bank) NOEXCEPT; @@ -1218,6 +1223,12 @@ class query bool is_silent_selected(const tx_link& link, const tx_link& coinbase) const NOEXCEPT; + /// The wire prevouts of the spends of the block's selected txs, where + /// silent selects the silent payment eligible txs and otherwise all. + bool get_prevouts_(data_chunk& prevouts, std::vector& selected, + const header_link& link, const block_view& block, + bool silent) const NOEXCEPT; + /// Mark the blocks of a bank's presilent table scanned. bool set_scanned_(bool bank) NOEXCEPT; diff --git a/test/query/batch/silent.cpp b/test/query/batch/silent.cpp index d5e68dd4c..e6efdac1b 100644 --- a/test/query/batch/silent.cpp +++ b/test/query/batch/silent.cpp @@ -459,6 +459,29 @@ BOOST_AUTO_TEST_CASE(query_batch_silent__get_silent_prevouts__no_taproot_output_ BOOST_REQUIRE(prevouts.empty()); } +BOOST_AUTO_TEST_CASE(query_batch_silent__get_block_prevouts__no_taproot_output__selected) +{ + database::settings settings{}; + settings.path = TEST_DIRECTORY; + test::chunk_store store{ settings }; + test::query_accessor query{ store }; + BOOST_REQUIRE(!store.create(test::events_handler)); + BOOST_REQUIRE(query.initialize(test::genesis)); + BOOST_REQUIRE(query.set(test::block1, database::context{ 0, 1, 0 }, {}, false, false)); + + const auto block = spend_block(witness_script); + BOOST_REQUIRE(query.set(block, database::context{ 0, 2, 0 }, {}, false, false)); + const auto link = query.to_header(block.hash()); + + data_chunk prevouts{}; + std::vector selected{}; + const chain::view::block view{ block.to_data(true), true }; + const auto& parent = *test::block1.transactions_ptr()->front(); + BOOST_REQUIRE(query.get_block_prevouts(prevouts, selected, link, view)); + BOOST_REQUIRE(selected == (std::vector{ false, true })); + BOOST_REQUIRE_EQUAL(prevouts, parent.outputs_ptr()->front()->to_data()); +} + BOOST_AUTO_TEST_CASE(query_batch_silent__compute_silents__banked_row__scanned) { database::settings settings{};