Skip to content

Commit

Permalink
Add account flags to account_info response: (#4459)
Browse files Browse the repository at this point in the history
Previously, the object `account_data` in the `account_info` response
contained a single field `Flags` that contains flags of an account. API
consumers must perform bitwise operations on this field to retrieve the
account flags.

This change adds a new object, `account_flags`, at the top level of the
`account_info` response `result`. The object contains relevant flags of
the account. This makes it easier to write simple code to check a flag's
value.

The flags included may depend on the amendments that are enabled.

Fix #2457.
  • Loading branch information
drlongle authored Mar 30, 2023
1 parent 8bfdbcb commit 5ebcaf0
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/ripple/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ JSS(account); // in/out: many
JSS(accountState); // out: LedgerToJson
JSS(accountTreeHash); // out: ledger/Ledger.cpp
JSS(account_data); // out: AccountInfo
JSS(account_flags); // out: AccountInfo
JSS(account_hash); // out: LedgerToJson
JSS(account_id); // out: WalletPropose
JSS(account_nfts); // out: AccountNFTs
Expand Down
33 changes: 33 additions & 0 deletions src/ripple/rpc/handlers/AccountInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ doAccountInfo(RPC::JsonContext& context)
if (jvAccepted)
return jvAccepted;

static constexpr std::
array<std::pair<std::string_view, LedgerSpecificFlags>, 9>
lsFlags{
{{"defaultRipple", lsfDefaultRipple},
{"depositAuth", lsfDepositAuth},
{"disableMasterKey", lsfDisableMaster},
{"disallowIncomingXRP", lsfDisallowXRP},
{"globalFreeze", lsfGlobalFreeze},
{"noFreeze", lsfNoFreeze},
{"passwordSpent", lsfPasswordSpent},
{"requireAuthorization", lsfRequireAuth},
{"requireDestinationTag", lsfRequireDestTag}}};

static constexpr std::
array<std::pair<std::string_view, LedgerSpecificFlags>, 4>
disallowIncomingFlags{
{{"disallowIncomingNFTokenOffer",
lsfDisallowIncomingNFTokenOffer},
{"disallowIncomingCheck", lsfDisallowIncomingCheck},
{"disallowIncomingPayChan", lsfDisallowIncomingPayChan},
{"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}};

auto const sleAccepted = ledger->read(keylet::account(accountID));
if (sleAccepted)
{
Expand All @@ -94,6 +116,17 @@ doAccountInfo(RPC::JsonContext& context)
RPC::injectSLE(jvAccepted, *sleAccepted);
result[jss::account_data] = jvAccepted;

Json::Value acctFlags{Json::objectValue};
for (auto const& lsf : lsFlags)
acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);

if (ledger->rules().enabled(featureDisallowIncoming))
{
for (auto const& lsf : disallowIncomingFlags)
acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second);
}
result[jss::account_flags] = std::move(acctFlags);

// Return SignerList(s) if that is requested.
if (params.isMember(jss::signer_lists) &&
params[jss::signer_lists].asBool())
Expand Down
101 changes: 100 additions & 1 deletion src/test/rpc/AccountInfo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class AccountInfo_test : public beast::unit_test::suite
"Missing field 'account'.");
}
{
// account_info with a malformed account sting.
// account_info with a malformed account string.
auto const info = env.rpc(
"json",
"account_info",
Expand Down Expand Up @@ -491,13 +491,112 @@ class AccountInfo_test : public beast::unit_test::suite
}
}

void
testAccountFlags(FeatureBitset const& features)
{
using namespace jtx;

Env env(*this, features);
Account const alice{"alice"};
env.fund(XRP(1000), alice);

auto getAccountFlag = [&env, &alice](std::string_view fName) {
auto const info = env.rpc(
"json",
"account_info",
R"({"account" : ")" + alice.human() + R"("})");

std::optional<bool> res;
if (info[jss::result][jss::status] == "success" &&
info[jss::result][jss::account_flags].isMember(fName.data()))
res.emplace(info[jss::result][jss::account_flags][fName.data()]
.asBool());

return res;
};

static constexpr std::
array<std::pair<std::string_view, std::uint32_t>, 7>
asFlags{
{{"defaultRipple", asfDefaultRipple},
{"depositAuth", asfDepositAuth},
{"disallowIncomingXRP", asfDisallowXRP},
{"globalFreeze", asfGlobalFreeze},
{"noFreeze", asfNoFreeze},
{"requireAuthorization", asfRequireAuth},
{"requireDestinationTag", asfRequireDest}}};

for (auto& asf : asFlags)
{
// Clear a flag and check that account_info returns results
// as expected
env(fclear(alice, asf.second));
env.close();
auto const f1 = getAccountFlag(asf.first);
BEAST_EXPECT(f1.has_value());
BEAST_EXPECT(!f1.value());

// Set a flag and check that account_info returns results
// as expected
env(fset(alice, asf.second));
env.close();
auto const f2 = getAccountFlag(asf.first);
BEAST_EXPECT(f2.has_value());
BEAST_EXPECT(f2.value());
}

static constexpr std::
array<std::pair<std::string_view, std::uint32_t>, 4>
disallowIncomingFlags{
{{"disallowIncomingCheck", asfDisallowIncomingCheck},
{"disallowIncomingNFTokenOffer",
asfDisallowIncomingNFTokenOffer},
{"disallowIncomingPayChan", asfDisallowIncomingPayChan},
{"disallowIncomingTrustline",
asfDisallowIncomingTrustline}}};

if (features[featureDisallowIncoming])
{
for (auto& asf : disallowIncomingFlags)
{
// Clear a flag and check that account_info returns results
// as expected
env(fclear(alice, asf.second));
env.close();
auto const f1 = getAccountFlag(asf.first);
BEAST_EXPECT(f1.has_value());
BEAST_EXPECT(!f1.value());

// Set a flag and check that account_info returns results
// as expected
env(fset(alice, asf.second));
env.close();
auto const f2 = getAccountFlag(asf.first);
BEAST_EXPECT(f2.has_value());
BEAST_EXPECT(f2.value());
}
}
else
{
for (auto& asf : disallowIncomingFlags)
{
BEAST_EXPECT(!getAccountFlag(asf.first));
}
}
}

void
run() override
{
testErrors();
testSignerLists();
testSignerListsApiVersion2();
testSignerListsV2();

FeatureBitset const allFeatures{
ripple::test::jtx::supported_amendments()};
testAccountFlags(allFeatures);
testAccountFlags(allFeatures - featureDisallowIncoming);
}
};

Expand Down

0 comments on commit 5ebcaf0

Please sign in to comment.