From 77dc63b54909df451ae6bca5704bd6a4fb120bbb Mon Sep 17 00:00:00 2001 From: Shawn Xie <35279399+shawnxie999@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:46:23 -0400 Subject: [PATCH] fix: add allowClawback flag for `account_info` (#4590) * Update the `account_info` API so that the `allowClawback` flag is included in the response. * The proposed `Clawback` amendement added an `allowClawback` flag in the `AccountRoot` object. * In the API response, under `account_flags`, there is now an `allowClawback` field with a boolean (`true` or `false`) value. * For reference, the XLS-39 Clawback implementation can be found in #4553 Fix #4588 --- src/ripple/rpc/handlers/AccountInfo.cpp | 8 +++++ src/test/rpc/AccountInfo_test.cpp | 43 ++++++++++++++++++++----- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index 13487dd2da..c8d25a3d8b 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -96,6 +96,9 @@ doAccountInfo(RPC::JsonContext& context) {"disallowIncomingPayChan", lsfDisallowIncomingPayChan}, {"disallowIncomingTrustline", lsfDisallowIncomingTrustline}}}; + static constexpr std::pair + allowClawbackFlag{"allowClawback", lsfAllowClawback}; + auto const sleAccepted = ledger->read(keylet::account(accountID)); if (sleAccepted) { @@ -123,6 +126,11 @@ doAccountInfo(RPC::JsonContext& context) for (auto const& lsf : disallowIncomingFlags) acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); } + + if (ledger->rules().enabled(featureClawback)) + acctFlags[allowClawbackFlag.first.data()] = + sleAccepted->isFlag(allowClawbackFlag.second); + result[jss::account_flags] = std::move(acctFlags); // The document states that signer_lists is a bool, however diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 9108ac6360..a0a819502b 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -519,13 +519,16 @@ public: Env env(*this, features); Account const alice{"alice"}; - env.fund(XRP(1000), alice); + Account const bob{"bob"}; + env.fund(XRP(1000), alice, bob); - auto getAccountFlag = [&env, &alice](std::string_view fName) { + auto getAccountFlag = [&env]( + std::string_view fName, + Account const& account) { auto const info = env.rpc( "json", "account_info", - R"({"account" : ")" + alice.human() + R"("})"); + R"({"account" : ")" + account.human() + R"("})"); std::optional res; if (info[jss::result][jss::status] == "success" && @@ -553,7 +556,7 @@ public: // as expected env(fclear(alice, asf.second)); env.close(); - auto const f1 = getAccountFlag(asf.first); + auto const f1 = getAccountFlag(asf.first, alice); BEAST_EXPECT(f1.has_value()); BEAST_EXPECT(!f1.value()); @@ -561,7 +564,7 @@ public: // as expected env(fset(alice, asf.second)); env.close(); - auto const f2 = getAccountFlag(asf.first); + auto const f2 = getAccountFlag(asf.first, alice); BEAST_EXPECT(f2.has_value()); BEAST_EXPECT(f2.value()); } @@ -584,7 +587,7 @@ public: // as expected env(fclear(alice, asf.second)); env.close(); - auto const f1 = getAccountFlag(asf.first); + auto const f1 = getAccountFlag(asf.first, alice); BEAST_EXPECT(f1.has_value()); BEAST_EXPECT(!f1.value()); @@ -592,7 +595,7 @@ public: // as expected env(fset(alice, asf.second)); env.close(); - auto const f2 = getAccountFlag(asf.first); + auto const f2 = getAccountFlag(asf.first, alice); BEAST_EXPECT(f2.has_value()); BEAST_EXPECT(f2.value()); } @@ -601,9 +604,31 @@ public: { for (auto& asf : disallowIncomingFlags) { - BEAST_EXPECT(!getAccountFlag(asf.first)); + BEAST_EXPECT(!getAccountFlag(asf.first, alice)); } } + + static constexpr std::pair + allowClawbackFlag{"allowClawback", asfAllowClawback}; + + if (features[featureClawback]) + { + // must use bob's account because alice has noFreeze set + auto const f1 = getAccountFlag(allowClawbackFlag.first, bob); + BEAST_EXPECT(f1.has_value()); + BEAST_EXPECT(!f1.value()); + + // Set allowClawback + env(fset(bob, allowClawbackFlag.second)); + env.close(); + auto const f2 = getAccountFlag(allowClawbackFlag.first, bob); + BEAST_EXPECT(f2.has_value()); + BEAST_EXPECT(f2.value()); + } + else + { + BEAST_EXPECT(!getAccountFlag(allowClawbackFlag.first, bob)); + } } void @@ -618,6 +643,8 @@ public: ripple::test::jtx::supported_amendments()}; testAccountFlags(allFeatures); testAccountFlags(allFeatures - featureDisallowIncoming); + testAccountFlags( + allFeatures - featureDisallowIncoming - featureClawback); } };