11
11
#include < util/check.h>
12
12
#include < util/time.h>
13
13
#include < util/translation.h>
14
+ #include < validation.h>
14
15
15
16
using node::NodeContext;
16
17
@@ -36,3 +37,80 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx) const
36
37
{
37
38
return CTxMemPoolEntry{tx, nFee, TicksSinceEpoch<std::chrono::seconds>(time ), nHeight, m_sequence, spendsCoinbase, sigOpCost, lp};
38
39
}
40
+
41
+ std::optional<std::string> CheckPackageMempoolAcceptResult (const Package& txns,
42
+ const PackageMempoolAcceptResult& result,
43
+ bool expect_valid,
44
+ const CTxMemPool* mempool)
45
+ {
46
+ if (expect_valid) {
47
+ if (result.m_state .IsInvalid ()) {
48
+ return strprintf (" Package validation unexpectedly failed: %s" , result.m_state .ToString ());
49
+ }
50
+ } else {
51
+ if (result.m_state .IsValid ()) {
52
+ strprintf (" Package validation unexpectedly succeeded. %s" , result.m_state .ToString ());
53
+ }
54
+ }
55
+ if (result.m_state .GetResult () != PackageValidationResult::PCKG_POLICY && txns.size () != result.m_tx_results .size ()) {
56
+ strprintf (" txns size %u does not match tx results size %u" , txns.size (), result.m_tx_results .size ());
57
+ }
58
+ for (const auto & tx : txns) {
59
+ const auto & wtxid = tx->GetWitnessHash ();
60
+ if (result.m_tx_results .count (wtxid) == 0 ) {
61
+ return strprintf (" result not found for tx %s" , wtxid.ToString ());
62
+ }
63
+
64
+ const auto & atmp_result = result.m_tx_results .at (wtxid);
65
+ const bool valid{atmp_result.m_result_type == MempoolAcceptResult::ResultType::VALID};
66
+ if (expect_valid && atmp_result.m_state .IsInvalid ()) {
67
+ return strprintf (" tx %s unexpectedly failed: %s" , wtxid.ToString (), atmp_result.m_state .ToString ());
68
+ }
69
+
70
+ // m_replaced_transactions should exist iff the result was VALID
71
+ if (atmp_result.m_replaced_transactions .has_value () != valid) {
72
+ return strprintf (" tx %s result should %shave m_replaced_transactions" ,
73
+ wtxid.ToString (), valid ? " " : " not " );
74
+ }
75
+
76
+ // m_vsize and m_base_fees should exist iff the result was VALID or MEMPOOL_ENTRY
77
+ const bool mempool_entry{atmp_result.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY};
78
+ if (atmp_result.m_base_fees .has_value () != (valid || mempool_entry)) {
79
+ return strprintf (" tx %s result should %shave m_base_fees" , wtxid.ToString (), valid || mempool_entry ? " " : " not " );
80
+ }
81
+ if (atmp_result.m_vsize .has_value () != (valid || mempool_entry)) {
82
+ return strprintf (" tx %s result should %shave m_vsize" , wtxid.ToString (), valid || mempool_entry ? " " : " not " );
83
+ }
84
+
85
+ // m_other_wtxid should exist iff the result was DIFFERENT_WITNESS
86
+ const bool diff_witness{atmp_result.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS};
87
+ if (atmp_result.m_other_wtxid .has_value () != diff_witness) {
88
+ return strprintf (" tx %s result should %shave m_other_wtxid" , wtxid.ToString (), diff_witness ? " " : " not " );
89
+ }
90
+
91
+ // m_effective_feerate and m_wtxids_fee_calculations should exist iff the result was valid
92
+ if (atmp_result.m_effective_feerate .has_value () != valid) {
93
+ return strprintf (" tx %s result should %shave m_effective_feerate" ,
94
+ wtxid.ToString (), valid ? " " : " not " );
95
+ }
96
+ if (atmp_result.m_wtxids_fee_calculations .has_value () != valid) {
97
+ return strprintf (" tx %s result should %shave m_effective_feerate" ,
98
+ wtxid.ToString (), valid ? " " : " not " );
99
+ }
100
+
101
+ if (mempool) {
102
+ // The tx by txid should be in the mempool iff the result was not INVALID.
103
+ const bool txid_in_mempool{atmp_result.m_result_type != MempoolAcceptResult::ResultType::INVALID};
104
+ if (mempool->exists (GenTxid::Txid (tx->GetHash ())) != txid_in_mempool) {
105
+ strprintf (" tx %s should %sbe in mempool" , wtxid.ToString (), txid_in_mempool ? " " : " not " );
106
+ }
107
+ // Additionally, if the result was DIFFERENT_WITNESS, we shouldn't be able to find the tx in mempool by wtxid.
108
+ if (tx->HasWitness () && atmp_result.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS) {
109
+ if (mempool->exists (GenTxid::Wtxid (wtxid))) {
110
+ strprintf (" wtxid %s should not be in mempool" , wtxid.ToString ());
111
+ }
112
+ }
113
+ }
114
+ }
115
+ return std::nullopt;
116
+ }
0 commit comments