Compare commits

...

11 Commits

Author SHA1 Message Date
Mayukha Vadari
e0e52df8fe Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-05-27 16:50:02 -04:00
Mayukha Vadari
14cf4ae1a2 Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-05-15 15:06:14 -04:00
copilot-swe-agent[bot]
ffdb36d098 fix: Restore correct behavior for vetoed/obsolete fields and move changelog to Unreleased
- Only set vetoed and obsolete fields for disabled amendments in admin mode
- Move API changelog entry from 2.5.0 to Unreleased section
- Clarify that both fields are only in admin-mode responses for disabled amendments

Agent-Logs-Url: https://github.com/XRPLF/rippled/sessions/5601e141-f680-49d6-84f4-9dd77a369805

Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-05-15 17:48:31 +00:00
Mayukha Vadari
c5037b0dc6 Merge branch 'develop' into copilot/fix-vetoed-type-error 2026-04-01 16:19:18 -04:00
Mayukha Vadari
ec7039c0e7 update changelog accordingly 2026-03-24 11:55:11 -07:00
Mayukha Vadari
f170f4c2c2 fix tests, improve code 2026-03-24 11:54:02 -07:00
Mayukha Vadari
8719bc19bc fix clang-tidy 2026-03-24 10:19:16 -07:00
Mayukha Vadari
137de6f8a8 add obsolete field to non-admin 2026-03-24 10:18:19 -07:00
copilot-swe-agent[bot]
5bf2674944 Add isBool() checks for obsolete field and clarify admin-mode in changelog
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-03-24 10:17:59 -07:00
copilot-swe-agent[bot]
3e2f6658c6 Update all test assertions to validate new boolean vetoed and obsolete fields
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-03-24 10:17:58 -07:00
copilot-swe-agent[bot]
ee368f7096 Fix amendment vetoed field type - use boolean and add obsolete field
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-03-24 10:16:50 -07:00
4 changed files with 46 additions and 25 deletions

View File

@@ -26,6 +26,10 @@ This version is supported by all `xrpld` versions. For WebSocket and HTTP JSON-R
This section contains changes targeting a future version.
### Breaking changes
- `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. Both `vetoed` and `obsolete` fields are only present in admin-mode responses for disabled amendments.
### Additions
- `ledger_entry`, `account_objects`: The `Delegate` ledger entry now includes an optional `DestinationNode` field, which stores the index into the authorized account's owner directory. This field is present on entries created after bidirectional directory tracking was introduced and may appear in RPC responses for those entries. ([#6681](https://github.com/XRPLF/rippled/pull/6681))

View File

@@ -435,6 +435,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

@@ -166,12 +166,15 @@ 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");
BEAST_EXPECTS(
feature.isMember(jss::obsolete) && feature[jss::obsolete].isBool() &&
feature[jss::obsolete].asBool() == expectObsolete,
feature[jss::name].asString() + " obsolete");
BEAST_EXPECTS(
feature.isMember(jss::supported) && feature[jss::supported].asBool(),
feature[jss::name].asString() + " supported");
@@ -303,6 +306,9 @@ class Feature_test : public beast::unit_test::Suite
(*it).isMember(jss::supported) &&
(*it)[jss::supported].asBool() == expectSupported,
(*it)[jss::name].asString() + " supported");
BEAST_EXPECTS(
(*it).isMember(jss::obsolete) && (*it)[jss::obsolete].isBool(),
(*it)[jss::name].asString() + " unknown obsolete");
BEAST_EXPECT(!(*it).isMember(jss::vetoed));
BEAST_EXPECT(!(*it).isMember(jss::majority));
BEAST_EXPECT(!(*it).isMember(jss::count));
@@ -372,12 +378,15 @@ class Feature_test : public beast::unit_test::Suite
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");
BEAST_EXPECTS(
(*it).isMember(jss::obsolete) && (*it)[jss::obsolete].isBool() &&
(*it)[jss::obsolete].asBool() == expectObsolete,
(*it)[jss::name].asString() + " obsolete");
}
BEAST_EXPECTS(
(*it).isMember(jss::supported) && (*it)[jss::supported].asBool() == expectSupported,
@@ -447,12 +456,15 @@ 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");
BEAST_EXPECTS(
feature.isMember(jss::obsolete) && feature[jss::obsolete].isBool() &&
feature[jss::obsolete].asBool() == expectObsolete,
feature[jss::name].asString() + " obsolete");
BEAST_EXPECTS(feature.isMember(jss::count), feature[jss::name].asString() + " count");
BEAST_EXPECTS(
feature.isMember(jss::threshold), feature[jss::name].asString() + " threshold");
@@ -542,8 +554,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"))
@@ -554,8 +567,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"))
@@ -566,8 +580,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

@@ -957,7 +957,8 @@ AmendmentTableImpl::injectJson(
{
if (fs.vote == AmendmentVote::Obsolete)
{
v[jss::vetoed] = "Obsolete";
v[jss::vetoed] = true;
v[jss::obsolete] = true;
}
else
{