Bitcoin ABC  0.24.11
P2P Digital Currency
processor_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2020 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 
5 #include <avalanche/processor.h>
6 
10 #include <avalanche/voterecord.h>
11 #include <chain.h>
12 #include <config.h>
13 #include <net_processing.h> // For ::PeerManager
14 #include <reverse_iterator.h>
15 #include <scheduler.h>
16 #include <util/time.h>
17 #include <util/translation.h> // For bilingual_str
18 // D6970 moved LookupBlockIndex from chain.h to validation.h TODO: remove this
19 // when LookupBlockIndex is refactored out of validation
20 #include <validation.h>
21 
22 #include <avalanche/test/util.h>
23 #include <test/util/setup_common.h>
24 
25 #include <boost/mpl/list.hpp>
26 #include <boost/test/unit_test.hpp>
27 
28 using namespace avalanche;
29 
30 namespace avalanche {
31 namespace {
32  struct AvalancheTest {
33  static void runEventLoop(avalanche::Processor &p) { p.runEventLoop(); }
34 
35  static std::vector<CInv> getInvsForNextPoll(Processor &p) {
36  return p.getInvsForNextPoll(false);
37  }
38 
39  static NodeId getSuitableNodeToQuery(Processor &p) {
40  return p.getSuitableNodeToQuery();
41  }
42 
43  static uint64_t getRound(const Processor &p) { return p.round; }
44  };
45 } // namespace
46 } // namespace avalanche
47 
48 namespace {
49 struct CConnmanTest : public CConnman {
50  using CConnman::CConnman;
51  void AddNode(CNode &node) {
52  LOCK(cs_vNodes);
53  vNodes.push_back(&node);
54  }
55  void ClearNodes() {
56  LOCK(cs_vNodes);
57  for (CNode *node : vNodes) {
58  delete node;
59  }
60  vNodes.clear();
61  }
62 };
63 
64 CService ip(uint32_t i) {
65  struct in_addr s;
66  s.s_addr = i;
67  return CService(CNetAddr(s), Params().GetDefaultPort());
68 }
69 
70 struct AvalancheTestingSetup : public TestChain100Setup {
71  const Config &config;
72  CConnmanTest *m_connman;
73 
74  std::unique_ptr<Processor> m_processor;
75 
76  // The master private key we delegate to.
77  CKey masterpriv;
78 
79  AvalancheTestingSetup()
80  : TestChain100Setup(), config(GetConfig()),
81  masterpriv(CKey::MakeCompressedKey()) {
82  // Deterministic randomness for tests.
83  auto connman = std::make_unique<CConnmanTest>(config, 0x1337, 0x1337);
84  m_connman = connman.get();
85  m_node.connman = std::move(connman);
87  config.GetChainParams(), *m_connman, m_node.banman.get(),
90 
91  // Get the processor ready.
94  m_node.connman.get(), error);
95  BOOST_CHECK(m_processor);
96  }
97 
98  ~AvalancheTestingSetup() {
99  m_connman->ClearNodes();
101  }
102 
103  CNode *ConnectNode(ServiceFlags nServices) {
104  static NodeId id = 0;
105 
106  CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
107  auto node = new CNode(id++, ServiceFlags(NODE_NETWORK), INVALID_SOCKET,
108  addr, 0, 0, 0, CAddress(), "",
111  node->nServices = nServices;
112  m_node.peerman->InitializeNode(config, node);
113  node->nVersion = 1;
114  node->fSuccessfullyConnected = true;
115  node->m_avalanche_state = std::make_unique<CNode::AvalancheState>();
116 
117  m_connman->AddNode(*node);
118  return node;
119  }
120 
121  size_t next_coinbase = 0;
122  ProofRef GetProof() {
123  size_t current_coinbase = next_coinbase++;
124  const CTransaction &coinbase = *m_coinbase_txns[current_coinbase];
125  ProofBuilder pb(0, 0, masterpriv);
126  BOOST_CHECK(pb.addUTXO(COutPoint(coinbase.GetId(), 0),
127  coinbase.vout[0].nValue, current_coinbase + 1,
128  true, coinbaseKey));
129  return pb.build();
130  }
131 
132  bool addNode(NodeId nodeid, const ProofId &proofid) {
133  return m_processor->withPeerManager([&](avalanche::PeerManager &pm) {
134  return pm.addNode(nodeid, proofid);
135  });
136  }
137 
138  bool addNode(NodeId nodeid) {
139  auto proof = GetProof();
140  return m_processor->withPeerManager([&](avalanche::PeerManager &pm) {
141  return pm.registerProof(proof) &&
142  pm.addNode(nodeid, proof->getId());
143  });
144  }
145 
146  std::array<CNode *, 8> ConnectNodes() {
147  auto proof = GetProof();
148  BOOST_CHECK(
149  m_processor->withPeerManager([&](avalanche::PeerManager &pm) {
150  return pm.registerProof(proof);
151  }));
152  const ProofId &proofid = proof->getId();
153 
154  std::array<CNode *, 8> nodes;
155  for (CNode *&n : nodes) {
156  n = ConnectNode(NODE_AVALANCHE);
157  BOOST_CHECK(addNode(n->GetId(), proofid));
158  }
159 
160  return nodes;
161  }
162 
163  void runEventLoop() { AvalancheTest::runEventLoop(*m_processor); }
164 
165  NodeId getSuitableNodeToQuery() {
166  return AvalancheTest::getSuitableNodeToQuery(*m_processor);
167  }
168 
169  std::vector<CInv> getInvsForNextPoll() {
170  return AvalancheTest::getInvsForNextPoll(*m_processor);
171  }
172 
173  uint64_t getRound() const { return AvalancheTest::getRound(*m_processor); }
174 
175  bool registerVotes(NodeId nodeid, const avalanche::Response &response,
176  std::vector<avalanche::BlockUpdate> &blockUpdates) {
177  int banscore;
178  std::string error;
179  std::vector<avalanche::ProofUpdate> proofUpdates;
180  return m_processor->registerVotes(nodeid, response, blockUpdates,
181  proofUpdates, banscore, error);
182  }
183 };
184 
185 struct BlockProvider {
186  AvalancheTestingSetup *fixture;
187 
188  std::vector<BlockUpdate> updates;
189  uint32_t invType;
190 
191  BlockProvider(AvalancheTestingSetup *_fixture)
192  : fixture(_fixture), invType(MSG_BLOCK) {}
193 
194  CBlockIndex *buildVoteItem() const {
195  CBlock block = fixture->CreateAndProcessBlock({}, CScript());
196  const BlockHash blockHash = block.GetHash();
197 
198  LOCK(cs_main);
199  return LookupBlockIndex(blockHash);
200  }
201 
202  uint256 getVoteItemId(const CBlockIndex *pindex) const {
203  return pindex->GetBlockHash();
204  }
205 
206  bool registerVotes(NodeId nodeid, const avalanche::Response &response,
207  std::string &error) {
208  int banscore;
209  std::vector<avalanche::ProofUpdate> proofUpdates;
210  return fixture->m_processor->registerVotes(
211  nodeid, response, updates, proofUpdates, banscore, error);
212  }
213  bool registerVotes(NodeId nodeid, const avalanche::Response &response) {
214  std::string error;
215  return registerVotes(nodeid, response, error);
216  }
217 
218  bool addToReconcile(const CBlockIndex *pindex) {
219  return fixture->m_processor->addBlockToReconcile(pindex);
220  }
221 
222  std::vector<Vote> buildVotesForItems(uint32_t error,
223  std::vector<CBlockIndex *> &&items) {
224  size_t numItems = items.size();
225 
226  std::vector<Vote> votes;
227  votes.reserve(numItems);
228 
229  // Votes are sorted by most work first
230  std::sort(items.begin(), items.end(), CBlockIndexWorkComparator());
231  for (auto &item : reverse_iterate(items)) {
232  votes.emplace_back(error, item->GetBlockHash());
233  }
234 
235  return votes;
236  }
237 };
238 
239 struct ProofProvider {
240  AvalancheTestingSetup *fixture;
241 
242  std::vector<ProofUpdate> updates;
243  uint32_t invType;
244 
245  ProofProvider(AvalancheTestingSetup *_fixture)
246  : fixture(_fixture), invType(MSG_AVA_PROOF) {}
247 
248  ProofRef buildVoteItem() const {
249  const ProofRef proof = fixture->GetProof();
250  fixture->m_processor->withPeerManager([&](avalanche::PeerManager &pm) {
251  BOOST_CHECK(pm.registerProof(proof));
252  });
253  return proof;
254  }
255 
256  uint256 getVoteItemId(const ProofRef &proof) const {
257  return proof->getId();
258  }
259 
260  bool registerVotes(NodeId nodeid, const avalanche::Response &response,
261  std::string &error) {
262  int banscore;
263  std::vector<avalanche::BlockUpdate> blockUpdates;
264  return fixture->m_processor->registerVotes(
265  nodeid, response, blockUpdates, updates, banscore, error);
266  }
267  bool registerVotes(NodeId nodeid, const avalanche::Response &response) {
268  std::string error;
269  return registerVotes(nodeid, response, error);
270  }
271 
272  bool addToReconcile(const ProofRef &proof) {
273  fixture->m_processor->addProofToReconcile(proof);
274  return true;
275  }
276 
277  std::vector<Vote> buildVotesForItems(uint32_t error,
278  std::vector<ProofRef> &&items) {
279  size_t numItems = items.size();
280 
281  std::vector<Vote> votes;
282  votes.reserve(numItems);
283 
284  // Votes are sorted by high score first
285  std::sort(items.begin(), items.end(), ProofComparator());
286  for (auto &item : items) {
287  votes.emplace_back(error, item->getId());
288  }
289 
290  return votes;
291  }
292 };
293 
294 } // namespace
295 
296 BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheTestingSetup)
297 
298 // FIXME A std::tuple can be used instead of boost::mpl::list after boost 1.67
299 using VoteItemProviders = boost::mpl::list<BlockProvider, ProofProvider>;
300 
301 #define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence) \
302  vr.registerVote(NO_NODE, vote); \
303  BOOST_CHECK_EQUAL(vr.isAccepted(), state); \
304  BOOST_CHECK_EQUAL(vr.hasFinalized(), finalized); \
305  BOOST_CHECK_EQUAL(vr.getConfidence(), confidence);
306 
307 BOOST_AUTO_TEST_CASE(vote_record) {
308  VoteRecord vraccepted(true);
309 
310  // Check initial state.
311  BOOST_CHECK_EQUAL(vraccepted.isAccepted(), true);
312  BOOST_CHECK_EQUAL(vraccepted.hasFinalized(), false);
313  BOOST_CHECK_EQUAL(vraccepted.getConfidence(), 0);
314 
315  VoteRecord vr(false);
316 
317  // Check initial state.
318  BOOST_CHECK_EQUAL(vr.isAccepted(), false);
319  BOOST_CHECK_EQUAL(vr.hasFinalized(), false);
321 
322  // We need to register 6 positive votes before we start counting.
323  for (int i = 0; i < 6; i++) {
324  REGISTER_VOTE_AND_CHECK(vr, 0, false, false, 0);
325  }
326 
327  // Next vote will flip state, and confidence will increase as long as we
328  // vote yes.
329  REGISTER_VOTE_AND_CHECK(vr, 0, true, false, 0);
330 
331  // A single neutral vote do not change anything.
332  REGISTER_VOTE_AND_CHECK(vr, -1, true, false, 1);
333  for (int i = 2; i < 8; i++) {
334  REGISTER_VOTE_AND_CHECK(vr, 0, true, false, i);
335  }
336 
337  // Two neutral votes will stall progress.
338  REGISTER_VOTE_AND_CHECK(vr, -1, true, false, 7);
339  REGISTER_VOTE_AND_CHECK(vr, -1, true, false, 7);
340  for (int i = 2; i < 8; i++) {
341  REGISTER_VOTE_AND_CHECK(vr, 0, true, false, 7);
342  }
343 
344  // Now confidence will increase as long as we vote yes.
345  for (int i = 8; i < AVALANCHE_FINALIZATION_SCORE; i++) {
346  REGISTER_VOTE_AND_CHECK(vr, 0, true, false, i);
347  }
348 
349  // The next vote will finalize the decision.
351 
352  // Now that we have two no votes, confidence stop increasing.
353  for (int i = 0; i < 5; i++) {
354  REGISTER_VOTE_AND_CHECK(vr, 1, true, true,
356  }
357 
358  // Next vote will flip state, and confidence will increase as long as we
359  // vote no.
360  REGISTER_VOTE_AND_CHECK(vr, 1, false, false, 0);
361 
362  // A single neutral vote do not change anything.
363  REGISTER_VOTE_AND_CHECK(vr, -1, false, false, 1);
364  for (int i = 2; i < 8; i++) {
365  REGISTER_VOTE_AND_CHECK(vr, 1, false, false, i);
366  }
367 
368  // Two neutral votes will stall progress.
369  REGISTER_VOTE_AND_CHECK(vr, -1, false, false, 7);
370  REGISTER_VOTE_AND_CHECK(vr, -1, false, false, 7);
371  for (int i = 2; i < 8; i++) {
372  REGISTER_VOTE_AND_CHECK(vr, 1, false, false, 7);
373  }
374 
375  // Now confidence will increase as long as we vote no.
376  for (int i = 8; i < AVALANCHE_FINALIZATION_SCORE; i++) {
377  REGISTER_VOTE_AND_CHECK(vr, 1, false, false, i);
378  }
379 
380  // The next vote will finalize the decision.
382 
383  // Check that inflight accounting work as expected.
384  VoteRecord vrinflight(false);
385  for (int i = 0; i < 2 * AVALANCHE_MAX_INFLIGHT_POLL; i++) {
386  bool shouldPoll = vrinflight.shouldPoll();
388  BOOST_CHECK_EQUAL(vrinflight.registerPoll(), shouldPoll);
389  }
390 
391  // Clear various number of inflight requests and check everything behaves as
392  // expected.
393  for (int i = 1; i < AVALANCHE_MAX_INFLIGHT_POLL; i++) {
394  vrinflight.clearInflightRequest(i);
395  BOOST_CHECK(vrinflight.shouldPoll());
396 
397  for (int j = 1; j < i; j++) {
398  BOOST_CHECK(vrinflight.registerPoll());
399  BOOST_CHECK(vrinflight.shouldPoll());
400  }
401 
402  BOOST_CHECK(vrinflight.registerPoll());
403  BOOST_CHECK(!vrinflight.shouldPoll());
404  }
405 }
406 
407 BOOST_AUTO_TEST_CASE(block_update) {
408  CBlockIndex index;
409  CBlockIndex *pindex = &index;
410 
411  std::set<VoteStatus> status{
416  };
417 
418  for (auto s : status) {
419  BlockUpdate abu(pindex, s);
420  // The use of BOOST_CHECK instead of BOOST_CHECK_EQUAL prevents from
421  // having to define operator<<() for each argument type.
422  BOOST_CHECK(abu.getVoteItem() == pindex);
423  BOOST_CHECK(abu.getStatus() == s);
424  }
425 }
426 
427 BOOST_AUTO_TEST_CASE(block_reconcile_twice) {
428  CBlock block = CreateAndProcessBlock({}, CScript());
429  const BlockHash blockHash = block.GetHash();
430  CBlockIndex *pindex;
431  {
432  LOCK(cs_main);
433  pindex = LookupBlockIndex(blockHash);
434  }
435 
436  // Adding the block twice does nothing.
437  BOOST_CHECK(m_processor->addBlockToReconcile(pindex));
438  BOOST_CHECK(!m_processor->addBlockToReconcile(pindex));
439  BOOST_CHECK(m_processor->isAccepted(pindex));
440 }
441 
442 namespace {
443 Response next(Response &r) {
444  auto copy = r;
445  r = {r.getRound() + 1, r.getCooldown(), r.GetVotes()};
446  return copy;
447 }
448 } // namespace
449 
451  P provider(this);
452  auto &updates = provider.updates;
453  const uint32_t invType = provider.invType;
454 
455  const auto item = provider.buildVoteItem();
456  const auto itemid = provider.getVoteItemId(item);
457 
458  // Create nodes that supports avalanche.
459  auto avanodes = ConnectNodes();
460 
461  // Querying for random item returns false.
462  BOOST_CHECK(!m_processor->isAccepted(item));
463 
464  // Add a new item. Check it is added to the polls.
465  BOOST_CHECK(provider.addToReconcile(item));
466  auto invs = getInvsForNextPoll();
467  BOOST_CHECK_EQUAL(invs.size(), 1);
468  BOOST_CHECK_EQUAL(invs[0].type, invType);
469  BOOST_CHECK(invs[0].hash == itemid);
470 
471  BOOST_CHECK(m_processor->isAccepted(item));
472 
473  int nextNodeIndex = 0;
474  auto registerNewVote = [&](const Response &resp) {
475  runEventLoop();
476  auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
477  BOOST_CHECK(provider.registerVotes(nodeid, resp));
478  };
479 
480  // Let's vote for this item a few times.
481  Response resp{0, 0, {Vote(0, itemid)}};
482  for (int i = 0; i < 6; i++) {
483  registerNewVote(next(resp));
484  BOOST_CHECK(m_processor->isAccepted(item));
485  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), 0);
486  BOOST_CHECK_EQUAL(updates.size(), 0);
487  }
488 
489  // A single neutral vote do not change anything.
490  resp = {getRound(), 0, {Vote(-1, itemid)}};
491  registerNewVote(next(resp));
492  BOOST_CHECK(m_processor->isAccepted(item));
493  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), 0);
494  BOOST_CHECK_EQUAL(updates.size(), 0);
495 
496  resp = {getRound(), 0, {Vote(0, itemid)}};
497  for (int i = 1; i < 7; i++) {
498  registerNewVote(next(resp));
499  BOOST_CHECK(m_processor->isAccepted(item));
500  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), i);
501  BOOST_CHECK_EQUAL(updates.size(), 0);
502  }
503 
504  // Two neutral votes will stall progress.
505  resp = {getRound(), 0, {Vote(-1, itemid)}};
506  registerNewVote(next(resp));
507  BOOST_CHECK(m_processor->isAccepted(item));
508  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), 6);
509  BOOST_CHECK_EQUAL(updates.size(), 0);
510  registerNewVote(next(resp));
511  BOOST_CHECK(m_processor->isAccepted(item));
512  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), 6);
513  BOOST_CHECK_EQUAL(updates.size(), 0);
514 
515  resp = {getRound(), 0, {Vote(0, itemid)}};
516  for (int i = 2; i < 8; i++) {
517  registerNewVote(next(resp));
518  BOOST_CHECK(m_processor->isAccepted(item));
519  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), 6);
520  BOOST_CHECK_EQUAL(updates.size(), 0);
521  }
522 
523  // We vote for it numerous times to finalize it.
524  for (int i = 7; i < AVALANCHE_FINALIZATION_SCORE; i++) {
525  registerNewVote(next(resp));
526  BOOST_CHECK(m_processor->isAccepted(item));
527  BOOST_CHECK_EQUAL(m_processor->getConfidence(item), i);
528  BOOST_CHECK_EQUAL(updates.size(), 0);
529  }
530 
531  // As long as it is not finalized, we poll.
532  invs = getInvsForNextPoll();
533  BOOST_CHECK_EQUAL(invs.size(), 1);
534  BOOST_CHECK_EQUAL(invs[0].type, invType);
535  BOOST_CHECK(invs[0].hash == itemid);
536 
537  // Now finalize the decision.
538  registerNewVote(next(resp));
539  BOOST_CHECK_EQUAL(updates.size(), 1);
540  BOOST_CHECK(updates[0].getVoteItem() == item);
541  BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
542  updates.clear();
543 
544  // Once the decision is finalized, there is no poll for it.
545  invs = getInvsForNextPoll();
546  BOOST_CHECK_EQUAL(invs.size(), 0);
547 
548  // Now let's undo this and finalize rejection.
549  BOOST_CHECK(provider.addToReconcile(item));
550  invs = getInvsForNextPoll();
551  BOOST_CHECK_EQUAL(invs.size(), 1);
552  BOOST_CHECK_EQUAL(invs[0].type, invType);
553  BOOST_CHECK(invs[0].hash == itemid);
554 
555  resp = {getRound(), 0, {Vote(1, itemid)}};
556  for (int i = 0; i < 6; i++) {
557  registerNewVote(next(resp));
558  BOOST_CHECK(m_processor->isAccepted(item));
559  BOOST_CHECK_EQUAL(updates.size(), 0);
560  }
561 
562  // Now the state will flip.
563  registerNewVote(next(resp));
564  BOOST_CHECK(!m_processor->isAccepted(item));
565  BOOST_CHECK_EQUAL(updates.size(), 1);
566  BOOST_CHECK(updates[0].getVoteItem() == item);
567  BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
568  updates.clear();
569 
570  // Now it is rejected, but we can vote for it numerous times.
571  for (int i = 1; i < AVALANCHE_FINALIZATION_SCORE; i++) {
572  registerNewVote(next(resp));
573  BOOST_CHECK(!m_processor->isAccepted(item));
574  BOOST_CHECK_EQUAL(updates.size(), 0);
575  }
576 
577  // As long as it is not finalized, we poll.
578  invs = getInvsForNextPoll();
579  BOOST_CHECK_EQUAL(invs.size(), 1);
580  BOOST_CHECK_EQUAL(invs[0].type, invType);
581  BOOST_CHECK(invs[0].hash == itemid);
582 
583  // Now finalize the decision.
584  registerNewVote(next(resp));
585  BOOST_CHECK(!m_processor->isAccepted(item));
586  BOOST_CHECK_EQUAL(updates.size(), 1);
587  BOOST_CHECK(updates[0].getVoteItem() == item);
588  BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
589  updates.clear();
590 
591  // Once the decision is finalized, there is no poll for it.
592  invs = getInvsForNextPoll();
593  BOOST_CHECK_EQUAL(invs.size(), 0);
594 }
595 
597  P provider(this);
598  auto &updates = provider.updates;
599  const uint32_t invType = provider.invType;
600 
601  auto itemA = provider.buildVoteItem();
602  auto itemidA = provider.getVoteItemId(itemA);
603 
604  auto itemB = provider.buildVoteItem();
605  auto itemidB = provider.getVoteItemId(itemB);
606 
607  // Create several nodes that support avalanche.
608  auto avanodes = ConnectNodes();
609 
610  // Querying for random item returns false.
611  BOOST_CHECK(!m_processor->isAccepted(itemA));
612  BOOST_CHECK(!m_processor->isAccepted(itemB));
613 
614  // Start voting on item A.
615  BOOST_CHECK(provider.addToReconcile(itemA));
616  auto invs = getInvsForNextPoll();
617  BOOST_CHECK_EQUAL(invs.size(), 1);
618  BOOST_CHECK_EQUAL(invs[0].type, invType);
619  BOOST_CHECK(invs[0].hash == itemidA);
620 
621  uint64_t round = getRound();
622  runEventLoop();
623  BOOST_CHECK(provider.registerVotes(avanodes[0]->GetId(),
624  {round, 0, {Vote(0, itemidA)}}));
625  BOOST_CHECK_EQUAL(updates.size(), 0);
626 
627  // Start voting on item B after one vote.
628  std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
629  Response resp{round + 1, 0, votes};
630  BOOST_CHECK(provider.addToReconcile(itemB));
631  invs = getInvsForNextPoll();
632  BOOST_CHECK_EQUAL(invs.size(), 2);
633 
634  // Ensure the inv ordering is as expected
635  for (size_t i = 0; i < invs.size(); i++) {
636  BOOST_CHECK_EQUAL(invs[i].type, invType);
637  BOOST_CHECK(invs[i].hash == votes[i].GetHash());
638  }
639 
640  // Let's vote for these items a few times.
641  for (int i = 0; i < 4; i++) {
642  NodeId nodeid = getSuitableNodeToQuery();
643  runEventLoop();
644  BOOST_CHECK(provider.registerVotes(nodeid, next(resp)));
645  BOOST_CHECK_EQUAL(updates.size(), 0);
646  }
647 
648  // Now it is accepted, but we can vote for it numerous times.
649  for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) {
650  NodeId nodeid = getSuitableNodeToQuery();
651  runEventLoop();
652  BOOST_CHECK(provider.registerVotes(nodeid, next(resp)));
653  BOOST_CHECK_EQUAL(updates.size(), 0);
654  }
655 
656  // Running two iterration of the event loop so that vote gets triggered on A
657  // and B.
658  NodeId firstNodeid = getSuitableNodeToQuery();
659  runEventLoop();
660  NodeId secondNodeid = getSuitableNodeToQuery();
661  runEventLoop();
662 
663  BOOST_CHECK(firstNodeid != secondNodeid);
664 
665  // Next vote will finalize item A.
666  BOOST_CHECK(provider.registerVotes(firstNodeid, next(resp)));
667  BOOST_CHECK_EQUAL(updates.size(), 1);
668  BOOST_CHECK(updates[0].getVoteItem() == itemA);
669  BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
670  updates = {};
671 
672  // We do not vote on A anymore.
673  invs = getInvsForNextPoll();
674  BOOST_CHECK_EQUAL(invs.size(), 1);
675  BOOST_CHECK_EQUAL(invs[0].type, invType);
676  BOOST_CHECK(invs[0].hash == itemidB);
677 
678  // Next vote will finalize item B.
679  BOOST_CHECK(provider.registerVotes(secondNodeid, resp));
680  BOOST_CHECK_EQUAL(updates.size(), 1);
681  BOOST_CHECK(updates[0].getVoteItem() == itemB);
682  BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
683  updates = {};
684 
685  // There is nothing left to vote on.
686  invs = getInvsForNextPoll();
687  BOOST_CHECK_EQUAL(invs.size(), 0);
688 }
689 
691  P provider(this);
692  auto &updates = provider.updates;
693  const uint32_t invType = provider.invType;
694 
695  const auto item = provider.buildVoteItem();
696  const auto itemid = provider.getVoteItemId(item);
697 
698  // There is no node to query.
699  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE);
700 
701  // Create a node that supports avalanche and one that doesn't.
702  ConnectNode(NODE_NONE);
703  auto avanode = ConnectNode(NODE_AVALANCHE);
704  NodeId avanodeid = avanode->GetId();
705  BOOST_CHECK(addNode(avanodeid));
706 
707  // It returns the avalanche peer.
708  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
709 
710  // Register an item and check it is added to the list of elements to poll.
711  BOOST_CHECK(provider.addToReconcile(item));
712  auto invs = getInvsForNextPoll();
713  BOOST_CHECK_EQUAL(invs.size(), 1);
714  BOOST_CHECK_EQUAL(invs[0].type, invType);
715  BOOST_CHECK(invs[0].hash == itemid);
716 
717  // Trigger a poll on avanode.
718  uint64_t round = getRound();
719  runEventLoop();
720 
721  // There is no more suitable peer available, so return nothing.
722  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE);
723 
724  // Respond to the request.
725  Response resp = {round, 0, {Vote(0, itemid)}};
726  BOOST_CHECK(provider.registerVotes(avanodeid, resp));
727  BOOST_CHECK_EQUAL(updates.size(), 0);
728 
729  // Now that avanode fullfilled his request, it is added back to the list of
730  // queriable nodes.
731  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
732 
733  auto checkRegisterVotesError = [&](NodeId nodeid,
735  const std::string &expectedError) {
736  std::string error;
737  BOOST_CHECK(!provider.registerVotes(nodeid, response, error));
738  BOOST_CHECK_EQUAL(error, expectedError);
739  BOOST_CHECK_EQUAL(updates.size(), 0);
740  };
741 
742  // Sending a response when not polled fails.
743  checkRegisterVotesError(avanodeid, next(resp), "unexpected-ava-response");
744 
745  // Trigger a poll on avanode.
746  round = getRound();
747  runEventLoop();
748  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), NO_NODE);
749 
750  // Sending responses that do not match the request also fails.
751  // 1. Too many results.
752  resp = {round, 0, {Vote(0, itemid), Vote(0, itemid)}};
753  runEventLoop();
754  checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size");
755  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
756 
757  // 2. Not enough results.
758  resp = {getRound(), 0, {}};
759  runEventLoop();
760  checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-size");
761  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
762 
763  // 3. Do not match the poll.
764  resp = {getRound(), 0, {Vote()}};
765  runEventLoop();
766  checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-content");
767  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
768 
769  // 4. Invalid round count. Request is not discarded.
770  uint64_t queryRound = getRound();
771  runEventLoop();
772 
773  resp = {queryRound + 1, 0, {Vote()}};
774  checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response");
775 
776  resp = {queryRound - 1, 0, {Vote()}};
777  checkRegisterVotesError(avanodeid, resp, "unexpected-ava-response");
778 
779  // 5. Making request for invalid nodes do not work. Request is not
780  // discarded.
781  resp = {queryRound, 0, {Vote(0, itemid)}};
782  checkRegisterVotesError(avanodeid + 1234, resp, "unexpected-ava-response");
783 
784  // Proper response gets processed and avanode is available again.
785  resp = {queryRound, 0, {Vote(0, itemid)}};
786  BOOST_CHECK(provider.registerVotes(avanodeid, resp));
787  BOOST_CHECK_EQUAL(updates.size(), 0);
788  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
789 
790  // Out of order response are rejected.
791  const auto item2 = provider.buildVoteItem();
792  BOOST_CHECK(provider.addToReconcile(item2));
793 
794  std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
795  resp = {getRound(), 0, {votes[1], votes[0]}};
796  runEventLoop();
797  checkRegisterVotesError(avanodeid, resp, "invalid-ava-response-content");
798  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
799 
800  // But they are accepted in order.
801  resp = {getRound(), 0, votes};
802  runEventLoop();
803  BOOST_CHECK(provider.registerVotes(avanodeid, resp));
804  BOOST_CHECK_EQUAL(updates.size(), 0);
805  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), avanodeid);
806 }
807 
808 BOOST_AUTO_TEST_CASE(dont_poll_invalid_block) {
809  std::vector<BlockUpdate> updates;
810 
811  CBlock blockA = CreateAndProcessBlock({}, CScript());
812  CBlock blockB = CreateAndProcessBlock({}, CScript());
813  const BlockHash blockHashA = blockA.GetHash();
814  const BlockHash blockHashB = blockB.GetHash();
815  const CBlockIndex *pindexA;
816  CBlockIndex *pindexB;
817  {
818  LOCK(cs_main);
819  pindexA = LookupBlockIndex(blockHashA);
820  pindexB = LookupBlockIndex(blockHashB);
821  }
822 
823  auto avanodes = ConnectNodes();
824 
825  // Register the blocks and check they are added to the list of elements to
826  // poll.
827  BOOST_CHECK(m_processor->addBlockToReconcile(pindexA));
828  BOOST_CHECK(m_processor->addBlockToReconcile(pindexB));
829  auto invs = getInvsForNextPoll();
830  BOOST_CHECK_EQUAL(invs.size(), 2);
831  BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK);
832  BOOST_CHECK(invs[0].hash == blockHashB);
833  BOOST_CHECK_EQUAL(invs[1].type, MSG_BLOCK);
834  BOOST_CHECK(invs[1].hash == blockHashA);
835 
836  // When a block is marked invalid, stop polling.
837  pindexB->nStatus = pindexB->nStatus.withFailed();
838  Response resp{getRound(), 0, {Vote(0, blockHashA)}};
839  runEventLoop();
840  BOOST_CHECK(registerVotes(avanodes[0]->GetId(), resp, updates));
841  BOOST_CHECK_EQUAL(updates.size(), 0);
842 }
843 
844 BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
846  P provider(this);
847 
848  const auto item = provider.buildVoteItem();
849  const auto itemid = provider.getVoteItemId(item);
850 
851  // Add the item
852  BOOST_CHECK(provider.addToReconcile(item));
853 
854  // Create a node that supports avalanche.
855  auto avanode = ConnectNode(NODE_AVALANCHE);
856  NodeId avanodeid = avanode->GetId();
857  BOOST_CHECK(addNode(avanodeid));
858 
859  // Expire requests after some time.
860  auto queryTimeDuration = std::chrono::milliseconds(10);
861  m_processor->setQueryTimeoutDuration(queryTimeDuration);
862  for (int i = 0; i < 10; i++) {
863  Response resp = {getRound(), 0, {Vote(0, itemid)}};
864 
865  auto start = std::chrono::steady_clock::now();
866  runEventLoop();
867  // We cannot guarantee that we'll wait for just 1ms, so we have to bail
868  // if we aren't within the proper time range.
869  std::this_thread::sleep_for(std::chrono::milliseconds(1));
870  runEventLoop();
871 
872  bool ret = provider.registerVotes(avanodeid, next(resp));
873  if (std::chrono::steady_clock::now() > start + queryTimeDuration) {
874  // We waited for too long, bail. Because we can't know for sure when
875  // previous steps ran, ret is not deterministic and we do not check
876  // it.
877  i--;
878  continue;
879  }
880 
881  // We are within time bounds, so the vote should have worked.
882  BOOST_CHECK(ret);
883 
884  // Now try again but wait for expiration.
885  runEventLoop();
886  std::this_thread::sleep_for(queryTimeDuration);
887  runEventLoop();
888  BOOST_CHECK(!provider.registerVotes(avanodeid, next(resp)));
889  }
890 }
891 
893  P provider(this);
894  const uint32_t invType = provider.invType;
895 
896  // Create enough nodes so that we run into the inflight request limit.
897  auto proof = GetProof();
898  BOOST_CHECK(m_processor->withPeerManager(
899  [&](avalanche::PeerManager &pm) { return pm.registerProof(proof); }));
900 
901  std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
902  for (auto &n : nodes) {
903  n = ConnectNode(NODE_AVALANCHE);
904  BOOST_CHECK(addNode(n->GetId(), proof->getId()));
905  }
906 
907  // Add an item to poll
908  const auto item = provider.buildVoteItem();
909  const auto itemid = provider.getVoteItemId(item);
910  BOOST_CHECK(provider.addToReconcile(item));
911 
912  // Ensure there are enough requests in flight.
913  std::map<NodeId, uint64_t> node_round_map;
914  for (int i = 0; i < AVALANCHE_MAX_INFLIGHT_POLL; i++) {
915  NodeId nodeid = getSuitableNodeToQuery();
916  BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
917  node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
918  auto invs = getInvsForNextPoll();
919  BOOST_CHECK_EQUAL(invs.size(), 1);
920  BOOST_CHECK_EQUAL(invs[0].type, invType);
921  BOOST_CHECK(invs[0].hash == itemid);
922  runEventLoop();
923  }
924 
925  // Now that we have enough in flight requests, we shouldn't poll.
926  auto suitablenodeid = getSuitableNodeToQuery();
927  BOOST_CHECK(suitablenodeid != NO_NODE);
928  auto invs = getInvsForNextPoll();
929  BOOST_CHECK_EQUAL(invs.size(), 0);
930  runEventLoop();
931  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), suitablenodeid);
932 
933  // Send one response, now we can poll again.
934  auto it = node_round_map.begin();
935  Response resp = {it->second, 0, {Vote(0, itemid)}};
936  BOOST_CHECK(provider.registerVotes(it->first, resp));
937  node_round_map.erase(it);
938 
939  invs = getInvsForNextPoll();
940  BOOST_CHECK_EQUAL(invs.size(), 1);
941  BOOST_CHECK_EQUAL(invs[0].type, invType);
942  BOOST_CHECK(invs[0].hash == itemid);
943 }
944 
945 BOOST_AUTO_TEST_CASE(quorum_diversity) {
946  std::vector<BlockUpdate> updates;
947 
948  CBlock block = CreateAndProcessBlock({}, CScript());
949  const BlockHash blockHash = block.GetHash();
950  const CBlockIndex *pindex;
951  {
952  LOCK(cs_main);
953  pindex = LookupBlockIndex(blockHash);
954  }
955 
956  // Create nodes that supports avalanche.
957  auto avanodes = ConnectNodes();
958 
959  // Querying for random block returns false.
960  BOOST_CHECK(!m_processor->isAccepted(pindex));
961 
962  // Add a new block. Check it is added to the polls.
963  BOOST_CHECK(m_processor->addBlockToReconcile(pindex));
964 
965  // Do one valid round of voting.
966  uint64_t round = getRound();
967  Response resp{round, 0, {Vote(0, blockHash)}};
968 
969  // Check that all nodes can vote.
970  for (size_t i = 0; i < avanodes.size(); i++) {
971  runEventLoop();
972  BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
973  }
974 
975  // Generate a query for every single node.
976  const NodeId firstNodeId = getSuitableNodeToQuery();
977  std::map<NodeId, uint64_t> node_round_map;
978  round = getRound();
979  for (size_t i = 0; i < avanodes.size(); i++) {
980  NodeId nodeid = getSuitableNodeToQuery();
981  BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
982  node_round_map[nodeid] = getRound();
983  runEventLoop();
984  }
985 
986  // Now only the first node can vote. All others would be duplicate in the
987  // quorum.
988  auto confidence = m_processor->getConfidence(pindex);
989  BOOST_REQUIRE(confidence > 0);
990 
991  for (auto &[nodeid, r] : node_round_map) {
992  if (nodeid == firstNodeId) {
993  // Node 0 is the only one which can vote at this stage.
994  round = r;
995  continue;
996  }
997 
998  BOOST_CHECK(
999  registerVotes(nodeid, {r, 0, {Vote(0, blockHash)}}, updates));
1000  BOOST_CHECK_EQUAL(m_processor->getConfidence(pindex), confidence);
1001  }
1002 
1003  BOOST_CHECK(
1004  registerVotes(firstNodeId, {round, 0, {Vote(0, blockHash)}}, updates));
1005  BOOST_CHECK_EQUAL(m_processor->getConfidence(pindex), confidence + 1);
1006 }
1007 
1009  CScheduler s;
1010 
1011  CBlock block = CreateAndProcessBlock({}, CScript());
1012  const BlockHash blockHash = block.GetHash();
1013  const CBlockIndex *pindex;
1014  {
1015  LOCK(cs_main);
1016  pindex = LookupBlockIndex(blockHash);
1017  }
1018 
1019  // Starting the event loop.
1020  BOOST_CHECK(m_processor->startEventLoop(s));
1021 
1022  // There is one task planned in the next hour (our event loop).
1023  std::chrono::system_clock::time_point start, stop;
1024  BOOST_CHECK_EQUAL(s.getQueueInfo(start, stop), 1);
1025 
1026  // Starting twice doesn't start it twice.
1027  BOOST_CHECK(!m_processor->startEventLoop(s));
1028 
1029  // Start the scheduler thread.
1030  std::thread schedulerThread(std::bind(&CScheduler::serviceQueue, &s));
1031 
1032  // Create a node that supports avalanche.
1033  auto avanode = ConnectNode(NODE_AVALANCHE);
1034  NodeId nodeid = avanode->GetId();
1035  BOOST_CHECK(addNode(nodeid));
1036 
1037  // There is no query in flight at the moment.
1038  BOOST_CHECK_EQUAL(getSuitableNodeToQuery(), nodeid);
1039 
1040  // Add a new block. Check it is added to the polls.
1041  uint64_t queryRound = getRound();
1042  BOOST_CHECK(m_processor->addBlockToReconcile(pindex));
1043 
1044  for (int i = 0; i < 60 * 1000; i++) {
1045  // Technically, this is a race condition, but this should do just fine
1046  // as we wait up to 1 minute for an event that should take 10ms.
1047  UninterruptibleSleep(std::chrono::milliseconds(1));
1048  if (getRound() != queryRound) {
1049  break;
1050  }
1051  }
1052 
1053  // Check that we effectively got a request and not timed out.
1054  BOOST_CHECK(getRound() > queryRound);
1055 
1056  // Respond and check the cooldown time is respected.
1057  uint64_t responseRound = getRound();
1058  auto queryTime =
1059  std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
1060 
1061  std::vector<BlockUpdate> updates;
1062  registerVotes(nodeid, {queryRound, 100, {Vote(0, blockHash)}}, updates);
1063  for (int i = 0; i < 10000; i++) {
1064  // We make sure that we do not get a request before queryTime.
1065  UninterruptibleSleep(std::chrono::milliseconds(1));
1066  if (getRound() != responseRound) {
1067  BOOST_CHECK(std::chrono::steady_clock::now() > queryTime);
1068  break;
1069  }
1070  }
1071 
1072  // But we eventually get one.
1073  BOOST_CHECK(getRound() > responseRound);
1074 
1075  // Stop event loop.
1076  BOOST_CHECK(m_processor->stopEventLoop());
1077 
1078  // We don't have any task scheduled anymore.
1079  BOOST_CHECK_EQUAL(s.getQueueInfo(start, stop), 0);
1080 
1081  // Can't stop the event loop twice.
1082  BOOST_CHECK(!m_processor->stopEventLoop());
1083 
1084  // Wait for the scheduler to stop.
1085  s.StopWhenDrained();
1086  schedulerThread.join();
1087 }
1088 
1090  CScheduler s;
1091  std::chrono::system_clock::time_point start, stop;
1092 
1093  std::thread schedulerThread;
1094  BOOST_CHECK(m_processor->startEventLoop(s));
1095  BOOST_CHECK_EQUAL(s.getQueueInfo(start, stop), 1);
1096 
1097  // Start the service thread after the queue size check to prevent a race
1098  // condition where the thread may be processing the event loop task during
1099  // the check.
1100  schedulerThread = std::thread(std::bind(&CScheduler::serviceQueue, &s));
1101 
1102  // Destroy the processor.
1103  m_processor.reset();
1104 
1105  // Now that avalanche is destroyed, there is no more scheduled tasks.
1106  BOOST_CHECK_EQUAL(s.getQueueInfo(start, stop), 0);
1107 
1108  // Wait for the scheduler to stop.
1109  s.StopWhenDrained();
1110  schedulerThread.join();
1111 }
1112 
1113 BOOST_AUTO_TEST_CASE(add_proof_to_reconcile) {
1114  uint32_t score = MIN_VALID_PROOF_SCORE;
1115 
1116  auto addProofToReconcile = [&](uint32_t proofScore) {
1117  auto proof = buildRandomProof(proofScore);
1118  m_processor->addProofToReconcile(proof);
1119  return proof;
1120  };
1121 
1122  for (size_t i = 0; i < AVALANCHE_MAX_ELEMENT_POLL; i++) {
1123  auto proof = addProofToReconcile(++score);
1124 
1125  auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1126  BOOST_CHECK_EQUAL(invs.size(), i + 1);
1127  BOOST_CHECK(invs.front().IsMsgProof());
1128  BOOST_CHECK_EQUAL(invs.front().hash, proof->getId());
1129  }
1130 
1131  // From here a new proof is only polled if its score is in the top
1132  // AVALANCHE_MAX_ELEMENT_POLL
1133  ProofId lastProofId;
1134  for (size_t i = 0; i < 10; i++) {
1135  auto proof = addProofToReconcile(++score);
1136 
1137  auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1139  BOOST_CHECK(invs.front().IsMsgProof());
1140  BOOST_CHECK_EQUAL(invs.front().hash, proof->getId());
1141 
1142  lastProofId = proof->getId();
1143  }
1144 
1145  for (size_t i = 0; i < 10; i++) {
1146  auto proof = addProofToReconcile(--score);
1147 
1148  auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1150  BOOST_CHECK(invs.front().IsMsgProof());
1151  BOOST_CHECK_EQUAL(invs.front().hash, lastProofId);
1152  }
1153 
1154  // The score is not high enough to get polled
1155  auto proof = addProofToReconcile(--score);
1156  auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1157  for (auto &inv : invs) {
1158  BOOST_CHECK_NE(inv.hash, proof->getId());
1159  }
1160 }
1161 
1162 BOOST_AUTO_TEST_CASE(proof_record) {
1163  BOOST_CHECK(!m_processor->isAccepted(nullptr));
1164  BOOST_CHECK_EQUAL(m_processor->getConfidence(nullptr), -1);
1165 
1166  auto proofA = GetProof();
1167  auto proofB = GetProof();
1168 
1169  BOOST_CHECK(!m_processor->isAccepted(proofA));
1170  BOOST_CHECK(!m_processor->isAccepted(proofB));
1171  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofA), -1);
1172  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofB), -1);
1173 
1174  m_processor->addProofToReconcile(proofA);
1175  BOOST_CHECK(!m_processor->isAccepted(proofA));
1176  BOOST_CHECK(!m_processor->isAccepted(proofB));
1177  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofA), 0);
1178  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofB), -1);
1179 
1180  m_processor->withPeerManager([&](avalanche::PeerManager &pm) {
1181  BOOST_CHECK(pm.registerProof(proofB));
1182  });
1183  m_processor->addProofToReconcile(proofB);
1184  BOOST_CHECK(!m_processor->isAccepted(proofA));
1185  BOOST_CHECK(m_processor->isAccepted(proofB));
1186  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofA), 0);
1187  BOOST_CHECK_EQUAL(m_processor->getConfidence(proofB), 0);
1188 }
1189 
avalanche::VoteStatus::Rejected
@ Rejected
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:514
CScheduler
Simple class for background tasks that should be run periodically or once "after a while".
Definition: scheduler.h:35
avalanche::ProofBuilder
Definition: proofbuilder.h:17
avalanche::VoteItemUpdate::getStatus
const VoteStatus & getStatus() const
Definition: processor.h:72
avalanche::MIN_VALID_PROOF_SCORE
constexpr uint32_t MIN_VALID_PROOF_SCORE
Definition: util.h:16
avalanche::VoteRecord
Vote history.
Definition: voterecord.h:29
CConnman::CConnman
CConnman(const Config &configIn, uint64_t seed0, uint64_t seed1, bool network_active=true)
Definition: net.cpp:2747
AVALANCHE_MAX_INFLIGHT_POLL
static constexpr int AVALANCHE_MAX_INFLIGHT_POLL
How many inflight requests can exist for one item.
Definition: voterecord.h:22
avalanche::Processor::MakeProcessor
static std::unique_ptr< Processor > MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, CConnman *connman, bilingual_str &error)
Definition: processor.cpp:147
NodeContext::args
ArgsManager * args
Definition: context.h:44
avalanche
Definition: avalanche.h:11
NodeContext::mempool
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:38
avalanche::Processor::getInvsForNextPoll
std::vector< CInv > getInvsForNextPoll(bool forPoll=true)
Definition: processor.cpp:537
avalanche::VoteItemUpdate
Definition: processor.h:64
avalanche::PeerManager::addNode
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
Definition: peermanager.cpp:17
bilingual_str
Bilingual messages:
Definition: translation.h:17
CNetAddr
Network address.
Definition: netaddress.h:117
avalanche::Processor::getSuitableNodeToQuery
NodeId getSuitableNodeToQuery()
Definition: processor.cpp:592
delegationbuilder.h
ConnectionType::OUTBOUND_FULL_RELAY
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
CNode
Information about a peer.
Definition: net.h:454
avalanche::VoteItemUpdate::getVoteItem
VoteItem getVoteItem()
Definition: processor.h:74
avalanche::Processor
Definition: processor.h:91
AVALANCHE_MAX_ELEMENT_POLL
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
Definition: processor.h:42
avalanche::ProofId
Definition: proofid.h:17
ServiceFlags
ServiceFlags
nServices flags.
Definition: protocol.h:314
CBlockIndex::nStatus
BlockStatus nStatus
Verification status of this block. See enum BlockStatus.
Definition: blockindex.h:76
NODE_NETWORK
@ NODE_NETWORK
Definition: protocol.h:321
CNode::nServices
std::atomic< ServiceFlags > nServices
Definition: net.h:463
avalanche::VoteRecord::registerPoll
bool registerPoll() const
Register that a request is being made regarding that item.
Definition: voterecord.cpp:92
BOOST_FIXTURE_TEST_SUITE
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
avalanche::buildRandomProof
ProofRef buildRandomProof(uint32_t score, const CKey &masterKey)
Definition: util.cpp:20
avalanche::VoteRecord::getConfidence
uint16_t getConfidence() const
Definition: voterecord.h:68
NodeContext::chain
std::unique_ptr< interfaces::Chain > chain
Definition: context.h:45
scheduler.h
CBlockIndex::GetBlockHash
BlockHash GetBlockHash() const
Definition: blockindex.h:133
CTransaction
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:194
proofbuilder.h
CNode::SetCommonVersion
void SetCommonVersion(int greatest_common_version)
Definition: net.h:825
CScheduler::serviceQueue
void serviceQueue()
Services the queue 'forever'.
Definition: scheduler.cpp:21
avalanche::Response::getRound
uint64_t getRound() const
Definition: protocol.h:43
Config
Definition: config.h:17
avalanche::VoteRecord::isAccepted
bool isAccepted() const
Vote accounting facilities.
Definition: voterecord.h:66
SyncWithValidationInterfaceQueue
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
Definition: validationinterface.cpp:162
CScheduler::getQueueInfo
size_t getQueueInfo(std::chrono::system_clock::time_point &first, std::chrono::system_clock::time_point &last) const
Returns number of tasks waiting to be serviced, and first and last task times.
Definition: scheduler.cpp:118
BlockStatus::withFailed
BlockStatus withFailed(bool hasFailed=true) const
Definition: blockstatus.h:67
GetRandInt
int GetRandInt(int nMax) noexcept
Definition: random.cpp:654
NODE_AVALANCHE
@ NODE_AVALANCHE
Definition: protocol.h:359
INVALID_SOCKET
#define INVALID_SOCKET
Definition: compat.h:55
CTransaction::GetId
const TxId GetId() const
Definition: transaction.h:244
cs_main
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:103
avalanche::VoteRecord::shouldPoll
bool shouldPoll() const
Return if this item is in condition to be polled at the moment.
Definition: voterecord.h:89
response
Response response
Definition: processor.cpp:321
avalanche::VoteRecord::clearInflightRequest
void clearInflightRequest(uint8_t count=1)
Clear count inflight requests.
Definition: voterecord.h:94
CTransaction::vout
const std::vector< CTxOut > vout
Definition: transaction.h:211
avalanche::Response
Definition: protocol.h:33
reverse_iterator.h
avalanche::VoteStatus::Finalized
@ Finalized
avalanche::PeerManager
Definition: peermanager.h:109
CNode::m_avalanche_state
std::unique_ptr< AvalancheState > m_avalanche_state
Definition: net.h:709
CNode::fSuccessfullyConnected
std::atomic_bool fSuccessfullyConnected
Definition: net.h:519
time.h
processor.h
REGISTER_VOTE_AND_CHECK
#define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence)
Definition: processor_tests.cpp:301
uint256
256-bit opaque blob.
Definition: uint256.h:127
avalanche::VoteRecord::hasFinalized
bool hasFinalized() const
Definition: voterecord.h:69
AVALANCHE_FINALIZATION_SCORE
static constexpr int AVALANCHE_FINALIZATION_SCORE
Finalization score.
Definition: voterecord.h:17
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:430
NO_NODE
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
Definition: nodeid.h:15
avalanche::ProofComparator
Compare proofs by score, then by id in case of equality.
Definition: proofcomparator.h:18
net_processing.h
voterecord.h
NodeContext::peerman
std::unique_ptr< PeerManager > peerman
Definition: context.h:39
BlockHash
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
NODE_NONE
@ NODE_NONE
Definition: protocol.h:317
avalanche::Processor::runEventLoop
void runEventLoop()
Definition: processor.cpp:659
avalanche::Vote
Definition: protocol.h:18
util.h
UninterruptibleSleep
void UninterruptibleSleep(const std::chrono::microseconds &n)
Definition: time.cpp:20
MSG_AVA_PROOF
@ MSG_AVA_PROOF
Definition: protocol.h:484
CBlock
Definition: block.h:55
m_node
NodeContext & m_node
Definition: chain.cpp:486
peermanager.h
stop
static RPCHelpMan stop()
Definition: server.cpp:203
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(vote_record)
Definition: processor_tests.cpp:307
CConnman
Definition: net.h:968
PeerManager::make
static std::unique_ptr< PeerManager > make(const CChainParams &chainparams, CConnman &connman, BanMan *banman, CScheduler &scheduler, ChainstateManager &chainman, CTxMemPool &pool, bool ignore_incoming_txs)
Definition: net_processing.cpp:1801
VoteItemProviders
boost::mpl::list< BlockProvider, ProofProvider > VoteItemProviders
Definition: processor_tests.cpp:299
CAddress
A CService with information about it as peer.
Definition: protocol.h:421
NodeContext::banman
std::unique_ptr< BanMan > banman
Definition: context.h:42
CBlockIndexWorkComparator
Definition: blockindexworkcomparator.h:10
CKey
An encapsulated secp256k1 private key.
Definition: key.h:28
CScheduler::StopWhenDrained
void StopWhenDrained()
Tell any threads running serviceQueue to stop when there is no work left to be done.
Definition: scheduler.h:86
translation.h
Config::GetChainParams
virtual const CChainParams & GetChainParams() const =0
LOCK
#define LOCK(cs)
Definition: sync.h:241
avalanche::Response::getCooldown
uint32_t getCooldown() const
Definition: protocol.h:44
GetDefaultPort
static uint16_t GetDefaultPort()
Definition: bitcoin.h:16
NodeContext::scheduler
std::unique_ptr< CScheduler > scheduler
Definition: context.h:52
avalanche::PeerManager::registerProof
bool registerProof(const ProofRef &proof, RegistrationMode mode=RegistrationMode::DEFAULT)
Definition: peermanager.cpp:167
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:508
LookupBlockIndex
CBlockIndex * LookupBlockIndex(const BlockHash &hash)
Definition: validation.cpp:150
interfaces::MakeChain
std::unique_ptr< Chain > MakeChain(NodeContext &node, const CChainParams &params)
Return implementation of Chain interface.
Definition: chain.cpp:492
config.h
NodeId
int64_t NodeId
Definition: nodeid.h:10
avalanche::Response::GetVotes
const std::vector< Vote > & GetVotes() const
Definition: protocol.h:45
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
avalanche::Processor::round
std::atomic< uint64_t > round
Keep track of peers and queries sent.
Definition: processor.h:108
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
avalanche::ProofRef
std::shared_ptr< const Proof > ProofRef
Definition: proof.h:163
avalanche::VoteStatus::Accepted
@ Accepted
CNode::nVersion
std::atomic< int > nVersion
Definition: net.h:491
NodeContext::connman
std::unique_ptr< CConnman > connman
Definition: context.h:37
avalanche::VoteStatus::Invalid
@ Invalid
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:23
CBlockHeader::GetHash
BlockHash GetHash() const
Definition: block.cpp:11
BOOST_AUTO_TEST_CASE_TEMPLATE
BOOST_AUTO_TEST_CASE_TEMPLATE(vote_item_register, P, VoteItemProviders)
Definition: processor_tests.cpp:450
GetConfig
const Config & GetConfig()
Definition: config.cpp:34
reverse_iterate
reverse_range< T > reverse_iterate(T &x)
Definition: reverse_iterator.h:25
MSG_BLOCK
@ MSG_BLOCK
Definition: protocol.h:478
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition: object.cpp:17
BOOST_AUTO_TEST_SUITE_END
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
BOOST_CHECK_EQUAL
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
PROTOCOL_VERSION
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11
NodeContext::chainman
ChainstateManager * chainman
Definition: context.h:41