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;
782  PublicKey toReEnableKey;
783  LedgerIndex seq(1234);
784  BEAST_EXPECT(countTx(txSet) == 0);
785  vote.addTx(seq, toDisableKey, NegativeUNLVote::ToDisable, txSet);
786  BEAST_EXPECT(countTx(txSet) == 1);
787  vote.addTx(seq, toReEnableKey, NegativeUNLVote::ToReEnable, txSet);
788  BEAST_EXPECT(countTx(txSet) == 2);
789  // content of a tx is implicitly tested after applied to a ledger
790  // in later test cases
791  }
792 
793  void
795  {
796  testcase("Pick One Candidate");
797  jtx::Env env(*this);
798 
799  NodeID myId(0xA0);
800  NegativeUNLVote vote(myId, env.journal);
801 
802  uint256 pad_0(0);
803  uint256 pad_f = ~pad_0;
804  NodeID n_1(1);
805  NodeID n_2(2);
806  NodeID n_3(3);
807  std::vector<NodeID> candidates({n_1});
808  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
809  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_1);
810  candidates.emplace_back(2);
811  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
812  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_2);
813  candidates.emplace_back(3);
814  BEAST_EXPECT(vote.choose(pad_0, candidates) == n_1);
815  BEAST_EXPECT(vote.choose(pad_f, candidates) == n_3);
816  }
817 
818  void
820  {
821  testcase("Build Score Table");
822  /*
823  * 1. no skip list
824  * 2. short skip list
825  * 3. local node not enough history
826  * 4. a node double validated some seq
827  * 5. local node had enough validations but on a wrong chain
828  * 6. a good case, long enough history and perfect scores
829  */
830  {
831  // 1. no skip list
832  NetworkHistory history = {*this, {10, 0, false, false, 1}};
833  BEAST_EXPECT(history.goodHistory);
834  if (history.goodHistory)
835  {
836  NegativeUNLVote vote(
837  history.UNLNodeIDs[3], history.env.journal);
838  BEAST_EXPECT(!vote.buildScoreTable(
839  history.lastLedger(),
840  history.UNLNodeIDSet,
841  history.validations));
842  }
843  }
844 
845  {
846  // 2. short skip list
847  NetworkHistory history = {*this, {10, 0, false, false, 256 / 2}};
848  BEAST_EXPECT(history.goodHistory);
849  if (history.goodHistory)
850  {
851  NegativeUNLVote vote(
852  history.UNLNodeIDs[3], history.env.journal);
853  BEAST_EXPECT(!vote.buildScoreTable(
854  history.lastLedger(),
855  history.UNLNodeIDSet,
856  history.validations));
857  }
858  }
859 
860  {
861  // 3. local node not enough history
862  NetworkHistory history = {*this, {10, 0, false, false, 256 + 2}};
863  BEAST_EXPECT(history.goodHistory);
864  if (history.goodHistory)
865  {
866  NodeID myId = history.UNLNodeIDs[3];
868  [&](std::shared_ptr<Ledger const> const& l,
869  std::size_t idx) -> bool {
870  // skip half my validations.
871  return !(
872  history.UNLNodeIDs[idx] == myId &&
873  l->seq() % 2 == 0);
874  });
875  NegativeUNLVote vote(myId, history.env.journal);
876  BEAST_EXPECT(!vote.buildScoreTable(
877  history.lastLedger(),
878  history.UNLNodeIDSet,
879  history.validations));
880  }
881  }
882 
883  {
884  // 4. a node double validated some seq
885  // 5. local node had enough validations but on a wrong chain
886  NetworkHistory history = {*this, {10, 0, false, false, 256 + 2}};
887  // We need two chains for these tests
888  bool wrongChainSuccess = history.goodHistory;
889  BEAST_EXPECT(wrongChainSuccess);
890  NetworkHistory::LedgerHistory wrongChain =
891  std::move(history.history);
892  // Create a new chain and use it as the one that majority of nodes
893  // follow
894  history.createLedgerHistory();
895  BEAST_EXPECT(history.goodHistory);
896 
897  if (history.goodHistory && wrongChainSuccess)
898  {
899  NodeID myId = history.UNLNodeIDs[3];
900  NodeID badNode = history.UNLNodeIDs[4];
902  [&](std::shared_ptr<Ledger const> const& l,
903  std::size_t idx) -> bool {
904  // everyone but me
905  return !(history.UNLNodeIDs[idx] == myId);
906  });
907 
908  // local node validate wrong chain
909  // a node double validates
910  for (auto& l : wrongChain)
911  {
912  RCLValidation v1(history.createSTVal(l, myId));
913  history.validations.add(myId, v1);
914  RCLValidation v2(history.createSTVal(l, badNode));
915  history.validations.add(badNode, v2);
916  }
917 
918  NegativeUNLVote vote(myId, history.env.journal);
919 
920  // local node still on wrong chain, can build a scoreTable,
921  // but all other nodes' scores are zero
922  auto scoreTable = vote.buildScoreTable(
923  wrongChain.back(),
924  history.UNLNodeIDSet,
925  history.validations);
926  BEAST_EXPECT(scoreTable);
927  if (scoreTable)
928  {
929  for (auto const& [n, score] : *scoreTable)
930  {
931  if (n == myId)
932  BEAST_EXPECT(score == 256);
933  else
934  BEAST_EXPECT(score == 0);
935  }
936  }
937 
938  // if local node switched to right history, but cannot build
939  // scoreTable because not enough local validations
940  BEAST_EXPECT(!vote.buildScoreTable(
941  history.lastLedger(),
942  history.UNLNodeIDSet,
943  history.validations));
944  }
945  }
946 
947  {
948  // 6. a good case
949  NetworkHistory history = {*this, {10, 0, false, false, 256 + 1}};
950  BEAST_EXPECT(history.goodHistory);
951  if (history.goodHistory)
952  {
954  [&](std::shared_ptr<Ledger const> const& l,
955  std::size_t idx) -> bool { return true; });
956  NegativeUNLVote vote(
957  history.UNLNodeIDs[3], history.env.journal);
958  auto scoreTable = vote.buildScoreTable(
959  history.lastLedger(),
960  history.UNLNodeIDSet,
961  history.validations);
962  BEAST_EXPECT(scoreTable);
963  if (scoreTable)
964  {
965  for (auto const& [_, score] : *scoreTable)
966  {
967  (void)_;
968  BEAST_EXPECT(score == 256);
969  }
970  }
971  }
972  }
973  }
974 
987  bool
989  NegativeUNLVote& vote,
990  hash_set<NodeID> const& unl,
991  hash_set<NodeID> const& negUnl,
992  hash_map<NodeID, std::uint32_t> const& scoreTable,
993  std::size_t numDisable,
994  std::size_t numReEnable)
995  {
996  auto [disableCandidates, reEnableCandidates] =
997  vote.findAllCandidates(unl, negUnl, scoreTable);
998  bool rightDisable = disableCandidates.size() == numDisable;
999  bool rightReEnable = reEnableCandidates.size() == numReEnable;
1000  return rightDisable && rightReEnable;
1001  };
1002 
1003  void
1005  {
1006  testcase("Find All Candidates");
1007  /*
1008  * -- unl size: 35
1009  * -- negUnl size: 3
1010  *
1011  * 0. all good scores
1012  * 1. all bad scores
1013  * 2. all between watermarks
1014  * 3. 2 good scorers in negUnl
1015  * 4. 2 bad scorers not in negUnl
1016  * 5. 2 in negUnl but not in unl, have a remove candidate from score
1017  * table
1018  * 6. 2 in negUnl but not in unl, no remove candidate from score table
1019  * 7. 2 new validators have good scores, already in negUnl
1020  * 8. 2 new validators have bad scores, not in negUnl
1021  * 9. expired the new validators have bad scores, not in negUnl
1022  */
1023  NetworkHistory history = {*this, {35, 0, false, false, 0}};
1024 
1025  hash_set<NodeID> negUnl_012;
1026  for (std::uint32_t i = 0; i < 3; ++i)
1027  negUnl_012.insert(history.UNLNodeIDs[i]);
1028 
1029  // build a good scoreTable to use, or copy and modify
1030  hash_map<NodeID, std::uint32_t> goodScoreTable;
1031  for (auto const& n : history.UNLNodeIDs)
1032  goodScoreTable[n] = NegativeUNLVote::negativeUNLHighWaterMark + 1;
1033 
1034  NegativeUNLVote vote(history.UNLNodeIDs[0], history.env.journal);
1035 
1036  {
1037  // all good scores
1038  BEAST_EXPECT(checkCandidateSizes(
1039  vote, history.UNLNodeIDSet, negUnl_012, goodScoreTable, 0, 3));
1040  }
1041  {
1042  // all bad scores
1044  for (auto& n : history.UNLNodeIDs)
1045  scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark - 1;
1046  BEAST_EXPECT(checkCandidateSizes(
1047  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 35 - 3, 0));
1048  }
1049  {
1050  // all between watermarks
1052  for (auto& n : history.UNLNodeIDs)
1053  scoreTable[n] = NegativeUNLVote::negativeUNLLowWaterMark + 1;
1054  BEAST_EXPECT(checkCandidateSizes(
1055  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 0));
1056  }
1057 
1058  {
1059  // 2 good scorers in negUnl
1060  auto scoreTable = goodScoreTable;
1061  scoreTable[*negUnl_012.begin()] =
1063  BEAST_EXPECT(checkCandidateSizes(
1064  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 0, 2));
1065  }
1066 
1067  {
1068  // 2 bad scorers not in negUnl
1069  auto scoreTable = goodScoreTable;
1070  scoreTable[history.UNLNodeIDs[11]] =
1072  scoreTable[history.UNLNodeIDs[12]] =
1074  BEAST_EXPECT(checkCandidateSizes(
1075  vote, history.UNLNodeIDSet, negUnl_012, scoreTable, 2, 3));
1076  }
1077 
1078  {
1079  // 2 in negUnl but not in unl, have a remove candidate from score
1080  // table
1081  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1082  UNL_temp.erase(history.UNLNodeIDs[0]);
1083  UNL_temp.erase(history.UNLNodeIDs[1]);
1084  BEAST_EXPECT(checkCandidateSizes(
1085  vote, UNL_temp, negUnl_012, goodScoreTable, 0, 3));
1086  }
1087 
1088  {
1089  // 2 in negUnl but not in unl, no remove candidate from score table
1090  auto scoreTable = goodScoreTable;
1091  scoreTable.erase(history.UNLNodeIDs[0]);
1092  scoreTable.erase(history.UNLNodeIDs[1]);
1093  scoreTable[history.UNLNodeIDs[2]] =
1095  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1096  UNL_temp.erase(history.UNLNodeIDs[0]);
1097  UNL_temp.erase(history.UNLNodeIDs[1]);
1098  BEAST_EXPECT(checkCandidateSizes(
1099  vote, UNL_temp, negUnl_012, scoreTable, 0, 2));
1100  }
1101 
1102  {
1103  // 2 new validators
1104  NodeID new_1(0xbead);
1105  NodeID new_2(0xbeef);
1106  hash_set<NodeID> nowTrusted = {new_1, new_2};
1107  hash_set<NodeID> UNL_temp = history.UNLNodeIDSet;
1108  UNL_temp.insert(new_1);
1109  UNL_temp.insert(new_2);
1110  vote.newValidators(256, nowTrusted);
1111  {
1112  // 2 new validators have good scores, already in negUnl
1113  auto scoreTable = goodScoreTable;
1114  scoreTable[new_1] =
1116  scoreTable[new_2] =
1118  hash_set<NodeID> negUnl_temp = negUnl_012;
1119  negUnl_temp.insert(new_1);
1120  negUnl_temp.insert(new_2);
1121  BEAST_EXPECT(checkCandidateSizes(
1122  vote, UNL_temp, negUnl_temp, scoreTable, 0, 3 + 2));
1123  }
1124  {
1125  // 2 new validators have bad scores, not in negUnl
1126  auto scoreTable = goodScoreTable;
1127  scoreTable[new_1] = 0;
1128  scoreTable[new_2] = 0;
1129  BEAST_EXPECT(checkCandidateSizes(
1130  vote, UNL_temp, negUnl_012, scoreTable, 0, 3));
1131  }
1132  {
1133  // expired the new validators have bad scores, not in negUnl
1134  vote.purgeNewValidators(
1136  auto scoreTable = goodScoreTable;
1137  scoreTable[new_1] = 0;
1138  scoreTable[new_2] = 0;
1139  BEAST_EXPECT(checkCandidateSizes(
1140  vote, UNL_temp, negUnl_012, scoreTable, 2, 3));
1141  }
1142  }
1143  }
1144 
1145  void
1147  {
1148  testcase("Find All Candidates Combination");
1149  /*
1150  * == combination 1:
1151  * -- unl size: 34, 35, 80
1152  * -- nUnl size: 0, 50%, all
1153  * -- score pattern: all 0, all negativeUNLLowWaterMark & +1 & -1, all
1154  * negativeUNLHighWaterMark & +1 & -1, all 100%
1155  *
1156  * == combination 2:
1157  * -- unl size: 34, 35, 80
1158  * -- negativeUNL size: 0, all
1159  * -- nUnl size: one on, one off, one on, one off,
1160  * -- score pattern: 2*(negativeUNLLowWaterMark, +1, -1) &
1161  * 2*(negativeUNLHighWaterMark, +1, -1) & rest
1162  * negativeUNLMinLocalValsToVote
1163  */
1164 
1165  jtx::Env env(*this);
1166 
1167  NodeID myId(0xA0);
1168  NegativeUNLVote vote(myId, env.journal);
1169 
1170  std::array<std::uint32_t, 3> unlSizes = {34, 35, 80};
1171  std::array<std::uint32_t, 3> nUnlPercent = {0, 50, 100};
1172  std::array<std::uint32_t, 8> scores = {
1173  0,
1181 
1182  //== combination 1:
1183  {
1184  auto fillScoreTable =
1185  [&](std::uint32_t unl_size,
1186  std::uint32_t nUnl_size,
1187  std::uint32_t score,
1188  hash_set<NodeID>& unl,
1189  hash_set<NodeID>& negUnl,
1190  hash_map<NodeID, std::uint32_t>& scoreTable) {
1191  std::vector<NodeID> nodeIDs;
1192  std::vector<PublicKey> keys = createPublicKeys(unl_size);
1193  for (auto const& k : keys)
1194  {
1195  nodeIDs.emplace_back(calcNodeID(k));
1196  unl.emplace(nodeIDs.back());
1197  scoreTable[nodeIDs.back()] = score;
1198  }
1199  for (std::uint32_t i = 0; i < nUnl_size; ++i)
1200  negUnl.insert(nodeIDs[i]);
1201  };
1202 
1203  for (auto us : unlSizes)
1204  {
1205  for (auto np : nUnlPercent)
1206  {
1207  for (auto score : scores)
1208  {
1209  hash_set<NodeID> unl;
1210  hash_set<NodeID> negUnl;
1212  fillScoreTable(
1213  us, us * np / 100, score, unl, negUnl, scoreTable);
1214  BEAST_EXPECT(unl.size() == us);
1215  BEAST_EXPECT(negUnl.size() == us * np / 100);
1216  BEAST_EXPECT(scoreTable.size() == us);
1217 
1218  std::size_t toDisable_expect = 0;
1219  std::size_t toReEnable_expect = 0;
1220  if (np == 0)
1221  {
1222  if (score <
1224  {
1225  toDisable_expect = us;
1226  }
1227  }
1228  else if (np == 50)
1229  {
1230  if (score >
1232  {
1233  toReEnable_expect = us * np / 100;
1234  }
1235  }
1236  else
1237  {
1238  if (score >
1240  {
1241  toReEnable_expect = us;
1242  }
1243  }
1244  BEAST_EXPECT(checkCandidateSizes(
1245  vote,
1246  unl,
1247  negUnl,
1248  scoreTable,
1249  toDisable_expect,
1250  toReEnable_expect));
1251  }
1252  }
1253  }
1254 
1255  //== combination 2:
1256  {
1257  auto fillScoreTable =
1258  [&](std::uint32_t unl_size,
1259  std::uint32_t nUnl_percent,
1260  hash_set<NodeID>& unl,
1261  hash_set<NodeID>& negUnl,
1262  hash_map<NodeID, std::uint32_t>& scoreTable) {
1263  std::vector<NodeID> nodeIDs;
1264  std::vector<PublicKey> keys =
1265  createPublicKeys(unl_size);
1266  for (auto const& k : keys)
1267  {
1268  nodeIDs.emplace_back(calcNodeID(k));
1269  unl.emplace(nodeIDs.back());
1270  }
1271 
1272  std::uint32_t nIdx = 0;
1273  for (auto score : scores)
1274  {
1275  scoreTable[nodeIDs[nIdx++]] = score;
1276  scoreTable[nodeIDs[nIdx++]] = score;
1277  }
1278  for (; nIdx < unl_size;)
1279  {
1280  scoreTable[nodeIDs[nIdx++]] = scores.back();
1281  }
1282 
1283  if (nUnl_percent == 100)
1284  {
1285  negUnl = unl;
1286  }
1287  else if (nUnl_percent == 50)
1288  {
1289  for (std::uint32_t i = 1; i < unl_size; i += 2)
1290  negUnl.insert(nodeIDs[i]);
1291  }
1292  };
1293 
1294  for (auto us : unlSizes)
1295  {
1296  for (auto np : nUnlPercent)
1297  {
1298  hash_set<NodeID> unl;
1299  hash_set<NodeID> negUnl;
1301 
1302  fillScoreTable(us, np, unl, negUnl, scoreTable);
1303  BEAST_EXPECT(unl.size() == us);
1304  BEAST_EXPECT(negUnl.size() == us * np / 100);
1305  BEAST_EXPECT(scoreTable.size() == us);
1306 
1307  std::size_t toDisable_expect = 0;
1308  std::size_t toReEnable_expect = 0;
1309  if (np == 0)
1310  {
1311  toDisable_expect = 4;
1312  }
1313  else if (np == 50)
1314  {
1315  toReEnable_expect = negUnl.size() - 6;
1316  }
1317  else
1318  {
1319  toReEnable_expect = negUnl.size() - 12;
1320  }
1321  BEAST_EXPECT(checkCandidateSizes(
1322  vote,
1323  unl,
1324  negUnl,
1325  scoreTable,
1326  toDisable_expect,
1327  toReEnable_expect));
1328  }
1329  }
1330  }
1331  }
1332  }
1333 
1334  void
1336  {
1337  testcase("New Validators");
1338  jtx::Env env(*this);
1339 
1340  NodeID myId(0xA0);
1341  NegativeUNLVote vote(myId, env.journal);
1342 
1343  // test cases:
1344  // newValidators_ of the NegativeUNLVote empty, add one
1345  // add a new one and one already added
1346  // add a new one and some already added
1347  // purge and see some are expired
1348 
1349  NodeID n1(0xA1);
1350  NodeID n2(0xA2);
1351  NodeID n3(0xA3);
1352 
1353  vote.newValidators(2, {n1});
1354  BEAST_EXPECT(vote.newValidators_.size() == 1);
1355  if (vote.newValidators_.size() == 1)
1356  {
1357  BEAST_EXPECT(vote.newValidators_.begin()->first == n1);
1358  BEAST_EXPECT(vote.newValidators_.begin()->second == 2);
1359  }
1360 
1361  vote.newValidators(3, {n1, n2});
1362  BEAST_EXPECT(vote.newValidators_.size() == 2);
1363  if (vote.newValidators_.size() == 2)
1364  {
1365  BEAST_EXPECT(vote.newValidators_[n1] == 2);
1366  BEAST_EXPECT(vote.newValidators_[n2] == 3);
1367  }
1368 
1369  vote.newValidators(
1371  BEAST_EXPECT(vote.newValidators_.size() == 3);
1372  if (vote.newValidators_.size() == 3)
1373  {
1374  BEAST_EXPECT(vote.newValidators_[n1] == 2);
1375  BEAST_EXPECT(vote.newValidators_[n2] == 3);
1376  BEAST_EXPECT(
1377  vote.newValidators_[n3] ==
1379  }
1380 
1382  BEAST_EXPECT(vote.newValidators_.size() == 3);
1384  BEAST_EXPECT(vote.newValidators_.size() == 2);
1386  BEAST_EXPECT(vote.newValidators_.size() == 1);
1387  BEAST_EXPECT(vote.newValidators_.begin()->first == n3);
1388  BEAST_EXPECT(
1389  vote.newValidators_.begin()->second ==
1391  }
1392 
1393  void
1394  run() override
1395  {
1396  testAddTx();
1402  }
1403 };
1404 
1410 class NegativeUNLVoteScoreTable_test : public beast::unit_test::suite
1411 {
1412  void
1414  {
1415  testcase("Build Score Table Combination");
1416  /*
1417  * local node good history, correct scores:
1418  * == combination:
1419  * -- unl size: 10, 34, 35, 50
1420  * -- score pattern: all 0, all 50%, all 100%, two 0% two 50% rest 100%
1421  */
1422  std::array<std::uint32_t, 4> unlSizes = {10, 34, 35, 50};
1423  std::array<std::array<std::uint32_t, 3>, 4> scorePattern = {
1424  {{{0, 0, 0}}, {{50, 50, 50}}, {{100, 100, 100}}, {{0, 50, 100}}}};
1425 
1426  for (auto unlSize : unlSizes)
1427  {
1428  for (std::uint32_t sp = 0; sp < 4; ++sp)
1429  {
1430  NetworkHistory history = {
1431  *this, {unlSize, 0, false, false, 256 + 2}};
1432  BEAST_EXPECT(history.goodHistory);
1433  if (history.goodHistory)
1434  {
1435  NodeID myId = history.UNLNodeIDs[3];
1437  [&](std::shared_ptr<Ledger const> const& l,
1438  std::size_t idx) -> bool {
1439  std::size_t k;
1440  if (idx < 2)
1441  k = 0;
1442  else if (idx < 4)
1443  k = 1;
1444  else
1445  k = 2;
1446 
1447  bool add_50 =
1448  scorePattern[sp][k] == 50 && l->seq() % 2 == 0;
1449  bool add_100 = scorePattern[sp][k] == 100;
1450  bool add_me = history.UNLNodeIDs[idx] == myId;
1451  return add_50 || add_100 || add_me;
1452  });
1453 
1454  NegativeUNLVote vote(myId, history.env.journal);
1455  auto scoreTable = vote.buildScoreTable(
1456  history.lastLedger(),
1457  history.UNLNodeIDSet,
1458  history.validations);
1459  BEAST_EXPECT(scoreTable);
1460  if (scoreTable)
1461  {
1462  std::uint32_t i = 0; // looping unl
1463  auto checkScores = [&](std::uint32_t score,
1464  std::uint32_t k) -> bool {
1465  if (history.UNLNodeIDs[i] == myId)
1466  return score == 256;
1467  if (scorePattern[sp][k] == 0)
1468  return score == 0;
1469  if (scorePattern[sp][k] == 50)
1470  return score == 256 / 2;
1471  if (scorePattern[sp][k] == 100)
1472  return score == 256;
1473  else
1474  return false;
1475  };
1476  for (; i < 2; ++i)
1477  {
1478  BEAST_EXPECT(checkScores(
1479  (*scoreTable)[history.UNLNodeIDs[i]], 0));
1480  }
1481  for (; i < 4; ++i)
1482  {
1483  BEAST_EXPECT(checkScores(
1484  (*scoreTable)[history.UNLNodeIDs[i]], 1));
1485  }
1486  for (; i < unlSize; ++i)
1487  {
1488  BEAST_EXPECT(checkScores(
1489  (*scoreTable)[history.UNLNodeIDs[i]], 2));
1490  }
1491  }
1492  }
1493  }
1494  }
1495  }
1496 
1497  void
1498  run() override
1499  {
1501  }
1502 };
1503 
1504 /*
1505  * Test the doVoting function of NegativeUNLVote.
1506  * The test cases are split to 5 classes for parallel execution.
1507  *
1508  * Voting tests: (use hasToDisable and hasToReEnable in some of the cases)
1509  *
1510  * == all good score, nUnl empty
1511  * -- txSet.size = 0
1512  * == all good score, nUnl not empty (use hasToDisable)
1513  * -- txSet.size = 1
1514  *
1515  * == 2 nodes offline, nUnl empty (use hasToReEnable)
1516  * -- txSet.size = 1
1517  * == 2 nodes offline, in nUnl
1518  * -- txSet.size = 0
1519  *
1520  * == 2 nodes offline, not in nUnl, but maxListed
1521  * -- txSet.size = 0
1522  *
1523  * == 2 nodes offline including me, not in nUnl
1524  * -- txSet.size = 0
1525  * == 2 nodes offline, not in negativeUNL, but I'm not a validator
1526  * -- txSet.size = 0
1527  * == 2 in nUnl, but not in unl, no other remove candidates
1528  * -- txSet.size = 1
1529  *
1530  * == 2 new validators have bad scores
1531  * -- txSet.size = 0
1532  * == 2 expired new validators have bad scores
1533  * -- txSet.size = 1
1534  */
1535 
1536 class NegativeUNLVoteGoodScore_test : public beast::unit_test::suite
1537 {
1538  void
1540  {
1541  testcase("Do Voting");
1542 
1543  {
1544  //== all good score, negativeUNL empty
1545  //-- txSet.size = 0
1546  NetworkHistory history = {*this, {51, 0, false, false, {}}};
1547  BEAST_EXPECT(history.goodHistory);
1548  if (history.goodHistory)
1549  {
1551  [&](std::shared_ptr<Ledger const> const& l,
1552  std::size_t idx) -> bool { return true; });
1553  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0));
1554  }
1555  }
1556 
1557  {
1558  // all good score, negativeUNL not empty (use hasToDisable)
1559  //-- txSet.size = 1
1560  NetworkHistory history = {*this, {37, 0, true, false, {}}};
1561  BEAST_EXPECT(history.goodHistory);
1562  if (history.goodHistory)
1563  {
1565  [&](std::shared_ptr<Ledger const> const& l,
1566  std::size_t idx) -> bool { return true; });
1567  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 1));
1568  }
1569  }
1570  }
1571 
1572  void
1573  run() override
1574  {
1575  testDoVoting();
1576  }
1577 };
1578 
1579 class NegativeUNLVoteOffline_test : public beast::unit_test::suite
1580 {
1581  void
1583  {
1584  testcase("Do Voting");
1585 
1586  {
1587  //== 2 nodes offline, negativeUNL empty (use hasToReEnable)
1588  //-- txSet.size = 1
1589  NetworkHistory history = {*this, {29, 1, false, true, {}}};
1590  BEAST_EXPECT(history.goodHistory);
1591  if (history.goodHistory)
1592  {
1594  [&](std::shared_ptr<Ledger const> const& l,
1595  std::size_t idx) -> bool {
1596  // skip node 0 and node 1
1597  return idx > 1;
1598  });
1599  BEAST_EXPECT(
1600  voteAndCheck(history, history.UNLNodeIDs.back(), 1));
1601  }
1602  }
1603 
1604  {
1605  // 2 nodes offline, in negativeUNL
1606  //-- txSet.size = 0
1607  NetworkHistory history = {*this, {30, 1, true, false, {}}};
1608  BEAST_EXPECT(history.goodHistory);
1609  if (history.goodHistory)
1610  {
1611  NodeID n1 =
1612  calcNodeID(*history.lastLedger()->negativeUNL().begin());
1613  NodeID n2 =
1614  calcNodeID(*history.lastLedger()->validatorToDisable());
1616  [&](std::shared_ptr<Ledger const> const& l,
1617  std::size_t idx) -> bool {
1618  // skip node 0 and node 1
1619  return history.UNLNodeIDs[idx] != n1 &&
1620  history.UNLNodeIDs[idx] != n2;
1621  });
1622  BEAST_EXPECT(
1623  voteAndCheck(history, history.UNLNodeIDs.back(), 0));
1624  }
1625  }
1626  }
1627 
1628  void
1629  run() override
1630  {
1631  testDoVoting();
1632  }
1633 };
1634 
1635 class NegativeUNLVoteMaxListed_test : public beast::unit_test::suite
1636 {
1637  void
1639  {
1640  testcase("Do Voting");
1641 
1642  {
1643  // 2 nodes offline, not in negativeUNL, but maxListed
1644  //-- txSet.size = 0
1645  NetworkHistory history = {*this, {32, 8, true, true, {}}};
1646  BEAST_EXPECT(history.goodHistory);
1647  if (history.goodHistory)
1648  {
1650  [&](std::shared_ptr<Ledger const> const& l,
1651  std::size_t idx) -> bool {
1652  // skip node 0 ~ 10
1653  return idx > 10;
1654  });
1655  BEAST_EXPECT(
1656  voteAndCheck(history, history.UNLNodeIDs.back(), 0));
1657  }
1658  }
1659  }
1660 
1661  void
1662  run() override
1663  {
1664  testDoVoting();
1665  }
1666 };
1667 
1668 class NegativeUNLVoteRetiredValidator_test : public beast::unit_test::suite
1669 {
1670  void
1672  {
1673  testcase("Do Voting");
1674 
1675  {
1676  //== 2 nodes offline including me, not in negativeUNL
1677  //-- txSet.size = 0
1678  NetworkHistory history = {*this, {35, 0, false, false, {}}};
1679  BEAST_EXPECT(history.goodHistory);
1680  if (history.goodHistory)
1681  {
1683  [&](std::shared_ptr<Ledger const> const& l,
1684  std::size_t idx) -> bool { return idx > 1; });
1685  BEAST_EXPECT(voteAndCheck(history, history.UNLNodeIDs[0], 0));
1686  }
1687  }
1688 
1689  {
1690  // 2 nodes offline, not in negativeUNL, but I'm not a validator
1691  //-- txSet.size = 0
1692  NetworkHistory history = {*this, {40, 0, false, false, {}}};
1693  BEAST_EXPECT(history.goodHistory);
1694  if (history.goodHistory)
1695  {
1697  [&](std::shared_ptr<Ledger const> const& l,
1698  std::size_t idx) -> bool { return idx > 1; });
1699  BEAST_EXPECT(voteAndCheck(history, NodeID(0xdeadbeef), 0));
1700  }
1701  }
1702 
1703  {
1704  //== 2 in negativeUNL, but not in unl, no other remove candidates
1705  //-- txSet.size = 1
1706  NetworkHistory history = {*this, {25, 2, false, false, {}}};
1707  BEAST_EXPECT(history.goodHistory);
1708  if (history.goodHistory)
1709  {
1711  [&](std::shared_ptr<Ledger const> const& l,
1712  std::size_t idx) -> bool { return idx > 1; });
1713  BEAST_EXPECT(voteAndCheck(
1714  history,
1715  history.UNLNodeIDs.back(),
1716  1,
1717  [&](NegativeUNLVote& vote) {
1718  history.UNLKeySet.erase(history.UNLKeys[0]);
1719  history.UNLKeySet.erase(history.UNLKeys[1]);
1720  }));
1721  }
1722  }
1723  }
1724 
1725  void
1726  run() override
1727  {
1728  testDoVoting();
1729  }
1730 };
1731 
1732 class NegativeUNLVoteNewValidator_test : public beast::unit_test::suite
1733 {
1734  void
1736  {
1737  testcase("Do Voting");
1738 
1739  {
1740  //== 2 new validators have bad scores
1741  //-- txSet.size = 0
1742  NetworkHistory history = {*this, {15, 0, false, false, {}}};
1743  BEAST_EXPECT(history.goodHistory);
1744  if (history.goodHistory)
1745  {
1747  [&](std::shared_ptr<Ledger const> const& l,
1748  std::size_t idx) -> bool { return true; });
1749  BEAST_EXPECT(voteAndCheck(
1750  history,
1751  history.UNLNodeIDs[0],
1752  0,
1753  [&](NegativeUNLVote& vote) {
1754  auto extra_key_1 =
1755  randomKeyPair(KeyType::ed25519).first;
1756  auto extra_key_2 =
1757  randomKeyPair(KeyType::ed25519).first;
1758  history.UNLKeySet.insert(extra_key_1);
1759  history.UNLKeySet.insert(extra_key_2);
1760  hash_set<NodeID> nowTrusted;
1761  nowTrusted.insert(calcNodeID(extra_key_1));
1762  nowTrusted.insert(calcNodeID(extra_key_2));
1763  vote.newValidators(
1764  history.lastLedger()->seq(), nowTrusted);
1765  }));
1766  }
1767  }
1768 
1769  {
1770  //== 2 expired new validators have bad scores
1771  //-- txSet.size = 1
1772  NetworkHistory history = {
1773  *this,
1774  {21,
1775  0,
1776  false,
1777  false,
1779  BEAST_EXPECT(history.goodHistory);
1780  if (history.goodHistory)
1781  {
1783  [&](std::shared_ptr<Ledger const> const& l,
1784  std::size_t idx) -> bool { return true; });
1785  BEAST_EXPECT(voteAndCheck(
1786  history,
1787  history.UNLNodeIDs[0],
1788  1,
1789  [&](NegativeUNLVote& vote) {
1790  auto extra_key_1 =
1791  randomKeyPair(KeyType::ed25519).first;
1792  auto extra_key_2 =
1793  randomKeyPair(KeyType::ed25519).first;
1794  history.UNLKeySet.insert(extra_key_1);
1795  history.UNLKeySet.insert(extra_key_2);
1796  hash_set<NodeID> nowTrusted;
1797  nowTrusted.insert(calcNodeID(extra_key_1));
1798  nowTrusted.insert(calcNodeID(extra_key_2));
1799  vote.newValidators(256, nowTrusted);
1800  }));
1801  }
1802  }
1803  }
1804 
1805  void
1806  run() override
1807  {
1808  testDoVoting();
1809  }
1810 };
1811 
1812 class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite
1813 {
1814  void
1816  {
1817  testcase("Filter Validations");
1818  jtx::Env env(*this);
1819  auto l = std::make_shared<Ledger>(
1821  env.app().config(),
1823  env.app().getNodeFamily());
1824 
1825  auto createSTVal = [&](std::pair<PublicKey, SecretKey> const& keys) {
1826  return std::make_shared<STValidation>(
1827  env.app().timeKeeper().now(),
1828  keys.first,
1829  keys.second,
1830  calcNodeID(keys.first),
1831  [&](STValidation& v) {
1832  v.setFieldH256(sfLedgerHash, l->info().hash);
1833  v.setFieldU32(sfLedgerSequence, l->seq());
1834  v.setFlag(vfFullValidation);
1835  });
1836  };
1837 
1838  // create keys and validations
1839  std::uint32_t numNodes = 10;
1840  std::uint32_t negUnlSize = 3;
1841  std::vector<std::string> cfgKeys;
1842  hash_set<NodeID> activeValidators;
1843  hash_set<PublicKey> nUnlKeys;
1845  for (int i = 0; i < numNodes; ++i)
1846  {
1847  auto keyPair = randomKeyPair(KeyType::secp256k1);
1848  vals.emplace_back(createSTVal(keyPair));
1849  cfgKeys.push_back(toBase58(TokenType::NodePublic, keyPair.first));
1850  activeValidators.emplace(calcNodeID(keyPair.first));
1851  if (i < negUnlSize)
1852  {
1853  nUnlKeys.insert(keyPair.first);
1854  }
1855  }
1856 
1857  // setup the ValidatorList
1858  auto& validators = env.app().validators();
1859  auto& local = *nUnlKeys.begin();
1860  std::vector<std::string> cfgPublishers;
1861  validators.load(local, cfgKeys, cfgPublishers);
1862  validators.updateTrusted(
1863  activeValidators,
1864  env.timeKeeper().now(),
1865  env.app().getOPs(),
1866  env.app().overlay(),
1867  env.app().getHashRouter());
1868  BEAST_EXPECT(validators.getTrustedMasterKeys().size() == numNodes);
1869  validators.setNegativeUNL(nUnlKeys);
1870  BEAST_EXPECT(validators.getNegativeUNL().size() == negUnlSize);
1871 
1872  // test the filter
1873  BEAST_EXPECT(vals.size() == numNodes);
1874  vals = validators.negativeUNLFilter(std::move(vals));
1875  BEAST_EXPECT(vals.size() == numNodes - negUnlSize);
1876  }
1877 
1878  void
1879  run() override
1880  {
1882  }
1883 };
1884 
1885 BEAST_DEFINE_TESTSUITE(NegativeUNL, ledger, ripple);
1886 BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, ledger, ripple);
1887 
1888 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, ripple);
1889 BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, ripple);
1890 BEAST_DEFINE_TESTSUITE_PRIO(NegativeUNLVoteGoodScore, consensus, ripple, 1);
1891 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteOffline, consensus, ripple);
1892 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteMaxListed, consensus, ripple);
1894  NegativeUNLVoteRetiredValidator,
1895  consensus,
1896  ripple,
1897  1);
1898 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteNewValidator, consensus, ripple);
1899 BEAST_DEFINE_TESTSUITE(NegativeUNLVoteFilterValidations, consensus, ripple);
1900 
1904 bool
1907  size_t size,
1908  bool hasToDisable,
1909  bool hasToReEnable)
1910 {
1911  bool sameSize = l->negativeUNL().size() == size;
1912  bool sameToDisable =
1913  (l->validatorToDisable() != std::nullopt) == hasToDisable;
1914  bool sameToReEnable =
1915  (l->validatorToReEnable() != std::nullopt) == hasToReEnable;
1916 
1917  return sameSize && sameToDisable && sameToReEnable;
1918 }
1919 
1920 bool
1921 applyAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx, bool pass)
1922 {
1923  auto res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
1924  if (pass)
1925  return res.first == tesSUCCESS;
1926  else
1927  return res.first == tefFAILURE || res.first == temDISABLED;
1928 }
1929 
1930 bool
1933  hash_map<PublicKey, std::uint32_t> nUnlLedgerSeq)
1934 {
1935  auto sle = l->read(keylet::negativeUNL());
1936  if (!sle)
1937  return false;
1938  if (!sle->isFieldPresent(sfDisabledValidators))
1939  return false;
1940 
1941  auto const& nUnlData = sle->getFieldArray(sfDisabledValidators);
1942  if (nUnlData.size() != nUnlLedgerSeq.size())
1943  return false;
1944 
1945  for (auto const& n : nUnlData)
1946  {
1947  if (!n.isFieldPresent(sfFirstLedgerSequence) ||
1948  !n.isFieldPresent(sfPublicKey))
1949  return false;
1950 
1951  auto seq = n.getFieldU32(sfFirstLedgerSequence);
1952  auto d = n.getFieldVL(sfPublicKey);
1953  auto s = makeSlice(d);
1954  if (!publicKeyType(s))
1955  return false;
1956  PublicKey pk(s);
1957  auto it = nUnlLedgerSeq.find(pk);
1958  if (it == nUnlLedgerSeq.end())
1959  return false;
1960  if (it->second != seq)
1961  return false;
1962  nUnlLedgerSeq.erase(it);
1963  }
1964  return nUnlLedgerSeq.size() == 0;
1965 }
1966 
1969 {
1970  std::size_t count = 0;
1971  for (auto i = txSet->begin(); i != txSet->end(); ++i)
1972  {
1973  ++count;
1974  }
1975  return count;
1976 };
1977 
1980 {
1982  std::size_t ss = 33;
1983  std::vector<uint8_t> data(ss, 0);
1984  data[0] = 0xED;
1985  for (int i = 0; i < n; ++i)
1986  {
1987  data[1]++;
1988  Slice s(data.data(), ss);
1989  keys.emplace_back(s);
1990  }
1991  return keys;
1992 }
1993 
1994 STTx
1995 createTx(bool disabling, LedgerIndex seq, PublicKey const& txKey)
1996 {
1997  auto fill = [&](auto& obj) {
1998  obj.setFieldU8(sfUNLModifyDisabling, disabling ? 1 : 0);
1999  obj.setFieldU32(sfLedgerSequence, seq);
2000  obj.setFieldVL(sfUNLModifyValidator, txKey);
2001  };
2002  return STTx(ttUNL_MODIFY, fill);
2003 }
2004 
2005 } // namespace test
2006 } // 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:1638
ripple::test::NegativeUNLVoteRetiredValidator_test::run
void run() override
Definition: NegativeUNL_test.cpp:1726
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:1995
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:90
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:819
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:1931
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::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:1539
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:1879
ripple::RCLValidation
Wrapper over STValidation for generic Validation code.
Definition: RCLValidations.h:38
ripple::test::NegativeUNLVoteFilterValidations_test
Definition: NegativeUNL_test.cpp:1812
ripple::test::NegativeUNLNoAmendment_test::testNegativeUNLNoAmendment
void testNegativeUNLNoAmendment()
Definition: NegativeUNL_test.cpp:524
ripple::test::NegativeUNLVoteMaxListed_test::run
void run() override
Definition: NegativeUNL_test.cpp:1662
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:1573
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:1979
std::vector::push_back
T push_back(T... args)
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:1394
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:1905
ripple::ttUNL_MODIFY
@ ttUNL_MODIFY
This system-generated transaction type is used to update the network's negative UNL.
Definition: TxFormats.h:158
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:59
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:1735
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:1921
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:45
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
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:1335
ripple::tefFAILURE
@ tefFAILURE
Definition: TER.h:148
ripple::test::NegativeUNLVoteInternal_test::testFindAllCandidates
void testFindAllCandidates()
Definition: NegativeUNL_test.cpp:1004
ripple::test::NegativeUNLVoteOffline_test
Definition: NegativeUNL_test.cpp:1579
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:1410
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:1146
ripple::test::NegativeUNLVoteRetiredValidator_test::testDoVoting
void testDoVoting()
Definition: NegativeUNL_test.cpp:1671
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:1582
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:112
ripple::test::NegativeUNLVoteFilterValidations_test::testFilterValidations
void testFilterValidations()
Definition: NegativeUNL_test.cpp:1815
ripple::test::NegativeUNLVoteRetiredValidator_test
Definition: NegativeUNL_test.cpp:1668
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:988
std::unordered_set::begin
T begin(T... args)
ripple::test::NegativeUNLVoteInternal_test::testPickOneCandidate
void testPickOneCandidate()
Definition: NegativeUNL_test.cpp:794
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::TimeKeeper::now
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
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:1629
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:1968
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:1635
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::NegativeUNLVoteScoreTable_test::run
void run() override
Definition: NegativeUNL_test.cpp:1498
ripple::test::ManualTimeKeeper::now
time_point now() const override
Returns the estimate of wall time, in network time.
Definition: ManualTimeKeeper.cpp:37
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:179
ripple::test::NetworkHistory::param
Parameter param
Definition: NegativeUNL_test.cpp:725
ripple::test::NegativeUNLVoteNewValidator_test
Definition: NegativeUNL_test.cpp:1732
ripple::test::NegativeUNLVoteScoreTable_test::testBuildScoreTableCombination
void testBuildScoreTableCombination()
Definition: NegativeUNL_test.cpp:1413
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:222
ripple::sfPublicKey
const SF_VL sfPublicKey
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::test::NegativeUNLVoteGoodScore_test
Definition: NegativeUNL_test.cpp:1536
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::BEAST_DEFINE_TESTSUITE_MANUAL
BEAST_DEFINE_TESTSUITE_MANUAL(LedgerReplayerLong, app, ripple)
ripple::test::NetworkHistory::UNLKeySet
hash_set< PublicKey > UNLKeySet
Definition: NegativeUNL_test.cpp:728
ripple::test::NegativeUNLVoteNewValidator_test::run
void run() override
Definition: NegativeUNL_test.cpp:1806
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)