mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 01:06:48 +00:00
Merge remote-tracking branch 'upstream/develop' into sponsor
This commit is contained in:
73
include/xrpl/basics/MallocTrim.h
Normal file
73
include/xrpl/basics/MallocTrim.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// cSpell:ignore ptmalloc
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Allocator interaction note:
|
||||
// - This facility invokes glibc's malloc_trim(0) on Linux/glibc to request that
|
||||
// ptmalloc return free heap pages to the OS.
|
||||
// - If an alternative allocator (e.g. jemalloc or tcmalloc) is linked or
|
||||
// preloaded (LD_PRELOAD), calling glibc's malloc_trim typically has no effect
|
||||
// on the *active* heap. The call is harmless but may not reclaim memory
|
||||
// because those allocators manage their own arenas.
|
||||
// - Only glibc sbrk/arena space is eligible for trimming; large mmap-backed
|
||||
// allocations are usually returned to the OS on free regardless of trimming.
|
||||
// - Call at known reclamation points (e.g., after cache sweeps / online delete)
|
||||
// and consider rate limiting to avoid churn.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct MallocTrimReport
|
||||
{
|
||||
bool supported{false};
|
||||
int trimResult{-1};
|
||||
std::int64_t rssBeforeKB{-1};
|
||||
std::int64_t rssAfterKB{-1};
|
||||
std::chrono::microseconds durationUs{-1};
|
||||
std::int64_t minfltDelta{-1};
|
||||
std::int64_t majfltDelta{-1};
|
||||
|
||||
[[nodiscard]] std::int64_t
|
||||
deltaKB() const noexcept
|
||||
{
|
||||
if (rssBeforeKB < 0 || rssAfterKB < 0)
|
||||
return 0;
|
||||
return rssAfterKB - rssBeforeKB;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attempt to return freed memory to the operating system.
|
||||
*
|
||||
* On Linux with glibc malloc, this issues ::malloc_trim(0), which may release
|
||||
* free space from ptmalloc arenas back to the kernel. On other platforms, or if
|
||||
* a different allocator is in use, this function is a no-op and the report will
|
||||
* indicate that trimming is unsupported or had no effect.
|
||||
*
|
||||
* @param tag Identifier for logging/debugging purposes.
|
||||
* @param journal Journal for diagnostic logging.
|
||||
* @return Report containing before/after metrics and the trim result.
|
||||
*
|
||||
* @note If an alternative allocator (jemalloc/tcmalloc) is linked or preloaded,
|
||||
* calling glibc's malloc_trim may have no effect on the active heap. The
|
||||
* call is harmless but typically does not reclaim memory under those
|
||||
* allocators.
|
||||
*
|
||||
* @note Only memory served from glibc's sbrk/arena heaps is eligible for trim.
|
||||
* Large allocations satisfied via mmap are usually returned on free
|
||||
* independently of trimming.
|
||||
*
|
||||
* @note Intended for use after operations that free significant memory (e.g.,
|
||||
* cache sweeps, ledger cleanup, online delete). Consider rate limiting.
|
||||
*/
|
||||
MallocTrimReport
|
||||
mallocTrim(std::string_view tag, beast::Journal journal);
|
||||
|
||||
} // namespace xrpl
|
||||
155
include/xrpl/basics/Mutex.hpp
Normal file
155
include/xrpl/basics/Mutex.hpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <typename ProtectedDataType, typename MutexType>
|
||||
class Mutex;
|
||||
|
||||
/**
|
||||
* @brief A lock on a mutex that provides access to the protected data.
|
||||
*
|
||||
* @tparam ProtectedDataType data type to hold
|
||||
* @tparam LockType type of lock
|
||||
* @tparam MutexType type of mutex
|
||||
*/
|
||||
template <typename ProtectedDataType, template <typename...> typename LockType, typename MutexType>
|
||||
class Lock
|
||||
{
|
||||
LockType<MutexType> lock_;
|
||||
ProtectedDataType& data_;
|
||||
|
||||
public:
|
||||
/** @cond */
|
||||
ProtectedDataType const&
|
||||
operator*() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
ProtectedDataType&
|
||||
operator*()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
ProtectedDataType const&
|
||||
get() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
ProtectedDataType&
|
||||
get()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
ProtectedDataType const*
|
||||
operator->() const
|
||||
{
|
||||
return &data_;
|
||||
}
|
||||
|
||||
ProtectedDataType*
|
||||
operator->()
|
||||
{
|
||||
return &data_;
|
||||
}
|
||||
|
||||
operator LockType<MutexType>&() &
|
||||
{
|
||||
return lock_;
|
||||
}
|
||||
|
||||
operator LockType<MutexType> const&() const&
|
||||
{
|
||||
return lock_;
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
friend class Mutex<std::remove_const_t<ProtectedDataType>, MutexType>;
|
||||
|
||||
Lock(MutexType& mutex, ProtectedDataType& data) : lock_(mutex), data_(data)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A container for data that is protected by a mutex. Inspired by Mutex in Rust.
|
||||
*
|
||||
* @tparam ProtectedDataType data type to hold
|
||||
* @tparam MutexType type of mutex
|
||||
*/
|
||||
template <typename ProtectedDataType, typename MutexType = std::mutex>
|
||||
class Mutex
|
||||
{
|
||||
mutable MutexType mutex_;
|
||||
ProtectedDataType data_{};
|
||||
|
||||
public:
|
||||
Mutex() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Mutex object with the given data
|
||||
*
|
||||
* @param data The data to protect
|
||||
*/
|
||||
explicit Mutex(ProtectedDataType data) : data_(std::move(data))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Make a new Mutex object with the given data
|
||||
*
|
||||
* @tparam Args The types of the arguments to forward to the constructor of the protected data
|
||||
* @param args The arguments to forward to the constructor of the protected data
|
||||
* @return The Mutex object that protects the given data
|
||||
*/
|
||||
template <typename... Args>
|
||||
static Mutex
|
||||
make(Args&&... args)
|
||||
{
|
||||
return Mutex{ProtectedDataType{std::forward<Args>(args)...}};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the mutex and get a lock object allowing access to the protected data
|
||||
*
|
||||
* @tparam LockType The type of lock to use
|
||||
* @return A lock on the mutex and a reference to the protected data
|
||||
*/
|
||||
template <template <typename...> typename LockType = std::lock_guard>
|
||||
Lock<ProtectedDataType const, LockType, MutexType>
|
||||
lock() const
|
||||
{
|
||||
return {mutex_, data_};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the mutex and get a lock object allowing access to the protected data
|
||||
*
|
||||
* @tparam LockType The type of lock to use
|
||||
* @return A lock on the mutex and a reference to the protected data
|
||||
*/
|
||||
template <template <typename...> typename LockType = std::lock_guard>
|
||||
Lock<ProtectedDataType, LockType, MutexType>
|
||||
lock()
|
||||
{
|
||||
return {mutex_, data_};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
@@ -26,14 +27,14 @@ public:
|
||||
|
||||
SemanticVersion();
|
||||
|
||||
SemanticVersion(std::string const& version);
|
||||
SemanticVersion(std::string_view version);
|
||||
|
||||
/** Parse a semantic version string.
|
||||
The parsing is as strict as possible.
|
||||
@return `true` if the string was parsed.
|
||||
*/
|
||||
bool
|
||||
parse(std::string const& input);
|
||||
parse(std::string_view input);
|
||||
|
||||
/** Produce a string from semantic version components. */
|
||||
std::string
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
template <class F>
|
||||
@@ -11,16 +9,18 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
|
||||
, name_(name)
|
||||
, running_(false)
|
||||
, coro_(
|
||||
// Stack size of 1MB wasn't sufficient for deep calls. ASAN tests flagged the issue. Hence
|
||||
// increasing the size to 1.5MB.
|
||||
boost::context::protected_fixedsize_stack(1536 * 1024),
|
||||
[this, fn = std::forward<F>(f)](
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
boost::coroutines2::asymmetric_coroutine<void>::push_type& do_yield) {
|
||||
yield_ = &do_yield;
|
||||
yield();
|
||||
fn(shared_from_this());
|
||||
#ifndef NDEBUG
|
||||
finished_ = true;
|
||||
#endif
|
||||
},
|
||||
boost::coroutines::attributes(megabytes(1)))
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include <xrpl/core/detail/Workers.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <boost/coroutine/all.hpp>
|
||||
#include <boost/context/protected_fixedsize_stack.hpp>
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
|
||||
#include <set>
|
||||
|
||||
@@ -48,8 +49,8 @@ public:
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_run_;
|
||||
std::condition_variable cv_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::pull_type coro_;
|
||||
boost::coroutines::asymmetric_coroutine<void>::push_type* yield_;
|
||||
boost::coroutines2::coroutine<void>::pull_type coro_;
|
||||
boost::coroutines2::coroutine<void>::push_type* yield_;
|
||||
#ifndef NDEBUG
|
||||
bool finished_ = false;
|
||||
#endif
|
||||
|
||||
13
include/xrpl/git/Git.h
Normal file
13
include/xrpl/git/Git.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::git {
|
||||
|
||||
std::string const&
|
||||
getCommitHash();
|
||||
|
||||
std::string const&
|
||||
getBuildBranch();
|
||||
|
||||
} // namespace xrpl::git
|
||||
@@ -23,13 +23,13 @@ public:
|
||||
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||
|
||||
RawStateTable()
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
initialBufferSize)}
|
||||
: monotonic_resource_{
|
||||
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||
, items_{monotonic_resource_.get()} {};
|
||||
|
||||
RawStateTable(RawStateTable const& rhs)
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
initialBufferSize)}
|
||||
: monotonic_resource_{
|
||||
std::make_unique<boost::container::pmr::monotonic_buffer_resource>(initialBufferSize)}
|
||||
, items_{rhs.items_, monotonic_resource_.get()}
|
||||
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||
|
||||
|
||||
@@ -29,6 +29,18 @@ public:
|
||||
bool sslVerify,
|
||||
beast::Journal j);
|
||||
|
||||
/** Destroys the global SSL context created by initializeSSLContext().
|
||||
*
|
||||
* This releases the underlying boost::asio::ssl::context and any
|
||||
* associated OpenSSL resources. Must not be called while any
|
||||
* HTTPClient requests are in flight.
|
||||
*
|
||||
* @note Currently only called from tests during teardown. In production,
|
||||
* the SSL context lives for the lifetime of the process.
|
||||
*/
|
||||
static void
|
||||
cleanupSSLContext();
|
||||
|
||||
static void
|
||||
get(bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
|
||||
@@ -77,16 +77,16 @@ public:
|
||||
If the object is not found or an error is encountered, the
|
||||
result will indicate the condition.
|
||||
@note This will be called concurrently.
|
||||
@param key A pointer to the key data.
|
||||
@param hash The hash of the object.
|
||||
@param pObject [out] The created object if successful.
|
||||
@return The result of the operation.
|
||||
*/
|
||||
virtual Status
|
||||
fetch(void const* key, std::shared_ptr<NodeObject>* pObject) = 0;
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) = 0;
|
||||
|
||||
/** Fetch a batch synchronously. */
|
||||
virtual std::pair<std::vector<std::shared_ptr<NodeObject>>, Status>
|
||||
fetchBatch(std::vector<uint256 const*> const& hashes) = 0;
|
||||
fetchBatch(std::vector<uint256> const& hashes) = 0;
|
||||
|
||||
/** Store a single object.
|
||||
Depending on the implementation this may happen immediately
|
||||
|
||||
@@ -49,7 +49,7 @@ getFullVersionString();
|
||||
@return the encoded version in a 64-bit integer
|
||||
*/
|
||||
std::uint64_t
|
||||
encodeSoftwareVersion(char const* const versionStr);
|
||||
encodeSoftwareVersion(std::string_view versionStr);
|
||||
|
||||
/** Returns this server's version packed in a 64-bit integer. */
|
||||
std::uint64_t
|
||||
|
||||
@@ -64,6 +64,49 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// Feature names must not exceed this length (in characters, excluding the null terminator).
|
||||
static constexpr std::size_t maxFeatureNameSize = 63;
|
||||
// Reserve this exact feature-name length (in characters/bytes, excluding the null terminator)
|
||||
// so that a 32-byte uint256 (for example, in WASM or other interop contexts) can be used
|
||||
// as a compact, fixed-size feature selector without conflicting with human-readable names.
|
||||
static constexpr std::size_t reservedFeatureNameSize = 32;
|
||||
|
||||
// Both validFeatureNameSize and validFeatureName are consteval functions that can be used in
|
||||
// static_asserts to validate feature names at compile time. They are only used inside
|
||||
// enforceValidFeatureName in Feature.cpp, but are exposed here for testing. The expected
|
||||
// parameter `auto fn` is a constexpr lambda which returns a const char*, making it available
|
||||
// for compile-time evaluation. Read more in https://accu.org/journals/overload/30/172/wu/
|
||||
consteval auto
|
||||
validFeatureNameSize(auto fn) -> bool
|
||||
{
|
||||
constexpr char const* n = fn();
|
||||
// Note, std::strlen is not constexpr, we need to implement our own here.
|
||||
constexpr std::size_t N = [](auto n) {
|
||||
std::size_t ret = 0;
|
||||
for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
|
||||
;
|
||||
return ret;
|
||||
}(n);
|
||||
return N != reservedFeatureNameSize && //
|
||||
N <= maxFeatureNameSize;
|
||||
}
|
||||
|
||||
consteval auto
|
||||
validFeatureName(auto fn) -> bool
|
||||
{
|
||||
constexpr char const* n = fn();
|
||||
// Prevent the use of visually confusable characters and enforce that feature names
|
||||
// are always valid ASCII. This is needed because C++ allows Unicode identifiers.
|
||||
// Characters below 0x20 are nonprintable control characters, and characters with the 0x80 bit
|
||||
// set are non-ASCII (e.g. UTF-8 encoding of Unicode), so both are disallowed.
|
||||
for (auto ptr = n; *ptr != '\0'; ++ptr)
|
||||
{
|
||||
if (*ptr & 0x80 || *ptr < 0x20)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
|
||||
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
|
||||
|
||||
|
||||
@@ -30,9 +30,11 @@ public:
|
||||
Item(
|
||||
char const* name,
|
||||
KeyType type,
|
||||
std::initializer_list<SOElement> uniqueFields,
|
||||
std::initializer_list<SOElement> commonFields)
|
||||
: soTemplate_(uniqueFields, commonFields), name_(name), type_(type)
|
||||
std::vector<SOElement> uniqueFields,
|
||||
std::vector<SOElement> commonFields)
|
||||
: soTemplate_(std::move(uniqueFields), std::move(commonFields))
|
||||
, name_(name)
|
||||
, type_(type)
|
||||
{
|
||||
// Verify that KeyType is appropriate.
|
||||
static_assert(
|
||||
@@ -142,16 +144,16 @@ protected:
|
||||
|
||||
@param name The name of this format.
|
||||
@param type The type of this format.
|
||||
@param uniqueFields An std::initializer_list of unique fields
|
||||
@param commonFields An std::initializer_list of common fields
|
||||
@param uniqueFields A std::vector of unique fields
|
||||
@param commonFields A std::vector of common fields
|
||||
|
||||
@return The created format.
|
||||
*/
|
||||
Item const&
|
||||
add(char const* name,
|
||||
KeyType type,
|
||||
std::initializer_list<SOElement> uniqueFields,
|
||||
std::initializer_list<SOElement> commonFields = {})
|
||||
std::vector<SOElement> uniqueFields,
|
||||
std::vector<SOElement> commonFields = {})
|
||||
{
|
||||
if (auto const item = findByType(type))
|
||||
{
|
||||
@@ -160,7 +162,7 @@ protected:
|
||||
item->getName());
|
||||
}
|
||||
|
||||
formats_.emplace_front(name, type, uniqueFields, commonFields);
|
||||
formats_.emplace_front(name, type, std::move(uniqueFields), std::move(commonFields));
|
||||
Item const& item{formats_.front()};
|
||||
|
||||
names_[name] = &item;
|
||||
|
||||
@@ -2,36 +2,34 @@
|
||||
|
||||
#include <xrpl/protocol/KnownFormats.h>
|
||||
|
||||
namespace xrpl {
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
/** Identifiers for on-ledger objects.
|
||||
|
||||
Each ledger object requires a unique type identifier, which is stored
|
||||
within the object itself; this makes it possible to iterate the entire
|
||||
ledger and determine each object's type and verify that the object you
|
||||
retrieved from a given hash matches the expected type.
|
||||
Each ledger object requires a unique type identifier, which is stored within the object itself;
|
||||
this makes it possible to iterate the entire ledger and determine each object's type and verify
|
||||
that the object you retrieved from a given hash matches the expected type.
|
||||
|
||||
@warning Since these values are stored inside objects stored on the ledger
|
||||
they are part of the protocol. **Changing them should be avoided
|
||||
because without special handling, this will result in a hard
|
||||
@warning Since these values are stored inside objects stored on the ledger they are part of the
|
||||
protocol.
|
||||
**Changing them should be avoided because without special handling, this will result in a hard
|
||||
fork.**
|
||||
|
||||
@note Values outside this range may be used internally by the code for
|
||||
various purposes, but attempting to use such values to identify
|
||||
on-ledger objects will results in an invariant failure.
|
||||
@note Values outside this range may be used internally by the code for various purposes, but
|
||||
attempting to use such values to identify on-ledger objects will result in an invariant failure.
|
||||
|
||||
@note When retiring types, the specific values should not be removed but
|
||||
should be marked as [[deprecated]]. This is to avoid accidental
|
||||
reuse of identifiers.
|
||||
@note When retiring types, the specific values should not be removed but should be marked as
|
||||
[[deprecated]]. This is to avoid accidental reuse of identifiers.
|
||||
|
||||
@todo The C++ language does not enable checking for duplicate values
|
||||
here. If it becomes possible then we should do this.
|
||||
@todo The C++ language does not enable checking for duplicate values here.
|
||||
If it becomes possible then we should do this.
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
// clang-format off
|
||||
enum LedgerEntryType : std::uint16_t
|
||||
{
|
||||
enum LedgerEntryType : std::uint16_t {
|
||||
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
#undef LEDGER_ENTRY
|
||||
@@ -46,12 +44,10 @@ enum LedgerEntryType : std::uint16_t
|
||||
//---------------------------------------------------------------------------
|
||||
/** A special type, matching any ledger entry type.
|
||||
|
||||
The value does not represent a concrete type, but rather is used in
|
||||
contexts where the specific type of a ledger object is unimportant,
|
||||
unknown or unavailable.
|
||||
The value does not represent a concrete type, but rather is used in contexts where the
|
||||
specific type of a ledger object is unimportant, unknown or unavailable.
|
||||
|
||||
Objects with this special type cannot be created or stored on the
|
||||
ledger.
|
||||
Objects with this special type cannot be created or stored on the ledger.
|
||||
|
||||
\sa keylet::unchecked
|
||||
*/
|
||||
@@ -59,12 +55,11 @@ enum LedgerEntryType : std::uint16_t
|
||||
|
||||
/** A special type, matching any ledger type except directory nodes.
|
||||
|
||||
The value does not represent a concrete type, but rather is used in
|
||||
contexts where the ledger object must not be a directory node but
|
||||
its specific type is otherwise unimportant, unknown or unavailable.
|
||||
The value does not represent a concrete type, but rather is used in contexts where the
|
||||
ledger object must not be a directory node but its specific type is otherwise unimportant,
|
||||
unknown or unavailable.
|
||||
|
||||
Objects with this special type cannot be created or stored on the
|
||||
ledger.
|
||||
Objects with this special type cannot be created or stored on the ledger.
|
||||
|
||||
\sa keylet::child
|
||||
*/
|
||||
@@ -93,110 +88,193 @@ enum LedgerEntryType : std::uint16_t
|
||||
Support for this type of object was never implemented.
|
||||
No objects of this type were ever created.
|
||||
*/
|
||||
ltGENERATOR_MAP [[deprecated("This object type is not supported and should not be used.")]] = 0x0067,
|
||||
ltGENERATOR_MAP [[deprecated("This object type is not supported and should not be used.")]] =
|
||||
0x0067,
|
||||
};
|
||||
// clang-format off
|
||||
|
||||
/**
|
||||
/** Ledger object flags.
|
||||
|
||||
These flags are specified in ledger objects and modify their behavior.
|
||||
|
||||
@warning Ledger object flags form part of the protocol.
|
||||
**Changing them should be avoided because without special handling, this will result in a hard
|
||||
fork.**
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
enum LedgerSpecificFlags {
|
||||
// ltACCOUNT_ROOT
|
||||
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
|
||||
lsfRequireDestTag =
|
||||
0x00020000, // True, to require a DestinationTag for payments.
|
||||
lsfRequireAuth =
|
||||
0x00040000, // True, to require a authorization to hold IOUs.
|
||||
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
|
||||
lsfDisableMaster = 0x00100000, // True, force regular key
|
||||
lsfNoFreeze = 0x00200000, // True, cannot freeze ripple states
|
||||
lsfGlobalFreeze = 0x00400000, // True, all assets frozen
|
||||
lsfDefaultRipple =
|
||||
0x00800000, // True, incoming trust lines allow rippling by default
|
||||
lsfDepositAuth = 0x01000000, // True, all deposits require authorization
|
||||
/* // reserved for Hooks amendment
|
||||
lsfTshCollect = 0x02000000, // True, allow TSH collect-calls to acc hooks
|
||||
*/
|
||||
lsfDisallowIncomingNFTokenOffer =
|
||||
0x04000000, // True, reject new incoming NFT offers
|
||||
lsfDisallowIncomingCheck =
|
||||
0x08000000, // True, reject new checks
|
||||
lsfDisallowIncomingPayChan =
|
||||
0x10000000, // True, reject new paychans
|
||||
lsfDisallowIncomingTrustline =
|
||||
0x20000000, // True, reject new trustlines (only if no issued assets)
|
||||
lsfAllowTrustLineLocking =
|
||||
0x40000000, // True, enable trustline locking
|
||||
lsfAllowTrustLineClawback =
|
||||
0x80000000, // True, enable clawback
|
||||
lsfDisallowIncomingSponsor =
|
||||
0x00004000, // True, reject new sponsor
|
||||
#pragma push_macro("XMACRO")
|
||||
#pragma push_macro("TO_VALUE")
|
||||
#pragma push_macro("VALUE_TO_MAP")
|
||||
#pragma push_macro("NULL_NAME")
|
||||
#pragma push_macro("TO_MAP")
|
||||
#pragma push_macro("ALL_LEDGER_FLAGS")
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000, // True, offer was placed as a sell.
|
||||
lsfHybrid = 0x00040000, // True, offer is hybrid.
|
||||
#undef XMACRO
|
||||
#undef TO_VALUE
|
||||
#undef VALUE_TO_MAP
|
||||
#undef NULL_NAME
|
||||
#undef TO_MAP
|
||||
|
||||
// ltRIPPLE_STATE
|
||||
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
|
||||
lsfHighReserve = 0x00020000,
|
||||
lsfLowAuth = 0x00040000,
|
||||
lsfHighAuth = 0x00080000,
|
||||
lsfLowNoRipple = 0x00100000,
|
||||
lsfHighNoRipple = 0x00200000,
|
||||
lsfLowFreeze = 0x00400000, // True, low side has set freeze flag
|
||||
lsfHighFreeze = 0x00800000, // True, high side has set freeze flag
|
||||
lsfLowDeepFreeze = 0x02000000, // True, low side has set deep freeze flag
|
||||
lsfHighDeepFreeze = 0x04000000, // True, high side has set deep freeze flag
|
||||
lsfAMMNode = 0x01000000, // True, trust line to AMM. Used by client
|
||||
// apps to identify payments via AMM.
|
||||
#undef ALL_LEDGER_FLAGS
|
||||
|
||||
// ltSIGNER_LIST
|
||||
lsfOneOwnerCount = 0x00010000, // True, uses only one OwnerCount
|
||||
// clang-format off
|
||||
|
||||
// ltDIR_NODE
|
||||
lsfNFTokenBuyOffers = 0x00000001,
|
||||
lsfNFTokenSellOffers = 0x00000002,
|
||||
#define XMACRO(LEDGER_OBJECT, LSF_FLAG, LSF_FLAG2) \
|
||||
LEDGER_OBJECT(AccountRoot, \
|
||||
LSF_FLAG(lsfPasswordSpent, 0x00010000) /* True, if password set fee is spent. */ \
|
||||
LSF_FLAG(lsfRequireDestTag, 0x00020000) /* True, to require a DestinationTag for payments. */ \
|
||||
LSF_FLAG(lsfRequireAuth, 0x00040000) /* True, to require a authorization to hold IOUs. */ \
|
||||
LSF_FLAG(lsfDisallowXRP, 0x00080000) /* True, to disallow sending XRP. */ \
|
||||
LSF_FLAG(lsfDisableMaster, 0x00100000) /* True, force regular key */ \
|
||||
LSF_FLAG(lsfNoFreeze, 0x00200000) /* True, cannot freeze ripple states */ \
|
||||
LSF_FLAG(lsfGlobalFreeze, 0x00400000) /* True, all assets frozen */ \
|
||||
LSF_FLAG(lsfDefaultRipple, 0x00800000) /* True, incoming trust lines allow rippling by default */ \
|
||||
LSF_FLAG(lsfDepositAuth, 0x01000000) /* True, all deposits require authorization */ \
|
||||
LSF_FLAG(lsfDisallowIncomingNFTokenOffer, 0x04000000) /* True, reject new incoming NFT offers */ \
|
||||
LSF_FLAG(lsfDisallowIncomingCheck, 0x08000000) /* True, reject new checks */ \
|
||||
LSF_FLAG(lsfDisallowIncomingPayChan, 0x10000000) /* True, reject new paychans */ \
|
||||
LSF_FLAG(lsfDisallowIncomingTrustline, 0x20000000) /* True, reject new trustlines (only if no issued assets) */ \
|
||||
LSF_FLAG(lsfAllowTrustLineLocking, 0x40000000) /* True, enable trustline locking */ \
|
||||
LSF_FLAG(lsfAllowTrustLineClawback, 0x80000000) /* True, enable clawback */ \
|
||||
LSF_FLAG(lsfDisallowIncomingSponsor, 0x00004000)) /* True, reject new sponsor */ \
|
||||
\
|
||||
LEDGER_OBJECT(Offer, \
|
||||
LSF_FLAG(lsfPassive, 0x00010000) \
|
||||
LSF_FLAG(lsfSell, 0x00020000) /* True, offer was placed as a sell. */ \
|
||||
LSF_FLAG(lsfHybrid, 0x00040000)) /* True, offer is hybrid. */ \
|
||||
\
|
||||
LEDGER_OBJECT(RippleState, \
|
||||
LSF_FLAG(lsfLowReserve, 0x00010000) /* True, if entry counts toward reserve. */ \
|
||||
LSF_FLAG(lsfHighReserve, 0x00020000) \
|
||||
LSF_FLAG(lsfLowAuth, 0x00040000) \
|
||||
LSF_FLAG(lsfHighAuth, 0x00080000) \
|
||||
LSF_FLAG(lsfLowNoRipple, 0x00100000) \
|
||||
LSF_FLAG(lsfHighNoRipple, 0x00200000) \
|
||||
LSF_FLAG(lsfLowFreeze, 0x00400000) /* True, low side has set freeze flag */ \
|
||||
LSF_FLAG(lsfHighFreeze, 0x00800000) /* True, high side has set freeze flag */ \
|
||||
LSF_FLAG(lsfAMMNode, 0x01000000) /* True, trust line to AMM. */ \
|
||||
/* Used by client apps to identify payments via AMM. */ \
|
||||
LSF_FLAG(lsfLowDeepFreeze, 0x02000000) /* True, low side has set deep freeze flag */ \
|
||||
LSF_FLAG(lsfHighDeepFreeze, 0x04000000)) /* True, high side has set deep freeze flag */ \
|
||||
\
|
||||
LEDGER_OBJECT(SignerList, \
|
||||
LSF_FLAG(lsfOneOwnerCount, 0x00010000)) /* True, uses only one OwnerCount */ \
|
||||
\
|
||||
LEDGER_OBJECT(DirNode, \
|
||||
LSF_FLAG(lsfNFTokenBuyOffers, 0x00000001) \
|
||||
LSF_FLAG(lsfNFTokenSellOffers, 0x00000002)) \
|
||||
\
|
||||
LEDGER_OBJECT(NFTokenOffer, \
|
||||
LSF_FLAG(lsfSellNFToken, 0x00000001)) \
|
||||
\
|
||||
LEDGER_OBJECT(MPTokenIssuance, \
|
||||
LSF_FLAG(lsfMPTLocked, 0x00000001) /* Also used in ltMPTOKEN */ \
|
||||
LSF_FLAG(lsfMPTCanLock, 0x00000002) \
|
||||
LSF_FLAG(lsfMPTRequireAuth, 0x00000004) \
|
||||
LSF_FLAG(lsfMPTCanEscrow, 0x00000008) \
|
||||
LSF_FLAG(lsfMPTCanTrade, 0x00000010) \
|
||||
LSF_FLAG(lsfMPTCanTransfer, 0x00000020) \
|
||||
LSF_FLAG(lsfMPTCanClawback, 0x00000040)) \
|
||||
\
|
||||
LEDGER_OBJECT(MPTokenIssuanceMutable, \
|
||||
LSF_FLAG(lsmfMPTCanMutateCanLock, 0x00000002) \
|
||||
LSF_FLAG(lsmfMPTCanMutateRequireAuth, 0x00000004) \
|
||||
LSF_FLAG(lsmfMPTCanMutateCanEscrow, 0x00000008) \
|
||||
LSF_FLAG(lsmfMPTCanMutateCanTrade, 0x00000010) \
|
||||
LSF_FLAG(lsmfMPTCanMutateCanTransfer, 0x00000020) \
|
||||
LSF_FLAG(lsmfMPTCanMutateCanClawback, 0x00000040) \
|
||||
LSF_FLAG(lsmfMPTCanMutateMetadata, 0x00010000) \
|
||||
LSF_FLAG(lsmfMPTCanMutateTransferFee, 0x00020000)) \
|
||||
\
|
||||
LEDGER_OBJECT(MPToken, \
|
||||
LSF_FLAG2(lsfMPTLocked, 0x00000001) \
|
||||
LSF_FLAG(lsfMPTAuthorized, 0x00000002)) \
|
||||
\
|
||||
LEDGER_OBJECT(Credential, \
|
||||
LSF_FLAG(lsfAccepted, 0x00010000)) \
|
||||
\
|
||||
LEDGER_OBJECT(Vault, \
|
||||
LSF_FLAG(lsfVaultPrivate, 0x00010000)) \
|
||||
\
|
||||
LEDGER_OBJECT(Loan, \
|
||||
LSF_FLAG(lsfLoanDefault, 0x00010000) \
|
||||
LSF_FLAG(lsfLoanImpaired, 0x00020000) \
|
||||
LSF_FLAG(lsfLoanOverpayment, 0x00040000)) /* True, loan allows overpayments */ \
|
||||
\
|
||||
LEDGER_OBJECT(Sponsorship, \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForFee, 0x00010000) \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000))
|
||||
|
||||
// ltNFTOKEN_OFFER
|
||||
lsfSellNFToken = 0x00000001,
|
||||
// clang-format on
|
||||
|
||||
// ltMPTOKEN_ISSUANCE
|
||||
lsfMPTLocked = 0x00000001, // Also used in ltMPTOKEN
|
||||
lsfMPTCanLock = 0x00000002,
|
||||
lsfMPTRequireAuth = 0x00000004,
|
||||
lsfMPTCanEscrow = 0x00000008,
|
||||
lsfMPTCanTrade = 0x00000010,
|
||||
lsfMPTCanTransfer = 0x00000020,
|
||||
lsfMPTCanClawback = 0x00000040,
|
||||
// Create all the flag values as an enum.
|
||||
//
|
||||
// example:
|
||||
// enum LedgerSpecificFlags {
|
||||
// lsfPasswordSpent = 0x00010000,
|
||||
// lsfRequireDestTag = 0x00020000,
|
||||
// ...
|
||||
// };
|
||||
#define TO_VALUE(name, value) name = value,
|
||||
#define NULL_NAME(name, values) values
|
||||
#define NULL_OUTPUT(name, value)
|
||||
enum LedgerSpecificFlags : std::uint32_t { XMACRO(NULL_NAME, TO_VALUE, NULL_OUTPUT) };
|
||||
|
||||
lsmfMPTCanMutateCanLock = 0x00000002,
|
||||
lsmfMPTCanMutateRequireAuth = 0x00000004,
|
||||
lsmfMPTCanMutateCanEscrow = 0x00000008,
|
||||
lsmfMPTCanMutateCanTrade = 0x00000010,
|
||||
lsmfMPTCanMutateCanTransfer = 0x00000020,
|
||||
lsmfMPTCanMutateCanClawback = 0x00000040,
|
||||
lsmfMPTCanMutateMetadata = 0x00010000,
|
||||
lsmfMPTCanMutateTransferFee = 0x00020000,
|
||||
// Create getter functions for each set of flags using Meyer's singleton pattern.
|
||||
// This avoids static initialization order fiasco while still providing efficient access.
|
||||
// This is used below in `getAllLedgerFlags()` to generate the server_definitions RPC output.
|
||||
//
|
||||
// example:
|
||||
// inline LedgerFlagMap const& getAccountRootFlags() {
|
||||
// static LedgerFlagMap const flags = {
|
||||
// {"lsfPasswordSpent", 0x00010000},
|
||||
// {"lsfRequireDestTag", 0x00020000},
|
||||
// ...};
|
||||
// return flags;
|
||||
// }
|
||||
using LedgerFlagMap = std::map<std::string, std::uint32_t>;
|
||||
#define VALUE_TO_MAP(name, value) {#name, value},
|
||||
#define TO_MAP(name, values) \
|
||||
inline LedgerFlagMap const& get##name##Flags() \
|
||||
{ \
|
||||
static LedgerFlagMap const flags = {values}; \
|
||||
return flags; \
|
||||
}
|
||||
XMACRO(TO_MAP, VALUE_TO_MAP, VALUE_TO_MAP)
|
||||
|
||||
// ltMPTOKEN
|
||||
lsfMPTAuthorized = 0x00000002,
|
||||
// Create a getter function for all ledger flag maps using Meyer's singleton pattern.
|
||||
// This is used to generate the server_definitions RPC output.
|
||||
//
|
||||
// example:
|
||||
// inline std::vector<std::pair<std::string, LedgerFlagMap>> const& getAllLedgerFlags() {
|
||||
// static std::vector<std::pair<std::string, LedgerFlagMap>> const flags = {
|
||||
// {"AccountRoot", getAccountRootFlags()},
|
||||
// ...};
|
||||
// return flags;
|
||||
// }
|
||||
#define ALL_LEDGER_FLAGS(name, values) {#name, get##name##Flags()},
|
||||
inline std::vector<std::pair<std::string, LedgerFlagMap>> const&
|
||||
getAllLedgerFlags()
|
||||
{
|
||||
static std::vector<std::pair<std::string, LedgerFlagMap>> const flags = {
|
||||
XMACRO(ALL_LEDGER_FLAGS, NULL_OUTPUT, NULL_OUTPUT)};
|
||||
return flags;
|
||||
}
|
||||
|
||||
// ltCREDENTIAL
|
||||
lsfAccepted = 0x00010000,
|
||||
#undef XMACRO
|
||||
#undef TO_VALUE
|
||||
#undef VALUE_TO_MAP
|
||||
#undef NULL_NAME
|
||||
#undef NULL_OUTPUT
|
||||
#undef TO_MAP
|
||||
#undef ALL_LEDGER_FLAGS
|
||||
|
||||
// ltVAULT
|
||||
lsfVaultPrivate = 0x00010000,
|
||||
|
||||
// ltLOAN
|
||||
lsfLoanDefault = 0x00010000,
|
||||
lsfLoanImpaired = 0x00020000,
|
||||
lsfLoanOverpayment = 0x00040000, // True, loan allows overpayments
|
||||
|
||||
// ltSPONSORSHIP
|
||||
lsfSponsorshipRequireSignForFee = 0x00010000,
|
||||
lsfSponsorshipRequireSignForReserve = 0x00020000,
|
||||
};
|
||||
#pragma pop_macro("XMACRO")
|
||||
#pragma pop_macro("TO_VALUE")
|
||||
#pragma pop_macro("VALUE_TO_MAP")
|
||||
#pragma pop_macro("NULL_NAME")
|
||||
#pragma pop_macro("TO_MAP")
|
||||
#pragma pop_macro("ALL_LEDGER_FLAGS")
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -213,6 +291,10 @@ private:
|
||||
public:
|
||||
static LedgerFormats const&
|
||||
getInstance();
|
||||
|
||||
// Fields shared by all ledger entry formats:
|
||||
static std::vector<SOElement> const&
|
||||
getCommonFields();
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -97,8 +98,12 @@ public:
|
||||
operator=(SOTemplate&& other) = default;
|
||||
|
||||
/** Create a template populated with all fields.
|
||||
After creating the template fields cannot be
|
||||
added, modified, or removed.
|
||||
After creating the template fields cannot be added, modified, or removed.
|
||||
*/
|
||||
SOTemplate(std::vector<SOElement> uniqueFields, std::vector<SOElement> commonFields = {});
|
||||
|
||||
/** Create a template populated with all fields.
|
||||
Note: Defers to the vector constructor above.
|
||||
*/
|
||||
SOTemplate(
|
||||
std::initializer_list<SOElement> uniqueFields,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum TxnSql : char {
|
||||
enum class TxnSql : char {
|
||||
txnSqlNew = 'N',
|
||||
txnSqlConflict = 'C',
|
||||
txnSqlHeld = 'H',
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
getMetaSQL(
|
||||
Serializer rawTxn,
|
||||
std::uint32_t inLedger,
|
||||
char status,
|
||||
TxnSql status,
|
||||
std::string const& escapedMetaData) const;
|
||||
|
||||
std::vector<uint256> const&
|
||||
|
||||
@@ -16,8 +16,11 @@ namespace xrpl {
|
||||
/** A secret key. */
|
||||
class SecretKey
|
||||
{
|
||||
public:
|
||||
static constexpr std::size_t size_ = 32;
|
||||
|
||||
private:
|
||||
std::uint8_t buf_[32];
|
||||
std::uint8_t buf_[size_];
|
||||
|
||||
public:
|
||||
using const_iterator = std::uint8_t const*;
|
||||
@@ -27,9 +30,14 @@ public:
|
||||
SecretKey&
|
||||
operator=(SecretKey const&) = default;
|
||||
|
||||
bool
|
||||
operator==(SecretKey const&) = delete;
|
||||
bool
|
||||
operator!=(SecretKey const&) = delete;
|
||||
|
||||
~SecretKey();
|
||||
|
||||
SecretKey(std::array<std::uint8_t, 32> const& data);
|
||||
SecretKey(std::array<std::uint8_t, size_> const& data);
|
||||
SecretKey(Slice const& slice);
|
||||
|
||||
std::uint8_t const*
|
||||
@@ -78,16 +86,10 @@ public:
|
||||
};
|
||||
|
||||
inline bool
|
||||
operator==(SecretKey const& lhs, SecretKey const& rhs)
|
||||
{
|
||||
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
|
||||
}
|
||||
operator==(SecretKey const& lhs, SecretKey const& rhs) = delete;
|
||||
|
||||
inline bool
|
||||
operator!=(SecretKey const& lhs, SecretKey const& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
operator!=(SecretKey const& lhs, SecretKey const& rhs) = delete;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace xrpl {
|
||||
static inline std::string const&
|
||||
systemName()
|
||||
{
|
||||
static std::string const name = "ripple";
|
||||
static std::string const name = "xrpld";
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,316 +3,491 @@
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** Transaction flags.
|
||||
|
||||
These flags are specified in a transaction's 'Flags' field and modify the
|
||||
behavior of that transaction.
|
||||
These flags are specified in a transaction's 'Flags' field and modify
|
||||
the behavior of that transaction.
|
||||
|
||||
There are two types of flags:
|
||||
|
||||
(1) Universal flags: these are flags which apply to, and are interpreted
|
||||
the same way by, all transactions, except, perhaps,
|
||||
to special pseudo-transactions.
|
||||
(1) Universal flags: these are flags which apply to, and are interpreted the same way by,
|
||||
all transactions, except, perhaps, to special pseudo-transactions.
|
||||
|
||||
(2) Tx-Specific flags: these are flags which are interpreted according
|
||||
to the type of the transaction being executed.
|
||||
That is, the same numerical flag value may have
|
||||
different effects, depending on the transaction
|
||||
being executed.
|
||||
(2) Tx-Specific flags: these are flags which are interpreted according to the type of the
|
||||
transaction being executed. That is, the same numerical flag value may have different
|
||||
effects, depending on the transaction being executed.
|
||||
|
||||
@note The universal transaction flags occupy the high-order 8 bits. The
|
||||
tx-specific flags occupy the remaining 24 bits.
|
||||
@note The universal transaction flags occupy the high-order 8 bits.
|
||||
The tx-specific flags occupy the remaining 24 bits.
|
||||
|
||||
@warning Transaction flags form part of the protocol. **Changing them
|
||||
should be avoided because without special handling, this will
|
||||
result in a hard fork.**
|
||||
@warning Transaction flags form part of the protocol.
|
||||
**Changing them should be avoided because without special handling, this will result in
|
||||
a hard fork.**
|
||||
|
||||
@ingroup protocol
|
||||
*/
|
||||
|
||||
// Formatting equals sign aligned 4 spaces after longest prefix, except for
|
||||
// wrapped lines
|
||||
// clang-format off
|
||||
using FlagValue = std::uint32_t;
|
||||
|
||||
// Universal Transaction flags:
|
||||
constexpr std::uint32_t tfFullyCanonicalSig = 0x80000000;
|
||||
constexpr std::uint32_t tfInnerBatchTxn = 0x40000000;
|
||||
constexpr std::uint32_t tfUniversal = tfFullyCanonicalSig | tfInnerBatchTxn;
|
||||
constexpr std::uint32_t tfUniversalMask = ~tfUniversal;
|
||||
inline constexpr FlagValue tfFullyCanonicalSig = 0x80000000;
|
||||
inline constexpr FlagValue tfInnerBatchTxn = 0x40000000;
|
||||
inline constexpr FlagValue tfUniversal = tfFullyCanonicalSig | tfInnerBatchTxn;
|
||||
inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
|
||||
|
||||
// Sponsor flags (Global):
|
||||
constexpr std::uint32_t tfSponsorFee = 0x00000001;
|
||||
constexpr std::uint32_t tfSponsorReserve = 0x00000002;
|
||||
constexpr std::uint32_t tfSponsorMask = ~(tfSponsorFee | tfSponsorReserve);
|
||||
#pragma push_macro("XMACRO")
|
||||
#pragma push_macro("TO_VALUE")
|
||||
#pragma push_macro("VALUE_TO_MAP")
|
||||
#pragma push_macro("NULL_NAME")
|
||||
#pragma push_macro("NULL_OUTPUT")
|
||||
#pragma push_macro("TO_MAP")
|
||||
#pragma push_macro("TO_MASK")
|
||||
#pragma push_macro("VALUE_TO_MASK")
|
||||
#pragma push_macro("ALL_TX_FLAGS")
|
||||
#pragma push_macro("NULL_MASK_ADJ")
|
||||
#pragma push_macro("MASK_ADJ_TO_MASK")
|
||||
|
||||
// AccountSet flags:
|
||||
constexpr std::uint32_t tfRequireDestTag = 0x00010000;
|
||||
constexpr std::uint32_t tfOptionalDestTag = 0x00020000;
|
||||
constexpr std::uint32_t tfRequireAuth = 0x00040000;
|
||||
constexpr std::uint32_t tfOptionalAuth = 0x00080000;
|
||||
constexpr std::uint32_t tfDisallowXRP = 0x00100000;
|
||||
constexpr std::uint32_t tfAllowXRP = 0x00200000;
|
||||
constexpr std::uint32_t tfAccountSetMask =
|
||||
~(tfUniversal | tfRequireDestTag | tfOptionalDestTag | tfRequireAuth |
|
||||
tfOptionalAuth | tfDisallowXRP | tfAllowXRP);
|
||||
#undef XMACRO
|
||||
#undef TO_VALUE
|
||||
#undef VALUE_TO_MAP
|
||||
#undef NULL_NAME
|
||||
#undef NULL_OUTPUT
|
||||
#undef TO_MAP
|
||||
#undef TO_MASK
|
||||
#undef VALUE_TO_MASK
|
||||
#undef NULL_MASK_ADJ
|
||||
#undef MASK_ADJ_TO_MASK
|
||||
|
||||
// AccountSet SetFlag/ClearFlag values
|
||||
constexpr std::uint32_t asfRequireDest = 1;
|
||||
constexpr std::uint32_t asfRequireAuth = 2;
|
||||
constexpr std::uint32_t asfDisallowXRP = 3;
|
||||
constexpr std::uint32_t asfDisableMaster = 4;
|
||||
constexpr std::uint32_t asfAccountTxnID = 5;
|
||||
constexpr std::uint32_t asfNoFreeze = 6;
|
||||
constexpr std::uint32_t asfGlobalFreeze = 7;
|
||||
constexpr std::uint32_t asfDefaultRipple = 8;
|
||||
constexpr std::uint32_t asfDepositAuth = 9;
|
||||
constexpr std::uint32_t asfAuthorizedNFTokenMinter = 10;
|
||||
/* // reserved for Hooks amendment
|
||||
constexpr std::uint32_t asfTshCollect = 11;
|
||||
*/
|
||||
constexpr std::uint32_t asfDisallowIncomingNFTokenOffer = 12;
|
||||
constexpr std::uint32_t asfDisallowIncomingCheck = 13;
|
||||
constexpr std::uint32_t asfDisallowIncomingPayChan = 14;
|
||||
constexpr std::uint32_t asfDisallowIncomingTrustline = 15;
|
||||
constexpr std::uint32_t asfAllowTrustLineClawback = 16;
|
||||
constexpr std::uint32_t asfAllowTrustLineLocking = 17;
|
||||
constexpr std::uint32_t asfDisallowIncomingSponsor = 19;
|
||||
// clang-format off
|
||||
#undef ALL_TX_FLAGS
|
||||
|
||||
// OfferCreate flags:
|
||||
constexpr std::uint32_t tfPassive = 0x00010000;
|
||||
constexpr std::uint32_t tfImmediateOrCancel = 0x00020000;
|
||||
constexpr std::uint32_t tfFillOrKill = 0x00040000;
|
||||
constexpr std::uint32_t tfSell = 0x00080000;
|
||||
constexpr std::uint32_t tfHybrid = 0x00100000;
|
||||
constexpr std::uint32_t tfOfferCreateMask =
|
||||
~(tfUniversal | tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell | tfHybrid);
|
||||
|
||||
// Payment flags:
|
||||
constexpr std::uint32_t tfNoRippleDirect = 0x00010000;
|
||||
constexpr std::uint32_t tfPartialPayment = 0x00020000;
|
||||
constexpr std::uint32_t tfLimitQuality = 0x00040000;
|
||||
constexpr std::uint32_t tfSponsorCreatedAccount = 0x00080000;
|
||||
constexpr std::uint32_t tfPaymentMask =
|
||||
~(tfUniversal | tfPartialPayment | tfLimitQuality | tfNoRippleDirect | tfSponsorCreatedAccount);
|
||||
constexpr std::uint32_t tfMPTPaymentMask = ~(tfUniversal | tfPartialPayment);
|
||||
|
||||
// TrustSet flags:
|
||||
constexpr std::uint32_t tfSetfAuth = 0x00010000;
|
||||
constexpr std::uint32_t tfSetNoRipple = 0x00020000;
|
||||
constexpr std::uint32_t tfClearNoRipple = 0x00040000;
|
||||
constexpr std::uint32_t tfSetFreeze = 0x00100000;
|
||||
constexpr std::uint32_t tfClearFreeze = 0x00200000;
|
||||
constexpr std::uint32_t tfSetDeepFreeze = 0x00400000;
|
||||
constexpr std::uint32_t tfClearDeepFreeze = 0x00800000;
|
||||
constexpr std::uint32_t tfTrustSetMask =
|
||||
~(tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple | tfSetFreeze |
|
||||
tfClearFreeze | tfSetDeepFreeze | tfClearDeepFreeze);
|
||||
constexpr std::uint32_t tfTrustSetPermissionMask = ~(tfUniversal | tfSetfAuth | tfSetFreeze | tfClearFreeze);
|
||||
|
||||
// EnableAmendment flags:
|
||||
constexpr std::uint32_t tfGotMajority = 0x00010000;
|
||||
constexpr std::uint32_t tfLostMajority = 0x00020000;
|
||||
constexpr std::uint32_t tfChangeMask =
|
||||
~( tfUniversal | tfGotMajority | tfLostMajority);
|
||||
|
||||
// PaymentChannelClaim flags:
|
||||
constexpr std::uint32_t tfRenew = 0x00010000;
|
||||
constexpr std::uint32_t tfClose = 0x00020000;
|
||||
constexpr std::uint32_t tfPayChanClaimMask = ~(tfUniversal | tfRenew | tfClose);
|
||||
|
||||
// NFTokenMint flags:
|
||||
constexpr std::uint32_t const tfBurnable = 0x00000001;
|
||||
constexpr std::uint32_t const tfOnlyXRP = 0x00000002;
|
||||
constexpr std::uint32_t const tfTrustLine = 0x00000004;
|
||||
constexpr std::uint32_t const tfTransferable = 0x00000008;
|
||||
constexpr std::uint32_t const tfMutable = 0x00000010;
|
||||
|
||||
// MPTokenIssuanceCreate flags:
|
||||
// Note: tf/lsfMPTLocked is intentionally omitted, since this transaction
|
||||
// is not allowed to modify it.
|
||||
constexpr std::uint32_t const tfMPTCanLock = lsfMPTCanLock;
|
||||
constexpr std::uint32_t const tfMPTRequireAuth = lsfMPTRequireAuth;
|
||||
constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow;
|
||||
constexpr std::uint32_t const tfMPTCanTrade = lsfMPTCanTrade;
|
||||
constexpr std::uint32_t const tfMPTCanTransfer = lsfMPTCanTransfer;
|
||||
constexpr std::uint32_t const tfMPTCanClawback = lsfMPTCanClawback;
|
||||
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask =
|
||||
~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback);
|
||||
|
||||
// MPTokenIssuanceCreate MutableFlags:
|
||||
// Indicating specific fields or flags may be changed after issuance.
|
||||
constexpr std::uint32_t const tmfMPTCanMutateCanLock = lsmfMPTCanMutateCanLock;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateRequireAuth = lsmfMPTCanMutateRequireAuth;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateCanEscrow = lsmfMPTCanMutateCanEscrow;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateCanTrade = lsmfMPTCanMutateCanTrade;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateCanTransfer = lsmfMPTCanMutateCanTransfer;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateCanClawback = lsmfMPTCanMutateCanClawback;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateMetadata = lsmfMPTCanMutateMetadata;
|
||||
constexpr std::uint32_t const tmfMPTCanMutateTransferFee = lsmfMPTCanMutateTransferFee;
|
||||
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask =
|
||||
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow | tmfMPTCanMutateCanTrade
|
||||
| tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
|
||||
|
||||
// MPTokenAuthorize flags:
|
||||
constexpr std::uint32_t const tfMPTUnauthorize = 0x00000001;
|
||||
constexpr std::uint32_t const tfMPTokenAuthorizeMask = ~(tfUniversal | tfMPTUnauthorize);
|
||||
|
||||
// MPTokenIssuanceSet flags:
|
||||
constexpr std::uint32_t const tfMPTLock = 0x00000001;
|
||||
constexpr std::uint32_t const tfMPTUnlock = 0x00000002;
|
||||
constexpr std::uint32_t const tfMPTokenIssuanceSetMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
||||
constexpr std::uint32_t const tfMPTokenIssuanceSetPermissionMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
||||
|
||||
// MPTokenIssuanceSet MutableFlags:
|
||||
// Set or Clear flags.
|
||||
constexpr std::uint32_t const tmfMPTSetCanLock = 0x00000001;
|
||||
constexpr std::uint32_t const tmfMPTClearCanLock = 0x00000002;
|
||||
constexpr std::uint32_t const tmfMPTSetRequireAuth = 0x00000004;
|
||||
constexpr std::uint32_t const tmfMPTClearRequireAuth = 0x00000008;
|
||||
constexpr std::uint32_t const tmfMPTSetCanEscrow = 0x00000010;
|
||||
constexpr std::uint32_t const tmfMPTClearCanEscrow = 0x00000020;
|
||||
constexpr std::uint32_t const tmfMPTSetCanTrade = 0x00000040;
|
||||
constexpr std::uint32_t const tmfMPTClearCanTrade = 0x00000080;
|
||||
constexpr std::uint32_t const tmfMPTSetCanTransfer = 0x00000100;
|
||||
constexpr std::uint32_t const tmfMPTClearCanTransfer = 0x00000200;
|
||||
constexpr std::uint32_t const tmfMPTSetCanClawback = 0x00000400;
|
||||
constexpr std::uint32_t const tmfMPTClearCanClawback = 0x00000800;
|
||||
constexpr std::uint32_t const tmfMPTokenIssuanceSetMutableMask = ~(tmfMPTSetCanLock | tmfMPTClearCanLock |
|
||||
tmfMPTSetRequireAuth | tmfMPTClearRequireAuth | tmfMPTSetCanEscrow | tmfMPTClearCanEscrow |
|
||||
tmfMPTSetCanTrade | tmfMPTClearCanTrade | tmfMPTSetCanTransfer | tmfMPTClearCanTransfer |
|
||||
tmfMPTSetCanClawback | tmfMPTClearCanClawback);
|
||||
|
||||
// MPTokenIssuanceDestroy flags:
|
||||
constexpr std::uint32_t const tfMPTokenIssuanceDestroyMask = ~tfUniversal;
|
||||
|
||||
// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between
|
||||
// accounts allowed a TrustLine to be added to the issuer of that token
|
||||
// without explicit permission from that issuer. This was enabled by
|
||||
// minting the NFToken with the tfTrustLine flag set.
|
||||
// XMACRO parameters:
|
||||
// - TRANSACTION: handles the transaction name, its flags, and mask adjustment
|
||||
// - TF_FLAG: defines a new flag constant
|
||||
// - TF_FLAG2: references an existing flag constant (no new definition)
|
||||
// - MASK_ADJ: specifies flags to add back to the mask (making them invalid for this tx type)
|
||||
//
|
||||
// That capability could be used to attack the NFToken issuer. It
|
||||
// would be possible for two accounts to trade the NFToken back and forth
|
||||
// building up any number of TrustLines on the issuer, increasing the
|
||||
// issuer's reserve without bound.
|
||||
// Note: MASK_ADJ is used when a universal flag should be invalid for a specific transaction.
|
||||
// For example, Batch uses MASK_ADJ(tfInnerBatchTxn) because the outer Batch transaction
|
||||
// must not have tfInnerBatchTxn set (only inner transactions should have it).
|
||||
//
|
||||
// The fixRemoveNFTokenAutoTrustLine amendment disables minting with the
|
||||
// tfTrustLine flag as a way to prevent the attack. But until the
|
||||
// amendment passes we still need to keep the old behavior available.
|
||||
constexpr std::uint32_t const tfNFTokenMintMask =
|
||||
~(tfUniversal | tfBurnable | tfOnlyXRP | tfTransferable);
|
||||
|
||||
constexpr std::uint32_t const tfNFTokenMintOldMask =
|
||||
~( ~tfNFTokenMintMask | tfTrustLine);
|
||||
|
||||
// if featureDynamicNFT enabled then new flag allowing mutable URI available.
|
||||
constexpr std::uint32_t const tfNFTokenMintOldMaskWithMutable =
|
||||
~( ~tfNFTokenMintOldMask | tfMutable);
|
||||
|
||||
constexpr std::uint32_t const tfNFTokenMintMaskWithMutable =
|
||||
~( ~tfNFTokenMintMask | tfMutable);
|
||||
|
||||
// NFTokenCreateOffer flags:
|
||||
constexpr std::uint32_t const tfSellNFToken = 0x00000001;
|
||||
constexpr std::uint32_t const tfNFTokenCreateOfferMask =
|
||||
~(tfUniversal | tfSellNFToken);
|
||||
|
||||
// NFTokenCancelOffer flags:
|
||||
constexpr std::uint32_t const tfNFTokenCancelOfferMask = ~tfUniversal;
|
||||
|
||||
// NFTokenAcceptOffer flags:
|
||||
constexpr std::uint32_t const tfNFTokenAcceptOfferMask = ~tfUniversal;
|
||||
|
||||
// Clawback flags:
|
||||
constexpr std::uint32_t const tfClawbackMask = ~tfUniversal;
|
||||
|
||||
// AMM Flags:
|
||||
constexpr std::uint32_t tfLPToken = 0x00010000;
|
||||
constexpr std::uint32_t tfWithdrawAll = 0x00020000;
|
||||
constexpr std::uint32_t tfOneAssetWithdrawAll = 0x00040000;
|
||||
constexpr std::uint32_t tfSingleAsset = 0x00080000;
|
||||
constexpr std::uint32_t tfTwoAsset = 0x00100000;
|
||||
constexpr std::uint32_t tfOneAssetLPToken = 0x00200000;
|
||||
constexpr std::uint32_t tfLimitLPToken = 0x00400000;
|
||||
constexpr std::uint32_t tfTwoAssetIfEmpty = 0x00800000;
|
||||
constexpr std::uint32_t tfWithdrawSubTx =
|
||||
tfLPToken | tfSingleAsset | tfTwoAsset | tfOneAssetLPToken |
|
||||
tfLimitLPToken | tfWithdrawAll | tfOneAssetWithdrawAll;
|
||||
constexpr std::uint32_t tfDepositSubTx =
|
||||
tfLPToken | tfSingleAsset | tfTwoAsset | tfOneAssetLPToken |
|
||||
tfLimitLPToken | tfTwoAssetIfEmpty;
|
||||
constexpr std::uint32_t tfWithdrawMask = ~(tfUniversal | tfWithdrawSubTx);
|
||||
constexpr std::uint32_t tfDepositMask = ~(tfUniversal | tfDepositSubTx);
|
||||
|
||||
// AMMClawback flags:
|
||||
constexpr std::uint32_t tfClawTwoAssets = 0x00000001;
|
||||
constexpr std::uint32_t tfAMMClawbackMask = ~(tfUniversal | tfClawTwoAssets);
|
||||
|
||||
// BridgeModify flags:
|
||||
constexpr std::uint32_t tfClearAccountCreateAmount = 0x00010000;
|
||||
constexpr std::uint32_t tfBridgeModifyMask = ~(tfUniversal | tfClearAccountCreateAmount);
|
||||
|
||||
// VaultCreate flags:
|
||||
constexpr std::uint32_t const tfVaultPrivate = 0x00010000;
|
||||
static_assert(tfVaultPrivate == lsfVaultPrivate);
|
||||
constexpr std::uint32_t const tfVaultShareNonTransferable = 0x00020000;
|
||||
constexpr std::uint32_t const tfVaultCreateMask = ~(tfUniversal | tfVaultPrivate | tfVaultShareNonTransferable);
|
||||
|
||||
// Batch Flags:
|
||||
constexpr std::uint32_t tfAllOrNothing = 0x00010000;
|
||||
constexpr std::uint32_t tfOnlyOne = 0x00020000;
|
||||
constexpr std::uint32_t tfUntilFailure = 0x00040000;
|
||||
constexpr std::uint32_t tfIndependent = 0x00080000;
|
||||
/**
|
||||
* @note If nested Batch transactions are supported in the future, the tfInnerBatchTxn flag
|
||||
* will need to be removed from this mask to allow Batch transaction to be inside
|
||||
* the sfRawTransactions array.
|
||||
*/
|
||||
constexpr std::uint32_t const tfBatchMask =
|
||||
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
||||
|
||||
// LoanSet and LoanPay flags:
|
||||
// LoanSet: True, indicates the loan supports overpayments
|
||||
// LoanPay: True, indicates any excess in this payment can be used
|
||||
// as an overpayment. False, no overpayments will be taken.
|
||||
constexpr std::uint32_t const tfLoanOverpayment = 0x00010000;
|
||||
// LoanPay exclusive flags:
|
||||
// tfLoanFullPayment: True, indicates that the payment is an early
|
||||
// full payment. It must pay the entire loan including close
|
||||
// interest and fees, or it will fail. False: Not a full payment.
|
||||
constexpr std::uint32_t const tfLoanFullPayment = 0x00020000;
|
||||
// tfLoanLatePayment: True, indicates that the payment is late,
|
||||
// and includes late interest and fees. If the loan is not late,
|
||||
// it will fail. False: not a late payment. If the current payment
|
||||
// is overdue, the transaction will fail.
|
||||
constexpr std::uint32_t const tfLoanLatePayment = 0x00040000;
|
||||
constexpr std::uint32_t const tfLoanSetMask = ~(tfUniversal |
|
||||
tfLoanOverpayment);
|
||||
constexpr std::uint32_t const tfLoanPayMask = ~(tfUniversal |
|
||||
tfLoanOverpayment | tfLoanFullPayment | tfLoanLatePayment);
|
||||
|
||||
// LoanManage flags:
|
||||
constexpr std::uint32_t const tfLoanDefault = 0x00010000;
|
||||
constexpr std::uint32_t const tfLoanImpair = 0x00020000;
|
||||
constexpr std::uint32_t const tfLoanUnimpair = 0x00040000;
|
||||
constexpr std::uint32_t const tfLoanManageMask = ~(tfUniversal | tfLoanDefault | tfLoanImpair | tfLoanUnimpair);
|
||||
|
||||
// SponsorshipSet flags:
|
||||
constexpr std::uint32_t tfSponsorshipSetRequireSignForFee = 0x00010000;
|
||||
constexpr std::uint32_t tfSponsorshipClearRequireSignForFee = 0x00020000;
|
||||
constexpr std::uint32_t tfSponsorshipSetRequireSignForReserve = 0x00040000;
|
||||
constexpr std::uint32_t tfSponsorshipClearRequireSignForReserve = 0x00080000;
|
||||
constexpr std::uint32_t tfDeleteObject = 0x00100000;
|
||||
constexpr std::uint32_t tfSponsorshipSetMask = ~(tfUniversal | tfSponsorshipSetRequireSignForFee | tfSponsorshipClearRequireSignForFee | tfSponsorshipSetRequireSignForReserve | tfSponsorshipClearRequireSignForReserve | tfDeleteObject);
|
||||
constexpr std::uint32_t tfSponsorshipSetPermissionMask = ~(tfUniversal | tfSponsorshipSetRequireSignForFee | tfSponsorshipSetRequireSignForReserve);
|
||||
|
||||
// SponsorshipTransfer flags:
|
||||
constexpr std::uint32_t tfSponsorshipEnd = 0x00000001;
|
||||
constexpr std::uint32_t tfSponsorshipCreate = 0x00000002;
|
||||
constexpr std::uint32_t tfSponsorshipReassign = 0x00000004;
|
||||
constexpr std::uint32_t tfSponsorshipTransferMask = ~(tfUniversal | tfSponsorshipEnd | tfSponsorshipCreate | tfSponsorshipReassign);
|
||||
// TODO: Consider rewriting this using reflection in C++26 or later. Alternatively this could be a DSL processed by a script at build time.
|
||||
#define XMACRO(TRANSACTION, TF_FLAG, TF_FLAG2, MASK_ADJ) \
|
||||
TRANSACTION(AccountSet, \
|
||||
TF_FLAG(tfRequireDestTag, 0x00010000) \
|
||||
TF_FLAG(tfOptionalDestTag, 0x00020000) \
|
||||
TF_FLAG(tfRequireAuth, 0x00040000) \
|
||||
TF_FLAG(tfOptionalAuth, 0x00080000) \
|
||||
TF_FLAG(tfDisallowXRP, 0x00100000) \
|
||||
TF_FLAG(tfAllowXRP, 0x00200000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(OfferCreate, \
|
||||
TF_FLAG(tfPassive, 0x00010000) \
|
||||
TF_FLAG(tfImmediateOrCancel, 0x00020000) \
|
||||
TF_FLAG(tfFillOrKill, 0x00040000) \
|
||||
TF_FLAG(tfSell, 0x00080000) \
|
||||
TF_FLAG(tfHybrid, 0x00100000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(Payment, \
|
||||
TF_FLAG(tfNoRippleDirect, 0x00010000) \
|
||||
TF_FLAG(tfPartialPayment, 0x00020000) \
|
||||
TF_FLAG(tfLimitQuality, 0x00040000) \
|
||||
TF_FLAG(tfSponsorCreatedAccount, 0x00080000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(TrustSet, \
|
||||
TF_FLAG(tfSetfAuth, 0x00010000) \
|
||||
TF_FLAG(tfSetNoRipple, 0x00020000) \
|
||||
TF_FLAG(tfClearNoRipple, 0x00040000) \
|
||||
TF_FLAG(tfSetFreeze, 0x00100000) \
|
||||
TF_FLAG(tfClearFreeze, 0x00200000) \
|
||||
TF_FLAG(tfSetDeepFreeze, 0x00400000) \
|
||||
TF_FLAG(tfClearDeepFreeze, 0x00800000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(EnableAmendment, \
|
||||
TF_FLAG(tfGotMajority, 0x00010000) \
|
||||
TF_FLAG(tfLostMajority, 0x00020000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(PaymentChannelClaim, \
|
||||
TF_FLAG(tfRenew, 0x00010000) \
|
||||
TF_FLAG(tfClose, 0x00020000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(NFTokenMint, \
|
||||
TF_FLAG(tfBurnable, 0x00000001) \
|
||||
TF_FLAG(tfOnlyXRP, 0x00000002) \
|
||||
/* deprecated TF_FLAG(tfTrustLine, 0x00000004) */ \
|
||||
TF_FLAG(tfTransferable, 0x00000008) \
|
||||
TF_FLAG(tfMutable, 0x00000010), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(MPTokenIssuanceCreate, \
|
||||
/* Note: tf/lsfMPTLocked is intentionally omitted since this transaction is not allowed to modify it. */ \
|
||||
TF_FLAG(tfMPTCanLock, lsfMPTCanLock) \
|
||||
TF_FLAG(tfMPTRequireAuth, lsfMPTRequireAuth) \
|
||||
TF_FLAG(tfMPTCanEscrow, lsfMPTCanEscrow) \
|
||||
TF_FLAG(tfMPTCanTrade, lsfMPTCanTrade) \
|
||||
TF_FLAG(tfMPTCanTransfer, lsfMPTCanTransfer) \
|
||||
TF_FLAG(tfMPTCanClawback, lsfMPTCanClawback), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(MPTokenAuthorize, \
|
||||
TF_FLAG(tfMPTUnauthorize, 0x00000001), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(MPTokenIssuanceSet, \
|
||||
TF_FLAG(tfMPTLock, 0x00000001) \
|
||||
TF_FLAG(tfMPTUnlock, 0x00000002), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(NFTokenCreateOffer, \
|
||||
TF_FLAG(tfSellNFToken, 0x00000001), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(AMMDeposit, \
|
||||
TF_FLAG(tfLPToken, 0x00010000) \
|
||||
TF_FLAG(tfSingleAsset, 0x00080000) \
|
||||
TF_FLAG(tfTwoAsset, 0x00100000) \
|
||||
TF_FLAG(tfOneAssetLPToken, 0x00200000) \
|
||||
TF_FLAG(tfLimitLPToken, 0x00400000) \
|
||||
TF_FLAG(tfTwoAssetIfEmpty, 0x00800000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(AMMWithdraw, \
|
||||
TF_FLAG2(tfLPToken, 0x00010000) \
|
||||
TF_FLAG(tfWithdrawAll, 0x00020000) \
|
||||
TF_FLAG(tfOneAssetWithdrawAll, 0x00040000) \
|
||||
TF_FLAG2(tfSingleAsset, 0x00080000) \
|
||||
TF_FLAG2(tfTwoAsset, 0x00100000) \
|
||||
TF_FLAG2(tfOneAssetLPToken, 0x00200000) \
|
||||
TF_FLAG2(tfLimitLPToken, 0x00400000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(AMMClawback, \
|
||||
TF_FLAG(tfClawTwoAssets, 0x00000001), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(XChainModifyBridge, \
|
||||
TF_FLAG(tfClearAccountCreateAmount, 0x00010000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(VaultCreate, \
|
||||
TF_FLAG(tfVaultPrivate, lsfVaultPrivate) \
|
||||
TF_FLAG(tfVaultShareNonTransferable, 0x00020000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(Batch, \
|
||||
TF_FLAG(tfAllOrNothing, 0x00010000) \
|
||||
TF_FLAG(tfOnlyOne, 0x00020000) \
|
||||
TF_FLAG(tfUntilFailure, 0x00040000) \
|
||||
TF_FLAG(tfIndependent, 0x00080000), \
|
||||
MASK_ADJ(tfInnerBatchTxn)) /* Batch must reject tfInnerBatchTxn - only inner transactions should have this flag */ \
|
||||
\
|
||||
TRANSACTION(LoanSet, /* True indicates the loan supports overpayments */ \
|
||||
TF_FLAG(tfLoanOverpayment, 0x00010000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(LoanPay, /* True indicates any excess in this payment can be used as an overpayment. */ \
|
||||
/* False: no overpayments will be taken. */ \
|
||||
TF_FLAG2(tfLoanOverpayment, 0x00010000) \
|
||||
TF_FLAG(tfLoanFullPayment, 0x00020000) /* True indicates that the payment is an early full payment. */ \
|
||||
/* It must pay the entire loan including close interest and fees, or it will fail. */ \
|
||||
/* False: Not a full payment. */ \
|
||||
TF_FLAG(tfLoanLatePayment, 0x00040000), /* True indicates that the payment is late, and includes late interest and fees. */ \
|
||||
/* If the loan is not late, it will fail. */ \
|
||||
/* False: not a late payment. If the current payment is overdue, the transaction will fail.*/ \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(LoanManage, \
|
||||
TF_FLAG(tfLoanDefault, 0x00010000) \
|
||||
TF_FLAG(tfLoanImpair, 0x00020000) \
|
||||
TF_FLAG(tfLoanUnimpair, 0x00040000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(SponsorshipSet, \
|
||||
TF_FLAG(tfSponsorshipSetRequireSignForFee, 0x00010000) \
|
||||
TF_FLAG(tfSponsorshipClearRequireSignForFee, 0x00020000) \
|
||||
TF_FLAG(tfSponsorshipSetRequireSignForReserve, 0x00040000) \
|
||||
TF_FLAG(tfSponsorshipClearRequireSignForReserve, 0x00080000) \
|
||||
TF_FLAG(tfDeleteObject, 0x00100000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(SponsorshipTransfer, \
|
||||
TF_FLAG(tfSponsorshipEnd, 0x00000001) \
|
||||
TF_FLAG(tfSponsorshipCreate, 0x00000002) \
|
||||
TF_FLAG(tfSponsorshipReassign, 0x00000004), \
|
||||
MASK_ADJ(0))
|
||||
|
||||
// clang-format on
|
||||
|
||||
// Create all the flag values.
|
||||
//
|
||||
// example:
|
||||
// inline constexpr FlagValue tfAccountSetRequireDestTag = 0x00010000;
|
||||
#define TO_VALUE(name, value) inline constexpr FlagValue name = value;
|
||||
#define NULL_NAME(name, values, maskAdj) values
|
||||
#define NULL_OUTPUT(name, value)
|
||||
#define NULL_MASK_ADJ(value)
|
||||
XMACRO(NULL_NAME, TO_VALUE, NULL_OUTPUT, NULL_MASK_ADJ)
|
||||
|
||||
// Create masks for each transaction type that has flags.
|
||||
//
|
||||
// example:
|
||||
// inline constexpr FlagValue tfAccountSetMask = ~(tfUniversal | tfRequireDestTag |
|
||||
// tfOptionalDestTag | tfRequireAuth | tfOptionalAuth | tfDisallowXRP | tfAllowXRP);
|
||||
//
|
||||
// The mask adjustment (maskAdj) allows adding flags back to the mask, making them invalid.
|
||||
// For example, Batch uses MASK_ADJ(tfInnerBatchTxn) to reject tfInnerBatchTxn on outer Batch.
|
||||
#define TO_MASK(name, values, maskAdj) \
|
||||
inline constexpr FlagValue tf##name##Mask = ~(tfUniversal values) | maskAdj;
|
||||
#define VALUE_TO_MASK(name, value) | name
|
||||
#define MASK_ADJ_TO_MASK(value) value
|
||||
XMACRO(TO_MASK, VALUE_TO_MASK, VALUE_TO_MASK, MASK_ADJ_TO_MASK)
|
||||
|
||||
// Verify that tfBatchMask correctly rejects tfInnerBatchTxn.
|
||||
// The outer Batch transaction must NOT have tfInnerBatchTxn set; only inner transactions should
|
||||
// have it.
|
||||
static_assert(
|
||||
(tfBatchMask & tfInnerBatchTxn) == tfInnerBatchTxn,
|
||||
"tfBatchMask must include tfInnerBatchTxn to reject it on outer Batch");
|
||||
|
||||
// Verify that other transaction masks correctly allow tfInnerBatchTxn.
|
||||
// Inner transactions need tfInnerBatchTxn to be valid, so these masks must not reject it.
|
||||
static_assert(
|
||||
(tfPaymentMask & tfInnerBatchTxn) == 0,
|
||||
"tfPaymentMask must not reject tfInnerBatchTxn");
|
||||
static_assert(
|
||||
(tfAccountSetMask & tfInnerBatchTxn) == 0,
|
||||
"tfAccountSetMask must not reject tfInnerBatchTxn");
|
||||
|
||||
// Create getter functions for each set of flags using Meyer's singleton pattern.
|
||||
// This avoids static initialization order fiasco while still providing efficient access.
|
||||
// This is used below in `getAllTxFlags()` to generate the server_definitions RPC
|
||||
// output.
|
||||
//
|
||||
// example:
|
||||
// inline FlagMap const& getAccountSetFlags() {
|
||||
// static FlagMap const flags = {
|
||||
// {"tfRequireDestTag", 0x00010000},
|
||||
// {"tfOptionalDestTag", 0x00020000},
|
||||
// ...};
|
||||
// return flags;
|
||||
// }
|
||||
using FlagMap = std::map<std::string, FlagValue>;
|
||||
#define VALUE_TO_MAP(name, value) {#name, value},
|
||||
#define TO_MAP(name, values, maskAdj) \
|
||||
inline FlagMap const& get##name##Flags() \
|
||||
{ \
|
||||
static FlagMap const flags = {values}; \
|
||||
return flags; \
|
||||
}
|
||||
XMACRO(TO_MAP, VALUE_TO_MAP, VALUE_TO_MAP, NULL_MASK_ADJ)
|
||||
|
||||
inline FlagMap const&
|
||||
getUniversalFlags()
|
||||
{
|
||||
static FlagMap const flags = {
|
||||
{"tfFullyCanonicalSig", tfFullyCanonicalSig}, {"tfInnerBatchTxn", tfInnerBatchTxn}};
|
||||
return flags;
|
||||
}
|
||||
|
||||
// Create a getter function for all transaction flag maps using Meyer's singleton pattern.
|
||||
// This is used to generate the server_definitions RPC output.
|
||||
//
|
||||
// example:
|
||||
// inline FlagMapPairList const& getAllTxFlags() {
|
||||
// static FlagMapPairList const flags = {
|
||||
// {"AccountSet", getAccountSetFlags()},
|
||||
// ...};
|
||||
// return flags;
|
||||
// }
|
||||
using FlagMapPairList = std::vector<std::pair<std::string, FlagMap>>;
|
||||
#define ALL_TX_FLAGS(name, values, maskAdj) {#name, get##name##Flags()},
|
||||
inline FlagMapPairList const&
|
||||
getAllTxFlags()
|
||||
{
|
||||
static FlagMapPairList const flags = {
|
||||
{"universal", getUniversalFlags()},
|
||||
XMACRO(ALL_TX_FLAGS, NULL_OUTPUT, NULL_OUTPUT, NULL_MASK_ADJ)};
|
||||
return flags;
|
||||
}
|
||||
|
||||
#undef XMACRO
|
||||
#undef TO_VALUE
|
||||
#undef VALUE_TO_MAP
|
||||
#undef NULL_NAME
|
||||
#undef NULL_OUTPUT
|
||||
#undef TO_MAP
|
||||
#undef TO_MASK
|
||||
#undef VALUE_TO_MASK
|
||||
#undef ALL_TX_FLAGS
|
||||
#undef NULL_MASK_ADJ
|
||||
#undef MASK_ADJ_TO_MASK
|
||||
|
||||
#pragma pop_macro("XMACRO")
|
||||
#pragma pop_macro("TO_VALUE")
|
||||
#pragma pop_macro("VALUE_TO_MAP")
|
||||
#pragma pop_macro("NULL_NAME")
|
||||
#pragma pop_macro("NULL_OUTPUT")
|
||||
#pragma pop_macro("TO_MAP")
|
||||
#pragma pop_macro("TO_MASK")
|
||||
#pragma pop_macro("VALUE_TO_MASK")
|
||||
#pragma pop_macro("ALL_TX_FLAGS")
|
||||
#pragma pop_macro("NULL_MASK_ADJ")
|
||||
#pragma pop_macro("MASK_ADJ_TO_MASK")
|
||||
|
||||
// Additional transaction masks and combos
|
||||
inline constexpr FlagValue tfMPTPaymentMask = ~(tfUniversal | tfPartialPayment);
|
||||
inline constexpr FlagValue tfTrustSetPermissionMask =
|
||||
~(tfUniversal | tfSetfAuth | tfSetFreeze | tfClearFreeze);
|
||||
inline constexpr FlagValue tfSponsorshipSetPermissionMask =
|
||||
~(tfUniversal | tfSponsorshipSetRequireSignForFee | tfSponsorshipSetRequireSignForReserve);
|
||||
|
||||
// MPTokenIssuanceCreate MutableFlags:
|
||||
// Indicating specific fields or flags may be changed after issuance.
|
||||
inline constexpr FlagValue tmfMPTCanMutateCanLock = lsmfMPTCanMutateCanLock;
|
||||
inline constexpr FlagValue tmfMPTCanMutateRequireAuth = lsmfMPTCanMutateRequireAuth;
|
||||
inline constexpr FlagValue tmfMPTCanMutateCanEscrow = lsmfMPTCanMutateCanEscrow;
|
||||
inline constexpr FlagValue tmfMPTCanMutateCanTrade = lsmfMPTCanMutateCanTrade;
|
||||
inline constexpr FlagValue tmfMPTCanMutateCanTransfer = lsmfMPTCanMutateCanTransfer;
|
||||
inline constexpr FlagValue tmfMPTCanMutateCanClawback = lsmfMPTCanMutateCanClawback;
|
||||
inline constexpr FlagValue tmfMPTCanMutateMetadata = lsmfMPTCanMutateMetadata;
|
||||
inline constexpr FlagValue tmfMPTCanMutateTransferFee = lsmfMPTCanMutateTransferFee;
|
||||
inline constexpr FlagValue tmfMPTokenIssuanceCreateMutableMask =
|
||||
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow |
|
||||
tmfMPTCanMutateCanTrade | tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback |
|
||||
tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
|
||||
|
||||
// MPTokenIssuanceSet MutableFlags:
|
||||
// Set or Clear flags.
|
||||
|
||||
inline constexpr FlagValue tmfMPTSetCanLock = 0x00000001;
|
||||
inline constexpr FlagValue tmfMPTClearCanLock = 0x00000002;
|
||||
inline constexpr FlagValue tmfMPTSetRequireAuth = 0x00000004;
|
||||
inline constexpr FlagValue tmfMPTClearRequireAuth = 0x00000008;
|
||||
inline constexpr FlagValue tmfMPTSetCanEscrow = 0x00000010;
|
||||
inline constexpr FlagValue tmfMPTClearCanEscrow = 0x00000020;
|
||||
inline constexpr FlagValue tmfMPTSetCanTrade = 0x00000040;
|
||||
inline constexpr FlagValue tmfMPTClearCanTrade = 0x00000080;
|
||||
inline constexpr FlagValue tmfMPTSetCanTransfer = 0x00000100;
|
||||
inline constexpr FlagValue tmfMPTClearCanTransfer = 0x00000200;
|
||||
inline constexpr FlagValue tmfMPTSetCanClawback = 0x00000400;
|
||||
inline constexpr FlagValue tmfMPTClearCanClawback = 0x00000800;
|
||||
inline constexpr FlagValue tmfMPTokenIssuanceSetMutableMask = ~(
|
||||
tmfMPTSetCanLock | tmfMPTClearCanLock | tmfMPTSetRequireAuth | tmfMPTClearRequireAuth |
|
||||
tmfMPTSetCanEscrow | tmfMPTClearCanEscrow | tmfMPTSetCanTrade | tmfMPTClearCanTrade |
|
||||
tmfMPTSetCanTransfer | tmfMPTClearCanTransfer | tmfMPTSetCanClawback | tmfMPTClearCanClawback);
|
||||
|
||||
// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between accounts allowed a
|
||||
// TrustLine to be added to the issuer of that token without explicit permission from that issuer.
|
||||
// This was enabled by minting the NFToken with the tfTrustLine flag set.
|
||||
//
|
||||
// That capability could be used to attack the NFToken issuer.
|
||||
// It would be possible for two accounts to trade the NFToken back and forth building up any number
|
||||
// of TrustLines on the issuer, increasing the issuer's reserve without bound.
|
||||
//
|
||||
// The fixRemoveNFTokenAutoTrustLine amendment disables minting with the tfTrustLine flag as a way
|
||||
// to prevent the attack. But until the amendment passes we still need to keep the old behavior
|
||||
// available.
|
||||
inline constexpr FlagValue tfTrustLine = 0x00000004; // needed for backwards compatibility
|
||||
inline constexpr FlagValue tfNFTokenMintMaskWithoutMutable =
|
||||
~(tfUniversal | tfBurnable | tfOnlyXRP | tfTransferable);
|
||||
|
||||
inline constexpr FlagValue tfNFTokenMintOldMask = ~(~tfNFTokenMintMaskWithoutMutable | tfTrustLine);
|
||||
|
||||
// if featureDynamicNFT enabled then new flag allowing mutable URI available.
|
||||
inline constexpr FlagValue tfNFTokenMintOldMaskWithMutable = ~(~tfNFTokenMintOldMask | tfMutable);
|
||||
|
||||
inline constexpr FlagValue tfWithdrawSubTx = tfLPToken | tfSingleAsset | tfTwoAsset |
|
||||
tfOneAssetLPToken | tfLimitLPToken | tfWithdrawAll | tfOneAssetWithdrawAll;
|
||||
inline constexpr FlagValue tfDepositSubTx =
|
||||
tfLPToken | tfSingleAsset | tfTwoAsset | tfOneAssetLPToken | tfLimitLPToken | tfTwoAssetIfEmpty;
|
||||
|
||||
#pragma push_macro("ACCOUNTSET_FLAGS")
|
||||
#pragma push_macro("ACCOUNTSET_FLAG_TO_VALUE")
|
||||
#pragma push_macro("ACCOUNTSET_FLAG_TO_MAP")
|
||||
|
||||
// AccountSet SetFlag/ClearFlag values
|
||||
#define ACCOUNTSET_FLAGS(ASF_FLAG) \
|
||||
ASF_FLAG(asfRequireDest, 1) \
|
||||
ASF_FLAG(asfRequireAuth, 2) \
|
||||
ASF_FLAG(asfDisallowXRP, 3) \
|
||||
ASF_FLAG(asfDisableMaster, 4) \
|
||||
ASF_FLAG(asfAccountTxnID, 5) \
|
||||
ASF_FLAG(asfNoFreeze, 6) \
|
||||
ASF_FLAG(asfGlobalFreeze, 7) \
|
||||
ASF_FLAG(asfDefaultRipple, 8) \
|
||||
ASF_FLAG(asfDepositAuth, 9) \
|
||||
ASF_FLAG(asfAuthorizedNFTokenMinter, 10) \
|
||||
/* 11 is reserved for Hooks amendment */ \
|
||||
/* ASF_FLAG(asfTshCollect, 11) */ \
|
||||
ASF_FLAG(asfDisallowIncomingNFTokenOffer, 12) \
|
||||
ASF_FLAG(asfDisallowIncomingCheck, 13) \
|
||||
ASF_FLAG(asfDisallowIncomingPayChan, 14) \
|
||||
ASF_FLAG(asfDisallowIncomingTrustline, 15) \
|
||||
ASF_FLAG(asfAllowTrustLineClawback, 16) \
|
||||
ASF_FLAG(asfAllowTrustLineLocking, 17) \
|
||||
ASF_FLAG(asfDisallowIncomingSponsor, 19)
|
||||
|
||||
#define ACCOUNTSET_FLAG_TO_VALUE(name, value) inline constexpr FlagValue name = value;
|
||||
#define ACCOUNTSET_FLAG_TO_MAP(name, value) {#name, value},
|
||||
|
||||
ACCOUNTSET_FLAGS(ACCOUNTSET_FLAG_TO_VALUE)
|
||||
|
||||
inline std::map<std::string, FlagValue> const&
|
||||
getAsfFlagMap()
|
||||
{
|
||||
static std::map<std::string, FlagValue> const flags = {
|
||||
ACCOUNTSET_FLAGS(ACCOUNTSET_FLAG_TO_MAP)};
|
||||
return flags;
|
||||
}
|
||||
|
||||
#undef ACCOUNTSET_FLAG_TO_VALUE
|
||||
#undef ACCOUNTSET_FLAG_TO_MAP
|
||||
#undef ACCOUNTSET_FLAGS
|
||||
|
||||
#pragma pop_macro("ACCOUNTSET_FLAG_TO_VALUE")
|
||||
#pragma pop_macro("ACCOUNTSET_FLAG_TO_MAP")
|
||||
#pragma pop_macro("ACCOUNTSET_FLAGS")
|
||||
|
||||
#pragma push_macro("SPONSOR_FLAGS")
|
||||
#pragma push_macro("SPONSOR_FLAG_TO_VALUE")
|
||||
#pragma push_macro("SPONSOR_FLAG_TO_MAP")
|
||||
|
||||
// Sponsor Flag values
|
||||
#define SPONSOR_FLAGS(SPF_FLAG) \
|
||||
SPF_FLAG(spfSponsorFee, 1) \
|
||||
SPF_FLAG(spfSponsorReserve, 2)
|
||||
|
||||
#define SPONSOR_FLAG_TO_VALUE(name, value) inline constexpr FlagValue name = value;
|
||||
#define SPONSOR_FLAG_TO_MAP(name, value) {#name, value},
|
||||
|
||||
SPONSOR_FLAGS(SPONSOR_FLAG_TO_VALUE)
|
||||
|
||||
inline std::map<std::string, FlagValue> const&
|
||||
getspfFlagMap()
|
||||
{
|
||||
static std::map<std::string, FlagValue> const flags = {SPONSOR_FLAGS(SPONSOR_FLAG_TO_MAP)};
|
||||
return flags;
|
||||
}
|
||||
|
||||
#undef SPONSOR_FLAG_TO_VALUE
|
||||
#undef SPONSOR_FLAG_TO_MAP
|
||||
#undef SPONSOR_FLAGS
|
||||
|
||||
#pragma pop_macro("SPONSOR_FLAG_TO_VALUE")
|
||||
#pragma pop_macro("SPONSOR_FLAG_TO_MAP")
|
||||
#pragma pop_macro("SPONSOR_FLAGS")
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <xrpl/protocol/KnownFormats.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** Transaction type identifiers.
|
||||
@@ -73,6 +75,9 @@ private:
|
||||
public:
|
||||
static TxFormats const&
|
||||
getInstance();
|
||||
|
||||
static std::vector<SOElement> const&
|
||||
getCommonFields();
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
XRPL_FEATURE(Sponsor, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -33,7 +33,7 @@ XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo
|
||||
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Batch, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
||||
// Check flags in Credential transactions
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ namespace jss {
|
||||
JSS(AL_size); // out: GetCounts
|
||||
JSS(AL_hit_rate); // out: GetCounts
|
||||
JSS(AcceptedCredentials); // out: AccountObjects
|
||||
JSS(ACCOUNT_SET_FLAGS); // out: RPC server_definitions
|
||||
JSS(Account); // in: TransactionSign; field.
|
||||
JSS(AMMID); // field
|
||||
JSS(Amount); // in: TransactionSign; field.
|
||||
@@ -187,6 +188,7 @@ JSS(closed_ledger); // out: NetworkOPs
|
||||
JSS(cluster); // out: PeerImp
|
||||
JSS(code); // out: errors
|
||||
JSS(command); // in: RPCHandler
|
||||
JSS(common); // out: RPC server_definitions
|
||||
JSS(complete); // out: NetworkOPs, InboundLedger
|
||||
JSS(complete_ledgers); // out: NetworkOPs, PeerImp
|
||||
JSS(consensus); // out: NetworkOPs, LedgerConsensus
|
||||
@@ -356,6 +358,8 @@ JSS(ledger_min); // in, out: AccountTx*
|
||||
JSS(ledger_time); // out: NetworkOPs
|
||||
JSS(LEDGER_ENTRY_TYPES); // out: RPC server_definitions
|
||||
// matches definitions.json format
|
||||
JSS(LEDGER_ENTRY_FLAGS); // out: RPC server_definitions
|
||||
JSS(LEDGER_ENTRY_FORMATS); // out: RPC server_definitions
|
||||
JSS(levels); // LogLevels
|
||||
JSS(limit); // in/out: AccountTx*, AccountOffers,
|
||||
// AccountLines, AccountObjects
|
||||
@@ -457,6 +461,7 @@ JSS(open); // out: handlers/Ledger
|
||||
JSS(open_ledger_cost); // out: SubmitTransaction
|
||||
JSS(open_ledger_fee); // out: TxQ
|
||||
JSS(open_ledger_level); // out: TxQ
|
||||
JSS(optionality); // out: server_definitions
|
||||
JSS(oracles); // in: get_aggregate_price
|
||||
JSS(oracle_document_id); // in: get_aggregate_price
|
||||
JSS(owner); // in: LedgerEntry, out: NetworkOPs
|
||||
@@ -619,6 +624,8 @@ JSS(TRANSACTION_RESULTS); // out: RPC server_definitions
|
||||
// matches definitions.json format
|
||||
JSS(TRANSACTION_TYPES); // out: RPC server_definitions
|
||||
// matches definitions.json format
|
||||
JSS(TRANSACTION_FLAGS); // out: RPC server_definitions
|
||||
JSS(TRANSACTION_FORMATS); // out: RPC server_definitions
|
||||
JSS(TYPES); // out: RPC server_definitions
|
||||
// matches definitions.json format
|
||||
JSS(transfer_rate); // out: nft_info (clio)
|
||||
|
||||
@@ -1,777 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class ReadView;
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/**
|
||||
* @brief Prototype for invariant check implementations.
|
||||
*
|
||||
* __THIS CLASS DOES NOT EXIST__ - or rather it exists in documentation only to
|
||||
* communicate the interface required of any invariant checker. Any invariant
|
||||
* check implementation should implement the public methods documented here.
|
||||
*
|
||||
*/
|
||||
class InvariantChecker_PROTOTYPE
|
||||
{
|
||||
public:
|
||||
explicit InvariantChecker_PROTOTYPE() = default;
|
||||
|
||||
/**
|
||||
* @brief called for each ledger entry in the current transaction.
|
||||
*
|
||||
* @param isDelete true if the SLE is being deleted
|
||||
* @param before ledger entry before modification by the transaction
|
||||
* @param after ledger entry after modification by the transaction
|
||||
*/
|
||||
void
|
||||
visitEntry(
|
||||
bool isDelete,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after);
|
||||
|
||||
/**
|
||||
* @brief called after all ledger entries have been visited to determine
|
||||
* the final status of the check
|
||||
*
|
||||
* @param tx the transaction being applied
|
||||
* @param tec the current TER result of the transaction
|
||||
* @param fee the fee actually charged for this transaction
|
||||
* @param view a ReadView of the ledger being modified
|
||||
* @param j journal for logging
|
||||
*
|
||||
* @return true if check passes, false if it fails
|
||||
*/
|
||||
bool
|
||||
finalize(
|
||||
STTx const& tx,
|
||||
TER const tec,
|
||||
XRPAmount const fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j);
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Invariant: We should never charge a transaction a negative fee or a
|
||||
* fee that is larger than what the transaction itself specifies.
|
||||
*
|
||||
* We can, in some circumstances, charge less.
|
||||
*/
|
||||
class TransactionFeeCheck
|
||||
{
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: A transaction must not create XRP and should only destroy
|
||||
* the XRP fee.
|
||||
*
|
||||
* We iterate through all account roots, payment channels and escrow entries
|
||||
* that were modified and calculate the net change in XRP caused by the
|
||||
* transactions.
|
||||
*/
|
||||
class XRPNotCreated
|
||||
{
|
||||
std::int64_t drops_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: we cannot remove an account ledger entry
|
||||
*
|
||||
* We iterate all account roots that were modified, and ensure that any that
|
||||
* were present before the transaction was applied continue to be present
|
||||
* afterwards unless they were explicitly deleted by a successful
|
||||
* AccountDelete transaction.
|
||||
*/
|
||||
class AccountRootsNotDeleted
|
||||
{
|
||||
std::uint32_t accountsDeleted_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: a deleted account must not have any objects left
|
||||
*
|
||||
* We iterate all deleted account roots, and ensure that there are no
|
||||
* objects left that are directly accessible with that account's ID.
|
||||
*
|
||||
* There should only be one deleted account, but that's checked by
|
||||
* AccountRootsNotDeleted. This invariant will handle multiple deleted account
|
||||
* roots without a problem.
|
||||
*/
|
||||
class AccountRootsDeletedClean
|
||||
{
|
||||
// Pair is <before, after>. Before is used for most of the checks, so that
|
||||
// if, for example, an object ID field is cleared, but the object is not
|
||||
// deleted, it can still be found. After is used specifically for any checks
|
||||
// that are expected as part of the deletion, such as zeroing out the
|
||||
// balance.
|
||||
std::vector<std::pair<std::shared_ptr<SLE const>, std::shared_ptr<SLE const>>> accountsDeleted_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: An account XRP balance must be in XRP and take a value
|
||||
* between 0 and INITIAL_XRP drops, inclusive.
|
||||
*
|
||||
* We iterate all account roots modified by the transaction and ensure that
|
||||
* their XRP balances are reasonable.
|
||||
*/
|
||||
class XRPBalanceChecks
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: corresponding modified ledger entries should match in type
|
||||
* and added entries should be a valid type.
|
||||
*/
|
||||
class LedgerEntryTypesMatch
|
||||
{
|
||||
bool typeMismatch_ = false;
|
||||
bool invalidTypeAdded_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Trust lines using XRP are not allowed.
|
||||
*
|
||||
* We iterate all the trust lines created by this transaction and ensure
|
||||
* that they are against a valid issuer.
|
||||
*/
|
||||
class NoXRPTrustLines
|
||||
{
|
||||
bool xrpTrustLine_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Trust lines with deep freeze flag are not allowed if normal
|
||||
* freeze flag is not set.
|
||||
*
|
||||
* We iterate all the trust lines created by this transaction and ensure
|
||||
* that they don't have deep freeze flag set without normal freeze flag set.
|
||||
*/
|
||||
class NoDeepFreezeTrustLinesWithoutFreeze
|
||||
{
|
||||
bool deepFreezeWithoutFreeze_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: frozen trust line balance change is not allowed.
|
||||
*
|
||||
* We iterate all affected trust lines and ensure that they don't have
|
||||
* unexpected change of balance if they're frozen.
|
||||
*/
|
||||
class TransfersNotFrozen
|
||||
{
|
||||
struct BalanceChange
|
||||
{
|
||||
std::shared_ptr<SLE const> const line;
|
||||
int const balanceChangeSign;
|
||||
};
|
||||
|
||||
struct IssuerChanges
|
||||
{
|
||||
std::vector<BalanceChange> senders;
|
||||
std::vector<BalanceChange> receivers;
|
||||
};
|
||||
|
||||
using ByIssuer = std::map<Issue, IssuerChanges>;
|
||||
ByIssuer balanceChanges_;
|
||||
|
||||
std::map<AccountID, std::shared_ptr<SLE const> const> possibleIssuers_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
|
||||
private:
|
||||
bool
|
||||
isValidEntry(std::shared_ptr<SLE const> const& before, std::shared_ptr<SLE const> const& after);
|
||||
|
||||
STAmount
|
||||
calculateBalanceChange(
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after,
|
||||
bool isDelete);
|
||||
|
||||
void
|
||||
recordBalance(Issue const& issue, BalanceChange change);
|
||||
|
||||
void
|
||||
recordBalanceChanges(std::shared_ptr<SLE const> const& after, STAmount const& balanceChange);
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
findIssuer(AccountID const& issuerID, ReadView const& view);
|
||||
|
||||
bool
|
||||
validateIssuerChanges(
|
||||
std::shared_ptr<SLE const> const& issuer,
|
||||
IssuerChanges const& changes,
|
||||
STTx const& tx,
|
||||
beast::Journal const& j,
|
||||
bool enforce);
|
||||
|
||||
bool
|
||||
validateFrozenState(
|
||||
BalanceChange const& change,
|
||||
bool high,
|
||||
STTx const& tx,
|
||||
beast::Journal const& j,
|
||||
bool enforce,
|
||||
bool globalFreeze);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: offers should be for non-negative amounts and must not
|
||||
* be XRP to XRP.
|
||||
*
|
||||
* Examine all offers modified by the transaction and ensure that there are
|
||||
* no offers which contain negative amounts or which exchange XRP for XRP.
|
||||
*/
|
||||
class NoBadOffers
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: an escrow entry must take a value between 0 and
|
||||
* INITIAL_XRP drops exclusive.
|
||||
*/
|
||||
class NoZeroEscrow
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: a new account root must be the consequence of a payment,
|
||||
* must have the right starting sequence, and the payment
|
||||
* may not create more than one new account root.
|
||||
*/
|
||||
class ValidNewAccountRoot
|
||||
{
|
||||
std::uint32_t accountsCreated_ = 0;
|
||||
std::uint32_t accountSeq_ = 0;
|
||||
bool pseudoAccount_ = false;
|
||||
std::uint32_t flags_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Validates several invariants for NFToken pages.
|
||||
*
|
||||
* The following checks are made:
|
||||
* - The page is correctly associated with the owner.
|
||||
* - The page is correctly ordered between the next and previous links.
|
||||
* - The page contains at least one and no more than 32 NFTokens.
|
||||
* - The NFTokens on this page do not belong on a lower or higher page.
|
||||
* - The NFTokens are correctly sorted on the page.
|
||||
* - Each URI, if present, is not empty.
|
||||
*/
|
||||
class ValidNFTokenPage
|
||||
{
|
||||
bool badEntry_ = false;
|
||||
bool badLink_ = false;
|
||||
bool badSort_ = false;
|
||||
bool badURI_ = false;
|
||||
bool invalidSize_ = false;
|
||||
bool deletedFinalPage_ = false;
|
||||
bool deletedLink_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Validates counts of NFTokens after all transaction types.
|
||||
*
|
||||
* The following checks are made:
|
||||
* - The number of minted or burned NFTokens can only be changed by
|
||||
* NFTokenMint or NFTokenBurn transactions.
|
||||
* - A successful NFTokenMint must increase the number of NFTokens.
|
||||
* - A failed NFTokenMint must not change the number of minted NFTokens.
|
||||
* - An NFTokenMint transaction cannot change the number of burned NFTokens.
|
||||
* - A successful NFTokenBurn must increase the number of burned NFTokens.
|
||||
* - A failed NFTokenBurn must not change the number of burned NFTokens.
|
||||
* - An NFTokenBurn transaction cannot change the number of minted NFTokens.
|
||||
*/
|
||||
class NFTokenCountTracking
|
||||
{
|
||||
std::uint32_t beforeMintedTotal = 0;
|
||||
std::uint32_t beforeBurnedTotal = 0;
|
||||
std::uint32_t afterMintedTotal = 0;
|
||||
std::uint32_t afterBurnedTotal = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Sponsored owner counts are balanced.
|
||||
*
|
||||
* The following check is made for every transaction:
|
||||
* - The sum of all per-account deltas of `sfSponsoredOwnerCount` equals
|
||||
* the sum of all per-account deltas of `sfSponsoringOwnerCount`.
|
||||
* - Account OwnerCount must be greater than or equal to SponsoredOwnerCount.
|
||||
*/
|
||||
class SponsorshipOwnerCountsMatch
|
||||
{
|
||||
std::int64_t deltaSponsoredOwnerCount_ = 0;
|
||||
std::int64_t deltaSponsoringOwnerCount_ = 0;
|
||||
std::uint64_t invalidOwnerCountLessThanSponsoredOwnerCount_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Sponsoring account relationships tracked consistently.
|
||||
*
|
||||
* The following check is made for every transaction:
|
||||
* - The net delta of `sfSponsoringAccountCount` across all accounts equals
|
||||
* the net delta of the count of ltACCOUNT_ROOT entries having
|
||||
* `sfSponsor` present (presence transitions only: add/remove).
|
||||
*/
|
||||
class SponsorshipAccountCountMatchesField
|
||||
{
|
||||
std::int64_t deltaSponsoringAccountCount_ = 0;
|
||||
std::int64_t deltaSponsorFieldPresence_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Token holder's trustline balance cannot be negative after
|
||||
* Clawback.
|
||||
*
|
||||
* We iterate all the trust lines affected by this transaction and ensure
|
||||
* that no more than one trustline is modified, and also holder's balance is
|
||||
* non-negative.
|
||||
*/
|
||||
class ValidClawback
|
||||
{
|
||||
std::uint32_t trustlinesChanged = 0;
|
||||
std::uint32_t mptokensChanged = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
class ValidMPTIssuance
|
||||
{
|
||||
std::uint32_t mptIssuancesCreated_ = 0;
|
||||
std::uint32_t mptIssuancesDeleted_ = 0;
|
||||
|
||||
std::uint32_t mptokensCreated_ = 0;
|
||||
std::uint32_t mptokensDeleted_ = 0;
|
||||
// non-MPT transactions may attempt to create
|
||||
// MPToken by an issuer
|
||||
bool mptCreatedByIssuer_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Permissioned Domains must have some rules and
|
||||
* AcceptedCredentials must have length between 1 and 10 inclusive.
|
||||
*
|
||||
* Since only permissions constitute rules, an empty credentials list
|
||||
* means that there are no rules and the invariant is violated.
|
||||
*
|
||||
* Credentials must be sorted and no duplicates allowed
|
||||
*
|
||||
*/
|
||||
class ValidPermissionedDomain
|
||||
{
|
||||
struct SleStatus
|
||||
{
|
||||
std::size_t credentialsSize_{0};
|
||||
bool isSorted_ = false;
|
||||
bool isUnique_ = false;
|
||||
bool isDelete_ = false;
|
||||
};
|
||||
std::vector<SleStatus> sleStatus_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Pseudo-accounts have valid and consistent properties
|
||||
*
|
||||
* Pseudo-accounts have certain properties, and some of those properties are
|
||||
* unique to pseudo-accounts. Check that all pseudo-accounts are following the
|
||||
* rules, and that only pseudo-accounts look like pseudo-accounts.
|
||||
*
|
||||
*/
|
||||
class ValidPseudoAccounts
|
||||
{
|
||||
std::vector<std::string> errors_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
class ValidPermissionedDEX
|
||||
{
|
||||
bool regularOffers_ = false;
|
||||
bool badHybrids_ = false;
|
||||
hash_set<uint256> domains_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
class ValidAMM
|
||||
{
|
||||
std::optional<AccountID> ammAccount_;
|
||||
std::optional<STAmount> lptAMMBalanceAfter_;
|
||||
std::optional<STAmount> lptAMMBalanceBefore_;
|
||||
bool ammPoolChanged_;
|
||||
|
||||
public:
|
||||
enum class ZeroAllowed : bool { No = false, Yes = true };
|
||||
|
||||
ValidAMM() : ammPoolChanged_{false}
|
||||
{
|
||||
}
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
|
||||
private:
|
||||
bool
|
||||
finalizeBid(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeVote(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeCreate(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDelete(bool enforce, TER res, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDeposit(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
// Includes clawback
|
||||
bool
|
||||
finalizeWithdraw(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDEX(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
generalInvariant(STTx const&, ReadView const&, ZeroAllowed zeroAllowed, beast::Journal const&)
|
||||
const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Some fields are unmodifiable
|
||||
*
|
||||
* Check that any fields specified as unmodifiable are not modified when the
|
||||
* object is modified. Creation and deletion are ignored.
|
||||
*
|
||||
*/
|
||||
class NoModifiedUnmodifiableFields
|
||||
{
|
||||
// Pair is <before, after>.
|
||||
std::set<std::pair<SLE::const_pointer, SLE::const_pointer>> changedEntries_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Loan brokers are internally consistent
|
||||
*
|
||||
* 1. If `LoanBroker.OwnerCount = 0` the `DirectoryNode` will have at most one
|
||||
* node (the root), which will only hold entries for `RippleState` or
|
||||
* `MPToken` objects.
|
||||
*
|
||||
*/
|
||||
class ValidLoanBroker
|
||||
{
|
||||
// Not all of these elements will necessarily be populated. Remaining items
|
||||
// will be looked up as needed.
|
||||
struct BrokerInfo
|
||||
{
|
||||
SLE::const_pointer brokerBefore = nullptr;
|
||||
// After is used for most of the checks, except
|
||||
// those that check changed values.
|
||||
SLE::const_pointer brokerAfter = nullptr;
|
||||
};
|
||||
// Collect all the LoanBrokers found directly or indirectly through
|
||||
// pseudo-accounts. Key is the brokerID / index. It will be used to find the
|
||||
// LoanBroker object if brokerBefore and brokerAfter are nullptr
|
||||
std::map<uint256, BrokerInfo> brokers_;
|
||||
// Collect all the modified trust lines. Their high and low accounts will be
|
||||
// loaded to look for LoanBroker pseudo-accounts.
|
||||
std::vector<SLE::const_pointer> lines_;
|
||||
// Collect all the modified MPTokens. Their accounts will be loaded to look
|
||||
// for LoanBroker pseudo-accounts.
|
||||
std::vector<SLE::const_pointer> mpts_;
|
||||
|
||||
bool
|
||||
goodZeroDirectory(ReadView const& view, SLE::const_ref dir, beast::Journal const& j) const;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Loans are internally consistent
|
||||
*
|
||||
* 1. If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0`
|
||||
*
|
||||
*/
|
||||
class ValidLoan
|
||||
{
|
||||
// Pair is <before, after>. After is used for most of the checks, except
|
||||
// those that check changed values.
|
||||
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> loans_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief Invariants: Vault object and MPTokenIssuance for vault shares
|
||||
*
|
||||
* - vault deleted and vault created is empty
|
||||
* - vault created must be linked to pseudo-account for shares and assets
|
||||
* - vault must have MPTokenIssuance for shares
|
||||
* - vault without shares outstanding must have no shares
|
||||
* - loss unrealized does not exceed the difference between assets total and
|
||||
* assets available
|
||||
* - assets available do not exceed assets total
|
||||
* - vault deposit increases assets and share issuance, and adds to:
|
||||
* total assets, assets available, shares outstanding
|
||||
* - vault withdrawal and clawback reduce assets and share issuance, and
|
||||
* subtracts from: total assets, assets available, shares outstanding
|
||||
* - vault set must not alter the vault assets or shares balance
|
||||
* - no vault transaction can change loss unrealized (it's updated by loan
|
||||
* transactions)
|
||||
*
|
||||
*/
|
||||
class ValidVault
|
||||
{
|
||||
Number static constexpr zero{};
|
||||
|
||||
struct Vault final
|
||||
{
|
||||
uint256 key = beast::zero;
|
||||
Asset asset = {};
|
||||
AccountID pseudoId = {};
|
||||
AccountID owner = {};
|
||||
uint192 shareMPTID = beast::zero;
|
||||
Number assetsTotal = 0;
|
||||
Number assetsAvailable = 0;
|
||||
Number assetsMaximum = 0;
|
||||
Number lossUnrealized = 0;
|
||||
|
||||
Vault static make(SLE const&);
|
||||
};
|
||||
|
||||
struct Shares final
|
||||
{
|
||||
MPTIssue share = {};
|
||||
std::uint64_t sharesTotal = 0;
|
||||
std::uint64_t sharesMaximum = 0;
|
||||
|
||||
Shares static make(SLE const&);
|
||||
};
|
||||
|
||||
std::vector<Vault> afterVault_ = {};
|
||||
std::vector<Shares> afterMPTs_ = {};
|
||||
std::vector<Vault> beforeVault_ = {};
|
||||
std::vector<Shares> beforeMPTs_ = {};
|
||||
std::unordered_map<uint256, Number> deltas_ = {};
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
// additional invariant checks can be declared above and then added to this
|
||||
// tuple
|
||||
using InvariantChecks = std::tuple<
|
||||
TransactionFeeCheck,
|
||||
AccountRootsNotDeleted,
|
||||
AccountRootsDeletedClean,
|
||||
LedgerEntryTypesMatch,
|
||||
XRPBalanceChecks,
|
||||
XRPNotCreated,
|
||||
NoXRPTrustLines,
|
||||
NoDeepFreezeTrustLinesWithoutFreeze,
|
||||
TransfersNotFrozen,
|
||||
SponsorshipOwnerCountsMatch,
|
||||
SponsorshipAccountCountMatchesField,
|
||||
NoBadOffers,
|
||||
NoZeroEscrow,
|
||||
ValidNewAccountRoot,
|
||||
ValidNFTokenPage,
|
||||
NFTokenCountTracking,
|
||||
ValidClawback,
|
||||
ValidMPTIssuance,
|
||||
ValidPermissionedDomain,
|
||||
ValidPermissionedDEX,
|
||||
ValidAMM,
|
||||
NoModifiedUnmodifiableFields,
|
||||
ValidPseudoAccounts,
|
||||
ValidLoanBroker,
|
||||
ValidLoan,
|
||||
ValidVault>;
|
||||
|
||||
/**
|
||||
* @brief get a tuple of all invariant checks
|
||||
*
|
||||
* @return std::tuple of instances that implement the required invariant check
|
||||
* methods
|
||||
*
|
||||
* @see xrpl::InvariantChecker_PROTOTYPE
|
||||
*/
|
||||
inline InvariantChecks
|
||||
getInvariantChecks()
|
||||
{
|
||||
return InvariantChecks{};
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
53
include/xrpl/tx/invariants/AMMInvariant.h
Normal file
53
include/xrpl/tx/invariants/AMMInvariant.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class ValidAMM
|
||||
{
|
||||
std::optional<AccountID> ammAccount_;
|
||||
std::optional<STAmount> lptAMMBalanceAfter_;
|
||||
std::optional<STAmount> lptAMMBalanceBefore_;
|
||||
bool ammPoolChanged_;
|
||||
|
||||
public:
|
||||
enum class ZeroAllowed : bool { No = false, Yes = true };
|
||||
|
||||
ValidAMM() : ammPoolChanged_{false}
|
||||
{
|
||||
}
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
|
||||
private:
|
||||
bool
|
||||
finalizeBid(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeVote(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeCreate(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDelete(bool enforce, TER res, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDeposit(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
// Includes clawback
|
||||
bool
|
||||
finalizeWithdraw(STTx const&, ReadView const&, bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
finalizeDEX(bool enforce, beast::Journal const&) const;
|
||||
bool
|
||||
generalInvariant(STTx const&, ReadView const&, ZeroAllowed zeroAllowed, beast::Journal const&)
|
||||
const;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
84
include/xrpl/tx/invariants/FreezeInvariant.h
Normal file
84
include/xrpl/tx/invariants/FreezeInvariant.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Invariant: frozen trust line balance change is not allowed.
|
||||
*
|
||||
* We iterate all affected trust lines and ensure that they don't have
|
||||
* unexpected change of balance if they're frozen.
|
||||
*/
|
||||
class TransfersNotFrozen
|
||||
{
|
||||
struct BalanceChange
|
||||
{
|
||||
std::shared_ptr<SLE const> const line;
|
||||
int const balanceChangeSign;
|
||||
};
|
||||
|
||||
struct IssuerChanges
|
||||
{
|
||||
std::vector<BalanceChange> senders;
|
||||
std::vector<BalanceChange> receivers;
|
||||
};
|
||||
|
||||
using ByIssuer = std::map<Issue, IssuerChanges>;
|
||||
ByIssuer balanceChanges_;
|
||||
|
||||
std::map<AccountID, std::shared_ptr<SLE const> const> possibleIssuers_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
|
||||
private:
|
||||
bool
|
||||
isValidEntry(std::shared_ptr<SLE const> const& before, std::shared_ptr<SLE const> const& after);
|
||||
|
||||
STAmount
|
||||
calculateBalanceChange(
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after,
|
||||
bool isDelete);
|
||||
|
||||
void
|
||||
recordBalance(Issue const& issue, BalanceChange change);
|
||||
|
||||
void
|
||||
recordBalanceChanges(std::shared_ptr<SLE const> const& after, STAmount const& balanceChange);
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
findIssuer(AccountID const& issuerID, ReadView const& view);
|
||||
|
||||
bool
|
||||
validateIssuerChanges(
|
||||
std::shared_ptr<SLE const> const& issuer,
|
||||
IssuerChanges const& changes,
|
||||
STTx const& tx,
|
||||
beast::Journal const& j,
|
||||
bool enforce);
|
||||
|
||||
bool
|
||||
validateFrozenState(
|
||||
BalanceChange const& change,
|
||||
bool high,
|
||||
STTx const& tx,
|
||||
beast::Journal const& j,
|
||||
bool enforce,
|
||||
bool globalFreeze);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
419
include/xrpl/tx/invariants/InvariantCheck.h
Normal file
419
include/xrpl/tx/invariants/InvariantCheck.h
Normal file
@@ -0,0 +1,419 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/tx/invariants/AMMInvariant.h>
|
||||
#include <xrpl/tx/invariants/FreezeInvariant.h>
|
||||
#include <xrpl/tx/invariants/LoanInvariant.h>
|
||||
#include <xrpl/tx/invariants/MPTInvariant.h>
|
||||
#include <xrpl/tx/invariants/NFTInvariant.h>
|
||||
#include <xrpl/tx/invariants/PermissionedDEXInvariant.h>
|
||||
#include <xrpl/tx/invariants/PermissionedDomainInvariant.h>
|
||||
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
|
||||
#include <xrpl/tx/invariants/VaultInvariant.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
#if GENERATING_DOCS
|
||||
/**
|
||||
* @brief Prototype for invariant check implementations.
|
||||
*
|
||||
* __THIS CLASS DOES NOT EXIST__ - or rather it exists in documentation only to
|
||||
* communicate the interface required of any invariant checker. Any invariant
|
||||
* check implementation should implement the public methods documented here.
|
||||
*
|
||||
* ## Rules for implementing `finalize`
|
||||
*
|
||||
* ### Invariants must run regardless of transaction result
|
||||
*
|
||||
* An invariant's `finalize` method MUST perform meaningful checks even when
|
||||
* the transaction has failed (i.e., `!isTesSuccess(tec)`). The following
|
||||
* pattern is almost certainly wrong and must never be used:
|
||||
*
|
||||
* @code
|
||||
* // WRONG: skipping all checks on failure defeats the purpose of invariants
|
||||
* if (!isTesSuccess(tec))
|
||||
* return true;
|
||||
* @endcode
|
||||
*
|
||||
* The entire purpose of invariants is to detect and prevent the impossible.
|
||||
* A bug or exploit could cause a failed transaction to mutate ledger state in
|
||||
* unexpected ways. Invariants are the last line of defense against such
|
||||
* scenarios.
|
||||
*
|
||||
* In general: an invariant that expects a domain-specific state change to
|
||||
* occur (e.g., a new object being created) should only expect that change
|
||||
* when the transaction succeeded. A failed VaultCreate must not have created
|
||||
* a Vault. A failed LoanSet must not have created a Loan.
|
||||
*
|
||||
* Also be aware that failed transactions, regardless of type, carry no
|
||||
* Privileges. Any privilege-gated checks must therefore also be applied to
|
||||
* failed transactions.
|
||||
*/
|
||||
class InvariantChecker_PROTOTYPE
|
||||
{
|
||||
public:
|
||||
explicit InvariantChecker_PROTOTYPE() = default;
|
||||
|
||||
/**
|
||||
* @brief called for each ledger entry in the current transaction.
|
||||
*
|
||||
* @param isDelete true if the SLE is being deleted
|
||||
* @param before ledger entry before modification by the transaction
|
||||
* @param after ledger entry after modification by the transaction
|
||||
*/
|
||||
void
|
||||
visitEntry(
|
||||
bool isDelete,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after);
|
||||
|
||||
/**
|
||||
* @brief called after all ledger entries have been visited to determine
|
||||
* the final status of the check.
|
||||
*
|
||||
* This method MUST perform meaningful checks even when `tec` indicates a
|
||||
* failed transaction. See the class-level documentation for the rules
|
||||
* governing how failed transactions must be handled.
|
||||
*
|
||||
* @param tx the transaction being applied
|
||||
* @param tec the current TER result of the transaction
|
||||
* @param fee the fee actually charged for this transaction
|
||||
* @param view a ReadView of the ledger being modified
|
||||
* @param j journal for logging
|
||||
*
|
||||
* @return true if check passes, false if it fails
|
||||
*/
|
||||
bool
|
||||
finalize(
|
||||
STTx const& tx,
|
||||
TER const tec,
|
||||
XRPAmount const fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j);
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Invariant: We should never charge a transaction a negative fee or a
|
||||
* fee that is larger than what the transaction itself specifies.
|
||||
*
|
||||
* We can, in some circumstances, charge less.
|
||||
*/
|
||||
class TransactionFeeCheck
|
||||
{
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: A transaction must not create XRP and should only destroy
|
||||
* the XRP fee.
|
||||
*
|
||||
* We iterate through all account roots, payment channels and escrow entries
|
||||
* that were modified and calculate the net change in XRP caused by the
|
||||
* transactions.
|
||||
*/
|
||||
class XRPNotCreated
|
||||
{
|
||||
std::int64_t drops_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: we cannot remove an account ledger entry
|
||||
*
|
||||
* We iterate all account roots that were modified, and ensure that any that
|
||||
* were present before the transaction was applied continue to be present
|
||||
* afterwards unless they were explicitly deleted by a successful
|
||||
* AccountDelete transaction.
|
||||
*/
|
||||
class AccountRootsNotDeleted
|
||||
{
|
||||
std::uint32_t accountsDeleted_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: a deleted account must not have any objects left
|
||||
*
|
||||
* We iterate all deleted account roots, and ensure that there are no
|
||||
* objects left that are directly accessible with that account's ID.
|
||||
*
|
||||
* There should only be one deleted account, but that's checked by
|
||||
* AccountRootsNotDeleted. This invariant will handle multiple deleted account
|
||||
* roots without a problem.
|
||||
*/
|
||||
class AccountRootsDeletedClean
|
||||
{
|
||||
// Pair is <before, after>. Before is used for most of the checks, so that
|
||||
// if, for example, an object ID field is cleared, but the object is not
|
||||
// deleted, it can still be found. After is used specifically for any checks
|
||||
// that are expected as part of the deletion, such as zeroing out the
|
||||
// balance.
|
||||
std::vector<std::pair<std::shared_ptr<SLE const>, std::shared_ptr<SLE const>>> accountsDeleted_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: An account XRP balance must be in XRP and take a value
|
||||
* between 0 and INITIAL_XRP drops, inclusive.
|
||||
*
|
||||
* We iterate all account roots modified by the transaction and ensure that
|
||||
* their XRP balances are reasonable.
|
||||
*/
|
||||
class XRPBalanceChecks
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: corresponding modified ledger entries should match in type
|
||||
* and added entries should be a valid type.
|
||||
*/
|
||||
class LedgerEntryTypesMatch
|
||||
{
|
||||
bool typeMismatch_ = false;
|
||||
bool invalidTypeAdded_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Trust lines using XRP are not allowed.
|
||||
*
|
||||
* We iterate all the trust lines created by this transaction and ensure
|
||||
* that they are against a valid issuer.
|
||||
*/
|
||||
class NoXRPTrustLines
|
||||
{
|
||||
bool xrpTrustLine_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Trust lines with deep freeze flag are not allowed if normal
|
||||
* freeze flag is not set.
|
||||
*
|
||||
* We iterate all the trust lines created by this transaction and ensure
|
||||
* that they don't have deep freeze flag set without normal freeze flag set.
|
||||
*/
|
||||
class NoDeepFreezeTrustLinesWithoutFreeze
|
||||
{
|
||||
bool deepFreezeWithoutFreeze_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: offers should be for non-negative amounts and must not
|
||||
* be XRP to XRP.
|
||||
*
|
||||
* Examine all offers modified by the transaction and ensure that there are
|
||||
* no offers which contain negative amounts or which exchange XRP for XRP.
|
||||
*/
|
||||
class NoBadOffers
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: an escrow entry must take a value between 0 and
|
||||
* INITIAL_XRP drops exclusive.
|
||||
*/
|
||||
class NoZeroEscrow
|
||||
{
|
||||
bool bad_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: a new account root must be the consequence of a payment,
|
||||
* must have the right starting sequence, and the payment
|
||||
* may not create more than one new account root.
|
||||
*/
|
||||
class ValidNewAccountRoot
|
||||
{
|
||||
std::uint32_t accountsCreated_ = 0;
|
||||
std::uint32_t accountSeq_ = 0;
|
||||
bool pseudoAccount_ = false;
|
||||
std::uint32_t flags_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Token holder's trustline balance cannot be negative after
|
||||
* Clawback.
|
||||
*
|
||||
* We iterate all the trust lines affected by this transaction and ensure
|
||||
* that no more than one trustline is modified, and also holder's balance is
|
||||
* non-negative.
|
||||
*/
|
||||
class ValidClawback
|
||||
{
|
||||
std::uint32_t trustlinesChanged = 0;
|
||||
std::uint32_t mptokensChanged = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Pseudo-accounts have valid and consistent properties
|
||||
*
|
||||
* Pseudo-accounts have certain properties, and some of those properties are
|
||||
* unique to pseudo-accounts. Check that all pseudo-accounts are following the
|
||||
* rules, and that only pseudo-accounts look like pseudo-accounts.
|
||||
*
|
||||
*/
|
||||
class ValidPseudoAccounts
|
||||
{
|
||||
std::vector<std::string> errors_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Some fields are unmodifiable
|
||||
*
|
||||
* Check that any fields specified as unmodifiable are not modified when the
|
||||
* object is modified. Creation and deletion are ignored.
|
||||
*
|
||||
*/
|
||||
class NoModifiedUnmodifiableFields
|
||||
{
|
||||
// Pair is <before, after>.
|
||||
std::set<std::pair<SLE::const_pointer, SLE::const_pointer>> changedEntries_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
// additional invariant checks can be declared above and then added to this
|
||||
// tuple
|
||||
using InvariantChecks = std::tuple<
|
||||
TransactionFeeCheck,
|
||||
AccountRootsNotDeleted,
|
||||
AccountRootsDeletedClean,
|
||||
LedgerEntryTypesMatch,
|
||||
XRPBalanceChecks,
|
||||
XRPNotCreated,
|
||||
NoXRPTrustLines,
|
||||
NoDeepFreezeTrustLinesWithoutFreeze,
|
||||
TransfersNotFrozen,
|
||||
NoBadOffers,
|
||||
NoZeroEscrow,
|
||||
ValidNewAccountRoot,
|
||||
ValidNFTokenPage,
|
||||
NFTokenCountTracking,
|
||||
ValidClawback,
|
||||
ValidMPTIssuance,
|
||||
ValidPermissionedDomain,
|
||||
ValidPermissionedDEX,
|
||||
ValidAMM,
|
||||
NoModifiedUnmodifiableFields,
|
||||
ValidPseudoAccounts,
|
||||
ValidLoanBroker,
|
||||
ValidLoan,
|
||||
ValidVault,
|
||||
SponsorshipOwnerCountsMatch,
|
||||
SponsorshipAccountCountMatchesField>;
|
||||
|
||||
/**
|
||||
* @brief get a tuple of all invariant checks
|
||||
*
|
||||
* @return std::tuple of instances that implement the required invariant check
|
||||
* methods
|
||||
*
|
||||
* @see xrpl::InvariantChecker_PROTOTYPE
|
||||
*/
|
||||
inline InvariantChecks
|
||||
getInvariantChecks()
|
||||
{
|
||||
return InvariantChecks{};
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
60
include/xrpl/tx/invariants/InvariantCheckPrivilege.h
Normal file
60
include/xrpl/tx/invariants/InvariantCheckPrivilege.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/*
|
||||
assert(enforce)
|
||||
|
||||
There are several asserts (or XRPL_ASSERTs) in invariant check files that check
|
||||
a variable named `enforce` when an invariant fails. At first glance, those
|
||||
asserts may look incorrect, but they are not.
|
||||
|
||||
Those asserts take advantage of two facts:
|
||||
1. `asserts` are not (normally) executed in release builds.
|
||||
2. Invariants should *never* fail, except in tests that specifically modify
|
||||
the open ledger to break them.
|
||||
|
||||
This makes `assert(enforce)` sort of a second-layer of invariant enforcement
|
||||
aimed at _developers_. It's designed to fire if a developer writes code that
|
||||
violates an invariant, and runs it in unit tests or a develop build that _does
|
||||
not have the relevant amendments enabled_. It's intentionally a pain in the neck
|
||||
so that bad code gets caught and fixed as early as possible.
|
||||
*/
|
||||
|
||||
enum Privilege {
|
||||
noPriv = 0x0000, // The transaction can not do any of the enumerated operations
|
||||
createAcct = 0x0001, // The transaction can create a new ACCOUNT_ROOT object.
|
||||
createPseudoAcct = 0x0002, // The transaction can create a pseudo account,
|
||||
// which implies createAcct
|
||||
mustDeleteAcct = 0x0004, // The transaction must delete an ACCOUNT_ROOT object
|
||||
mayDeleteAcct = 0x0008, // The transaction may delete an ACCOUNT_ROOT
|
||||
// object, but does not have to
|
||||
overrideFreeze = 0x0010, // The transaction can override some freeze rules
|
||||
changeNFTCounts = 0x0020, // The transaction can mint or burn an NFT
|
||||
createMPTIssuance = 0x0040, // The transaction can create a new MPT issuance
|
||||
destroyMPTIssuance = 0x0080, // The transaction can destroy an MPT issuance
|
||||
mustAuthorizeMPT = 0x0100, // The transaction MUST create or delete an MPT
|
||||
// object (except by issuer)
|
||||
mayAuthorizeMPT = 0x0200, // The transaction MAY create or delete an MPT
|
||||
// object (except by issuer)
|
||||
mayDeleteMPT = 0x0400, // The transaction MAY delete an MPT object. May not create.
|
||||
mustModifyVault = 0x0800, // The transaction must modify, delete or create, a vault
|
||||
mayModifyVault = 0x1000, // The transaction MAY modify, delete or create, a vault
|
||||
};
|
||||
|
||||
constexpr Privilege
|
||||
operator|(Privilege lhs, Privilege rhs)
|
||||
{
|
||||
return safe_cast<Privilege>(
|
||||
safe_cast<std::underlying_type_t<Privilege>>(lhs) |
|
||||
safe_cast<std::underlying_type_t<Privilege>>(rhs));
|
||||
}
|
||||
|
||||
bool
|
||||
hasPrivilege(STTx const& tx, Privilege priv);
|
||||
|
||||
} // namespace xrpl
|
||||
75
include/xrpl/tx/invariants/LoanInvariant.h
Normal file
75
include/xrpl/tx/invariants/LoanInvariant.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Invariants: Loan brokers are internally consistent
|
||||
*
|
||||
* 1. If `LoanBroker.OwnerCount = 0` the `DirectoryNode` will have at most one
|
||||
* node (the root), which will only hold entries for `RippleState` or
|
||||
* `MPToken` objects.
|
||||
*
|
||||
*/
|
||||
class ValidLoanBroker
|
||||
{
|
||||
// Not all of these elements will necessarily be populated. Remaining items
|
||||
// will be looked up as needed.
|
||||
struct BrokerInfo
|
||||
{
|
||||
SLE::const_pointer brokerBefore = nullptr;
|
||||
// After is used for most of the checks, except
|
||||
// those that check changed values.
|
||||
SLE::const_pointer brokerAfter = nullptr;
|
||||
};
|
||||
// Collect all the LoanBrokers found directly or indirectly through
|
||||
// pseudo-accounts. Key is the brokerID / index. It will be used to find the
|
||||
// LoanBroker object if brokerBefore and brokerAfter are nullptr
|
||||
std::map<uint256, BrokerInfo> brokers_;
|
||||
// Collect all the modified trust lines. Their high and low accounts will be
|
||||
// loaded to look for LoanBroker pseudo-accounts.
|
||||
std::vector<SLE::const_pointer> lines_;
|
||||
// Collect all the modified MPTokens. Their accounts will be loaded to look
|
||||
// for LoanBroker pseudo-accounts.
|
||||
std::vector<SLE::const_pointer> mpts_;
|
||||
|
||||
bool
|
||||
goodZeroDirectory(ReadView const& view, SLE::const_ref dir, beast::Journal const& j) const;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariants: Loans are internally consistent
|
||||
*
|
||||
* 1. If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0`
|
||||
*
|
||||
*/
|
||||
class ValidLoan
|
||||
{
|
||||
// Pair is <before, after>. After is used for most of the checks, except
|
||||
// those that check changed values.
|
||||
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> loans_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
31
include/xrpl/tx/invariants/MPTInvariant.h
Normal file
31
include/xrpl/tx/invariants/MPTInvariant.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class ValidMPTIssuance
|
||||
{
|
||||
std::uint32_t mptIssuancesCreated_ = 0;
|
||||
std::uint32_t mptIssuancesDeleted_ = 0;
|
||||
|
||||
std::uint32_t mptokensCreated_ = 0;
|
||||
std::uint32_t mptokensDeleted_ = 0;
|
||||
// non-MPT transactions may attempt to create
|
||||
// MPToken by an issuer
|
||||
bool mptCreatedByIssuer_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
70
include/xrpl/tx/invariants/NFTInvariant.h
Normal file
70
include/xrpl/tx/invariants/NFTInvariant.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Invariant: Validates several invariants for NFToken pages.
|
||||
*
|
||||
* The following checks are made:
|
||||
* - The page is correctly associated with the owner.
|
||||
* - The page is correctly ordered between the next and previous links.
|
||||
* - The page contains at least one and no more than 32 NFTokens.
|
||||
* - The NFTokens on this page do not belong on a lower or higher page.
|
||||
* - The NFTokens are correctly sorted on the page.
|
||||
* - Each URI, if present, is not empty.
|
||||
*/
|
||||
class ValidNFTokenPage
|
||||
{
|
||||
bool badEntry_ = false;
|
||||
bool badLink_ = false;
|
||||
bool badSort_ = false;
|
||||
bool badURI_ = false;
|
||||
bool invalidSize_ = false;
|
||||
bool deletedFinalPage_ = false;
|
||||
bool deletedLink_ = false;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Validates counts of NFTokens after all transaction types.
|
||||
*
|
||||
* The following checks are made:
|
||||
* - The number of minted or burned NFTokens can only be changed by
|
||||
* NFTokenMint or NFTokenBurn transactions.
|
||||
* - A successful NFTokenMint must increase the number of NFTokens.
|
||||
* - A failed NFTokenMint must not change the number of minted NFTokens.
|
||||
* - An NFTokenMint transaction cannot change the number of burned NFTokens.
|
||||
* - A successful NFTokenBurn must increase the number of burned NFTokens.
|
||||
* - A failed NFTokenBurn must not change the number of burned NFTokens.
|
||||
* - An NFTokenBurn transaction cannot change the number of minted NFTokens.
|
||||
*/
|
||||
class NFTokenCountTracking
|
||||
{
|
||||
std::uint32_t beforeMintedTotal = 0;
|
||||
std::uint32_t beforeBurnedTotal = 0;
|
||||
std::uint32_t afterMintedTotal = 0;
|
||||
std::uint32_t afterBurnedTotal = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
25
include/xrpl/tx/invariants/PermissionedDEXInvariant.h
Normal file
25
include/xrpl/tx/invariants/PermissionedDEXInvariant.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class ValidPermissionedDEX
|
||||
{
|
||||
bool regularOffers_ = false;
|
||||
bool badHybrids_ = false;
|
||||
hash_set<uint256> domains_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
41
include/xrpl/tx/invariants/PermissionedDomainInvariant.h
Normal file
41
include/xrpl/tx/invariants/PermissionedDomainInvariant.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Invariants: Permissioned Domains must have some rules and
|
||||
* AcceptedCredentials must have length between 1 and 10 inclusive.
|
||||
*
|
||||
* Since only permissions constitute rules, an empty credentials list
|
||||
* means that there are no rules and the invariant is violated.
|
||||
*
|
||||
* Credentials must be sorted and no duplicates allowed
|
||||
*
|
||||
*/
|
||||
class ValidPermissionedDomain
|
||||
{
|
||||
struct SleStatus
|
||||
{
|
||||
std::size_t credentialsSize_{0};
|
||||
bool isSorted_ = false;
|
||||
bool isUnique_ = false;
|
||||
bool isDelete_ = false;
|
||||
};
|
||||
std::vector<SleStatus> sleStatus_;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
55
include/xrpl/tx/invariants/SponsorshipInvariant.h
Normal file
55
include/xrpl/tx/invariants/SponsorshipInvariant.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Invariant: Sponsored owner counts are balanced.
|
||||
*
|
||||
* The following check is made for every transaction:
|
||||
* - The sum of all per-account deltas of `sfSponsoredOwnerCount` equals
|
||||
* the sum of all per-account deltas of `sfSponsoringOwnerCount`.
|
||||
* - Account OwnerCount must be greater than or equal to SponsoredOwnerCount.
|
||||
*/
|
||||
class SponsorshipOwnerCountsMatch
|
||||
{
|
||||
std::int64_t deltaSponsoredOwnerCount_ = 0;
|
||||
std::int64_t deltaSponsoringOwnerCount_ = 0;
|
||||
std::uint64_t invalidOwnerCountLessThanSponsoredOwnerCount_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Invariant: Sponsoring account relationships tracked consistently.
|
||||
*
|
||||
* The following check is made for every transaction:
|
||||
* - The net delta of `sfSponsoringAccountCount` across all accounts equals
|
||||
* the net delta of the count of ltACCOUNT_ROOT entries having
|
||||
* `sfSponsor` present (presence transitions only: add/remove).
|
||||
*/
|
||||
class SponsorshipAccountCountMatchesField
|
||||
{
|
||||
std::int64_t deltaSponsoringAccountCount_ = 0;
|
||||
std::int64_t deltaSponsorFieldPresence_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
77
include/xrpl/tx/invariants/VaultInvariant.h
Normal file
77
include/xrpl/tx/invariants/VaultInvariant.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/*
|
||||
* @brief Invariants: Vault object and MPTokenIssuance for vault shares
|
||||
*
|
||||
* - vault deleted and vault created is empty
|
||||
* - vault created must be linked to pseudo-account for shares and assets
|
||||
* - vault must have MPTokenIssuance for shares
|
||||
* - vault without shares outstanding must have no shares
|
||||
* - loss unrealized does not exceed the difference between assets total and
|
||||
* assets available
|
||||
* - assets available do not exceed assets total
|
||||
* - vault deposit increases assets and share issuance, and adds to:
|
||||
* total assets, assets available, shares outstanding
|
||||
* - vault withdrawal and clawback reduce assets and share issuance, and
|
||||
* subtracts from: total assets, assets available, shares outstanding
|
||||
* - vault set must not alter the vault assets or shares balance
|
||||
* - no vault transaction can change loss unrealized (it's updated by loan
|
||||
* transactions)
|
||||
*
|
||||
*/
|
||||
class ValidVault
|
||||
{
|
||||
Number static constexpr zero{};
|
||||
|
||||
struct Vault final
|
||||
{
|
||||
uint256 key = beast::zero;
|
||||
Asset asset = {};
|
||||
AccountID pseudoId = {};
|
||||
AccountID owner = {};
|
||||
uint192 shareMPTID = beast::zero;
|
||||
Number assetsTotal = 0;
|
||||
Number assetsAvailable = 0;
|
||||
Number assetsMaximum = 0;
|
||||
Number lossUnrealized = 0;
|
||||
|
||||
Vault static make(SLE const&);
|
||||
};
|
||||
|
||||
struct Shares final
|
||||
{
|
||||
MPTIssue share = {};
|
||||
std::uint64_t sharesTotal = 0;
|
||||
std::uint64_t sharesMaximum = 0;
|
||||
|
||||
Shares static make(SLE const&);
|
||||
};
|
||||
|
||||
std::vector<Vault> afterVault_ = {};
|
||||
std::vector<Shares> afterMPTs_ = {};
|
||||
std::vector<Vault> beforeVault_ = {};
|
||||
std::vector<Shares> beforeMPTs_ = {};
|
||||
std::unordered_map<uint256, Number> deltas_ = {};
|
||||
|
||||
public:
|
||||
void
|
||||
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
|
||||
|
||||
bool
|
||||
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -10,8 +10,8 @@
|
||||
#include <xrpl/tx/paths/detail/FlatSets.h>
|
||||
#include <xrpl/tx/paths/detail/FlowDebugInfo.h>
|
||||
#include <xrpl/tx/paths/detail/Steps.h>
|
||||
#include <xrpl/tx/transactors/AMM/AMMContext.h>
|
||||
#include <xrpl/tx/transactors/AMM/AMMHelpers.h>
|
||||
#include <xrpl/tx/transactors/dex/AMMContext.h>
|
||||
#include <xrpl/tx/transactors/dex/AMMHelpers.h>
|
||||
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CredentialCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CredentialDelete : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialDelete(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CredentialAccept : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialAccept(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,80 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class EscrowCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit EscrowCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class EscrowFinish : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit EscrowFinish(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflightSigValidated(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class EscrowCancel : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit EscrowCancel(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,83 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class PayChanCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit PayChanCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelCreate = PayChanCreate;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class PayChanFund : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit PayChanFund(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelFund = PayChanFund;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class PayChanClaim : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit PayChanClaim(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelClaim = PayChanClaim;
|
||||
|
||||
} // namespace xrpl
|
||||
29
include/xrpl/tx/transactors/credentials/CredentialAccept.h
Normal file
29
include/xrpl/tx/transactors/credentials/CredentialAccept.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CredentialAccept : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialAccept(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
29
include/xrpl/tx/transactors/credentials/CredentialCreate.h
Normal file
29
include/xrpl/tx/transactors/credentials/CredentialCreate.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CredentialCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
29
include/xrpl/tx/transactors/credentials/CredentialDelete.h
Normal file
29
include/xrpl/tx/transactors/credentials/CredentialDelete.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CredentialDelete : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit CredentialDelete(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -370,7 +370,7 @@ changeSpotPriceQuality(
|
||||
if (!amounts)
|
||||
{
|
||||
JLOG(j.trace()) << "changeSpotPrice calc failed: " << to_string(pool.in) << " "
|
||||
<< to_string(pool.out) << " " << quality << " " << tfee << std::endl;
|
||||
<< to_string(pool.out) << " " << quality << " " << tfee;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,6 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class DIDSet : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit DIDSet(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class DIDDelete : public Transactor
|
||||
{
|
||||
public:
|
||||
23
include/xrpl/tx/transactors/did/DIDSet.h
Normal file
23
include/xrpl/tx/transactors/did/DIDSet.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class DIDSet : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit DIDSet(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
26
include/xrpl/tx/transactors/escrow/EscrowCancel.h
Normal file
26
include/xrpl/tx/transactors/escrow/EscrowCancel.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class EscrowCancel : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit EscrowCancel(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
29
include/xrpl/tx/transactors/escrow/EscrowCreate.h
Normal file
29
include/xrpl/tx/transactors/escrow/EscrowCreate.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class EscrowCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit EscrowCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
35
include/xrpl/tx/transactors/escrow/EscrowFinish.h
Normal file
35
include/xrpl/tx/transactors/escrow/EscrowFinish.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class EscrowFinish : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit EscrowFinish(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflightSigValidated(PreflightContext const& ctx);
|
||||
|
||||
static XRPAmount
|
||||
calculateBaseFee(ReadView const& view, STTx const& tx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
#include <xrpl/tx/transactors/Lending/LendingHelpers.h>
|
||||
#include <xrpl/tx/transactors/lending/LendingHelpers.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -26,9 +26,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
@@ -13,9 +13,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <xrpl/protocol/nft.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
#include <xrpl/tx/transactors/NFT/NFTokenUtils.h>
|
||||
#include <xrpl/tx/transactors/nft/NFTokenUtils.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
34
include/xrpl/tx/transactors/payment_channel/PayChanClaim.h
Normal file
34
include/xrpl/tx/transactors/payment_channel/PayChanClaim.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class PayChanClaim : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Normal};
|
||||
|
||||
explicit PayChanClaim(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelClaim = PayChanClaim;
|
||||
|
||||
} // namespace xrpl
|
||||
31
include/xrpl/tx/transactors/payment_channel/PayChanCreate.h
Normal file
31
include/xrpl/tx/transactors/payment_channel/PayChanCreate.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class PayChanCreate : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit PayChanCreate(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelCreate = PayChanCreate;
|
||||
|
||||
} // namespace xrpl
|
||||
28
include/xrpl/tx/transactors/payment_channel/PayChanFund.h
Normal file
28
include/xrpl/tx/transactors/payment_channel/PayChanFund.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class PayChanFund : public Transactor
|
||||
{
|
||||
public:
|
||||
static constexpr ConsequencesFactoryType ConsequencesFactory{Custom};
|
||||
|
||||
explicit PayChanFund(ApplyContext& ctx) : Transactor(ctx)
|
||||
{
|
||||
}
|
||||
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
};
|
||||
|
||||
using PaymentChannelFund = PayChanFund;
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -13,9 +13,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user