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>
59 for (
auto const& a : amendments)
82 cfg->section(SECTION_AMENDMENTS) =
84 cfg->section(SECTION_VETO_AMENDMENTS) =
95 result.
reserve(amendments.size());
96 for (
auto const& a : amendments)
129 template <
class Arg,
class... Args>
133 if constexpr (
sizeof...(args) > 0)
138 template <
class Arg,
class... Args>
147 if constexpr (
sizeof...(args) > 0)
151 template <
class Arg,
class... Args>
160 left.reserve(
totalsize(left, right, args...));
172 yes_{
"g",
"i",
"k",
"m",
"o",
"q",
"r",
"s",
"t",
"u"};
201 app, majorityTime, supported, enabled, vetoed,
journal_);
212 return makeTable(env.
app(), majorityTime, supported, enabled, vetoed);
239 testcase(
"Construction");
246 for (
auto const& a :
yes_)
268 testcase(
"Name to ID mapping");
273 for (
auto const& a :
yes_)
282 BEAST_EXPECT(!table->find(a));
284 BEAST_EXPECT(!table->find(a));
291 table->getJson(unsupportedID)[
to_string(unsupportedID)];
292 BEAST_EXPECT(unsupp.
size() == 0);
296 table->veto(unsupportedID);
299 table->getJson(unsupportedID)[
to_string(unsupportedID)];
300 BEAST_EXPECT(unsupp[jss::vetoed].asBool());
311 testcase(
"Bad Config");
321 fail(
"Accepted only amendment ID");
326 e.
what() ==
"Invalid entry '" +
id +
"' in [Test]");
332 test.
append(
id +
" Test Name");
338 fail(
"Accepted extra arguments");
344 "Invalid entry '" +
id +
" Test Name' in [Test]");
350 sid.resize(sid.length() - 1);
353 test.
append(sid +
" Name");
359 fail(
"Accepted short amendment ID");
364 e.
what() ==
"Invalid entry '" + sid +
" Name' in [Test]");
370 sid.resize(sid.length() + 1,
'0');
373 test.
append(sid +
" Name");
379 fail(
"Accepted long amendment ID");
384 e.
what() ==
"Invalid entry '" + sid +
" Name' in [Test]");
390 sid.resize(sid.length() - 1);
394 test.
append(sid +
" Name");
400 fail(
"Accepted non-hex amendment ID");
405 e.
what() ==
"Invalid entry '" + sid +
" Name' in [Test]");
413 testcase(
"enable and veto");
423 for (
uint256 const& a : allEnabled)
424 BEAST_EXPECT(table->enable(a));
427 BEAST_EXPECT(!table->hasUnsupportedEnabled());
433 bool const enabled = table->isEnabled(supportedID);
434 bool const found = allEnabled.find(supportedID) != allEnabled.end();
437 a + (enabled ?
" enabled " :
" disabled ") +
438 (found ?
" found" :
" not found"));
448 for (
uint256 const& a : desired)
449 BEAST_EXPECT(vetoed.
count(a) == 0);
455 BEAST_EXPECT(desired == table->getDesired());
461 BEAST_EXPECT(table->unVeto(unvetoedID));
474 BEAST_EXPECT(table->getDesired().empty());
478 BEAST_EXPECT(!table->hasUnsupportedEnabled());
480 BEAST_EXPECT(table->hasUnsupportedEnabled());
492 trustedValidators.
reserve(num);
493 for (
int i = 0; i < num; ++i)
497 trustedValidators.
insert(back.first);
499 table->trustChanged(trustedValidators);
532 auto const roundTime =
hourTime(hour);
536 validations.
reserve(validators.size());
539 for (
auto const& [pub, sec] : validators)
544 for (
auto const& [hash, nVotes] : votes)
550 field.push_back(hash);
554 auto v = std::make_shared<STValidation>(
572 table.
doVoting(rules, roundTime, enabled, majority, validations);
573 for (
auto const& [hash, action] : actions)
581 if (enabled.
find(hash) != enabled.
end())
582 Throw<std::runtime_error>(
"enabling already enabled");
583 if (majority.
find(hash) == majority.
end())
584 Throw<std::runtime_error>(
"enabling without majority");
586 majority.
erase(hash);
590 if (majority.
find(hash) != majority.
end())
591 Throw<std::runtime_error>(
592 "got majority while having majority");
593 majority[hash] = roundTime;
597 if (majority.
find(hash) == majority.
end())
598 Throw<std::runtime_error>(
599 "lost majority without majority");
600 majority.
erase(hash);
604 Throw<std::runtime_error>(
"unknown action");
613 testcase(
"Vote NO on unknown");
615 auto const testAmendment =
amendmentId(
"TestAmendment");
629 env.current()->rules(),
637 BEAST_EXPECT(ourVotes.
empty());
638 BEAST_EXPECT(enabled.
empty());
639 BEAST_EXPECT(majority.
empty());
644 env.current()->rules(),
652 BEAST_EXPECT(ourVotes.
empty());
653 BEAST_EXPECT(enabled.
empty());
660 env.current()->rules(),
668 BEAST_EXPECT(ourVotes.
empty());
669 BEAST_EXPECT(enabled.
empty());
676 testcase(
"Vote NO on vetoed");
678 auto const testAmendment =
amendmentId(
"vetoedAmendment");
696 env.current()->rules(),
704 BEAST_EXPECT(ourVotes.
empty());
705 BEAST_EXPECT(enabled.
empty());
706 BEAST_EXPECT(majority.
empty());
711 env.current()->rules(),
719 BEAST_EXPECT(ourVotes.
empty());
720 BEAST_EXPECT(enabled.
empty());
725 env.current()->rules(),
733 BEAST_EXPECT(ourVotes.
empty());
734 BEAST_EXPECT(enabled.
empty());
741 testcase(
"voteEnable");
756 env.current()->rules(),
765 BEAST_EXPECT(enabled.
empty());
766 for (
auto const& i :
yes_)
770 for (
auto const& i :
yes_)
775 env.current()->rules(),
784 BEAST_EXPECT(enabled.
empty());
786 for (
auto const& i :
yes_)
791 env.current()->rules(),
803 env.current()->rules(),
812 BEAST_EXPECT(ourVotes.
empty());
813 for (
auto const& i :
yes_)
821 testcase(
"detectMajority");
823 auto const testAmendment =
amendmentId(
"detectMajority");
837 for (
int i = 0; i <= 17; ++i)
842 if ((i > 0) && (i < 17))
846 env.current()->rules(),
858 BEAST_EXPECT(!ourVotes.
empty());
859 BEAST_EXPECT(enabled.
empty());
860 BEAST_EXPECT(majority.
empty());
865 BEAST_EXPECT(!ourVotes.
empty());
866 BEAST_EXPECT(!majority.
empty());
867 BEAST_EXPECT(enabled.
empty());
872 BEAST_EXPECT(!ourVotes.
empty());
873 BEAST_EXPECT(majority.
empty());
874 BEAST_EXPECT(!enabled.
empty());
879 BEAST_EXPECT(ourVotes.
empty());
880 BEAST_EXPECT(majority.
empty());
881 BEAST_EXPECT(!enabled.
empty());
890 testcase(
"lostMajority");
892 auto const testAmendment =
amendmentId(
"lostMajority");
915 env.current()->rules(),
924 BEAST_EXPECT(enabled.
empty());
925 BEAST_EXPECT(!majority.
empty());
928 for (
int i = 1; i < 8; ++i)
934 votes.
emplace_back(testAmendment, validators.size() - i);
937 env.current()->rules(),
949 BEAST_EXPECT(!ourVotes.
empty());
950 BEAST_EXPECT(enabled.
empty());
951 BEAST_EXPECT(!majority.
empty());
956 BEAST_EXPECT(!ourVotes.
empty());
957 BEAST_EXPECT(majority.
empty());
958 BEAST_EXPECT(enabled.
empty());
971 testcase(
"changedUNL");
973 auto const testAmendment =
amendmentId(
"changedUNL");
996 env.current()->rules(),
1005 BEAST_EXPECT(enabled.
empty());
1006 BEAST_EXPECT(majority.
empty());
1014 auto callTrustChanged =
1023 [&trustedValidators](
auto const& val) {
1024 trustedValidators.insert(val.first);
1028 table->trustChanged(trustedValidators);
1032 callTrustChanged(validators, table);
1042 env.current()->rules(),
1051 BEAST_EXPECT(enabled.
empty());
1052 BEAST_EXPECT(!majority.
empty());
1067 env.current()->rules(),
1076 BEAST_EXPECT(enabled.
empty());
1077 BEAST_EXPECT(majority.
empty());
1081 validators.
insert(validators.
begin(), savedValidator);
1083 votes.
front().second = validators.
size() - 2;
1086 env.current()->rules(),
1095 BEAST_EXPECT(enabled.
empty());
1096 BEAST_EXPECT(!majority.
empty());
1103 callTrustChanged(validators, table);
1105 votes.
front().second = validators.
size() - 2;
1108 env.current()->rules(),
1117 BEAST_EXPECT(enabled.
empty());
1118 BEAST_EXPECT(majority.
empty());
1132 testcase(
"validatorFlapping");
1140 for (
int flapRateHours : {23, 25})
1143 auto const testAmendment =
amendmentId(
"validatorFlapping");
1154 decltype(allValidators)
const mostValidators(
1155 allValidators.begin() + 1, allValidators.end());
1156 BEAST_EXPECT(allValidators.size() == mostValidators.size() + 1);
1164 votes.
emplace_back(testAmendment, allValidators.size() - 2);
1166 int delay = flapRateHours;
1168 for (
int hour = 1; hour < (24 * 8); ++hour)
1170 decltype(allValidators)
const& thisHoursValidators =
1171 (delay < flapRateHours) ? mostValidators : allValidators;
1172 delay = delay == flapRateHours ? 0 : delay + 1;
1174 votes.
front().second = thisHoursValidators.size() - 2;
1178 env.current()->rules(),
1181 thisHoursValidators,
1187 if (hour <= (24 * 7) || flapRateHours > 24)
1191 BEAST_EXPECT(enabled.
empty());
1197 bool const expectMajority = (delay <= 24)
1199 : &thisHoursValidators == &allValidators;
1200 BEAST_EXPECT(majority.
empty() != expectMajority);
1208 BEAST_EXPECT(!enabled.
empty());
1209 BEAST_EXPECT(majority.
empty());
1218 testcase(
"hasUnsupportedEnabled");
1220 using namespace std::chrono_literals;
1221 weeks constexpr w(1);
1224 BEAST_EXPECT(!table->hasUnsupportedEnabled());
1225 BEAST_EXPECT(!table->firstUnsupportedExpected());
1226 BEAST_EXPECT(table->needValidatedLedger(1));
1232 [&enabled](
auto const& s) { enabled.insert(amendmentId(s)); });
1235 table->doValidatedLedger(1, enabled, majority);
1236 BEAST_EXPECT(table->hasUnsupportedEnabled());
1237 BEAST_EXPECT(!table->firstUnsupportedExpected());
1243 [&majority, &t](
auto const& s) {
1244 majority[amendmentId(s)] = NetClock::time_point{--t};
1247 table->doValidatedLedger(1, enabled, majority);
1248 BEAST_EXPECT(table->hasUnsupportedEnabled());
1250 table->firstUnsupportedExpected() &&
1254 BEAST_EXPECT(!table->needValidatedLedger(256));
1255 BEAST_EXPECT(table->needValidatedLedger(257));