Use some utils from spec instead

This commit is contained in:
Alex Kremer
2026-08-12 22:23:44 +01:00
parent 0cf14ab07c
commit 7f02a67e2c
7 changed files with 23 additions and 250 deletions

View File

@@ -10,13 +10,13 @@
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
#include "rpc/common/Validators.hpp"
#include "util/TxUtils.hpp"
#include "util/log/Logger.hpp"
#include <boost/json/array.hpp>
#include <boost/json/conversion.hpp>
#include <boost/json/object.hpp>
#include <boost/json/value.hpp>
#include <rpcspec/detail/TxTypes.hpp>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/jss.h>
@@ -113,7 +113,9 @@ public:
static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion)
{
auto const& typesKeysInLowercase = util::getTxTypesInLowercase();
// TODO: reaches into rpcspec's detail namespace; goes away when account_tx moves
// to the shared spec, where the tx_type validator calls this internally.
auto const& typesKeysInLowercase = spec::detail::txTypesInLowercase();
static auto const kRpcSpecForV1 = RpcSpec{
{JS(account), validation::Required{}, validation::CustomValidators::accountValidator},
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},

View File

@@ -33,7 +33,6 @@ target_sources(
Taggable.cpp
TerminationHandler.cpp
TimeUtils.cpp
TxUtils.cpp
LedgerUtils.cpp
MPTIssuanceUtils.cpp
config/Array.cpp

View File

@@ -1,72 +1,25 @@
#include "util/LedgerUtils.hpp"
#include "util/JsonUtils.hpp"
#include <rpcspec/detail/XrplParse.hpp>
#include <xrpl/protocol/LedgerFormats.h>
#include <algorithm>
#include <functional>
#include <optional>
#include <string>
#include <unordered_map>
namespace util {
// TODO: both lookups reach into rpcspec's detail namespace; they switch to the public
// rpcspec ledger-types API in the next PR.
xrpl::LedgerEntryType
LedgerTypes::getLedgerEntryTypeFromStr(std::string const& entryName)
{
if (auto const result = getLedgerTypeAttributeFromStr(entryName); result.has_value()) {
return result->get().type_;
}
return xrpl::ltANY;
return rpc::spec::detail::ledgerEntryTypeFromStr(entryName);
}
xrpl::LedgerEntryType
LedgerTypes::getAccountOwnedLedgerTypeFromStr(std::string const& entryName)
{
if (auto const result = getLedgerTypeAttributeFromStr(entryName); result.has_value() &&
result->get().category_ != LedgerTypeAttribute::LedgerCategory::Chain) {
return result->get().type_;
}
return xrpl::ltANY;
}
std::optional<std::reference_wrapper<impl::LedgerTypeAttribute const>>
LedgerTypes::getLedgerTypeAttributeFromStr(std::string const& entryName)
{
static std::unordered_map<
std::string,
std::reference_wrapper<impl::LedgerTypeAttribute const>> const kNameMap = []() {
std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>>
map;
std::ranges::for_each(kLedgerTypes, [&map](auto const& item) {
map.insert({util::toLower(item.name_), item});
});
return map;
}();
static std::unordered_map<
std::string,
std::reference_wrapper<impl::LedgerTypeAttribute const>> const kRpcNameMap = []() {
std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>>
map;
std::ranges::for_each(kLedgerTypes, [&map](auto const& item) {
map.insert({item.rpcName_, item});
});
return map;
}();
if (auto const it = kRpcNameMap.find(entryName); it != kRpcNameMap.end()) {
return it->second;
}
auto const entryNameLowercase = util::toLower(entryName);
if (auto const it = kNameMap.find(entryNameLowercase); it != kNameMap.end()) {
return it->second;
}
return std::nullopt;
return rpc::spec::detail::accountOwnedLedgerTypeFromStr(entryName);
}
} // namespace util

View File

@@ -1,8 +1,7 @@
#pragma once
#include "rpc/JS.hpp"
#include <fmt/format.h>
#include <rpcspec/detail/XrplParse.hpp>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/StringUtilities.h>
#include <xrpl/basics/strHex.h>
@@ -12,7 +11,6 @@
#include <algorithm>
#include <array>
#include <functional>
#include <optional>
#include <string>
#include <unordered_set>
@@ -20,150 +18,13 @@
namespace util {
class LedgerTypes;
namespace impl {
class LedgerTypeAttribute {
enum class LedgerCategory {
Invalid,
AccountOwned, // The ledger object is owned by account
Chain, // The ledger object is shared across the chain
DeletionBlocker // The ledger object is owned by account and it blocks deletion
};
xrpl::LedgerEntryType type_ = xrpl::ltANY;
char const* name_ = nullptr;
char const* rpcName_ = nullptr;
LedgerCategory category_ = LedgerCategory::Invalid;
constexpr LedgerTypeAttribute(
char const* name,
char const* rpcName,
xrpl::LedgerEntryType type,
LedgerCategory category
)
: type_{type}, name_{name}, rpcName_{rpcName}, category_{category}
{
}
public:
static constexpr LedgerTypeAttribute
chainLedgerType(char const* name, char const* rpcName, xrpl::LedgerEntryType type)
{
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::Chain);
}
static constexpr LedgerTypeAttribute
accountOwnedLedgerType(char const* name, char const* rpcName, xrpl::LedgerEntryType type)
{
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::AccountOwned);
}
static constexpr LedgerTypeAttribute
deletionBlockerLedgerType(char const* name, char const* rpcName, xrpl::LedgerEntryType type)
{
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::DeletionBlocker);
}
friend class util::LedgerTypes;
};
} // namespace impl
/**
* @brief A helper class that provides lists of different ledger type category.
*
*/
class LedgerTypes {
using LedgerTypeAttribute = impl::LedgerTypeAttribute;
using LedgerTypeAttributeList = LedgerTypeAttribute[];
static constexpr LedgerTypeAttributeList const kLedgerTypes{
LedgerTypeAttribute::accountOwnedLedgerType(
JS(AccountRoot),
JS(account),
xrpl::ltACCOUNT_ROOT
),
LedgerTypeAttribute::chainLedgerType(JS(Amendments), JS(amendments), xrpl::ltAMENDMENTS),
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Check), JS(check), xrpl::ltCHECK),
LedgerTypeAttribute::accountOwnedLedgerType(
JS(DepositPreauth),
JS(deposit_preauth),
xrpl::ltDEPOSIT_PREAUTH
),
// dir node belongs to account, but can not be filtered from account_objects
LedgerTypeAttribute::chainLedgerType(JS(DirectoryNode), JS(directory), xrpl::ltDIR_NODE),
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Escrow), JS(escrow), xrpl::ltESCROW),
LedgerTypeAttribute::chainLedgerType(JS(FeeSettings), JS(fee), xrpl::ltFEE_SETTINGS),
LedgerTypeAttribute::chainLedgerType(JS(LedgerHashes), JS(hashes), xrpl::ltLEDGER_HASHES),
LedgerTypeAttribute::accountOwnedLedgerType(JS(Offer), JS(offer), xrpl::ltOFFER),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(PayChannel),
JS(payment_channel),
xrpl::ltPAYCHAN
),
LedgerTypeAttribute::accountOwnedLedgerType(
JS(SignerList),
JS(signer_list),
xrpl::ltSIGNER_LIST
),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(RippleState),
JS(state),
xrpl::ltRIPPLE_STATE
),
LedgerTypeAttribute::accountOwnedLedgerType(JS(Ticket), JS(ticket), xrpl::ltTICKET),
LedgerTypeAttribute::accountOwnedLedgerType(
JS(NFTokenOffer),
JS(nft_offer),
xrpl::ltNFTOKEN_OFFER
),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(NFTokenPage),
JS(nft_page),
xrpl::ltNFTOKEN_PAGE
),
LedgerTypeAttribute::accountOwnedLedgerType(JS(AMM), JS(amm), xrpl::ltAMM),
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Bridge), JS(bridge), xrpl::ltBRIDGE),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(XChainOwnedClaimID),
JS(xchain_owned_claim_id),
xrpl::ltXCHAIN_OWNED_CLAIM_ID
),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(XChainOwnedCreateAccountClaimID),
JS(xchain_owned_create_account_claim_id),
xrpl::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID
),
LedgerTypeAttribute::accountOwnedLedgerType(JS(DID), JS(did), xrpl::ltDID),
LedgerTypeAttribute::accountOwnedLedgerType(JS(Oracle), JS(oracle), xrpl::ltORACLE),
LedgerTypeAttribute::accountOwnedLedgerType(
JS(Credential),
JS(credential),
xrpl::ltCREDENTIAL
),
LedgerTypeAttribute::accountOwnedLedgerType(JS(Vault), JS(vault), xrpl::ltVAULT),
// loan broker is a pseudo-account object, like AMM and Vault
LedgerTypeAttribute::accountOwnedLedgerType(
JS(LoanBroker),
JS(loan_broker),
xrpl::ltLOAN_BROKER
),
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Loan), JS(loan), xrpl::ltLOAN),
LedgerTypeAttribute::chainLedgerType(JS(NegativeUNL), JS(nunl), xrpl::ltNEGATIVE_UNL),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(MPTokenIssuance),
JS(mpt_issuance),
xrpl::ltMPTOKEN_ISSUANCE
),
LedgerTypeAttribute::deletionBlockerLedgerType(JS(MPToken), JS(mptoken), xrpl::ltMPTOKEN),
LedgerTypeAttribute::deletionBlockerLedgerType(
JS(PermissionedDomain),
JS(permissioned_domain),
xrpl::ltPERMISSIONED_DOMAIN
),
LedgerTypeAttribute::accountOwnedLedgerType(JS(Delegate), JS(delegate), xrpl::ltDELEGATE),
};
// TODO: reaches into rpcspec's detail namespace; switches to the public rpcspec
// ledger-types API in the next PR.
static constexpr auto const& kLedgerTypes = rpc::spec::detail::kLedgerTypesTable;
public:
/**
@@ -175,7 +36,7 @@ public:
{
std::array<char const*, std::size(kLedgerTypes)> res{};
std::ranges::transform(kLedgerTypes, std::begin(res), [](auto const& item) {
return item.rpcName_;
return item.rpcName.data();
});
return res;
}
@@ -188,8 +49,10 @@ public:
static constexpr auto
getDeletionBlockerLedgerTypes()
{
// TODO: LedgerCategory comes from rpcspec's detail namespace; switches to the
// public rpcspec ledger-types API in the next PR.
constexpr auto kFilter = [](auto const& item) {
return item.category_ == LedgerTypeAttribute::LedgerCategory::DeletionBlocker;
return item.category == rpc::spec::detail::LedgerCategory::DeletionBlocker;
};
constexpr auto kDeletionBlockersCount =
@@ -198,7 +61,7 @@ public:
auto it = std::begin(res);
std::ranges::for_each(kLedgerTypes, [&](auto const& item) {
if (kFilter(item)) {
*it = item.type_;
*it = item.type;
++it;
}
});
@@ -224,10 +87,6 @@ public:
*/
static xrpl::LedgerEntryType
getAccountOwnedLedgerTypeFromStr(std::string const& entryName);
private:
static std::optional<std::reference_wrapper<impl::LedgerTypeAttribute const>>
getLedgerTypeAttributeFromStr(std::string const& entryName);
};
/**

View File

@@ -1,33 +0,0 @@
#include "util/JsonUtils.hpp"
#include <xrpl/protocol/TxFormats.h>
#include <algorithm>
#include <iterator>
#include <string>
#include <unordered_set>
namespace util {
/**
* @brief Get the transaction types in lowercase
*
* @return The transaction types in lowercase
*/
[[nodiscard]] std::unordered_set<std::string> const&
getTxTypesInLowercase()
{
static std::unordered_set<std::string> const kTypesKeysInLowercase = []() {
std::unordered_set<std::string> keys;
std::transform(
xrpl::TxFormats::getInstance().begin(),
xrpl::TxFormats::getInstance().end(),
std::inserter(keys, keys.begin()),
[](auto const& pair) { return util::toLower(pair.getName()); }
);
return keys;
}();
return kTypesKeysInLowercase;
}
} // namespace util

View File

@@ -1,9 +0,0 @@
#pragma once
#include <string>
#include <unordered_set>
namespace util {
[[nodiscard]] std::unordered_set<std::string> const&
getTxTypesInLowercase();
} // namespace util

View File

@@ -1,7 +1,7 @@
#include "util/JsonUtils.hpp"
#include "util/TxUtils.hpp"
#include <gtest/gtest.h>
#include <rpcspec/detail/TxTypes.hpp>
#include <xrpl/protocol/TxFormats.h>
#include <algorithm>
@@ -10,7 +10,9 @@
TEST(TxUtilTests, txTypesInLowercase)
{
auto const& types = util::getTxTypesInLowercase();
// TODO: reaches into rpcspec's detail namespace; switches to the public rpcspec
// tx-types API in the next PR.
auto const& types = rpc::spec::detail::txTypesInLowercase();
ASSERT_TRUE(
std::size_t(
std::distance(