20 #include <ripple/app/misc/AmendmentTable.h>
21 #include <ripple/basics/BasicConfig.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/basics/chrono.h>
24 #include <ripple/beast/unit_test.h>
25 #include <ripple/core/ConfigSections.h>
26 #include <ripple/protocol/Feature.h>
27 #include <ripple/protocol/PublicKey.h>
28 #include <ripple/protocol/STValidation.h>
29 #include <ripple/protocol/SecretKey.h>
30 #include <ripple/protocol/TxFlags.h>
31 #include <ripple/protocol/digest.h>
32 #include <ripple/protocol/jss.h>
33 #include <test/jtx/Env.h>
34 #include <test/unit_test/SuiteJournal.h>
57 for (
auto const& a : amendments)
75 "a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
76 "l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u"};
78 enabled_{
"b",
"d",
"f",
"h",
"j",
"l",
"n",
"p"};
100 majorityTime, supported, enabled, vetoed,
journal);
116 testcase(
"Construction");
141 testcase(
"Name to ID mapping");
153 BEAST_EXPECT(!table->find(a));
155 BEAST_EXPECT(!table->find(a));
162 table->getJson(unsupportedID)[
to_string(unsupportedID)];
163 BEAST_EXPECT(unsupp.
size() == 0);
167 table->veto(unsupportedID);
170 table->getJson(unsupportedID)[
to_string(unsupportedID)];
171 BEAST_EXPECT(unsupp[jss::vetoed].asBool());
181 testcase(
"Bad Config");
190 fail(
"Accepted only amendment ID");
200 test.
append(
id +
" Test Name");
205 fail(
"Accepted extra arguments");
215 sid.resize(sid.length() - 1);
218 test.
append(sid +
" Name");
223 fail(
"Accepted short amendment ID");
233 sid.resize(sid.length() + 1,
'0');
236 test.
append(sid +
" Name");
241 fail(
"Accepted long amendment ID");
251 sid.resize(sid.length() - 1);
255 test.
append(sid +
" Name");
260 fail(
"Accepted non-hex amendment ID");
272 testcase(
"enable and veto");
288 for (
uint256 const& a : lateEnabled)
292 BEAST_EXPECT(!table->hasUnsupportedEnabled());
295 allEnabled.
insert(lateEnabled.begin(), lateEnabled.end());
300 table->isEnabled(supportedID) ==
301 (allEnabled.
find(supportedID) != allEnabled.
end()));
311 for (
uint256 const& a : desired)
312 BEAST_EXPECT(vetoed.
count(a) == 0);
318 BEAST_EXPECT(desired == table->getDesired());
324 table->unVeto(unvetoedID);
337 BEAST_EXPECT(table->getDesired().empty());
341 BEAST_EXPECT(!table->hasUnsupportedEnabled());
343 BEAST_EXPECT(table->hasUnsupportedEnabled());
352 for (
int i = 0; i < num; ++i)
388 auto const roundTime =
weekTime(week);
392 validations.
reserve(validators.size());
395 for (
auto const& [pub, sec] : validators)
400 for (
auto const& [hash, nVotes] : votes)
405 field.push_back(hash);
409 auto v = std::make_shared<STValidation>(
427 Rules({feat}), roundTime, enabled, majority, validations);
428 for (
auto const& [hash, action] : actions)
436 if (enabled.
find(hash) != enabled.
end())
437 Throw<std::runtime_error>(
"enabling already enabled");
438 if (majority.
find(hash) == majority.
end())
439 Throw<std::runtime_error>(
"enabling without majority");
441 majority.
erase(hash);
445 if (majority.
find(hash) != majority.
end())
446 Throw<std::runtime_error>(
447 "got majority while having majority");
448 majority[hash] = roundTime;
452 if (majority.
find(hash) == majority.
end())
453 Throw<std::runtime_error>(
454 "lost majority without majority");
455 majority.
erase(hash);
459 Throw<std::runtime_error>(
"unknown action");
468 testcase(
"Vote NO on unknown");
470 auto const testAmendment =
amendmentId(
"TestAmendment");
490 BEAST_EXPECT(ourVotes.empty());
491 BEAST_EXPECT(enabled.empty());
492 BEAST_EXPECT(majority.
empty());
494 votes.emplace_back(testAmendment, validators.size());
505 BEAST_EXPECT(ourVotes.empty());
506 BEAST_EXPECT(enabled.empty());
521 BEAST_EXPECT(ourVotes.empty());
522 BEAST_EXPECT(enabled.empty());
529 testcase(
"Vote NO on vetoed");
531 auto const testAmendment =
amendmentId(
"vetoedAmendment");
552 BEAST_EXPECT(ourVotes.empty());
553 BEAST_EXPECT(enabled.empty());
554 BEAST_EXPECT(majority.
empty());
556 votes.emplace_back(testAmendment, validators.size());
567 BEAST_EXPECT(ourVotes.empty());
568 BEAST_EXPECT(enabled.empty());
581 BEAST_EXPECT(ourVotes.empty());
582 BEAST_EXPECT(enabled.empty());
589 testcase(
"voteEnable");
611 BEAST_EXPECT(enabled.empty());
630 BEAST_EXPECT(enabled.empty());
658 BEAST_EXPECT(ourVotes.empty());
667 testcase(
"detectMajority");
669 auto const testAmendment =
amendmentId(
"detectMajority");
678 for (
int i = 0; i <= 17; ++i)
683 if ((i > 0) && (i < 17))
699 BEAST_EXPECT(!ourVotes.empty());
700 BEAST_EXPECT(enabled.empty());
701 BEAST_EXPECT(majority.
empty());
706 BEAST_EXPECT(!ourVotes.empty());
707 BEAST_EXPECT(!majority.
empty());
708 BEAST_EXPECT(enabled.empty());
713 BEAST_EXPECT(!ourVotes.empty());
714 BEAST_EXPECT(majority.
empty());
715 BEAST_EXPECT(!enabled.empty());
720 BEAST_EXPECT(ourVotes.empty());
721 BEAST_EXPECT(majority.
empty());
722 BEAST_EXPECT(!enabled.empty());
731 testcase(
"lostMajority");
733 auto const testAmendment =
amendmentId(
"lostMajority");
759 BEAST_EXPECT(enabled.empty());
760 BEAST_EXPECT(!majority.
empty());
763 for (
int i = 1; i < 8; ++i)
769 votes.
emplace_back(testAmendment, validators.size() - i);
784 BEAST_EXPECT(!ourVotes.empty());
785 BEAST_EXPECT(enabled.empty());
786 BEAST_EXPECT(!majority.
empty());
791 BEAST_EXPECT(!ourVotes.empty());
792 BEAST_EXPECT(majority.
empty());
793 BEAST_EXPECT(enabled.empty());
801 testcase(
"hasUnsupportedEnabled");
806 using namespace std::chrono_literals;
807 weeks constexpr w(1);
809 BEAST_EXPECT(!table->hasUnsupportedEnabled());
810 BEAST_EXPECT(!table->firstUnsupportedExpected());
811 BEAST_EXPECT(table->needValidatedLedger(1));
817 [&enabled](
auto const& s) { enabled.insert(amendmentId(s)); });
820 table->doValidatedLedger(1, enabled, majority);
821 BEAST_EXPECT(table->hasUnsupportedEnabled());
822 BEAST_EXPECT(!table->firstUnsupportedExpected());
828 [&majority, &t](
auto const& s) {
829 majority[amendmentId(s)] = NetClock::time_point{--t};
832 table->doValidatedLedger(1, enabled, majority);
833 BEAST_EXPECT(table->hasUnsupportedEnabled());
835 table->firstUnsupportedExpected() &&
839 BEAST_EXPECT(!table->needValidatedLedger(256));
840 BEAST_EXPECT(table->needValidatedLedger(257));