Add deletion_blockers_only param to account_objects RPC command

This commit is contained in:
Joseph Busch
2019-09-19 12:21:59 -05:00
committed by Manoj doshi
parent fccb7e1c70
commit 7e7664c29a
5 changed files with 101 additions and 12 deletions

View File

@@ -182,6 +182,7 @@ JSS ( dbKBLedger ); // out: getCounts
JSS ( dbKBTotal ); // out: getCounts
JSS ( dbKBTransaction ); // out: getCounts
JSS ( debug_signing ); // in: TransactionSign
JSS ( deletion_blockers_only ); // in: AccountObjects
JSS ( delivered_amount ); // out: insertDeliveredAmount
JSS ( deposit_authorized ); // out: deposit_authorized
JSS ( deposit_preauth ); // in: AccountObjects, LedgerData

View File

@@ -72,12 +72,49 @@ Json::Value doAccountObjects (RPC::Context& context)
if (! ledger->exists(keylet::account (accountID)))
return rpcError (rpcACT_NOT_FOUND);
auto [rpcStatus, type] = RPC::chooseLedgerEntryType(params);
if (rpcStatus)
boost::optional<std::vector<LedgerEntryType>> typeFilter;
if (params.isMember(jss::deletion_blockers_only) &&
params[jss::deletion_blockers_only].asBool())
{
result.clear();
rpcStatus.inject(result);
return result;
struct {
Json::StaticString name;
LedgerEntryType type;
} static constexpr deletionBlockers[] = {
{ jss::check, ltCHECK },
{ jss::escrow, ltESCROW },
{ jss::payment_channel, ltPAYCHAN },
{ jss::state, ltRIPPLE_STATE }
};
typeFilter.emplace();
typeFilter->reserve(std::size(deletionBlockers));
for (auto [name, type] : deletionBlockers)
{
if (params.isMember(jss::type) &&
name != params[jss::type])
{
continue;
}
typeFilter->push_back(type);
}
}
else
{
auto [rpcStatus, type] = RPC::chooseLedgerEntryType(params);
if (rpcStatus)
{
result.clear();
rpcStatus.inject(result);
return result;
}
else if (type != ltINVALID)
{
typeFilter = std::vector<LedgerEntryType>({ type });
}
}
unsigned int limit;
@@ -107,7 +144,7 @@ Json::Value doAccountObjects (RPC::Context& context)
return RPC::invalid_field_error (jss::marker);
}
if (! RPC::getAccountObjects (*ledger, accountID, type,
if (! RPC::getAccountObjects (*ledger, accountID, typeFilter,
dirIndex, entryIndex, limit, result))
{
result[jss::account_objects] = Json::arrayValue;

View File

@@ -82,8 +82,8 @@ accountFromString(
bool
getAccountObjects(ReadView const& ledger, AccountID const& account,
LedgerEntryType const type, uint256 dirIndex, uint256 const& entryIndex,
std::uint32_t const limit, Json::Value& jvResult)
boost::optional<std::vector<LedgerEntryType>> const& typeFilter, uint256 dirIndex,
uint256 const& entryIndex, std::uint32_t const limit, Json::Value& jvResult)
{
auto const rootDirIndex = getOwnerDirIndex (account);
auto found = false;
@@ -117,7 +117,18 @@ getAccountObjects(ReadView const& ledger, AccountID const& account,
for (; iter != entries.end (); ++iter)
{
auto const sleNode = ledger.read(keylet::child(*iter));
if (type == ltINVALID || sleNode->getType () == type)
auto typeMatchesFilter = [] (
std::vector<LedgerEntryType> const& typeFilter,
LedgerEntryType ledgerType)
{
auto it = std::find(typeFilter.begin(), typeFilter.end(),
ledgerType);
return it != typeFilter.end();
};
if (!typeFilter.has_value() ||
typeMatchesFilter(typeFilter.value(), sleNode->getType()))
{
jvObjects.append (sleNode->getJson (JsonOptions::none));

View File

@@ -55,7 +55,7 @@ accountFromString (AccountID& result, std::string const& strIdent,
/** Gathers all objects for an account in a ledger.
@param ledger Ledger to search account objects.
@param account AccountID to find objects for.
@param type Gathers objects of this type. ltINVALID gathers all types.
@param typeFilter Gathers objects of these types. empty gathers all types.
@param dirIndex Begin gathering account objects from this directory.
@param entryIndex Begin gathering objects from this directory node.
@param limit Maximum number of objects to find.
@@ -63,8 +63,8 @@ accountFromString (AccountID& result, std::string const& strIdent,
*/
bool
getAccountObjects (ReadView const& ledger, AccountID const& account,
LedgerEntryType const type, uint256 dirIndex, uint256 const& entryIndex,
std::uint32_t const limit, Json::Value& jvResult);
boost::optional<std::vector<LedgerEntryType>> const& typeFilter, uint256 dirIndex,
uint256 const& entryIndex, std::uint32_t const limit, Json::Value& jvResult);
/** Look up a ledger from a request and fill a Json::Result with either
an error, or data representing a ledger.

View File

@@ -494,6 +494,46 @@ public:
BEAST_EXPECT (ticket[sfLedgerEntryType.jsonName] == jss::Ticket);
BEAST_EXPECT (ticket[sfSequence.jsonName].asUInt() == 9);
}
{
// See how "deletion_blockers_only" handles gw's directory.
Json::Value params;
params[jss::account] = gw.human();
params[jss::deletion_blockers_only] = true;
auto resp = env.rpc("json", "account_objects", to_string(params));
constexpr Json::StaticString const expectedLedgerTypes[] = {
jss::Escrow, jss::Check, jss::RippleState, jss::PayChannel
};
constexpr auto expectedAccountObjects{
static_cast<std::uint32_t>(std::size(expectedLedgerTypes))
};
if (BEAST_EXPECT(acct_objs_is_size(resp, expectedAccountObjects)))
{
auto const& aobjs = resp[jss::result][jss::account_objects];
for (std::uint32_t i = 0; i < expectedAccountObjects; ++i)
{
BEAST_EXPECT(
aobjs[i]["LedgerEntryType"] == expectedLedgerTypes[i]);
}
}
}
{
// See how "deletion_blockers_only" with `type` handles gw's directory.
Json::Value params;
params[jss::account] = gw.human();
params[jss::deletion_blockers_only] = true;
params[jss::type] = jss::escrow;
auto resp = env.rpc("json", "account_objects", to_string(params));
if (BEAST_EXPECT(acct_objs_is_size(resp, 1u)))
{
auto const& aobjs = resp[jss::result][jss::account_objects];
BEAST_EXPECT(
aobjs[0u]["LedgerEntryType"] == jss::Escrow);
}
}
// Run up the number of directory entries so gw has two
// directory nodes.
for (int d = 1'000'032; d >= 1'000'000; --d)