From 6fe82114a558a850dda651235898fd6129d7b6da Mon Sep 17 00:00:00 2001 From: Long Le Date: Mon, 13 Mar 2023 12:05:20 +0100 Subject: [PATCH 1/4] Parse flags in account_info method (#2457) --- src/ripple/protocol/jss.h | 1 + src/ripple/rpc/handlers/AccountInfo.cpp | 18 ++++++++ src/test/rpc/AccountInfo_test.cpp | 57 ++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index 1c5bf8463b0..3932349c82a 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -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 diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index f08805761ee..c0389c05b67 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -77,6 +77,19 @@ doAccountInfo(RPC::JsonContext& context) if (jvAccepted) return jvAccepted; + static constexpr std:: + array, 9> + lsFlags{ + {{"defaultRipple", lsfDefaultRipple}, + {"depositAuth", lsfDepositAuth}, + {"disableMasterKey", lsfDisableMaster}, + {"disallowIncomingXRP", lsfDisallowXRP}, + {"globalFreeze", lsfGlobalFreeze}, + {"noFreeze", lsfNoFreeze}, + {"passwordSpent", lsfPasswordSpent}, + {"requireAuthorization", lsfRequireAuth}, + {"requireDestinationTag", lsfRequireDestTag}}}; + auto const sleAccepted = ledger->read(keylet::account(accountID)); if (sleAccepted) { @@ -94,6 +107,11 @@ 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); + 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()) diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 9772a0ffb70..34c0cac190a 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -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", @@ -491,6 +491,60 @@ class AccountInfo_test : public beast::unit_test::suite } } + void + testAccountFlags() + { + using namespace jtx; + Env env(*this); + 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 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, 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 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 f2 = getAccountFlag(asf.first); + BEAST_EXPECT(f2.has_value()); + BEAST_EXPECT(f2.value()); + } + } + void run() override { @@ -498,6 +552,7 @@ class AccountInfo_test : public beast::unit_test::suite testSignerLists(); testSignerListsApiVersion2(); testSignerListsV2(); + testAccountFlags(); } }; From 8db58e365961e237f83bbe6c68ddf4791af39659 Mon Sep 17 00:00:00 2001 From: Long Le Date: Tue, 14 Mar 2023 11:37:45 +0100 Subject: [PATCH 2/4] Add support for DisallowIncoming flags --- src/ripple/rpc/handlers/AccountInfo.cpp | 7 ++++++- src/test/rpc/AccountInfo_test.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index c0389c05b67..a3c774adb09 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -78,12 +78,17 @@ doAccountInfo(RPC::JsonContext& context) return jvAccepted; static constexpr std:: - array, 9> + array, 13> lsFlags{ {{"defaultRipple", lsfDefaultRipple}, {"depositAuth", lsfDepositAuth}, {"disableMasterKey", lsfDisableMaster}, {"disallowIncomingXRP", lsfDisallowXRP}, + {"disallowIncomingNFTokenOffer", + lsfDisallowIncomingNFTokenOffer}, + {"disallowIncomingCheck", lsfDisallowIncomingCheck}, + {"disallowIncomingPayChan", lsfDisallowIncomingPayChan}, + {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}, {"globalFreeze", lsfGlobalFreeze}, {"noFreeze", lsfNoFreeze}, {"passwordSpent", lsfPasswordSpent}, diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 34c0cac190a..2ef467f7116 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -515,10 +515,16 @@ class AccountInfo_test : public beast::unit_test::suite }; static constexpr std:: - array, 7> + array, 11> asFlags{ {{"defaultRipple", asfDefaultRipple}, {"depositAuth", asfDepositAuth}, + {"disallowIncomingCheck", asfDisallowIncomingCheck}, + {"disallowIncomingNFTokenOffer", + asfDisallowIncomingNFTokenOffer}, + {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, + {"disallowIncomingTrustline", + asfDisallowIncomingTrustline}, {"disallowIncomingXRP", asfDisallowXRP}, {"globalFreeze", asfGlobalFreeze}, {"noFreeze", asfNoFreeze}, From 7bc8f480d0c99f80590f96369354ee4143aefee0 Mon Sep 17 00:00:00 2001 From: Long Le Date: Mon, 20 Mar 2023 17:29:29 +0100 Subject: [PATCH 3/4] Return DisallowIncoming flags only when the amendment is enabled --- src/ripple/rpc/handlers/AccountInfo.cpp | 24 +++++++--- src/test/rpc/AccountInfo_test.cpp | 64 ++++++++++++++++++++----- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index a3c774adb09..61c82508482 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -78,23 +78,27 @@ doAccountInfo(RPC::JsonContext& context) return jvAccepted; static constexpr std:: - array, 13> + array, 8> lsFlags{ {{"defaultRipple", lsfDefaultRipple}, {"depositAuth", lsfDepositAuth}, {"disableMasterKey", lsfDisableMaster}, - {"disallowIncomingXRP", lsfDisallowXRP}, - {"disallowIncomingNFTokenOffer", - lsfDisallowIncomingNFTokenOffer}, - {"disallowIncomingCheck", lsfDisallowIncomingCheck}, - {"disallowIncomingPayChan", lsfDisallowIncomingPayChan}, - {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}, {"globalFreeze", lsfGlobalFreeze}, {"noFreeze", lsfNoFreeze}, {"passwordSpent", lsfPasswordSpent}, {"requireAuthorization", lsfRequireAuth}, {"requireDestinationTag", lsfRequireDestTag}}}; + static constexpr std:: + array, 5> + disallowIncomingFlags{ + {{"disallowIncomingXRP", lsfDisallowXRP}, + {"disallowIncomingNFTokenOffer", + lsfDisallowIncomingNFTokenOffer}, + {"disallowIncomingCheck", lsfDisallowIncomingCheck}, + {"disallowIncomingPayChan", lsfDisallowIncomingPayChan}, + {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}}; + auto const sleAccepted = ledger->read(keylet::account(accountID)); if (sleAccepted) { @@ -115,6 +119,12 @@ doAccountInfo(RPC::JsonContext& context) 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. diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 2ef467f7116..0db9d6ad174 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -492,10 +492,11 @@ class AccountInfo_test : public beast::unit_test::suite } void - testAccountFlags() + testAccountFlags(FeatureBitset const& features) { using namespace jtx; - Env env(*this); + + Env env(*this, features); Account const alice{"alice"}; env.fund(XRP(1000), alice); @@ -515,17 +516,10 @@ class AccountInfo_test : public beast::unit_test::suite }; static constexpr std:: - array, 11> + array, 6> asFlags{ {{"defaultRipple", asfDefaultRipple}, {"depositAuth", asfDepositAuth}, - {"disallowIncomingCheck", asfDisallowIncomingCheck}, - {"disallowIncomingNFTokenOffer", - asfDisallowIncomingNFTokenOffer}, - {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, - {"disallowIncomingTrustline", - asfDisallowIncomingTrustline}, - {"disallowIncomingXRP", asfDisallowXRP}, {"globalFreeze", asfGlobalFreeze}, {"noFreeze", asfNoFreeze}, {"requireAuthorization", asfRequireAuth}, @@ -537,7 +531,7 @@ class AccountInfo_test : public beast::unit_test::suite // as expected env(fclear(alice, asf.second)); env.close(); - auto f1 = getAccountFlag(asf.first); + auto const f1 = getAccountFlag(asf.first); BEAST_EXPECT(f1.has_value()); BEAST_EXPECT(!f1.value()); @@ -545,10 +539,50 @@ class AccountInfo_test : public beast::unit_test::suite // as expected env(fset(alice, asf.second)); env.close(); - auto f2 = getAccountFlag(asf.first); + auto const f2 = getAccountFlag(asf.first); BEAST_EXPECT(f2.has_value()); BEAST_EXPECT(f2.value()); } + + static constexpr std:: + array, 5> + disallowIncomingFlags{ + {{"disallowIncomingCheck", asfDisallowIncomingCheck}, + {"disallowIncomingNFTokenOffer", + asfDisallowIncomingNFTokenOffer}, + {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, + {"disallowIncomingTrustline", + asfDisallowIncomingTrustline}, + {"disallowIncomingXRP", asfDisallowXRP}}}; + + 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 @@ -558,7 +592,11 @@ class AccountInfo_test : public beast::unit_test::suite testSignerLists(); testSignerListsApiVersion2(); testSignerListsV2(); - testAccountFlags(); + + FeatureBitset const allFeatures{ + ripple::test::jtx::supported_amendments()}; + testAccountFlags(allFeatures); + testAccountFlags(allFeatures - featureDisallowIncoming); } }; From a34d76e113627c0c629048bca88dd8deb8fdab40 Mon Sep 17 00:00:00 2001 From: Long Le Date: Wed, 29 Mar 2023 19:20:48 +0200 Subject: [PATCH 4/4] Address reviewer's comment --- src/ripple/rpc/handlers/AccountInfo.cpp | 8 ++++---- src/test/rpc/AccountInfo_test.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index 61c82508482..ef130ef185f 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -78,11 +78,12 @@ doAccountInfo(RPC::JsonContext& context) return jvAccepted; static constexpr std:: - array, 8> + array, 9> lsFlags{ {{"defaultRipple", lsfDefaultRipple}, {"depositAuth", lsfDepositAuth}, {"disableMasterKey", lsfDisableMaster}, + {"disallowIncomingXRP", lsfDisallowXRP}, {"globalFreeze", lsfGlobalFreeze}, {"noFreeze", lsfNoFreeze}, {"passwordSpent", lsfPasswordSpent}, @@ -90,10 +91,9 @@ doAccountInfo(RPC::JsonContext& context) {"requireDestinationTag", lsfRequireDestTag}}}; static constexpr std:: - array, 5> + array, 4> disallowIncomingFlags{ - {{"disallowIncomingXRP", lsfDisallowXRP}, - {"disallowIncomingNFTokenOffer", + {{"disallowIncomingNFTokenOffer", lsfDisallowIncomingNFTokenOffer}, {"disallowIncomingCheck", lsfDisallowIncomingCheck}, {"disallowIncomingPayChan", lsfDisallowIncomingPayChan}, diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 0db9d6ad174..0cda0632edc 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -516,10 +516,11 @@ class AccountInfo_test : public beast::unit_test::suite }; static constexpr std:: - array, 6> + array, 7> asFlags{ {{"defaultRipple", asfDefaultRipple}, {"depositAuth", asfDepositAuth}, + {"disallowIncomingXRP", asfDisallowXRP}, {"globalFreeze", asfGlobalFreeze}, {"noFreeze", asfNoFreeze}, {"requireAuthorization", asfRequireAuth}, @@ -545,15 +546,14 @@ class AccountInfo_test : public beast::unit_test::suite } static constexpr std:: - array, 5> + array, 4> disallowIncomingFlags{ {{"disallowIncomingCheck", asfDisallowIncomingCheck}, {"disallowIncomingNFTokenOffer", asfDisallowIncomingNFTokenOffer}, {"disallowIncomingPayChan", asfDisallowIncomingPayChan}, {"disallowIncomingTrustline", - asfDisallowIncomingTrustline}, - {"disallowIncomingXRP", asfDisallowXRP}}}; + asfDisallowIncomingTrustline}}}; if (features[featureDisallowIncoming]) {