txospenderindex_tests.cpp
1 // Copyright (c) The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <index/txospenderindex.h> 6 #include <test/util/common.h> 7 #include <test/util/setup_common.h> 8 #include <validation.h> 9 10 #include <boost/test/unit_test.hpp> 11 12 BOOST_AUTO_TEST_SUITE(txospenderindex_tests) 13 14 BOOST_FIXTURE_TEST_CASE(txospenderindex_initial_sync, TestChain100Setup) 15 { 16 // Setup phase: 17 // Mine blocks for coinbase maturity, so we can spend some coinbase outputs in the test. 18 const CScript& coinbase_script = m_coinbase_txns[0]->vout[0].scriptPubKey; 19 for (int i = 0; i < 10; i++) CreateAndProcessBlock({}, coinbase_script); 20 21 // Spend 10 outputs 22 std::vector<COutPoint> spent(10); 23 std::vector<CMutableTransaction> spender(spent.size()); 24 for (size_t i = 0; i < spent.size(); i++) { 25 // Outpoint 26 auto coinbase_tx = m_coinbase_txns[i]; 27 spent[i] = COutPoint(coinbase_tx->GetHash(), 0); 28 29 // Spending tx 30 spender[i].version = 1; 31 spender[i].vin.resize(1); 32 spender[i].vin[0].prevout.hash = spent[i].hash; 33 spender[i].vin[0].prevout.n = spent[i].n; 34 spender[i].vout.resize(1); 35 spender[i].vout[0].nValue = coinbase_tx->GetValueOut(); 36 spender[i].vout[0].scriptPubKey = coinbase_script; 37 38 // Sign 39 std::vector<unsigned char> vchSig; 40 const uint256 hash = SignatureHash(coinbase_script, spender[i], 0, SIGHASH_ALL, 0, SigVersion::BASE); 41 BOOST_REQUIRE(coinbaseKey.Sign(hash, vchSig)); 42 vchSig.push_back((unsigned char)SIGHASH_ALL); 43 spender[i].vin[0].scriptSig << vchSig; 44 } 45 46 // Generate and ensure block has been fully processed 47 const uint256 tip_hash = CreateAndProcessBlock(spender, coinbase_script).GetHash(); 48 m_node.validation_signals->SyncWithValidationInterfaceQueue(); 49 BOOST_CHECK_EQUAL(WITH_LOCK(::cs_main, return m_node.chainman->ActiveTip()->GetBlockHash()), tip_hash); 50 51 // Now we concluded the setup phase, run index 52 TxoSpenderIndex txospenderindex(interfaces::MakeChain(m_node), 1 << 20, true); 53 BOOST_REQUIRE(txospenderindex.Init()); 54 BOOST_CHECK(!txospenderindex.BlockUntilSyncedToCurrentChain()); // false when not synced 55 BOOST_CHECK_NE(txospenderindex.GetSummary().best_block_hash, tip_hash); 56 57 // Transaction should not be found in the index before it is synced. 58 for (const auto& outpoint : spent) { 59 BOOST_CHECK(!txospenderindex.FindSpender(outpoint).value()); 60 } 61 62 txospenderindex.Sync(); 63 BOOST_CHECK_EQUAL(txospenderindex.GetSummary().best_block_hash, tip_hash); 64 65 for (size_t i = 0; i < spent.size(); i++) { 66 const auto tx_spender{txospenderindex.FindSpender(spent[i])}; 67 BOOST_REQUIRE(tx_spender.has_value()); 68 BOOST_REQUIRE(tx_spender->has_value()); 69 BOOST_CHECK_EQUAL((*tx_spender)->tx->GetHash(), spender[i].GetHash()); 70 BOOST_CHECK_EQUAL((*tx_spender)->block_hash, tip_hash); 71 } 72 73 // Shutdown sequence (c.f. Shutdown() in init.cpp) 74 txospenderindex.Stop(); 75 } 76 77 BOOST_AUTO_TEST_SUITE_END()