Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
proofpool_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2021 The Bitcoin developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
9#include <key.h>
11#include <primitives/txid.h>
12#include <random.h>
13
14#include <avalanche/test/util.h>
15#include <test/util/random.h>
16#include <test/util/setup_common.h>
17
18#include <boost/test/unit_test.hpp>
19
20using namespace avalanche;
21
23
26 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
27
28 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 0);
29
31 for (size_t i = 0; i < 10; i++) {
33 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
34 ProofPool::AddProofStatus::SUCCEED);
35 proofIds.insert(proof->getId());
36 }
37
38 auto fetchedProofIds = testPool.getProofIds();
39 BOOST_CHECK_EQUAL(testPool.countProofs(), 10);
41 for (auto proofid : proofIds) {
42 BOOST_CHECK_EQUAL(fetchedProofIds.count(proofid), 1);
43 }
44}
45
48
49 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
50
51 std::vector<ProofRef> proofs;
52 for (size_t i = 0; i < 10; i++) {
53 // Add a bunch of random proofs
55 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
56 ProofPool::AddProofStatus::SUCCEED);
57 BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
58 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), i + 1);
59
60 // Trying to add them again will return a duplicated status
61 for (size_t j = 0; j < 10; j++) {
62 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
63 ProofPool::AddProofStatus::DUPLICATED);
64 BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
65 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), i + 1);
66 }
67 proofs.push_back(std::move(proof));
68 }
69
70 const CKey key = CKey::MakeCompressedKey();
72
73 auto buildProofWithSequence = [&](uint64_t sequence) {
76 pb.addUTXO(conflictingOutpoint, 10 * COIN, 123456, false, key));
77 return pb.build();
78 };
79
81 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof_seq10),
82 ProofPool::AddProofStatus::SUCCEED);
83 BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
84 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 11);
85 proofs.push_back(std::move(proof_seq10));
86
88 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof_seq20),
89 ProofPool::AddProofStatus::REJECTED);
90 BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
91 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 11);
92
93 // Removing proofs which are not in the pool will fail
94 for (size_t i = 0; i < 10; i++) {
95 BOOST_CHECK(!testPool.removeProof(ProofId(GetRandHash())));
96 }
97 BOOST_CHECK_EQUAL(testPool.countProofs(), 11);
98 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 11);
99
100 for (auto proof : proofs) {
101 BOOST_CHECK(testPool.removeProof(proof->getId()));
102 }
103 BOOST_CHECK_EQUAL(testPool.size(), 0);
104 BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
105 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 0);
106}
107
109 gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1");
112
113 testPool.rescan(pm);
114 BOOST_CHECK_EQUAL(testPool.size(), 0);
115 BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
116 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 0);
117
118 // No peer should be created
119 bool hasPeer = false;
120 pm.forEachPeer([&](const Peer &p) { hasPeer = true; });
122
123 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
124
125 std::set<ProofRef, ProofRefComparatorByAddress> poolProofs;
126 for (size_t i = 0; i < 10; i++) {
128 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
129 ProofPool::AddProofStatus::SUCCEED);
130 poolProofs.insert(std::move(proof));
131 BOOST_CHECK_EQUAL(testPool.countProofs(), i + 1);
132 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), i + 1);
133 }
134
135 testPool.rescan(pm);
136
137 // All the proofs should be registered as peer
138 std::set<ProofRef, ProofRefComparatorByAddress> pmProofs;
139 pm.forEachPeer([&](const Peer &p) { pmProofs.insert(p.proof); });
141 pmProofs.begin(), pmProofs.end());
142 BOOST_CHECK_EQUAL(testPool.size(), 0);
143 BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
144 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 0);
145
146 gArgs.ClearForcedArg("-avaproofstakeutxoconfirmations");
147}
148
151
152 const CKey key = CKey::MakeCompressedKey();
153
155 [&](uint64_t sequence, const std::vector<COutPoint> &outpoints) {
157 for (const COutPoint &outpoint : outpoints) {
159 pb.addUTXO(outpoint, 10 * COIN, 123456, false, key));
160 }
161 return pb.build();
162 };
163
164 const COutPoint outpoint1{TxId(GetRandHash()), 0};
165 const COutPoint outpoint2{TxId(GetRandHash()), 0};
166 const COutPoint outpoint3{TxId(GetRandHash()), 0};
167
168 // Build and register 3 proofs with a single utxo
172
173 BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq10),
174 ProofPool::AddProofStatus::SUCCEED);
175 BOOST_CHECK(testPool.getProof(proof_seq10->getId()));
176 BOOST_CHECK_EQUAL(testPool.countProofs(), 1);
177 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 1);
178
179 BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq20),
180 ProofPool::AddProofStatus::SUCCEED);
181 BOOST_CHECK(testPool.getProof(proof_seq20->getId()));
182 BOOST_CHECK_EQUAL(testPool.countProofs(), 2);
183 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 2);
184
185 BOOST_CHECK_EQUAL(testPool.addProofIfPreferred(proof_seq30),
186 ProofPool::AddProofStatus::SUCCEED);
187 BOOST_CHECK(testPool.getProof(proof_seq30->getId()));
188 BOOST_CHECK_EQUAL(testPool.countProofs(), 3);
189 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 3);
190
191 // Build a proof that conflicts with the above 3, but has a higher sequence
193 123, {outpoint1, outpoint2, outpoint3});
196
197 // The no conflict call should reject our candidate and not alter the 3
198 // conflicting proofs
201 testPool.addProofIfNoConflict(proof_seq123, conflictingProofs),
202 ProofPool::AddProofStatus::REJECTED);
206 BOOST_CHECK_EQUAL(testPool.countProofs(), 3);
207 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 3);
208 BOOST_CHECK(!testPool.getProof(proof_seq123->getId()));
209 BOOST_CHECK(testPool.getProof(proof_seq10->getId()));
210 BOOST_CHECK(testPool.getProof(proof_seq20->getId()));
211 BOOST_CHECK(testPool.getProof(proof_seq30->getId()));
212
213 // The conflict handling call will override the 3 conflicting proofs
214 conflictingProofs.clear();
216 testPool.addProofIfPreferred(proof_seq123, conflictingProofs),
217 ProofPool::AddProofStatus::SUCCEED);
221 BOOST_CHECK_EQUAL(testPool.countProofs(), 1);
222 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 1);
223 BOOST_CHECK(testPool.getProof(proof_seq123->getId()));
224 BOOST_CHECK(!testPool.getProof(proof_seq10->getId()));
225 BOOST_CHECK(!testPool.getProof(proof_seq20->getId()));
226 BOOST_CHECK(!testPool.getProof(proof_seq30->getId()));
227}
228
231
232 const CKey key = CKey::MakeCompressedKey();
234
235 auto buildProofWithSequence = [&](uint64_t sequence) {
238 pb.addUTXO(conflictingOutpoint, 10 * COIN, 123456, false, key));
239 return pb.build();
240 };
241
245
246 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proofSeq20),
247 ProofPool::AddProofStatus::SUCCEED);
248
249 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
250
256 };
257 };
258
263 conflictingProofs.end(),
266 };
267
268 {
269 // Without override, duplicated proof
272 testPool.addProofIfNoConflict(proofSeq20, conflictingProofs),
273 ProofPool::AddProofStatus::DUPLICATED);
275 }
276
277 {
278 // With override, duplicated proof
281 testPool.addProofIfPreferred(proofSeq20, conflictingProofs),
282 ProofPool::AddProofStatus::DUPLICATED);
284 }
285
286 {
287 // Without override, worst proof
290 testPool.addProofIfNoConflict(proofSeq10, conflictingProofs),
291 ProofPool::AddProofStatus::REJECTED);
293 }
294
295 {
296 // Without override, better proof
299 testPool.addProofIfNoConflict(proofSeq30, conflictingProofs),
300 ProofPool::AddProofStatus::REJECTED);
302 }
303
304 {
305 // With override, worst proof
308 testPool.addProofIfPreferred(proofSeq10, conflictingProofs),
309 ProofPool::AddProofStatus::REJECTED);
311 }
312
313 {
314 // With override, better proof
317 testPool.addProofIfPreferred(proofSeq30, conflictingProofs),
318 ProofPool::AddProofStatus::SUCCEED);
320 }
321}
322
325
326 for (size_t i = 0; i < 10; i++) {
328 }
329
330 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
331
332 for (size_t i = 0; i < 10; i++) {
334 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
335 ProofPool::AddProofStatus::SUCCEED);
336
337 auto retrievedProof = testPool.getProof(proof->getId());
339 BOOST_CHECK_EQUAL(retrievedProof->getId(), proof->getId());
340 }
341}
342
345 BOOST_CHECK_EQUAL(testPool.getLowestScoreProof(), nullptr);
346
347 const CKey key = CKey::MakeCompressedKey();
348 auto buildProofWithRandomOutpoints = [&](uint32_t score) {
349 int numOutpoints = InsecureRand32() % 10 + 1;
351 for (int i = 0; i < numOutpoints; i++) {
352 Amount amount = 1 * COIN;
353 if (i == numOutpoints - 1) {
354 // Last UTXO is the remainder
355 amount =
356 (int64_t(score) * COIN) / 100 - (numOutpoints - 1) * COIN;
357 }
358 const COutPoint outpoint{TxId(GetRandHash()), 0};
359 BOOST_CHECK(pb.addUTXO(outpoint, amount, 123456, false, key));
360 }
361 return pb.build();
362 };
363
364 // Add some proofs with different scores and check the lowest scoring proof
365 for (int i = 9; i >= 0; i--) {
367 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
368 ProofPool::AddProofStatus::SUCCEED);
369 auto checkLowestScoreProof = testPool.getLowestScoreProof();
372 BOOST_CHECK_EQUAL(checkLowestScoreProof->getId(), proof->getId());
373 }
374 BOOST_CHECK_EQUAL(testPool.countProofs(), 10);
375 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 10);
376
377 auto lowestScoreProof = testPool.getLowestScoreProof();
378
379 // Adding more proofs doesn't change the lowest scoring proof
380 for (size_t i = 1; i < 10; i++) {
382 BOOST_CHECK_EQUAL(testPool.addProofIfNoConflict(proof),
383 ProofPool::AddProofStatus::SUCCEED);
384 auto checkLowestScoreProof = testPool.getLowestScoreProof();
388 lowestScoreProof->getId());
389 }
390 BOOST_CHECK_EQUAL(testPool.countProofs(), 19);
391 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 19);
392
393 // Remove proofs by lowest score, checking the lowest score as we go
394 for (int scoreCount = 1; scoreCount < 10; scoreCount++) {
395 for (size_t i = 0; i < 2; i++) {
397 testPool.removeProof(testPool.getLowestScoreProof()->getId()));
398 BOOST_CHECK_EQUAL(testPool.getLowestScoreProof()->getScore(),
400 }
401 }
402
403 // Remove the last proof
404 BOOST_CHECK(testPool.removeProof(testPool.getLowestScoreProof()->getId()));
405 BOOST_CHECK_EQUAL(testPool.getLowestScoreProof(), nullptr);
406 BOOST_CHECK_EQUAL(testPool.countProofs(), 0);
407 BOOST_CHECK_EQUAL(testPool.getProofIds().size(), 0);
408}
409
static constexpr Amount COIN
Definition amount.h:144
ArgsManager gArgs
Definition args.cpp:38
#define Assert(val)
Identity function.
Definition check.h:84
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition args.cpp:597
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
Definition args.cpp:648
An encapsulated secp256k1 private key.
Definition key.h:28
static CKey MakeCompressedKey()
Produce a valid compressed key.
Definition key.cpp:466
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:20
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition validation.h:699
Map a proof to each utxo.
Definition proofpool.h:57
std::set< ProofRef, ConflictingProofComparator > ConflictingProofSet
Definition proofpool.h:88
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
Definition proof.h:40
const CScript UNSPENDABLE_ECREG_PAYOUT_SCRIPT
Definition util.h:19
ProofRef buildRandomProof(Chainstate &active_chainstate, uint32_t score, int height, const CKey &masterKey)
Definition util.cpp:20
constexpr uint32_t MIN_VALID_PROOF_SCORE
Definition util.h:17
std::unordered_set< ProofId, SaltedProofIdHasher > ProofIdSet
Definition proofpool.h:52
NodeContext & m_node
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:18
#define BOOST_CHECK(expr)
Definition object.cpp:17
BOOST_AUTO_TEST_CASE(get_proof_ids)
uint256 GetRandHash() noexcept
Definition random.cpp:659
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
A TxId is the identifier of a transaction.
Definition txid.h:14