Line data Source code
1 : // Copyright (c) 2021-2025 The Dash 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 <test/data/trivially_invalid.json.h> 6 : #include <test/data/trivially_valid.json.h> 7 : #include <test/util/json.h> 8 : #include <test/util/setup_common.h> 9 : 10 : #include <chain.h> 11 : #include <chainparams.h> 12 : #include <deploymentstatus.h> 13 : #include <evo/providertx.h> 14 : #include <primitives/transaction.h> 15 : #include <validation.h> 16 : 17 : #include <boost/test/unit_test.hpp> 18 : 19 : #include <univalue.h> 20 : 21 : struct TestChain100V19Activation : public TestChain100Setup { 22 2 : TestChain100V19Activation() 23 2 : : TestChain100Setup{CBaseChainParams::REGTEST, {"-testactivationheight=v19@100"}} {} 24 : }; 25 : 26 146 : BOOST_FIXTURE_TEST_SUITE(evo_trivialvalidation, TestChain100V19Activation) 27 : 28 : template <class T> 29 74 : void TestTxHelper(const CMutableTransaction& tx, gsl::not_null<const CBlockIndex*> pindexPrev, 30 : const std::optional<std::string>& expected_error, const ChainstateManager& chainman) 31 : { 32 74 : const bool payload_to_fail = expected_error.has_value() && expected_error.value() == "gettxpayload-fail"; 33 74 : const auto opt_payload = GetTxPayload<T>(tx, false); 34 74 : BOOST_CHECK_EQUAL(opt_payload.has_value(), !payload_to_fail); 35 : 36 : // No need to check anything else if GetTxPayload() expected to fail 37 74 : if (payload_to_fail) return; 38 : 39 72 : TxValidationState dummy_state; 40 72 : BOOST_CHECK_EQUAL(opt_payload->IsTriviallyValid(pindexPrev, chainman, dummy_state), !expected_error.has_value()); 41 72 : if (expected_error.has_value()) { 42 22 : BOOST_CHECK_EQUAL(dummy_state.GetRejectReason(), expected_error.value()); 43 22 : } 44 74 : } 45 : 46 4 : void trivialvalidation_runner(const ChainstateManager& chainman, const std::string& json) 47 : { 48 4 : const UniValue vectors = read_json(json); 49 : 50 78 : for (size_t idx = 1; idx < vectors.size(); idx++) { 51 74 : const UniValue& test = vectors[idx]; 52 74 : uint256 txHash; 53 74 : std::string txType; 54 74 : CMutableTransaction tx; 55 74 : std::optional<std::string> expected_err; 56 : try { 57 : // Additional data 58 74 : txHash = uint256S(test[0].get_str()); 59 74 : BOOST_TEST_MESSAGE("tx: " << test[0].get_str()); 60 74 : txType = test[1].get_str(); 61 74 : BOOST_CHECK(test[2].get_str() == "basic" || test[2].get_str() == "legacy"); 62 : // Determine which pindexPrev to supply based on whether we want to validate legacy or basic 63 : // TODO: Introduce trivial validation test vectors for extended addresses 64 136 : const CBlockIndex* pindexPrev{(test[2].get_str() == "basic") ? chainman.ActiveChain()[100] 65 62 : : chainman.ActiveChain()[98]}; 66 74 : assert(pindexPrev); 67 : // Raw transaction 68 74 : CDataStream stream(ParseHex(test[3].get_str()), SER_NETWORK, PROTOCOL_VERSION); 69 74 : stream >> tx; 70 74 : expected_err = (test.size() > 4) ? std::make_optional(test[4].get_str()) : std::nullopt; 71 : // Sanity check 72 74 : BOOST_CHECK_EQUAL(tx.nVersion, 3); 73 74 : BOOST_CHECK_EQUAL(tx.GetHash(), txHash); 74 : // Deserialization based on transaction nType 75 74 : TxValidationState dummy_state; 76 74 : switch (tx.nType) { 77 : case TRANSACTION_PROVIDER_REGISTER: { 78 26 : BOOST_CHECK_EQUAL(txType, "proregtx"); 79 : 80 26 : TestTxHelper<CProRegTx>(tx, pindexPrev, expected_err, chainman); 81 26 : break; 82 : } 83 : case TRANSACTION_PROVIDER_UPDATE_SERVICE: { 84 14 : BOOST_CHECK_EQUAL(txType, "proupservtx"); 85 : 86 14 : TestTxHelper<CProUpServTx>(tx, pindexPrev, expected_err, chainman); 87 14 : break; 88 : } 89 : case TRANSACTION_PROVIDER_UPDATE_REGISTRAR: { 90 18 : BOOST_CHECK_EQUAL(txType, "proupregtx"); 91 : 92 18 : TestTxHelper<CProUpRegTx>(tx, pindexPrev, expected_err, chainman); 93 18 : break; 94 : } 95 : case TRANSACTION_PROVIDER_UPDATE_REVOKE: { 96 16 : BOOST_CHECK_EQUAL(txType, "prouprevtx"); 97 : 98 16 : TestTxHelper<CProUpRevTx>(tx, pindexPrev, expected_err, chainman); 99 16 : break; 100 : } 101 : default: 102 : // TRANSACTION_COINBASE and TRANSACTION_NORMAL 103 : // are not subject to trivial validation checks 104 0 : BOOST_CHECK(false); 105 0 : } 106 74 : } catch (...) { 107 0 : BOOST_ERROR("Bad test, couldn't deserialize data: " << test.write()); 108 : continue; 109 0 : } 110 74 : } 111 4 : } 112 : 113 148 : BOOST_AUTO_TEST_CASE(trivialvalidation_valid) 114 : { 115 1 : const std::string json(json_tests::trivially_valid, json_tests::trivially_valid + sizeof(json_tests::trivially_valid)); 116 : 117 1 : bls::bls_legacy_scheme.store(true); 118 1 : trivialvalidation_runner(*m_node.chainman, json); 119 : 120 1 : bls::bls_legacy_scheme.store(false); 121 1 : trivialvalidation_runner(*m_node.chainman, json); 122 1 : } 123 : 124 148 : BOOST_AUTO_TEST_CASE(trivialvalidation_invalid) 125 : { 126 1 : const std::string json(json_tests::trivially_invalid, json_tests::trivially_invalid + sizeof(json_tests::trivially_invalid)); 127 : 128 1 : bls::bls_legacy_scheme.store(true); 129 1 : trivialvalidation_runner(*m_node.chainman, json); 130 : 131 1 : bls::bls_legacy_scheme.store(false); 132 1 : trivialvalidation_runner(*m_node.chainman, json); 133 1 : } 134 : 135 146 : BOOST_AUTO_TEST_SUITE_END()