LCOV - code coverage report
Current view: top level - src/test - coinjoin_inouts_tests.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 57 57 100.0 %
Date: 2026-06-25 07:23:51 Functions: 18 18 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2025 The Dash Core developers
       2             : // Distributed under the MIT/X11 software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <test/util/setup_common.h>
       6             : 
       7             : #include <algorithm>
       8             : #include <array>
       9             : #include <cstdint>
      10             : #include <vector>
      11             : 
      12             : #include <chain.h>
      13             : #include <coinjoin/coinjoin.h>
      14             : #include <coinjoin/common.h>
      15             : #include <evo/chainhelper.h>
      16             : #include <script/script.h>
      17             : #include <uint256.h>
      18             : #include <util/check.h>
      19             : #include <util/time.h>
      20             : 
      21             : #include <boost/test/unit_test.hpp>
      22             : 
      23         146 : BOOST_FIXTURE_TEST_SUITE(coinjoin_inouts_tests, TestingSetup)
      24             : 
      25           3 : static CScript P2PKHScript(uint8_t tag = 0x01)
      26             : {
      27             :     // OP_DUP OP_HASH160 <20-byte-tag> OP_EQUALVERIFY OP_CHECKSIG
      28           3 :     std::vector<unsigned char> hash(20, tag);
      29           3 :     return CScript{} << OP_DUP << OP_HASH160 << hash << OP_EQUALVERIFY << OP_CHECKSIG;
      30           3 : }
      31             : 
      32         149 : BOOST_AUTO_TEST_CASE(broadcasttx_isvalidstructure_good_and_bad)
      33             : {
      34             :     // Good: equal vin/vout sizes, vin count >= min participants, <= max*entry_size, P2PKH outputs with standard denominations
      35           1 :     CCoinJoinBroadcastTx good;
      36             :     {
      37           1 :         CMutableTransaction mtx;
      38             :         // Use min pool participants (e.g. 3). Build 3 inputs and 3 denominated outputs
      39           1 :         const int participants = std::max(3, CoinJoin::GetMinPoolParticipants());
      40           4 :         for (int i = 0; i < participants; ++i) {
      41           3 :             CTxIn in;
      42           3 :             in.prevout = COutPoint(uint256::ONE, static_cast<uint32_t>(i));
      43           3 :             mtx.vin.push_back(in);
      44             :             // Pick the smallest denomination
      45           3 :             CTxOut out{CoinJoin::GetSmallestDenomination(), P2PKHScript(static_cast<uint8_t>(i))};
      46           3 :             mtx.vout.push_back(out);
      47           3 :         }
      48           1 :         good.tx = MakeTransactionRef(mtx);
      49           1 :         good.m_protxHash = uint256::ONE; // at least one of (outpoint, protxhash) must be set
      50           1 :     }
      51           1 :     BOOST_CHECK(good.IsValidStructure());
      52             : 
      53             :     // Bad: both identifiers null
      54           1 :     CCoinJoinBroadcastTx bad_ids = good;
      55           1 :     bad_ids.m_protxHash = uint256{};
      56           1 :     bad_ids.masternodeOutpoint.SetNull();
      57           1 :     BOOST_CHECK(!bad_ids.IsValidStructure());
      58             : 
      59             :     // Bad: vin/vout size mismatch
      60           1 :     CCoinJoinBroadcastTx bad_sizes = good;
      61             :     {
      62           1 :         CMutableTransaction mtx(*good.tx);
      63           1 :         mtx.vout.pop_back();
      64           1 :         bad_sizes.tx = MakeTransactionRef(mtx);
      65           1 :     }
      66           1 :     BOOST_CHECK(!bad_sizes.IsValidStructure());
      67             : 
      68             :     // Bad: non-P2PKH output
      69           1 :     CCoinJoinBroadcastTx bad_script = good;
      70             :     {
      71           1 :         CMutableTransaction mtx(*good.tx);
      72           1 :         mtx.vout[0].scriptPubKey = CScript() << OP_RETURN << std::vector<unsigned char>{'x'};
      73           1 :         bad_script.tx = MakeTransactionRef(mtx);
      74           1 :     }
      75           1 :     BOOST_CHECK(!bad_script.IsValidStructure());
      76             : 
      77             :     // Bad: non-denominated amount
      78           1 :     CCoinJoinBroadcastTx bad_amount = good;
      79             :     {
      80           1 :         CMutableTransaction mtx(*good.tx);
      81           1 :         mtx.vout[0].nValue = 42; // not a valid denom
      82           1 :         bad_amount.tx = MakeTransactionRef(mtx);
      83           1 :     }
      84           1 :     BOOST_CHECK(!bad_amount.IsValidStructure());
      85           1 : }
      86             : 
      87         149 : BOOST_AUTO_TEST_CASE(queue_timeout_bounds)
      88             : {
      89           1 :     CCoinJoinQueue dsq;
      90           1 :     dsq.nDenom = CoinJoin::AmountToDenomination(CoinJoin::GetSmallestDenomination());
      91           1 :     dsq.m_protxHash = uint256::ONE;
      92           1 :     dsq.nTime = GetAdjustedTime();
      93             :     // current time -> not out of bounds
      94           1 :     BOOST_CHECK(!dsq.IsTimeOutOfBounds());
      95             : 
      96             :     // Too old (beyond COINJOIN_QUEUE_TIMEOUT)
      97           1 :     SetMockTime(GetTime() + (COINJOIN_QUEUE_TIMEOUT + 1));
      98           1 :     BOOST_CHECK(dsq.IsTimeOutOfBounds());
      99             : 
     100             :     // Too far in the future
     101           1 :     SetMockTime(GetTime() - 2 * (COINJOIN_QUEUE_TIMEOUT + 1)); // move back to anchor baseline
     102           1 :     dsq.nTime = GetAdjustedTime() + (COINJOIN_QUEUE_TIMEOUT + 1);
     103           1 :     BOOST_CHECK(dsq.IsTimeOutOfBounds());
     104             : 
     105             :     // Reset mock time
     106           1 :     SetMockTime(0);
     107           1 : }
     108         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16