diff --git a/src/ripple/app/misc/AmendmentTable.h b/src/ripple/app/misc/AmendmentTable.h index d7f7c8b26bb..fef13d50ddb 100644 --- a/src/ripple/app/misc/AmendmentTable.h +++ b/src/ripple/app/misc/AmendmentTable.h @@ -81,11 +81,11 @@ class AmendmentTable firstUnsupportedExpected() const = 0; virtual Json::Value - getJson() const = 0; + getJson(bool isAdmin) const = 0; /** Returns a Json::objectValue. */ virtual Json::Value - getJson(uint256 const& amendment) const = 0; + getJson(uint256 const& amendment, bool isAdmin) const = 0; /** Called when a new fully-validated ledger is accepted. */ void diff --git a/src/ripple/app/misc/impl/AmendmentTable.cpp b/src/ripple/app/misc/impl/AmendmentTable.cpp index 8f4f0321992..3a268e574e3 100644 --- a/src/ripple/app/misc/impl/AmendmentTable.cpp +++ b/src/ripple/app/misc/impl/AmendmentTable.cpp @@ -388,6 +388,7 @@ class AmendmentTableImpl final : public AmendmentTable Json::Value& v, uint256 const& amendment, AmendmentState const& state, + bool isAdmin, std::lock_guard const& lock) const; void @@ -428,9 +429,9 @@ class AmendmentTableImpl final : public AmendmentTable firstUnsupportedExpected() const override; Json::Value - getJson() const override; + getJson(bool isAdmin) const override; Json::Value - getJson(uint256 const&) const override; + getJson(uint256 const&, bool isAdmin) const override; bool needValidatedLedger(LedgerIndex seq) const override; @@ -906,13 +907,14 @@ AmendmentTableImpl::injectJson( Json::Value& v, const uint256& id, const AmendmentState& fs, + bool isAdmin, std::lock_guard const&) const { if (!fs.name.empty()) v[jss::name] = fs.name; v[jss::supported] = fs.supported; - if (!fs.enabled) + if (!fs.enabled && isAdmin) { if (fs.vote == AmendmentVote::obsolete) v[jss::vetoed] = "Obsolete"; @@ -921,7 +923,7 @@ AmendmentTableImpl::injectJson( } v[jss::enabled] = fs.enabled; - if (!fs.enabled && lastVote_) + if (!fs.enabled && lastVote_ && isAdmin) { auto const votesTotal = lastVote_->trustedValidations(); auto const votesNeeded = lastVote_->threshold(); @@ -936,7 +938,7 @@ AmendmentTableImpl::injectJson( } Json::Value -AmendmentTableImpl::getJson() const +AmendmentTableImpl::getJson(bool isAdmin) const { Json::Value ret(Json::objectValue); { @@ -947,6 +949,7 @@ AmendmentTableImpl::getJson() const ret[to_string(e.first)] = Json::objectValue, e.first, e.second, + isAdmin, lock); } } @@ -954,7 +957,7 @@ AmendmentTableImpl::getJson() const } Json::Value -AmendmentTableImpl::getJson(uint256 const& amendmentID) const +AmendmentTableImpl::getJson(uint256 const& amendmentID, bool isAdmin) const { Json::Value ret = Json::objectValue; Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue); @@ -963,7 +966,7 @@ AmendmentTableImpl::getJson(uint256 const& amendmentID) const std::lock_guard lock(mutex_); AmendmentState const* a = get(amendmentID, lock); if (a) - injectJson(jAmendment, amendmentID, *a, lock); + injectJson(jAmendment, amendmentID, *a, isAdmin, lock); } return ret; diff --git a/src/ripple/rpc/handlers/Feature1.cpp b/src/ripple/rpc/handlers/Feature1.cpp index 482c1b33b00..a67f8156896 100644 --- a/src/ripple/rpc/handlers/Feature1.cpp +++ b/src/ripple/rpc/handlers/Feature1.cpp @@ -38,28 +38,7 @@ doFeature(RPC::JsonContext& context) if (context.app.config().reporting()) return rpcError(rpcREPORTING_UNSUPPORTED); - if (context.role != Role::ADMIN) - { - if (!context.params.isMember(jss::feature)) - { - return RPC::missing_field_error(jss::feature); - } - std::string const& featureStr = context.params[jss::feature].asString(); - uint256 feature; - if (!feature.parseHex(featureStr)) - { - return rpcError(rpcBAD_FEATURE); - } - std::string const& featureName = featureToName(feature); - if (featureName == featureStr) - { - return rpcError(rpcBAD_FEATURE); - } - Json::Value jvReply = Json::objectValue; - jvReply[jss::feature] = featureName; - return jvReply; - } - + bool const isAdmin = context.role == Role::ADMIN; // Get majority amendment status majorityAmendments_t majorities; @@ -70,12 +49,15 @@ doFeature(RPC::JsonContext& context) if (!context.params.isMember(jss::feature)) { - auto features = table.getJson(); + auto features = table.getJson(isAdmin); - for (auto const& [h, t] : majorities) + if (isAdmin) { - features[to_string(h)][jss::majority] = - t.time_since_epoch().count(); + for (auto const& [h, t] : majorities) + { + features[to_string(h)][jss::majority] = + t.time_since_epoch().count(); + } } Json::Value jvReply = Json::objectValue; @@ -90,6 +72,10 @@ doFeature(RPC::JsonContext& context) if (!feature && !feature.parseHex(context.params[jss::feature].asString())) return rpcError(rpcBAD_FEATURE); + if (!isAdmin && context.params.isMember(jss::vetoed)) + { + return rpcFORBIDDEN; + } if (context.params.isMember(jss::vetoed)) { if (context.params[jss::vetoed].asBool()) @@ -98,7 +84,11 @@ doFeature(RPC::JsonContext& context) table.unVeto(feature); } - Json::Value jvReply = table.getJson(feature); + Json::Value jvReply = table.getJson(feature, isAdmin); + if (!isAdmin) + { + return jvReply; + } auto m = majorities.find(feature); if (m != majorities.end()) diff --git a/src/test/app/AmendmentTable_test.cpp b/src/test/app/AmendmentTable_test.cpp index 64e6a038653..24145431eba 100644 --- a/src/test/app/AmendmentTable_test.cpp +++ b/src/test/app/AmendmentTable_test.cpp @@ -288,7 +288,7 @@ class AmendmentTable_test final : public beast::unit_test::suite uint256 const unsupportedID = amendmentId(unsupported_[0]); { Json::Value const unsupp = - table->getJson(unsupportedID)[to_string(unsupportedID)]; + table->getJson(unsupportedID, true)[to_string(unsupportedID)]; BEAST_EXPECT(unsupp.size() == 0); } @@ -296,7 +296,7 @@ class AmendmentTable_test final : public beast::unit_test::suite table->veto(unsupportedID); { Json::Value const unsupp = - table->getJson(unsupportedID)[to_string(unsupportedID)]; + table->getJson(unsupportedID, true)[to_string(unsupportedID)]; BEAST_EXPECT(unsupp[jss::vetoed].asBool()); } }