rippled
NegativeUNL_test.cpp
1 //-----------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/consensus/RCLValidations.h>
21 #include <ripple/app/ledger/Ledger.h>
22 #include <ripple/app/misc/NegativeUNLVote.h>
23 #include <ripple/app/misc/ValidatorList.h>
24 #include <ripple/app/tx/apply.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/beast/unit_test.h>
27 #include <ripple/ledger/View.h>
28 #include <test/jtx.h>
29 
30 namespace ripple {
31 namespace test {
32 
33 /*
34  * This file implements the following negative UNL related tests:
35  * -- test filling and applying ttUNL_MODIFY Tx and ledger update
36  * -- test ttUNL_MODIFY Tx failure without featureNegativeUNL amendment
37  * -- test the NegativeUNLVote class. The test cases are split to multiple
38  * test classes to allow parallel execution.
39  * -- test the negativeUNLFilter function
40  *
41  * Other negative UNL related tests such as ValidatorList and RPC related ones
42  * are put in their existing unit test files.
43  */
44 
55 bool
58  size_t size,
59  bool hasToDisable,
60  bool hasToReEnable);
61 
71 bool
72 applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass);
73 
83 bool
86  hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq);
87 
95 countTx(std::shared_ptr<SHAMap> const& txSet);
96 
105 
114 STTx
115 createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey);
116 
117 class NegativeUNL_test : public beast::unit_test::suite
118 {
126  void
128  {
129  /*
130  * test cases:
131  *
132  * (1) the ledger after genesis
133  * -- cannot apply Disable Tx
134  * -- cannot apply ReEnable Tx
135  * -- nUNL empty
136  * -- no ToDisable
137  * -- no ToReEnable
138  *
139  * (2) a flag ledger
140  * -- apply an Disable Tx
141  * -- cannot apply the second Disable Tx
142  * -- cannot apply a ReEnable Tx
143  * -- nUNL empty
144  * -- has ToDisable with right nodeId
145  * -- no ToReEnable
146  * ++ extra test: first Disable Tx in ledger TxSet
147  *
148  * (3) ledgers before the next flag ledger
149  * -- nUNL empty
150  * -- has ToDisable with right nodeId
151  * -- no ToReEnable
152  *
153  * (4) next flag ledger
154  * -- nUNL size == 1, with right nodeId
155  * -- no ToDisable
156  * -- no ToReEnable
157  * -- cannot apply an Disable Tx with nodeId already in nUNL
158  * -- apply an Disable Tx with different nodeId
159  * -- cannot apply a ReEnable Tx with the same NodeId as Add
160  * -- cannot apply a ReEnable Tx with a NodeId not in nUNL
161  * -- apply a ReEnable Tx with a nodeId already in nUNL
162  * -- has ToDisable with right nodeId
163  * -- has ToReEnable with right nodeId
164  * -- nUNL size still 1, right nodeId
165  *
166  * (5) ledgers before the next flag ledger
167  * -- nUNL size == 1, right nodeId
168  * -- has ToDisable with right nodeId
169  * -- has ToReEnable with right nodeId
170  *
171  * (6) next flag ledger
172  * -- nUNL size == 1, different nodeId
173  * -- no ToDisable
174  * -- no ToReEnable
175  * -- apply an Disable Tx with different nodeId
176  * -- nUNL size still 1, right nodeId
177  * -- has ToDisable with right nodeId
178  * -- no ToReEnable
179  *
180  * (7) ledgers before the next flag ledger
181  * -- nUNL size still 1, right nodeId
182  * -- has ToDisable with right nodeId
183  * -- no ToReEnable
184  *
185  * (8) next flag ledger
186  * -- nUNL size == 2
187  * -- apply a ReEnable Tx
188  * -- cannot apply second ReEnable Tx, even with right nodeId
189  * -- cannot apply an Disable Tx with the same NodeId as Remove
190  * -- nUNL size == 2
191  * -- no ToDisable
192  * -- has ToReEnable with right nodeId
193  *
194  * (9) ledgers before the next flag ledger
195  * -- nUNL size == 2
196  * -- no ToDisable
197  * -- has ToReEnable with right nodeId
198  *
199  * (10) next flag ledger
200  * -- nUNL size == 1
201  * -- apply a ReEnable Tx
202  * -- nUNL size == 1
203  * -- no ToDisable
204  * -- has ToReEnable with right nodeId
205  *
206  * (11) ledgers before the next flag ledger
207  * -- nUNL size == 1
208  * -- no ToDisable
209  * -- has ToReEnable with right nodeId
210  *
211  * (12) next flag ledger
212  * -- nUNL size == 0
213  * -- no ToDisable
214  * -- no ToReEnable
215  *
216  * (13) ledgers before the next flag ledger
217  * -- nUNL size == 0
218  * -- no ToDisable
219  * -- no ToReEnable
220  *
221  * (14) next flag ledger
222  * -- nUNL size == 0
223  * -- no ToDisable
224  * -- no ToReEnable
225  */
226 
227  testcase("Create UNLModify Tx and apply to ledgers");
228 
231  // genesis ledger
232  auto l = std::make_shared<Ledger>(
234  env.app().config(),
236  env.app().getNodeFamily());
237  BEAST_EXPECT(l->rules().enabled(featureNegativeUNL));
238 
239  // Record the public keys and ledger sequences of expected negative UNL
240  // validators when we build the ledger history
242 
243  {
244  //(1) the ledger after genesis, not a flag ledger
245  l = std::make_shared<Ledger>(
246  *l, env.app().timeKeeper().closeTime());
247 
248  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
249  auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
250 
251  OpenView accum(&*l);
252  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
253  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
254  accum.apply(*l);
255  BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
256  }
257 
258  {
259  //(2) a flag ledger
260  // generate more ledgers
261  for (auto i = 0; i < 256 - 2; ++i)
262  {
263  l = std::make_shared<Ledger>(
264  *l, env.app().timeKeeper().closeTime());
265  }
266  BEAST_EXPECT(l->isFlagLedger());
267  l->updateNegativeUNL();
268 
269  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
270  auto txDisable_1 = createTx(true, l->seq(), publicKeys[1]);
271  auto txReEnable_2 = createTx(false, l->seq(), publicKeys[2]);
272 
273  // can apply 1 and only 1 ToDisable Tx,
274  // cannot apply ToReEnable Tx, since negative UNL is empty
275  OpenView accum(&*l);
276  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, true));
277  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_1, false));
278  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_2, false));
279  accum.apply(*l);
280  auto good_size = negUnlSizeTest(l, 0, true, false);
281  BEAST_EXPECT(good_size);
282  if (good_size)
283  {
284  BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
285  //++ first ToDisable Tx in ledger's TxSet
286  uint256 txID = txDisable_0.getTransactionID();
287  BEAST_EXPECT(l->txExists(txID));
288  }
289  }
290 
291  {
292  //(3) ledgers before the next flag ledger
293  for (auto i = 0; i < 256; ++i)
294  {
295  auto good_size = negUnlSizeTest(l, 0, true, false);
296  BEAST_EXPECT(good_size);
297  if (good_size)
298  BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
299  l = std::make_shared<Ledger>(
300  *l, env.app().timeKeeper().closeTime());
301  }
302  BEAST_EXPECT(l->isFlagLedger());
303  l->updateNegativeUNL();
304 
305  //(4) next flag ledger
306  // test if the ledger updated correctly
307  auto good_size = negUnlSizeTest(l, 1, false, false);
308  BEAST_EXPECT(good_size);
309  if (good_size)
310  {
311  BEAST_EXPECT(*(l->negativeUNL().begin()) == publicKeys[0]);
312  nUnlLedgerSeq.emplace(publicKeys[0], l->seq());
313  }
314 
315  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
316  auto txDisable_1 = createTx(true, l->seq(), publicKeys[1]);
317  auto txReEnable_0 = createTx(false, l->seq(), publicKeys[0]);
318  auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
319  auto txReEnable_2 = createTx(false, l->seq(), publicKeys[2]);
320 
321  OpenView accum(&*l);
322  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
323  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_1, true));
324  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
325  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_2, false));
326  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_0, true));
327  accum.apply(*l);
328  good_size = negUnlSizeTest(l, 1, true, true);
329  BEAST_EXPECT(good_size);
330  if (good_size)
331  {
332  BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
333  BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
334  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
335  // test sfFirstLedgerSequence
336  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
337  }
338  }
339 
340  {
341  //(5) ledgers before the next flag ledger
342  for (auto i = 0; i < 256; ++i)
343  {
344  auto good_size = negUnlSizeTest(l, 1, true, true);
345  BEAST_EXPECT(good_size);
346  if (good_size)
347  {
348  BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
349  BEAST_EXPECT(l->validatorToDisable() == publicKeys[1]);
350  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
351  }
352  l = std::make_shared<Ledger>(
353  *l, env.app().timeKeeper().closeTime());
354  }
355  BEAST_EXPECT(l->isFlagLedger());
356  l->updateNegativeUNL();
357 
358  //(6) next flag ledger
359  // test if the ledger updated correctly
360  auto good_size = negUnlSizeTest(l, 1, false, false);
361  BEAST_EXPECT(good_size);
362  if (good_size)
363  {
364  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
365  }
366 
367  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
368 
369  OpenView accum(&*l);
370  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, true));
371  accum.apply(*l);
372  good_size = negUnlSizeTest(l, 1, true, false);
373  BEAST_EXPECT(good_size);
374  if (good_size)
375  {
376  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
377  BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
378  nUnlLedgerSeq.emplace(publicKeys[1], l->seq());
379  nUnlLedgerSeq.erase(publicKeys[0]);
380  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
381  }
382  }
383 
384  {
385  //(7) ledgers before the next flag ledger
386  for (auto i = 0; i < 256; ++i)
387  {
388  auto good_size = negUnlSizeTest(l, 1, true, false);
389  BEAST_EXPECT(good_size);
390  if (good_size)
391  {
392  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
393  BEAST_EXPECT(l->validatorToDisable() == publicKeys[0]);
394  }
395  l = std::make_shared<Ledger>(
396  *l, env.app().timeKeeper().closeTime());
397  }
398  BEAST_EXPECT(l->isFlagLedger());
399  l->updateNegativeUNL();
400 
401  //(8) next flag ledger
402  // test if the ledger updated correctly
403  auto good_size = negUnlSizeTest(l, 2, false, false);
404  BEAST_EXPECT(good_size);
405  if (good_size)
406  {
407  BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
408  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
409  nUnlLedgerSeq.emplace(publicKeys[0], l->seq());
410  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
411  }
412 
413  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
414  auto txReEnable_0 = createTx(false, l->seq(), publicKeys[0]);
415  auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
416 
417  OpenView accum(&*l);
418  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_0, true));
419  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, false));
420  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
421  accum.apply(*l);
422  good_size = negUnlSizeTest(l, 2, false, true);
423  BEAST_EXPECT(good_size);
424  if (good_size)
425  {
426  BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
427  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
428  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
429  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
430  }
431  }
432 
433  {
434  //(9) ledgers before the next flag ledger
435  for (auto i = 0; i < 256; ++i)
436  {
437  auto good_size = negUnlSizeTest(l, 2, false, true);
438  BEAST_EXPECT(good_size);
439  if (good_size)
440  {
441  BEAST_EXPECT(l->negativeUNL().count(publicKeys[0]));
442  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
443  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[0]);
444  }
445  l = std::make_shared<Ledger>(
446  *l, env.app().timeKeeper().closeTime());
447  }
448  BEAST_EXPECT(l->isFlagLedger());
449  l->updateNegativeUNL();
450 
451  //(10) next flag ledger
452  // test if the ledger updated correctly
453  auto good_size = negUnlSizeTest(l, 1, false, false);
454  BEAST_EXPECT(good_size);
455  if (good_size)
456  {
457  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
458  nUnlLedgerSeq.erase(publicKeys[0]);
459  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
460  }
461 
462  auto txReEnable_1 = createTx(false, l->seq(), publicKeys[1]);
463 
464  OpenView accum(&*l);
465  BEAST_EXPECT(applyAndTestResult(env, accum, txReEnable_1, true));
466  accum.apply(*l);
467  good_size = negUnlSizeTest(l, 1, false, true);
468  BEAST_EXPECT(good_size);
469  if (good_size)
470  {
471  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
472  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
473  BEAST_EXPECT(VerifyPubKeyAndSeq(l, nUnlLedgerSeq));
474  }
475  }
476 
477  {
478  //(11) ledgers before the next flag ledger
479  for (auto i = 0; i < 256; ++i)
480  {
481  auto good_size = negUnlSizeTest(l, 1, false, true);
482  BEAST_EXPECT(good_size);
483  if (good_size)
484  {
485  BEAST_EXPECT(l->negativeUNL().count(publicKeys[1]));
486  BEAST_EXPECT(l->validatorToReEnable() == publicKeys[1]);
487  }
488  l = std::make_shared<Ledger>(
489  *l, env.app().timeKeeper().closeTime());
490  }
491  BEAST_EXPECT(l->isFlagLedger());
492  l->updateNegativeUNL();
493 
494  //(12) next flag ledger
495  BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
496  }
497 
498  {
499  //(13) ledgers before the next flag ledger
500  for (auto i = 0; i < 256; ++i)
501  {
502  BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
503  l = std::make_shared<Ledger>(
504  *l, env.app().timeKeeper().closeTime());
505  }
506  BEAST_EXPECT(l->isFlagLedger());
507  l->updateNegativeUNL();
508 
509  //(14) next flag ledger
510  BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
511  }
512  }
513 
514  void
515  run() override
516  {
517  testNegativeUNL();
518  }
519 };
520 
521 class NegativeUNLNoAmendment_test : public beast::unit_test::suite
522 {
523  void
525  {
526  testcase("No negative UNL amendment");
527 
530  // genesis ledger
531  auto l = std::make_shared<Ledger>(
533  env.app().config(),
535  env.app().getNodeFamily());
536  BEAST_EXPECT(!l->rules().enabled(featureNegativeUNL));
537 
538  // generate more ledgers
539  for (auto i = 0; i < 256 - 1; ++i)
540  {
541  l = std::make_shared<Ledger>(
542  *l, env.app().timeKeeper().closeTime());
543  }
544  BEAST_EXPECT(l->seq() == 256);
545  auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
546  OpenView accum(&*l);
547  BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
548  accum.apply(*l);
549  BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
550  }
551 
552  void
553  run() override
554  {
556  }
557 };
558 
563 {
570  struct Parameter
571  {
572  std::uint32_t numNodes; // number of validators
573  std::uint32_t negUNLSize; // size of negative UNL in the last ledger
574  bool hasToDisable; // if has ToDisable in the last ledger
575  bool hasToReEnable; // if has ToReEnable in the last ledger
581  };
582 
583  NetworkHistory(beast::unit_test::suite& suite, Parameter const& p)
584  : env(suite, jtx::supported_amendments() | featureNegativeUNL)
585  , param(p)
586  , validations(env.app().getValidations())
587  {
588  createNodes();
589  if (!param.numLedgers)
590  param.numLedgers = 256 * (param.negUNLSize + 1);
592  }
593 
594  void
596  {
597  assert(param.numNodes <= 256);
599  for (int i = 0; i < param.numNodes; ++i)
600  {
601  UNLKeySet.insert(UNLKeys[i]);
602  UNLNodeIDs.push_back(calcNodeID(UNLKeys[i]));
603  UNLNodeIDSet.insert(UNLNodeIDs.back());
604  }
605  }
606 
611  bool
613  {
614  static uint256 fake_amemdment; // So we have different genesis ledgers
615  auto l = std::make_shared<Ledger>(
617  env.app().config(),
618  std::vector<uint256>{fake_amemdment++},
619  env.app().getNodeFamily());
620  history.push_back(l);
621 
622  // When putting validators into the negative UNL, we start with
623  // validator 0, then validator 1 ...
624  int nidx = 0;
625  while (l->seq() <= param.numLedgers)
626  {
627  l = std::make_shared<Ledger>(
628  *l, env.app().timeKeeper().closeTime());
629  history.push_back(l);
630 
631  if (l->isFlagLedger())
632  {
633  l->updateNegativeUNL();
634  OpenView accum(&*l);
635  if (l->negativeUNL().size() < param.negUNLSize)
636  {
637  auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
638  if (!applyAndTestResult(env, accum, tx, true))
639  break;
640  ++nidx;
641  }
642  else if (l->negativeUNL().size() == param.negUNLSize)
643  {
644  if (param.hasToDisable)
645  {
646  auto tx = createTx(true, l->seq(), UNLKeys[nidx]);
647  if (!applyAndTestResult(env, accum, tx, true))
648  break;
649  ++nidx;
650  }
651  if (param.hasToReEnable)
652  {
653  auto tx = createTx(false, l->seq(), UNLKeys[0]);
654  if (!applyAndTestResult(env, accum, tx, true))
655  break;
656  }
657  }
658  accum.apply(*l);
659  }
660  l->updateSkipList();
661  }
662  return negUnlSizeTest(
664  }
665 
674  {
675  static auto keyPair = randomKeyPair(KeyType::secp256k1);
676  return std::make_shared<STValidation>(
677  env.app().timeKeeper().now(),
678  keyPair.first,
679  keyPair.second,
680  v,
681  [&](STValidation& v) {
682  v.setFieldH256(sfLedgerHash, ledger->info().hash);
683  v.setFieldU32(sfLedgerSequence, ledger->seq());
684  v.setFlag(vfFullValidation);
685  });
686  };
687 
695  template <class NeedValidation>
696  void
697  walkHistoryAndAddValidations(NeedValidation&& needVal)
698  {
699  std::uint32_t curr = 0;
700  std::size_t need = 256 + 1;
701  // only last 256 + 1 ledgers need validations
702  if (history.size() > need)
703  curr = history.size() - need;
704  for (; curr != history.size(); ++curr)
705  {
706  for (std::size_t i = 0; i < param.numNodes; ++i)
707  {
708  if (needVal(history[curr], i))
709  {
711  v.setTrusted();
712  validations.add(UNLNodeIDs[i], v);
713  }
714  }
715  }
716  }
717 
719  lastLedger() const
720  {
721  return history.back();
722  }
723 
733 };
734 
735 auto defaultPreVote = [](NegativeUNLVote& vote) {};
747 template <typename PreVote = decltype(defaultPreVote)>
748 bool
750  NetworkHistory& history,
751  NodeID const& myId,
752  std::size_t expect,
753  PreVote const& pre = defaultPreVote)
754 {
755  NegativeUNLVote vote(myId, history.env.journal);
756  pre(vote);
757  auto txSet = std::make_shared<SHAMap>(
759  vote.doVoting(
760  history.lastLedger(), history.UNLKeySet, history.validations, txSet);
761  return countTx(txSet) == expect;
762 }
763 
767 class NegativeUNLVoteInternal_test : public beast::unit_test::suite
768 {
769  void
771  {
772  testcase("Create UNLModify Tx");
773  jtx::Env env(*this);
774 
775  NodeID myId(0xA0);
776  NegativeUNLVote vote(myId, env.journal);
777 
778  // one add, one remove
779  auto txSet = std::make_shared<SHAMap>(
781  PublicKey toDisableKey(
783  PublicKey toReEnableKey(
785  LedgerIndex seq(1234);
786  BEAST_EXPECT(countTx(txSet) == 0);
787  vote.addTx(seq, toDisableKey, NegativeUNLVote::ToDisable, txSet);
788  BEAST_EXPECT(countTx(txSet) == 1);
789  vote.addTx(seq, toReEnableKey, NegativeUNLVote::ToReEnable, txSet);
790  BEAST_EXPECT(countTx(txSet) == 2);
791  // content of a tx is implicitly tested after applied to a ledger
792  // in later test cases
793  }
794 
795  void
797  {
798  testcase("Pick One Candidate");
799  jtx::Env env(*this);
800 
801  NodeID myId(0xA0);
802  NegativeUNLVote vote(myId, env.journal);
803 
804  uint256 pad_0(0);
805  uint256 pad_f = ~pad_0;
806  NodeID n_1(1);
807  NodeID n_2(2);
808  NodeID n_3(3);
809  std::vector<NodeID> candidates({n_1});
810  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
811  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_1);
812  candidates.emplace_back(2);
813  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
814  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_2);
815  candidates.emplace_back(3);
816  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
817  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_3);
818  }
819 
820  void
822  {
823  testcase("Build Score Table");
824  /*
825  * 1. no skip list
826  * 2. short skip list
827  * 3. local node not enough history
828  * 4. a node double validated some seq
829  * 5. local node had enough validations but on a wrong chain
830  * 6. a good case, long enough history and perfect scores
831  */
832  {
833  // 1. no skip list
834  NetworkHistory history = {*this, {10, 0, false, false, 1}};
835  BEAST_EXPECT(history.goodHistory);
836  if (history.goodHistory)
837  {
838  NegativeUNLVote vote(
839  history.UNLNodeIDs[3], history.env.journal);
840  BEAST_EXPECT(!vote.buildScoreTable(
841  history.lastLedger(),
842  history.UNLNodeIDSet,
843  history.validations));
844  }
845  }
846 
847  {
848  // 2. short skip list
849  NetworkHistory history = {*this, {10, 0, false, false, 256 / 2}};
850  BEAST_EXPECT(history.goodHistory);
851  if (history.goodHistory)
852  {
853  NegativeUNLVote vote(
854  history.UNLNodeIDs[3], history.env.journal);
855  BEAST_EXPECT(!vote.buildScoreTable(
856  history.lastLedger(),
857  history.UNLNodeIDSet,
858  history.validations));
859  }
860  }
861 
862  {
863  // 3. local node not enough history
864  NetworkHistory history = {*this, {10, 0, false, false, 256 + 2}};
865  BEAST_EXPECT(history.goodHistory);
866  if (history.goodHistory)
867  {
868  NodeID myId = history.UNLNodeIDs[3];
870  [&](std::shared_ptr<Ledger const> const& l,
871  std::size_t idx) -> bool {
872  // skip half my validations.
873  return !(
874  history.UNLNodeIDs[idx] == myId &&
875  l->seq() % 2 == 0);
876  });
877  NegativeUNLVote vote(myId, history.env.journal);
878  BEAST_EXPECT(!vote.buildScoreTable(
879  history.lastLedger(),
880  history.UNLNodeIDSet,
881  history.validations));
882  }
883  }
884 
885  {
886  // 4. a node double validated some seq
887  // 5. local node had enough validations but on a wrong chain
888  NetworkHistory history = {*this, {10, 0, false, false, 256 + 2}};
889  // We need two chains for these tests
890  bool wrongChainSuccess = history.goodHistory;
891  BEAST_EXPECT(wrongChainSuccess);
892  NetworkHistory::LedgerHistory wrongChain =
893  std::move(history.history);
894  // Create a new chain and use it as the one that majority of nodes
895  // follow
896  history.createLedgerHistory();
897  BEAST_EXPECT(history.goodHistory);
898 
899  if (history.goodHistory && wrongChainSuccess)
900  {
901  NodeID myId = history.UNLNodeIDs[3];
902  NodeID badNode = history.UNLNodeIDs[4];
904  [&](std::shared_ptr<Ledger const> const& l,
905  std::size_t idx) -> bool {
906  // everyone but me
907  return !(history.UNLNodeIDs[idx] == myId);
908  });
909 
910  // local node validate wrong chain
911  // a node double validates
912  for (auto& l : wrongChain)
913  {
914  RCLValidation v1(history.createSTVal(l, myId));
915  history.validations.add(myId, v1);
916  RCLValidation v2(history.createSTVal(l, badNode));
917  history.validations.add(badNode, v2);
918  }
919 
920  NegativeUNLVote vote(myId, history.env.journal);
921 
922  // local node still on wrong chain, can build a scoreTable,
923  // but all other nodes' scores are zero
924  auto scoreTable = vote.buildScoreTable(
925  wrongChain.back(),
926  history.UNLNodeIDSet,
927  history.validations);
928  BEAST_EXPECT(scoreTable);
929  if (scoreTable)
930  {
931  for (auto const& [n, score] : *scoreTable)
932  {
933  if (n == myId)
934  BEAST_EXPECT(score == 256);
935  else
936  BEAST_EXPECT(score == 0);
937  }
938  }
939 
940  // if local node switched to right history, but cannot build
941  // scoreTable because not enough local validations
942  BEAST_EXPECT(!vote.buildScoreTable(
943  history.lastLedger(),
944  history.UNLNodeIDSet,
945  history.validations));
946  }
947  }
948 
949  {
950  // 6. a good case
951  NetworkHistory history = {*this, {10, 0, false, false, 256 + 1}};
952  BEAST_EXPECT(history.goodHistory);
953  if (history.goodHistory)
954  {
956  [&](std::shared_ptr<Ledger const> const& l,
957  std::size_t idx) -> bool { return true; });
958  NegativeUNLVote vote(
959  history.UNLNodeIDs[3], history.env.journal);
960  auto scoreTable = vote.buildScoreTable(
961  history.lastLedger(),
962  history.UNLNodeIDSet,
963  history.validations);
964  BEAST_EXPECT(scoreTable);
965  if (scoreTable)
966  {
967  for (auto const& [_, score] : *scoreTable)
968  {
969  (void)_;
970  BEAST_EXPECT(score == 256);
971  }
972  }
973  }
974  }
975  }
976 
989  bool
991  NegativeUNLVote& vote,
992  hash_set<NodeID> const& unl,
993  hash_set<NodeID> const& negUnl,
994  hash_map<NodeID, std::uint32_t> const& scoreTable,
995  std::size_t numDisable,
996  std::size_t numReEnable)
997  {
998  auto [disableCandidates, reEnableCandidates] =
999  vote.findAllCandidates(unl, negUnl, scoreTable);
1000  bool rightDisable = disableCandidates.size() == numDisable;
1001  bool rightReEnable = reEnableCandidates.size() == numReEnable;
1002  return rightDisable && rightReEnable;
1003  };
1004 
1005  void
1007  {
1008  testcase("Find All Candidates");
1009  /*
1010  * -- unl size: 35
1011  * -- negUnl size: 3
1012  *
1013  * 0. all good scores
1014  * 1. all bad scores
1015  * 2. all between watermarks
1016  * 3. 2 good scorers in negUnl
1017  * 4. 2 bad scorers not in negUnl
1018  * 5. 2 in negUnl but not in unl, have a remove candidate from score
1019  * table
1020  * 6. 2 in negUnl but not in unl, no remove candidate from score table
1021  * 7. 2 new validators have good scores, already in negUnl
1022  * 8. 2 new validators have bad scores, not in negUnl
1023  * 9. expired the new validators have bad scores, not in negUnl
1024  */
1025  NetworkHistory history = {*this, {35, 0, false, false, 0}};
1026 
1027  hash_set<NodeID> negUnl_012;
1028  for (std::uint32_t i = 0; i < 3; ++i)
1029  negUnl_012.insert(history.UNLNodeIDs[i]);
1030 
1031  // build a good scoreTable to use, or copy and modify
1032  hash_map<NodeID, std::uint32_t> goodScoreTable;
1033  for (auto const& n : history.UNLNodeIDs)
1034  goodScoreTable[n] = NegativeUNLVote::negativeUNLHighWaterMark + 1;
1035 
1036  NegativeUNLVote vote(history.UNLNodeIDs[0], history.env.journal);
1037 
1038  {
1039  // all good scores
1040  BEAST_EXPECT(checkCandidateSizes(
1041  vote, history.UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3));
1042  }
1043  {
1044  // all bad scores
1046  for (auto& n : history.UNLNodeIDs)
1047  scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark - 1;
1048  BEAST_EXPECT(checkCandidateSizes(
1049  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0));
1050  }
1051  {
1052  // all between watermarks
1054  for (auto& n : history.UNLNodeIDs)
1055  scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark + 1;
1056  BEAST_EXPECT(checkCandidateSizes(
1057  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 0));
1058  }
1059 
1060  {
1061  // 2 good scorers in negUnl
1062  auto scoreTable = goodScoreTable;
1063  scoreTable[*negUnl_012.begin()] =
1065  BEAST_EXPECT(checkCandidateSizes(
1066  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 2));
1067  }
1068 
1069  {
1070  // 2 bad scorers not in negUnl
1071  auto scoreTable = goodScoreTable;
1072  scoreTable[history.UNLNodeIDs[11]] =
1074  scoreTable[history.UNLNodeIDs[12]] =
1076  BEAST_EXPECT(checkCandidateSizes(
1077  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 2, 3));
1078  }
1079 
1080  {
1081  // 2 in negUnl but not in unl, have a remove candidate from score
1082  // table
1083  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1084  UNL_temp.erase(history.UNLNodeIDs[0]);
1085  UNL_temp.erase(history.UNLNodeIDs[1]);
1086  BEAST_EXPECT(checkCandidateSizes(
1087  vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3));
1088  }
1089 
1090  {
1091  // 2 in negUnl but not in unl, no remove candidate from score table
1092  auto scoreTable = goodScoreTable;
1093  scoreTable.erase(history.UNLNodeIDs[0]);
1094  scoreTable.erase(history.UNLNodeIDs[1]);
1095  scoreTable[history.UNLNodeIDs[2]] =
1097  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1098  UNL_temp.erase(history.UNLNodeIDs[0]);
1099  UNL_temp.erase(history.UNLNodeIDs[1]);
1100  BEAST_EXPECT(checkCandidateSizes(
1101  vote, UNL_temp, negUnl_012, scoreTable, 0, 2));
1102  }
1103 
1104  {
1105  // 2 new validators
1106  NodeID new_1(0xbead);
1107  NodeID new_2(0xbeef);
1108  hash_set<NodeID> nowTrusted = {new_1, new_2};
1109  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1110  UNL_temp.insert(new_1);
1111  UNL_temp.insert(new_2);
1112  vote.newValidators(256, nowTrusted);
1113  {
1114  // 2 new validators have good scores, already in negUnl
1115  auto scoreTable = goodScoreTable;
1116  scoreTable[new_1] =
1118  scoreTable[new_2] =
1120  hash_set<NodeID> negUnl_temp = negUnl_012;
1121  negUnl_temp.insert(new_1);
1122  negUnl_temp.insert(new_2);
1123  BEAST_EXPECT(checkCandidateSizes(
1124  vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2));
1125  }
1126  {
1127  // 2 new validators have bad scores, not in negUnl
1128  auto scoreTable = goodScoreTable;
1129  scoreTable[new_1] = 0;
1130  scoreTable[new_2] = 0;
1131  BEAST_EXPECT(checkCandidateSizes(
1132  vote, UNL_temp, negUnl_012, scoreTable, 0, 3));
1133  }
1134  {
1135  // expired the new validators have bad scores, not in negUnl
1136  vote.purgeNewValidators(
1138  auto scoreTable = goodScoreTable;
1139  scoreTable[new_1] = 0;
1140  scoreTable[new_2] = 0;
1141  BEAST_EXPECT(checkCandidateSizes(
1142  vote, UNL_temp, negUnl_012, scoreTable, 2, 3));
1143  }
1144  }
1145  }
1146 
1147  void
1149  {
1150  testcase("Find All Candidates Combination");
1151  /*
1152  * == combination 1:
1153  * -- unl size: 34, 35, 80
1154  * -- nUnl size: 0, 50%, all
1155  * -- score pattern: all 0, all negativeUNLLowWaterMark & +1 & -1, all
1156  * negativeUNLHighWaterMark & +1 & -1, all 100%
1157  *
1158  * == combination 2:
1159  * -- unl size: 34, 35, 80
1160  * -- negativeUNL size: 0, all
1161  * -- nUnl size: one on, one off, one on, one off,
1162  * -- score pattern: 2*(negativeUNLLowWaterMark, +1, -1) &
1163  * 2*(negativeUNLHighWaterMark, +1, -1) & rest
1164  * negativeUNLMinLocalValsToVote
1165  */
1166 
1167  jtx::Env env(*this);
1168 
1169  NodeID myId(0xA0);
1170  NegativeUNLVote vote(myId, env.journal);
1171 
1172  std::array<std::uint32_t, 3> unlSizes = {34, 35, 80};
1173  std::array<std::uint32_t, 3> nUnlPercent = {0, 50, 100};
1174  std::array<std::uint32_t, 8> scores = {
1175  0,
1183 
1184  //== combination 1:
1185  {
1186  auto fillScoreTable =
1187  [&](std::uint32_t unl_size,
1188  std::uint32_t nUnl_size,
1189  std::uint32_t score,
1190  hash_set<NodeID>& unl,
1191  hash_set<NodeID>& negUnl,
1192  hash_map<NodeID, std::uint32_t>& scoreTable) {
1193  std::vector<NodeID> nodeIDs;
1194  std::vector<PublicKey> keys = createPublicKeys(unl_size);
1195  for (auto const& k : keys)
1196  {
1197  nodeIDs.emplace_back(calcNodeID(k));
1198  unl.emplace(nodeIDs.back());
1199  scoreTable[nodeIDs.back()] = score;
1200  }
1201  for (std::uint32_t i = 0; i < nUnl_size; ++i)
1202  negUnl.insert(nodeIDs[i]);
1203  };
1204 
1205  for (auto us : unlSizes)
1206  {
1207  for (auto np : nUnlPercent)
1208  {
1209  for (auto score : scores)
1210  {
1211  hash_set<NodeID> unl;
1212  hash_set<NodeID> negUnl;
1214  fillScoreTable(
1215  us, us * np / 100, score, unl, negUnl, scoreTable);
1216  BEAST_EXPECT(unl.size() == us);
1217  BEAST_EXPECT(negUnl.size() == us * np / 100);
1218  BEAST_EXPECT(scoreTable.size() == us);
1219 
1220  std::size_t toDisable_expect = 0;
1221  std::size_t toReEnable_expect = 0;
1222  if (np == 0)
1223  {
1224  if (score <
1226  {
1227  toDisable_expect = us;
1228  }
1229  }
1230  else if (np == 50)
1231  {
1232  if (score >
1234  {
1235  toReEnable_expect = us * np / 100;
1236  }
1237  }
1238  else
1239  {
1240  if (score >
1242  {
1243  toReEnable_expect = us;
1244  }
1245  }
1246  BEAST_EXPECT(checkCandidateSizes(
1247  vote,
1248  unl,
1249  negUnl,
1250  scoreTable,
1251  toDisable_expect,
1252  toReEnable_expect));
1253  }
1254  }
1255  }
1256 
1257  //== combination 2:
1258  {
1259  auto fillScoreTable =
1260  [&](std::uint32_t unl_size,
1261  std::uint32_t nUnl_percent,
1262  hash_set<NodeID>& unl,
1263  hash_set<NodeID>& negUnl,
1264  hash_map<NodeID, std::uint32_t>& scoreTable) {
1265  std::vector<NodeID> nodeIDs;
1266  std::vector<PublicKey> keys =
1267  createPublicKeys(unl_size);
1268  for (auto const& k : keys)
1269  {
1270  nodeIDs.emplace_back(calcNodeID(k));
1271  unl.emplace(nodeIDs.back());
1272  }
1273 
1274  std::uint32_t nIdx = 0;
1275  for (auto score : scores)
1276  {
1277  scoreTable[nodeIDs[nIdx++]] = score;
1278  scoreTable[nodeIDs[nIdx++]] = score;
1279  }
1280  for (; nIdx < unl_size;)
1281  {
1282  scoreTable[nodeIDs[nIdx++]] = scores.back();
1283  }
1284 
1285  if (nUnl_percent == 100)
1286  {
1287  negUnl = unl;
1288  }
1289  else if (nUnl_percent == 50)
1290  {
1291  for (std::uint32_t i = 1; i < unl_size; i += 2)
1292  negUnl.insert(nodeIDs[i]);
1293  }
1294  };
1295 
1296  for (auto us : unlSizes)
1297  {
1298  for (auto np : nUnlPercent)
1299  {
1300  hash_set<NodeID> unl;
1301  hash_set<NodeID> negUnl;
1303 
1304  fillScoreTable(us, np, unl, negUnl, scoreTable);
1305  BEAST_EXPECT(unl.size() == us);
1306  BEAST_EXPECT(negUnl.size() == us * np / 100);
1307  BEAST_EXPECT(scoreTable.size() == us);
1308 
1309  std::size_t toDisable_expect = 0;
1310  std::size_t toReEnable_expect = 0;
1311  if (np == 0)
1312  {
1313  toDisable_expect = 4;
1314  }
1315  else if (np == 50)
1316  {
1317  toReEnable_expect = negUnl.size() - 6;
1318  }
1319  else
1320  {
1321  toReEnable_expect = negUnl.size() - 12;
1322  }
1323  BEAST_EXPECT(checkCandidateSizes(
1324  vote,
1325  unl,
1326  negUnl,
1327  scoreTable,
1328  toDisable_expect,
1329  toReEnable_expect));
1330  }
1331  }
1332  }
1333  }
1334  }
1335 
1336  void
1338  {
1339  testcase("New Validators");
1340  jtx::Env env(*this);
1341 
1342  NodeID myId(0xA0);
1343  NegativeUNLVote vote(myId, env.journal);
1344 
1345  // test cases:
1346  // newValidators_ of the NegativeUNLVote empty, add one
1347  // add a new one and one already added
1348  // add a new one and some already added
1349  // purge and see some are expired
1350 
1351  NodeID n1(0xA1);
1352  NodeID n2(0xA2);
1353  NodeID n3(0xA3);
1354 
1355  vote.newValidators(2, {n1});
1356  BEAST_EXPECT(vote.newValidators_.size() == 1);
1357  if (vote.newValidators_.size() == 1)
1358  {
1359  BEAST_EXPECT(vote.newValidators_.begin()->first == n1);
1360  BEAST_EXPECT(vote.newValidators_.begin()->second == 2);
1361  }
1362 
1363  vote.newValidators(3, {n1, n2});
1364  BEAST_EXPECT(vote.newValidators_.size() == 2);
1365  if (vote.newValidators_.size() == 2)
1366  {
1367  BEAST_EXPECT(vote.newValidators_[n1] == 2);
1368  BEAST_EXPECT(vote.newValidators_[n2] == 3);
1369  }
1370 
1371  vote.newValidators(
1373  BEAST_EXPECT(vote.newValidators_.size() == 3);
1374  if (vote.newValidators_.size() == 3)
1375  {
1376  BEAST_EXPECT(vote.newValidators_[n1] == 2);
1377  BEAST_EXPECT(vote.newValidators_[n2] == 3);
1378  BEAST_EXPECT(
1379  vote.newValidators_[n3] ==
1381  }
1382 
1384  BEAST_EXPECT(vote.newValidators_.size() == 3);
1386  BEAST_EXPECT(vote.newValidators_.size() == 2);
1388  BEAST_EXPECT(vote.newValidators_.size() == 1);
1389  BEAST_EXPECT(vote.newValidators_.begin()->first == n3);
1390  BEAST_EXPECT(
1391  vote.newValidators_.begin()->second ==
1393  }
1394 
1395  void
1396  run() override
1397  {
1398  testAddTx();
1404  }
1405 };
1406 
1412 class NegativeUNLVoteScoreTable_test : public beast::unit_test::suite
1413 {
1414  void
1416  {
1417  testcase("Build Score Table Combination");
1418  /*
1419  * local node good history, correct scores:
1420  * == combination:
1421  * -- unl size: 10, 34, 35, 50
1422  * -- score pattern: all 0, all 50%, all 100%, two 0% two 50% rest 100%
1423  */
1424  std::array<std::uint32_t, 4> unlSizes = {10, 34, 35, 50};
1425  std::array<std::array<std::uint32_t, 3>, 4> scorePattern = {
1426  {{{0, 0, 0}}, {{50, 50, 50}}, {{100, 100, 100}}, {{0, 50, 100}}}};
1427 
1428  for (auto unlSize : unlSizes)
1429  {
1430  for (std::uint32_t sp = 0; sp < 4; ++sp)
1431  {
1432  NetworkHistory history = {
1433  *this, {unlSize, 0, false, false, 256 + 2}};
1434  BEAST_EXPECT(history.goodHistory);
1435  if (history.goodHistory)
1436  {
1437  NodeID myId = history.UNLNodeIDs[3];
1439  [&](std::shared_ptr<Ledger const> const& l,
1440  std::size_t idx) -> bool {
1441  std::size_t k;
1442  if (idx < 2)
1443  k = 0;
1444  else if (idx < 4)
1445  k = 1;
1446  else
1447  k = 2;
1448 
1449  bool add_50 =
1450  scorePattern[sp][k] == 50 && l->seq() % 2 == 0;
1451  bool add_100 = scorePattern[sp][k] == 100;
1452  bool add_me = history.UNLNodeIDs[idx] == myId;
1453  return add_50 || add_100 || add_me;
1454  });
1455 
1456  NegativeUNLVote vote(myId, history.env.journal);
1457  auto scoreTable = vote.buildScoreTable(
1458  history.lastLedger(),
1459  history.UNLNodeIDSet,
1460  history.validations);
1461  BEAST_EXPECT(scoreTable);
1462  if (scoreTable)
1463  {
1464  std::uint32_t i = 0; // looping unl
1465  auto checkScores = [&](std::uint32_t score,
1466  std::uint32_t k) -> bool {
1467  if (history.UNLNodeIDs[i] == myId)
1468  return score == 256;
1469  if (scorePattern[sp][k] == 0)
1470  return score == 0;
1471  if (scorePattern[sp][k] == 50)
1472  return score == 256 / 2;
1473  if (scorePattern[sp][k] == 100)
1474  return score == 256;
1475  else
1476  return false;
1477  };
1478  for (; i < 2; ++i)
1479  {
1480  BEAST_EXPECT(checkScores(
1481  (*scoreTable)[history.UNLNodeIDs[i]], 0));
1482  }
1483  for (; i < 4; ++i)
1484  {
1485  BEAST_EXPECT(checkScores(
1486  (*scoreTable)[history.UNLNodeIDs[i]], 1));
1487  }
1488  for (; i < unlSize; ++i)
1489  {
1490  BEAST_EXPECT(checkScores(
1491  (*scoreTable)[history.UNLNodeIDs[i]], 2));
1492  }
1493  }
1494  }
1495  }
1496  }
1497  }
1498 
1499  void
1500  run() override
1501  {
1503  }
1504 };
1505 
1506 /*
1507  * Test the doVoting function of NegativeUNLVote.
1508  * The test cases are split to 5 classes for parallel execution.
1509  *
1510  * Voting tests: (use hasToDisable and hasToReEnable in some of the cases)
1511  *
1512  * == all good score, nUnl empty
1513  * -- txSet.size = 0
1514  * == all good score, nUnl not empty (use hasToDisable)
1515  * -- txSet.size = 1
1516  *
1517  * == 2 nodes offline, nUnl empty (use hasToReEnable)
1518  * -- txSet.size = 1
1519  * == 2 nodes offline, in nUnl
1520  * -- txSet.size = 0
1521  *
1522  * == 2 nodes offline, not in nUnl, but maxListed
1523  * -- txSet.size = 0
1524  *
1525  * == 2 nodes offline including me, not in nUnl
1526  * -- txSet.size = 0
1527  * == 2 nodes offline, not in negativeUNL, but I'm not a validator
1528  * -- txSet.size = 0
1529  * == 2 in nUnl, but not in unl, no other remove candidates
1530  * -- txSet.size = 1
1531  *
1532  * == 2 new validators have bad scores
1533  * -- txSet.size = 0
1534  * == 2 expired new validators have bad scores
1535  * -- txSet.size = 1
1536  */
1537 
1538 class NegativeUNLVoteGoodScore_test : public beast::unit_test::suite
1539 {
1540  void
1542  {
1543  testcase("Do Voting");
1544 
1545  {
1546  //== all good score, negativeUNL empty
1547  //-- txSet.size = 0
1548  NetworkHistory history = {*this, {51, 0, false, false, {}}};
1549  BEAST_EXPECT(history.goodHistory);
1550  if (history.goodHistory)
1551  {
1553  [&](std::shared_ptr<Ledger const> const& l,
1554  std::size_t idx) -> bool { return true; });
1555  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0));
1556  }
1557  }
1558 
1559  {
1560  // all good score, negativeUNL not empty (use hasToDisable)
1561  //-- txSet.size = 1
1562  NetworkHistory history = {*this, {37, 0, true, false, {}}};
1563  BEAST_EXPECT(history.goodHistory);
1564  if (history.goodHistory)
1565  {
1567  [&](std::shared_ptr<Ledger const> const& l,
1568  std::size_t idx) -> bool { return true; });
1569  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 1));
1570  }
1571  }
1572  }
1573 
1574  void
1575  run() override
1576  {
1577  testDoVoting();
1578  }
1579 };
1580 
1581 class NegativeUNLVoteOffline_test : public beast::unit_test::suite
1582 {
1583  void
1585  {
1586  testcase("Do Voting");
1587 
1588  {
1589  //== 2 nodes offline, negativeUNL empty (use hasToReEnable)
1590  //-- txSet.size = 1
1591  NetworkHistory history = {*this, {29, 1, false, true, {}}};
1592  BEAST_EXPECT(history.goodHistory);
1593  if (history.goodHistory)
1594  {
1596  [&](std::shared_ptr<Ledger const> const& l,
1597  std::size_t idx) -> bool {
1598  // skip node 0 and node 1
1599  return idx > 1;
1600  });
1601  BEAST_EXPECT(
1602  voteAndCheck(history, history.UNLNodeIDs.back(), 1));
1603  }
1604  }
1605 
1606  {
1607  // 2 nodes offline, in negativeUNL
1608  //-- txSet.size = 0
1609  NetworkHistory history = {*this, {30, 1, true, false, {}}};
1610  BEAST_EXPECT(history.goodHistory);
1611  if (history.goodHistory)
1612  {
1613  NodeID n1 =
1614  calcNodeID(*history.lastLedger()->negativeUNL().begin());
1615  NodeID n2 =
1616  calcNodeID(*history.lastLedger()->validatorToDisable());
1618  [&](std::shared_ptr<Ledger const> const& l,
1619  std::size_t idx) -> bool {
1620  // skip node 0 and node 1
1621  return history.UNLNodeIDs[idx] != n1 &&
1622  history.UNLNodeIDs[idx] != n2;
1623  });
1624  BEAST_EXPECT(
1625  voteAndCheck(history, history.UNLNodeIDs.back(), 0));
1626  }
1627  }
1628  }
1629 
1630  void
1631  run() override
1632  {
1633  testDoVoting();
1634  }
1635 };
1636 
1637 class NegativeUNLVoteMaxListed_test : public beast::unit_test::suite
1638 {
1639  void
1641  {
1642  testcase("Do Voting");
1643 
1644  {
1645  // 2 nodes offline, not in negativeUNL, but maxListed
1646  //-- txSet.size = 0
1647  NetworkHistory history = {*this, {32, 8, true, true, {}}};
1648  BEAST_EXPECT(history.goodHistory);
1649  if (history.goodHistory)
1650  {
1652  [&](std::shared_ptr<Ledger const> const& l,
1653  std::size_t idx) -> bool {
1654  // skip node 0 ~ 10
1655  return idx > 10;
1656  });
1657  BEAST_EXPECT(
1658  voteAndCheck(history, history.UNLNodeIDs.back(), 0));
1659  }
1660  }
1661  }
1662 
1663  void
1664  run() override
1665  {
1666  testDoVoting();
1667  }
1668 };
1669 
1670 class NegativeUNLVoteRetiredValidator_test : public beast::unit_test::suite
1671 {
1672  void
1674  {
1675  testcase("Do Voting");
1676 
1677  {
1678  //== 2 nodes offline including me, not in negativeUNL
1679  //-- txSet.size = 0
1680  NetworkHistory history = {*this, {35, 0, false, false, {}}};
1681  BEAST_EXPECT(history.goodHistory);
1682  if (history.goodHistory)
1683  {
1685  [&](std::shared_ptr<Ledger const> const& l,
1686  std::size_t idx) -> bool { return idx > 1; });
1687  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0));
1688  }
1689  }
1690 
1691  {
1692  // 2 nodes offline, not in negativeUNL, but I'm not a validator
1693  //-- txSet.size = 0
1694  NetworkHistory history = {*this, {40, 0, false, false, {}}};
1695  BEAST_EXPECT(history.goodHistory);
1696  if (history.goodHistory)
1697  {
1699  [&](std::shared_ptr<Ledger const> const& l,
1700  std::size_t idx) -> bool { return idx > 1; });
1701  BEAST_EXPECT(voteAndCheck(history, NodeID(0xdeadbeef), 0));
1702  }
1703  }
1704 
1705  {
1706  //== 2 in negativeUNL, but not in unl, no other remove candidates
1707  //-- txSet.size = 1
1708  NetworkHistory history = {*this, {25, 2, false, false, {}}};
1709  BEAST_EXPECT(history.goodHistory);
1710  if (history.goodHistory)
1711  {
1713  [&](std::shared_ptr<Ledger const> const& l,
1714  std::size_t idx) -> bool { return idx > 1; });
1715  BEAST_EXPECT(voteAndCheck(
1716  history,
1717  history.UNLNodeIDs.back(),
1718  1,
1719  [&](NegativeUNLVote& vote) {
1720  history.UNLKeySet.erase(history.UNLKeys[0]);
1721  history.UNLKeySet.erase(history.UNLKeys[1]);
1722  }));
1723  }
1724  }
1725  }
1726 
1727  void
1728  run() override
1729  {
1730  testDoVoting();
1731  }
1732 };
1733 
1734 class NegativeUNLVoteNewValidator_test : public beast::unit_test::suite
1735 {
1736  void
1738  {
1739  testcase("Do Voting");
1740 
1741  {
1742  //== 2 new validators have bad scores
1743  //-- txSet.size = 0
1744  NetworkHistory history = {*this, {15, 0, false, false, {}}};
1745  BEAST_EXPECT(history.goodHistory);
1746  if (history.goodHistory)
1747  {
1749  [&](std::shared_ptr<Ledger const> const& l,
1750  std::size_t idx) -> bool { return true; });
1751  BEAST_EXPECT(voteAndCheck(
1752  history,
1753  history.UNLNodeIDs[0],
1754  0,
1755  [&](NegativeUNLVote& vote) {
1756  auto extra_key_1 =
1757  randomKeyPair(KeyType::ed25519).first;
1758  auto extra_key_2 =
1759  randomKeyPair(KeyType::ed25519).first;
1760  history.UNLKeySet.insert(extra_key_1);
1761  history.UNLKeySet.insert(extra_key_2);
1762  hash_set<NodeID> nowTrusted;
1763  nowTrusted.insert(calcNodeID(extra_key_1));
1764  nowTrusted.insert(calcNodeID(extra_key_2));
1765  vote.newValidators(
1766  history.lastLedger()->seq(), nowTrusted);
1767  }));
1768  }
1769  }
1770 
1771  {
1772  //== 2 expired new validators have bad scores
1773  //-- txSet.size = 1
1774  NetworkHistory history = {
1775  *this,
1776  {21,
1777  0,
1778  false,
1779  false,
1781  BEAST_EXPECT(history.goodHistory);
1782  if (history.goodHistory)
1783  {
1785  [&](std::shared_ptr<Ledger const> const& l,
1786  std::size_t idx) -> bool { return true; });
1787  BEAST_EXPECT(voteAndCheck(
1788  history,
1789  history.UNLNodeIDs[0],
1790  1,
1791  [&](NegativeUNLVote& vote) {
1792  auto extra_key_1 =
1793  randomKeyPair(KeyType::ed25519).first;
1794  auto extra_key_2 =
1795  randomKeyPair(KeyType::ed25519).first;
1796  history.UNLKeySet.insert(extra_key_1);
1797  history.UNLKeySet.insert(extra_key_2);
1798  hash_set<NodeID> nowTrusted;
1799  nowTrusted.insert(calcNodeID(extra_key_1));
1800  nowTrusted.insert(calcNodeID(extra_key_2));
1801  vote.newValidators(256, nowTrusted);
1802  }));
1803  }
1804  }
1805  }
1806 
1807  void
1808  run() override
1809  {
1810  testDoVoting();
1811  }
1812 };
1813 
1814 class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite
1815 {
1816  void
1818  {
1819  testcase("Filter Validations");
1820  jtx::Env env(*this);
1821  auto l = std::make_shared<Ledger>(
1823  env.app().config(),
1825  env.app().getNodeFamily());
1826 
1827  auto createSTVal = [&](std::pair<PublicKey, SecretKey> const& keys) {
1828  return std::make_shared<STValidation>(
1829  env.app().timeKeeper().now(),
1830  keys.first,
1831  keys.second,
1832  calcNodeID(keys.first),
1833  [&](STValidation& v) {
1834  v.setFieldH256(sfLedgerHash, l->info().hash);
1835  v.setFieldU32(sfLedgerSequence, l->seq());
1836  v.setFlag(vfFullValidation);
1837  });
1838  };
1839 
1840  // create keys and validations
1841  std::uint32_t numNodes = 10;
1842  std::uint32_t negUnlSize = 3;
1843  std::vector<std::string> cfgKeys;
1844  hash_set<NodeID> activeValidators;
1845  hash_set<PublicKey> nUnlKeys;
1847  for (int i = 0; i < numNodes; ++i)
1848  {
1849  auto keyPair = randomKeyPair(KeyType::secp256k1);
1850  vals.emplace_back(createSTVal(keyPair));
1851  cfgKeys.push_back(toBase58(TokenType::NodePublic, keyPair.first));
1852  activeValidators.emplace(calcNodeID(keyPair.first));
1853  if (i < negUnlSize)
1854  {
1855  nUnlKeys.insert(keyPair.first);
1856  }
1857  }
1858 
1859  // setup the ValidatorList
1860  auto& validators = env.app().validators();
1861  auto& local = *nUnlKeys.begin();
1862  std::vector<std::string> cfgPublishers;
1863  validators.load(local, cfgKeys, cfgPublishers);
1864  validators.updateTrusted(
1865  activeValidators,
1866  env.timeKeeper().now(),
1867  env.app().getOPs(),
1868  env.app().overlay(),
1869  env.app().getHashRouter());
1870  BEAST_EXPECT(validators.getTrustedMasterKeys().size() == numNodes);
1871  validators.setNegativeUNL(nUnlKeys);
1872  BEAST_EXPECT(validators.getNegativeUNL().size() == negUnlSize);
1873 
1874  // test the filter
1875  BEAST_EXPECT(vals.size() == numNodes);
1876  vals = validators.negativeUNLFilter(std::move(vals));
1877  BEAST_EXPECT(vals.size() == numNodes - negUnlSize);
1878  }
1879 
1880  void
1881  run() override
1882  {
1884  }
1885 };
1886 
1887 BEAST_DEFINE_TESTSUITE(NegativeUNL, ledger, ripple);
1888 BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, ledger, ripple);
1889 
1890 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, ripple);
1891 BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, ripple);
1892 BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus, ripple, 1);
1893 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus, ripple);
1894 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus, ripple);
1896  NegativeUNLVoteRetiredValidator,
1897  consensus,
1898  ripple,
1899  1);
1900 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, ripple);
1901 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, ripple);
1902 
1906 bool
1909  size_t size,
1910  bool hasToDisable,
1911  bool hasToReEnable)
1912 {
1913  bool sameSize = l->negativeUNL().size() == size;
1914  bool sameToDisable =
1915  (l->validatorToDisable() != std::nullopt) == hasToDisable;
1916  bool sameToReEnable =
1917  (l->validatorToReEnable() != std::nullopt) == hasToReEnable;
1918 
1919  return sameSize && sameToDisable && sameToReEnable;
1920 }
1921 
1922 bool
1923 applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
1924 {
1925  auto res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
1926  if (pass)
1927  return res.first == tesSUCCESS;
1928  else
1929  return res.first == tefFAILURE || res.first == temDISABLED;
1930 }
1931 
1932 bool
1935  hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq)
1936 {
1937  auto sle = l->read(keylet::negativeUNL());
1938  if (!sle)
1939  return false;
1940  if (!sle->isFieldPresent(sfDisabledValidators))
1941  return false;
1942 
1943  auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
1944  if (nUnlData.size() != nUnlLedgerSeq.size())
1945  return false;
1946 
1947  for (auto const& n : nUnlData)
1948  {
1949  if (!n.isFieldPresent(sfFirstLedgerSequence) ||
1950  !n.isFieldPresent(sfPublicKey))
1951  return false;
1952 
1953  auto seq = n.getFieldU32(sfFirstLedgerSequence);
1954  auto d = n.getFieldVL(sfPublicKey);
1955  auto s = makeSlice(d);
1956  if (!publicKeyType(s))
1957  return false;
1958  PublicKey pk(s);
1959  auto it = nUnlLedgerSeq.find(pk);
1960  if (it == nUnlLedgerSeq.end())
1961  return false;
1962  if (it->second != seq)
1963  return false;
1964  nUnlLedgerSeq.erase(it);
1965  }
1966  return nUnlLedgerSeq.size() == 0;
1967 }
1968 
1971 {
1972  std::size_t count = 0;
1973  for (auto i = txSet->begin(); i != txSet->end(); ++i)
1974  {
1975  ++count;
1976  }
1977  return count;
1978 };
1979 
1982 {
1984  std::size_t ss = 33;
1985  std::vector<uint8_t> data(ss, 0);
1986  data[0] = 0xED;
1987  for (int i = 0; i < n; ++i)
1988  {
1989  data[1]++;
1990  Slice s(data.data(), ss);
1991  keys.emplace_back(s);
1992  }
1993  return keys;
1994 }
1995 
1996 STTx
1997 createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
1998 {
1999  auto fill = [&](auto& obj) {
2000  obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
2001  obj.setFieldU32(sfLedgerSequence, seq);
2002  obj.setFieldVL(sfUNLModifyValidator, txKey);
2003  };
2004  return STTx(ttUNL_MODIFY, fill);
2005 }
2006 
2007 } // namespace test
2008 } // namespace ripple
ripple::test::NegativeUNLNoAmendment_test::run
void run() override
Definition: NegativeUNL_test.cpp:553
ripple::test::NetworkHistory::UNLKeys
std::vector< PublicKey > UNLKeys
Definition: NegativeUNL_test.cpp:727
ripple::Application::getNodeFamily
virtual Family & getNodeFamily()=0
ripple::test::NegativeUNLVoteMaxListed_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1640
ripple::test::NegativeUNLVoteRetiredValidator_test::run
void run() override
Definition: NegativeUNL_test.cpp:1728
ripple::sfUNLModifyValidator
const SF_VL sfUNLModifyValidator
ripple::NegativeUNLVote::doVoting
void doVoting(std::shared_ptr< Ledger const > const &prevLedger, hash_set< PublicKey > const &unlKeys, RCLValidations &validations, std::shared_ptr< SHAMap > const &initialSet)
Cast our local vote on the NegativeUNL candidates.
Definition: NegativeUNLVote.cpp:33
ripple::RCLValidation::setTrusted
void setTrusted()
Definition: RCLValidations.h:104
ripple::test::createTx
STTx createTx(bool disabling, LedgerIndex seq, PublicKey const &txKey)
Create ttUNL_MODIFY Tx.
Definition: NegativeUNL_test.cpp:1997
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:99
ripple::test::NetworkHistory::history
LedgerHistory history
Definition: NegativeUNL_test.cpp:731
std::shared_ptr
STL class.
ripple::test::NegativeUNLVoteInternal_test::testBuildScoreTableSpecialCases
void testBuildScoreTableSpecialCases()
Definition: NegativeUNL_test.cpp:821
ripple::calcNodeID
NodeID calcNodeID(PublicKey const &pk)
Calculate the 160-bit node ID from a node public key.
Definition: PublicKey.cpp:303
ripple::NodeID
base_uint< 160, detail::NodeIDTag > NodeID
NodeID is a 160-bit hash representing one node.
Definition: UintTypes.h:59
ripple::sfLedgerSequence
const SF_UINT32 sfLedgerSequence
ripple::apply
std::pair< TER, bool > apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition: apply.cpp:109
ripple::test::VerifyPubKeyAndSeq
bool VerifyPubKeyAndSeq(std::shared_ptr< Ledger const > const &l, hash_map< PublicKey, std::uint32_t > nUnlLedgerSeq)
Verify the content of negative UNL entries (public key and ledger sequence) of a ledger.
Definition: NegativeUNL_test.cpp:1933
ripple::OpenView::apply
void apply(TxsRawView &to) const
Apply changes.
Definition: OpenView.cpp:130
ripple::sfFirstLedgerSequence
const SF_UINT32 sfFirstLedgerSequence
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::unordered_set
STL class.
std::pair
ripple::SHAMapType::TRANSACTION
@ TRANSACTION
ripple::test::NetworkHistory::Parameter
Only reasonable parameters can be honored, e.g cannot hasToReEnable when nUNLSize == 0.
Definition: NegativeUNL_test.cpp:570
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
std::vector
STL class.
std::unordered_map::find
T find(T... args)
std::vector::size
T size(T... args)
ripple::test::ManualTimeKeeper::now
time_point now() const override
Definition: ManualTimeKeeper.h:38
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
std::unordered_map::emplace
T emplace(T... args)
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:144
ripple::test::NegativeUNLVoteGoodScore_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1541
ripple::NegativeUNLVote::ToReEnable
@ ToReEnable
Definition: NegativeUNLVote.h:85
ripple::test::NetworkHistory::Parameter::hasToDisable
bool hasToDisable
Definition: NegativeUNL_test.cpp:574
ripple::test::jtx::Env::timeKeeper
ManualTimeKeeper & timeKeeper()
Definition: Env.h:253
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:241
std::vector::back
T back(T... args)
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::NegativeUNLVote::negativeUNLHighWaterMark
static constexpr size_t negativeUNLHighWaterMark
An unreliable validator must have more than negativeUNLHighWaterMark validations in the last flag led...
Definition: NegativeUNLVote.h:61
ripple::test::NegativeUNLVoteFilterValidations_test::run
void run() override
Definition: NegativeUNL_test.cpp:1881
ripple::RCLValidation
Wrapper over STValidation for generic Validation code.
Definition: RCLValidations.h:38
ripple::test::NegativeUNLVoteFilterValidations_test
Definition: NegativeUNL_test.cpp:1814
ripple::test::NegativeUNLNoAmendment_test::testNegativeUNLNoAmendment
void testNegativeUNLNoAmendment()
Definition: NegativeUNL_test.cpp:524
ripple::TimeKeeper::closeTime
time_point closeTime() const
Returns the predicted close time, in network time.
Definition: TimeKeeper.h:76
ripple::test::NegativeUNLVoteMaxListed_test::run
void run() override
Definition: NegativeUNL_test.cpp:1664
ripple::test::BEAST_DEFINE_TESTSUITE_PRIO
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, ripple, 2)
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::STValidation
Definition: STValidation.h:44
ripple::test::NegativeUNLVoteGoodScore_test::run
void run() override
Definition: NegativeUNL_test.cpp:1575
ripple::NegativeUNLVote::newValidators_
hash_map< NodeID, LedgerIndex > newValidators_
Definition: NegativeUNLVote.h:130
ripple::test::NegativeUNLVoteInternal_test::testAddTx
void testAddTx()
Definition: NegativeUNL_test.cpp:770
ripple::test::NegativeUNLNoAmendment_test
Definition: NegativeUNL_test.cpp:521
ripple::test::createPublicKeys
std::vector< PublicKey > createPublicKeys(std::size_t n)
Create fake public keys.
Definition: NegativeUNL_test.cpp:1981
std::vector::push_back
T push_back(T... args)
ripple::KeyType::ed25519
@ ed25519
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:207
ripple::base_uint< 256 >
ripple::test::NegativeUNLVoteInternal_test::run
void run() override
Definition: NegativeUNL_test.cpp:1396
ripple::NegativeUNLVote::ToDisable
@ ToDisable
Definition: NegativeUNLVote.h:84
ripple::test::negUnlSizeTest
bool negUnlSizeTest(std::shared_ptr< Ledger const > const &l, size_t size, bool hasToDisable, bool hasToReEnable)
Test the size of the negative UNL in a ledger, also test if the ledger has ToDisalbe and/or ToReEnabl...
Definition: NegativeUNL_test.cpp:1907
ripple::ttUNL_MODIFY
@ ttUNL_MODIFY
This system-generated transaction type is used to update the network's negative UNL.
Definition: TxFormats.h:216
ripple::test::NetworkHistory::Parameter::negUNLSize
std::uint32_t negUNLSize
Definition: NegativeUNL_test.cpp:573
ripple::NegativeUNLVote::findAllCandidates
const Candidates findAllCandidates(hash_set< NodeID > const &unl, hash_set< NodeID > const &negUnl, hash_map< NodeID, std::uint32_t > const &scoreTable)
Process the score table and find all disabling and re-enabling candidates.
Definition: NegativeUNLVote.cpp:242
ripple::Validations::add
ValStatus add(NodeID const &nodeID, Validation const &val)
Add a new validation.
Definition: Validations.h:622
ripple::PublicKey
A public key.
Definition: PublicKey.h:61
ripple::derivePublicKey
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
Definition: SecretKey.cpp:313
ripple::NegativeUNLVote::negativeUNLMinLocalValsToVote
static constexpr size_t negativeUNLMinLocalValsToVote
The minimum number of validations of the local node for it to participate in the voting.
Definition: NegativeUNLVote.h:67
ripple::test::NetworkHistory::walkHistoryAndAddValidations
void walkHistoryAndAddValidations(NeedValidation &&needVal)
Walk the ledger history and create validation messages for the ledgers.
Definition: NegativeUNL_test.cpp:697
ripple::Application::config
virtual Config & config()=0
ripple::test::NegativeUNLVoteNewValidator_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1737
ripple::test::NetworkHistory::validations
RCLValidations & validations
Definition: NegativeUNL_test.cpp:726
std::array
STL class.
ripple::test::applyAndTestResult
bool applyAndTestResult(jtx::Env &env, OpenView &view, STTx const &tx, bool pass)
Try to apply a ttUNL_MODIFY Tx, and test the apply result.
Definition: NegativeUNL_test.cpp:1923
std::unordered_map::erase
T erase(T... args)
ripple::test::NetworkHistory::createSTVal
std::shared_ptr< STValidation > createSTVal(std::shared_ptr< Ledger const > const &ledger, NodeID const &v)
Create a validation.
Definition: NegativeUNL_test.cpp:673
ripple::STTx
Definition: STTx.h:46
ripple::test::voteAndCheck
bool voteAndCheck(NetworkHistory &history, NodeID const &myId, std::size_t expect, PreVote const &pre=defaultPreVote)
Create a NegativeUNLVote object.
Definition: NegativeUNL_test.cpp:749
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint32_t
ripple::NegativeUNLVote::buildScoreTable
std::optional< hash_map< NodeID, std::uint32_t > > buildScoreTable(std::shared_ptr< Ledger const > const &prevLedger, hash_set< NodeID > const &unl, RCLValidations &validations)
Build a reliability measurement score table of validators' validation messages in the last flag ledge...
Definition: NegativeUNLVote.cpp:158
ripple::test::NegativeUNLVoteInternal_test::testNewValidators
void testNewValidators()
Definition: NegativeUNL_test.cpp:1337
ripple::tefFAILURE
@ tefFAILURE
Definition: TER.h:163
ripple::test::NegativeUNLVoteInternal_test::testFindAllCandidates
void testFindAllCandidates()
Definition: NegativeUNL_test.cpp:1006
ripple::TimeKeeper::now
time_point now() const override
Returns the current time, using the server's clock.
Definition: TimeKeeper.h:64
ripple::test::NegativeUNLVoteOffline_test
Definition: NegativeUNL_test.cpp:1581
ripple::NegativeUNLVote::addTx
void addTx(LedgerIndex seq, PublicKey const &vp, NegativeUNLModify modify, std::shared_ptr< SHAMap > const &initialSet)
Add a ttUNL_MODIFY Tx to the transaction set.
Definition: NegativeUNLVote.cpp:107
ripple::sfUNLModifyDisabling
const SF_UINT8 sfUNLModifyDisabling
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::NegativeUNLVote::newValidatorDisableSkip
static constexpr size_t newValidatorDisableSkip
We don't want to disable new validators immediately after adding them.
Definition: NegativeUNLVote.h:73
ripple::KeyType::secp256k1
@ secp256k1
ripple::test::NegativeUNLVoteScoreTable_test
Rest the build score table function of NegativeUNLVote.
Definition: NegativeUNL_test.cpp:1412
ripple::randomKeyPair
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Definition: SecretKey.cpp:368
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:33
ripple::test::NegativeUNLVoteInternal_test::testFindAllCandidatesCombination
void testFindAllCandidatesCombination()
Definition: NegativeUNL_test.cpp:1148
ripple::test::NegativeUNLVoteRetiredValidator_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1673
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::NetworkHistory::UNLNodeIDSet
hash_set< NodeID > UNLNodeIDSet
Definition: NegativeUNL_test.cpp:730
ripple::test::NegativeUNLVoteOffline_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1584
ripple::test::NetworkHistory::Parameter::numLedgers
std::optional< int > numLedgers
if not specified, the number of ledgers in the history is calculated from negUNLSize,...
Definition: NegativeUNL_test.cpp:580
ripple::test::NetworkHistory::lastLedger
std::shared_ptr< Ledger const > lastLedger() const
Definition: NegativeUNL_test.cpp:719
ripple::test::NetworkHistory::createNodes
void createNodes()
Definition: NegativeUNL_test.cpp:595
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:113
ripple::test::NegativeUNLVoteFilterValidations_test::testFilterValidations
void testFilterValidations()
Definition: NegativeUNL_test.cpp:1817
ripple::test::NegativeUNLVoteRetiredValidator_test
Definition: NegativeUNL_test.cpp:1670
ripple::test::NegativeUNLVoteInternal_test::checkCandidateSizes
bool checkCandidateSizes(NegativeUNLVote &vote, hash_set< NodeID > const &unl, hash_set< NodeID > const &negUnl, hash_map< NodeID, std::uint32_t > const &scoreTable, std::size_t numDisable, std::size_t numReEnable)
Find all candidates and check if the number of candidates meets expectation.
Definition: NegativeUNL_test.cpp:990
std::unordered_set::begin
T begin(T... args)
ripple::test::NegativeUNLVoteInternal_test::testPickOneCandidate
void testPickOneCandidate()
Definition: NegativeUNL_test.cpp:796
ripple::featureNegativeUNL
const uint256 featureNegativeUNL
std::unordered_set::insert
T insert(T... args)
ripple::create_genesis
const create_genesis_t create_genesis
Definition: Ledger.cpp:62
ripple::NegativeUNLVote::negativeUNLLowWaterMark
static constexpr size_t negativeUNLLowWaterMark
A validator is considered unreliable if its validations is less than negativeUNLLowWaterMark in the l...
Definition: NegativeUNLVote.h:55
ripple::test::NetworkHistory::NetworkHistory
NetworkHistory(beast::unit_test::suite &suite, Parameter const &p)
Definition: NegativeUNL_test.cpp:583
ripple::Application::overlay
virtual Overlay & overlay()=0
ripple::test::NegativeUNLVoteInternal_test
Test the private member functions of NegativeUNLVote.
Definition: NegativeUNL_test.cpp:767
ripple::test::NegativeUNLVoteOffline_test::run
void run() override
Definition: NegativeUNL_test.cpp:1631
ripple::TokenType::NodePublic
@ NodePublic
ripple::Validations< RCLValidationsAdaptor >
ripple::test::countTx
std::size_t countTx(std::shared_ptr< SHAMap > const &txSet)
Count the number of Tx in a TxSet.
Definition: NegativeUNL_test.cpp:1970
std::optional< int >
std::size_t
ripple::NegativeUNLVote::purgeNewValidators
void purgeNewValidators(LedgerIndex seq)
Purge validators that are not new anymore.
Definition: NegativeUNLVote.cpp:334
ripple::test::NegativeUNLVoteMaxListed_test
Definition: NegativeUNL_test.cpp:1637
ripple::test::NetworkHistory::env
jtx::Env env
Definition: NegativeUNL_test.cpp:724
ripple::test::NetworkHistory::Parameter::hasToReEnable
bool hasToReEnable
Definition: NegativeUNL_test.cpp:575
ripple::NegativeUNLVote
Manager to create NegativeUNL votes.
Definition: NegativeUNLVote.h:46
std::unordered_map::end
T end(T... args)
ripple::test::NetworkHistory::UNLNodeIDs
std::vector< NodeID > UNLNodeIDs
Definition: NegativeUNL_test.cpp:729
ripple::test::defaultPreVote
auto defaultPreVote
Definition: NegativeUNL_test.cpp:735
ripple::test::BEAST_DEFINE_TESTSUITE_MANUAL
BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, ripple)
ripple::test::NegativeUNLVoteScoreTable_test::run
void run() override
Definition: NegativeUNL_test.cpp:1500
ripple::NegativeUNLVote::choose
NodeID choose(uint256 const &randomPadData, std::vector< NodeID > const &candidates)
Pick one candidate from a vector of candidates.
Definition: NegativeUNLVote.cpp:139
ripple::test::NegativeUNL_test::run
void run() override
Definition: NegativeUNL_test.cpp:515
ripple::keylet::negativeUNL
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Definition: Indexes.cpp:189
ripple::test::NetworkHistory::param
Parameter param
Definition: NegativeUNL_test.cpp:725
ripple::test::NegativeUNLVoteNewValidator_test
Definition: NegativeUNL_test.cpp:1734
ripple::test::NegativeUNLVoteScoreTable_test::testBuildScoreTableCombination
void testBuildScoreTableCombination()
Definition: NegativeUNL_test.cpp:1415
ripple::test::NetworkHistory::goodHistory
bool goodHistory
Definition: NegativeUNL_test.cpp:732
std::unordered_map
STL class.
ripple::test::NegativeUNL_test
Definition: NegativeUNL_test.cpp:117
ripple::test::NetworkHistory::Parameter::numNodes
std::uint32_t numNodes
Definition: NegativeUNL_test.cpp:572
ripple::sfDisabledValidators
const SField sfDisabledValidators
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:238
ripple::sfPublicKey
const SF_VL sfPublicKey
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::test::NegativeUNLVoteGoodScore_test
Definition: NegativeUNL_test.cpp:1538
ripple::test::NegativeUNL_test::testNegativeUNL
void testNegativeUNL()
Test filling and applying ttUNL_MODIFY Tx, as well as ledger update:
Definition: NegativeUNL_test.cpp:127
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::test::NetworkHistory::UNLKeySet
hash_set< PublicKey > UNLKeySet
Definition: NegativeUNL_test.cpp:728
ripple::randomSecretKey
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
Definition: SecretKey.cpp:281
ripple::test::NegativeUNLVoteNewValidator_test::run
void run() override
Definition: NegativeUNL_test.cpp:1808
ripple::test::NetworkHistory
Utility class for creating validators and ledger history.
Definition: NegativeUNL_test.cpp:562
ripple::test::NetworkHistory::createLedgerHistory
bool createLedgerHistory()
create ledger history and apply needed ttUNL_MODIFY tx at flag ledgers
Definition: NegativeUNL_test.cpp:612
ripple::NegativeUNLVote::newValidators
void newValidators(LedgerIndex seq, hash_set< NodeID > const &nowTrusted)
Notify NegativeUNLVote that new validators are added.
Definition: NegativeUNLVote.cpp:317
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)