mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-05-04 02:49:10 +02:00
Merge bitcoin/bitcoin#34653: test: improve txospender index tests code
e8f8b74a46test: index, improve txospenderindex_initial_sync() test code (furszy)ac3bea07cdtest: improve rpc_gettxspendingprevout.py code (furszy) Pull request description: Fixes #34637. Was reviewing #34637 and, while reading the new txospender index test code for the first time, found it could use some cleanups. Finding stuff in there is harder than it should be due to the amount of dup code. The first commit cleans up `rpc_gettxspendingprevout.py` by introducing helper functions to avoid repeating the same dicts everywhere, using for-loops instead of duplicating the same checks for each node, and renaming variables to better reflect what they actually represent. The second commit reorganizes `txospenderindex_initial_sync()` moving index initialization after the test setup phase, since the index doesn't participate in it anyway. It adds a post-sync check to catch cases where `Sync()` aborted prematurely. Note: This is just a pre-work for deeper index changes I'm cooking. ACKs for top commit: achow101: ACKe8f8b74a46sedited: Re-ACKe8f8b74a46w0xlt: reACKe8f8b74a46Tree-SHA512: 3f7026712ab20a43f376afa28c683dcd5daec8ed1bbf1c36d7ec6bbf231f468d4de74efae4aa8295ff3afb83986286ccaf31c03b34e45fc9971652f064791ed0
This commit is contained in:
@@ -2,10 +2,8 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <index/txospenderindex.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/time.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@@ -14,63 +12,63 @@ BOOST_AUTO_TEST_SUITE(txospenderindex_tests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(txospenderindex_initial_sync, TestChain100Setup)
|
||||
{
|
||||
TxoSpenderIndex txospenderindex(interfaces::MakeChain(m_node), 1 << 20, true);
|
||||
BOOST_REQUIRE(txospenderindex.Init());
|
||||
|
||||
// Setup phase:
|
||||
// Mine blocks for coinbase maturity, so we can spend some coinbase outputs in the test.
|
||||
for (int i = 0; i < 50; i++) {
|
||||
std::vector<CMutableTransaction> no_txns;
|
||||
CreateAndProcessBlock(no_txns, this->m_coinbase_txns[i]->vout[0].scriptPubKey);
|
||||
}
|
||||
const CScript& coinbase_script = m_coinbase_txns[0]->vout[0].scriptPubKey;
|
||||
for (int i = 0; i < 10; i++) CreateAndProcessBlock({}, coinbase_script);
|
||||
|
||||
// Spend 10 outputs
|
||||
std::vector<COutPoint> spent(10);
|
||||
std::vector<CMutableTransaction> spender(spent.size());
|
||||
|
||||
for (size_t i = 0; i < spent.size(); i++) {
|
||||
spent[i] = COutPoint(this->m_coinbase_txns[i]->GetHash(), 0);
|
||||
// Outpoint
|
||||
auto coinbase_tx = m_coinbase_txns[i];
|
||||
spent[i] = COutPoint(coinbase_tx->GetHash(), 0);
|
||||
|
||||
// Spending tx
|
||||
spender[i].version = 1;
|
||||
spender[i].vin.resize(1);
|
||||
spender[i].vin[0].prevout.hash = spent[i].hash;
|
||||
spender[i].vin[0].prevout.n = spent[i].n;
|
||||
spender[i].vout.resize(1);
|
||||
spender[i].vout[0].nValue = this->m_coinbase_txns[i]->GetValueOut();
|
||||
spender[i].vout[0].scriptPubKey = this->m_coinbase_txns[i]->vout[0].scriptPubKey;
|
||||
spender[i].vout[0].nValue = coinbase_tx->GetValueOut();
|
||||
spender[i].vout[0].scriptPubKey = coinbase_script;
|
||||
|
||||
// Sign:
|
||||
// Sign
|
||||
std::vector<unsigned char> vchSig;
|
||||
const uint256 hash = SignatureHash(this->m_coinbase_txns[i]->vout[0].scriptPubKey, spender[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
|
||||
coinbaseKey.Sign(hash, vchSig);
|
||||
const uint256 hash = SignatureHash(coinbase_script, spender[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
|
||||
BOOST_REQUIRE(coinbaseKey.Sign(hash, vchSig));
|
||||
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
||||
spender[i].vin[0].scriptSig << vchSig;
|
||||
}
|
||||
|
||||
CBlock block = CreateAndProcessBlock(spender, this->m_coinbase_txns[0]->vout[0].scriptPubKey);
|
||||
// Generate and ensure block has been fully processed
|
||||
const uint256 tip_hash = CreateAndProcessBlock(spender, coinbase_script).GetHash();
|
||||
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
||||
BOOST_CHECK_EQUAL(WITH_LOCK(::cs_main, return m_node.chainman->ActiveTip()->GetBlockHash()), tip_hash);
|
||||
|
||||
// Transaction should not be found in the index before it is started.
|
||||
// Now we concluded the setup phase, run index
|
||||
TxoSpenderIndex txospenderindex(interfaces::MakeChain(m_node), 1 << 20, true);
|
||||
BOOST_REQUIRE(txospenderindex.Init());
|
||||
BOOST_CHECK(!txospenderindex.BlockUntilSyncedToCurrentChain()); // false when not synced
|
||||
BOOST_CHECK_NE(txospenderindex.GetSummary().best_block_hash, tip_hash);
|
||||
|
||||
// Transaction should not be found in the index before it is synced.
|
||||
for (const auto& outpoint : spent) {
|
||||
BOOST_CHECK(!txospenderindex.FindSpender(outpoint).value());
|
||||
}
|
||||
|
||||
// BlockUntilSyncedToCurrentChain should return false before txospenderindex is started.
|
||||
BOOST_CHECK(!txospenderindex.BlockUntilSyncedToCurrentChain());
|
||||
|
||||
txospenderindex.Sync();
|
||||
BOOST_CHECK_EQUAL(txospenderindex.GetSummary().best_block_hash, tip_hash);
|
||||
|
||||
for (size_t i = 0; i < spent.size(); i++) {
|
||||
const auto tx_spender{txospenderindex.FindSpender(spent[i])};
|
||||
BOOST_REQUIRE(tx_spender.has_value());
|
||||
BOOST_REQUIRE(tx_spender->has_value());
|
||||
BOOST_CHECK_EQUAL((*tx_spender)->tx->GetHash(), spender[i].GetHash());
|
||||
BOOST_CHECK_EQUAL((*tx_spender)->block_hash, block.GetHash());
|
||||
BOOST_CHECK_EQUAL((*tx_spender)->block_hash, tip_hash);
|
||||
}
|
||||
|
||||
// It is not safe to stop and destroy the index until it finishes handling
|
||||
// the last BlockConnected notification. The BlockUntilSyncedToCurrentChain()
|
||||
// call above is sufficient to ensure this, but the
|
||||
// SyncWithValidationInterfaceQueue() call below is also needed to ensure
|
||||
// TSAN always sees the test thread waiting for the notification thread, and
|
||||
// avoid potential false positive reports.
|
||||
m_node.validation_signals->SyncWithValidationInterfaceQueue();
|
||||
|
||||
// shutdown sequence (c.f. Shutdown() in init.cpp)
|
||||
txospenderindex.Stop();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user