mirror of
				https://github.com/XRPLF/clio.git
				synced 2025-11-04 11:55:51 +00:00 
			
		
		
		
	Ledger entry type filter for account_objects and ledger_data (#1116)
Fix #1109
This commit is contained in:
		@@ -165,7 +165,8 @@ target_sources (clio PRIVATE
 | 
			
		||||
  src/util/Random.cpp
 | 
			
		||||
  src/util/Taggable.cpp
 | 
			
		||||
  src/util/TerminationHandler.cpp
 | 
			
		||||
  src/util/TxUtil.cpp
 | 
			
		||||
  src/util/TxUtils.cpp
 | 
			
		||||
  src/util/LedgerUtils.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Clio server
 | 
			
		||||
@@ -194,6 +195,7 @@ if (tests)
 | 
			
		||||
    unittests/util/TxUtilTests.cpp
 | 
			
		||||
    unittests/util/TestObject.cpp
 | 
			
		||||
    unittests/util/StringUtils.cpp
 | 
			
		||||
    unittests/util/LedgerUtilsTests.cpp
 | 
			
		||||
    unittests/util/prometheus/CounterTests.cpp
 | 
			
		||||
    unittests/util/prometheus/GaugeTests.cpp
 | 
			
		||||
    unittests/util/prometheus/HistogramTests.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
#include "rpc/RPCHelpers.h"
 | 
			
		||||
#include "rpc/common/Types.h"
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/array.hpp>
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
@@ -47,30 +48,6 @@
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
// found here : https://xrpl.org/ledger_entry.html#:~:text=valid%20fields%20are%3A-,index,-account_root
 | 
			
		||||
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPES_MAP{
 | 
			
		||||
    {JS(amm), ripple::ltAMM},
 | 
			
		||||
    {JS(state), ripple::ltRIPPLE_STATE},
 | 
			
		||||
    {JS(ticket), ripple::ltTICKET},
 | 
			
		||||
    {JS(signer_list), ripple::ltSIGNER_LIST},
 | 
			
		||||
    {JS(payment_channel), ripple::ltPAYCHAN},
 | 
			
		||||
    {JS(offer), ripple::ltOFFER},
 | 
			
		||||
    {JS(escrow), ripple::ltESCROW},
 | 
			
		||||
    {JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
 | 
			
		||||
    {JS(check), ripple::ltCHECK},
 | 
			
		||||
    {JS(nft_page), ripple::ltNFTOKEN_PAGE},
 | 
			
		||||
    {JS(nft_offer), ripple::ltNFTOKEN_OFFER},
 | 
			
		||||
    {JS(did), ripple::ltDID},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::unordered_set<std::string> const AccountObjectsHandler::TYPES_KEYS = [] {
 | 
			
		||||
    std::unordered_set<std::string> keys;
 | 
			
		||||
    std::transform(TYPES_MAP.begin(), TYPES_MAP.end(), std::inserter(keys, keys.begin()), [](auto const& pair) {
 | 
			
		||||
        return pair.first;
 | 
			
		||||
    });
 | 
			
		||||
    return keys;
 | 
			
		||||
}();
 | 
			
		||||
 | 
			
		||||
AccountObjectsHandler::Result
 | 
			
		||||
AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const& ctx) const
 | 
			
		||||
{
 | 
			
		||||
@@ -93,16 +70,9 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const
 | 
			
		||||
    auto typeFilter = std::optional<std::vector<ripple::LedgerEntryType>>{};
 | 
			
		||||
 | 
			
		||||
    if (input.deletionBlockersOnly) {
 | 
			
		||||
        static constexpr ripple::LedgerEntryType deletionBlockers[] = {
 | 
			
		||||
            ripple::ltCHECK,
 | 
			
		||||
            ripple::ltESCROW,
 | 
			
		||||
            ripple::ltNFTOKEN_PAGE,
 | 
			
		||||
            ripple::ltPAYCHAN,
 | 
			
		||||
            ripple::ltRIPPLE_STATE,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        typeFilter.emplace();
 | 
			
		||||
        typeFilter->reserve(std::size(deletionBlockers));
 | 
			
		||||
        auto const& deletionBlockers = util::getDeletionBlockerLedgerTypes();
 | 
			
		||||
        typeFilter->reserve(deletionBlockers.size());
 | 
			
		||||
 | 
			
		||||
        for (auto type : deletionBlockers) {
 | 
			
		||||
            if (input.type && input.type != type)
 | 
			
		||||
@@ -189,7 +159,7 @@ tag_invoke(boost::json::value_to_tag<AccountObjectsHandler::Input>, boost::json:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (jsonObject.contains(JS(type)))
 | 
			
		||||
        input.type = AccountObjectsHandler::TYPES_MAP.at(jv.at(JS(type)).as_string().c_str());
 | 
			
		||||
        input.type = util::getLedgerEntryTypeFromStr(jv.at(JS(type)).as_string().c_str());
 | 
			
		||||
 | 
			
		||||
    if (jsonObject.contains(JS(limit)))
 | 
			
		||||
        input.limit = jv.at(JS(limit)).as_int64();
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,25 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "data/BackendInterface.h"
 | 
			
		||||
#include "rpc/RPCHelpers.h"
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
#include "rpc/common/Modifiers.h"
 | 
			
		||||
#include "rpc/common/Types.h"
 | 
			
		||||
#include "rpc/common/Validators.h"
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
#include <boost/json/value.hpp>
 | 
			
		||||
#include <ripple/protocol/LedgerFormats.h>
 | 
			
		||||
#include <ripple/protocol/STLedgerEntry.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
@@ -80,6 +93,7 @@ public:
 | 
			
		||||
    static RpcSpecConstRef
 | 
			
		||||
    spec([[maybe_unused]] uint32_t apiVersion)
 | 
			
		||||
    {
 | 
			
		||||
        auto const& ledgerTypeStrs = util::getLedgerEntryTypeStrs();
 | 
			
		||||
        static auto const rpcSpec = RpcSpec{
 | 
			
		||||
            {JS(account), validation::Required{}, validation::AccountValidator},
 | 
			
		||||
            {JS(ledger_hash), validation::Uint256HexStringValidator},
 | 
			
		||||
@@ -90,7 +104,7 @@ public:
 | 
			
		||||
             modifiers::Clamp<int32_t>(LIMIT_MIN, LIMIT_MAX)},
 | 
			
		||||
            {JS(type),
 | 
			
		||||
             validation::Type<std::string>{},
 | 
			
		||||
             validation::OneOf<std::string>(TYPES_KEYS.cbegin(), TYPES_KEYS.cend())},
 | 
			
		||||
             validation::OneOf<std::string>(ledgerTypeStrs.cbegin(), ledgerTypeStrs.cend())},
 | 
			
		||||
            {JS(marker), validation::AccountMarkerValidator},
 | 
			
		||||
            {JS(deletion_blockers_only), validation::Type<bool>{}},
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
#include "rpc/common/Modifiers.h"
 | 
			
		||||
#include "rpc/common/Types.h"
 | 
			
		||||
#include "rpc/common/Validators.h"
 | 
			
		||||
#include "util/TxUtil.h"
 | 
			
		||||
#include "util/TxUtils.h"
 | 
			
		||||
#include "util/log/Logger.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/array.hpp>
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
#include "rpc/RPCHelpers.h"
 | 
			
		||||
#include "rpc/common/Types.h"
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
#include "util/log/Logger.h"
 | 
			
		||||
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
@@ -42,45 +43,13 @@
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <variant>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
 | 
			
		||||
std::unordered_map<std::string, ripple::LedgerEntryType> const LedgerDataHandler::TYPES_MAP{
 | 
			
		||||
    {JS(account), ripple::ltACCOUNT_ROOT},
 | 
			
		||||
    {JS(did), ripple::ltDID},
 | 
			
		||||
    {JS(amendments), ripple::ltAMENDMENTS},
 | 
			
		||||
    {JS(check), ripple::ltCHECK},
 | 
			
		||||
    {JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
 | 
			
		||||
    {JS(directory), ripple::ltDIR_NODE},
 | 
			
		||||
    {JS(escrow), ripple::ltESCROW},
 | 
			
		||||
    {JS(fee), ripple::ltFEE_SETTINGS},
 | 
			
		||||
    {JS(hashes), ripple::ltLEDGER_HASHES},
 | 
			
		||||
    {JS(offer), ripple::ltOFFER},
 | 
			
		||||
    {JS(payment_channel), ripple::ltPAYCHAN},
 | 
			
		||||
    {JS(signer_list), ripple::ltSIGNER_LIST},
 | 
			
		||||
    {JS(state), ripple::ltRIPPLE_STATE},
 | 
			
		||||
    {JS(ticket), ripple::ltTICKET},
 | 
			
		||||
    {JS(nft_offer), ripple::ltNFTOKEN_OFFER},
 | 
			
		||||
    {JS(nft_page), ripple::ltNFTOKEN_PAGE},
 | 
			
		||||
    {JS(amm), ripple::ltAMM}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: should be std::views::keys when clang supports it
 | 
			
		||||
std::unordered_set<std::string> const LedgerDataHandler::TYPES_KEYS = [] {
 | 
			
		||||
    std::unordered_set<std::string> keys;
 | 
			
		||||
    std::transform(TYPES_MAP.begin(), TYPES_MAP.end(), std::inserter(keys, keys.begin()), [](auto const& pair) {
 | 
			
		||||
        return pair.first;
 | 
			
		||||
    });
 | 
			
		||||
    return keys;
 | 
			
		||||
}();
 | 
			
		||||
 | 
			
		||||
LedgerDataHandler::Result
 | 
			
		||||
LedgerDataHandler::process(Input input, Context const& ctx) const
 | 
			
		||||
{
 | 
			
		||||
@@ -246,7 +215,7 @@ tag_invoke(boost::json::value_to_tag<LedgerDataHandler::Input>, boost::json::val
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (jsonObject.contains(JS(type)))
 | 
			
		||||
        input.type = LedgerDataHandler::TYPES_MAP.at(jsonObject.at(JS(type)).as_string().c_str());
 | 
			
		||||
        input.type = util::getLedgerEntryTypeFromStr(jsonObject.at(JS(type)).as_string().c_str());
 | 
			
		||||
 | 
			
		||||
    return input;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,27 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "data/BackendInterface.h"
 | 
			
		||||
#include "rpc/RPCHelpers.h"
 | 
			
		||||
#include "rpc/Errors.h"
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
#include "rpc/common/MetaProcessors.h"
 | 
			
		||||
#include "rpc/common/Types.h"
 | 
			
		||||
#include "rpc/common/Validators.h"
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
#include "util/log/Logger.h"
 | 
			
		||||
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <boost/json/array.hpp>
 | 
			
		||||
#include <boost/json/conversion.hpp>
 | 
			
		||||
#include <boost/json/object.hpp>
 | 
			
		||||
#include <boost/json/value.hpp>
 | 
			
		||||
#include <ripple/basics/base_uint.h>
 | 
			
		||||
#include <ripple/protocol/ErrorCodes.h>
 | 
			
		||||
#include <ripple/protocol/LedgerFormats.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
 | 
			
		||||
namespace rpc {
 | 
			
		||||
@@ -41,10 +56,6 @@ class LedgerDataHandler {
 | 
			
		||||
    std::shared_ptr<BackendInterface> sharedPtrBackend_;
 | 
			
		||||
    util::Logger log_{"RPC"};
 | 
			
		||||
 | 
			
		||||
    static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPES_MAP;
 | 
			
		||||
 | 
			
		||||
    static std::unordered_set<std::string> const TYPES_KEYS;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    // constants
 | 
			
		||||
    static uint32_t constexpr LIMITBINARY = 2048;
 | 
			
		||||
@@ -84,6 +95,7 @@ public:
 | 
			
		||||
    static RpcSpecConstRef
 | 
			
		||||
    spec([[maybe_unused]] uint32_t apiVersion)
 | 
			
		||||
    {
 | 
			
		||||
        auto const& ledgerTypeStrs = util::getLedgerEntryTypeStrs();
 | 
			
		||||
        static auto const rpcSpec = RpcSpec{
 | 
			
		||||
            {JS(binary), validation::Type<bool>{}},
 | 
			
		||||
            {"out_of_order", validation::Type<bool>{}},
 | 
			
		||||
@@ -97,7 +109,7 @@ public:
 | 
			
		||||
             meta::WithCustomError{
 | 
			
		||||
                 validation::Type<std::string>{}, Status{ripple::rpcINVALID_PARAMS, "Invalid field 'type', not string."}
 | 
			
		||||
             },
 | 
			
		||||
             validation::OneOf<std::string>(TYPES_KEYS.cbegin(), TYPES_KEYS.cend())},
 | 
			
		||||
             validation::OneOf<std::string>(ledgerTypeStrs.cbegin(), ledgerTypeStrs.cend())},
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
        return rpcSpec;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								src/util/LedgerUtils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/util/LedgerUtils.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    This file is part of clio: https://github.com/XRPLF/clio
 | 
			
		||||
    Copyright (c) 2024, the clio developers.
 | 
			
		||||
 | 
			
		||||
    Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
    purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
    copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
 | 
			
		||||
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
    ANY  SPECIAL,  DIRECT,  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
 | 
			
		||||
#include <ripple/protocol/LedgerFormats.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
struct LedgerTypeAttributes {
 | 
			
		||||
    ripple::LedgerEntryType type = ripple::ltANY;
 | 
			
		||||
    bool deletionBlocker = false;
 | 
			
		||||
 | 
			
		||||
    LedgerTypeAttributes(ripple::LedgerEntryType type, bool blocker = false) : type(type), deletionBlocker(blocker)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Ledger entry type filter list, add new types here to support filtering for ledger_data and
 | 
			
		||||
// account_objects
 | 
			
		||||
static std::unordered_map<std::string, LedgerTypeAttributes> const LEDGER_TYPES_MAP{
 | 
			
		||||
    {{JS(account), LedgerTypeAttributes(ripple::ltACCOUNT_ROOT)},
 | 
			
		||||
     {JS(amendments), LedgerTypeAttributes(ripple::ltAMENDMENTS)},
 | 
			
		||||
     {JS(check), LedgerTypeAttributes(ripple::ltCHECK, true)},
 | 
			
		||||
     {JS(deposit_preauth), LedgerTypeAttributes(ripple::ltDEPOSIT_PREAUTH)},
 | 
			
		||||
     {JS(directory), LedgerTypeAttributes(ripple::ltDIR_NODE)},
 | 
			
		||||
     {JS(escrow), LedgerTypeAttributes(ripple::ltESCROW, true)},
 | 
			
		||||
     {JS(fee), LedgerTypeAttributes(ripple::ltFEE_SETTINGS)},
 | 
			
		||||
     {JS(hashes), LedgerTypeAttributes(ripple::ltLEDGER_HASHES)},
 | 
			
		||||
     {JS(offer), LedgerTypeAttributes(ripple::ltOFFER)},
 | 
			
		||||
     {JS(payment_channel), LedgerTypeAttributes(ripple::ltPAYCHAN, true)},
 | 
			
		||||
     {JS(signer_list), LedgerTypeAttributes(ripple::ltSIGNER_LIST)},
 | 
			
		||||
     {JS(state), LedgerTypeAttributes(ripple::ltRIPPLE_STATE, true)},
 | 
			
		||||
     {JS(ticket), LedgerTypeAttributes(ripple::ltTICKET)},
 | 
			
		||||
     {JS(nft_offer), LedgerTypeAttributes(ripple::ltNFTOKEN_OFFER)},
 | 
			
		||||
     {JS(nft_page), LedgerTypeAttributes(ripple::ltNFTOKEN_PAGE, true)},
 | 
			
		||||
     {JS(amm), LedgerTypeAttributes(ripple::ltAMM)},
 | 
			
		||||
     {JS(bridge), LedgerTypeAttributes(ripple::ltBRIDGE, true)},
 | 
			
		||||
     {JS(xchain_owned_claim_id), LedgerTypeAttributes(ripple::ltXCHAIN_OWNED_CLAIM_ID, true)},
 | 
			
		||||
     {JS(xchain_owned_create_account_claim_id),
 | 
			
		||||
      LedgerTypeAttributes(ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID, true)},
 | 
			
		||||
     {JS(did), LedgerTypeAttributes(ripple::ltDID)}}
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
std::unordered_set<std::string> const&
 | 
			
		||||
getLedgerEntryTypeStrs()
 | 
			
		||||
{
 | 
			
		||||
    static std::unordered_set<std::string> const typesKeys = []() {
 | 
			
		||||
        std::unordered_set<std::string> keys;
 | 
			
		||||
        std::transform(
 | 
			
		||||
            detail::LEDGER_TYPES_MAP.begin(),
 | 
			
		||||
            detail::LEDGER_TYPES_MAP.end(),
 | 
			
		||||
            std::inserter(keys, keys.begin()),
 | 
			
		||||
            [](auto const& item) { return item.first; }
 | 
			
		||||
        );
 | 
			
		||||
        return keys;
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    return typesKeys;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ripple::LedgerEntryType
 | 
			
		||||
getLedgerEntryTypeFromStr(std::string const& entryName)
 | 
			
		||||
{
 | 
			
		||||
    if (detail::LEDGER_TYPES_MAP.find(entryName) == detail::LEDGER_TYPES_MAP.end())
 | 
			
		||||
        return ripple::ltANY;
 | 
			
		||||
 | 
			
		||||
    return detail::LEDGER_TYPES_MAP.at(entryName).type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<ripple::LedgerEntryType> const&
 | 
			
		||||
getDeletionBlockerLedgerTypes()
 | 
			
		||||
{
 | 
			
		||||
    static std::vector<ripple::LedgerEntryType> const deletionBlockerLedgerTypes = []() {
 | 
			
		||||
        // TODO: Move to std::ranges::views::filter when move to higher clang
 | 
			
		||||
        auto ret = std::vector<ripple::LedgerEntryType>{};
 | 
			
		||||
        std::for_each(detail::LEDGER_TYPES_MAP.cbegin(), detail::LEDGER_TYPES_MAP.cend(), [&ret](auto const& item) {
 | 
			
		||||
            if (item.second.deletionBlocker)
 | 
			
		||||
                ret.push_back(item.second.type);
 | 
			
		||||
        });
 | 
			
		||||
        return ret;
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    return deletionBlockerLedgerTypes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace util
 | 
			
		||||
@@ -22,13 +22,34 @@
 | 
			
		||||
#include <fmt/core.h>
 | 
			
		||||
#include <ripple/basics/Slice.h>
 | 
			
		||||
#include <ripple/basics/StringUtilities.h>
 | 
			
		||||
#include <ripple/protocol/LedgerFormats.h>
 | 
			
		||||
#include <ripple/protocol/LedgerHeader.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace util {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Returns a string set of all supported ledger entry types.
 | 
			
		||||
 */
 | 
			
		||||
std::unordered_set<std::string> const&
 | 
			
		||||
getLedgerEntryTypeStrs();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return the ledger type from a string representation.
 | 
			
		||||
 */
 | 
			
		||||
ripple::LedgerEntryType
 | 
			
		||||
getLedgerEntryTypeFromStr(std::string const& entryName);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return the list of ledger entry types which will block the account deletion.
 | 
			
		||||
 */
 | 
			
		||||
std::vector<ripple::LedgerEntryType> const&
 | 
			
		||||
getDeletionBlockerLedgerTypes();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Deserializes a ripple::LedgerHeader from ripple::Slice of data.
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								unittests/util/LedgerUtilsTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								unittests/util/LedgerUtilsTests.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
/*
 | 
			
		||||
    This file is part of clio: https://github.com/XRPLF/clio
 | 
			
		||||
    Copyright (c) 2024, the clio developers.
 | 
			
		||||
 | 
			
		||||
    Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
    purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
    copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
 | 
			
		||||
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
    ANY  SPECIAL,  DIRECT,  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "rpc/JS.h"
 | 
			
		||||
#include "util/LedgerUtils.h"
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
#include <ripple/protocol/LedgerFormats.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
 | 
			
		||||
TEST(LedgerUtilsTests, LedgerObjectTypeList)
 | 
			
		||||
{
 | 
			
		||||
    auto const& types = util::getLedgerEntryTypeStrs();
 | 
			
		||||
    static char const* typesList[] = {
 | 
			
		||||
        JS(account),
 | 
			
		||||
        JS(amendments),
 | 
			
		||||
        JS(check),
 | 
			
		||||
        JS(deposit_preauth),
 | 
			
		||||
        JS(directory),
 | 
			
		||||
        JS(escrow),
 | 
			
		||||
        JS(fee),
 | 
			
		||||
        JS(hashes),
 | 
			
		||||
        JS(offer),
 | 
			
		||||
        JS(payment_channel),
 | 
			
		||||
        JS(signer_list),
 | 
			
		||||
        JS(state),
 | 
			
		||||
        JS(ticket),
 | 
			
		||||
        JS(nft_offer),
 | 
			
		||||
        JS(nft_page),
 | 
			
		||||
        JS(amm),
 | 
			
		||||
        JS(bridge),
 | 
			
		||||
        JS(xchain_owned_claim_id),
 | 
			
		||||
        JS(xchain_owned_create_account_claim_id),
 | 
			
		||||
        JS(did)
 | 
			
		||||
    };
 | 
			
		||||
    ASSERT_TRUE(std::size(typesList) == types.size());
 | 
			
		||||
    EXPECT_TRUE(std::all_of(std::cbegin(typesList), std::cend(typesList), [&types](auto const& type) {
 | 
			
		||||
        return std::find(std::cbegin(types), std::cend(types), type) != std::cend(types);
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(LedgerUtilsTests, StrToType)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(util::getLedgerEntryTypeFromStr("mess"), ripple::ltANY);
 | 
			
		||||
    EXPECT_EQ(util::getLedgerEntryTypeFromStr("tomato"), ripple::ltANY);
 | 
			
		||||
    EXPECT_EQ(util::getLedgerEntryTypeFromStr("account"), ripple::ltACCOUNT_ROOT);
 | 
			
		||||
 | 
			
		||||
    auto const& types = util::getLedgerEntryTypeStrs();
 | 
			
		||||
    std::for_each(types.cbegin(), types.cend(), [](auto const& typeStr) {
 | 
			
		||||
        EXPECT_NE(util::getLedgerEntryTypeFromStr(typeStr), ripple::ltANY);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(LedgerUtilsTests, DeletionBlockerTypes)
 | 
			
		||||
{
 | 
			
		||||
    auto const& testedTypes = util::getDeletionBlockerLedgerTypes();
 | 
			
		||||
 | 
			
		||||
    static ripple::LedgerEntryType constexpr deletionBlockers[] = {
 | 
			
		||||
        ripple::ltCHECK,
 | 
			
		||||
        ripple::ltESCROW,
 | 
			
		||||
        ripple::ltNFTOKEN_PAGE,
 | 
			
		||||
        ripple::ltPAYCHAN,
 | 
			
		||||
        ripple::ltRIPPLE_STATE,
 | 
			
		||||
        ripple::ltXCHAIN_OWNED_CLAIM_ID,
 | 
			
		||||
        ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID,
 | 
			
		||||
        ripple::ltBRIDGE
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(std::size(deletionBlockers) == testedTypes.size());
 | 
			
		||||
    EXPECT_TRUE(std::any_of(testedTypes.cbegin(), testedTypes.cend(), [](auto const& type) {
 | 
			
		||||
        return std::find(std::cbegin(deletionBlockers), std::cend(deletionBlockers), type) !=
 | 
			
		||||
            std::cend(deletionBlockers);
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
//==============================================================================
 | 
			
		||||
 | 
			
		||||
#include "util/JsonUtils.h"
 | 
			
		||||
#include "util/TxUtil.h"
 | 
			
		||||
#include "util/TxUtils.h"
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
#include <ripple/protocol/TxFormats.h>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user