@@ -43,6 +43,11 @@ struct Runner
43
43
44
44
/* * Which txhashes have been assigned already (to prevent reuse). */
45
45
std::set<uint256> txhashset;
46
+
47
+ /* * Which (peer, gtxid) combinations are known to be expired. These need to be accumulated here instead of
48
+ * checked directly in the GetRequestable return value to avoid introducing a dependency between the various
49
+ * parallel tests. */
50
+ std::multiset<std::pair<NodeId, GenTxid>> expired;
46
51
};
47
52
48
53
std::chrono::microseconds RandomTime8s () { return std::chrono::microseconds{1 + InsecureRandBits (23 )}; }
@@ -149,7 +154,9 @@ class Scenario
149
154
const auto now = m_now;
150
155
assert (offset.count () <= 0 );
151
156
runner.actions .emplace_back (m_now, [=,&runner]() {
152
- auto ret = runner.txrequest .GetRequestable (peer, now + offset);
157
+ std::vector<std::pair<NodeId, GenTxid>> expired_now;
158
+ auto ret = runner.txrequest .GetRequestable (peer, now + offset, &expired_now);
159
+ for (const auto & entry : expired_now) runner.expired .insert (entry);
153
160
runner.txrequest .SanityCheck ();
154
161
runner.txrequest .PostGetRequestableSanityCheck (now + offset);
155
162
size_t total = candidates + inflight + completed;
@@ -163,6 +170,21 @@ class Scenario
163
170
});
164
171
}
165
172
173
+ /* * Verify that an announcement for gtxid by peer has expired some time before this check is scheduled.
174
+ *
175
+ * Every expected expiration should be accounted for through exactly one call to this function.
176
+ */
177
+ void CheckExpired (NodeId peer, GenTxid gtxid)
178
+ {
179
+ const auto & testname = m_testname;
180
+ auto & runner = m_runner;
181
+ runner.actions .emplace_back (m_now, [=,&runner]() {
182
+ auto it = runner.expired .find (std::pair<NodeId, GenTxid>{peer, gtxid});
183
+ BOOST_CHECK_MESSAGE (it != runner.expired .end (), " [" + testname + " ] missing expiration" );
184
+ if (it != runner.expired .end ()) runner.expired .erase (it);
185
+ });
186
+ }
187
+
166
188
/* * Generate a random txhash, whose priorities for certain peers are constrained.
167
189
*
168
190
* For example, NewTxHash({{p1,p2,p3},{p2,p4,p5}}) will generate a txhash T such that both:
@@ -256,6 +278,7 @@ void BuildSingleTest(Scenario& scenario, int config)
256
278
scenario.Check (peer, {}, 0 , 1 , 0 , " s7" );
257
279
scenario.AdvanceTime (MICROSECOND);
258
280
scenario.Check (peer, {}, 0 , 0 , 0 , " s8" );
281
+ scenario.CheckExpired (peer, gtxid);
259
282
return ;
260
283
} else {
261
284
scenario.AdvanceTime (std::chrono::microseconds{InsecureRandRange (expiry.count ())});
@@ -268,7 +291,6 @@ void BuildSingleTest(Scenario& scenario, int config)
268
291
}
269
292
}
270
293
271
- if (InsecureRandBool ()) scenario.AdvanceTime (RandomTime8s ());
272
294
if (config & 4 ) { // The peer will go offline
273
295
scenario.DisconnectedPeer (peer);
274
296
} else { // The transaction is no longer needed
@@ -519,9 +541,11 @@ void BuildWtxidTest(Scenario& scenario, int config)
519
541
if (config & 2 ) {
520
542
scenario.Check (peerT, {}, 0 , 0 , 1 , " w9" );
521
543
scenario.Check (peerW, {wtxid}, 1 , 0 , 0 , " w10" );
544
+ scenario.CheckExpired (peerT, txid);
522
545
} else {
523
546
scenario.Check (peerT, {txid}, 1 , 0 , 0 , " w11" );
524
547
scenario.Check (peerW, {}, 0 , 0 , 1 , " w12" );
548
+ scenario.CheckExpired (peerW, wtxid);
525
549
}
526
550
527
551
// If a good transaction with either that hash as wtxid or txid arrives, both
@@ -567,6 +591,7 @@ void BuildTimeBackwardsTest(Scenario& scenario)
567
591
scenario.AdvanceTime (expiry - scenario.Now ());
568
592
scenario.Check (peer1, {}, 0 , 0 , 1 , " r9" );
569
593
scenario.Check (peer2, {gtxid}, 1 , 0 , 0 , " r10" ); // Request goes back to peer2.
594
+ scenario.CheckExpired (peer1, gtxid);
570
595
scenario.Check (peer1, {}, 0 , 0 , 1 , " r11" , -MICROSECOND); // Going back does not unexpire.
571
596
scenario.Check (peer2, {gtxid}, 1 , 0 , 0 , " r12" , -MICROSECOND);
572
597
@@ -623,6 +648,7 @@ void BuildWeirdRequestsTest(Scenario& scenario)
623
648
scenario.AdvanceTime (expiryA - scenario.Now ());
624
649
scenario.Check (peer1, {}, 0 , 0 , 1 , " q12" );
625
650
scenario.Check (peer2, {gtxid2, gtxid1}, 2 , 0 , 0 , " q13" );
651
+ scenario.CheckExpired (peer1, gtxid1);
626
652
627
653
// Requesting it yet again from peer1 doesn't do anything, as it's already COMPLETED.
628
654
if (InsecureRandBool ()) scenario.AdvanceTime (RandomTime8s ());
@@ -697,6 +723,7 @@ void TestInterleavedScenarios()
697
723
}
698
724
699
725
BOOST_CHECK_EQUAL (runner.txrequest .Size (), 0U );
726
+ BOOST_CHECK (runner.expired .empty ());
700
727
}
701
728
702
729
} // namespace
0 commit comments