Compare commits

...

10 Commits

Author SHA1 Message Date
Mayukha Vadari
c3f9b69678 Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-02-27 16:41:54 -05:00
Mayukha Vadari
5f0b615a6b Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-02-27 13:44:53 -05:00
Mayukha Vadari
5c243e0d67 Merge remote-tracking branch 'upstream/develop' into copilot/fix-vetoed-type-error 2026-02-26 14:57:08 -05:00
Mayukha Vadari
0bad7f6bbf Merge commit '2c1fad1023' into copilot/fix-vetoed-type-error
# Conflicts:
#	src/test/rpc/Feature_test.cpp
2026-02-26 14:56:39 -05:00
copilot-swe-agent[bot]
029414e374 Add isBool() checks for obsolete field and clarify admin-mode in changelog
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-02-26 17:32:45 +00:00
Mayukha Vadari
b6bb23edb2 Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-02-06 11:43:50 -05:00
Mayukha Vadari
eefb26e9a9 Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-02-03 00:01:51 -05:00
copilot-swe-agent[bot]
710f319cbe Update all test assertions to validate new boolean vetoed and obsolete fields
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:51:42 +00:00
copilot-swe-agent[bot]
3a696131ef Fix amendment vetoed field type - use boolean and add obsolete field
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:45:39 +00:00
copilot-swe-agent[bot]
d1fb93e0cf Initial plan 2026-01-30 15:42:41 +00:00
4 changed files with 63 additions and 25 deletions

View File

@@ -75,6 +75,10 @@ This release contains bug fixes only and no API changes.
[Version 2.5.0](https://github.com/XRPLF/rippled/releases/tag/2.5.0) was released on Jun 24, 2025.
### Breaking changes in 2.5.0
- `feature`: In admin-mode responses, the `vetoed` field is now always a boolean. Disabled obsolete amendments now have `"vetoed": true` and a new `"obsolete": true` field, instead of the previous `"vetoed": "Obsolete"` string value. This change improves type safety for API clients while avoiding changes to non-admin responses.
### Additions and bugfixes in 2.5.0
- `tx`: Added `ctid` field to the response and improved error handling. ([#4738](https://github.com/XRPLF/rippled/pull/4738))

View File

@@ -449,6 +449,7 @@ JSS(node_write_retries); // out: GetCounts
JSS(node_writes_delayed); // out::GetCounts
JSS(nth); // out: RPC server_definitions
JSS(obligations); // out: GatewayBalances
JSS(obsolete); // out: AmendmentTableImpl
JSS(offers); // out: NetworkOPs, AccountOffers, Subscribe
JSS(offer_id); // out: insertNFTokenOfferID
JSS(offline); // in: TransactionSign

View File

@@ -148,12 +148,20 @@ class Feature_test : public beast::unit_test::suite
feature.isMember(jss::enabled) && !feature[jss::enabled].asBool(),
feature[jss::name].asString() + " enabled");
BEAST_EXPECTS(
feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
(!feature[jss::vetoed].isBool() ||
feature[jss::vetoed].asBool() == expectVeto) &&
(feature[jss::vetoed].isBool() ||
feature[jss::vetoed].asString() == "Obsolete"),
feature[jss::name].asString() + " vetoed");
feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool(),
feature[jss::name].asString() + " vetoed is bool");
BEAST_EXPECTS(
feature[jss::vetoed].asBool() == (expectVeto || expectObsolete),
feature[jss::name].asString() + " vetoed value");
if (expectObsolete)
BEAST_EXPECTS(
feature.isMember(jss::obsolete) && feature[jss::obsolete].isBool() &&
feature[jss::obsolete].asBool() == true,
feature[jss::name].asString() + " obsolete");
else
BEAST_EXPECTS(
!feature.isMember(jss::obsolete),
feature[jss::name].asString() + " no obsolete");
BEAST_EXPECTS(
feature.isMember(jss::supported) && feature[jss::supported].asBool(),
feature[jss::name].asString() + " supported");
@@ -253,6 +261,7 @@ class Feature_test : public beast::unit_test::suite
(*it)[jss::supported].asBool() == expectSupported,
(*it)[jss::name].asString() + " supported");
BEAST_EXPECT(!(*it).isMember(jss::vetoed));
BEAST_EXPECT(!(*it).isMember(jss::obsolete));
BEAST_EXPECT(!(*it).isMember(jss::majority));
BEAST_EXPECT(!(*it).isMember(jss::count));
BEAST_EXPECT(!(*it).isMember(jss::validations));
@@ -315,13 +324,23 @@ class Feature_test : public beast::unit_test::suite
BEAST_EXPECTS(
!(*it).isMember(jss::vetoed), (*it)[jss::name].asString() + " vetoed");
else
{
BEAST_EXPECTS(
(*it).isMember(jss::vetoed) && (*it)[jss::vetoed].isBool() == !expectObsolete &&
(!(*it)[jss::vetoed].isBool() ||
(*it)[jss::vetoed].asBool() == expectVeto) &&
((*it)[jss::vetoed].isBool() ||
(*it)[jss::vetoed].asString() == "Obsolete"),
(*it)[jss::name].asString() + " vetoed");
(*it).isMember(jss::vetoed) && (*it)[jss::vetoed].isBool(),
(*it)[jss::name].asString() + " vetoed is bool");
BEAST_EXPECTS(
(*it)[jss::vetoed].asBool() == (expectVeto || expectObsolete),
(*it)[jss::name].asString() + " vetoed value");
if (expectObsolete)
BEAST_EXPECTS(
(*it).isMember(jss::obsolete) && (*it)[jss::obsolete].isBool() &&
(*it)[jss::obsolete].asBool() == true,
(*it)[jss::name].asString() + " obsolete");
else
BEAST_EXPECTS(
!(*it).isMember(jss::obsolete),
(*it)[jss::name].asString() + " no obsolete");
}
BEAST_EXPECTS(
(*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported,
(*it)[jss::name].asString() + " supported");
@@ -389,12 +408,20 @@ class Feature_test : public beast::unit_test::suite
(expectVeto || expectObsolete) ^ feature.isMember(jss::majority),
feature[jss::name].asString() + " majority");
BEAST_EXPECTS(
feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool() == !expectObsolete &&
(!feature[jss::vetoed].isBool() ||
feature[jss::vetoed].asBool() == expectVeto) &&
(feature[jss::vetoed].isBool() ||
feature[jss::vetoed].asString() == "Obsolete"),
feature[jss::name].asString() + " vetoed");
feature.isMember(jss::vetoed) && feature[jss::vetoed].isBool(),
feature[jss::name].asString() + " vetoed is bool");
BEAST_EXPECTS(
feature[jss::vetoed].asBool() == (expectVeto || expectObsolete),
feature[jss::name].asString() + " vetoed value");
if (expectObsolete)
BEAST_EXPECTS(
feature.isMember(jss::obsolete) && feature[jss::obsolete].isBool() &&
feature[jss::obsolete].asBool() == true,
feature[jss::name].asString() + " obsolete");
else
BEAST_EXPECTS(
!feature.isMember(jss::obsolete),
feature[jss::name].asString() + " no obsolete");
BEAST_EXPECTS(feature.isMember(jss::count), feature[jss::name].asString() + " count");
BEAST_EXPECTS(
feature.isMember(jss::threshold), feature[jss::name].asString() + " threshold");
@@ -485,8 +512,9 @@ class Feature_test : public beast::unit_test::suite
auto feature = *(jrr.begin());
BEAST_EXPECTS(feature[jss::name] == featureName, "name");
BEAST_EXPECTS(
feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete",
"vetoed");
feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool() == true, "vetoed");
BEAST_EXPECTS(
feature[jss::obsolete].isBool() && feature[jss::obsolete].asBool() == true, "obsolete");
jrr = env.rpc("feature", featureName, "reject")[jss::result];
if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))
@@ -497,8 +525,9 @@ class Feature_test : public beast::unit_test::suite
feature = *(jrr.begin());
BEAST_EXPECTS(feature[jss::name] == featureName, "name");
BEAST_EXPECTS(
feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete",
"vetoed");
feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool() == true, "vetoed");
BEAST_EXPECTS(
feature[jss::obsolete].isBool() && feature[jss::obsolete].asBool() == true, "obsolete");
jrr = env.rpc("feature", featureName, "accept")[jss::result];
if (!BEAST_EXPECTS(jrr[jss::status] == jss::success, "status"))
@@ -509,8 +538,9 @@ class Feature_test : public beast::unit_test::suite
feature = *(jrr.begin());
BEAST_EXPECTS(feature[jss::name] == featureName, "name");
BEAST_EXPECTS(
feature[jss::vetoed].isString() && feature[jss::vetoed].asString() == "Obsolete",
"vetoed");
feature[jss::vetoed].isBool() && feature[jss::vetoed].asBool() == true, "vetoed");
BEAST_EXPECTS(
feature[jss::obsolete].isBool() && feature[jss::obsolete].asBool() == true, "obsolete");
// anything other than accept or reject is an error
jrr = env.rpc("feature", featureName, "maybe");

View File

@@ -931,7 +931,10 @@ AmendmentTableImpl::injectJson(
if (!fs.enabled && isAdmin)
{
if (fs.vote == AmendmentVote::obsolete)
v[jss::vetoed] = "Obsolete";
{
v[jss::vetoed] = true;
v[jss::obsolete] = true;
}
else
v[jss::vetoed] = fs.vote == AmendmentVote::down;
}