Branch data Line data Source code
1 : : // Copyright (c) 2011-2022 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 <arith_uint256.h>
6 : : #include <consensus/validation.h>
7 : : #include <policy/policy.h>
8 : : #include <primitives/transaction.h>
9 : : #include <pubkey.h>
10 : : #include <script/sign.h>
11 : : #include <script/signingprovider.h>
12 : : #include <test/util/random.h>
13 : : #include <test/util/setup_common.h>
14 : : #include <test/util/transaction_utils.h>
15 : : #include <txorphanage.h>
16 : :
17 : : #include <array>
18 : : #include <cstdint>
19 : :
20 : : #include <boost/test/unit_test.hpp>
21 : :
22 : : BOOST_FIXTURE_TEST_SUITE(orphanage_tests, TestingSetup)
23 : :
24 : 0 : class TxOrphanageTest : public TxOrphanage
25 : : {
26 : : public:
27 : 2 : TxOrphanageTest(FastRandomContext& rng) : m_rng{rng} {}
28 : :
29 : 14 : inline size_t CountOrphans() const
30 : : {
31 [ + - ]: 3 : return m_orphans.size();
32 : : }
33 : :
34 : 60 : CTransactionRef RandomOrphan()
35 : : {
36 : 60 : std::map<Wtxid, OrphanTx>::iterator it;
37 : 60 : it = m_orphans.lower_bound(Wtxid::FromUint256(m_rng.rand256()));
38 [ - + ]: 60 : if (it == m_orphans.end())
39 : 0 : it = m_orphans.begin();
40 [ + - ]: 60 : return it->second.tx;
41 : : }
42 : :
43 : : FastRandomContext& m_rng;
44 : : };
45 : :
46 : 10 : static void MakeNewKeyWithFastRandomContext(CKey& key, FastRandomContext& rand_ctx)
47 : : {
48 : 10 : std::vector<unsigned char> keydata;
49 : 10 : keydata = rand_ctx.randbytes(32);
50 [ + - ]: 10 : key.Set(keydata.data(), keydata.data() + keydata.size(), /*fCompressedIn=*/true);
51 [ - + ]: 10 : assert(key.IsValid());
52 : 10 : }
53 : :
54 : : // Creates a transaction with 2 outputs. Spends all outpoints. If outpoints is empty, spends a random one.
55 : 9 : static CTransactionRef MakeTransactionSpending(const std::vector<COutPoint>& outpoints, FastRandomContext& det_rand)
56 : : {
57 : 9 : CKey key;
58 [ + - ]: 9 : MakeNewKeyWithFastRandomContext(key, det_rand);
59 [ + - ]: 9 : CMutableTransaction tx;
60 : : // If no outpoints are given, create a random one.
61 [ + + ]: 9 : if (outpoints.empty()) {
62 [ + - ]: 4 : tx.vin.emplace_back(Txid::FromUint256(det_rand.rand256()), 0);
63 : : } else {
64 [ + + ]: 12 : for (const auto& outpoint : outpoints) {
65 [ + - ]: 7 : tx.vin.emplace_back(outpoint);
66 : : }
67 : : }
68 : : // Ensure txid != wtxid
69 [ + - + - ]: 18 : tx.vin[0].scriptWitness.stack.push_back({1});
70 [ + - ]: 9 : tx.vout.resize(2);
71 [ + - ]: 9 : tx.vout[0].nValue = CENT;
72 [ + - + - : 9 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
+ - ]
73 [ + - ]: 9 : tx.vout[1].nValue = 3 * CENT;
74 [ + - + - : 9 : tx.vout[1].scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(key.GetPubKey()));
+ - ]
75 [ + - ]: 18 : return MakeTransactionRef(tx);
76 : 9 : }
77 : :
78 : : // Make another (not necessarily valid) tx with the same txid but different wtxid.
79 : 1 : static CTransactionRef MakeMutation(const CTransactionRef& ptx)
80 : : {
81 : 1 : CMutableTransaction tx(*ptx);
82 [ + - + - ]: 2 : tx.vin[0].scriptWitness.stack.push_back({5});
83 [ + - ]: 1 : auto mutated_tx = MakeTransactionRef(tx);
84 [ - + ]: 1 : assert(ptx->GetHash() == mutated_tx->GetHash());
85 : 1 : return mutated_tx;
86 : 1 : }
87 : :
88 : 7 : static bool EqualTxns(const std::set<CTransactionRef>& set_txns, const std::vector<CTransactionRef>& vec_txns)
89 : : {
90 [ + - ]: 7 : if (vec_txns.size() != set_txns.size()) return false;
91 [ + + ]: 19 : for (const auto& tx : vec_txns) {
92 [ + - ]: 12 : if (!set_txns.contains(tx)) return false;
93 : : }
94 : : return true;
95 : : }
96 : 6 : static bool EqualTxns(const std::set<CTransactionRef>& set_txns,
97 : : const std::vector<std::pair<CTransactionRef, NodeId>>& vec_txns)
98 : : {
99 [ + - ]: 6 : if (vec_txns.size() != set_txns.size()) return false;
100 [ + + ]: 16 : for (const auto& [tx, nodeid] : vec_txns) {
101 [ + - ]: 10 : if (!set_txns.contains(tx)) return false;
102 : : }
103 : : return true;
104 : : }
105 : :
106 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
107 : : {
108 : : // This test had non-deterministic coverage due to
109 : : // randomly selected seeds.
110 : : // This seed is chosen so that all branches of the function
111 : : // ecdsa_signature_parse_der_lax are executed during this test.
112 : : // Specifically branches that run only when an ECDSA
113 : : // signature's R and S values have leading zeros.
114 : 1 : m_rng.Reseed(uint256{33});
115 : :
116 : 1 : TxOrphanageTest orphanage{m_rng};
117 : 1 : CKey key;
118 [ + - ]: 1 : MakeNewKeyWithFastRandomContext(key, m_rng);
119 : 1 : FillableSigningProvider keystore;
120 [ + - + - : 2 : BOOST_CHECK(keystore.AddKey(key));
+ - ]
121 : :
122 : : // Freeze time for length of test
123 : 1 : auto now{GetTime<std::chrono::seconds>()};
124 [ + - ]: 1 : SetMockTime(now);
125 : :
126 : : // 50 orphan transactions:
127 [ + + ]: 51 : for (int i = 0; i < 50; i++)
128 : : {
129 [ + - ]: 50 : CMutableTransaction tx;
130 [ + - ]: 50 : tx.vin.resize(1);
131 : 50 : tx.vin[0].prevout.n = 0;
132 [ + - ]: 50 : tx.vin[0].prevout.hash = Txid::FromUint256(m_rng.rand256());
133 [ + - ]: 50 : tx.vin[0].scriptSig << OP_1;
134 [ + - ]: 50 : tx.vout.resize(1);
135 [ + - ]: 50 : tx.vout[0].nValue = 1*CENT;
136 [ + - + - : 50 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
+ - ]
137 : :
138 [ + - + - ]: 150 : orphanage.AddTx(MakeTransactionRef(tx), i);
139 : 50 : }
140 : :
141 : : // ... and 50 that depend on other orphans:
142 [ + + ]: 51 : for (int i = 0; i < 50; i++)
143 : : {
144 : 50 : CTransactionRef txPrev = orphanage.RandomOrphan();
145 : :
146 [ + - ]: 50 : CMutableTransaction tx;
147 [ + - ]: 50 : tx.vin.resize(1);
148 [ + - ]: 50 : tx.vin[0].prevout.n = 0;
149 [ + - ]: 50 : tx.vin[0].prevout.hash = txPrev->GetHash();
150 [ + - ]: 50 : tx.vout.resize(1);
151 [ + - ]: 50 : tx.vout[0].nValue = 1*CENT;
152 [ + - + - : 50 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
+ - ]
153 : 50 : SignatureData empty;
154 [ + - + - : 100 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
+ - + - ]
155 : :
156 [ + - + - ]: 100 : orphanage.AddTx(MakeTransactionRef(tx), i);
157 [ + - ]: 150 : }
158 : :
159 : : // This really-big orphan should be ignored:
160 [ + + ]: 11 : for (int i = 0; i < 10; i++)
161 : : {
162 : 10 : CTransactionRef txPrev = orphanage.RandomOrphan();
163 : :
164 [ + - ]: 10 : CMutableTransaction tx;
165 [ + - ]: 10 : tx.vout.resize(1);
166 [ + - ]: 10 : tx.vout[0].nValue = 1*CENT;
167 [ + - + - : 10 : tx.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
+ - ]
168 [ + - ]: 10 : tx.vin.resize(2777);
169 [ + + ]: 27780 : for (unsigned int j = 0; j < tx.vin.size(); j++)
170 : : {
171 : 27770 : tx.vin[j].prevout.n = j;
172 : 27770 : tx.vin[j].prevout.hash = txPrev->GetHash();
173 : : }
174 : 10 : SignatureData empty;
175 [ + - + - : 20 : BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
+ - ]
176 : : // Reuse same signature for other inputs
177 : : // (they don't have to be valid for this test)
178 [ + + ]: 27770 : for (unsigned int j = 1; j < tx.vin.size(); j++)
179 : 27760 : tx.vin[j].scriptSig = tx.vin[0].scriptSig;
180 : :
181 [ + - + - : 40 : BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
+ - + - +
- ]
182 [ + - ]: 30 : }
183 : :
184 [ + - ]: 1 : size_t expected_num_orphans = orphanage.CountOrphans();
185 : :
186 : : // Non-existent peer; nothing should be deleted
187 [ + - ]: 1 : orphanage.EraseForPeer(/*peer=*/-1);
188 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);
189 : :
190 : : // Each of first three peers stored
191 : : // two transactions each.
192 [ + + ]: 4 : for (NodeId i = 0; i < 3; i++)
193 : : {
194 [ + - ]: 3 : orphanage.EraseForPeer(i);
195 : 3 : expected_num_orphans -= 2;
196 [ + - + - ]: 6 : BOOST_CHECK(orphanage.CountOrphans() == expected_num_orphans);
197 : : }
198 : :
199 : : // Test LimitOrphanTxSize() function, nothing should timeout:
200 : 1 : FastRandomContext rng{/*fDeterministic=*/true};
201 [ + - ]: 1 : orphanage.LimitOrphans(/*max_orphans=*/expected_num_orphans, rng);
202 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);
203 : 1 : expected_num_orphans -= 1;
204 [ + - ]: 1 : orphanage.LimitOrphans(/*max_orphans=*/expected_num_orphans, rng);
205 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);
206 [ - + ]: 1 : assert(expected_num_orphans > 40);
207 [ + - ]: 1 : orphanage.LimitOrphans(40, rng);
208 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 40);
209 [ + - ]: 1 : orphanage.LimitOrphans(10, rng);
210 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 10);
211 [ + - ]: 1 : orphanage.LimitOrphans(0, rng);
212 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 0);
213 : :
214 : : // Add one more orphan, check timeout logic
215 [ + - ]: 1 : auto timeout_tx = MakeTransactionSpending(/*outpoints=*/{}, rng);
216 [ + - ]: 1 : orphanage.AddTx(timeout_tx, 0);
217 [ + - ]: 1 : orphanage.LimitOrphans(1, rng);
218 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 1);
219 : :
220 : : // One second shy of expiration
221 [ + - ]: 1 : SetMockTime(now + ORPHAN_TX_EXPIRE_TIME - 1s);
222 [ + - ]: 1 : orphanage.LimitOrphans(1, rng);
223 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 1);
224 : :
225 : : // Jump one more second, orphan should be timed out on limiting
226 [ + - ]: 1 : SetMockTime(now + ORPHAN_TX_EXPIRE_TIME);
227 [ + - + - ]: 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 1);
228 [ + - ]: 1 : orphanage.LimitOrphans(1, rng);
229 [ + - + - : 1 : BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 0);
+ - ]
230 : 1 : }
231 : :
232 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(same_txid_diff_witness)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
233 : : {
234 : 1 : FastRandomContext det_rand{true};
235 : 1 : TxOrphanage orphanage;
236 : 1 : NodeId peer{0};
237 : :
238 : 1 : std::vector<COutPoint> empty_outpoints;
239 [ + - ]: 1 : auto parent = MakeTransactionSpending(empty_outpoints, det_rand);
240 : :
241 : : // Create children to go into orphanage.
242 [ + - + - : 2 : auto child_normal = MakeTransactionSpending({{parent->GetHash(), 0}}, det_rand);
+ - ]
243 [ + - ]: 1 : auto child_mutated = MakeMutation(child_normal);
244 : :
245 [ + - ]: 1 : const auto& normal_wtxid = child_normal->GetWitnessHash();
246 : 1 : const auto& mutated_wtxid = child_mutated->GetWitnessHash();
247 [ + - + - : 2 : BOOST_CHECK(normal_wtxid != mutated_wtxid);
+ - ]
248 : :
249 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_normal, peer));
+ - + - ]
250 : : // EraseTx fails as transaction by this wtxid doesn't exist.
251 [ + - + - : 1 : BOOST_CHECK_EQUAL(orphanage.EraseTx(mutated_wtxid), 0);
+ - ]
252 [ + - + - : 2 : BOOST_CHECK(orphanage.HaveTx(normal_wtxid));
+ - + - ]
253 [ + - + - : 2 : BOOST_CHECK(!orphanage.HaveTx(mutated_wtxid));
+ - + - ]
254 : :
255 : : // Must succeed. Both transactions should be present in orphanage.
256 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_mutated, peer));
+ - + - ]
257 [ + - + - : 2 : BOOST_CHECK(orphanage.HaveTx(normal_wtxid));
+ - + - ]
258 [ + - + - : 2 : BOOST_CHECK(orphanage.HaveTx(mutated_wtxid));
+ - + - ]
259 : :
260 : : // Outpoints map should track all entries: check that both are returned as children of the parent.
261 [ + + + - : 3 : std::set<CTransactionRef> expected_children{child_normal, child_mutated};
- - - - ]
262 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_children, orphanage.GetChildrenFromSamePeer(parent, peer)));
+ - + - ]
263 : :
264 : : // Erase by wtxid: mutated first
265 [ + - + - : 1 : BOOST_CHECK_EQUAL(orphanage.EraseTx(mutated_wtxid), 1);
+ - ]
266 [ + - + - : 2 : BOOST_CHECK(orphanage.HaveTx(normal_wtxid));
+ - + - ]
267 [ + - + - : 2 : BOOST_CHECK(!orphanage.HaveTx(mutated_wtxid));
+ - + - ]
268 : :
269 [ + - + - : 1 : BOOST_CHECK_EQUAL(orphanage.EraseTx(normal_wtxid), 1);
+ - ]
270 [ + - + - : 2 : BOOST_CHECK(!orphanage.HaveTx(normal_wtxid));
+ - + - ]
271 [ + - + - : 2 : BOOST_CHECK(!orphanage.HaveTx(mutated_wtxid));
+ - ]
272 [ + - + - : 7 : }
- + + - +
- + - ]
273 : :
274 : :
275 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(get_children)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
276 : : {
277 : 1 : FastRandomContext det_rand{true};
278 : 1 : std::vector<COutPoint> empty_outpoints;
279 : :
280 [ + - ]: 1 : auto parent1 = MakeTransactionSpending(empty_outpoints, det_rand);
281 [ + - ]: 1 : auto parent2 = MakeTransactionSpending(empty_outpoints, det_rand);
282 : :
283 : : // Make sure these parents have different txids otherwise this test won't make sense.
284 [ - + ]: 1 : while (parent1->GetHash() == parent2->GetHash()) {
285 [ # # # # ]: 0 : parent2 = MakeTransactionSpending(empty_outpoints, det_rand);
286 : : }
287 : :
288 : : // Create children to go into orphanage.
289 [ + - + - : 2 : auto child_p1n0 = MakeTransactionSpending({{parent1->GetHash(), 0}}, det_rand);
+ - ]
290 [ + - + - : 2 : auto child_p2n1 = MakeTransactionSpending({{parent2->GetHash(), 1}}, det_rand);
+ - ]
291 : : // Spends the same tx twice. Should not cause duplicates.
292 [ + - + - : 2 : auto child_p1n0_p1n1 = MakeTransactionSpending({{parent1->GetHash(), 0}, {parent1->GetHash(), 1}}, det_rand);
+ - ]
293 : : // Spends the same outpoint as previous tx. Should still be returned; don't assume outpoints are unique.
294 [ + - + - ]: 2 : auto child_p1n0_p2n0 = MakeTransactionSpending({{parent1->GetHash(), 0}, {parent2->GetHash(), 0}}, det_rand);
295 : :
296 : 1 : const NodeId node1{1};
297 : 1 : const NodeId node2{2};
298 : :
299 : : // All orphans provided by node1
300 : 1 : {
301 : 1 : TxOrphanage orphanage;
302 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0, node1));
+ - + - ]
303 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p2n1, node1));
+ - + - ]
304 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0_p1n1, node1));
+ - + - ]
305 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0_p2n0, node1));
+ - + - ]
306 : :
307 [ + + + - : 4 : std::set<CTransactionRef> expected_parent1_children{child_p1n0, child_p1n0_p2n0, child_p1n0_p1n1};
- - - - ]
308 [ + + + - : 3 : std::set<CTransactionRef> expected_parent2_children{child_p2n1, child_p1n0_p2n0};
- - - - ]
309 : :
310 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_children, orphanage.GetChildrenFromSamePeer(parent1, node1)));
+ - + - ]
311 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_children, orphanage.GetChildrenFromSamePeer(parent2, node1)));
+ - + - ]
312 : :
313 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_children, orphanage.GetChildrenFromDifferentPeer(parent1, node2)));
+ - + - ]
314 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_children, orphanage.GetChildrenFromDifferentPeer(parent2, node2)));
+ - + - ]
315 : :
316 : : // The peer must match
317 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromSamePeer(parent1, node2).empty());
+ - + - ]
318 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromSamePeer(parent2, node2).empty());
+ - + - ]
319 : :
320 : : // There shouldn't be any children of this tx in the orphanage
321 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromSamePeer(child_p1n0_p2n0, node1).empty());
+ - + - ]
322 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromSamePeer(child_p1n0_p2n0, node2).empty());
+ - + - ]
323 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromDifferentPeer(child_p1n0_p2n0, node1).empty());
+ - + - ]
324 [ + - + - : 2 : BOOST_CHECK(orphanage.GetChildrenFromDifferentPeer(child_p1n0_p2n0, node2).empty());
+ - ]
325 : 1 : }
326 : :
327 : : // Orphans provided by node1 and node2
328 : 1 : {
329 : 1 : TxOrphanage orphanage;
330 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0, node1));
+ - + - ]
331 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p2n1, node1));
+ - + - ]
332 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0_p1n1, node2));
+ - + - ]
333 [ + - + - : 2 : BOOST_CHECK(orphanage.AddTx(child_p1n0_p2n0, node2));
+ - + - ]
334 : :
335 : : // +----------------+---------------+----------------------------------+
336 : : // | | sender=node1 | sender=node2 |
337 : : // +----------------+---------------+----------------------------------+
338 : : // | spends parent1 | child_p1n0 | child_p1n0_p1n1, child_p1n0_p2n0 |
339 : : // | spends parent2 | child_p2n1 | child_p1n0_p2n0 |
340 : : // +----------------+---------------+----------------------------------+
341 : :
342 : : // Children of parent1 from node1:
343 : 1 : {
344 [ + + + - : 2 : std::set<CTransactionRef> expected_parent1_node1{child_p1n0};
- - - - ]
345 : :
346 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_node1, orphanage.GetChildrenFromSamePeer(parent1, node1)));
+ - + - ]
347 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_node1, orphanage.GetChildrenFromDifferentPeer(parent1, node2)));
+ - ]
348 : 0 : }
349 : :
350 : : // Children of parent2 from node1:
351 : 1 : {
352 [ + + + - : 2 : std::set<CTransactionRef> expected_parent2_node1{child_p2n1};
- - - - ]
353 : :
354 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_node1, orphanage.GetChildrenFromSamePeer(parent2, node1)));
+ - + - ]
355 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_node1, orphanage.GetChildrenFromDifferentPeer(parent2, node2)));
+ - ]
356 : 0 : }
357 : :
358 : : // Children of parent1 from node2:
359 : 1 : {
360 [ + + + - : 3 : std::set<CTransactionRef> expected_parent1_node2{child_p1n0_p1n1, child_p1n0_p2n0};
- - - - ]
361 : :
362 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_node2, orphanage.GetChildrenFromSamePeer(parent1, node2)));
+ - + - ]
363 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent1_node2, orphanage.GetChildrenFromDifferentPeer(parent1, node1)));
+ - ]
364 : 0 : }
365 : :
366 : : // Children of parent2 from node2:
367 : 1 : {
368 [ + + + - : 2 : std::set<CTransactionRef> expected_parent2_node2{child_p1n0_p2n0};
- - - - ]
369 : :
370 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_node2, orphanage.GetChildrenFromSamePeer(parent2, node2)));
+ - + - ]
371 [ + - + - : 2 : BOOST_CHECK(EqualTxns(expected_parent2_node2, orphanage.GetChildrenFromDifferentPeer(parent2, node1)));
+ - ]
372 : 0 : }
373 [ + - ]: 1 : }
374 [ + - + - : 22 : }
+ - - + +
- + - - +
+ - - + +
- - + + -
+ - - + +
- - + + -
+ - + - +
- + - ]
375 : :
376 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(too_large_orphan_tx)
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
377 : : {
378 : 1 : TxOrphanage orphanage;
379 [ + - ]: 1 : CMutableTransaction tx;
380 [ + - ]: 1 : tx.vin.resize(1);
381 : :
382 : : // check that txs larger than MAX_STANDARD_TX_WEIGHT are not added to the orphanage
383 [ + - ]: 1 : BulkTransaction(tx, MAX_STANDARD_TX_WEIGHT + 4);
384 [ + - + - : 1 : BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(tx)), MAX_STANDARD_TX_WEIGHT + 4);
+ - ]
385 [ + - + - : 4 : BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), 0));
+ - + - +
- ]
386 : :
387 : 1 : tx.vout.clear();
388 [ + - ]: 1 : BulkTransaction(tx, MAX_STANDARD_TX_WEIGHT);
389 [ + - + - : 1 : BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(tx)), MAX_STANDARD_TX_WEIGHT);
+ - ]
390 [ + - + - : 4 : BOOST_CHECK(orphanage.AddTx(MakeTransactionRef(tx), 0));
+ - + - +
- ]
391 : 1 : }
392 : :
393 : : BOOST_AUTO_TEST_SUITE_END()
|