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