Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse flags in account_info method #4459

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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},
intelliot marked this conversation as resolved.
Show resolved Hide resolved
{"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