mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-22 23:00:55 +00:00
switch to list of valid entry types
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
@@ -20,6 +21,9 @@ class ValidAMM
|
||||
public:
|
||||
enum class ZeroAllowed : bool { No = false, Yes = true };
|
||||
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltAMM, ltRIPPLE_STATE, ltACCOUNT_ROOT, ltMPTOKEN>{};
|
||||
|
||||
ValidAMM() = default;
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -17,6 +18,8 @@ class ValidBookDirectory
|
||||
hash_set<uint256> rootIndexes_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltDIR_NODE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -38,6 +39,9 @@ class TransfersNotFrozen
|
||||
std::map<AccountID, SLE::const_pointer const> possibleIssuers_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltACCOUNT_ROOT, ltRIPPLE_STATE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <xrpl/tx/invariants/AMMInvariant.h>
|
||||
#include <xrpl/tx/invariants/DirectoryInvariant.h>
|
||||
#include <xrpl/tx/invariants/FreezeInvariant.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
#include <xrpl/tx/invariants/LoanBrokerInvariant.h>
|
||||
#include <xrpl/tx/invariants/LoanInvariant.h>
|
||||
#include <xrpl/tx/invariants/MPTInvariant.h>
|
||||
@@ -107,6 +108,8 @@ public:
|
||||
class TransactionFeeCheck
|
||||
{
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitNoLedgerEntryTypes{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -127,6 +130,9 @@ class XRPNotCreated
|
||||
std::int64_t drops_ = 0;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltACCOUNT_ROOT, ltPAYCHAN, ltESCROW>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -147,6 +153,8 @@ class AccountRootsNotDeleted
|
||||
std::uint32_t accountsDeleted_ = 0;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -174,6 +182,8 @@ class AccountRootsDeletedClean
|
||||
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> accountsDeleted_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -193,6 +203,8 @@ class XRPBalanceChecks
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -210,6 +222,8 @@ class LedgerEntryTypesMatch
|
||||
bool invalidTypeAdded_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitAllLedgerEntryTypes{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -228,6 +242,8 @@ class NoXRPTrustLines
|
||||
bool xrpTrustLine_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltRIPPLE_STATE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -247,6 +263,8 @@ class NoDeepFreezeTrustLinesWithoutFreeze
|
||||
bool deepFreezeWithoutFreeze_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltRIPPLE_STATE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -266,6 +284,8 @@ class NoBadOffers
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltOFFER>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -282,6 +302,9 @@ class NoZeroEscrow
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltESCROW, ltMPTOKEN_ISSUANCE, ltMPTOKEN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -302,6 +325,8 @@ class ValidNewAccountRoot
|
||||
std::uint32_t flags_ = 0;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -323,6 +348,9 @@ class ValidClawback
|
||||
std::uint32_t mptokensChanged_ = 0;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltRIPPLE_STATE, ltMPTOKEN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -343,6 +371,8 @@ class ValidPseudoAccounts
|
||||
std::vector<std::string> errors_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -363,6 +393,8 @@ class NoModifiedUnmodifiableFields
|
||||
std::set<std::pair<SLE::const_pointer, SLE::const_pointer>> changedEntries_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitAllLedgerEntryTypes{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -378,6 +410,8 @@ class ValidAmounts
|
||||
std::vector<std::shared_ptr<SLE const>> afterEntries_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitAllLedgerEntryTypes{};
|
||||
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
|
||||
50
include/xrpl/tx/invariants/InvariantEntryTypes.h
Normal file
50
include/xrpl/tx/invariants/InvariantEntryTypes.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
struct VisitAllLedgerEntryTypes
|
||||
{
|
||||
static constexpr bool visitsAll = true;
|
||||
static constexpr bool visitsNone = false;
|
||||
static constexpr bool empty = false;
|
||||
|
||||
template <LedgerEntryType>
|
||||
static consteval bool
|
||||
contains()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct VisitNoLedgerEntryTypes
|
||||
{
|
||||
static constexpr bool visitsAll = false;
|
||||
static constexpr bool visitsNone = true;
|
||||
static constexpr bool empty = true;
|
||||
|
||||
template <LedgerEntryType>
|
||||
static consteval bool
|
||||
contains()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <LedgerEntryType... Types>
|
||||
struct VisitLedgerEntryTypes
|
||||
{
|
||||
static constexpr bool visitsAll = false;
|
||||
static constexpr bool visitsNone = false;
|
||||
static constexpr bool empty = sizeof...(Types) == 0;
|
||||
|
||||
template <LedgerEntryType Type>
|
||||
static consteval bool
|
||||
contains()
|
||||
{
|
||||
return ((Type == Types) || ...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -45,6 +46,9 @@ class ValidLoanBroker
|
||||
goodZeroDirectory(ReadView const& view, SLE::const_ref dir, beast::Journal const& j);
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltLOAN_BROKER, ltACCOUNT_ROOT, ltRIPPLE_STATE, ltMPTOKEN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -22,6 +23,8 @@ class ValidLoan
|
||||
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> loans_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltLOAN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -36,6 +37,9 @@ class ValidMPTIssuance
|
||||
std::vector<std::shared_ptr<SLE const>> deletedHoldings_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltMPTOKEN_ISSUANCE, ltMPTOKEN, ltRIPPLE_STATE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -64,6 +68,9 @@ class ValidMPTPayment
|
||||
hash_map<uint192, MPTData> data_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltMPTOKEN_ISSUANCE, ltMPTOKEN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -85,6 +92,8 @@ class ValidMPTTransfer
|
||||
hash_map<uint256, bool> deletedAuthorized_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltMPTOKEN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -32,6 +33,8 @@ class ValidNFTokenPage
|
||||
bool deletedLink_ = false;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltNFTOKEN_PAGE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
@@ -60,6 +63,8 @@ class NFTokenCountTracking
|
||||
std::uint32_t afterBurnedTotal_ = 0;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltACCOUNT_ROOT>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -17,6 +18,8 @@ class ValidPermissionedDEX
|
||||
hash_set<uint256> domains_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<ltDIR_NODE, ltOFFER>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -31,6 +32,9 @@ class ValidPermissionedDomain
|
||||
std::vector<SleStatus> sleStatus_;
|
||||
|
||||
public:
|
||||
static constexpr auto kRelevantLedgerEntryTypes =
|
||||
VisitLedgerEntryTypes<ltPERMISSIONED_DOMAIN>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/invariants/InvariantEntryTypes.h>
|
||||
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
@@ -153,6 +154,13 @@ public:
|
||||
[[nodiscard]] static std::int32_t
|
||||
computeCoarsestScale(std::vector<DeltaInfo> const& numbers);
|
||||
|
||||
static constexpr auto kRelevantLedgerEntryTypes = VisitLedgerEntryTypes<
|
||||
ltVAULT,
|
||||
ltMPTOKEN_ISSUANCE,
|
||||
ltMPTOKEN,
|
||||
ltACCOUNT_ROOT,
|
||||
ltRIPPLE_STATE>{};
|
||||
|
||||
void
|
||||
visitEntry(bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <xrpl/tx/invariants/PermissionedDomainInvariant.h>
|
||||
#include <xrpl/tx/invariants/VaultInvariant.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
@@ -38,79 +39,68 @@ namespace xrpl {
|
||||
|
||||
namespace {
|
||||
|
||||
template <class... Checkers>
|
||||
struct InvariantCheckTypes
|
||||
{
|
||||
};
|
||||
template <class Checker>
|
||||
using RelevantLedgerEntryTypes = std::remove_cvref_t<decltype(Checker::kRelevantLedgerEntryTypes)>;
|
||||
|
||||
using RoutedInvariantCheckTypes = InvariantCheckTypes<
|
||||
TransactionFeeCheck,
|
||||
AccountRootsNotDeleted,
|
||||
AccountRootsDeletedClean,
|
||||
LedgerEntryTypesMatch,
|
||||
XRPBalanceChecks,
|
||||
XRPNotCreated,
|
||||
NoXRPTrustLines,
|
||||
NoDeepFreezeTrustLinesWithoutFreeze,
|
||||
TransfersNotFrozen,
|
||||
NoBadOffers,
|
||||
NoZeroEscrow,
|
||||
ValidNewAccountRoot,
|
||||
ValidNFTokenPage,
|
||||
NFTokenCountTracking,
|
||||
ValidClawback,
|
||||
ValidMPTIssuance,
|
||||
ValidPermissionedDomain,
|
||||
ValidPermissionedDEX,
|
||||
ValidBookDirectory,
|
||||
ValidAMM,
|
||||
NoModifiedUnmodifiableFields,
|
||||
ValidPseudoAccounts,
|
||||
ValidLoanBroker,
|
||||
ValidLoan,
|
||||
ValidVault,
|
||||
ValidMPTPayment,
|
||||
ValidAmounts,
|
||||
ValidMPTTransfer>;
|
||||
template <class Checker>
|
||||
concept HasRelevantLedgerEntryTypes = requires { Checker::kRelevantLedgerEntryTypes; };
|
||||
|
||||
template <class Checker, class... Checkers>
|
||||
consteval std::size_t
|
||||
countInvariantCheck(InvariantCheckTypes<Checkers...>)
|
||||
template <class Checker>
|
||||
consteval bool
|
||||
hasInvariantVisitRoute()
|
||||
{
|
||||
return (std::size_t{0} + ... + (std::is_same_v<Checker, Checkers> ? 1 : 0));
|
||||
if constexpr (HasRelevantLedgerEntryTypes<Checker>)
|
||||
{
|
||||
using Types = RelevantLedgerEntryTypes<Checker>;
|
||||
return Types::visitsAll || Types::visitsNone || !Types::empty;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <std::size_t... Is>
|
||||
consteval bool
|
||||
allInvariantChecksAreRouted(std::index_sequence<Is...>)
|
||||
allInvariantChecksHaveVisitRoutes(std::index_sequence<Is...>)
|
||||
{
|
||||
return (
|
||||
(countInvariantCheck<std::tuple_element_t<Is, InvariantChecks>>(
|
||||
RoutedInvariantCheckTypes{}) == 1) &&
|
||||
...);
|
||||
return (hasInvariantVisitRoute<std::tuple_element_t<Is, InvariantChecks>>() && ...);
|
||||
}
|
||||
|
||||
static_assert(
|
||||
allInvariantChecksAreRouted(std::make_index_sequence<std::tuple_size_v<InvariantChecks>>{}),
|
||||
"Every invariant check must be routed exactly once.");
|
||||
allInvariantChecksHaveVisitRoutes(
|
||||
std::make_index_sequence<std::tuple_size_v<InvariantChecks>>{}),
|
||||
"Every invariant check must declare ledger-entry visit routing.");
|
||||
|
||||
template <class... Checkers>
|
||||
template <class Checker>
|
||||
void
|
||||
visitInvariantChecks(
|
||||
visitAllEntryInvariantCheck(
|
||||
InvariantChecks& checkers,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after)
|
||||
{
|
||||
(..., std::get<Checkers>(checkers).visitEntry(isDelete, before, after));
|
||||
if constexpr (RelevantLedgerEntryTypes<Checker>::visitsAll)
|
||||
std::get<Checker>(checkers).visitEntry(isDelete, before, after);
|
||||
}
|
||||
|
||||
template <std::size_t... Is>
|
||||
void
|
||||
visitAllEntryInvariantChecks(
|
||||
InvariantChecks& checkers,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
(...,
|
||||
visitAllEntryInvariantCheck<std::tuple_element_t<Is, InvariantChecks>>(
|
||||
checkers, isDelete, before, after));
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<LedgerEntryType>
|
||||
entryTypeForSpecificInvariants(SLE::const_ref before, SLE::const_ref after)
|
||||
entryTypeForMappedInvariants(SLE::const_ref before, SLE::const_ref after)
|
||||
{
|
||||
if (before && after && before->getType() != after->getType())
|
||||
{
|
||||
// LedgerEntryTypesMatch runs as a broad invariant and reports this.
|
||||
// LedgerEntryTypesMatch runs as an all-entry invariant and reports this.
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -121,102 +111,68 @@ entryTypeForSpecificInvariants(SLE::const_ref before, SLE::const_ref after)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <LedgerEntryType Type, class Checker>
|
||||
void
|
||||
visitTypeSpecificInvariantChecks(
|
||||
visitLedgerTypeInvariantCheck(
|
||||
InvariantChecks& checkers,
|
||||
LedgerEntryType type,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after)
|
||||
{
|
||||
switch (type)
|
||||
using Types = RelevantLedgerEntryTypes<Checker>;
|
||||
if constexpr (!Types::visitsAll && !Types::visitsNone && Types::template contains<Type>())
|
||||
{
|
||||
case ltACCOUNT_ROOT:
|
||||
visitInvariantChecks<
|
||||
AccountRootsNotDeleted,
|
||||
AccountRootsDeletedClean,
|
||||
XRPBalanceChecks,
|
||||
TransfersNotFrozen,
|
||||
ValidNewAccountRoot,
|
||||
NFTokenCountTracking,
|
||||
ValidAMM,
|
||||
ValidPseudoAccounts,
|
||||
ValidLoanBroker,
|
||||
ValidVault>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltRIPPLE_STATE:
|
||||
visitInvariantChecks<
|
||||
NoXRPTrustLines,
|
||||
NoDeepFreezeTrustLinesWithoutFreeze,
|
||||
TransfersNotFrozen,
|
||||
ValidMPTIssuance,
|
||||
ValidAMM,
|
||||
ValidLoanBroker,
|
||||
ValidVault>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltOFFER:
|
||||
visitInvariantChecks<NoBadOffers, ValidPermissionedDEX>(
|
||||
checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltESCROW:
|
||||
visitInvariantChecks<NoZeroEscrow>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltNFTOKEN_PAGE:
|
||||
visitInvariantChecks<ValidNFTokenPage>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltMPTOKEN_ISSUANCE:
|
||||
visitInvariantChecks<NoZeroEscrow, ValidMPTIssuance, ValidVault, ValidMPTPayment>(
|
||||
checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltMPTOKEN:
|
||||
visitInvariantChecks<
|
||||
NoZeroEscrow,
|
||||
ValidClawback,
|
||||
ValidMPTIssuance,
|
||||
ValidAMM,
|
||||
ValidLoanBroker,
|
||||
ValidVault,
|
||||
ValidMPTPayment,
|
||||
ValidMPTTransfer>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltPERMISSIONED_DOMAIN:
|
||||
visitInvariantChecks<ValidPermissionedDomain>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltDIR_NODE:
|
||||
visitInvariantChecks<ValidPermissionedDEX, ValidBookDirectory>(
|
||||
checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltAMM:
|
||||
visitInvariantChecks<ValidAMM>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltLOAN_BROKER:
|
||||
visitInvariantChecks<ValidLoanBroker>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltLOAN:
|
||||
visitInvariantChecks<ValidLoan>(checkers, isDelete, before, after);
|
||||
break;
|
||||
case ltVAULT:
|
||||
visitInvariantChecks<ValidVault>(checkers, isDelete, before, after);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
std::get<Checker>(checkers).visitEntry(isDelete, before, after);
|
||||
}
|
||||
}
|
||||
|
||||
template <LedgerEntryType Type, std::size_t... Is>
|
||||
void
|
||||
visitBroadInvariantChecks(
|
||||
visitLedgerTypeInvariantChecks(
|
||||
InvariantChecks& checkers,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
(...,
|
||||
visitLedgerTypeInvariantCheck<Type, std::tuple_element_t<Is, InvariantChecks>>(
|
||||
checkers, isDelete, before, after));
|
||||
}
|
||||
|
||||
using LedgerTypeInvariantVisitor = void (*)(InvariantChecks&, bool, SLE::const_ref, SLE::const_ref);
|
||||
|
||||
template <LedgerEntryType Type>
|
||||
void
|
||||
visitMappedLedgerTypeInvariantChecks(
|
||||
InvariantChecks& checkers,
|
||||
bool isDelete,
|
||||
SLE::const_ref before,
|
||||
SLE::const_ref after)
|
||||
{
|
||||
visitInvariantChecks<
|
||||
LedgerEntryTypesMatch,
|
||||
XRPNotCreated,
|
||||
NoModifiedUnmodifiableFields,
|
||||
ValidAmounts>(checkers, isDelete, before, after);
|
||||
visitLedgerTypeInvariantChecks<Type>(
|
||||
checkers,
|
||||
isDelete,
|
||||
before,
|
||||
after,
|
||||
std::make_index_sequence<std::tuple_size_v<InvariantChecks>>{});
|
||||
}
|
||||
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
#undef LEDGER_ENTRY
|
||||
|
||||
#define LEDGER_ENTRY(tag, ...) \
|
||||
std::pair<LedgerEntryType, LedgerTypeInvariantVisitor>{ \
|
||||
tag, &visitMappedLedgerTypeInvariantChecks<tag>},
|
||||
|
||||
static constexpr auto kLedgerTypeInvariantVisitors =
|
||||
std::to_array<std::pair<LedgerEntryType, LedgerTypeInvariantVisitor>>({
|
||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||
});
|
||||
|
||||
#undef LEDGER_ENTRY
|
||||
#pragma pop_macro("LEDGER_ENTRY")
|
||||
|
||||
} // namespace
|
||||
|
||||
ApplyContext::ApplyContext(
|
||||
@@ -296,10 +252,22 @@ ApplyContext::checkInvariantsHelper(
|
||||
// call each check's per-entry method
|
||||
visit([&checkers](
|
||||
uint256 const&, bool isDelete, SLE::const_ref before, SLE::const_ref after) {
|
||||
visitBroadInvariantChecks(checkers, isDelete, before, after);
|
||||
visitAllEntryInvariantChecks(
|
||||
checkers,
|
||||
isDelete,
|
||||
before,
|
||||
after,
|
||||
std::make_index_sequence<std::tuple_size_v<InvariantChecks>>{});
|
||||
|
||||
if (auto const type = entryTypeForSpecificInvariants(before, after))
|
||||
visitTypeSpecificInvariantChecks(checkers, *type, isDelete, before, after);
|
||||
if (auto const type = entryTypeForMappedInvariants(before, after))
|
||||
{
|
||||
auto const iter = std::find_if(
|
||||
kLedgerTypeInvariantVisitors.cbegin(),
|
||||
kLedgerTypeInvariantVisitors.cend(),
|
||||
[type](auto const& visitor) { return visitor.first == *type; });
|
||||
if (iter != kLedgerTypeInvariantVisitors.cend())
|
||||
iter->second(checkers, isDelete, before, after);
|
||||
}
|
||||
});
|
||||
|
||||
// Note: do not replace this logic with a `...&&` fold expression.
|
||||
|
||||
Reference in New Issue
Block a user