37 supportedAmendments.size() ==
41 for (
auto const& [name, vote] : supportedAmendments)
55 fail(
"Unknown VoteBehavior", __FILE__, __LINE__);
75 std::size_t supported = 0, unsupported = 0, retired = 0;
82 BEAST_EXPECT(supportedAmendments.contains(name));
91 fail(
"Unknown AmendmentSupport", __FILE__, __LINE__);
95 BEAST_EXPECT(supported + retired == supportedAmendments.size());
96 BEAST_EXPECT(
allAmendments.size() - unsupported == supportedAmendments.size());
146 testcase(
"No Params, None Enabled");
153 auto jrr = env.rpc(
"feature")[jss::result];
154 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
156 for (
auto const& feature : jrr[jss::features])
158 if (!BEAST_EXPECT(feature.isMember(jss::name)))
162 bool const expectVeto =
164 bool const expectObsolete =
167 feature.isMember(jss::enabled) && !feature[jss::enabled].asBool(),
168 feature[jss::name].asString() +
" enabled");
170 feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
171 (!feature[jss::vetoed].isBool() ||
172 feature[jss::vetoed].asBool() == expectVeto) &&
173 (feature[jss::vetoed].isBool() ||
174 feature[jss::vetoed].asString() ==
"Obsolete"),
175 feature[jss::name].asString() +
" vetoed");
177 feature.isMember(jss::supported) && feature[jss::supported].asBool(),
178 feature[jss::name].asString() +
" supported");
191 auto jrr = env.rpc(
"feature", name)[jss::result];
192 BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status");
193 jrr.removeMember(jss::status);
194 BEAST_EXPECT(jrr.size() == 1);
196 char const sha[] =
"12523DF04B553A0B1AD74F42DDB741DE8DC06A03FC089A0EF197E2A87F1D8107";
197 BEAST_EXPECT(expected == sha);
198 BEAST_EXPECT(jrr.isMember(expected));
199 auto feature = *(jrr.begin());
201 BEAST_EXPECTS(feature[jss::name] == name,
"name");
202 BEAST_EXPECTS(!feature[jss::enabled].asBool(),
"enabled");
203 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
204 BEAST_EXPECTS(feature[jss::supported].asBool(),
"supported");
207 jrr = env.rpc(
"feature",
"fMM")[jss::result];
208 BEAST_EXPECT(jrr[jss::error] ==
"badFeature");
209 BEAST_EXPECT(jrr[jss::error_message] ==
"Feature unknown or invalid.");
212 static constexpr auto kOK63Name = [] {
213 return "123456789012345678901234567890123456789012345678901234567890123";
217 static constexpr auto kBaD64Name = [] {
218 return "1234567890123456789012345678901234567890123456789012345678901234";
222 static constexpr auto kOK31Name = [] {
return "1234567890123456789012345678901"; };
225 static constexpr auto kBaD32Name = [] {
return "12345678901234567890123456789012"; };
228 static constexpr auto kOK33Name = [] {
return "123456789012345678901234567890123"; };
232 static constexpr auto kOkName = [] {
return "AMM_123"; };
236 static constexpr auto kBadName = [] {
return "ΑMM_123"; };
239 static constexpr auto kBadEmoji = [] {
return "🔥"; };
286 auto result = env.rpc(
"feature")[jss::result];
287 BEAST_EXPECT(result.isMember(jss::features));
291 BEAST_EXPECT(result[jss::features].size() >= 50);
292 for (
auto it = result[jss::features].begin(); it != result[jss::features].end(); ++it)
295 (void)
id.parseHex(it.key().asString().c_str());
296 if (!BEAST_EXPECT((*it).isMember(jss::name)))
298 bool const expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
299 bool const expectSupported = env.app().getAmendmentTable().isSupported(
id);
301 (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled,
302 (*it)[jss::name].asString() +
" enabled");
304 (*it).isMember(jss::supported) &&
305 (*it)[jss::supported].asBool() == expectSupported,
306 (*it)[jss::name].asString() +
" supported");
307 BEAST_EXPECT(!(*it).isMember(jss::vetoed));
308 BEAST_EXPECT(!(*it).isMember(jss::majority));
309 BEAST_EXPECT(!(*it).isMember(jss::count));
310 BEAST_EXPECT(!(*it).isMember(jss::validations));
311 BEAST_EXPECT(!(*it).isMember(jss::threshold));
318 params[jss::feature] =
319 "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCD"
321 auto const result = env.rpc(
"json",
"feature",
to_string(params))[jss::result];
322 BEAST_EXPECTS(result[jss::error] ==
"badFeature", result.toStyledString());
323 BEAST_EXPECT(result[jss::error_message] ==
"Feature unknown or invalid.");
328 params[jss::feature] =
329 "93E516234E35E08CA689FA33A6D38E103881F8DCB53023F728C307AA89D515"
332 params[jss::vetoed] =
true;
333 auto const result = env.rpc(
"json",
"feature",
to_string(params))[jss::result];
334 BEAST_EXPECTS(result[jss::error] ==
"noPermission", result[jss::error].asString());
336 result[jss::error_message] ==
"You don't have permission for this command.");
343 testcase(
"No Params, Some Enabled");
350 auto jrr = env.rpc(
"feature")[jss::result];
351 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
353 for (
auto it = jrr[jss::features].begin(); it != jrr[jss::features].end(); ++it)
356 (void)
id.parseHex(it.key().asString().c_str());
357 if (!BEAST_EXPECT((*it).isMember(jss::name)))
359 bool const expectEnabled = env.app().getAmendmentTable().isEnabled(
id);
360 bool const expectSupported = env.app().getAmendmentTable().isSupported(
id);
361 bool const expectVeto =
363 bool const expectObsolete =
366 (*it).isMember(jss::enabled) && (*it)[jss::enabled].asBool() == expectEnabled,
367 (*it)[jss::name].asString() +
" enabled");
371 !(*it).isMember(jss::vetoed), (*it)[jss::name].asString() +
" vetoed");
376 (*it).isMember(jss::vetoed) && (*it)[jss::vetoed].isBool() == !expectObsolete &&
377 (!(*it)[jss::vetoed].isBool() ||
378 (*it)[jss::vetoed].asBool() == expectVeto) &&
379 ((*it)[jss::vetoed].isBool() ||
380 (*it)[jss::vetoed].asString() ==
"Obsolete"),
381 (*it)[jss::name].asString() +
" vetoed");
384 (*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported,
385 (*it)[jss::name].asString() +
" supported");
395 Env env{*
this, envconfig(validator,
"")};
397 auto jrr = env.rpc(
"feature")[jss::result];
398 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
403 for (
auto const& feature : jrr[jss::features])
405 if (!BEAST_EXPECT(feature.isMember(jss::name)))
408 !feature.isMember(jss::majority), feature[jss::name].asString() +
" majority");
409 BEAST_EXPECTS(!feature.isMember(jss::count), feature[jss::name].asString() +
" count");
411 !feature.isMember(jss::threshold), feature[jss::name].asString() +
" threshold");
413 !feature.isMember(jss::validations),
414 feature[jss::name].asString() +
" validations");
415 BEAST_EXPECTS(!feature.isMember(jss::vote), feature[jss::name].asString() +
" vote");
419 if (!BEAST_EXPECT(majorities.empty()))
423 for (
auto i = 0; i <= 256; ++i)
427 if (!majorities.empty())
433 BEAST_EXPECT(majorities.size() >= 2);
436 jrr = env.rpc(
"feature")[jss::result];
437 if (!BEAST_EXPECT(jrr.isMember(jss::features)))
439 for (
auto const& feature : jrr[jss::features])
441 if (!BEAST_EXPECT(feature.isMember(jss::name)))
443 bool const expectVeto =
445 bool const expectObsolete =
448 (expectVeto || expectObsolete) ^ feature.isMember(jss::majority),
449 feature[jss::name].asString() +
" majority");
451 feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
452 (!feature[jss::vetoed].isBool() ||
453 feature[jss::vetoed].asBool() == expectVeto) &&
454 (feature[jss::vetoed].isBool() ||
455 feature[jss::vetoed].asString() ==
"Obsolete"),
456 feature[jss::name].asString() +
" vetoed");
457 BEAST_EXPECTS(feature.isMember(jss::count), feature[jss::name].asString() +
" count");
459 feature.isMember(jss::threshold), feature[jss::name].asString() +
" threshold");
461 feature.isMember(jss::validations), feature[jss::name].asString() +
" validations");
462 BEAST_EXPECT(feature[jss::count] == ((expectVeto || expectObsolete) ? 0 : 1));
463 BEAST_EXPECT(feature[jss::threshold] == 1);
464 BEAST_EXPECT(feature[jss::validations] == 1);
466 expectVeto || expectObsolete || feature[jss::majority] == 2540,
467 "Majority: " + feature[jss::majority].asString());
478 static constexpr char const* kFeatureName =
"fixAMMOverflowOffer";
480 auto jrr = env.rpc(
"feature", kFeatureName)[jss::result];
481 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
483 jrr.removeMember(jss::status);
484 if (!BEAST_EXPECT(jrr.size() == 1))
486 auto feature = *(jrr.begin());
487 BEAST_EXPECTS(feature[jss::name] == kFeatureName,
"name");
488 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
490 jrr = env.rpc(
"feature", kFeatureName,
"reject")[jss::result];
491 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
493 jrr.removeMember(jss::status);
494 if (!BEAST_EXPECT(jrr.size() == 1))
496 feature = *(jrr.begin());
497 BEAST_EXPECTS(feature[jss::name] == kFeatureName,
"name");
498 BEAST_EXPECTS(feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool(),
"vetoed");
500 jrr = env.rpc(
"feature", kFeatureName,
"accept")[jss::result];
501 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
503 jrr.removeMember(jss::status);
504 if (!BEAST_EXPECT(jrr.size() == 1))
506 feature = *(jrr.begin());
507 BEAST_EXPECTS(feature[jss::name] == kFeatureName,
"name");
508 BEAST_EXPECTS(feature[jss::vetoed].isBool() && !feature[jss::vetoed].asBool(),
"vetoed");
511 jrr = env.rpc(
"feature", kFeatureName,
"maybe");
512 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
513 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");
529 if (obsoleteFeature ==
std::end(supportedAmendments))
535 auto const featureName = obsoleteFeature->first;
537 auto jrr = env.rpc(
"feature", featureName)[jss::result];
538 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
540 jrr.removeMember(jss::status);
541 if (!BEAST_EXPECT(jrr.size() == 1))
543 auto feature = *(jrr.begin());
544 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
546 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
549 jrr = env.rpc(
"feature", featureName,
"reject")[jss::result];
550 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
552 jrr.removeMember(jss::status);
553 if (!BEAST_EXPECT(jrr.size() == 1))
555 feature = *(jrr.begin());
556 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
558 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
561 jrr = env.rpc(
"feature", featureName,
"accept")[jss::result];
562 if (!BEAST_EXPECTS(jrr[jss::status] == jss::success,
"status"))
564 jrr.removeMember(jss::status);
565 if (!BEAST_EXPECT(jrr.size() == 1))
567 feature = *(jrr.begin());
568 BEAST_EXPECTS(feature[jss::name] == featureName,
"name");
570 feature[jss::vetoed].isString() && feature[jss::vetoed].asString() ==
"Obsolete",
574 jrr = env.rpc(
"feature", featureName,
"maybe");
575 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
576 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid parameters.");