mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'develop' into vlntb/RIPD-2536-taggedcache-expire-now
This commit is contained in:
@@ -367,7 +367,7 @@ get(Section const& section,
|
||||
}
|
||||
|
||||
inline std::string
|
||||
get(Section const& section, std::string const& name, const char* defaultValue)
|
||||
get(Section const& section, std::string const& name, char const* defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto compressed = bf(outCapacity);
|
||||
|
||||
auto compressedSize = LZ4_compress_default(
|
||||
reinterpret_cast<const char*>(in),
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<char*>(compressed),
|
||||
inSize,
|
||||
outCapacity);
|
||||
@@ -89,7 +89,7 @@ lz4Decompress(
|
||||
Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
|
||||
|
||||
if (LZ4_decompress_safe(
|
||||
reinterpret_cast<const char*>(in),
|
||||
reinterpret_cast<char const*>(in),
|
||||
reinterpret_cast<char*>(decompressed),
|
||||
inSize,
|
||||
decompressedSize) != decompressedSize)
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
constexpr const E&
|
||||
constexpr E const&
|
||||
value() const&
|
||||
{
|
||||
return val_;
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
return std::move(val_);
|
||||
}
|
||||
|
||||
constexpr const E&&
|
||||
constexpr E const&&
|
||||
value() const&&
|
||||
{
|
||||
return std::move(val_);
|
||||
|
||||
@@ -654,12 +654,14 @@ SharedWeakUnion<T>::convertToWeak()
|
||||
break;
|
||||
case destroy:
|
||||
// We just added a weak ref. How could we destroy?
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
|
||||
"added ref");
|
||||
delete p;
|
||||
unsafeSetRawPtr(nullptr);
|
||||
return true; // Should never happen
|
||||
// LCOV_EXCL_STOP
|
||||
case partialDestroy:
|
||||
// This is a weird case. We just converted the last strong
|
||||
// pointer to a weak pointer.
|
||||
|
||||
@@ -294,7 +294,7 @@ IntrusiveRefCounts::releaseStrongRef() const
|
||||
}
|
||||
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_release))
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
// Can't be in partial destroy because only decrementing the strong
|
||||
// count to zero can start a partial destroy, and that can't happen
|
||||
@@ -351,7 +351,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
}
|
||||
}
|
||||
if (refCounts.compare_exchange_weak(
|
||||
prevIntVal, nextIntVal, std::memory_order_release))
|
||||
prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(!(prevIntVal & partialDestroyStartedMask)),
|
||||
@@ -374,7 +374,7 @@ IntrusiveRefCounts::releaseWeakRef() const
|
||||
// This case should only be hit if the partialDestroyStartedBit is
|
||||
// set non-atomically (and even then very rarely). The code is kept
|
||||
// in case we need to set the flag non-atomically for perf reasons.
|
||||
refCounts.wait(prevIntVal, std::memory_order_acq_rel);
|
||||
refCounts.wait(prevIntVal, std::memory_order_acquire);
|
||||
prevIntVal = refCounts.load(std::memory_order_acquire);
|
||||
prev = RefCountPair{prevIntVal};
|
||||
}
|
||||
@@ -382,7 +382,7 @@ IntrusiveRefCounts::releaseWeakRef() const
|
||||
{
|
||||
// partial destroy MUST finish before running a full destroy (when
|
||||
// using weak pointers)
|
||||
refCounts.wait(prevIntVal - weakDelta, std::memory_order_acq_rel);
|
||||
refCounts.wait(prevIntVal - weakDelta, std::memory_order_acquire);
|
||||
}
|
||||
return ReleaseWeakRefAction::destroy;
|
||||
}
|
||||
@@ -396,7 +396,7 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
|
||||
auto desiredValue = RefCountPair{2, 1}.combinedValue();
|
||||
|
||||
while (!refCounts.compare_exchange_weak(
|
||||
curValue, desiredValue, std::memory_order_release))
|
||||
curValue, desiredValue, std::memory_order_acq_rel))
|
||||
{
|
||||
RefCountPair const prev{curValue};
|
||||
if (!prev.strong)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
@@ -150,6 +150,24 @@ public:
|
||||
return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
|
||||
}
|
||||
|
||||
Number
|
||||
truncate() const noexcept
|
||||
{
|
||||
if (exponent_ >= 0 || mantissa_ == 0)
|
||||
return *this;
|
||||
|
||||
Number ret = *this;
|
||||
while (ret.exponent_ < 0 && ret.mantissa_ != 0)
|
||||
{
|
||||
ret.exponent_ += 1;
|
||||
ret.mantissa_ /= rep(10);
|
||||
}
|
||||
// We are guaranteed that normalize() will never throw an exception
|
||||
// because exponent is either negative or zero at this point.
|
||||
ret.normalize();
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend constexpr bool
|
||||
operator>(Number const& x, Number const& y) noexcept
|
||||
{
|
||||
|
||||
@@ -4,37 +4,34 @@ Utility functions and classes.
|
||||
|
||||
ripple/basic should contain no dependencies on other modules.
|
||||
|
||||
# Choosing a rippled container.
|
||||
|
||||
Choosing a rippled container.
|
||||
=============================
|
||||
- `std::vector`
|
||||
- For ordered containers with most insertions or erases at the end.
|
||||
|
||||
* `std::vector`
|
||||
* For ordered containers with most insertions or erases at the end.
|
||||
- `std::deque`
|
||||
- For ordered containers with most insertions or erases at the start or end.
|
||||
|
||||
* `std::deque`
|
||||
* For ordered containers with most insertions or erases at the start or end.
|
||||
|
||||
* `std::list`
|
||||
* For ordered containers with inserts and erases to the middle.
|
||||
* For containers with iterators stable over insert and erase.
|
||||
* Generally slower and bigger than `std::vector` or `std::deque` except for
|
||||
- `std::list`
|
||||
- For ordered containers with inserts and erases to the middle.
|
||||
- For containers with iterators stable over insert and erase.
|
||||
- Generally slower and bigger than `std::vector` or `std::deque` except for
|
||||
those cases.
|
||||
|
||||
* `std::set`
|
||||
* For sorted containers.
|
||||
- `std::set`
|
||||
- For sorted containers.
|
||||
|
||||
* `ripple::hash_set`
|
||||
* Where inserts and contains need to be O(1).
|
||||
* For "small" sets, `std::set` might be faster and smaller.
|
||||
- `ripple::hash_set`
|
||||
- Where inserts and contains need to be O(1).
|
||||
- For "small" sets, `std::set` might be faster and smaller.
|
||||
|
||||
* `ripple::hardened_hash_set`
|
||||
* For data sets where the key could be manipulated by an attacker
|
||||
in an attempt to mount an algorithmic complexity attack: see
|
||||
- `ripple::hardened_hash_set`
|
||||
- For data sets where the key could be manipulated by an attacker
|
||||
in an attempt to mount an algorithmic complexity attack: see
|
||||
http://en.wikipedia.org/wiki/Algorithmic_complexity_attack
|
||||
|
||||
|
||||
The following container is deprecated
|
||||
|
||||
* `std::unordered_set`
|
||||
* Use `ripple::hash_set` instead, which uses a better hashing algorithm.
|
||||
* Or use `ripple::hardened_hash_set` to prevent algorithmic complexity attacks.
|
||||
- `std::unordered_set`
|
||||
- Use `ripple::hash_set` instead, which uses a better hashing algorithm.
|
||||
- Or use `ripple::hardened_hash_set` to prevent algorithmic complexity attacks.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <xrpl/basics/Resolver.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
explicit ResolverAsio() = default;
|
||||
|
||||
static std::unique_ptr<ResolverAsio>
|
||||
New(boost::asio::io_service&, beast::Journal);
|
||||
New(boost::asio::io_context&, beast::Journal);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
sweep();
|
||||
|
||||
bool
|
||||
del(const key_type& key, bool valid);
|
||||
del(key_type const& key, bool valid);
|
||||
|
||||
public:
|
||||
/** Replace aliased objects with originals.
|
||||
@@ -134,20 +134,20 @@ public:
|
||||
template <class R>
|
||||
bool
|
||||
canonicalize(
|
||||
const key_type& key,
|
||||
key_type const& key,
|
||||
SharedPointerType& data,
|
||||
R&& replaceCallback);
|
||||
|
||||
bool
|
||||
canonicalize_replace_cache(
|
||||
const key_type& key,
|
||||
key_type const& key,
|
||||
SharedPointerType const& data);
|
||||
|
||||
bool
|
||||
canonicalize_replace_client(const key_type& key, SharedPointerType& data);
|
||||
canonicalize_replace_client(key_type const& key, SharedPointerType& data);
|
||||
|
||||
SharedPointerType
|
||||
fetch(const key_type& key);
|
||||
fetch(key_type const& key);
|
||||
|
||||
/** Insert the element into the container.
|
||||
If the key already exists, nothing happens.
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
// simply return an iterator.
|
||||
//
|
||||
bool
|
||||
retrieve(const key_type& key, T& data);
|
||||
retrieve(key_type const& key, T& data);
|
||||
|
||||
mutex_type&
|
||||
peekMutex();
|
||||
@@ -322,10 +322,10 @@ private:
|
||||
std::string m_name;
|
||||
|
||||
// Desired number of cache entries (0 = ignore)
|
||||
const int m_target_size;
|
||||
int const m_target_size;
|
||||
|
||||
// Desired maximum cache age
|
||||
const clock_type::duration m_target_age;
|
||||
clock_type::duration const m_target_age;
|
||||
|
||||
// Number of items cached
|
||||
int m_cache_count;
|
||||
|
||||
@@ -371,7 +371,7 @@ TaggedCache<
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::del(const key_type& key, bool valid)
|
||||
Mutex>::del(key_type const& key, bool valid)
|
||||
{
|
||||
// Remove from cache, if !valid, remove from map too. Returns true if
|
||||
// removed from cache
|
||||
@@ -420,7 +420,7 @@ TaggedCache<
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize(
|
||||
const key_type& key,
|
||||
key_type const& key,
|
||||
SharedPointerType& data,
|
||||
R&& replaceCallback)
|
||||
{
|
||||
@@ -515,7 +515,7 @@ TaggedCache<
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize_replace_cache(
|
||||
const key_type& key,
|
||||
key_type const& key,
|
||||
SharedPointerType const& data)
|
||||
{
|
||||
return canonicalize(
|
||||
@@ -541,7 +541,7 @@ TaggedCache<
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::
|
||||
canonicalize_replace_client(const key_type& key, SharedPointerType& data)
|
||||
canonicalize_replace_client(key_type const& key, SharedPointerType& data)
|
||||
{
|
||||
return canonicalize(key, data, []() { return false; });
|
||||
}
|
||||
@@ -564,7 +564,7 @@ TaggedCache<
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::fetch(const key_type& key)
|
||||
Mutex>::fetch(key_type const& key)
|
||||
{
|
||||
std::lock_guard<mutex_type> l(m_mutex);
|
||||
auto ret = initialFetch(key, l);
|
||||
@@ -662,7 +662,7 @@ TaggedCache<
|
||||
SharedPointerType,
|
||||
Hash,
|
||||
KeyEqual,
|
||||
Mutex>::retrieve(const key_type& key, T& data)
|
||||
Mutex>::retrieve(key_type const& key, T& data)
|
||||
{
|
||||
// retrieve the value of the stored data
|
||||
auto entry = fetch(key);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef RIPPLE_ALGORITHM_H_INCLUDED
|
||||
#define RIPPLE_ALGORITHM_H_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -374,7 +374,7 @@ public:
|
||||
}
|
||||
|
||||
base_uint&
|
||||
operator^=(const base_uint& b)
|
||||
operator^=(base_uint const& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
data_[i] ^= b.data_[i];
|
||||
@@ -383,7 +383,7 @@ public:
|
||||
}
|
||||
|
||||
base_uint&
|
||||
operator&=(const base_uint& b)
|
||||
operator&=(base_uint const& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
data_[i] &= b.data_[i];
|
||||
@@ -392,7 +392,7 @@ public:
|
||||
}
|
||||
|
||||
base_uint&
|
||||
operator|=(const base_uint& b)
|
||||
operator|=(base_uint const& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
data_[i] |= b.data_[i];
|
||||
@@ -415,11 +415,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint
|
||||
base_uint const
|
||||
operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
base_uint const ret = *this;
|
||||
++(*this);
|
||||
|
||||
return ret;
|
||||
@@ -441,11 +441,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
const base_uint
|
||||
base_uint const
|
||||
operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
const base_uint ret = *this;
|
||||
base_uint const ret = *this;
|
||||
--(*this);
|
||||
|
||||
return ret;
|
||||
@@ -466,7 +466,7 @@ public:
|
||||
}
|
||||
|
||||
base_uint&
|
||||
operator+=(const base_uint& b)
|
||||
operator+=(base_uint const& b)
|
||||
{
|
||||
std::uint64_t carry = 0;
|
||||
|
||||
@@ -511,7 +511,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool
|
||||
parseHex(const char* str)
|
||||
parseHex(char const* str)
|
||||
{
|
||||
return parseHex(std::string_view{str});
|
||||
}
|
||||
@@ -632,6 +632,16 @@ to_string(base_uint<Bits, Tag> const& a)
|
||||
return strHex(a.cbegin(), a.cend());
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
inline std::string
|
||||
to_short_string(base_uint<Bits, Tag> const& a)
|
||||
{
|
||||
static_assert(
|
||||
base_uint<Bits, Tag>::bytes > 4,
|
||||
"For 4 bytes or less, use a native type");
|
||||
return strHex(a.cbegin(), a.cbegin() + 4) + "...";
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& out, base_uint<Bits, Tag> const& u)
|
||||
|
||||
@@ -43,7 +43,7 @@ struct less
|
||||
using result_type = bool;
|
||||
|
||||
constexpr bool
|
||||
operator()(const T& left, const T& right) const
|
||||
operator()(T const& left, T const& right) const
|
||||
{
|
||||
return std::less<T>()(left, right);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ struct equal_to
|
||||
using result_type = bool;
|
||||
|
||||
constexpr bool
|
||||
operator()(const T& left, const T& right) const
|
||||
operator()(T const& left, T const& right) const
|
||||
{
|
||||
return std::equal_to<T>()(left, right);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,8 @@
|
||||
#include <xrpl/beast/hash/xxhasher.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
auto constexpr muldiv_max = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
@@ -52,7 +52,7 @@ template <
|
||||
typename Value,
|
||||
typename Hash,
|
||||
typename Pred = std::equal_to<Key>,
|
||||
typename Alloc = std::allocator<std::pair<const Key, Value>>>
|
||||
typename Alloc = std::allocator<std::pair<Key const, Value>>>
|
||||
class partitioned_unordered_map
|
||||
{
|
||||
std::size_t partitions_;
|
||||
|
||||
@@ -28,9 +28,8 @@ namespace ripple {
|
||||
// the destination can hold all values of the source. This is particularly
|
||||
// handy when the source or destination is an enumeration type.
|
||||
|
||||
template <class Dest, class Src>
|
||||
static constexpr bool is_safetocasttovalue_v =
|
||||
(std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
||||
template <class Src, class Dest>
|
||||
concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
||||
(std::is_signed<Src>::value || std::is_unsigned<Dest>::value) &&
|
||||
(std::is_signed<Src>::value != std::is_signed<Dest>::value
|
||||
? sizeof(Dest) > sizeof(Src)
|
||||
@@ -78,7 +77,7 @@ inline constexpr std::
|
||||
unsafe_cast(Src s) noexcept
|
||||
{
|
||||
static_assert(
|
||||
!is_safetocasttovalue_v<Dest, Src>,
|
||||
!SafeToCast<Src, Dest>,
|
||||
"Only unsafe if casting signed to unsigned or "
|
||||
"destination is too small");
|
||||
return static_cast<Dest>(s);
|
||||
|
||||
@@ -24,10 +24,8 @@
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -76,13 +74,13 @@ public:
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const tagged_integer& rhs) const noexcept
|
||||
operator<(tagged_integer const& rhs) const noexcept
|
||||
{
|
||||
return m_value < rhs.m_value;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const tagged_integer& rhs) const noexcept
|
||||
operator==(tagged_integer const& rhs) const noexcept
|
||||
{
|
||||
return m_value == rhs.m_value;
|
||||
}
|
||||
@@ -144,14 +142,14 @@ public:
|
||||
}
|
||||
|
||||
tagged_integer&
|
||||
operator<<=(const tagged_integer& rhs) noexcept
|
||||
operator<<=(tagged_integer const& rhs) noexcept
|
||||
{
|
||||
m_value <<= rhs.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
tagged_integer&
|
||||
operator>>=(const tagged_integer& rhs) noexcept
|
||||
operator>>=(tagged_integer const& rhs) noexcept
|
||||
{
|
||||
m_value >>= rhs.m_value;
|
||||
return *this;
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Measures handler latency on an io_service queue. */
|
||||
/** Measures handler latency on an io_context queue. */
|
||||
template <class Clock>
|
||||
class io_latency_probe
|
||||
{
|
||||
@@ -44,12 +45,12 @@ private:
|
||||
std::condition_variable_any m_cond;
|
||||
std::size_t m_count;
|
||||
duration const m_period;
|
||||
boost::asio::io_service& m_ios;
|
||||
boost::asio::io_context& m_ios;
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
|
||||
bool m_cancel;
|
||||
|
||||
public:
|
||||
io_latency_probe(duration const& period, boost::asio::io_service& ios)
|
||||
io_latency_probe(duration const& period, boost::asio::io_context& ios)
|
||||
: m_count(1)
|
||||
, m_period(period)
|
||||
, m_ios(ios)
|
||||
@@ -64,16 +65,16 @@ public:
|
||||
cancel(lock, true);
|
||||
}
|
||||
|
||||
/** Return the io_service associated with the latency probe. */
|
||||
/** Return the io_context associated with the latency probe. */
|
||||
/** @{ */
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
{
|
||||
return m_ios;
|
||||
}
|
||||
|
||||
boost::asio::io_service const&
|
||||
get_io_service() const
|
||||
boost::asio::io_context const&
|
||||
get_io_context() const
|
||||
{
|
||||
return m_ios;
|
||||
}
|
||||
@@ -109,8 +110,10 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
m_ios.post(sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
}
|
||||
|
||||
/** Initiate continuous i/o latency sampling.
|
||||
@@ -124,8 +127,10 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
m_ios.post(sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -236,12 +241,13 @@ private:
|
||||
// The latency is too high to maintain the desired
|
||||
// period so don't bother with a timer.
|
||||
//
|
||||
m_probe->m_ios.post(
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_probe->m_timer.expires_from_now(when - now);
|
||||
m_probe->m_timer.expires_after(when - now);
|
||||
m_probe->m_timer.async_wait(
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
@@ -254,7 +260,8 @@ private:
|
||||
if (!m_probe)
|
||||
return;
|
||||
typename Clock::time_point const now(Clock::now());
|
||||
m_probe->m_ios.post(
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
#ifndef BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
|
||||
#define BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Abstract interface to a clock.
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <xrpl/beast/clock/abstract_clock.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Manual clock implementation.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <xrpl/beast/container/aged_container.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#ifndef BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -3257,7 +3257,6 @@ operator==(aged_unordered_container<
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
using EqRng = std::pair<const_iterator, const_iterator>;
|
||||
for (auto iter(cbegin()), last(cend()); iter != last;)
|
||||
{
|
||||
auto const& k(extract(*iter));
|
||||
|
||||
@@ -29,11 +29,9 @@
|
||||
#include <charconv>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
|
||||
@@ -26,12 +26,9 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <tuple>
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace beast {
|
||||
template <class Hasher = xxhasher>
|
||||
struct uhash
|
||||
{
|
||||
explicit uhash() = default;
|
||||
uhash() = default;
|
||||
|
||||
using result_type = typename Hasher::result_type;
|
||||
|
||||
|
||||
@@ -24,32 +24,110 @@
|
||||
|
||||
#include <xxhash.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class xxhasher
|
||||
{
|
||||
private:
|
||||
// requires 64-bit std::size_t
|
||||
static_assert(sizeof(std::size_t) == 8, "");
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
XXH3_state_t* state_;
|
||||
private:
|
||||
static_assert(sizeof(std::size_t) == 8, "requires 64-bit std::size_t");
|
||||
// Have an internal buffer to avoid the streaming API
|
||||
// A 64-byte buffer should to be big enough for us
|
||||
static constexpr std::size_t INTERNAL_BUFFER_SIZE = 64;
|
||||
|
||||
alignas(64) std::array<std::uint8_t, INTERNAL_BUFFER_SIZE> buffer_;
|
||||
std::span<std::uint8_t> readBuffer_;
|
||||
std::span<std::uint8_t> writeBuffer_;
|
||||
|
||||
std::optional<XXH64_hash_t> seed_;
|
||||
XXH3_state_t* state_ = nullptr;
|
||||
|
||||
void
|
||||
resetBuffers()
|
||||
{
|
||||
writeBuffer_ = std::span{buffer_};
|
||||
readBuffer_ = {};
|
||||
}
|
||||
|
||||
void
|
||||
updateHash(void const* data, std::size_t len)
|
||||
{
|
||||
if (writeBuffer_.size() < len)
|
||||
{
|
||||
flushToState(data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(writeBuffer_.data(), data, len);
|
||||
writeBuffer_ = writeBuffer_.subspan(len);
|
||||
readBuffer_ = std::span{
|
||||
std::begin(buffer_), buffer_.size() - writeBuffer_.size()};
|
||||
}
|
||||
}
|
||||
|
||||
static XXH3_state_t*
|
||||
allocState()
|
||||
{
|
||||
auto ret = XXH3_createState();
|
||||
if (ret == nullptr)
|
||||
throw std::bad_alloc();
|
||||
throw std::bad_alloc(); // LCOV_EXCL_LINE
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
void
|
||||
flushToState(void const* data, std::size_t len)
|
||||
{
|
||||
if (!state_)
|
||||
{
|
||||
state_ = allocState();
|
||||
if (seed_.has_value())
|
||||
{
|
||||
XXH3_64bits_reset_withSeed(state_, *seed_);
|
||||
}
|
||||
else
|
||||
{
|
||||
XXH3_64bits_reset(state_);
|
||||
}
|
||||
}
|
||||
XXH3_64bits_update(state_, readBuffer_.data(), readBuffer_.size());
|
||||
resetBuffers();
|
||||
if (data && len)
|
||||
{
|
||||
XXH3_64bits_update(state_, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
result_type
|
||||
retrieveHash()
|
||||
{
|
||||
if (state_)
|
||||
{
|
||||
flushToState(nullptr, 0);
|
||||
return XXH3_64bits_digest(state_);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seed_.has_value())
|
||||
{
|
||||
return XXH3_64bits_withSeed(
|
||||
readBuffer_.data(), readBuffer_.size(), *seed_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return XXH3_64bits(readBuffer_.data(), readBuffer_.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr auto const endian = boost::endian::order::native;
|
||||
|
||||
xxhasher(xxhasher const&) = delete;
|
||||
@@ -58,43 +136,43 @@ public:
|
||||
|
||||
xxhasher()
|
||||
{
|
||||
state_ = allocState();
|
||||
XXH3_64bits_reset(state_);
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
~xxhasher() noexcept
|
||||
{
|
||||
XXH3_freeState(state_);
|
||||
if (state_)
|
||||
{
|
||||
XXH3_freeState(state_);
|
||||
}
|
||||
}
|
||||
|
||||
template <
|
||||
class Seed,
|
||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
explicit xxhasher(Seed seed)
|
||||
explicit xxhasher(Seed seed) : seed_(seed)
|
||||
{
|
||||
state_ = allocState();
|
||||
XXH3_64bits_reset_withSeed(state_, seed);
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
template <
|
||||
class Seed,
|
||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||
xxhasher(Seed seed, Seed)
|
||||
xxhasher(Seed seed, Seed) : seed_(seed)
|
||||
{
|
||||
state_ = allocState();
|
||||
XXH3_64bits_reset_withSeed(state_, seed);
|
||||
resetBuffers();
|
||||
}
|
||||
|
||||
void
|
||||
operator()(void const* key, std::size_t len) noexcept
|
||||
{
|
||||
XXH3_64bits_update(state_, key, len);
|
||||
updateHash(key, len);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
operator result_type() noexcept
|
||||
{
|
||||
return XXH3_64bits_digest(state_);
|
||||
return retrieveHash();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,11 +29,7 @@
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -98,7 +94,11 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
|
||||
else if (addr.is_v6())
|
||||
hash_append(h, addr.to_v6().to_bytes());
|
||||
else
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("beast::hash_append : invalid address type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
} // namespace beast
|
||||
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace IP {
|
||||
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <ios>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace IP {
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <xrpl/beast/net/IPAddress.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <ios>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
@@ -215,7 +214,7 @@ namespace std {
|
||||
template <>
|
||||
struct hash<::beast::IP::Endpoint>
|
||||
{
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
std::size_t
|
||||
operator()(::beast::IP::Endpoint const& endpoint) const
|
||||
@@ -230,7 +229,7 @@ namespace boost {
|
||||
template <>
|
||||
struct hash<::beast::IP::Endpoint>
|
||||
{
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
std::size_t
|
||||
operator()(::beast::IP::Endpoint const& endpoint) const
|
||||
|
||||
@@ -28,10 +28,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
#ifndef BEAST_TEST_YIELD_TO_HPP
|
||||
#define BEAST_TEST_YIELD_TO_HPP
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
@@ -30,10 +31,12 @@ namespace test {
|
||||
class enable_yield_to
|
||||
{
|
||||
protected:
|
||||
boost::asio::io_service ios_;
|
||||
boost::asio::io_context ios_;
|
||||
|
||||
private:
|
||||
boost::optional<boost::asio::io_service::work> work_;
|
||||
boost::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
work_;
|
||||
std::vector<std::thread> threads_;
|
||||
std::mutex m_;
|
||||
std::condition_variable cv_;
|
||||
@@ -43,7 +46,8 @@ public:
|
||||
/// The type of yield context passed to functions.
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
explicit enable_yield_to(std::size_t concurrency = 1) : work_(ios_)
|
||||
explicit enable_yield_to(std::size_t concurrency = 1)
|
||||
: work_(boost::asio::make_work_guard(ios_))
|
||||
{
|
||||
threads_.reserve(concurrency);
|
||||
while (concurrency--)
|
||||
@@ -57,9 +61,9 @@ public:
|
||||
t.join();
|
||||
}
|
||||
|
||||
/// Return the `io_service` associated with the object
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
/// Return the `io_context` associated with the object
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
{
|
||||
return ios_;
|
||||
}
|
||||
@@ -112,13 +116,18 @@ enable_yield_to::spawn(F0&& f, FN&&... fn)
|
||||
{
|
||||
boost::asio::spawn(
|
||||
ios_,
|
||||
boost::allocator_arg,
|
||||
boost::context::fixedsize_stack(2 * 1024 * 1024),
|
||||
[&](yield_context yield) {
|
||||
f(yield);
|
||||
std::lock_guard lock{m_};
|
||||
if (--running_ == 0)
|
||||
cv_.notify_all();
|
||||
},
|
||||
boost::coroutines::attributes(2 * 1024 * 1024));
|
||||
[](std::exception_ptr e) {
|
||||
if (e)
|
||||
std::rethrow_exception(e);
|
||||
});
|
||||
spawn(fn...);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -39,11 +39,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#endif
|
||||
|
||||
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
||||
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
|
||||
XRPL_ASSERT(cond, function " : " description)
|
||||
|
||||
// How to use the instrumentation macros:
|
||||
//
|
||||
// * XRPL_ASSERT if cond must be true but the line might not be reached during
|
||||
// fuzzing. Same like `assert` in normal use.
|
||||
// * XRPL_ASSERT_PARTS is for convenience, and works like XRPL_ASSERT, but
|
||||
// splits the message param into "function" and "description", then joins
|
||||
// them with " : " before passing to XRPL_ASSERT.
|
||||
// * ALWAYS if cond must be true _and_ the line must be reached during fuzzing.
|
||||
// Same like `assert` in normal use.
|
||||
// * REACHABLE if the line must be reached during fuzzing
|
||||
|
||||
@@ -31,36 +31,28 @@ namespace beast {
|
||||
|
||||
template <class Generator>
|
||||
void
|
||||
rngfill(void* buffer, std::size_t bytes, Generator& g)
|
||||
rngfill(void* const buffer, std::size_t const bytes, Generator& g)
|
||||
{
|
||||
using result_type = typename Generator::result_type;
|
||||
constexpr std::size_t result_size = sizeof(result_type);
|
||||
|
||||
while (bytes >= sizeof(result_type))
|
||||
std::uint8_t* const buffer_start = static_cast<std::uint8_t*>(buffer);
|
||||
std::size_t const complete_iterations = bytes / result_size;
|
||||
std::size_t const bytes_remaining = bytes % result_size;
|
||||
|
||||
for (std::size_t count = 0; count < complete_iterations; ++count)
|
||||
{
|
||||
auto const v = g();
|
||||
std::memcpy(buffer, &v, sizeof(v));
|
||||
buffer = reinterpret_cast<std::uint8_t*>(buffer) + sizeof(v);
|
||||
bytes -= sizeof(v);
|
||||
result_type const v = g();
|
||||
std::size_t const offset = count * result_size;
|
||||
std::memcpy(buffer_start + offset, &v, result_size);
|
||||
}
|
||||
|
||||
XRPL_ASSERT(
|
||||
bytes < sizeof(result_type), "beast::rngfill(void*) : maximum bytes");
|
||||
|
||||
#ifdef __GNUC__
|
||||
// gcc 11.1 (falsely) warns about an array-bounds overflow in release mode.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
|
||||
if (bytes > 0)
|
||||
if (bytes_remaining > 0)
|
||||
{
|
||||
auto const v = g();
|
||||
std::memcpy(buffer, &v, bytes);
|
||||
result_type const v = g();
|
||||
std::size_t const offset = complete_iterations * result_size;
|
||||
std::memcpy(buffer_start + offset, &v, bytes_remaining);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
template <
|
||||
|
||||
@@ -37,9 +37,9 @@ class temp_dir
|
||||
|
||||
public:
|
||||
#if !GENERATING_DOCS
|
||||
temp_dir(const temp_dir&) = delete;
|
||||
temp_dir(temp_dir const&) = delete;
|
||||
temp_dir&
|
||||
operator=(const temp_dir&) = delete;
|
||||
operator=(temp_dir const&) = delete;
|
||||
#endif
|
||||
|
||||
/// Construct a temporary directory.
|
||||
|
||||
@@ -39,7 +39,7 @@ class Reader
|
||||
{
|
||||
public:
|
||||
using Char = char;
|
||||
using Location = const Char*;
|
||||
using Location = Char const*;
|
||||
|
||||
/** \brief Constructs a Reader allowing all features
|
||||
* for parsing.
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
* error occurred.
|
||||
*/
|
||||
bool
|
||||
parse(const char* beginDoc, const char* endDoc, Value& root);
|
||||
parse(char const* beginDoc, char const* endDoc, Value& root);
|
||||
|
||||
/// \brief Parse from input stream.
|
||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||
@@ -133,7 +133,7 @@ private:
|
||||
using Errors = std::deque<ErrorInfo>;
|
||||
|
||||
bool
|
||||
expectToken(TokenType type, Token& token, const char* message);
|
||||
expectToken(TokenType type, Token& token, char const* message);
|
||||
bool
|
||||
readToken(Token& token);
|
||||
void
|
||||
@@ -217,7 +217,7 @@ Reader::parse(Value& root, BufferSequence const& bs)
|
||||
std::string s;
|
||||
s.reserve(buffer_size(bs));
|
||||
for (auto const& b : bs)
|
||||
s.append(buffer_cast<char const*>(b), buffer_size(b));
|
||||
s.append(static_cast<char const*>(b.data()), buffer_size(b));
|
||||
return parse(s, root);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
||||
#define RIPPLE_JSON_JSON_VALUE_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
|
||||
#include <cstring>
|
||||
@@ -61,24 +62,24 @@ enum ValueType {
|
||||
class StaticString
|
||||
{
|
||||
public:
|
||||
constexpr explicit StaticString(const char* czstring) : str_(czstring)
|
||||
constexpr explicit StaticString(char const* czstring) : str_(czstring)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr
|
||||
operator const char*() const
|
||||
operator char const*() const
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
constexpr const char*
|
||||
constexpr char const*
|
||||
c_str() const
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* str_;
|
||||
char const* str_;
|
||||
};
|
||||
|
||||
inline bool
|
||||
@@ -156,10 +157,10 @@ public:
|
||||
using Int = Json::Int;
|
||||
using ArrayIndex = UInt;
|
||||
|
||||
static const Value null;
|
||||
static const Int minInt;
|
||||
static const Int maxInt;
|
||||
static const UInt maxUInt;
|
||||
static Value const null;
|
||||
static Int const minInt;
|
||||
static Int const maxInt;
|
||||
static UInt const maxUInt;
|
||||
|
||||
private:
|
||||
class CZString
|
||||
@@ -171,24 +172,24 @@ private:
|
||||
duplicateOnCopy
|
||||
};
|
||||
CZString(int index);
|
||||
CZString(const char* cstr, DuplicationPolicy allocate);
|
||||
CZString(const CZString& other);
|
||||
CZString(char const* cstr, DuplicationPolicy allocate);
|
||||
CZString(CZString const& other);
|
||||
~CZString();
|
||||
CZString&
|
||||
operator=(const CZString& other) = delete;
|
||||
operator=(CZString const& other) = delete;
|
||||
bool
|
||||
operator<(const CZString& other) const;
|
||||
operator<(CZString const& other) const;
|
||||
bool
|
||||
operator==(const CZString& other) const;
|
||||
operator==(CZString const& other) const;
|
||||
int
|
||||
index() const;
|
||||
const char*
|
||||
char const*
|
||||
c_str() const;
|
||||
bool
|
||||
isStaticString() const;
|
||||
|
||||
private:
|
||||
const char* cstr_;
|
||||
char const* cstr_;
|
||||
int index_;
|
||||
};
|
||||
|
||||
@@ -215,7 +216,8 @@ public:
|
||||
Value(Int value);
|
||||
Value(UInt value);
|
||||
Value(double value);
|
||||
Value(const char* value);
|
||||
Value(char const* value);
|
||||
Value(ripple::Number const& value);
|
||||
/** \brief Constructs a value from a static string.
|
||||
|
||||
* Like other value string constructor but do not duplicate the string for
|
||||
@@ -227,10 +229,10 @@ public:
|
||||
* Json::Value aValue( StaticString("some text") );
|
||||
* \endcode
|
||||
*/
|
||||
Value(const StaticString& value);
|
||||
Value(StaticString const& value);
|
||||
Value(std::string const& value);
|
||||
Value(bool value);
|
||||
Value(const Value& other);
|
||||
Value(Value const& other);
|
||||
~Value();
|
||||
|
||||
Value&
|
||||
@@ -247,7 +249,7 @@ public:
|
||||
ValueType
|
||||
type() const;
|
||||
|
||||
const char*
|
||||
char const*
|
||||
asCString() const;
|
||||
/** Returns the unquoted string value. */
|
||||
std::string
|
||||
@@ -317,12 +319,12 @@ public:
|
||||
/// Access an array element (zero based index )
|
||||
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||
/// this from the operator[] which takes a string.)
|
||||
const Value&
|
||||
Value const&
|
||||
operator[](UInt index) const;
|
||||
/// If the array contains at least index+1 elements, returns the element
|
||||
/// value, otherwise returns defaultValue.
|
||||
Value
|
||||
get(UInt index, const Value& defaultValue) const;
|
||||
get(UInt index, Value const& defaultValue) const;
|
||||
/// Return true if index < size().
|
||||
bool
|
||||
isValidIndex(UInt index) const;
|
||||
@@ -330,25 +332,25 @@ public:
|
||||
///
|
||||
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||
Value&
|
||||
append(const Value& value);
|
||||
append(Value const& value);
|
||||
Value&
|
||||
append(Value&& value);
|
||||
|
||||
/// Access an object value by name, create a null member if it does not
|
||||
/// exist.
|
||||
Value&
|
||||
operator[](const char* key);
|
||||
operator[](char const* key);
|
||||
/// Access an object value by name, returns null if there is no member with
|
||||
/// that name.
|
||||
const Value&
|
||||
operator[](const char* key) const;
|
||||
Value const&
|
||||
operator[](char const* key) const;
|
||||
/// Access an object value by name, create a null member if it does not
|
||||
/// exist.
|
||||
Value&
|
||||
operator[](std::string const& key);
|
||||
/// Access an object value by name, returns null if there is no member with
|
||||
/// that name.
|
||||
const Value&
|
||||
Value const&
|
||||
operator[](std::string const& key) const;
|
||||
/** \brief Access an object value by name, create a null member if it does
|
||||
not exist.
|
||||
@@ -364,14 +366,16 @@ public:
|
||||
* \endcode
|
||||
*/
|
||||
Value&
|
||||
operator[](const StaticString& key);
|
||||
operator[](StaticString const& key);
|
||||
Value const&
|
||||
operator[](StaticString const& key) const;
|
||||
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
Value
|
||||
get(const char* key, const Value& defaultValue) const;
|
||||
get(char const* key, Value const& defaultValue) const;
|
||||
/// Return the member named key if it exist, defaultValue otherwise.
|
||||
Value
|
||||
get(std::string const& key, const Value& defaultValue) const;
|
||||
get(std::string const& key, Value const& defaultValue) const;
|
||||
|
||||
/// \brief Remove and return the named member.
|
||||
///
|
||||
@@ -380,14 +384,14 @@ public:
|
||||
/// \pre type() is objectValue or nullValue
|
||||
/// \post type() is unchanged
|
||||
Value
|
||||
removeMember(const char* key);
|
||||
removeMember(char const* key);
|
||||
/// Same as removeMember(const char*)
|
||||
Value
|
||||
removeMember(std::string const& key);
|
||||
|
||||
/// Return true if the object has a member named key.
|
||||
bool
|
||||
isMember(const char* key) const;
|
||||
isMember(char const* key) const;
|
||||
/// Return true if the object has a member named key.
|
||||
bool
|
||||
isMember(std::string const& key) const;
|
||||
@@ -414,13 +418,13 @@ public:
|
||||
end();
|
||||
|
||||
friend bool
|
||||
operator==(const Value&, const Value&);
|
||||
operator==(Value const&, Value const&);
|
||||
friend bool
|
||||
operator<(const Value&, const Value&);
|
||||
operator<(Value const&, Value const&);
|
||||
|
||||
private:
|
||||
Value&
|
||||
resolveReference(const char* key, bool isStatic);
|
||||
resolveReference(char const* key, bool isStatic);
|
||||
|
||||
private:
|
||||
union ValueHolder
|
||||
@@ -436,32 +440,38 @@ private:
|
||||
int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
|
||||
};
|
||||
|
||||
inline Value
|
||||
to_json(ripple::Number const& number)
|
||||
{
|
||||
return to_string(number);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const Value&, const Value&);
|
||||
operator==(Value const&, Value const&);
|
||||
|
||||
inline bool
|
||||
operator!=(const Value& x, const Value& y)
|
||||
operator!=(Value const& x, Value const& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const Value&, const Value&);
|
||||
operator<(Value const&, Value const&);
|
||||
|
||||
inline bool
|
||||
operator<=(const Value& x, const Value& y)
|
||||
operator<=(Value const& x, Value const& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>(const Value& x, const Value& y)
|
||||
operator>(Value const& x, Value const& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>=(const Value& x, const Value& y)
|
||||
operator>=(Value const& x, Value const& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
@@ -482,11 +492,11 @@ public:
|
||||
virtual ~ValueAllocator() = default;
|
||||
|
||||
virtual char*
|
||||
makeMemberName(const char* memberName) = 0;
|
||||
makeMemberName(char const* memberName) = 0;
|
||||
virtual void
|
||||
releaseMemberName(char* memberName) = 0;
|
||||
virtual char*
|
||||
duplicateStringValue(const char* value, unsigned int length = unknown) = 0;
|
||||
duplicateStringValue(char const* value, unsigned int length = unknown) = 0;
|
||||
virtual void
|
||||
releaseStringValue(char* value) = 0;
|
||||
};
|
||||
@@ -503,16 +513,16 @@ public:
|
||||
|
||||
ValueIteratorBase();
|
||||
|
||||
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueIteratorBase(Value::ObjectValues::iterator const& current);
|
||||
|
||||
bool
|
||||
operator==(const SelfType& other) const
|
||||
operator==(SelfType const& other) const
|
||||
{
|
||||
return isEqual(other);
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const SelfType& other) const
|
||||
operator!=(SelfType const& other) const
|
||||
{
|
||||
return !isEqual(other);
|
||||
}
|
||||
@@ -528,7 +538,7 @@ public:
|
||||
|
||||
/// Return the member name of the referenced Value. "" if it is not an
|
||||
/// objectValue.
|
||||
const char*
|
||||
char const*
|
||||
memberName() const;
|
||||
|
||||
protected:
|
||||
@@ -542,13 +552,13 @@ protected:
|
||||
decrement();
|
||||
|
||||
difference_type
|
||||
computeDistance(const SelfType& other) const;
|
||||
computeDistance(SelfType const& other) const;
|
||||
|
||||
bool
|
||||
isEqual(const SelfType& other) const;
|
||||
isEqual(SelfType const& other) const;
|
||||
|
||||
void
|
||||
copy(const SelfType& other);
|
||||
copy(SelfType const& other);
|
||||
|
||||
private:
|
||||
Value::ObjectValues::iterator current_;
|
||||
@@ -566,8 +576,8 @@ class ValueConstIterator : public ValueIteratorBase
|
||||
public:
|
||||
using size_t = unsigned int;
|
||||
using difference_type = int;
|
||||
using reference = const Value&;
|
||||
using pointer = const Value*;
|
||||
using reference = Value const&;
|
||||
using pointer = Value const*;
|
||||
using SelfType = ValueConstIterator;
|
||||
|
||||
ValueConstIterator() = default;
|
||||
@@ -575,11 +585,11 @@ public:
|
||||
private:
|
||||
/*! \internal Use by Value to create an iterator.
|
||||
*/
|
||||
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueConstIterator(Value::ObjectValues::iterator const& current);
|
||||
|
||||
public:
|
||||
SelfType&
|
||||
operator=(const ValueIteratorBase& other);
|
||||
operator=(ValueIteratorBase const& other);
|
||||
|
||||
SelfType
|
||||
operator++(int)
|
||||
@@ -632,17 +642,17 @@ public:
|
||||
using SelfType = ValueIterator;
|
||||
|
||||
ValueIterator() = default;
|
||||
ValueIterator(const ValueConstIterator& other);
|
||||
ValueIterator(const ValueIterator& other);
|
||||
ValueIterator(ValueConstIterator const& other);
|
||||
ValueIterator(ValueIterator const& other);
|
||||
|
||||
private:
|
||||
/*! \internal Use by Value to create an iterator.
|
||||
*/
|
||||
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueIterator(Value::ObjectValues::iterator const& current);
|
||||
|
||||
public:
|
||||
SelfType&
|
||||
operator=(const SelfType& other);
|
||||
operator=(SelfType const& other);
|
||||
|
||||
SelfType
|
||||
operator++(int)
|
||||
|
||||
@@ -39,14 +39,14 @@ public:
|
||||
{
|
||||
}
|
||||
virtual std::string
|
||||
write(const Value& root) = 0;
|
||||
write(Value const& root) = 0;
|
||||
};
|
||||
|
||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||
* without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human'
|
||||
* consumption, but may be useful to support feature such as RPC where bandwith
|
||||
* consumption, but may be useful to support feature such as RPC where bandwidth
|
||||
* is limited. \sa Reader, Value
|
||||
*/
|
||||
|
||||
@@ -60,11 +60,11 @@ public:
|
||||
|
||||
public: // overridden from Writer
|
||||
std::string
|
||||
write(const Value& root) override;
|
||||
write(Value const& root) override;
|
||||
|
||||
private:
|
||||
void
|
||||
writeValue(const Value& value);
|
||||
writeValue(Value const& value);
|
||||
|
||||
std::string document_;
|
||||
};
|
||||
@@ -101,15 +101,15 @@ public: // overridden from Writer
|
||||
* JSON document that represents the root value.
|
||||
*/
|
||||
std::string
|
||||
write(const Value& root) override;
|
||||
write(Value const& root) override;
|
||||
|
||||
private:
|
||||
void
|
||||
writeValue(const Value& value);
|
||||
writeValue(Value const& value);
|
||||
void
|
||||
writeArrayValue(const Value& value);
|
||||
writeArrayValue(Value const& value);
|
||||
bool
|
||||
isMultineArray(const Value& value);
|
||||
isMultineArray(Value const& value);
|
||||
void
|
||||
pushValue(std::string const& value);
|
||||
void
|
||||
@@ -168,15 +168,15 @@ public:
|
||||
* return a value.
|
||||
*/
|
||||
void
|
||||
write(std::ostream& out, const Value& root);
|
||||
write(std::ostream& out, Value const& root);
|
||||
|
||||
private:
|
||||
void
|
||||
writeValue(const Value& value);
|
||||
writeValue(Value const& value);
|
||||
void
|
||||
writeArrayValue(const Value& value);
|
||||
writeArrayValue(Value const& value);
|
||||
bool
|
||||
isMultineArray(const Value& value);
|
||||
isMultineArray(Value const& value);
|
||||
void
|
||||
pushValue(std::string const& value);
|
||||
void
|
||||
@@ -207,12 +207,12 @@ valueToString(double value);
|
||||
std::string
|
||||
valueToString(bool value);
|
||||
std::string
|
||||
valueToQuotedString(const char* value);
|
||||
valueToQuotedString(char const* value);
|
||||
|
||||
/// \brief Output using the StyledStreamWriter.
|
||||
/// \see Json::operator>>()
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const Value& root);
|
||||
operator<<(std::ostream&, Value const& root);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ pretty(Value const&);
|
||||
|
||||
/** Output using the StyledStreamWriter. @see Json::operator>>(). */
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const Value& root);
|
||||
operator<<(std::ostream&, Value const& root);
|
||||
|
||||
} // namespace Json
|
||||
|
||||
|
||||
392
include/xrpl/ledger/ApplyView.h
Normal file
392
include/xrpl/ledger/ApplyView.h
Normal file
@@ -0,0 +1,392 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
enum ApplyFlags : std::uint32_t {
|
||||
tapNONE = 0x00,
|
||||
|
||||
// This is a local transaction with the
|
||||
// fail_hard flag set.
|
||||
tapFAIL_HARD = 0x10,
|
||||
|
||||
// This is not the transaction's last pass
|
||||
// Transaction can be retried, soft failures allowed
|
||||
tapRETRY = 0x20,
|
||||
|
||||
// Transaction came from a privileged source
|
||||
tapUNLIMITED = 0x400,
|
||||
|
||||
// Transaction is executing as part of a batch
|
||||
tapBATCH = 0x800,
|
||||
|
||||
// Transaction shouldn't be applied
|
||||
// Signatures shouldn't be checked
|
||||
tapDRY_RUN = 0x1000
|
||||
};
|
||||
|
||||
constexpr ApplyFlags
|
||||
operator|(ApplyFlags const& lhs, ApplyFlags const& rhs)
|
||||
{
|
||||
return safe_cast<ApplyFlags>(
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) |
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
}
|
||||
|
||||
static_assert(
|
||||
(tapFAIL_HARD | tapRETRY) == safe_cast<ApplyFlags>(0x30u),
|
||||
"ApplyFlags operator |");
|
||||
static_assert(
|
||||
(tapRETRY | tapFAIL_HARD) == safe_cast<ApplyFlags>(0x30u),
|
||||
"ApplyFlags operator |");
|
||||
|
||||
constexpr ApplyFlags
|
||||
operator&(ApplyFlags const& lhs, ApplyFlags const& rhs)
|
||||
{
|
||||
return safe_cast<ApplyFlags>(
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(lhs) &
|
||||
safe_cast<std::underlying_type_t<ApplyFlags>>(rhs));
|
||||
}
|
||||
|
||||
static_assert((tapFAIL_HARD & tapRETRY) == tapNONE, "ApplyFlags operator &");
|
||||
static_assert((tapRETRY & tapFAIL_HARD) == tapNONE, "ApplyFlags operator &");
|
||||
|
||||
constexpr ApplyFlags
|
||||
operator~(ApplyFlags const& flags)
|
||||
{
|
||||
return safe_cast<ApplyFlags>(
|
||||
~safe_cast<std::underlying_type_t<ApplyFlags>>(flags));
|
||||
}
|
||||
|
||||
static_assert(
|
||||
~tapRETRY == safe_cast<ApplyFlags>(0xFFFFFFDFu),
|
||||
"ApplyFlags operator ~");
|
||||
|
||||
inline ApplyFlags
|
||||
operator|=(ApplyFlags& lhs, ApplyFlags const& rhs)
|
||||
{
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline ApplyFlags
|
||||
operator&=(ApplyFlags& lhs, ApplyFlags const& rhs)
|
||||
{
|
||||
lhs = lhs & rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Writeable view to a ledger, for applying a transaction.
|
||||
|
||||
This refinement of ReadView provides an interface where
|
||||
the SLE can be "checked out" for modifications and put
|
||||
back in an updated or removed state. Also added is an
|
||||
interface to provide contextual information necessary
|
||||
to calculate the results of transaction processing,
|
||||
including the metadata if the view is later applied to
|
||||
the parent (using an interface in the derived class).
|
||||
The context info also includes values from the base
|
||||
ledger such as sequence number and the network time.
|
||||
|
||||
This allows implementations to journal changes made to
|
||||
the state items in a ledger, with the option to apply
|
||||
those changes to the base or discard the changes without
|
||||
affecting the base.
|
||||
|
||||
Typical usage is to call read() for non-mutating
|
||||
operations.
|
||||
|
||||
For mutating operations the sequence is as follows:
|
||||
|
||||
// Add a new value
|
||||
v.insert(sle);
|
||||
|
||||
// Check out a value for modification
|
||||
sle = v.peek(k);
|
||||
|
||||
// Indicate that changes were made
|
||||
v.update(sle)
|
||||
|
||||
// Or, erase the value
|
||||
v.erase(sle)
|
||||
|
||||
The invariant is that insert, update, and erase may not
|
||||
be called with any SLE which belongs to different view.
|
||||
*/
|
||||
class ApplyView : public ReadView
|
||||
{
|
||||
private:
|
||||
/** Add an entry to a directory using the specified insert strategy */
|
||||
std::optional<std::uint64_t>
|
||||
dirAdd(
|
||||
bool preserveOrder,
|
||||
Keylet const& directory,
|
||||
uint256 const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
||||
|
||||
public:
|
||||
ApplyView() = default;
|
||||
|
||||
/** Returns the tx apply flags.
|
||||
|
||||
Flags can affect the outcome of transaction
|
||||
processing. For example, transactions applied
|
||||
to an open ledger generate "local" failures,
|
||||
while transactions applied to the consensus
|
||||
ledger produce hard failures (and claim a fee).
|
||||
*/
|
||||
virtual ApplyFlags
|
||||
flags() const = 0;
|
||||
|
||||
/** Prepare to modify the SLE associated with key.
|
||||
|
||||
Effects:
|
||||
|
||||
Gives the caller ownership of a modifiable
|
||||
SLE associated with the specified key.
|
||||
|
||||
The returned SLE may be used in a subsequent
|
||||
call to erase or update.
|
||||
|
||||
The SLE must not be passed to any other ApplyView.
|
||||
|
||||
@return `nullptr` if the key is not present
|
||||
*/
|
||||
virtual std::shared_ptr<SLE>
|
||||
peek(Keylet const& k) = 0;
|
||||
|
||||
/** Remove a peeked SLE.
|
||||
|
||||
Requirements:
|
||||
|
||||
`sle` was obtained from prior call to peek()
|
||||
on this instance of the RawView.
|
||||
|
||||
Effects:
|
||||
|
||||
The key is no longer associated with the SLE.
|
||||
*/
|
||||
virtual void
|
||||
erase(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Insert a new state SLE
|
||||
|
||||
Requirements:
|
||||
|
||||
`sle` was not obtained from any calls to
|
||||
peek() on any instances of RawView.
|
||||
|
||||
The SLE's key must not already exist.
|
||||
|
||||
Effects:
|
||||
|
||||
The key in the state map is associated
|
||||
with the SLE.
|
||||
|
||||
The RawView acquires ownership of the shared_ptr.
|
||||
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
insert(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Indicate changes to a peeked SLE
|
||||
|
||||
Requirements:
|
||||
|
||||
The SLE's key must exist.
|
||||
|
||||
`sle` was obtained from prior call to peek()
|
||||
on this instance of the RawView.
|
||||
|
||||
Effects:
|
||||
|
||||
The SLE is updated
|
||||
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
/** @{ */
|
||||
virtual void
|
||||
update(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Called when a credit is made to an account
|
||||
// This is required to support PaymentSandbox
|
||||
virtual void
|
||||
creditHook(
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& amount,
|
||||
STAmount const& preCreditBalance)
|
||||
{
|
||||
}
|
||||
|
||||
// Called when the owner count changes
|
||||
// This is required to support PaymentSandbox
|
||||
virtual void
|
||||
adjustOwnerCountHook(
|
||||
AccountID const& account,
|
||||
std::uint32_t cur,
|
||||
std::uint32_t next)
|
||||
{
|
||||
}
|
||||
|
||||
/** Append an entry to a directory
|
||||
|
||||
Entries in the directory will be stored in order of insertion, i.e. new
|
||||
entries will always be added at the tail end of the last page.
|
||||
|
||||
@param directory the base of the directory
|
||||
@param key the entry to insert
|
||||
@param describe callback to add required entries to a new page
|
||||
|
||||
@return a \c std::optional which, if insertion was successful,
|
||||
will contain the page number in which the item was stored.
|
||||
|
||||
@note this function may create a page (including a root page), if no
|
||||
page with space is available. This function will only fail if the
|
||||
page counter exceeds the protocol-defined maximum number of
|
||||
allowable pages.
|
||||
*/
|
||||
/** @{ */
|
||||
std::optional<std::uint64_t>
|
||||
dirAppend(
|
||||
Keylet const& directory,
|
||||
Keylet const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
if (key.type != ltOFFER)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::ApplyView::dirAppend : only Offers are appended to "
|
||||
"book directories");
|
||||
// Only Offers are appended to book directories. Call dirInsert()
|
||||
// instead
|
||||
return std::nullopt;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
return dirAdd(true, directory, key.key, describe);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Insert an entry to a directory
|
||||
|
||||
Entries in the directory will be stored in a semi-random order, but
|
||||
each page will be maintained in sorted order.
|
||||
|
||||
@param directory the base of the directory
|
||||
@param key the entry to insert
|
||||
@param describe callback to add required entries to a new page
|
||||
|
||||
@return a \c std::optional which, if insertion was successful,
|
||||
will contain the page number in which the item was stored.
|
||||
|
||||
@note this function may create a page (including a root page), if no
|
||||
page with space is available.this function will only fail if the
|
||||
page counter exceeds the protocol-defined maximum number of
|
||||
allowable pages.
|
||||
*/
|
||||
/** @{ */
|
||||
std::optional<std::uint64_t>
|
||||
dirInsert(
|
||||
Keylet const& directory,
|
||||
uint256 const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
return dirAdd(false, directory, key, describe);
|
||||
}
|
||||
|
||||
std::optional<std::uint64_t>
|
||||
dirInsert(
|
||||
Keylet const& directory,
|
||||
Keylet const& key,
|
||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
||||
{
|
||||
return dirAdd(false, directory, key.key, describe);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Remove an entry from a directory
|
||||
|
||||
@param directory the base of the directory
|
||||
@param page the page number for this page
|
||||
@param key the entry to remove
|
||||
@param keepRoot if deleting the last entry, don't
|
||||
delete the root page (i.e. the directory itself).
|
||||
|
||||
@return \c true if the entry was found and deleted and
|
||||
\c false otherwise.
|
||||
|
||||
@note This function will remove zero or more pages from the directory;
|
||||
the root page will not be deleted even if it is empty, unless
|
||||
\p keepRoot is not set and the directory is empty.
|
||||
*/
|
||||
/** @{ */
|
||||
bool
|
||||
dirRemove(
|
||||
Keylet const& directory,
|
||||
std::uint64_t page,
|
||||
uint256 const& key,
|
||||
bool keepRoot);
|
||||
|
||||
bool
|
||||
dirRemove(
|
||||
Keylet const& directory,
|
||||
std::uint64_t page,
|
||||
Keylet const& key,
|
||||
bool keepRoot)
|
||||
{
|
||||
return dirRemove(directory, page, key.key, keepRoot);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/** Remove the specified directory, invoking the callback for every node. */
|
||||
bool
|
||||
dirDelete(
|
||||
Keylet const& directory,
|
||||
std::function<void(uint256 const&)> const&);
|
||||
|
||||
/** Remove the specified directory, if it is empty.
|
||||
|
||||
@param directory the identifier of the directory node to be deleted
|
||||
@return \c true if the directory was found and was successfully deleted
|
||||
\c false otherwise.
|
||||
|
||||
@note The function should only be called with the root entry (i.e. with
|
||||
the first page) of a directory.
|
||||
*/
|
||||
bool
|
||||
emptyDirDelete(Keylet const& directory);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
99
include/xrpl/ledger/ApplyViewImpl.h
Normal file
99
include/xrpl/ledger/ApplyViewImpl.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_APPLYVIEWIMPL_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_APPLYVIEWIMPL_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/OpenView.h>
|
||||
#include <xrpl/ledger/detail/ApplyViewBase.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Editable, discardable view that can build metadata for one tx.
|
||||
|
||||
Iteration of the tx map is delegated to the base.
|
||||
|
||||
@note Presented as ApplyView to clients.
|
||||
*/
|
||||
class ApplyViewImpl final : public detail::ApplyViewBase
|
||||
{
|
||||
public:
|
||||
ApplyViewImpl() = delete;
|
||||
ApplyViewImpl(ApplyViewImpl const&) = delete;
|
||||
ApplyViewImpl&
|
||||
operator=(ApplyViewImpl&&) = delete;
|
||||
ApplyViewImpl&
|
||||
operator=(ApplyViewImpl const&) = delete;
|
||||
|
||||
ApplyViewImpl(ApplyViewImpl&&) = default;
|
||||
ApplyViewImpl(ReadView const* base, ApplyFlags flags);
|
||||
|
||||
/** Apply the transaction.
|
||||
|
||||
After a call to `apply`, the only valid
|
||||
operation on this object is to call the
|
||||
destructor.
|
||||
*/
|
||||
std::optional<TxMeta>
|
||||
apply(
|
||||
OpenView& to,
|
||||
STTx const& tx,
|
||||
TER ter,
|
||||
std::optional<uint256> parentBatchId,
|
||||
bool isDryRun,
|
||||
beast::Journal j);
|
||||
|
||||
/** Set the amount of currency delivered.
|
||||
|
||||
This value is used when generating metadata
|
||||
for payments, to set the DeliveredAmount field.
|
||||
If the amount is not specified, the field is
|
||||
excluded from the resulting metadata.
|
||||
*/
|
||||
void
|
||||
deliver(STAmount const& amount)
|
||||
{
|
||||
deliver_ = amount;
|
||||
}
|
||||
|
||||
/** Get the number of modified entries
|
||||
*/
|
||||
std::size_t
|
||||
size();
|
||||
|
||||
/** Visit modified entries
|
||||
*/
|
||||
void
|
||||
visit(
|
||||
OpenView& target,
|
||||
std::function<void(
|
||||
uint256 const& key,
|
||||
bool isDelete,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func);
|
||||
|
||||
private:
|
||||
std::optional<STAmount> deliver_;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
113
include/xrpl/ledger/BookDirs.h
Normal file
113
include/xrpl/ledger/BookDirs.h
Normal file
@@ -0,0 +1,113 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2015 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_BOOK_DIRS_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_BOOK_DIRS_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class BookDirs
|
||||
{
|
||||
private:
|
||||
ReadView const* view_ = nullptr;
|
||||
uint256 const root_;
|
||||
uint256 const next_quality_;
|
||||
uint256 const key_;
|
||||
std::shared_ptr<SLE const> sle_ = nullptr;
|
||||
unsigned int entry_ = 0;
|
||||
uint256 index_;
|
||||
|
||||
public:
|
||||
class const_iterator;
|
||||
using value_type = std::shared_ptr<SLE const>;
|
||||
|
||||
BookDirs(ReadView const&, Book const&);
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
class BookDirs::const_iterator
|
||||
{
|
||||
public:
|
||||
using value_type = BookDirs::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type const&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const;
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return &**this;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator++();
|
||||
|
||||
const_iterator
|
||||
operator++(int);
|
||||
|
||||
private:
|
||||
friend class BookDirs;
|
||||
|
||||
const_iterator(
|
||||
ReadView const& view,
|
||||
uint256 const& root,
|
||||
uint256 const& dir_key)
|
||||
: view_(&view), root_(root), key_(dir_key), cur_key_(dir_key)
|
||||
{
|
||||
}
|
||||
|
||||
ReadView const* view_ = nullptr;
|
||||
uint256 root_;
|
||||
uint256 next_quality_;
|
||||
uint256 key_;
|
||||
uint256 cur_key_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
unsigned int entry_ = 0;
|
||||
uint256 index_;
|
||||
std::optional<value_type> mutable cache_;
|
||||
|
||||
static beast::Journal j_;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
31
include/xrpl/ledger/CachedSLEs.h
Normal file
31
include/xrpl/ledger/CachedSLEs.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_CACHEDSLES_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_CACHEDSLES_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/TaggedCache.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
namespace ripple {
|
||||
using CachedSLEs = TaggedCache<uint256, SLE const>;
|
||||
}
|
||||
|
||||
#endif // RIPPLE_LEDGER_CACHEDSLES_H_INCLUDED
|
||||
188
include/xrpl/ledger/CachedView.h
Normal file
188
include/xrpl/ledger/CachedView.h
Normal file
@@ -0,0 +1,188 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_CACHEDVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_CACHEDVIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/ledger/CachedSLEs.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class CachedViewImpl : public DigestAwareReadView
|
||||
{
|
||||
private:
|
||||
DigestAwareReadView const& base_;
|
||||
CachedSLEs& cache_;
|
||||
std::mutex mutable mutex_;
|
||||
std::unordered_map<key_type, uint256, hardened_hash<>> mutable map_;
|
||||
|
||||
public:
|
||||
CachedViewImpl() = delete;
|
||||
CachedViewImpl(CachedViewImpl const&) = delete;
|
||||
CachedViewImpl&
|
||||
operator=(CachedViewImpl const&) = delete;
|
||||
|
||||
CachedViewImpl(DigestAwareReadView const* base, CachedSLEs& cache)
|
||||
: base_(*base), cache_(cache)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// ReadView
|
||||
//
|
||||
|
||||
bool
|
||||
exists(Keylet const& k) const override;
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
bool
|
||||
open() const override
|
||||
{
|
||||
return base_.open();
|
||||
}
|
||||
|
||||
LedgerInfo const&
|
||||
info() const override
|
||||
{
|
||||
return base_.info();
|
||||
}
|
||||
|
||||
Fees const&
|
||||
fees() const override
|
||||
{
|
||||
return base_.fees();
|
||||
}
|
||||
|
||||
Rules const&
|
||||
rules() const override
|
||||
{
|
||||
return base_.rules();
|
||||
}
|
||||
|
||||
std::optional<key_type>
|
||||
succ(
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last = std::nullopt) const override
|
||||
{
|
||||
return base_.succ(key, last);
|
||||
}
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesBegin() const override
|
||||
{
|
||||
return base_.slesBegin();
|
||||
}
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesEnd() const override
|
||||
{
|
||||
return base_.slesEnd();
|
||||
}
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesUpperBound(uint256 const& key) const override
|
||||
{
|
||||
return base_.slesUpperBound(key);
|
||||
}
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsBegin() const override
|
||||
{
|
||||
return base_.txsBegin();
|
||||
}
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsEnd() const override
|
||||
{
|
||||
return base_.txsEnd();
|
||||
}
|
||||
|
||||
bool
|
||||
txExists(key_type const& key) const override
|
||||
{
|
||||
return base_.txExists(key);
|
||||
}
|
||||
|
||||
tx_type
|
||||
txRead(key_type const& key) const override
|
||||
{
|
||||
return base_.txRead(key);
|
||||
}
|
||||
|
||||
//
|
||||
// DigestAwareReadView
|
||||
//
|
||||
|
||||
std::optional<digest_type>
|
||||
digest(key_type const& key) const override
|
||||
{
|
||||
return base_.digest(key);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/** Wraps a DigestAwareReadView to provide caching.
|
||||
|
||||
@tparam Base A subclass of DigestAwareReadView
|
||||
*/
|
||||
template <class Base>
|
||||
class CachedView : public detail::CachedViewImpl
|
||||
{
|
||||
private:
|
||||
static_assert(std::is_base_of<DigestAwareReadView, Base>::value, "");
|
||||
|
||||
std::shared_ptr<Base const> sp_;
|
||||
|
||||
public:
|
||||
using base_type = Base;
|
||||
|
||||
CachedView() = delete;
|
||||
CachedView(CachedView const&) = delete;
|
||||
CachedView&
|
||||
operator=(CachedView const&) = delete;
|
||||
|
||||
CachedView(std::shared_ptr<Base const> const& base, CachedSLEs& cache)
|
||||
: CachedViewImpl(base.get(), cache), sp_(base)
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns the base type.
|
||||
|
||||
@note This breaks encapsulation and bypasses the cache.
|
||||
*/
|
||||
std::shared_ptr<Base const> const&
|
||||
base() const
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
117
include/xrpl/ledger/CredentialHelpers.h
Normal file
117
include/xrpl/ledger/CredentialHelpers.h
Normal file
@@ -0,0 +1,117 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2024 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_MISC_CREDENTIALHELPERS_H_INCLUDED
|
||||
#define RIPPLE_APP_MISC_CREDENTIALHELPERS_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace credentials {
|
||||
|
||||
// These function will be used by the code that use DepositPreauth / Credentials
|
||||
// (and any future preauthorization modes) as part of authorization (all the
|
||||
// transfer funds transactions)
|
||||
|
||||
// Check if credential sfExpiration field has passed ledger's parentCloseTime
|
||||
bool
|
||||
checkExpired(
|
||||
std::shared_ptr<SLE const> const& sleCredential,
|
||||
NetClock::time_point const& closed);
|
||||
|
||||
// Return true if any expired credential was found in arr (and deleted)
|
||||
bool
|
||||
removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j);
|
||||
|
||||
// Actually remove a credentials object from the ledger
|
||||
TER
|
||||
deleteSLE(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleCredential,
|
||||
beast::Journal j);
|
||||
|
||||
// Amendment and parameters checks for sfCredentialIDs field
|
||||
NotTEC
|
||||
checkFields(STTx const& tx, beast::Journal j);
|
||||
|
||||
// Accessing the ledger to check if provided credentials are valid. Do not use
|
||||
// in doApply (only in preclaim) since it does not remove expired credentials.
|
||||
// If you call it in prelaim, you also must call verifyDepositPreauth in doApply
|
||||
TER
|
||||
valid(
|
||||
STTx const& tx,
|
||||
ReadView const& view,
|
||||
AccountID const& src,
|
||||
beast::Journal j);
|
||||
|
||||
// Check if subject has any credential maching the given domain. If you call it
|
||||
// in preclaim and it returns tecEXPIRED, you should call verifyValidDomain in
|
||||
// doApply. This will ensure that expired credentials are deleted.
|
||||
TER
|
||||
validDomain(ReadView const& view, uint256 domainID, AccountID const& subject);
|
||||
|
||||
// This function is only called when we about to return tecNO_PERMISSION
|
||||
// because all the checks for the DepositPreauth authorization failed.
|
||||
TER
|
||||
authorizedDepositPreauth(
|
||||
ApplyView const& view,
|
||||
STVector256 const& ctx,
|
||||
AccountID const& dst);
|
||||
|
||||
// Sort credentials array, return empty set if there are duplicates
|
||||
std::set<std::pair<AccountID, Slice>>
|
||||
makeSorted(STArray const& credentials);
|
||||
|
||||
// Check credentials array passed to DepositPreauth/PermissionedDomainSet
|
||||
// transactions
|
||||
NotTEC
|
||||
checkArray(STArray const& credentials, unsigned maxSize, beast::Journal j);
|
||||
|
||||
} // namespace credentials
|
||||
|
||||
// Check expired credentials and for credentials maching DomainID of the ledger
|
||||
// object
|
||||
TER
|
||||
verifyValidDomain(
|
||||
ApplyView& view,
|
||||
AccountID const& account,
|
||||
uint256 domainID,
|
||||
beast::Journal j);
|
||||
|
||||
// Check expired credentials and for existing DepositPreauth ledger object
|
||||
TER
|
||||
verifyDepositPreauth(
|
||||
STTx const& tx,
|
||||
ApplyView& view,
|
||||
AccountID const& src,
|
||||
AccountID const& dst,
|
||||
std::shared_ptr<SLE> const& sleDst,
|
||||
beast::Journal j);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
132
include/xrpl/ledger/Dir.h
Normal file
132
include/xrpl/ledger/Dir.h
Normal file
@@ -0,0 +1,132 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2015 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_DIR_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_DIR_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** A class that simplifies iterating ledger directory pages
|
||||
|
||||
The Dir class provides a forward iterator for walking through
|
||||
the uint256 values contained in ledger directories.
|
||||
|
||||
The Dir class also allows accelerated directory walking by
|
||||
stepping directly from one page to the next using the next_page()
|
||||
member function.
|
||||
|
||||
As of July 2024, the Dir class is only being used with NFTokenOffer
|
||||
directories and for unit tests.
|
||||
*/
|
||||
class Dir
|
||||
{
|
||||
private:
|
||||
ReadView const* view_ = nullptr;
|
||||
Keylet root_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
STVector256 const* indexes_ = nullptr;
|
||||
|
||||
public:
|
||||
class const_iterator;
|
||||
using value_type = std::shared_ptr<SLE const>;
|
||||
|
||||
Dir(ReadView const&, Keylet const&);
|
||||
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
const_iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
class Dir::const_iterator
|
||||
{
|
||||
public:
|
||||
using value_type = Dir::value_type;
|
||||
using pointer = value_type const*;
|
||||
using reference = value_type const&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
bool
|
||||
operator==(const_iterator const& other) const;
|
||||
|
||||
bool
|
||||
operator!=(const_iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return &**this;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator++();
|
||||
|
||||
const_iterator
|
||||
operator++(int);
|
||||
|
||||
const_iterator&
|
||||
next_page();
|
||||
|
||||
std::size_t
|
||||
page_size();
|
||||
|
||||
Keylet const&
|
||||
page() const
|
||||
{
|
||||
return page_;
|
||||
}
|
||||
|
||||
uint256
|
||||
index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class Dir;
|
||||
|
||||
const_iterator(ReadView const& view, Keylet const& root, Keylet const& page)
|
||||
: view_(&view), root_(root), page_(page)
|
||||
{
|
||||
}
|
||||
|
||||
ReadView const* view_ = nullptr;
|
||||
Keylet root_;
|
||||
Keylet page_;
|
||||
uint256 index_;
|
||||
std::optional<value_type> mutable cache_;
|
||||
std::shared_ptr<SLE const> sle_;
|
||||
STVector256 const* indexes_ = nullptr;
|
||||
std::vector<uint256>::const_iterator it_;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
276
include/xrpl/ledger/OpenView.h
Normal file
276
include/xrpl/ledger/OpenView.h
Normal file
@@ -0,0 +1,276 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_OPENVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_OPENVIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/detail/RawStateTable.h>
|
||||
#include <xrpl/protocol/STArray.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Open ledger construction tag.
|
||||
|
||||
Views constructed with this tag will have the
|
||||
rules of open ledgers applied during transaction
|
||||
processing.
|
||||
*/
|
||||
inline constexpr struct open_ledger_t
|
||||
{
|
||||
explicit constexpr open_ledger_t() = default;
|
||||
} open_ledger{};
|
||||
|
||||
/** Batch view construction tag.
|
||||
|
||||
Views constructed with this tag are part of a stack of views
|
||||
used during batch transaction applied.
|
||||
*/
|
||||
inline constexpr struct batch_view_t
|
||||
{
|
||||
explicit constexpr batch_view_t() = default;
|
||||
} batch_view{};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Writable ledger view that accumulates state and tx changes.
|
||||
|
||||
@note Presented as ReadView to clients.
|
||||
*/
|
||||
class OpenView final : public ReadView, public TxsRawView
|
||||
{
|
||||
private:
|
||||
// Initial size for the monotonic_buffer_resource used for allocations
|
||||
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||
// It is unclear how the size initially chosen in qalloc.
|
||||
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||
|
||||
class txs_iter_impl;
|
||||
|
||||
struct txData
|
||||
{
|
||||
std::shared_ptr<Serializer const> txn;
|
||||
std::shared_ptr<Serializer const> meta;
|
||||
|
||||
// Constructor needed for emplacement in std::map
|
||||
txData(
|
||||
std::shared_ptr<Serializer const> const& txn_,
|
||||
std::shared_ptr<Serializer const> const& meta_)
|
||||
: txn(txn_), meta(meta_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// List of tx, key order
|
||||
// Use boost::pmr functionality instead of std::pmr
|
||||
// functions b/c clang does not support pmr yet (as-of 9/2020)
|
||||
using txs_map = std::map<
|
||||
key_type,
|
||||
txData,
|
||||
std::less<key_type>,
|
||||
boost::container::pmr::polymorphic_allocator<
|
||||
std::pair<key_type const, txData>>>;
|
||||
|
||||
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||
// easily moved.
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource>
|
||||
monotonic_resource_;
|
||||
txs_map txs_;
|
||||
Rules rules_;
|
||||
LedgerInfo info_;
|
||||
ReadView const* base_;
|
||||
detail::RawStateTable items_;
|
||||
std::shared_ptr<void const> hold_;
|
||||
|
||||
/// In batch mode, the number of transactions already executed.
|
||||
std::size_t baseTxCount_ = 0;
|
||||
|
||||
bool open_ = true;
|
||||
|
||||
public:
|
||||
OpenView() = delete;
|
||||
OpenView&
|
||||
operator=(OpenView&&) = delete;
|
||||
OpenView&
|
||||
operator=(OpenView const&) = delete;
|
||||
|
||||
OpenView(OpenView&&) = default;
|
||||
|
||||
/** Construct a shallow copy.
|
||||
|
||||
Effects:
|
||||
|
||||
Creates a new object with a copy of
|
||||
the modification state table.
|
||||
|
||||
The objects managed by shared pointers are
|
||||
not duplicated but shared between instances.
|
||||
Since the SLEs are immutable, calls on the
|
||||
RawView interface cannot break invariants.
|
||||
*/
|
||||
OpenView(OpenView const&);
|
||||
|
||||
/** Construct an open ledger view.
|
||||
|
||||
Effects:
|
||||
|
||||
The sequence number is set to the
|
||||
sequence number of parent plus one.
|
||||
|
||||
The parentCloseTime is set to the
|
||||
closeTime of parent.
|
||||
|
||||
If `hold` is not nullptr, retains
|
||||
ownership of a copy of `hold` until
|
||||
the MetaView is destroyed.
|
||||
|
||||
Calls to rules() will return the
|
||||
rules provided on construction.
|
||||
|
||||
The tx list starts empty and will contain
|
||||
all newly inserted tx.
|
||||
*/
|
||||
OpenView(
|
||||
open_ledger_t,
|
||||
ReadView const* base,
|
||||
Rules const& rules,
|
||||
std::shared_ptr<void const> hold = nullptr);
|
||||
|
||||
OpenView(
|
||||
open_ledger_t,
|
||||
Rules const& rules,
|
||||
std::shared_ptr<ReadView const> const& base)
|
||||
: OpenView(open_ledger, &*base, rules, base)
|
||||
{
|
||||
}
|
||||
|
||||
OpenView(batch_view_t, OpenView& base) : OpenView(std::addressof(base))
|
||||
{
|
||||
baseTxCount_ = base.txCount();
|
||||
}
|
||||
|
||||
/** Construct a new last closed ledger.
|
||||
|
||||
Effects:
|
||||
|
||||
The LedgerInfo is copied from the base.
|
||||
|
||||
The rules are inherited from the base.
|
||||
|
||||
The tx list starts empty and will contain
|
||||
all newly inserted tx.
|
||||
*/
|
||||
OpenView(ReadView const* base, std::shared_ptr<void const> hold = nullptr);
|
||||
|
||||
/** Returns true if this reflects an open ledger. */
|
||||
bool
|
||||
open() const override
|
||||
{
|
||||
return open_;
|
||||
}
|
||||
|
||||
/** Return the number of tx inserted since creation.
|
||||
|
||||
This is used to set the "apply ordinal"
|
||||
when calculating transaction metadata.
|
||||
*/
|
||||
std::size_t
|
||||
txCount() const;
|
||||
|
||||
/** Apply changes. */
|
||||
void
|
||||
apply(TxsRawView& to) const;
|
||||
|
||||
// ReadView
|
||||
|
||||
LedgerInfo const&
|
||||
info() const override;
|
||||
|
||||
Fees const&
|
||||
fees() const override;
|
||||
|
||||
Rules const&
|
||||
rules() const override;
|
||||
|
||||
bool
|
||||
exists(Keylet const& k) const override;
|
||||
|
||||
std::optional<key_type>
|
||||
succ(
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last = std::nullopt) const override;
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesBegin() const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesEnd() const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesUpperBound(uint256 const& key) const override;
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsBegin() const override;
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsEnd() const override;
|
||||
|
||||
bool
|
||||
txExists(key_type const& key) const override;
|
||||
|
||||
tx_type
|
||||
txRead(key_type const& key) const override;
|
||||
|
||||
// RawView
|
||||
|
||||
void
|
||||
rawErase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawDestroyXRP(XRPAmount const& fee) override;
|
||||
|
||||
// TxsRawView
|
||||
|
||||
void
|
||||
rawTxInsert(
|
||||
key_type const& key,
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData) override;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
212
include/xrpl/ledger/PaymentSandbox.h
Normal file
212
include/xrpl/ledger/PaymentSandbox.h
Normal file
@@ -0,0 +1,212 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_PAYMENTSANDBOX_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_PAYMENTSANDBOX_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/detail/ApplyViewBase.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// VFALCO TODO Inline this implementation
|
||||
// into the PaymentSandbox class itself
|
||||
class DeferredCredits
|
||||
{
|
||||
public:
|
||||
struct Adjustment
|
||||
{
|
||||
Adjustment(STAmount const& d, STAmount const& c, STAmount const& b)
|
||||
: debits(d), credits(c), origBalance(b)
|
||||
{
|
||||
}
|
||||
STAmount debits;
|
||||
STAmount credits;
|
||||
STAmount origBalance;
|
||||
};
|
||||
|
||||
// Get the adjustments for the balance between main and other.
|
||||
// Returns the debits, credits and the original balance
|
||||
std::optional<Adjustment>
|
||||
adjustments(
|
||||
AccountID const& main,
|
||||
AccountID const& other,
|
||||
Currency const& currency) const;
|
||||
|
||||
void
|
||||
credit(
|
||||
AccountID const& sender,
|
||||
AccountID const& receiver,
|
||||
STAmount const& amount,
|
||||
STAmount const& preCreditSenderBalance);
|
||||
|
||||
void
|
||||
ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next);
|
||||
|
||||
// Get the adjusted owner count. Since DeferredCredits is meant to be used
|
||||
// in payments, and payments only decrease owner counts, return the max
|
||||
// remembered owner count.
|
||||
std::optional<std::uint32_t>
|
||||
ownerCount(AccountID const& id) const;
|
||||
|
||||
void
|
||||
apply(DeferredCredits& to);
|
||||
|
||||
private:
|
||||
// lowAccount, highAccount
|
||||
using Key = std::tuple<AccountID, AccountID, Currency>;
|
||||
struct Value
|
||||
{
|
||||
explicit Value() = default;
|
||||
|
||||
STAmount lowAcctCredits;
|
||||
STAmount highAcctCredits;
|
||||
STAmount lowAcctOrigBalance;
|
||||
};
|
||||
|
||||
static Key
|
||||
makeKey(AccountID const& a1, AccountID const& a2, Currency const& c);
|
||||
|
||||
std::map<Key, Value> credits_;
|
||||
std::map<AccountID, std::uint32_t> ownerCounts_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A wrapper which makes credits unavailable to balances.
|
||||
|
||||
This is used for payments and pathfinding, so that consuming
|
||||
liquidity from a path never causes portions of that path or
|
||||
other paths to gain liquidity.
|
||||
|
||||
The behavior of certain free functions in the ApplyView API
|
||||
will change via the balanceHook and creditHook overrides
|
||||
of PaymentSandbox.
|
||||
|
||||
@note Presented as ApplyView to clients
|
||||
*/
|
||||
class PaymentSandbox final : public detail::ApplyViewBase
|
||||
{
|
||||
public:
|
||||
PaymentSandbox() = delete;
|
||||
PaymentSandbox(PaymentSandbox const&) = delete;
|
||||
PaymentSandbox&
|
||||
operator=(PaymentSandbox&&) = delete;
|
||||
PaymentSandbox&
|
||||
operator=(PaymentSandbox const&) = delete;
|
||||
|
||||
PaymentSandbox(PaymentSandbox&&) = default;
|
||||
|
||||
PaymentSandbox(ReadView const* base, ApplyFlags flags)
|
||||
: ApplyViewBase(base, flags)
|
||||
{
|
||||
}
|
||||
|
||||
PaymentSandbox(ApplyView const* base) : ApplyViewBase(base, base->flags())
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct on top of existing PaymentSandbox.
|
||||
|
||||
The changes are pushed to the parent when
|
||||
apply() is called.
|
||||
|
||||
@param parent A non-null pointer to the parent.
|
||||
|
||||
@note A pointer is used to prevent confusion
|
||||
with copy construction.
|
||||
*/
|
||||
// VFALCO If we are constructing on top of a PaymentSandbox,
|
||||
// or a PaymentSandbox-derived class, we MUST go through
|
||||
// one of these constructors or invariants will be broken.
|
||||
/** @{ */
|
||||
explicit PaymentSandbox(PaymentSandbox const* base)
|
||||
: ApplyViewBase(base, base->flags()), ps_(base)
|
||||
{
|
||||
}
|
||||
|
||||
explicit PaymentSandbox(PaymentSandbox* base)
|
||||
: ApplyViewBase(base, base->flags()), ps_(base)
|
||||
{
|
||||
}
|
||||
/** @} */
|
||||
|
||||
STAmount
|
||||
balanceHook(
|
||||
AccountID const& account,
|
||||
AccountID const& issuer,
|
||||
STAmount const& amount) const override;
|
||||
|
||||
void
|
||||
creditHook(
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& amount,
|
||||
STAmount const& preCreditBalance) override;
|
||||
|
||||
void
|
||||
adjustOwnerCountHook(
|
||||
AccountID const& account,
|
||||
std::uint32_t cur,
|
||||
std::uint32_t next) override;
|
||||
|
||||
std::uint32_t
|
||||
ownerCountHook(AccountID const& account, std::uint32_t count)
|
||||
const override;
|
||||
|
||||
/** Apply changes to base view.
|
||||
|
||||
`to` must contain contents identical to the parent
|
||||
view passed upon construction, else undefined
|
||||
behavior will result.
|
||||
*/
|
||||
/** @{ */
|
||||
void
|
||||
apply(RawView& to);
|
||||
|
||||
void
|
||||
apply(PaymentSandbox& to);
|
||||
/** @} */
|
||||
|
||||
// Return a map of balance changes on trust lines. The low account is the
|
||||
// first account in the key. If the two accounts are equal, the map contains
|
||||
// the total changes in currency regardless of issuer. This is useful to get
|
||||
// the total change in XRP balances.
|
||||
std::map<std::tuple<AccountID, AccountID, Currency>, STAmount>
|
||||
balanceChanges(ReadView const& view) const;
|
||||
|
||||
XRPAmount
|
||||
xrpDestroyed() const;
|
||||
|
||||
private:
|
||||
detail::DeferredCredits tab_;
|
||||
PaymentSandbox const* ps_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
111
include/xrpl/ledger/RawView.h
Normal file
111
include/xrpl/ledger/RawView.h
Normal file
@@ -0,0 +1,111 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_RAWVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_RAWVIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Interface for ledger entry changes.
|
||||
|
||||
Subclasses allow raw modification of ledger entries.
|
||||
*/
|
||||
class RawView
|
||||
{
|
||||
public:
|
||||
virtual ~RawView() = default;
|
||||
RawView() = default;
|
||||
RawView(RawView const&) = default;
|
||||
RawView&
|
||||
operator=(RawView const&) = delete;
|
||||
|
||||
/** Delete an existing state item.
|
||||
|
||||
The SLE is provided so the implementation
|
||||
can calculate metadata.
|
||||
*/
|
||||
virtual void
|
||||
rawErase(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Unconditionally insert a state item.
|
||||
|
||||
Requirements:
|
||||
The key must not already exist.
|
||||
|
||||
Effects:
|
||||
|
||||
The key is associated with the SLE.
|
||||
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Unconditionally replace a state item.
|
||||
|
||||
Requirements:
|
||||
|
||||
The key must exist.
|
||||
|
||||
Effects:
|
||||
|
||||
The key is associated with the SLE.
|
||||
|
||||
@note The key is taken from the SLE
|
||||
*/
|
||||
virtual void
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) = 0;
|
||||
|
||||
/** Destroy XRP.
|
||||
|
||||
This is used to pay for transaction fees.
|
||||
*/
|
||||
virtual void
|
||||
rawDestroyXRP(XRPAmount const& fee) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Interface for changing ledger entries with transactions.
|
||||
|
||||
Allows raw modification of ledger entries and insertion
|
||||
of transactions into the transaction map.
|
||||
*/
|
||||
class TxsRawView : public RawView
|
||||
{
|
||||
public:
|
||||
/** Add a transaction to the tx map.
|
||||
|
||||
Closed ledgers must have metadata,
|
||||
while open ledgers omit metadata.
|
||||
*/
|
||||
virtual void
|
||||
rawTxInsert(
|
||||
ReadView::key_type const& key,
|
||||
std::shared_ptr<Serializer const> const& txn,
|
||||
std::shared_ptr<Serializer const> const& metaData) = 0;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
284
include/xrpl/ledger/ReadView.h
Normal file
284
include/xrpl/ledger/ReadView.h
Normal file
@@ -0,0 +1,284 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_READVIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_READVIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/ledger/detail/ReadViewFwdRange.h>
|
||||
#include <xrpl/protocol/Fees.h>
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A view into a ledger.
|
||||
|
||||
This interface provides read access to state
|
||||
and transaction items. There is no checkpointing
|
||||
or calculation of metadata.
|
||||
*/
|
||||
class ReadView
|
||||
{
|
||||
public:
|
||||
using tx_type =
|
||||
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>;
|
||||
|
||||
using key_type = uint256;
|
||||
|
||||
using mapped_type = std::shared_ptr<SLE const>;
|
||||
|
||||
struct sles_type : detail::ReadViewFwdRange<std::shared_ptr<SLE const>>
|
||||
{
|
||||
explicit sles_type(ReadView const& view);
|
||||
iterator
|
||||
begin() const;
|
||||
iterator
|
||||
end() const;
|
||||
iterator
|
||||
upper_bound(key_type const& key) const;
|
||||
};
|
||||
|
||||
struct txs_type : detail::ReadViewFwdRange<tx_type>
|
||||
{
|
||||
explicit txs_type(ReadView const& view);
|
||||
bool
|
||||
empty() const;
|
||||
iterator
|
||||
begin() const;
|
||||
iterator
|
||||
end() const;
|
||||
};
|
||||
|
||||
virtual ~ReadView() = default;
|
||||
|
||||
ReadView&
|
||||
operator=(ReadView&& other) = delete;
|
||||
ReadView&
|
||||
operator=(ReadView const& other) = delete;
|
||||
|
||||
ReadView() : sles(*this), txs(*this)
|
||||
{
|
||||
}
|
||||
|
||||
ReadView(ReadView const& other) : sles(*this), txs(*this)
|
||||
{
|
||||
}
|
||||
|
||||
ReadView(ReadView&& other) : sles(*this), txs(*this)
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns information about the ledger. */
|
||||
virtual LedgerInfo const&
|
||||
info() const = 0;
|
||||
|
||||
/** Returns true if this reflects an open ledger. */
|
||||
virtual bool
|
||||
open() const = 0;
|
||||
|
||||
/** Returns the close time of the previous ledger. */
|
||||
NetClock::time_point
|
||||
parentCloseTime() const
|
||||
{
|
||||
return info().parentCloseTime;
|
||||
}
|
||||
|
||||
/** Returns the sequence number of the base ledger. */
|
||||
LedgerIndex
|
||||
seq() const
|
||||
{
|
||||
return info().seq;
|
||||
}
|
||||
|
||||
/** Returns the fees for the base ledger. */
|
||||
virtual Fees const&
|
||||
fees() const = 0;
|
||||
|
||||
/** Returns the tx processing rules. */
|
||||
virtual Rules const&
|
||||
rules() const = 0;
|
||||
|
||||
/** Determine if a state item exists.
|
||||
|
||||
@note This can be more efficient than calling read.
|
||||
|
||||
@return `true` if a SLE is associated with the
|
||||
specified key.
|
||||
*/
|
||||
virtual bool
|
||||
exists(Keylet const& k) const = 0;
|
||||
|
||||
/** Return the key of the next state item.
|
||||
|
||||
This returns the key of the first state item
|
||||
whose key is greater than the specified key. If
|
||||
no such key is present, std::nullopt is returned.
|
||||
|
||||
If `last` is engaged, returns std::nullopt when
|
||||
the key returned would be outside the open
|
||||
interval (key, last).
|
||||
*/
|
||||
virtual std::optional<key_type>
|
||||
succ(
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last = std::nullopt) const = 0;
|
||||
|
||||
/** Return the state item associated with a key.
|
||||
|
||||
Effects:
|
||||
If the key exists, gives the caller ownership
|
||||
of the non-modifiable corresponding SLE.
|
||||
|
||||
@note While the returned SLE is `const` from the
|
||||
perspective of the caller, it can be changed
|
||||
by other callers through raw operations.
|
||||
|
||||
@return `nullptr` if the key is not present or
|
||||
if the type does not match.
|
||||
*/
|
||||
virtual std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const = 0;
|
||||
|
||||
// Accounts in a payment are not allowed to use assets acquired during that
|
||||
// payment. The PaymentSandbox tracks the debits, credits, and owner count
|
||||
// changes that accounts make during a payment. `balanceHook` adjusts
|
||||
// balances so newly acquired assets are not counted toward the balance.
|
||||
// This is required to support PaymentSandbox.
|
||||
virtual STAmount
|
||||
balanceHook(
|
||||
AccountID const& account,
|
||||
AccountID const& issuer,
|
||||
STAmount const& amount) const
|
||||
{
|
||||
return amount;
|
||||
}
|
||||
|
||||
// Accounts in a payment are not allowed to use assets acquired during that
|
||||
// payment. The PaymentSandbox tracks the debits, credits, and owner count
|
||||
// changes that accounts make during a payment. `ownerCountHook` adjusts the
|
||||
// ownerCount so it returns the max value of the ownerCount so far.
|
||||
// This is required to support PaymentSandbox.
|
||||
virtual std::uint32_t
|
||||
ownerCountHook(AccountID const& account, std::uint32_t count) const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
// used by the implementation
|
||||
virtual std::unique_ptr<sles_type::iter_base>
|
||||
slesBegin() const = 0;
|
||||
|
||||
// used by the implementation
|
||||
virtual std::unique_ptr<sles_type::iter_base>
|
||||
slesEnd() const = 0;
|
||||
|
||||
// used by the implementation
|
||||
virtual std::unique_ptr<sles_type::iter_base>
|
||||
slesUpperBound(key_type const& key) const = 0;
|
||||
|
||||
// used by the implementation
|
||||
virtual std::unique_ptr<txs_type::iter_base>
|
||||
txsBegin() const = 0;
|
||||
|
||||
// used by the implementation
|
||||
virtual std::unique_ptr<txs_type::iter_base>
|
||||
txsEnd() const = 0;
|
||||
|
||||
/** Returns `true` if a tx exists in the tx map.
|
||||
|
||||
A tx exists in the map if it is part of the
|
||||
base ledger, or if it is a newly inserted tx.
|
||||
*/
|
||||
virtual bool
|
||||
txExists(key_type const& key) const = 0;
|
||||
|
||||
/** Read a transaction from the tx map.
|
||||
|
||||
If the view represents an open ledger,
|
||||
the metadata object will be empty.
|
||||
|
||||
@return A pair of nullptr if the
|
||||
key is not found in the tx map.
|
||||
*/
|
||||
virtual tx_type
|
||||
txRead(key_type const& key) const = 0;
|
||||
|
||||
//
|
||||
// Memberspaces
|
||||
//
|
||||
|
||||
/** Iterable range of ledger state items.
|
||||
|
||||
@note Visiting each state entry in the ledger can
|
||||
become quite expensive as the ledger grows.
|
||||
*/
|
||||
sles_type sles;
|
||||
|
||||
// The range of transactions
|
||||
txs_type txs;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** ReadView that associates keys with digests. */
|
||||
class DigestAwareReadView : public ReadView
|
||||
{
|
||||
public:
|
||||
using digest_type = uint256;
|
||||
|
||||
DigestAwareReadView() = default;
|
||||
DigestAwareReadView(DigestAwareReadView const&) = default;
|
||||
|
||||
/** Return the digest associated with the key.
|
||||
|
||||
@return std::nullopt if the item does not exist.
|
||||
*/
|
||||
virtual std::optional<digest_type>
|
||||
digest(key_type const& key) const = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Rules
|
||||
makeRulesGivenLedger(DigestAwareReadView const& ledger, Rules const& current);
|
||||
|
||||
Rules
|
||||
makeRulesGivenLedger(
|
||||
DigestAwareReadView const& ledger,
|
||||
std::unordered_set<uint256, beast::uhash<>> const& presets);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#include <xrpl/ledger/detail/ReadViewFwdRange.ipp>
|
||||
|
||||
#endif
|
||||
63
include/xrpl/ledger/Sandbox.h
Normal file
63
include/xrpl/ledger/Sandbox.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_SANDBOX_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_SANDBOX_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/detail/ApplyViewBase.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Discardable, editable view to a ledger.
|
||||
|
||||
The sandbox inherits the flags of the base.
|
||||
|
||||
@note Presented as ApplyView to clients.
|
||||
*/
|
||||
class Sandbox : public detail::ApplyViewBase
|
||||
{
|
||||
public:
|
||||
Sandbox() = delete;
|
||||
Sandbox(Sandbox const&) = delete;
|
||||
Sandbox&
|
||||
operator=(Sandbox&&) = delete;
|
||||
Sandbox&
|
||||
operator=(Sandbox const&) = delete;
|
||||
|
||||
Sandbox(Sandbox&&) = default;
|
||||
|
||||
Sandbox(ReadView const* base, ApplyFlags flags) : ApplyViewBase(base, flags)
|
||||
{
|
||||
}
|
||||
|
||||
Sandbox(ApplyView const* base) : Sandbox(base, base->flags())
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
apply(RawView& to)
|
||||
{
|
||||
items_.apply(to);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
982
include/xrpl/ledger/View.h
Normal file
982
include/xrpl/ledger/View.h
Normal file
@@ -0,0 +1,982 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_VIEW_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_VIEW_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/OpenView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/Rate.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STObject.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
enum class WaiveTransferFee : bool { No = false, Yes };
|
||||
enum class SkipEntry : bool { No = false, Yes };
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Determines whether the given expiration time has passed.
|
||||
|
||||
In the XRP Ledger, expiration times are defined as the number of whole
|
||||
seconds after the "Ripple Epoch" which, for historical reasons, is set
|
||||
to January 1, 2000 (00:00 UTC).
|
||||
|
||||
This is like the way the Unix epoch works, except the Ripple Epoch is
|
||||
precisely 946,684,800 seconds after the Unix Epoch.
|
||||
|
||||
See https://xrpl.org/basic-data-types.html#specifying-time
|
||||
|
||||
Expiration is defined in terms of the close time of the parent ledger,
|
||||
because we definitively know the time that it closed (since consensus
|
||||
agrees on time) but we do not know the closing time of the ledger that
|
||||
is under construction.
|
||||
|
||||
@param view The ledger whose parent time is used as the clock.
|
||||
@param exp The optional expiration time we want to check.
|
||||
|
||||
@returns `true` if `exp` is in the past; `false` otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
hasExpired(ReadView const& view, std::optional<std::uint32_t> const& exp);
|
||||
|
||||
/** Controls the treatment of frozen account balances */
|
||||
enum FreezeHandling { fhIGNORE_FREEZE, fhZERO_IF_FROZEN };
|
||||
|
||||
/** Controls the treatment of unauthorized MPT balances */
|
||||
enum AuthHandling { ahIGNORE_AUTH, ahZERO_IF_UNAUTHORIZED };
|
||||
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(ReadView const& view, AccountID const& issuer);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(ReadView const& view, Asset const& asset);
|
||||
|
||||
// Note, depth parameter is used to limit the recursion depth
|
||||
[[nodiscard]] bool
|
||||
isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptShare,
|
||||
int depth);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
AccountID const& issuer);
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isIndividualFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& issue)
|
||||
{
|
||||
return isIndividualFrozen(view, account, issue.currency, issue.account);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue);
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isIndividualFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Asset const& asset)
|
||||
{
|
||||
return std::visit(
|
||||
[&](auto const& issue) {
|
||||
return isIndividualFrozen(view, account, issue);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
AccountID const& issuer);
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& issue,
|
||||
int = 0 /*ignored*/)
|
||||
{
|
||||
return isFrozen(view, account, issue.currency, issue.account);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue,
|
||||
int depth = 0);
|
||||
|
||||
/**
|
||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||
* purely defensive, as we currently do not allow such vaults to be created.
|
||||
*/
|
||||
[[nodiscard]] inline bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Asset const& asset,
|
||||
int depth = 0)
|
||||
{
|
||||
return std::visit(
|
||||
[&](auto const& issue) {
|
||||
return isFrozen(view, account, issue, depth);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, Issue const& issue)
|
||||
{
|
||||
return isFrozen(view, account, issue) ? (TER)tecFROZEN : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
checkFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue)
|
||||
{
|
||||
return isFrozen(view, account, mptIssue) ? (TER)tecLOCKED : (TER)tesSUCCESS;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
checkFrozen(ReadView const& view, AccountID const& account, Asset const& asset)
|
||||
{
|
||||
return std::visit(
|
||||
[&](auto const& issue) { return checkFrozen(view, account, issue); },
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
MPTIssue const& mptIssue,
|
||||
int depth = 0);
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
Issue const& issue)
|
||||
{
|
||||
for (auto const& account : accounts)
|
||||
{
|
||||
if (isFrozen(view, account, issue.currency, issue.account))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
std::initializer_list<AccountID> const& accounts,
|
||||
Asset const& asset,
|
||||
int depth = 0)
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
||||
if constexpr (std::is_same_v<TIss, Issue>)
|
||||
return isAnyFrozen(view, accounts, issue);
|
||||
else
|
||||
return isAnyFrozen(view, accounts, issue, depth);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
AccountID const& issuer);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isLPTokenFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& asset,
|
||||
Issue const& asset2);
|
||||
|
||||
// Returns the amount an account can spend without going into debt.
|
||||
//
|
||||
// <-- saAmount: amount of currency held by account. May be negative.
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Currency const& currency,
|
||||
AccountID const& issuer,
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Issue const& issue,
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptIssue,
|
||||
FreezeHandling zeroIfFrozen,
|
||||
AuthHandling zeroIfUnauthorized,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
Asset const& asset,
|
||||
FreezeHandling zeroIfFrozen,
|
||||
AuthHandling zeroIfUnauthorized,
|
||||
beast::Journal j);
|
||||
|
||||
// Returns the amount an account can spend of the currency type saDefault, or
|
||||
// returns saDefault if this account is the issuer of the currency in
|
||||
// question. Should be used in favor of accountHolds when questioning how much
|
||||
// an account can spend while also allowing currency issuers to spend
|
||||
// unlimited amounts of their own currency (since they can always issue more).
|
||||
[[nodiscard]] STAmount
|
||||
accountFunds(
|
||||
ReadView const& view,
|
||||
AccountID const& id,
|
||||
STAmount const& saDefault,
|
||||
FreezeHandling freezeHandling,
|
||||
beast::Journal j);
|
||||
|
||||
// Return the account's liquid (not reserved) XRP. Generally prefer
|
||||
// calling accountHolds() over this interface. However, this interface
|
||||
// allows the caller to temporarily adjust the owner count should that be
|
||||
// necessary.
|
||||
//
|
||||
// @param ownerCountAdj positive to add to count, negative to reduce count.
|
||||
[[nodiscard]] XRPAmount
|
||||
xrpLiquid(
|
||||
ReadView const& view,
|
||||
AccountID const& id,
|
||||
std::int32_t ownerCountAdj,
|
||||
beast::Journal j);
|
||||
|
||||
/** Iterate all items in the given directory. */
|
||||
void
|
||||
forEachItem(
|
||||
ReadView const& view,
|
||||
Keylet const& root,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f);
|
||||
|
||||
/** Iterate all items after an item in the given directory.
|
||||
@param after The key of the item to start after
|
||||
@param hint The directory page containing `after`
|
||||
@param limit The maximum number of items to return
|
||||
@return `false` if the iteration failed
|
||||
*/
|
||||
bool
|
||||
forEachItemAfter(
|
||||
ReadView const& view,
|
||||
Keylet const& root,
|
||||
uint256 const& after,
|
||||
std::uint64_t const hint,
|
||||
unsigned int limit,
|
||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f);
|
||||
|
||||
/** Iterate all items in an account's owner directory. */
|
||||
inline void
|
||||
forEachItem(
|
||||
ReadView const& view,
|
||||
AccountID const& id,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
return forEachItem(view, keylet::ownerDir(id), f);
|
||||
}
|
||||
|
||||
/** Iterate all items after an item in an owner directory.
|
||||
@param after The key of the item to start after
|
||||
@param hint The directory page containing `after`
|
||||
@param limit The maximum number of items to return
|
||||
@return `false` if the iteration failed
|
||||
*/
|
||||
inline bool
|
||||
forEachItemAfter(
|
||||
ReadView const& view,
|
||||
AccountID const& id,
|
||||
uint256 const& after,
|
||||
std::uint64_t const hint,
|
||||
unsigned int limit,
|
||||
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
|
||||
{
|
||||
return forEachItemAfter(view, keylet::ownerDir(id), after, hint, limit, f);
|
||||
}
|
||||
|
||||
/** Returns IOU issuer transfer fee as Rate. Rate specifies
|
||||
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
||||
* is represented as 1,010,000,000.
|
||||
* @param issuer The IOU issuer
|
||||
*/
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, AccountID const& issuer);
|
||||
|
||||
/** Returns MPT transfer fee as Rate. Rate specifies
|
||||
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
||||
* is represented as 1,010,000,000.
|
||||
* @param issuanceID MPTokenIssuanceID of MPTTokenIssuance object
|
||||
*/
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, MPTID const& issuanceID);
|
||||
|
||||
/** Returns the transfer fee as Rate based on the type of token
|
||||
* @param view The ledger view
|
||||
* @param amount The amount to transfer
|
||||
*/
|
||||
[[nodiscard]] Rate
|
||||
transferRate(ReadView const& view, STAmount const& amount);
|
||||
|
||||
/** Returns `true` if the directory is empty
|
||||
@param key The key of the directory
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
dirIsEmpty(ReadView const& view, Keylet const& k);
|
||||
|
||||
// Return the list of enabled amendments
|
||||
[[nodiscard]] std::set<uint256>
|
||||
getEnabledAmendments(ReadView const& view);
|
||||
|
||||
// Return a map of amendments that have achieved majority
|
||||
using majorityAmendments_t = std::map<uint256, NetClock::time_point>;
|
||||
[[nodiscard]] majorityAmendments_t
|
||||
getMajorityAmendments(ReadView const& view);
|
||||
|
||||
/** Return the hash of a ledger by sequence.
|
||||
The hash is retrieved by looking up the "skip list"
|
||||
in the passed ledger. As the skip list is limited
|
||||
in size, if the requested ledger sequence number is
|
||||
out of the range of ledgers represented in the skip
|
||||
list, then std::nullopt is returned.
|
||||
@return The hash of the ledger with the
|
||||
given sequence number or std::nullopt.
|
||||
*/
|
||||
[[nodiscard]] std::optional<uint256>
|
||||
hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal);
|
||||
|
||||
/** Find a ledger index from which we could easily get the requested ledger
|
||||
|
||||
The index that we return should meet two requirements:
|
||||
1) It must be the index of a ledger that has the hash of the ledger
|
||||
we are looking for. This means that its sequence must be equal to
|
||||
greater than the sequence that we want but not more than 256 greater
|
||||
since each ledger contains the hashes of the 256 previous ledgers.
|
||||
|
||||
2) Its hash must be easy for us to find. This means it must be 0 mod 256
|
||||
because every such ledger is permanently enshrined in a LedgerHashes
|
||||
page which we can easily retrieve via the skip list.
|
||||
*/
|
||||
inline LedgerIndex
|
||||
getCandidateLedger(LedgerIndex requested)
|
||||
{
|
||||
return (requested + 255) & (~255);
|
||||
}
|
||||
|
||||
/** Return false if the test ledger is provably incompatible
|
||||
with the valid ledger, that is, they could not possibly
|
||||
both be valid. Use the first form if you have both ledgers,
|
||||
use the second form if you have not acquired the valid ledger yet
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
areCompatible(
|
||||
ReadView const& validLedger,
|
||||
ReadView const& testLedger,
|
||||
beast::Journal::Stream& s,
|
||||
char const* reason);
|
||||
|
||||
[[nodiscard]] bool
|
||||
areCompatible(
|
||||
uint256 const& validHash,
|
||||
LedgerIndex validIndex,
|
||||
ReadView const& testLedger,
|
||||
beast::Journal::Stream& s,
|
||||
char const* reason);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Adjust the owner count up or down. */
|
||||
void
|
||||
adjustOwnerCount(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sle,
|
||||
std::int32_t amount,
|
||||
beast::Journal j);
|
||||
|
||||
/** @{ */
|
||||
/** Returns the first entry in the directory, advancing the index
|
||||
|
||||
@deprecated These are legacy function that are considered deprecated
|
||||
and will soon be replaced with an iterator-based model
|
||||
that is easier to use. You should not use them in new code.
|
||||
|
||||
@param view The view against which to operate
|
||||
@param root The root (i.e. first page) of the directory to iterate
|
||||
@param page The current page
|
||||
@param index The index inside the current page
|
||||
@param entry The entry at the current index
|
||||
|
||||
@return true if the directory isn't empty; false otherwise
|
||||
*/
|
||||
bool
|
||||
cdirFirst(
|
||||
ReadView const& view,
|
||||
uint256 const& root,
|
||||
std::shared_ptr<SLE const>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
|
||||
bool
|
||||
dirFirst(
|
||||
ApplyView& view,
|
||||
uint256 const& root,
|
||||
std::shared_ptr<SLE>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
/** @} */
|
||||
|
||||
/** @{ */
|
||||
/** Returns the next entry in the directory, advancing the index
|
||||
|
||||
@deprecated These are legacy function that are considered deprecated
|
||||
and will soon be replaced with an iterator-based model
|
||||
that is easier to use. You should not use them in new code.
|
||||
|
||||
@param view The view against which to operate
|
||||
@param root The root (i.e. first page) of the directory to iterate
|
||||
@param page The current page
|
||||
@param index The index inside the current page
|
||||
@param entry The entry at the current index
|
||||
|
||||
@return true if the directory isn't empty; false otherwise
|
||||
*/
|
||||
bool
|
||||
cdirNext(
|
||||
ReadView const& view,
|
||||
uint256 const& root,
|
||||
std::shared_ptr<SLE const>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
|
||||
bool
|
||||
dirNext(
|
||||
ApplyView& view,
|
||||
uint256 const& root,
|
||||
std::shared_ptr<SLE>& page,
|
||||
unsigned int& index,
|
||||
uint256& entry);
|
||||
/** @} */
|
||||
|
||||
[[nodiscard]] std::function<void(SLE::ref)>
|
||||
describeOwnerDir(AccountID const& account);
|
||||
|
||||
[[nodiscard]] TER
|
||||
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);
|
||||
|
||||
AccountID
|
||||
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
||||
|
||||
/**
|
||||
*
|
||||
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
|
||||
*
|
||||
* The list of valid ownerField is maintained in View.cpp and the caller to
|
||||
* this function must perform necessary amendment check(s) before using a
|
||||
* field. The amendment check is **not** performed in createPseudoAccount.
|
||||
*/
|
||||
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
|
||||
createPseudoAccount(
|
||||
ApplyView& view,
|
||||
uint256 const& pseudoOwnerKey,
|
||||
SField const& ownerField);
|
||||
|
||||
// Returns true iff sleAcct is a pseudo-account.
|
||||
//
|
||||
// Returns false if sleAcct is
|
||||
// * NOT a pseudo-account OR
|
||||
// * NOT a ltACCOUNT_ROOT OR
|
||||
// * null pointer
|
||||
[[nodiscard]] bool
|
||||
isPseudoAccount(std::shared_ptr<SLE const> sleAcct);
|
||||
|
||||
// Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account if
|
||||
// set
|
||||
// Pseudo-account designator fields MUST be maintained by including the
|
||||
// SField::sMD_PseudoAccount flag in the SField definition. (Don't forget to
|
||||
// "| SField::sMD_Default"!) The fields do NOT need to be amendment-gated,
|
||||
// since a non-active amendment will not set any field, by definition.
|
||||
// Specific properties of a pseudo-account are NOT checked here, that's what
|
||||
// InvariantCheck is for.
|
||||
[[nodiscard]] std::vector<SField const*> const&
|
||||
getPseudoAccountFields();
|
||||
|
||||
[[nodiscard]] inline bool
|
||||
isPseudoAccount(ReadView const& view, AccountID accountId)
|
||||
{
|
||||
return isPseudoAccount(view.read(keylet::account(accountId)));
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
canAddHolding(ReadView const& view, Asset const& asset);
|
||||
|
||||
/// Any transactors that call addEmptyHolding() in doApply must call
|
||||
/// canAddHolding() in preflight with the same View and Asset
|
||||
[[nodiscard]] TER
|
||||
addEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
XRPAmount priorBalance,
|
||||
Issue const& issue,
|
||||
beast::Journal journal);
|
||||
|
||||
[[nodiscard]] TER
|
||||
addEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
XRPAmount priorBalance,
|
||||
MPTIssue const& mptIssue,
|
||||
beast::Journal journal);
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
addEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
XRPAmount priorBalance,
|
||||
Asset const& asset,
|
||||
beast::Journal journal)
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
||||
return addEmptyHolding(
|
||||
view, accountID, priorBalance, issue, journal);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
authorizeMPToken(
|
||||
ApplyView& view,
|
||||
XRPAmount const& priorBalance,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
beast::Journal journal,
|
||||
std::uint32_t flags = 0,
|
||||
std::optional<AccountID> holderID = std::nullopt);
|
||||
|
||||
// VFALCO NOTE Both STAmount parameters should just
|
||||
// be "Amount", a unit-less number.
|
||||
//
|
||||
/** Create a trust line
|
||||
|
||||
This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
uint256 const& uIndex, // --> ripple state entry
|
||||
SLE::ref sleAccount, // --> the account being set.
|
||||
bool const bAuth, // --> authorize account.
|
||||
bool const bNoRipple, // --> others cannot ripple through
|
||||
bool const bFreeze, // --> funds cannot leave
|
||||
bool bDeepFreeze, // --> can neither receive nor send funds
|
||||
STAmount const& saBalance, // --> balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // --> limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uSrcQualityIn,
|
||||
std::uint32_t uSrcQualityOut,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
removeEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
Issue const& issue,
|
||||
beast::Journal journal);
|
||||
|
||||
[[nodiscard]] TER
|
||||
removeEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
MPTIssue const& mptIssue,
|
||||
beast::Journal journal);
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
removeEmptyHolding(
|
||||
ApplyView& view,
|
||||
AccountID const& accountID,
|
||||
Asset const& asset,
|
||||
beast::Journal journal)
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue) -> TER {
|
||||
return removeEmptyHolding(view, accountID, issue, journal);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
/** Delete an offer.
|
||||
|
||||
Requirements:
|
||||
The passed `sle` be obtained from a prior
|
||||
call to view.peek()
|
||||
*/
|
||||
// [[nodiscard]] // nodiscard commented out so Flow, BookTip and others compile.
|
||||
TER
|
||||
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Money Transfers
|
||||
//
|
||||
|
||||
// Direct send w/o fees:
|
||||
// - Redeeming IOUs and/or sending sender's own IOUs.
|
||||
// - Create trust line of needed.
|
||||
// --> bCheckIssuer : normally require issuer to be involved.
|
||||
// [[nodiscard]] // nodiscard commented out so DirectStep.cpp compiles.
|
||||
|
||||
/** Calls static rippleCreditIOU if saAmount represents Issue.
|
||||
* Calls static rippleCreditMPT if saAmount represents MPTIssue.
|
||||
*/
|
||||
TER
|
||||
rippleCredit(
|
||||
ApplyView& view,
|
||||
AccountID const& uSenderID,
|
||||
AccountID const& uReceiverID,
|
||||
STAmount const& saAmount,
|
||||
bool bCheckIssuer,
|
||||
beast::Journal j);
|
||||
|
||||
TER
|
||||
rippleLockEscrowMPT(
|
||||
ApplyView& view,
|
||||
AccountID const& uGrantorID,
|
||||
STAmount const& saAmount,
|
||||
beast::Journal j);
|
||||
|
||||
TER
|
||||
rippleUnlockEscrowMPT(
|
||||
ApplyView& view,
|
||||
AccountID const& uGrantorID,
|
||||
AccountID const& uGranteeID,
|
||||
STAmount const& netAmount,
|
||||
STAmount const& grossAmount,
|
||||
beast::Journal j);
|
||||
|
||||
/** Calls static accountSendIOU if saAmount represents Issue.
|
||||
* Calls static accountSendMPT if saAmount represents MPTIssue.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
accountSend(
|
||||
ApplyView& view,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& saAmount,
|
||||
beast::Journal j,
|
||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
||||
|
||||
[[nodiscard]] TER
|
||||
issueIOU(
|
||||
ApplyView& view,
|
||||
AccountID const& account,
|
||||
STAmount const& amount,
|
||||
Issue const& issue,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
redeemIOU(
|
||||
ApplyView& view,
|
||||
AccountID const& account,
|
||||
STAmount const& amount,
|
||||
Issue const& issue,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
transferXRP(
|
||||
ApplyView& view,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
STAmount const& amount,
|
||||
beast::Journal j);
|
||||
|
||||
/* Check if MPToken (for MPT) or trust line (for IOU) exists:
|
||||
* - StrongAuth - before checking if authorization is required
|
||||
* - WeakAuth
|
||||
* for MPT - after checking lsfMPTRequireAuth flag
|
||||
* for IOU - do not check if trust line exists
|
||||
* - Legacy
|
||||
* for MPT - before checking lsfMPTRequireAuth flag i.e. same as StrongAuth
|
||||
* for IOU - do not check if trust line exists i.e. same as WeakAuth
|
||||
*/
|
||||
enum class AuthType { StrongAuth, WeakAuth, Legacy };
|
||||
|
||||
/** Check if the account lacks required authorization.
|
||||
*
|
||||
* Return tecNO_AUTH or tecNO_LINE if it does
|
||||
* and tesSUCCESS otherwise.
|
||||
*
|
||||
* If StrongAuth then return tecNO_LINE if the RippleState doesn't exist. Return
|
||||
* tecNO_AUTH if lsfRequireAuth is set on the issuer's AccountRoot, and the
|
||||
* RippleState does exist, and the RippleState is not authorized.
|
||||
*
|
||||
* If WeakAuth then return tecNO_AUTH if lsfRequireAuth is set, and the
|
||||
* RippleState exists, and is not authorized. Return tecNO_LINE if
|
||||
* lsfRequireAuth is set and the RippleState doesn't exist. Consequently, if
|
||||
* WeakAuth and lsfRequireAuth is *not* set, this function will return
|
||||
* tesSUCCESS even if RippleState does *not* exist.
|
||||
*
|
||||
* The default "Legacy" auth type is equivalent to WeakAuth.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
requireAuth(
|
||||
ReadView const& view,
|
||||
Issue const& issue,
|
||||
AccountID const& account,
|
||||
AuthType authType = AuthType::Legacy);
|
||||
|
||||
/** Check if the account lacks required authorization.
|
||||
*
|
||||
* This will also check for expired credentials. If it is called directly
|
||||
* from preclaim, the user should convert result tecEXPIRED to tesSUCCESS and
|
||||
* proceed to also check permissions with enforceMPTokenAuthorization inside
|
||||
* doApply. This will ensure that any expired credentials are deleted.
|
||||
*
|
||||
* requireAuth check is recursive for MPT shares in a vault, descending to
|
||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
||||
* purely defensive, as we currently do not allow such vaults to be created.
|
||||
*
|
||||
* If StrongAuth then return tecNO_AUTH if MPToken doesn't exist or
|
||||
* lsfMPTRequireAuth is set and MPToken is not authorized.
|
||||
*
|
||||
* If WeakAuth then return tecNO_AUTH if lsfMPTRequireAuth is set and MPToken
|
||||
* doesn't exist or is not authorized (explicitly or via credentials, if
|
||||
* DomainID is set in MPTokenIssuance). Consequently, if WeakAuth and
|
||||
* lsfMPTRequireAuth is *not* set, this function will return true even if
|
||||
* MPToken does *not* exist.
|
||||
*
|
||||
* The default "Legacy" auth type is equivalent to StrongAuth.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
requireAuth(
|
||||
ReadView const& view,
|
||||
MPTIssue const& mptIssue,
|
||||
AccountID const& account,
|
||||
AuthType authType = AuthType::Legacy,
|
||||
int depth = 0);
|
||||
|
||||
[[nodiscard]] TER inline requireAuth(
|
||||
ReadView const& view,
|
||||
Asset const& asset,
|
||||
AccountID const& account,
|
||||
AuthType authType = AuthType::Legacy)
|
||||
{
|
||||
return std::visit(
|
||||
[&]<ValidIssueType TIss>(TIss const& issue_) {
|
||||
return requireAuth(view, issue_, account, authType);
|
||||
},
|
||||
asset.value());
|
||||
}
|
||||
|
||||
/** Enforce account has MPToken to match its authorization.
|
||||
*
|
||||
* Called from doApply - it will check for expired (and delete if found any)
|
||||
* credentials matching DomainID set in MPTokenIssuance. Must be called if
|
||||
* requireAuth(...MPTIssue...) returned tesSUCCESS or tecEXPIRED in preclaim,
|
||||
* which implies that preclaim should replace `tecEXPIRED` with `tesSUCCESS`
|
||||
* in order for the transactor to proceed to doApply.
|
||||
*
|
||||
* This function will create MPToken (if needed) on the basis of any
|
||||
* non-expired credentials and will delete any expired credentials, indirectly
|
||||
* via verifyValidDomain, as per DomainID (if set in MPTokenIssuance).
|
||||
*
|
||||
* The caller does NOT need to ensure that DomainID is actually set - this
|
||||
* function handles gracefully both cases when DomainID is set and when not.
|
||||
*
|
||||
* The caller does NOT need to look for existing MPToken to match
|
||||
* mptIssue/account - this function checks lsfMPTAuthorized of an existing
|
||||
* MPToken iff DomainID is not set.
|
||||
*
|
||||
* Do not use for accounts which hold implied permission e.g. object owners or
|
||||
* if MPTokenIssuance does not require authorization. In both cases use
|
||||
* MPTokenAuthorize::authorize if MPToken does not yet exist.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
enforceMPTokenAuthorization(
|
||||
ApplyView& view,
|
||||
MPTID const& mptIssuanceID,
|
||||
AccountID const& account,
|
||||
XRPAmount const& priorBalance,
|
||||
beast::Journal j);
|
||||
|
||||
/** Check if the destination account is allowed
|
||||
* to receive MPT. Return tecNO_AUTH if it doesn't
|
||||
* and tesSUCCESS otherwise.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canTransfer(
|
||||
ReadView const& view,
|
||||
MPTIssue const& mptIssue,
|
||||
AccountID const& from,
|
||||
AccountID const& to);
|
||||
|
||||
/** Deleter function prototype. Returns the status of the entry deletion
|
||||
* (if should not be skipped) and if the entry should be skipped. The status
|
||||
* is always tesSUCCESS if the entry should be skipped.
|
||||
*/
|
||||
using EntryDeleter = std::function<std::pair<TER, SkipEntry>(
|
||||
LedgerEntryType,
|
||||
uint256 const&,
|
||||
std::shared_ptr<SLE>&)>;
|
||||
/** Cleanup owner directory entries on account delete.
|
||||
* Used for a regular and AMM accounts deletion. The caller
|
||||
* has to provide the deleter function, which handles details of
|
||||
* specific account-owned object deletion.
|
||||
* @return tecINCOMPLETE indicates maxNodesToDelete
|
||||
* are deleted and there remains more nodes to delete.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
cleanupOnAccountDelete(
|
||||
ApplyView& view,
|
||||
Keylet const& ownerDirKeylet,
|
||||
EntryDeleter const& deleter,
|
||||
beast::Journal j,
|
||||
std::optional<std::uint16_t> maxNodesToDelete = std::nullopt);
|
||||
|
||||
/** Delete trustline to AMM. The passed `sle` must be obtained from a prior
|
||||
* call to view.peek(). Fail if neither side of the trustline is AMM or
|
||||
* if ammAccountID is seated and is not one of the trustline's side.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
deleteAMMTrustLine(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> sleState,
|
||||
std::optional<AccountID> const& ammAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
// From the perspective of a vault, return the number of shares to give the
|
||||
// depositor when they deposit a fixed amount of assets. Since shares are MPT
|
||||
// this number is integral and always truncated in this calculation.
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
assetsToSharesDeposit(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& assets);
|
||||
|
||||
// From the perspective of a vault, return the number of assets to take from
|
||||
// depositor when they receive a fixed amount of shares. Note, since shares are
|
||||
// MPT, they are always an integral number.
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
sharesToAssetsDeposit(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares);
|
||||
|
||||
enum class TruncateShares : bool { no = false, yes = true };
|
||||
|
||||
// From the perspective of a vault, return the number of shares to demand from
|
||||
// the depositor when they ask to withdraw a fixed amount of assets. Since
|
||||
// shares are MPT this number is integral, and it will be rounded to nearest
|
||||
// unless explicitly requested to be truncated instead.
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
assetsToSharesWithdraw(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& assets,
|
||||
TruncateShares truncate = TruncateShares::no);
|
||||
|
||||
// From the perspective of a vault, return the number of assets to give the
|
||||
// depositor when they redeem a fixed amount of shares. Note, since shares are
|
||||
// MPT, they are always an integral number.
|
||||
[[nodiscard]] std::optional<STAmount>
|
||||
sharesToAssetsWithdraw(
|
||||
std::shared_ptr<SLE const> const& vault,
|
||||
std::shared_ptr<SLE const> const& issuance,
|
||||
STAmount const& shares);
|
||||
|
||||
/** Has the specified time passed?
|
||||
|
||||
@param now the current time
|
||||
@param mark the cutoff point
|
||||
@return true if \a now refers to a time strictly after \a mark, else false.
|
||||
*/
|
||||
bool
|
||||
after(NetClock::time_point now, std::uint32_t mark);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
163
include/xrpl/ledger/detail/ApplyStateTable.h
Normal file
163
include/xrpl/ledger/detail/ApplyStateTable.h
Normal file
@@ -0,0 +1,163 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_APPLYSTATETABLE_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_APPLYSTATETABLE_H_INCLUDED
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/OpenView.h>
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
namespace detail {
|
||||
|
||||
// Helper class that buffers modifications
|
||||
class ApplyStateTable
|
||||
{
|
||||
public:
|
||||
using key_type = ReadView::key_type;
|
||||
|
||||
private:
|
||||
enum class Action {
|
||||
cache,
|
||||
erase,
|
||||
insert,
|
||||
modify,
|
||||
};
|
||||
|
||||
using items_t = std::map<key_type, std::pair<Action, std::shared_ptr<SLE>>>;
|
||||
|
||||
items_t items_;
|
||||
XRPAmount dropsDestroyed_{0};
|
||||
|
||||
public:
|
||||
ApplyStateTable() = default;
|
||||
ApplyStateTable(ApplyStateTable&&) = default;
|
||||
|
||||
ApplyStateTable(ApplyStateTable const&) = delete;
|
||||
ApplyStateTable&
|
||||
operator=(ApplyStateTable&&) = delete;
|
||||
ApplyStateTable&
|
||||
operator=(ApplyStateTable const&) = delete;
|
||||
|
||||
void
|
||||
apply(RawView& to) const;
|
||||
|
||||
std::optional<TxMeta>
|
||||
apply(
|
||||
OpenView& to,
|
||||
STTx const& tx,
|
||||
TER ter,
|
||||
std::optional<STAmount> const& deliver,
|
||||
std::optional<uint256 const> const& parentBatchId,
|
||||
bool isDryRun,
|
||||
beast::Journal j);
|
||||
|
||||
bool
|
||||
exists(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
std::optional<key_type>
|
||||
succ(
|
||||
ReadView const& base,
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last) const;
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
read(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
peek(ReadView const& base, Keylet const& k);
|
||||
|
||||
std::size_t
|
||||
size() const;
|
||||
|
||||
void
|
||||
visit(
|
||||
ReadView const& base,
|
||||
std::function<void(
|
||||
uint256 const& key,
|
||||
bool isDelete,
|
||||
std::shared_ptr<SLE const> const& before,
|
||||
std::shared_ptr<SLE const> const& after)> const& func) const;
|
||||
|
||||
void
|
||||
erase(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
rawErase(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
insert(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
update(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
replace(ReadView const& base, std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
destroyXRP(XRPAmount const& fee);
|
||||
|
||||
// For debugging
|
||||
XRPAmount const&
|
||||
dropsDestroyed() const
|
||||
{
|
||||
return dropsDestroyed_;
|
||||
}
|
||||
|
||||
private:
|
||||
using Mods = hash_map<key_type, std::shared_ptr<SLE>>;
|
||||
|
||||
static void
|
||||
threadItem(TxMeta& meta, std::shared_ptr<SLE> const& to);
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
getForMod(
|
||||
ReadView const& base,
|
||||
key_type const& key,
|
||||
Mods& mods,
|
||||
beast::Journal j);
|
||||
|
||||
void
|
||||
threadTx(
|
||||
ReadView const& base,
|
||||
TxMeta& meta,
|
||||
AccountID const& to,
|
||||
Mods& mods,
|
||||
beast::Journal j);
|
||||
|
||||
void
|
||||
threadOwners(
|
||||
ReadView const& base,
|
||||
TxMeta& meta,
|
||||
std::shared_ptr<SLE const> const& sle,
|
||||
Mods& mods,
|
||||
beast::Journal j);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
130
include/xrpl/ledger/detail/ApplyViewBase.h
Normal file
130
include/xrpl/ledger/detail/ApplyViewBase.h
Normal file
@@ -0,0 +1,130 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_APPLYVIEWBASE_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_APPLYVIEWBASE_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/detail/ApplyStateTable.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace detail {
|
||||
|
||||
class ApplyViewBase : public ApplyView, public RawView
|
||||
{
|
||||
public:
|
||||
ApplyViewBase() = delete;
|
||||
ApplyViewBase(ApplyViewBase const&) = delete;
|
||||
ApplyViewBase&
|
||||
operator=(ApplyViewBase&&) = delete;
|
||||
ApplyViewBase&
|
||||
operator=(ApplyViewBase const&) = delete;
|
||||
|
||||
ApplyViewBase(ApplyViewBase&&) = default;
|
||||
|
||||
ApplyViewBase(ReadView const* base, ApplyFlags flags);
|
||||
|
||||
// ReadView
|
||||
bool
|
||||
open() const override;
|
||||
|
||||
LedgerInfo const&
|
||||
info() const override;
|
||||
|
||||
Fees const&
|
||||
fees() const override;
|
||||
|
||||
Rules const&
|
||||
rules() const override;
|
||||
|
||||
bool
|
||||
exists(Keylet const& k) const override;
|
||||
|
||||
std::optional<key_type>
|
||||
succ(
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last = std::nullopt) const override;
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
read(Keylet const& k) const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesBegin() const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesEnd() const override;
|
||||
|
||||
std::unique_ptr<sles_type::iter_base>
|
||||
slesUpperBound(uint256 const& key) const override;
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsBegin() const override;
|
||||
|
||||
std::unique_ptr<txs_type::iter_base>
|
||||
txsEnd() const override;
|
||||
|
||||
bool
|
||||
txExists(key_type const& key) const override;
|
||||
|
||||
tx_type
|
||||
txRead(key_type const& key) const override;
|
||||
|
||||
// ApplyView
|
||||
|
||||
ApplyFlags
|
||||
flags() const override;
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
peek(Keylet const& k) override;
|
||||
|
||||
void
|
||||
erase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
insert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
update(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
// RawView
|
||||
|
||||
void
|
||||
rawErase(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawInsert(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawReplace(std::shared_ptr<SLE> const& sle) override;
|
||||
|
||||
void
|
||||
rawDestroyXRP(XRPAmount const& feeDrops) override;
|
||||
|
||||
protected:
|
||||
ApplyFlags flags_;
|
||||
ReadView const* base_;
|
||||
detail::ApplyStateTable items_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
142
include/xrpl/ledger/detail/RawStateTable.h
Normal file
142
include/xrpl/ledger/detail/RawStateTable.h
Normal file
@@ -0,0 +1,142 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_RAWSTATETABLE_H_INCLUDED
|
||||
|
||||
#include <xrpl/ledger/RawView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
|
||||
#include <boost/container/pmr/monotonic_buffer_resource.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
namespace detail {
|
||||
|
||||
// Helper class that buffers raw modifications
|
||||
class RawStateTable
|
||||
{
|
||||
public:
|
||||
using key_type = ReadView::key_type;
|
||||
// Initial size for the monotonic_buffer_resource used for allocations
|
||||
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||
// It is unclear how the size initially chosen in qalloc.
|
||||
static constexpr size_t initialBufferSize = kilobytes(256);
|
||||
|
||||
RawStateTable()
|
||||
: 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)}
|
||||
, items_{rhs.items_, monotonic_resource_.get()}
|
||||
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||
|
||||
RawStateTable(RawStateTable&&) = default;
|
||||
|
||||
RawStateTable&
|
||||
operator=(RawStateTable&&) = delete;
|
||||
RawStateTable&
|
||||
operator=(RawStateTable const&) = delete;
|
||||
|
||||
void
|
||||
apply(RawView& to) const;
|
||||
|
||||
bool
|
||||
exists(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
std::optional<key_type>
|
||||
succ(
|
||||
ReadView const& base,
|
||||
key_type const& key,
|
||||
std::optional<key_type> const& last) const;
|
||||
|
||||
void
|
||||
erase(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
insert(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
void
|
||||
replace(std::shared_ptr<SLE> const& sle);
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
read(ReadView const& base, Keylet const& k) const;
|
||||
|
||||
void
|
||||
destroyXRP(XRPAmount const& fee);
|
||||
|
||||
std::unique_ptr<ReadView::sles_type::iter_base>
|
||||
slesBegin(ReadView const& base) const;
|
||||
|
||||
std::unique_ptr<ReadView::sles_type::iter_base>
|
||||
slesEnd(ReadView const& base) const;
|
||||
|
||||
std::unique_ptr<ReadView::sles_type::iter_base>
|
||||
slesUpperBound(ReadView const& base, uint256 const& key) const;
|
||||
|
||||
private:
|
||||
enum class Action {
|
||||
erase,
|
||||
insert,
|
||||
replace,
|
||||
};
|
||||
|
||||
class sles_iter_impl;
|
||||
|
||||
struct sleAction
|
||||
{
|
||||
Action action;
|
||||
std::shared_ptr<SLE> sle;
|
||||
|
||||
// Constructor needed for emplacement in std::map
|
||||
sleAction(Action action_, std::shared_ptr<SLE> const& sle_)
|
||||
: action(action_), sle(sle_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Use boost::pmr functionality instead of the std::pmr
|
||||
// functions b/c clang does not support pmr yet (as-of 9/2020)
|
||||
using items_t = std::map<
|
||||
key_type,
|
||||
sleAction,
|
||||
std::less<key_type>,
|
||||
boost::container::pmr::polymorphic_allocator<
|
||||
std::pair<key_type const, sleAction>>>;
|
||||
// monotonic_resource_ must outlive `items_`. Make a pointer so it may be
|
||||
// easily moved.
|
||||
std::unique_ptr<boost::container::pmr::monotonic_buffer_resource>
|
||||
monotonic_resource_;
|
||||
items_t items_;
|
||||
|
||||
XRPAmount dropsDestroyed_{0};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
154
include/xrpl/ledger/detail/ReadViewFwdRange.h
Normal file
154
include/xrpl/ledger/detail/ReadViewFwdRange.h
Normal file
@@ -0,0 +1,154 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_READVIEWFWDRANGE_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_READVIEWFWDRANGE_H_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class ReadView;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// A type-erased ForwardIterator
|
||||
//
|
||||
template <class ValueType>
|
||||
class ReadViewFwdIter
|
||||
{
|
||||
public:
|
||||
using base_type = ReadViewFwdIter;
|
||||
|
||||
using value_type = ValueType;
|
||||
|
||||
ReadViewFwdIter() = default;
|
||||
ReadViewFwdIter(ReadViewFwdIter const&) = default;
|
||||
ReadViewFwdIter&
|
||||
operator=(ReadViewFwdIter const&) = default;
|
||||
|
||||
virtual ~ReadViewFwdIter() = default;
|
||||
|
||||
virtual std::unique_ptr<ReadViewFwdIter>
|
||||
copy() const = 0;
|
||||
|
||||
virtual bool
|
||||
equal(ReadViewFwdIter const& impl) const = 0;
|
||||
|
||||
virtual void
|
||||
increment() = 0;
|
||||
|
||||
virtual value_type
|
||||
dereference() const = 0;
|
||||
};
|
||||
|
||||
// A range using type-erased ForwardIterator
|
||||
//
|
||||
template <class ValueType>
|
||||
class ReadViewFwdRange
|
||||
{
|
||||
public:
|
||||
using iter_base = ReadViewFwdIter<ValueType>;
|
||||
|
||||
static_assert(
|
||||
std::is_nothrow_move_constructible<ValueType>{},
|
||||
"ReadViewFwdRange move and move assign constructors should be "
|
||||
"noexcept");
|
||||
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
using value_type = ValueType;
|
||||
|
||||
using pointer = value_type const*;
|
||||
|
||||
using reference = value_type const&;
|
||||
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
|
||||
iterator(iterator const& other);
|
||||
iterator(iterator&& other) noexcept;
|
||||
|
||||
// Used by the implementation
|
||||
explicit iterator(
|
||||
ReadView const* view,
|
||||
std::unique_ptr<iter_base> impl);
|
||||
|
||||
iterator&
|
||||
operator=(iterator const& other);
|
||||
|
||||
iterator&
|
||||
operator=(iterator&& other) noexcept;
|
||||
|
||||
bool
|
||||
operator==(iterator const& other) const;
|
||||
|
||||
bool
|
||||
operator!=(iterator const& other) const;
|
||||
|
||||
// Can throw
|
||||
reference
|
||||
operator*() const;
|
||||
|
||||
// Can throw
|
||||
pointer
|
||||
operator->() const;
|
||||
|
||||
iterator&
|
||||
operator++();
|
||||
|
||||
iterator
|
||||
operator++(int);
|
||||
|
||||
private:
|
||||
ReadView const* view_ = nullptr;
|
||||
std::unique_ptr<iter_base> impl_;
|
||||
std::optional<value_type> mutable cache_;
|
||||
};
|
||||
|
||||
static_assert(std::is_nothrow_move_constructible<iterator>{}, "");
|
||||
static_assert(std::is_nothrow_move_assignable<iterator>{}, "");
|
||||
|
||||
using const_iterator = iterator;
|
||||
|
||||
using value_type = ValueType;
|
||||
|
||||
ReadViewFwdRange() = delete;
|
||||
ReadViewFwdRange(ReadViewFwdRange const&) = default;
|
||||
ReadViewFwdRange&
|
||||
operator=(ReadViewFwdRange const&) = default;
|
||||
|
||||
explicit ReadViewFwdRange(ReadView const& view) : view_(&view)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
ReadView const* view_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
139
include/xrpl/ledger/detail/ReadViewFwdRange.ipp
Normal file
139
include/xrpl/ledger/detail/ReadViewFwdRange.ipp
Normal file
@@ -0,0 +1,139 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LEDGER_READVIEWFWDRANGEINL_H_INCLUDED
|
||||
#define RIPPLE_LEDGER_READVIEWFWDRANGEINL_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
namespace detail {
|
||||
|
||||
template <class ValueType>
|
||||
ReadViewFwdRange<ValueType>::iterator::iterator(iterator const& other)
|
||||
: view_(other.view_)
|
||||
, impl_(other.impl_ ? other.impl_->copy() : nullptr)
|
||||
, cache_(other.cache_)
|
||||
{
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
ReadViewFwdRange<ValueType>::iterator::iterator(iterator&& other) noexcept
|
||||
: view_(other.view_)
|
||||
, impl_(std::move(other.impl_))
|
||||
, cache_(std::move(other.cache_))
|
||||
{
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
ReadViewFwdRange<ValueType>::iterator::iterator(
|
||||
ReadView const* view,
|
||||
std::unique_ptr<iter_base> impl)
|
||||
: view_(view), impl_(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator=(iterator const& other)
|
||||
-> iterator&
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
view_ = other.view_;
|
||||
impl_ = other.impl_ ? other.impl_->copy() : nullptr;
|
||||
cache_ = other.cache_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator=(iterator&& other) noexcept
|
||||
-> iterator&
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
view_ = other.view_;
|
||||
impl_ = std::move(other.impl_);
|
||||
cache_ = std::move(other.cache_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
bool
|
||||
ReadViewFwdRange<ValueType>::iterator::operator==(iterator const& other) const
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
view_ == other.view_,
|
||||
"ripple::detail::ReadViewFwdRange::iterator::operator==(iterator) "
|
||||
"const : input view match");
|
||||
|
||||
if (impl_ != nullptr && other.impl_ != nullptr)
|
||||
return impl_->equal(*other.impl_);
|
||||
|
||||
return impl_ == other.impl_;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
bool
|
||||
ReadViewFwdRange<ValueType>::iterator::operator!=(iterator const& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator*() const -> reference
|
||||
{
|
||||
if (!cache_)
|
||||
cache_ = impl_->dereference();
|
||||
return *cache_;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator->() const -> pointer
|
||||
{
|
||||
return &**this;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator++() -> iterator&
|
||||
{
|
||||
impl_->increment();
|
||||
cache_.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ValueType>
|
||||
auto
|
||||
ReadViewFwdRange<ValueType>::iterator::operator++(int) -> iterator
|
||||
{
|
||||
iterator prev(view_, impl_->copy());
|
||||
prev.cache_ = std::move(cache_);
|
||||
++(*this);
|
||||
return prev;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
328
include/xrpl/net/AutoSocket.h
Normal file
328
include/xrpl/net/AutoSocket.h
Normal file
@@ -0,0 +1,328 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_WEBSOCKET_AUTOSOCKET_AUTOSOCKET_H_INCLUDED
|
||||
#define RIPPLE_WEBSOCKET_AUTOSOCKET_AUTOSOCKET_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/net/IPAddressConversion.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/beast/core/bind_handler.hpp>
|
||||
|
||||
// Socket wrapper that supports both SSL and non-SSL connections.
|
||||
// Generally, handle it as you would an SSL connection.
|
||||
// To force a non-SSL connection, just don't call async_handshake.
|
||||
// To force SSL only inbound, call setSSLOnly.
|
||||
|
||||
class AutoSocket
|
||||
{
|
||||
public:
|
||||
using ssl_socket = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
|
||||
using endpoint_type = boost::asio::ip::tcp::socket::endpoint_type;
|
||||
using socket_ptr = std::unique_ptr<ssl_socket>;
|
||||
using plain_socket = ssl_socket::next_layer_type;
|
||||
using lowest_layer_type = ssl_socket::lowest_layer_type;
|
||||
using handshake_type = ssl_socket::handshake_type;
|
||||
using error_code = boost::system::error_code;
|
||||
using callback = std::function<void(error_code)>;
|
||||
|
||||
public:
|
||||
AutoSocket(
|
||||
boost::asio::io_context& s,
|
||||
boost::asio::ssl::context& c,
|
||||
bool secureOnly,
|
||||
bool plainOnly)
|
||||
: mSecure(secureOnly)
|
||||
, mBuffer((plainOnly || secureOnly) ? 0 : 4)
|
||||
, j_{beast::Journal::getNullSink()}
|
||||
{
|
||||
mSocket = std::make_unique<ssl_socket>(s, c);
|
||||
}
|
||||
|
||||
AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c)
|
||||
: AutoSocket(s, c, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
isSecure()
|
||||
{
|
||||
return mSecure;
|
||||
}
|
||||
ssl_socket&
|
||||
SSLSocket()
|
||||
{
|
||||
return *mSocket;
|
||||
}
|
||||
plain_socket&
|
||||
PlainSocket()
|
||||
{
|
||||
return mSocket->next_layer();
|
||||
}
|
||||
|
||||
beast::IP::Endpoint
|
||||
local_endpoint()
|
||||
{
|
||||
return beast::IP::from_asio(lowest_layer().local_endpoint());
|
||||
}
|
||||
|
||||
beast::IP::Endpoint
|
||||
remote_endpoint()
|
||||
{
|
||||
return beast::IP::from_asio(lowest_layer().remote_endpoint());
|
||||
}
|
||||
|
||||
lowest_layer_type&
|
||||
lowest_layer()
|
||||
{
|
||||
return mSocket->lowest_layer();
|
||||
}
|
||||
|
||||
void
|
||||
swap(AutoSocket& s) noexcept
|
||||
{
|
||||
mBuffer.swap(s.mBuffer);
|
||||
mSocket.swap(s.mSocket);
|
||||
std::swap(mSecure, s.mSecure);
|
||||
}
|
||||
|
||||
boost::system::error_code
|
||||
cancel(boost::system::error_code& ec)
|
||||
{
|
||||
return lowest_layer().cancel(ec);
|
||||
}
|
||||
|
||||
void
|
||||
async_handshake(handshake_type type, callback cbFunc)
|
||||
{
|
||||
if ((type == ssl_socket::client) || (mSecure))
|
||||
{
|
||||
// must be ssl
|
||||
mSecure = true;
|
||||
mSocket->async_handshake(type, cbFunc);
|
||||
}
|
||||
else if (mBuffer.empty())
|
||||
{
|
||||
// must be plain
|
||||
mSecure = false;
|
||||
post(
|
||||
mSocket->get_executor(),
|
||||
boost::beast::bind_handler(cbFunc, error_code()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// autodetect
|
||||
mSocket->next_layer().async_receive(
|
||||
boost::asio::buffer(mBuffer),
|
||||
boost::asio::socket_base::message_peek,
|
||||
std::bind(
|
||||
&AutoSocket::handle_autodetect,
|
||||
this,
|
||||
cbFunc,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ShutdownHandler>
|
||||
void
|
||||
async_shutdown(ShutdownHandler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
mSocket->async_shutdown(handler);
|
||||
else
|
||||
{
|
||||
error_code ec;
|
||||
try
|
||||
{
|
||||
lowest_layer().shutdown(plain_socket::shutdown_both);
|
||||
}
|
||||
catch (boost::system::system_error& e)
|
||||
{
|
||||
ec = e.code();
|
||||
}
|
||||
post(
|
||||
mSocket->get_executor(),
|
||||
boost::beast::bind_handler(handler, ec));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Seq, typename Handler>
|
||||
void
|
||||
async_read_some(Seq const& buffers, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
mSocket->async_read_some(buffers, handler);
|
||||
else
|
||||
PlainSocket().async_read_some(buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Seq, typename Condition, typename Handler>
|
||||
void
|
||||
async_read_until(Seq const& buffers, Condition condition, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read_until(
|
||||
*mSocket, buffers, condition, handler);
|
||||
else
|
||||
boost::asio::async_read_until(
|
||||
PlainSocket(), buffers, condition, handler);
|
||||
}
|
||||
|
||||
template <typename Allocator, typename Handler>
|
||||
void
|
||||
async_read_until(
|
||||
boost::asio::basic_streambuf<Allocator>& buffers,
|
||||
std::string const& delim,
|
||||
Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read_until(*mSocket, buffers, delim, handler);
|
||||
else
|
||||
boost::asio::async_read_until(
|
||||
PlainSocket(), buffers, delim, handler);
|
||||
}
|
||||
|
||||
template <typename Allocator, typename MatchCondition, typename Handler>
|
||||
void
|
||||
async_read_until(
|
||||
boost::asio::basic_streambuf<Allocator>& buffers,
|
||||
MatchCondition cond,
|
||||
Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read_until(*mSocket, buffers, cond, handler);
|
||||
else
|
||||
boost::asio::async_read_until(
|
||||
PlainSocket(), buffers, cond, handler);
|
||||
}
|
||||
|
||||
template <typename Buf, typename Handler>
|
||||
void
|
||||
async_write(Buf const& buffers, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_write(*mSocket, buffers, handler);
|
||||
else
|
||||
boost::asio::async_write(PlainSocket(), buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Allocator, typename Handler>
|
||||
void
|
||||
async_write(
|
||||
boost::asio::basic_streambuf<Allocator>& buffers,
|
||||
Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_write(*mSocket, buffers, handler);
|
||||
else
|
||||
boost::asio::async_write(PlainSocket(), buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Buf, typename Condition, typename Handler>
|
||||
void
|
||||
async_read(Buf const& buffers, Condition cond, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read(*mSocket, buffers, cond, handler);
|
||||
else
|
||||
boost::asio::async_read(PlainSocket(), buffers, cond, handler);
|
||||
}
|
||||
|
||||
template <typename Allocator, typename Condition, typename Handler>
|
||||
void
|
||||
async_read(
|
||||
boost::asio::basic_streambuf<Allocator>& buffers,
|
||||
Condition cond,
|
||||
Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read(*mSocket, buffers, cond, handler);
|
||||
else
|
||||
boost::asio::async_read(PlainSocket(), buffers, cond, handler);
|
||||
}
|
||||
|
||||
template <typename Buf, typename Handler>
|
||||
void
|
||||
async_read(Buf const& buffers, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
boost::asio::async_read(*mSocket, buffers, handler);
|
||||
else
|
||||
boost::asio::async_read(PlainSocket(), buffers, handler);
|
||||
}
|
||||
|
||||
template <typename Seq, typename Handler>
|
||||
void
|
||||
async_write_some(Seq const& buffers, Handler handler)
|
||||
{
|
||||
if (isSecure())
|
||||
mSocket->async_write_some(buffers, handler);
|
||||
else
|
||||
PlainSocket().async_write_some(buffers, handler);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
handle_autodetect(
|
||||
callback cbFunc,
|
||||
error_code const& ec,
|
||||
size_t bytesTransferred)
|
||||
{
|
||||
using namespace ripple;
|
||||
|
||||
if (ec)
|
||||
{
|
||||
JLOG(j_.warn()) << "Handle autodetect error: " << ec;
|
||||
cbFunc(ec);
|
||||
}
|
||||
else if (
|
||||
(mBuffer[0] < 127) && (mBuffer[0] > 31) &&
|
||||
((bytesTransferred < 2) ||
|
||||
((mBuffer[1] < 127) && (mBuffer[1] > 31))) &&
|
||||
((bytesTransferred < 3) ||
|
||||
((mBuffer[2] < 127) && (mBuffer[2] > 31))) &&
|
||||
((bytesTransferred < 4) ||
|
||||
((mBuffer[3] < 127) && (mBuffer[3] > 31))))
|
||||
{
|
||||
// not ssl
|
||||
JLOG(j_.trace()) << "non-SSL";
|
||||
mSecure = false;
|
||||
cbFunc(ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ssl
|
||||
JLOG(j_.trace()) << "SSL";
|
||||
mSecure = true;
|
||||
mSocket->async_handshake(ssl_socket::server, cbFunc);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
socket_ptr mSocket;
|
||||
bool mSecure;
|
||||
std::vector<char> mBuffer;
|
||||
beast::Journal j_;
|
||||
};
|
||||
|
||||
#endif
|
||||
99
include/xrpl/net/HTTPClient.h
Normal file
99
include/xrpl/net/HTTPClient.h
Normal file
@@ -0,0 +1,99 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NET_HTTPCLIENT_H_INCLUDED
|
||||
#define RIPPLE_NET_HTTPCLIENT_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Provides an asynchronous HTTP client implementation with optional SSL.
|
||||
*/
|
||||
class HTTPClient
|
||||
{
|
||||
public:
|
||||
explicit HTTPClient() = default;
|
||||
|
||||
static constexpr auto maxClientHeaderBytes = kilobytes(32);
|
||||
|
||||
static void
|
||||
initializeSSLContext(
|
||||
std::string const& sslVerifyDir,
|
||||
std::string const& sslVerifyFile,
|
||||
bool sslVerify,
|
||||
beast::Journal j);
|
||||
|
||||
static void
|
||||
get(bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
std::deque<std::string> deqSites,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
std::size_t responseMax, // if no Content-Length header
|
||||
std::chrono::seconds timeout,
|
||||
std::function<bool(
|
||||
boost::system::error_code const& ecResult,
|
||||
int iStatus,
|
||||
std::string const& strData)> complete,
|
||||
beast::Journal& j);
|
||||
|
||||
static void
|
||||
get(bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
std::size_t responseMax, // if no Content-Length header
|
||||
std::chrono::seconds timeout,
|
||||
std::function<bool(
|
||||
boost::system::error_code const& ecResult,
|
||||
int iStatus,
|
||||
std::string const& strData)> complete,
|
||||
beast::Journal& j);
|
||||
|
||||
static void
|
||||
request(
|
||||
bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::function<
|
||||
void(boost::asio::streambuf& sb, std::string const& strHost)> build,
|
||||
std::size_t responseMax, // if no Content-Length header
|
||||
std::chrono::seconds timeout,
|
||||
std::function<bool(
|
||||
boost::system::error_code const& ecResult,
|
||||
int iStatus,
|
||||
std::string const& strData)> complete,
|
||||
beast::Journal& j);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
200
include/xrpl/net/HTTPClientSSLContext.h
Normal file
200
include/xrpl/net/HTTPClientSSLContext.h
Normal file
@@ -0,0 +1,200 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2019 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
|
||||
#define RIPPLE_NET_HTTPCLIENTSSLCONTEXT_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/net/RegisterSSLCerts.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class HTTPClientSSLContext
|
||||
{
|
||||
public:
|
||||
explicit HTTPClientSSLContext(
|
||||
std::string const& sslVerifyDir,
|
||||
std::string const& sslVerifyFile,
|
||||
bool sslVerify,
|
||||
beast::Journal j,
|
||||
boost::asio::ssl::context_base::method method =
|
||||
boost::asio::ssl::context::sslv23)
|
||||
: ssl_context_{method}, j_(j), verify_{sslVerify}
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
if (sslVerifyFile.empty())
|
||||
{
|
||||
registerSSLCerts(ssl_context_, ec, j_);
|
||||
|
||||
if (ec && sslVerifyDir.empty())
|
||||
Throw<std::runtime_error>(boost::str(
|
||||
boost::format("Failed to set_default_verify_paths: %s") %
|
||||
ec.message()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ssl_context_.load_verify_file(sslVerifyFile);
|
||||
}
|
||||
|
||||
if (!sslVerifyDir.empty())
|
||||
{
|
||||
ssl_context_.add_verify_path(sslVerifyDir, ec);
|
||||
|
||||
if (ec)
|
||||
Throw<std::runtime_error>(boost::str(
|
||||
boost::format("Failed to add verify path: %s") %
|
||||
ec.message()));
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::ssl::context&
|
||||
context()
|
||||
{
|
||||
return ssl_context_;
|
||||
}
|
||||
|
||||
bool
|
||||
sslVerify() const
|
||||
{
|
||||
return verify_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief invoked before connect/async_connect on an ssl stream
|
||||
* to setup name verification.
|
||||
*
|
||||
* If we intend to verify the SSL connection, we need to set the
|
||||
* default domain for server name indication *prior* to connecting
|
||||
*
|
||||
* @param strm asio ssl stream
|
||||
* @param host hostname to verify
|
||||
*
|
||||
* @return error_code indicating failures, if any
|
||||
*/
|
||||
template <
|
||||
class T,
|
||||
class = std::enable_if_t<
|
||||
std::is_same<
|
||||
T,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
|
||||
value ||
|
||||
std::is_same<
|
||||
T,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
|
||||
value>>
|
||||
boost::system::error_code
|
||||
preConnectVerify(T& strm, std::string const& host)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (!SSL_set_tlsext_host_name(strm.native_handle(), host.c_str()))
|
||||
{
|
||||
ec.assign(
|
||||
static_cast<int>(::ERR_get_error()),
|
||||
boost::asio::error::get_ssl_category());
|
||||
}
|
||||
else if (!sslVerify())
|
||||
{
|
||||
strm.set_verify_mode(boost::asio::ssl::verify_none, ec);
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
class = std::enable_if_t<
|
||||
std::is_same<
|
||||
T,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>::
|
||||
value ||
|
||||
std::is_same<
|
||||
T,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>::
|
||||
value>>
|
||||
/**
|
||||
* @brief invoked after connect/async_connect but before sending data
|
||||
* on an ssl stream - to setup name verification.
|
||||
*
|
||||
* @param strm asio ssl stream
|
||||
* @param host hostname to verify
|
||||
*/
|
||||
boost::system::error_code
|
||||
postConnectVerify(T& strm, std::string const& host)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
|
||||
if (sslVerify())
|
||||
{
|
||||
strm.set_verify_mode(boost::asio::ssl::verify_peer, ec);
|
||||
if (!ec)
|
||||
{
|
||||
strm.set_verify_callback(
|
||||
std::bind(
|
||||
&rfc6125_verify,
|
||||
host,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
j_),
|
||||
ec);
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief callback invoked for name verification - just passes through
|
||||
* to the asio `host_name_verification` (rfc6125) implementation.
|
||||
*
|
||||
* @param domain hostname expected
|
||||
* @param preverified passed by implementation
|
||||
* @param ctx passed by implementation
|
||||
* @param j journal for logging
|
||||
*/
|
||||
static bool
|
||||
rfc6125_verify(
|
||||
std::string const& domain,
|
||||
bool preverified,
|
||||
boost::asio::ssl::verify_context& ctx,
|
||||
beast::Journal j)
|
||||
{
|
||||
if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
|
||||
return true;
|
||||
|
||||
JLOG(j.warn()) << "Outbound SSL connection to " << domain
|
||||
<< " fails certificate verification";
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::ssl::context ssl_context_;
|
||||
beast::Journal const j_;
|
||||
bool const verify_;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
43
include/xrpl/net/RegisterSSLCerts.h
Normal file
43
include/xrpl/net/RegisterSSLCerts.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2016 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NET_REGISTER_SSL_CERTS_H_INCLUDED
|
||||
#define RIPPLE_NET_REGISTER_SSL_CERTS_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
namespace ripple {
|
||||
/** Register default SSL certificates.
|
||||
|
||||
Register the system default SSL root certificates. On linux/mac,
|
||||
this just calls asio's `set_default_verify_paths` to look in standard
|
||||
operating system locations. On windows, it uses the OS certificate
|
||||
store accessible via CryptoAPI.
|
||||
*/
|
||||
void
|
||||
registerSSLCerts(
|
||||
boost::asio::ssl::context&,
|
||||
boost::system::error_code&,
|
||||
beast::Journal j);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -79,4 +79,3 @@ mirror the JSON test as much as possible.
|
||||
Refer to the Protocol Buffers [language
|
||||
guide](https://developers.google.com/protocol-buffers/docs/proto3)
|
||||
for more detailed information about Protocol Buffers.
|
||||
|
||||
|
||||
@@ -6,89 +6,81 @@ option java_multiple_files = true;
|
||||
|
||||
import "org/xrpl/rpc/v1/ledger.proto";
|
||||
|
||||
message GetLedgerRequest
|
||||
{
|
||||
message GetLedgerRequest {
|
||||
LedgerSpecifier ledger = 1;
|
||||
|
||||
LedgerSpecifier ledger = 1;
|
||||
// If true, include transactions contained in this ledger
|
||||
bool transactions = 2;
|
||||
|
||||
// If true, include transactions contained in this ledger
|
||||
bool transactions = 2;
|
||||
// If true and transactions, include full transactions and metadata
|
||||
// If false and transactions, include only transaction hashes
|
||||
bool expand = 3;
|
||||
|
||||
// If true and transactions, include full transactions and metadata
|
||||
// If false and transactions, include only transaction hashes
|
||||
bool expand = 3;
|
||||
// If true, include state map difference between this ledger and the
|
||||
// previous ledger. This includes all added, modified or deleted ledger
|
||||
// objects
|
||||
bool get_objects = 4;
|
||||
|
||||
// If true, include state map difference between this ledger and the
|
||||
// previous ledger. This includes all added, modified or deleted ledger
|
||||
// objects
|
||||
bool get_objects = 4;
|
||||
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 5;
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 5;
|
||||
|
||||
// Identifying string. If user is set, client_ip is not set, and request is
|
||||
// coming from a secure_gateway host, then the client is not subject to
|
||||
// resource controls
|
||||
string user = 6;
|
||||
// Identifying string. If user is set, client_ip is not set, and request is
|
||||
// coming from a secure_gateway host, then the client is not subject to
|
||||
// resource controls
|
||||
string user = 6;
|
||||
|
||||
// For every object in the diff, get the object's predecessor and successor
|
||||
// in the state map. Only used if get_objects is also true.
|
||||
bool get_object_neighbors = 7;
|
||||
// For every object in the diff, get the object's predecessor and successor
|
||||
// in the state map. Only used if get_objects is also true.
|
||||
bool get_object_neighbors = 7;
|
||||
}
|
||||
|
||||
message GetLedgerResponse
|
||||
{
|
||||
bytes ledger_header = 1;
|
||||
message GetLedgerResponse {
|
||||
bytes ledger_header = 1;
|
||||
|
||||
oneof transactions
|
||||
{
|
||||
// Just the hashes
|
||||
TransactionHashList hashes_list = 2;
|
||||
|
||||
// Full transactions and metadata
|
||||
TransactionAndMetadataList transactions_list = 3;
|
||||
}
|
||||
oneof transactions {
|
||||
// Just the hashes
|
||||
TransactionHashList hashes_list = 2;
|
||||
|
||||
// True if the ledger has been validated
|
||||
bool validated = 4;
|
||||
// Full transactions and metadata
|
||||
TransactionAndMetadataList transactions_list = 3;
|
||||
}
|
||||
|
||||
// State map difference between this ledger and the previous ledger
|
||||
RawLedgerObjects ledger_objects = 5;
|
||||
// True if the ledger has been validated
|
||||
bool validated = 4;
|
||||
|
||||
// True if the skiplist object is included in ledger_objects
|
||||
bool skiplist_included = 6;
|
||||
// State map difference between this ledger and the previous ledger
|
||||
RawLedgerObjects ledger_objects = 5;
|
||||
|
||||
// True if request was exempt from resource controls
|
||||
bool is_unlimited = 7;
|
||||
// True if the skiplist object is included in ledger_objects
|
||||
bool skiplist_included = 6;
|
||||
|
||||
// True if the response contains the state map diff
|
||||
bool objects_included = 8;
|
||||
// True if request was exempt from resource controls
|
||||
bool is_unlimited = 7;
|
||||
|
||||
// True if the response contains key of objects adjacent to objects in state
|
||||
// map diff
|
||||
bool object_neighbors_included = 9;
|
||||
// True if the response contains the state map diff
|
||||
bool objects_included = 8;
|
||||
|
||||
// True if the response contains key of objects adjacent to objects in state
|
||||
// map diff
|
||||
bool object_neighbors_included = 9;
|
||||
|
||||
// Successor information for book directories modified as part of this
|
||||
// ledger
|
||||
repeated BookSuccessor book_successors = 10;
|
||||
// Successor information for book directories modified as part of this
|
||||
// ledger
|
||||
repeated BookSuccessor book_successors = 10;
|
||||
}
|
||||
|
||||
message TransactionHashList
|
||||
{
|
||||
repeated bytes hashes = 1;
|
||||
message TransactionHashList {
|
||||
repeated bytes hashes = 1;
|
||||
}
|
||||
|
||||
message TransactionAndMetadata
|
||||
{
|
||||
bytes transaction_blob = 1;
|
||||
message TransactionAndMetadata {
|
||||
bytes transaction_blob = 1;
|
||||
|
||||
bytes metadata_blob = 2;
|
||||
bytes metadata_blob = 2;
|
||||
}
|
||||
|
||||
message TransactionAndMetadataList
|
||||
{
|
||||
repeated TransactionAndMetadata transactions = 1;
|
||||
message TransactionAndMetadataList {
|
||||
repeated TransactionAndMetadata transactions = 1;
|
||||
}
|
||||
|
||||
@@ -8,46 +8,43 @@ import "org/xrpl/rpc/v1/ledger.proto";
|
||||
|
||||
// Get ledger objects for a specific ledger. You can iterate through several
|
||||
// calls to retrieve the entire contents of a single ledger version.
|
||||
message GetLedgerDataRequest
|
||||
{
|
||||
// If set, only objects with a key greater than marker are returned.
|
||||
// This can be used to pick up where a previous call left off.
|
||||
// Set marker to the value of marker in the previous response.
|
||||
bytes marker = 1;
|
||||
message GetLedgerDataRequest {
|
||||
// If set, only objects with a key greater than marker are returned.
|
||||
// This can be used to pick up where a previous call left off.
|
||||
// Set marker to the value of marker in the previous response.
|
||||
bytes marker = 1;
|
||||
|
||||
LedgerSpecifier ledger = 2;
|
||||
LedgerSpecifier ledger = 2;
|
||||
|
||||
// If set, only objects with a key less than end_marker are returned
|
||||
bytes end_marker = 3;
|
||||
// If set, only objects with a key less than end_marker are returned
|
||||
bytes end_marker = 3;
|
||||
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 4;
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 4;
|
||||
|
||||
// Identifying string. If user is set, client_ip is not set, and request is
|
||||
// coming from a secure_gateway host, then the client is not subject to
|
||||
// resource controls
|
||||
string user = 6;
|
||||
// Identifying string. If user is set, client_ip is not set, and request is
|
||||
// coming from a secure_gateway host, then the client is not subject to
|
||||
// resource controls
|
||||
string user = 6;
|
||||
}
|
||||
|
||||
message GetLedgerDataResponse
|
||||
{
|
||||
// Sequence of the ledger containing the returned ledger objects
|
||||
uint32 ledger_index = 1;
|
||||
message GetLedgerDataResponse {
|
||||
// Sequence of the ledger containing the returned ledger objects
|
||||
uint32 ledger_index = 1;
|
||||
|
||||
// Hash of the ledger containing the returned ledger objects
|
||||
bytes ledger_hash = 2;
|
||||
|
||||
// Ledger objects
|
||||
RawLedgerObjects ledger_objects = 3;
|
||||
// Hash of the ledger containing the returned ledger objects
|
||||
bytes ledger_hash = 2;
|
||||
|
||||
// Key to be passed into a subsequent call to continue iteration. If not
|
||||
// set, there are no more objects left in the ledger, or no more objects
|
||||
// with key less than end_marker (if end_marker was set in the request)
|
||||
bytes marker = 4;
|
||||
// Ledger objects
|
||||
RawLedgerObjects ledger_objects = 3;
|
||||
|
||||
// True if request was exempt from resource controls
|
||||
bool is_unlimited = 7;
|
||||
// Key to be passed into a subsequent call to continue iteration. If not
|
||||
// set, there are no more objects left in the ledger, or no more objects
|
||||
// with key less than end_marker (if end_marker was set in the request)
|
||||
bytes marker = 4;
|
||||
|
||||
// True if request was exempt from resource controls
|
||||
bool is_unlimited = 7;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,27 +6,23 @@ option java_multiple_files = true;
|
||||
|
||||
import "org/xrpl/rpc/v1/ledger.proto";
|
||||
|
||||
|
||||
// Get the state map difference between the two specified ledgers
|
||||
message GetLedgerDiffRequest
|
||||
{
|
||||
LedgerSpecifier base_ledger = 1;
|
||||
message GetLedgerDiffRequest {
|
||||
LedgerSpecifier base_ledger = 1;
|
||||
|
||||
LedgerSpecifier desired_ledger = 2;
|
||||
LedgerSpecifier desired_ledger = 2;
|
||||
|
||||
// If true, include the full ledger object. If false, only keys are included.
|
||||
bool include_blobs = 3;
|
||||
// If true, include the full ledger object. If false, only keys are included.
|
||||
bool include_blobs = 3;
|
||||
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 4;
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 4;
|
||||
}
|
||||
|
||||
message GetLedgerDiffResponse
|
||||
{
|
||||
// All ledger objects that were added, modified or deleted between
|
||||
// base_ledger and desired_ledger
|
||||
RawLedgerObjects ledger_objects = 1;
|
||||
message GetLedgerDiffResponse {
|
||||
// All ledger objects that were added, modified or deleted between
|
||||
// base_ledger and desired_ledger
|
||||
RawLedgerObjects ledger_objects = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,25 +7,23 @@ option java_multiple_files = true;
|
||||
import "org/xrpl/rpc/v1/ledger.proto";
|
||||
|
||||
// Get a single ledger object
|
||||
message GetLedgerEntryRequest
|
||||
{
|
||||
// Key of the desired object
|
||||
bytes key = 1;
|
||||
message GetLedgerEntryRequest {
|
||||
// Key of the desired object
|
||||
bytes key = 1;
|
||||
|
||||
// Ledger containing the object
|
||||
LedgerSpecifier ledger = 2;
|
||||
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 3;
|
||||
// Ledger containing the object
|
||||
LedgerSpecifier ledger = 2;
|
||||
|
||||
// If the request needs to be forwarded from a reporting node to a p2p node,
|
||||
// the reporting node will set this field. Clients should not set this
|
||||
// field.
|
||||
string client_ip = 3;
|
||||
}
|
||||
|
||||
message GetLedgerEntryResponse
|
||||
{
|
||||
RawLedgerObject ledger_object = 1;
|
||||
message GetLedgerEntryResponse {
|
||||
RawLedgerObject ledger_object = 1;
|
||||
|
||||
// Ledger containing the object. Will match the value specified in the
|
||||
// request.
|
||||
LedgerSpecifier ledger = 2;
|
||||
// Ledger containing the object. Will match the value specified in the
|
||||
// request.
|
||||
LedgerSpecifier ledger = 2;
|
||||
}
|
||||
|
||||
@@ -5,71 +5,61 @@ option java_package = "org.xrpl.rpc.v1";
|
||||
option java_multiple_files = true;
|
||||
|
||||
// Next field: 4
|
||||
message LedgerSpecifier
|
||||
{
|
||||
// Next field: 4
|
||||
enum Shortcut
|
||||
{
|
||||
SHORTCUT_UNSPECIFIED = 0;
|
||||
SHORTCUT_VALIDATED = 1;
|
||||
SHORTCUT_CLOSED = 2;
|
||||
SHORTCUT_CURRENT = 3;
|
||||
}
|
||||
message LedgerSpecifier {
|
||||
// Next field: 4
|
||||
enum Shortcut {
|
||||
SHORTCUT_UNSPECIFIED = 0;
|
||||
SHORTCUT_VALIDATED = 1;
|
||||
SHORTCUT_CLOSED = 2;
|
||||
SHORTCUT_CURRENT = 3;
|
||||
}
|
||||
|
||||
oneof ledger
|
||||
{
|
||||
Shortcut shortcut = 1;
|
||||
uint32 sequence = 2;
|
||||
// 32 bytes
|
||||
bytes hash = 3;
|
||||
}
|
||||
oneof ledger {
|
||||
Shortcut shortcut = 1;
|
||||
uint32 sequence = 2;
|
||||
// 32 bytes
|
||||
bytes hash = 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Next field: 3
|
||||
message RawLedgerObject
|
||||
{
|
||||
// Raw data of the ledger object. In GetLedgerResponse and
|
||||
// GetLedgerDiffResponse, data will be empty if the object was deleted.
|
||||
bytes data = 1;
|
||||
message RawLedgerObject {
|
||||
// Raw data of the ledger object. In GetLedgerResponse and
|
||||
// GetLedgerDiffResponse, data will be empty if the object was deleted.
|
||||
bytes data = 1;
|
||||
|
||||
// Key of the ledger object
|
||||
bytes key = 2;
|
||||
// Key of the ledger object
|
||||
bytes key = 2;
|
||||
|
||||
enum ModificationType
|
||||
{
|
||||
UNSPECIFIED = 0;
|
||||
CREATED = 1;
|
||||
MODIFIED = 2;
|
||||
DELETED = 3;
|
||||
}
|
||||
enum ModificationType {
|
||||
UNSPECIFIED = 0;
|
||||
CREATED = 1;
|
||||
MODIFIED = 2;
|
||||
DELETED = 3;
|
||||
}
|
||||
|
||||
// Whether the object was created, modified or deleted
|
||||
ModificationType mod_type = 3;
|
||||
// Whether the object was created, modified or deleted
|
||||
ModificationType mod_type = 3;
|
||||
|
||||
// Key of the object preceding this object in the desired ledger
|
||||
bytes predecessor = 4;
|
||||
// Key of the object preceding this object in the desired ledger
|
||||
bytes predecessor = 4;
|
||||
|
||||
// Key of the object succeeding this object in the desired ledger
|
||||
bytes successor = 5;
|
||||
// Key of the object succeeding this object in the desired ledger
|
||||
bytes successor = 5;
|
||||
}
|
||||
|
||||
message RawLedgerObjects
|
||||
{
|
||||
repeated RawLedgerObject objects = 1;
|
||||
message RawLedgerObjects {
|
||||
repeated RawLedgerObject objects = 1;
|
||||
}
|
||||
|
||||
// Successor information for book directories. The book base is (usually) not
|
||||
// an actual object, yet we need to be able to ask for the successor to the
|
||||
// book base.
|
||||
message BookSuccessor {
|
||||
// Base of the book in question
|
||||
bytes book_base = 1;
|
||||
|
||||
// Base of the book in question
|
||||
bytes book_base = 1;
|
||||
|
||||
// First book directory in the book. An empty value here means the entire
|
||||
// book is deleted
|
||||
bytes first_book = 2;
|
||||
|
||||
// First book directory in the book. An empty value here means the entire
|
||||
// book is deleted
|
||||
bytes first_book = 2;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,13 +9,11 @@ import "org/xrpl/rpc/v1/get_ledger_entry.proto";
|
||||
import "org/xrpl/rpc/v1/get_ledger_data.proto";
|
||||
import "org/xrpl/rpc/v1/get_ledger_diff.proto";
|
||||
|
||||
|
||||
// These methods are binary only methods for retrieiving arbitrary ledger state
|
||||
// via gRPC. These methods are used by clio, but can also be
|
||||
// used by any client that wants to extract ledger state in an efficient manner.
|
||||
// They do not directly mimic the JSON equivalent methods.
|
||||
service XRPLedgerAPIService {
|
||||
|
||||
// Get a specific ledger, optionally including transactions and any modified,
|
||||
// added or deleted ledger objects
|
||||
rpc GetLedger(GetLedgerRequest) returns (GetLedgerResponse);
|
||||
@@ -29,5 +27,4 @@ service XRPLedgerAPIService {
|
||||
// Get all ledger objects that are different between the two specified
|
||||
// ledgers. Note, this method has no JSON equivalent.
|
||||
rpc GetLedgerDiff(GetLedgerDiffRequest) returns (GetLedgerDiffResponse);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,29 +4,28 @@ package protocol;
|
||||
// Unused numbers in the list below may have been used previously. Please don't
|
||||
// reassign them for reuse unless you are 100% certain that there won't be a
|
||||
// conflict. Even if you're sure, it's probably best to assign a new type.
|
||||
enum MessageType
|
||||
{
|
||||
mtMANIFESTS = 2;
|
||||
mtPING = 3;
|
||||
mtCLUSTER = 5;
|
||||
mtENDPOINTS = 15;
|
||||
mtTRANSACTION = 30;
|
||||
mtGET_LEDGER = 31;
|
||||
mtLEDGER_DATA = 32;
|
||||
mtPROPOSE_LEDGER = 33;
|
||||
mtSTATUS_CHANGE = 34;
|
||||
mtHAVE_SET = 35;
|
||||
mtVALIDATION = 41;
|
||||
mtGET_OBJECTS = 42;
|
||||
mtVALIDATORLIST = 54;
|
||||
mtSQUELCH = 55;
|
||||
mtVALIDATORLISTCOLLECTION = 56;
|
||||
mtPROOF_PATH_REQ = 57;
|
||||
mtPROOF_PATH_RESPONSE = 58;
|
||||
mtREPLAY_DELTA_REQ = 59;
|
||||
mtREPLAY_DELTA_RESPONSE = 60;
|
||||
mtHAVE_TRANSACTIONS = 63;
|
||||
mtTRANSACTIONS = 64;
|
||||
enum MessageType {
|
||||
mtMANIFESTS = 2;
|
||||
mtPING = 3;
|
||||
mtCLUSTER = 5;
|
||||
mtENDPOINTS = 15;
|
||||
mtTRANSACTION = 30;
|
||||
mtGET_LEDGER = 31;
|
||||
mtLEDGER_DATA = 32;
|
||||
mtPROPOSE_LEDGER = 33;
|
||||
mtSTATUS_CHANGE = 34;
|
||||
mtHAVE_SET = 35;
|
||||
mtVALIDATION = 41;
|
||||
mtGET_OBJECTS = 42;
|
||||
mtVALIDATORLIST = 54;
|
||||
mtSQUELCH = 55;
|
||||
mtVALIDATORLISTCOLLECTION = 56;
|
||||
mtPROOF_PATH_REQ = 57;
|
||||
mtPROOF_PATH_RESPONSE = 58;
|
||||
mtREPLAY_DELTA_REQ = 59;
|
||||
mtREPLAY_DELTA_RESPONSE = 60;
|
||||
mtHAVE_TRANSACTIONS = 63;
|
||||
mtTRANSACTIONS = 64;
|
||||
}
|
||||
|
||||
// token, iterations, target, challenge = issue demand for proof of work
|
||||
@@ -36,352 +35,309 @@ enum MessageType
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* Provides the current ephemeral key for a validator. */
|
||||
message TMManifest
|
||||
{
|
||||
// A Manifest object in the Ripple serialization format.
|
||||
required bytes stobject = 1;
|
||||
message TMManifest {
|
||||
// A Manifest object in the Ripple serialization format.
|
||||
required bytes stobject = 1;
|
||||
}
|
||||
|
||||
message TMManifests
|
||||
{
|
||||
repeated TMManifest list = 1;
|
||||
message TMManifests {
|
||||
repeated TMManifest list = 1;
|
||||
|
||||
// The manifests sent when a peer first connects to another peer are `history`.
|
||||
optional bool history = 2 [deprecated=true];
|
||||
// The manifests sent when a peer first connects to another peer are `history`.
|
||||
optional bool history = 2 [deprecated = true];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// The status of a node in our cluster
|
||||
message TMClusterNode
|
||||
{
|
||||
required string publicKey = 1;
|
||||
required uint32 reportTime = 2;
|
||||
required uint32 nodeLoad = 3;
|
||||
optional string nodeName = 4;
|
||||
optional string address = 5;
|
||||
message TMClusterNode {
|
||||
required string publicKey = 1;
|
||||
required uint32 reportTime = 2;
|
||||
required uint32 nodeLoad = 3;
|
||||
optional string nodeName = 4;
|
||||
optional string address = 5;
|
||||
}
|
||||
|
||||
// Sources that are placing load on the server
|
||||
message TMLoadSource
|
||||
{
|
||||
required string name = 1;
|
||||
required uint32 cost = 2;
|
||||
optional uint32 count = 3; // number of connections
|
||||
message TMLoadSource {
|
||||
required string name = 1;
|
||||
required uint32 cost = 2;
|
||||
optional uint32 count = 3; // number of connections
|
||||
}
|
||||
|
||||
// The status of all nodes in the cluster
|
||||
message TMCluster
|
||||
{
|
||||
repeated TMClusterNode clusterNodes = 1;
|
||||
repeated TMLoadSource loadSources = 2;
|
||||
message TMCluster {
|
||||
repeated TMClusterNode clusterNodes = 1;
|
||||
repeated TMLoadSource loadSources = 2;
|
||||
}
|
||||
|
||||
// Node public key
|
||||
message TMLink
|
||||
{
|
||||
required bytes nodePubKey = 1 [deprecated=true]; // node public key
|
||||
message TMLink {
|
||||
required bytes nodePubKey = 1 [deprecated = true]; // node public key
|
||||
}
|
||||
|
||||
// Peer public key
|
||||
message TMPublicKey
|
||||
{
|
||||
required bytes publicKey = 1;
|
||||
message TMPublicKey {
|
||||
required bytes publicKey = 1;
|
||||
}
|
||||
|
||||
// A transaction can have only one input and one output.
|
||||
// If you want to send an amount that is greater than any single address of yours
|
||||
// you must first combine coins from one address to another.
|
||||
|
||||
enum TransactionStatus
|
||||
{
|
||||
tsNEW = 1; // origin node did/could not validate
|
||||
tsCURRENT = 2; // scheduled to go in this ledger
|
||||
tsCOMMITED = 3; // in a closed ledger
|
||||
tsREJECT_CONFLICT = 4;
|
||||
tsREJECT_INVALID = 5;
|
||||
tsREJECT_FUNDS = 6;
|
||||
tsHELD_SEQ = 7;
|
||||
tsHELD_LEDGER = 8; // held for future ledger
|
||||
enum TransactionStatus {
|
||||
tsNEW = 1; // origin node did/could not validate
|
||||
tsCURRENT = 2; // scheduled to go in this ledger
|
||||
tsCOMMITED = 3; // in a closed ledger
|
||||
tsREJECT_CONFLICT = 4;
|
||||
tsREJECT_INVALID = 5;
|
||||
tsREJECT_FUNDS = 6;
|
||||
tsHELD_SEQ = 7;
|
||||
tsHELD_LEDGER = 8; // held for future ledger
|
||||
}
|
||||
|
||||
message TMTransaction
|
||||
{
|
||||
required bytes rawTransaction = 1;
|
||||
required TransactionStatus status = 2;
|
||||
optional uint64 receiveTimestamp = 3;
|
||||
optional bool deferred = 4; // not applied to open ledger
|
||||
message TMTransaction {
|
||||
required bytes rawTransaction = 1;
|
||||
required TransactionStatus status = 2;
|
||||
optional uint64 receiveTimestamp = 3;
|
||||
optional bool deferred = 4; // not applied to open ledger
|
||||
}
|
||||
|
||||
message TMTransactions
|
||||
{
|
||||
repeated TMTransaction transactions = 1;
|
||||
message TMTransactions {
|
||||
repeated TMTransaction transactions = 1;
|
||||
}
|
||||
|
||||
|
||||
enum NodeStatus
|
||||
{
|
||||
nsCONNECTING = 1; // acquiring connections
|
||||
nsCONNECTED = 2; // convinced we are connected to the real network
|
||||
nsMONITORING = 3; // we know what the previous ledger is
|
||||
nsVALIDATING = 4; // we have the full ledger contents
|
||||
nsSHUTTING = 5; // node is shutting down
|
||||
enum NodeStatus {
|
||||
nsCONNECTING = 1; // acquiring connections
|
||||
nsCONNECTED = 2; // convinced we are connected to the real network
|
||||
nsMONITORING = 3; // we know what the previous ledger is
|
||||
nsVALIDATING = 4; // we have the full ledger contents
|
||||
nsSHUTTING = 5; // node is shutting down
|
||||
}
|
||||
|
||||
enum NodeEvent
|
||||
{
|
||||
neCLOSING_LEDGER = 1; // closing a ledger because its close time has come
|
||||
neACCEPTED_LEDGER = 2; // accepting a closed ledger, we have finished computing it
|
||||
neSWITCHED_LEDGER = 3; // changing due to network consensus
|
||||
neLOST_SYNC = 4;
|
||||
enum NodeEvent {
|
||||
neCLOSING_LEDGER = 1; // closing a ledger because its close time has come
|
||||
neACCEPTED_LEDGER = 2; // accepting a closed ledger, we have finished computing it
|
||||
neSWITCHED_LEDGER = 3; // changing due to network consensus
|
||||
neLOST_SYNC = 4;
|
||||
}
|
||||
|
||||
message TMStatusChange
|
||||
{
|
||||
optional NodeStatus newStatus = 1;
|
||||
optional NodeEvent newEvent = 2;
|
||||
optional uint32 ledgerSeq = 3;
|
||||
optional bytes ledgerHash = 4;
|
||||
optional bytes ledgerHashPrevious = 5;
|
||||
optional uint64 networkTime = 6;
|
||||
optional uint32 firstSeq = 7;
|
||||
optional uint32 lastSeq = 8;
|
||||
message TMStatusChange {
|
||||
optional NodeStatus newStatus = 1;
|
||||
optional NodeEvent newEvent = 2;
|
||||
optional uint32 ledgerSeq = 3;
|
||||
optional bytes ledgerHash = 4;
|
||||
optional bytes ledgerHashPrevious = 5;
|
||||
optional uint64 networkTime = 6;
|
||||
optional uint32 firstSeq = 7;
|
||||
optional uint32 lastSeq = 8;
|
||||
}
|
||||
|
||||
|
||||
// Announce to the network our position on a closing ledger
|
||||
message TMProposeSet
|
||||
{
|
||||
required uint32 proposeSeq = 1;
|
||||
required bytes currentTxHash = 2; // the hash of the ledger we are proposing
|
||||
required bytes nodePubKey = 3;
|
||||
required uint32 closeTime = 4;
|
||||
required bytes signature = 5; // signature of above fields
|
||||
required bytes previousledger = 6;
|
||||
repeated bytes addedTransactions = 10; // not required if number is large
|
||||
repeated bytes removedTransactions = 11; // not required if number is large
|
||||
message TMProposeSet {
|
||||
required uint32 proposeSeq = 1;
|
||||
required bytes currentTxHash = 2; // the hash of the ledger we are proposing
|
||||
required bytes nodePubKey = 3;
|
||||
required uint32 closeTime = 4;
|
||||
required bytes signature = 5; // signature of above fields
|
||||
required bytes previousledger = 6;
|
||||
repeated bytes addedTransactions = 10; // not required if number is large
|
||||
repeated bytes removedTransactions = 11; // not required if number is large
|
||||
|
||||
// node vouches signature is correct
|
||||
optional bool checkedSignature = 7 [deprecated=true];
|
||||
// node vouches signature is correct
|
||||
optional bool checkedSignature = 7 [deprecated = true];
|
||||
|
||||
// Number of hops traveled
|
||||
optional uint32 hops = 12 [deprecated=true];
|
||||
// Number of hops traveled
|
||||
optional uint32 hops = 12 [deprecated = true];
|
||||
}
|
||||
|
||||
enum TxSetStatus
|
||||
{
|
||||
tsHAVE = 1; // We have this set locally
|
||||
tsCAN_GET = 2; // We have a peer with this set
|
||||
tsNEED = 3; // We need this set and can't get it
|
||||
enum TxSetStatus {
|
||||
tsHAVE = 1; // We have this set locally
|
||||
tsCAN_GET = 2; // We have a peer with this set
|
||||
tsNEED = 3; // We need this set and can't get it
|
||||
}
|
||||
|
||||
message TMHaveTransactionSet
|
||||
{
|
||||
required TxSetStatus status = 1;
|
||||
required bytes hash = 2;
|
||||
message TMHaveTransactionSet {
|
||||
required TxSetStatus status = 1;
|
||||
required bytes hash = 2;
|
||||
}
|
||||
|
||||
// Validator list (UNL)
|
||||
message TMValidatorList
|
||||
{
|
||||
required bytes manifest = 1;
|
||||
required bytes blob = 2;
|
||||
required bytes signature = 3;
|
||||
required uint32 version = 4;
|
||||
message TMValidatorList {
|
||||
required bytes manifest = 1;
|
||||
required bytes blob = 2;
|
||||
required bytes signature = 3;
|
||||
required uint32 version = 4;
|
||||
}
|
||||
|
||||
// Validator List v2
|
||||
message ValidatorBlobInfo
|
||||
{
|
||||
optional bytes manifest = 1;
|
||||
required bytes blob = 2;
|
||||
required bytes signature = 3;
|
||||
message ValidatorBlobInfo {
|
||||
optional bytes manifest = 1;
|
||||
required bytes blob = 2;
|
||||
required bytes signature = 3;
|
||||
}
|
||||
|
||||
// Collection of Validator List v2 (UNL)
|
||||
message TMValidatorListCollection
|
||||
{
|
||||
required uint32 version = 1;
|
||||
required bytes manifest = 2;
|
||||
repeated ValidatorBlobInfo blobs = 3;
|
||||
message TMValidatorListCollection {
|
||||
required uint32 version = 1;
|
||||
required bytes manifest = 2;
|
||||
repeated ValidatorBlobInfo blobs = 3;
|
||||
}
|
||||
|
||||
// Used to sign a final closed ledger after reprocessing
|
||||
message TMValidation
|
||||
{
|
||||
// The serialized validation
|
||||
required bytes validation = 1;
|
||||
message TMValidation {
|
||||
// The serialized validation
|
||||
required bytes validation = 1;
|
||||
|
||||
// node vouches signature is correct
|
||||
optional bool checkedSignature = 2 [deprecated = true];
|
||||
// node vouches signature is correct
|
||||
optional bool checkedSignature = 2 [deprecated = true];
|
||||
|
||||
// Number of hops traveled
|
||||
optional uint32 hops = 3 [deprecated = true];
|
||||
// Number of hops traveled
|
||||
optional uint32 hops = 3 [deprecated = true];
|
||||
}
|
||||
|
||||
// An array of Endpoint messages
|
||||
message TMEndpoints
|
||||
{
|
||||
// Previously used - don't reuse.
|
||||
reserved 2;
|
||||
message TMEndpoints {
|
||||
// Previously used - don't reuse.
|
||||
reserved 2;
|
||||
|
||||
// This field is used to allow the TMEndpoints message format to be
|
||||
// modified as necessary in the future.
|
||||
required uint32 version = 1;
|
||||
// This field is used to allow the TMEndpoints message format to be
|
||||
// modified as necessary in the future.
|
||||
required uint32 version = 1;
|
||||
|
||||
// An update to the Endpoint type that uses a string
|
||||
// to represent endpoints, thus allowing ipv6 or ipv4 addresses
|
||||
message TMEndpointv2
|
||||
{
|
||||
required string endpoint = 1;
|
||||
required uint32 hops = 2;
|
||||
}
|
||||
repeated TMEndpointv2 endpoints_v2 = 3;
|
||||
// An update to the Endpoint type that uses a string
|
||||
// to represent endpoints, thus allowing ipv6 or ipv4 addresses
|
||||
message TMEndpointv2 {
|
||||
required string endpoint = 1;
|
||||
required uint32 hops = 2;
|
||||
}
|
||||
repeated TMEndpointv2 endpoints_v2 = 3;
|
||||
};
|
||||
|
||||
message TMIndexedObject
|
||||
{
|
||||
optional bytes hash = 1;
|
||||
optional bytes nodeID = 2;
|
||||
optional bytes index = 3;
|
||||
optional bytes data = 4;
|
||||
optional uint32 ledgerSeq = 5;
|
||||
message TMIndexedObject {
|
||||
optional bytes hash = 1;
|
||||
optional bytes nodeID = 2;
|
||||
optional bytes index = 3;
|
||||
optional bytes data = 4;
|
||||
optional uint32 ledgerSeq = 5;
|
||||
}
|
||||
|
||||
message TMGetObjectByHash
|
||||
{
|
||||
enum ObjectType {
|
||||
otUNKNOWN = 0;
|
||||
otLEDGER = 1;
|
||||
otTRANSACTION = 2;
|
||||
otTRANSACTION_NODE = 3;
|
||||
otSTATE_NODE = 4;
|
||||
otCAS_OBJECT = 5;
|
||||
otFETCH_PACK = 6;
|
||||
otTRANSACTIONS = 7;
|
||||
}
|
||||
message TMGetObjectByHash {
|
||||
enum ObjectType {
|
||||
otUNKNOWN = 0;
|
||||
otLEDGER = 1;
|
||||
otTRANSACTION = 2;
|
||||
otTRANSACTION_NODE = 3;
|
||||
otSTATE_NODE = 4;
|
||||
otCAS_OBJECT = 5;
|
||||
otFETCH_PACK = 6;
|
||||
otTRANSACTIONS = 7;
|
||||
}
|
||||
|
||||
required ObjectType type = 1;
|
||||
required bool query = 2; // is this a query or a reply?
|
||||
optional uint32 seq = 3; // used to match replies to queries
|
||||
optional bytes ledgerHash = 4; // the hash of the ledger these queries are for
|
||||
optional bool fat = 5; // return related nodes
|
||||
repeated TMIndexedObject objects = 6; // the specific objects requested
|
||||
required ObjectType type = 1;
|
||||
required bool query = 2; // is this a query or a reply?
|
||||
optional uint32 seq = 3; // used to match replies to queries
|
||||
optional bytes ledgerHash = 4; // the hash of the ledger these queries are for
|
||||
optional bool fat = 5; // return related nodes
|
||||
repeated TMIndexedObject objects = 6; // the specific objects requested
|
||||
}
|
||||
|
||||
|
||||
message TMLedgerNode
|
||||
{
|
||||
required bytes nodedata = 1;
|
||||
optional bytes nodeid = 2; // missing for ledger base data
|
||||
message TMLedgerNode {
|
||||
required bytes nodedata = 1;
|
||||
optional bytes nodeid = 2; // missing for ledger base data
|
||||
}
|
||||
|
||||
enum TMLedgerInfoType
|
||||
{
|
||||
liBASE = 0; // basic ledger info
|
||||
liTX_NODE = 1; // transaction node
|
||||
liAS_NODE = 2; // account state node
|
||||
liTS_CANDIDATE = 3; // candidate transaction set
|
||||
enum TMLedgerInfoType {
|
||||
liBASE = 0; // basic ledger info
|
||||
liTX_NODE = 1; // transaction node
|
||||
liAS_NODE = 2; // account state node
|
||||
liTS_CANDIDATE = 3; // candidate transaction set
|
||||
}
|
||||
|
||||
enum TMLedgerType
|
||||
{
|
||||
ltACCEPTED = 0;
|
||||
ltCURRENT = 1; // no longer supported
|
||||
ltCLOSED = 2;
|
||||
enum TMLedgerType {
|
||||
ltACCEPTED = 0;
|
||||
ltCURRENT = 1; // no longer supported
|
||||
ltCLOSED = 2;
|
||||
}
|
||||
|
||||
enum TMQueryType
|
||||
{
|
||||
qtINDIRECT = 0;
|
||||
enum TMQueryType {
|
||||
qtINDIRECT = 0;
|
||||
}
|
||||
|
||||
message TMGetLedger
|
||||
{
|
||||
required TMLedgerInfoType itype = 1;
|
||||
optional TMLedgerType ltype = 2;
|
||||
optional bytes ledgerHash = 3; // Can also be the transaction set hash if liTS_CANDIDATE
|
||||
optional uint32 ledgerSeq = 4;
|
||||
repeated bytes nodeIDs = 5;
|
||||
optional uint64 requestCookie = 6;
|
||||
optional TMQueryType queryType = 7;
|
||||
optional uint32 queryDepth = 8; // How deep to go, number of extra levels
|
||||
message TMGetLedger {
|
||||
required TMLedgerInfoType itype = 1;
|
||||
optional TMLedgerType ltype = 2;
|
||||
optional bytes ledgerHash = 3; // Can also be the transaction set hash if liTS_CANDIDATE
|
||||
optional uint32 ledgerSeq = 4;
|
||||
repeated bytes nodeIDs = 5;
|
||||
optional uint64 requestCookie = 6;
|
||||
optional TMQueryType queryType = 7;
|
||||
optional uint32 queryDepth = 8; // How deep to go, number of extra levels
|
||||
}
|
||||
|
||||
enum TMReplyError
|
||||
{
|
||||
reNO_LEDGER = 1; // We don't have the ledger you are asking about
|
||||
reNO_NODE = 2; // We don't have any of the nodes you are asking for
|
||||
reBAD_REQUEST = 3; // The request is wrong, e.g. wrong format
|
||||
enum TMReplyError {
|
||||
reNO_LEDGER = 1; // We don't have the ledger you are asking about
|
||||
reNO_NODE = 2; // We don't have any of the nodes you are asking for
|
||||
reBAD_REQUEST = 3; // The request is wrong, e.g. wrong format
|
||||
}
|
||||
|
||||
message TMLedgerData
|
||||
{
|
||||
required bytes ledgerHash = 1;
|
||||
required uint32 ledgerSeq = 2;
|
||||
required TMLedgerInfoType type = 3;
|
||||
repeated TMLedgerNode nodes = 4;
|
||||
optional uint32 requestCookie = 5;
|
||||
optional TMReplyError error = 6;
|
||||
message TMLedgerData {
|
||||
required bytes ledgerHash = 1;
|
||||
required uint32 ledgerSeq = 2;
|
||||
required TMLedgerInfoType type = 3;
|
||||
repeated TMLedgerNode nodes = 4;
|
||||
optional uint32 requestCookie = 5;
|
||||
optional TMReplyError error = 6;
|
||||
}
|
||||
|
||||
message TMPing
|
||||
{
|
||||
enum pingType {
|
||||
ptPING = 0; // we want a reply
|
||||
ptPONG = 1; // this is a reply
|
||||
}
|
||||
required pingType type = 1;
|
||||
optional uint32 seq = 2; // detect stale replies, ensure other side is reading
|
||||
optional uint64 pingTime = 3; // know when we think we sent the ping
|
||||
optional uint64 netTime = 4;
|
||||
message TMPing {
|
||||
enum pingType {
|
||||
ptPING = 0; // we want a reply
|
||||
ptPONG = 1; // this is a reply
|
||||
}
|
||||
required pingType type = 1;
|
||||
optional uint32 seq = 2; // detect stale replies, ensure other side is reading
|
||||
optional uint64 pingTime = 3; // know when we think we sent the ping
|
||||
optional uint64 netTime = 4;
|
||||
}
|
||||
|
||||
message TMSquelch
|
||||
{
|
||||
required bool squelch = 1; // squelch if true, otherwise unsquelch
|
||||
required bytes validatorPubKey = 2; // validator's public key
|
||||
optional uint32 squelchDuration = 3; // squelch duration in seconds
|
||||
message TMSquelch {
|
||||
required bool squelch = 1; // squelch if true, otherwise unsquelch
|
||||
required bytes validatorPubKey = 2; // validator's public key
|
||||
optional uint32 squelchDuration = 3; // squelch duration in seconds
|
||||
}
|
||||
|
||||
enum TMLedgerMapType
|
||||
{
|
||||
lmTRANASCTION = 1; // transaction map
|
||||
lmACCOUNT_STATE = 2; // account state map
|
||||
enum TMLedgerMapType {
|
||||
lmTRANASCTION = 1; // transaction map
|
||||
lmACCOUNT_STATE = 2; // account state map
|
||||
}
|
||||
|
||||
message TMProofPathRequest
|
||||
{
|
||||
required bytes key = 1;
|
||||
required bytes ledgerHash = 2;
|
||||
required TMLedgerMapType type = 3;
|
||||
message TMProofPathRequest {
|
||||
required bytes key = 1;
|
||||
required bytes ledgerHash = 2;
|
||||
required TMLedgerMapType type = 3;
|
||||
}
|
||||
|
||||
message TMProofPathResponse
|
||||
{
|
||||
required bytes key = 1;
|
||||
required bytes ledgerHash = 2;
|
||||
required TMLedgerMapType type = 3;
|
||||
optional bytes ledgerHeader = 4;
|
||||
repeated bytes path = 5;
|
||||
optional TMReplyError error = 6;
|
||||
message TMProofPathResponse {
|
||||
required bytes key = 1;
|
||||
required bytes ledgerHash = 2;
|
||||
required TMLedgerMapType type = 3;
|
||||
optional bytes ledgerHeader = 4;
|
||||
repeated bytes path = 5;
|
||||
optional TMReplyError error = 6;
|
||||
}
|
||||
|
||||
message TMReplayDeltaRequest
|
||||
{
|
||||
required bytes ledgerHash = 1;
|
||||
message TMReplayDeltaRequest {
|
||||
required bytes ledgerHash = 1;
|
||||
}
|
||||
|
||||
message TMReplayDeltaResponse
|
||||
{
|
||||
required bytes ledgerHash = 1;
|
||||
optional bytes ledgerHeader = 2;
|
||||
repeated bytes transaction = 3;
|
||||
optional TMReplyError error = 4;
|
||||
message TMReplayDeltaResponse {
|
||||
required bytes ledgerHash = 1;
|
||||
optional bytes ledgerHeader = 2;
|
||||
repeated bytes transaction = 3;
|
||||
optional TMReplyError error = 4;
|
||||
}
|
||||
|
||||
message TMHaveTransactions
|
||||
{
|
||||
repeated bytes hashes = 1;
|
||||
message TMHaveTransactions {
|
||||
repeated bytes hashes = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,14 +48,6 @@ class STObject;
|
||||
class STAmount;
|
||||
class Rules;
|
||||
|
||||
/** Calculate AMM account ID.
|
||||
*/
|
||||
AccountID
|
||||
ammAccountID(
|
||||
std::uint16_t prefix,
|
||||
uint256 const& parentHash,
|
||||
uint256 const& ammID);
|
||||
|
||||
/** Calculate Liquidity Provider Token (LPT) Currency.
|
||||
*/
|
||||
Currency
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <xrpl/protocol/json_get_or_throw.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
@@ -149,7 +148,7 @@ namespace std {
|
||||
template <>
|
||||
struct hash<ripple::AccountID> : ripple::AccountID::hasher
|
||||
{
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef RIPPLE_PROTOCOL_ASSET_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_ASSET_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
@@ -27,6 +28,7 @@
|
||||
namespace ripple {
|
||||
|
||||
class Asset;
|
||||
class STAmount;
|
||||
|
||||
template <typename TIss>
|
||||
concept ValidIssueType =
|
||||
@@ -92,6 +94,9 @@ public:
|
||||
void
|
||||
setJson(Json::Value& jv) const;
|
||||
|
||||
STAmount
|
||||
operator()(Number const&) const;
|
||||
|
||||
bool
|
||||
native() const
|
||||
{
|
||||
@@ -114,6 +119,14 @@ public:
|
||||
equalTokens(Asset const& lhs, Asset const& rhs);
|
||||
};
|
||||
|
||||
inline Json::Value
|
||||
to_json(Asset const& asset)
|
||||
{
|
||||
Json::Value jv;
|
||||
asset.setJson(jv);
|
||||
return jv;
|
||||
}
|
||||
|
||||
template <ValidIssueType TIss>
|
||||
constexpr bool
|
||||
Asset::holds() const
|
||||
@@ -219,9 +232,6 @@ validJSONAsset(Json::Value const& jv);
|
||||
Asset
|
||||
assetFromJson(Json::Value const& jv);
|
||||
|
||||
Json::Value
|
||||
to_json(Asset const& asset);
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif // RIPPLE_PROTOCOL_ASSET_H_INCLUDED
|
||||
|
||||
37
include/xrpl/protocol/Batch.h
Normal file
37
include/xrpl/protocol/Batch.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2024 Ripple Labs Inc.
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
inline void
|
||||
serializeBatch(
|
||||
Serializer& msg,
|
||||
std::uint32_t const& flags,
|
||||
std::vector<uint256> const& txids)
|
||||
{
|
||||
msg.add32(HashPrefix::batch);
|
||||
msg.add32(flags);
|
||||
msg.add32(std::uint32_t(txids.size()));
|
||||
for (auto const& txid : txids)
|
||||
msg.addBitString(txid);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_PROTOCOL_BOOK_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
@@ -36,12 +37,17 @@ class Book final : public CountedObject<Book>
|
||||
public:
|
||||
Issue in;
|
||||
Issue out;
|
||||
std::optional<uint256> domain;
|
||||
|
||||
Book()
|
||||
{
|
||||
}
|
||||
|
||||
Book(Issue const& in_, Issue const& out_) : in(in_), out(out_)
|
||||
Book(
|
||||
Issue const& in_,
|
||||
Issue const& out_,
|
||||
std::optional<uint256> const& domain_)
|
||||
: in(in_), out(out_), domain(domain_)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -61,6 +67,8 @@ hash_append(Hasher& h, Book const& b)
|
||||
{
|
||||
using beast::hash_append;
|
||||
hash_append(h, b.in, b.out);
|
||||
if (b.domain)
|
||||
hash_append(h, *(b.domain));
|
||||
}
|
||||
|
||||
Book
|
||||
@@ -71,7 +79,8 @@ reversed(Book const& book);
|
||||
[[nodiscard]] inline constexpr bool
|
||||
operator==(Book const& lhs, Book const& rhs)
|
||||
{
|
||||
return (lhs.in == rhs.in) && (lhs.out == rhs.out);
|
||||
return (lhs.in == rhs.in) && (lhs.out == rhs.out) &&
|
||||
(lhs.domain == rhs.domain);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
@@ -82,7 +91,18 @@ operator<=>(Book const& lhs, Book const& rhs)
|
||||
{
|
||||
if (auto const c{lhs.in <=> rhs.in}; c != 0)
|
||||
return c;
|
||||
return lhs.out <=> rhs.out;
|
||||
if (auto const c{lhs.out <=> rhs.out}; c != 0)
|
||||
return c;
|
||||
|
||||
// Manually compare optionals
|
||||
if (lhs.domain && rhs.domain)
|
||||
return *lhs.domain <=> *rhs.domain; // Compare values if both exist
|
||||
if (!lhs.domain && rhs.domain)
|
||||
return std::weak_ordering::less; // Empty is considered less
|
||||
if (lhs.domain && !rhs.domain)
|
||||
return std::weak_ordering::greater; // Non-empty is greater
|
||||
|
||||
return std::weak_ordering::equivalent; // Both are empty
|
||||
}
|
||||
/** @} */
|
||||
|
||||
@@ -104,7 +124,7 @@ private:
|
||||
boost::base_from_member<std::hash<ripple::AccountID>, 1>;
|
||||
|
||||
public:
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
using value_type = std::size_t;
|
||||
using argument_type = ripple::Issue;
|
||||
@@ -126,12 +146,14 @@ template <>
|
||||
struct hash<ripple::Book>
|
||||
{
|
||||
private:
|
||||
using hasher = std::hash<ripple::Issue>;
|
||||
using issue_hasher = std::hash<ripple::Issue>;
|
||||
using uint256_hasher = ripple::uint256::hasher;
|
||||
|
||||
hasher m_hasher;
|
||||
issue_hasher m_issue_hasher;
|
||||
uint256_hasher m_uint256_hasher;
|
||||
|
||||
public:
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
using value_type = std::size_t;
|
||||
using argument_type = ripple::Book;
|
||||
@@ -139,8 +161,12 @@ public:
|
||||
value_type
|
||||
operator()(argument_type const& value) const
|
||||
{
|
||||
value_type result(m_hasher(value.in));
|
||||
boost::hash_combine(result, m_hasher(value.out));
|
||||
value_type result(m_issue_hasher(value.in));
|
||||
boost::hash_combine(result, m_issue_hasher(value.out));
|
||||
|
||||
if (value.domain)
|
||||
boost::hash_combine(result, m_uint256_hasher(*value.domain));
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -154,7 +180,7 @@ namespace boost {
|
||||
template <>
|
||||
struct hash<ripple::Issue> : std::hash<ripple::Issue>
|
||||
{
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
using Base = std::hash<ripple::Issue>;
|
||||
// VFALCO NOTE broken in vs2012
|
||||
@@ -164,7 +190,7 @@ struct hash<ripple::Issue> : std::hash<ripple::Issue>
|
||||
template <>
|
||||
struct hash<ripple::Book> : std::hash<ripple::Book>
|
||||
{
|
||||
explicit hash() = default;
|
||||
hash() = default;
|
||||
|
||||
using Base = std::hash<ripple::Book>;
|
||||
// VFALCO NOTE broken in vs2012
|
||||
|
||||
@@ -120,7 +120,7 @@ enum error_code_i {
|
||||
rpcSRC_ACT_MALFORMED = 65,
|
||||
rpcSRC_ACT_MISSING = 66,
|
||||
rpcSRC_ACT_NOT_FOUND = 67,
|
||||
// unused 68,
|
||||
rpcDELEGATE_ACT_NOT_FOUND = 68,
|
||||
rpcSRC_CUR_MALFORMED = 69,
|
||||
rpcSRC_ISR_MALFORMED = 70,
|
||||
rpcSTREAM_MALFORMED = 71,
|
||||
@@ -154,7 +154,15 @@ enum error_code_i {
|
||||
// Simulate
|
||||
rpcTX_SIGNED = 96,
|
||||
|
||||
rpcLAST = rpcTX_SIGNED // rpcLAST should always equal the last code.
|
||||
// Pathfinding
|
||||
rpcDOMAIN_MALFORMED = 97,
|
||||
|
||||
// ledger_entry
|
||||
rpcENTRY_NOT_FOUND = 98,
|
||||
rpcUNEXPECTED_LEDGER_TYPE = 99,
|
||||
|
||||
rpcLAST =
|
||||
rpcUNEXPECTED_LEDGER_TYPE // rpcLAST should always equal the last code.
|
||||
};
|
||||
|
||||
/** Codes returned in the `warnings` array of certain RPC commands.
|
||||
@@ -166,6 +174,8 @@ enum warning_code_i {
|
||||
warnRPC_AMENDMENT_BLOCKED = 1002,
|
||||
warnRPC_EXPIRED_VALIDATOR_LIST = 1003,
|
||||
// unused = 1004
|
||||
warnRPC_FIELDS_DEPRECATED = 2004, // rippled needs to maintain
|
||||
// compatibility with Clio on this code.
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <boost/container/flat_map.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
@@ -54,6 +53,18 @@
|
||||
* then change the macro parameter in features.macro to
|
||||
* `VoteBehavior::DefaultYes`. The communication process is beyond
|
||||
* the scope of these instructions.
|
||||
|
||||
* 5) If a supported feature (`Supported::yes`) was _ever_ in a released
|
||||
* version, it can never be changed back to `Supported::no`, because
|
||||
* it _may_ still become enabled at any time. This would cause newer
|
||||
* versions of `rippled` to become amendment blocked.
|
||||
* Instead, to prevent newer versions from voting on the feature, use
|
||||
* `VoteBehavior::Obsolete`. Obsolete features can not be voted for
|
||||
* by any versions of `rippled` built with that setting, but will still
|
||||
* work correctly if they get enabled. If a feature remains obsolete
|
||||
* for long enough that _all_ clients that could vote for it are
|
||||
* amendment blocked, the feature can be removed from the code
|
||||
* as if it was unsupported.
|
||||
*
|
||||
*
|
||||
* When a feature has been enabled for several years, the conditional code
|
||||
|
||||
@@ -1,570 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2019 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BASICS_FEES_H_INCLUDED
|
||||
#define BASICS_FEES_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <ios>
|
||||
#include <iosfwd>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace feeunit {
|
||||
|
||||
/** "drops" are the smallest divisible amount of XRP. This is what most
|
||||
of the code uses. */
|
||||
struct dropTag;
|
||||
/** "fee units" calculations are a not-really-unitless value that is used
|
||||
to express the cost of a given transaction vs. a reference transaction.
|
||||
They are primarily used by the Transactor classes. */
|
||||
struct feeunitTag;
|
||||
/** "fee levels" are used by the transaction queue to compare the relative
|
||||
cost of transactions that require different levels of effort to process.
|
||||
See also: src/ripple/app/misc/FeeEscalation.md#fee-level */
|
||||
struct feelevelTag;
|
||||
/** unitless values are plain scalars wrapped in a TaggedFee. They are
|
||||
used for calculations in this header. */
|
||||
struct unitlessTag;
|
||||
|
||||
template <class T>
|
||||
using enable_if_unit_t = typename std::enable_if_t<
|
||||
std::is_class_v<T> && std::is_object_v<typename T::unit_type> &&
|
||||
std::is_object_v<typename T::value_type>>;
|
||||
|
||||
/** `is_usable_unit_v` is checked to ensure that only values with
|
||||
known valid type tags can be used (sometimes transparently) in
|
||||
non-fee contexts. At the time of implementation, this includes
|
||||
all known tags, but more may be added in the future, and they
|
||||
should not be added automatically unless determined to be
|
||||
appropriate.
|
||||
*/
|
||||
template <class T, class = enable_if_unit_t<T>>
|
||||
constexpr bool is_usable_unit_v =
|
||||
std::is_same_v<typename T::unit_type, feeunitTag> ||
|
||||
std::is_same_v<typename T::unit_type, feelevelTag> ||
|
||||
std::is_same_v<typename T::unit_type, unitlessTag> ||
|
||||
std::is_same_v<typename T::unit_type, dropTag>;
|
||||
|
||||
template <class UnitTag, class T>
|
||||
class TaggedFee : private boost::totally_ordered<TaggedFee<UnitTag, T>>,
|
||||
private boost::additive<TaggedFee<UnitTag, T>>,
|
||||
private boost::equality_comparable<TaggedFee<UnitTag, T>, T>,
|
||||
private boost::dividable<TaggedFee<UnitTag, T>, T>,
|
||||
private boost::modable<TaggedFee<UnitTag, T>, T>,
|
||||
private boost::unit_steppable<TaggedFee<UnitTag, T>>
|
||||
{
|
||||
public:
|
||||
using unit_type = UnitTag;
|
||||
using value_type = T;
|
||||
|
||||
private:
|
||||
value_type fee_;
|
||||
|
||||
protected:
|
||||
template <class Other>
|
||||
static constexpr bool is_compatible_v =
|
||||
std::is_arithmetic_v<Other> && std::is_arithmetic_v<value_type> &&
|
||||
std::is_convertible_v<Other, value_type>;
|
||||
|
||||
template <class OtherFee, class = enable_if_unit_t<OtherFee>>
|
||||
static constexpr bool is_compatiblefee_v =
|
||||
is_compatible_v<typename OtherFee::value_type> &&
|
||||
std::is_same_v<UnitTag, typename OtherFee::unit_type>;
|
||||
|
||||
template <class Other>
|
||||
using enable_if_compatible_t =
|
||||
typename std::enable_if_t<is_compatible_v<Other>>;
|
||||
|
||||
template <class OtherFee>
|
||||
using enable_if_compatiblefee_t =
|
||||
typename std::enable_if_t<is_compatiblefee_v<OtherFee>>;
|
||||
|
||||
public:
|
||||
TaggedFee() = default;
|
||||
constexpr TaggedFee(TaggedFee const& other) = default;
|
||||
constexpr TaggedFee&
|
||||
operator=(TaggedFee const& other) = default;
|
||||
|
||||
constexpr explicit TaggedFee(beast::Zero) : fee_(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr TaggedFee&
|
||||
operator=(beast::Zero)
|
||||
{
|
||||
fee_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr explicit TaggedFee(value_type fee) : fee_(fee)
|
||||
{
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator=(value_type fee)
|
||||
{
|
||||
fee_ = fee;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Instances with the same unit, and a type that is
|
||||
"safe" to convert to this one can be converted
|
||||
implicitly */
|
||||
template <
|
||||
class Other,
|
||||
class = std::enable_if_t<
|
||||
is_compatible_v<Other> &&
|
||||
is_safetocasttovalue_v<value_type, Other>>>
|
||||
constexpr TaggedFee(TaggedFee<unit_type, Other> const& fee)
|
||||
: TaggedFee(safe_cast<value_type>(fee.fee()))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr TaggedFee
|
||||
operator*(value_type const& rhs) const
|
||||
{
|
||||
return TaggedFee{fee_ * rhs};
|
||||
}
|
||||
|
||||
friend constexpr TaggedFee
|
||||
operator*(value_type lhs, TaggedFee const& rhs)
|
||||
{
|
||||
// multiplication is commutative
|
||||
return rhs * lhs;
|
||||
}
|
||||
|
||||
constexpr value_type
|
||||
operator/(TaggedFee const& rhs) const
|
||||
{
|
||||
return fee_ / rhs.fee_;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator+=(TaggedFee const& other)
|
||||
{
|
||||
fee_ += other.fee();
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator-=(TaggedFee const& other)
|
||||
{
|
||||
fee_ -= other.fee();
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator++()
|
||||
{
|
||||
++fee_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator--()
|
||||
{
|
||||
--fee_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator*=(value_type const& rhs)
|
||||
{
|
||||
fee_ *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee&
|
||||
operator/=(value_type const& rhs)
|
||||
{
|
||||
fee_ /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class transparent = value_type>
|
||||
std::enable_if_t<std::is_integral_v<transparent>, TaggedFee&>
|
||||
operator%=(value_type const& rhs)
|
||||
{
|
||||
fee_ %= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaggedFee
|
||||
operator-() const
|
||||
{
|
||||
static_assert(
|
||||
std::is_signed_v<T>, "- operator illegal on unsigned fee types");
|
||||
return TaggedFee{-fee_};
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(TaggedFee const& other) const
|
||||
{
|
||||
return fee_ == other.fee_;
|
||||
}
|
||||
|
||||
template <class Other, class = enable_if_compatible_t<Other>>
|
||||
bool
|
||||
operator==(TaggedFee<unit_type, Other> const& other) const
|
||||
{
|
||||
return fee_ == other.fee();
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(value_type other) const
|
||||
{
|
||||
return fee_ == other;
|
||||
}
|
||||
|
||||
template <class Other, class = enable_if_compatible_t<Other>>
|
||||
bool
|
||||
operator!=(TaggedFee<unit_type, Other> const& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(TaggedFee const& other) const
|
||||
{
|
||||
return fee_ < other.fee_;
|
||||
}
|
||||
|
||||
/** Returns true if the amount is not zero */
|
||||
explicit constexpr
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return fee_ != 0;
|
||||
}
|
||||
|
||||
/** Return the sign of the amount */
|
||||
constexpr int
|
||||
signum() const noexcept
|
||||
{
|
||||
return (fee_ < 0) ? -1 : (fee_ ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Returns the number of drops */
|
||||
constexpr value_type
|
||||
fee() const
|
||||
{
|
||||
return fee_;
|
||||
}
|
||||
|
||||
template <class Other>
|
||||
constexpr double
|
||||
decimalFromReference(TaggedFee<unit_type, Other> reference) const
|
||||
{
|
||||
return static_cast<double>(fee_) / reference.fee();
|
||||
}
|
||||
|
||||
// `is_usable_unit_v` is checked to ensure that only values with
|
||||
// known valid type tags can be converted to JSON. At the time
|
||||
// of implementation, that includes all known tags, but more may
|
||||
// be added in the future.
|
||||
std::enable_if_t<is_usable_unit_v<TaggedFee>, Json::Value>
|
||||
jsonClipped() const
|
||||
{
|
||||
if constexpr (std::is_integral_v<value_type>)
|
||||
{
|
||||
using jsontype = std::conditional_t<
|
||||
std::is_signed_v<value_type>,
|
||||
Json::Int,
|
||||
Json::UInt>;
|
||||
|
||||
constexpr auto min = std::numeric_limits<jsontype>::min();
|
||||
constexpr auto max = std::numeric_limits<jsontype>::max();
|
||||
|
||||
if (fee_ < min)
|
||||
return min;
|
||||
if (fee_ > max)
|
||||
return max;
|
||||
return static_cast<jsontype>(fee_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return fee_;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the underlying value. Code SHOULD NOT call this
|
||||
function unless the type has been abstracted away,
|
||||
e.g. in a templated function.
|
||||
*/
|
||||
constexpr value_type
|
||||
value() const
|
||||
{
|
||||
return fee_;
|
||||
}
|
||||
|
||||
friend std::istream&
|
||||
operator>>(std::istream& s, TaggedFee& val)
|
||||
{
|
||||
s >> val.fee_;
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// Output Fees as just their numeric value.
|
||||
template <class Char, class Traits, class UnitTag, class T>
|
||||
std::basic_ostream<Char, Traits>&
|
||||
operator<<(std::basic_ostream<Char, Traits>& os, const TaggedFee<UnitTag, T>& q)
|
||||
{
|
||||
return os << q.value();
|
||||
}
|
||||
|
||||
template <class UnitTag, class T>
|
||||
std::string
|
||||
to_string(TaggedFee<UnitTag, T> const& amount)
|
||||
{
|
||||
return std::to_string(amount.fee());
|
||||
}
|
||||
|
||||
template <class Source, class = enable_if_unit_t<Source>>
|
||||
constexpr bool can_muldiv_source_v =
|
||||
std::is_convertible_v<typename Source::value_type, std::uint64_t>;
|
||||
|
||||
template <class Dest, class = enable_if_unit_t<Dest>>
|
||||
constexpr bool can_muldiv_dest_v =
|
||||
can_muldiv_source_v<Dest> && // Dest is also a source
|
||||
std::is_convertible_v<std::uint64_t, typename Dest::value_type> &&
|
||||
sizeof(typename Dest::value_type) >= sizeof(std::uint64_t);
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class = enable_if_unit_t<Source1>,
|
||||
class = enable_if_unit_t<Source2>>
|
||||
constexpr bool can_muldiv_sources_v =
|
||||
can_muldiv_source_v<Source1> && can_muldiv_source_v<Source2> &&
|
||||
std::is_same_v<typename Source1::unit_type, typename Source2::unit_type>;
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class Dest,
|
||||
class = enable_if_unit_t<Source1>,
|
||||
class = enable_if_unit_t<Source2>,
|
||||
class = enable_if_unit_t<Dest>>
|
||||
constexpr bool can_muldiv_v =
|
||||
can_muldiv_sources_v<Source1, Source2> && can_muldiv_dest_v<Dest>;
|
||||
// Source and Dest can be the same by default
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class Dest,
|
||||
class = enable_if_unit_t<Source1>,
|
||||
class = enable_if_unit_t<Source2>,
|
||||
class = enable_if_unit_t<Dest>>
|
||||
constexpr bool can_muldiv_commute_v = can_muldiv_v<Source1, Source2, Dest> &&
|
||||
!std::is_same_v<typename Source1::unit_type, typename Dest::unit_type>;
|
||||
|
||||
template <class T>
|
||||
using enable_muldiv_source_t =
|
||||
typename std::enable_if_t<can_muldiv_source_v<T>>;
|
||||
|
||||
template <class T>
|
||||
using enable_muldiv_dest_t = typename std::enable_if_t<can_muldiv_dest_v<T>>;
|
||||
|
||||
template <class Source1, class Source2>
|
||||
using enable_muldiv_sources_t =
|
||||
typename std::enable_if_t<can_muldiv_sources_v<Source1, Source2>>;
|
||||
|
||||
template <class Source1, class Source2, class Dest>
|
||||
using enable_muldiv_t =
|
||||
typename std::enable_if_t<can_muldiv_v<Source1, Source2, Dest>>;
|
||||
|
||||
template <class Source1, class Source2, class Dest>
|
||||
using enable_muldiv_commute_t =
|
||||
typename std::enable_if_t<can_muldiv_commute_v<Source1, Source2, Dest>>;
|
||||
|
||||
template <class T>
|
||||
TaggedFee<unitlessTag, T>
|
||||
scalar(T value)
|
||||
{
|
||||
return TaggedFee<unitlessTag, T>{value};
|
||||
}
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class Dest,
|
||||
class = enable_muldiv_t<Source1, Source2, Dest>>
|
||||
std::optional<Dest>
|
||||
mulDivU(Source1 value, Dest mul, Source2 div)
|
||||
{
|
||||
// Fees can never be negative in any context.
|
||||
if (value.value() < 0 || mul.value() < 0 || div.value() < 0)
|
||||
{
|
||||
// split the asserts so if one hits, the user can tell which
|
||||
// without a debugger.
|
||||
XRPL_ASSERT(
|
||||
value.value() >= 0,
|
||||
"ripple::feeunit::mulDivU : minimum value input");
|
||||
XRPL_ASSERT(
|
||||
mul.value() >= 0, "ripple::feeunit::mulDivU : minimum mul input");
|
||||
XRPL_ASSERT(
|
||||
div.value() >= 0, "ripple::feeunit::mulDivU : minimum div input");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
using desttype = typename Dest::value_type;
|
||||
constexpr auto max = std::numeric_limits<desttype>::max();
|
||||
|
||||
// Shortcuts, since these happen a lot in the real world
|
||||
if (value == div)
|
||||
return mul;
|
||||
if (mul.value() == div.value())
|
||||
{
|
||||
if (value.value() > max)
|
||||
return std::nullopt;
|
||||
return Dest{static_cast<desttype>(value.value())};
|
||||
}
|
||||
|
||||
using namespace boost::multiprecision;
|
||||
|
||||
uint128_t product;
|
||||
product = multiply(
|
||||
product,
|
||||
static_cast<std::uint64_t>(value.value()),
|
||||
static_cast<std::uint64_t>(mul.value()));
|
||||
|
||||
auto quotient = product / div.value();
|
||||
|
||||
if (quotient > max)
|
||||
return std::nullopt;
|
||||
|
||||
return Dest{static_cast<desttype>(quotient)};
|
||||
}
|
||||
|
||||
} // namespace feeunit
|
||||
|
||||
template <class T>
|
||||
using FeeLevel = feeunit::TaggedFee<feeunit::feelevelTag, T>;
|
||||
using FeeLevel64 = FeeLevel<std::uint64_t>;
|
||||
using FeeLevelDouble = FeeLevel<double>;
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class Dest,
|
||||
class = feeunit::enable_muldiv_t<Source1, Source2, Dest>>
|
||||
std::optional<Dest>
|
||||
mulDiv(Source1 value, Dest mul, Source2 div)
|
||||
{
|
||||
return feeunit::mulDivU(value, mul, div);
|
||||
}
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class Dest,
|
||||
class = feeunit::enable_muldiv_commute_t<Source1, Source2, Dest>>
|
||||
std::optional<Dest>
|
||||
mulDiv(Dest value, Source1 mul, Source2 div)
|
||||
{
|
||||
// Multiplication is commutative
|
||||
return feeunit::mulDivU(mul, value, div);
|
||||
}
|
||||
|
||||
template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
|
||||
std::optional<Dest>
|
||||
mulDiv(std::uint64_t value, Dest mul, std::uint64_t div)
|
||||
{
|
||||
// Give the scalars a non-tag so the
|
||||
// unit-handling version gets called.
|
||||
return feeunit::mulDivU(feeunit::scalar(value), mul, feeunit::scalar(div));
|
||||
}
|
||||
|
||||
template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
|
||||
std::optional<Dest>
|
||||
mulDiv(Dest value, std::uint64_t mul, std::uint64_t div)
|
||||
{
|
||||
// Multiplication is commutative
|
||||
return mulDiv(mul, value, div);
|
||||
}
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
|
||||
std::optional<std::uint64_t>
|
||||
mulDiv(Source1 value, std::uint64_t mul, Source2 div)
|
||||
{
|
||||
// Give the scalars a dimensionless unit so the
|
||||
// unit-handling version gets called.
|
||||
auto unitresult = feeunit::mulDivU(value, feeunit::scalar(mul), div);
|
||||
|
||||
if (!unitresult)
|
||||
return std::nullopt;
|
||||
|
||||
return unitresult->value();
|
||||
}
|
||||
|
||||
template <
|
||||
class Source1,
|
||||
class Source2,
|
||||
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
|
||||
std::optional<std::uint64_t>
|
||||
mulDiv(std::uint64_t value, Source1 mul, Source2 div)
|
||||
{
|
||||
// Multiplication is commutative
|
||||
return mulDiv(mul, value, div);
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
|
||||
std::is_integral_v<typename Dest::value_type> &&
|
||||
std::is_integral_v<typename Src::value_type>,
|
||||
Dest>
|
||||
safe_cast(Src s) noexcept
|
||||
{
|
||||
// Dest may not have an explicit value constructor
|
||||
return Dest{safe_cast<typename Dest::value_type>(s.value())};
|
||||
}
|
||||
|
||||
template <class Dest, class Src>
|
||||
constexpr std::enable_if_t<
|
||||
std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
|
||||
std::is_integral_v<typename Dest::value_type> &&
|
||||
std::is_integral_v<typename Src::value_type>,
|
||||
Dest>
|
||||
unsafe_cast(Src s) noexcept
|
||||
{
|
||||
// Dest may not have an explicit value constructor
|
||||
return Dest{unsafe_cast<typename Dest::value_type>(s.value())};
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif // BASICS_FEES_H_INCLUDED
|
||||
@@ -88,6 +88,9 @@ enum class HashPrefix : std::uint32_t {
|
||||
|
||||
/** Credentials signature */
|
||||
credential = detail::make_hash_prefix('C', 'R', 'D'),
|
||||
|
||||
/** Batch */
|
||||
batch = detail::make_hash_prefix('B', 'C', 'H'),
|
||||
};
|
||||
|
||||
template <class Hasher>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -99,6 +98,12 @@ public:
|
||||
|
||||
static IOUAmount
|
||||
minPositiveAmount();
|
||||
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, IOUAmount const& x)
|
||||
{
|
||||
return os << to_string(x);
|
||||
}
|
||||
};
|
||||
|
||||
inline IOUAmount::IOUAmount(beast::Zero)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -279,12 +280,18 @@ amm(Asset const& issue1, Asset const& issue2) noexcept;
|
||||
Keylet
|
||||
amm(uint256 const& amm) noexcept;
|
||||
|
||||
/** A keylet for Delegate object */
|
||||
Keylet
|
||||
delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept;
|
||||
|
||||
Keylet
|
||||
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
|
||||
|
||||
// `seq` is stored as `sfXChainClaimID` in the object
|
||||
Keylet
|
||||
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
||||
|
||||
// `seq` is stored as `sfXChainAccountCreateCount` in the object
|
||||
Keylet
|
||||
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
||||
|
||||
@@ -330,6 +337,15 @@ mptoken(uint256 const& mptokenKey)
|
||||
Keylet
|
||||
mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept;
|
||||
|
||||
Keylet
|
||||
vault(AccountID const& owner, std::uint32_t seq) noexcept;
|
||||
|
||||
inline Keylet
|
||||
vault(uint256 const& vaultKey)
|
||||
{
|
||||
return {ltVAULT, vaultKey};
|
||||
}
|
||||
|
||||
Keylet
|
||||
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** A currency issued by an account.
|
||||
|
||||
@@ -56,7 +56,7 @@ enum LedgerEntryType : std::uint16_t
|
||||
#pragma push_macro("LEDGER_ENTRY")
|
||||
#undef LEDGER_ENTRY
|
||||
|
||||
#define LEDGER_ENTRY(tag, value, name, rpcName, fields) tag = value,
|
||||
#define LEDGER_ENTRY(tag, value, ...) tag = value,
|
||||
|
||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||
|
||||
@@ -132,7 +132,7 @@ enum LedgerSpecificFlags {
|
||||
lsfNoFreeze = 0x00200000, // True, cannot freeze ripple states
|
||||
lsfGlobalFreeze = 0x00400000, // True, all assets frozen
|
||||
lsfDefaultRipple =
|
||||
0x00800000, // True, trust lines allow rippling by default
|
||||
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
|
||||
@@ -145,13 +145,15 @@ enum LedgerSpecificFlags {
|
||||
0x10000000, // True, reject new paychans
|
||||
lsfDisallowIncomingTrustline =
|
||||
0x20000000, // True, reject new trustlines (only if no issued assets)
|
||||
// 0x40000000 is available
|
||||
lsfAllowTrustLineLocking =
|
||||
0x40000000, // True, enable trustline locking
|
||||
lsfAllowTrustLineClawback =
|
||||
0x80000000, // True, enable clawback
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
lsfSell = 0x00020000, // True, offer was placed as a sell.
|
||||
lsfHybrid = 0x00040000, // True, offer is hybrid.
|
||||
|
||||
// ltRIPPLE_STATE
|
||||
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
|
||||
@@ -186,11 +188,23 @@ enum LedgerSpecificFlags {
|
||||
lsfMPTCanTransfer = 0x00000020,
|
||||
lsfMPTCanClawback = 0x00000040,
|
||||
|
||||
lsmfMPTCanMutateCanLock = 0x00000002,
|
||||
lsmfMPTCanMutateRequireAuth = 0x00000004,
|
||||
lsmfMPTCanMutateCanEscrow = 0x00000008,
|
||||
lsmfMPTCanMutateCanTrade = 0x00000010,
|
||||
lsmfMPTCanMutateCanTransfer = 0x00000020,
|
||||
lsmfMPTCanMutateCanClawback = 0x00000040,
|
||||
lsmfMPTCanMutateMetadata = 0x00010000,
|
||||
lsmfMPTCanMutateTransferFee = 0x00020000,
|
||||
|
||||
// ltMPTOKEN
|
||||
lsfMPTAuthorized = 0x00000002,
|
||||
|
||||
// ltCREDENTIAL
|
||||
lsfAccepted = 0x00010000,
|
||||
|
||||
// ltVAULT
|
||||
lsfVaultPrivate = 0x00010000,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -24,15 +24,12 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
@@ -42,8 +42,11 @@ public:
|
||||
AccountID const&
|
||||
getIssuer() const;
|
||||
|
||||
MPTID const&
|
||||
getMptID() const;
|
||||
constexpr MPTID const&
|
||||
getMptID() const
|
||||
{
|
||||
return mptID_;
|
||||
}
|
||||
|
||||
std::string
|
||||
getText() const;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <concepts>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -80,7 +79,7 @@ struct MultiApiJson
|
||||
}
|
||||
|
||||
void
|
||||
set(const char* key, auto const& v)
|
||||
set(char const* key, auto const& v)
|
||||
requires std::constructible_from<Json::Value, decltype(v)>
|
||||
{
|
||||
for (auto& a : this->val)
|
||||
@@ -91,7 +90,7 @@ struct MultiApiJson
|
||||
enum IsMemberResult : int { none = 0, some, all };
|
||||
|
||||
[[nodiscard]] IsMemberResult
|
||||
isMember(const char* key) const
|
||||
isMember(char const* key) const
|
||||
{
|
||||
int count = 0;
|
||||
for (auto& a : this->val)
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace RPC {
|
||||
|
||||
/**
|
||||
Adds common synthetic fields to transaction-related JSON responses
|
||||
|
||||
@@ -40,6 +42,7 @@ insertNFTSyntheticInJson(
|
||||
TxMeta const&);
|
||||
/** @} */
|
||||
|
||||
} // namespace RPC
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
107
include/xrpl/protocol/Permissions.h
Normal file
107
include/xrpl/protocol/Permissions.h
Normal file
@@ -0,0 +1,107 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
||||
#define RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
||||
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ripple {
|
||||
/**
|
||||
* We have both transaction type permissions and granular type permissions.
|
||||
* Since we will reuse the TransactionFormats to parse the Transaction
|
||||
* Permissions, only the GranularPermissionType is defined here. To prevent
|
||||
* conflicts with TxType, the GranularPermissionType is always set to a value
|
||||
* greater than the maximum value of uint16.
|
||||
*/
|
||||
enum GranularPermissionType : std::uint32_t {
|
||||
#pragma push_macro("PERMISSION")
|
||||
#undef PERMISSION
|
||||
|
||||
#define PERMISSION(type, txType, value) type = value,
|
||||
|
||||
#include <xrpl/protocol/detail/permissions.macro>
|
||||
|
||||
#undef PERMISSION
|
||||
#pragma pop_macro("PERMISSION")
|
||||
};
|
||||
|
||||
enum Delegation { delegatable, notDelegatable };
|
||||
|
||||
class Permission
|
||||
{
|
||||
private:
|
||||
Permission();
|
||||
|
||||
std::unordered_map<std::uint16_t, uint256> txFeatureMap_;
|
||||
|
||||
std::unordered_map<std::uint16_t, Delegation> delegatableTx_;
|
||||
|
||||
std::unordered_map<std::string, GranularPermissionType>
|
||||
granularPermissionMap_;
|
||||
|
||||
std::unordered_map<GranularPermissionType, std::string> granularNameMap_;
|
||||
|
||||
std::unordered_map<GranularPermissionType, TxType> granularTxTypeMap_;
|
||||
|
||||
public:
|
||||
static Permission const&
|
||||
getInstance();
|
||||
|
||||
Permission(Permission const&) = delete;
|
||||
Permission&
|
||||
operator=(Permission const&) = delete;
|
||||
|
||||
std::optional<std::string>
|
||||
getPermissionName(std::uint32_t const value) const;
|
||||
|
||||
std::optional<std::uint32_t>
|
||||
getGranularValue(std::string const& name) const;
|
||||
|
||||
std::optional<std::string>
|
||||
getGranularName(GranularPermissionType const& value) const;
|
||||
|
||||
std::optional<TxType>
|
||||
getGranularTxType(GranularPermissionType const& gpType) const;
|
||||
|
||||
std::optional<std::reference_wrapper<uint256 const>> const
|
||||
getTxFeature(TxType txType) const;
|
||||
|
||||
bool
|
||||
isDelegatable(std::uint32_t const& permissionValue, Rules const& rules)
|
||||
const;
|
||||
|
||||
// for tx level permission, permission value is equal to tx type plus one
|
||||
uint32_t
|
||||
txToPermissionType(TxType const& type) const;
|
||||
|
||||
// tx type value is permission value minus one
|
||||
TxType
|
||||
permissionToTxType(uint32_t const& value) const;
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/partitioned_unordered_map.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -116,6 +115,23 @@ std::size_t constexpr maxMPTokenMetadataLength = 1024;
|
||||
/** The maximum amount of MPTokenIssuance */
|
||||
std::uint64_t constexpr maxMPTokenAmount = 0x7FFF'FFFF'FFFF'FFFFull;
|
||||
|
||||
/** The maximum length of Data payload */
|
||||
std::size_t constexpr maxDataPayloadLength = 256;
|
||||
|
||||
/** Vault withdrawal policies */
|
||||
std::uint8_t constexpr vaultStrategyFirstComeFirstServe = 1;
|
||||
|
||||
/** Default IOU scale factor for a Vault */
|
||||
std::uint8_t constexpr vaultDefaultIOUScale = 6;
|
||||
/** Maximum scale factor for a Vault. The number is chosen to ensure that
|
||||
1 IOU can be always converted to shares.
|
||||
10^19 > maxMPTokenAmount (2^64-1) > 10^18 */
|
||||
std::uint8_t constexpr vaultMaximumIOUScale = 18;
|
||||
|
||||
/** Maximum recursion depth for vault shares being put as an asset inside
|
||||
* another vault; counted from 0 */
|
||||
std::uint8_t constexpr maxAssetCheckDepth = 5;
|
||||
|
||||
/** A ledger index. */
|
||||
using LedgerIndex = std::uint32_t;
|
||||
|
||||
@@ -155,6 +171,13 @@ std::size_t constexpr maxPriceScale = 20;
|
||||
*/
|
||||
std::size_t constexpr maxTrim = 25;
|
||||
|
||||
/** The maximum number of delegate permissions an account can grant
|
||||
*/
|
||||
std::size_t constexpr permissionMaxSize = 10;
|
||||
|
||||
/** The maximum number of transactions that can be in a batch. */
|
||||
std::size_t constexpr maxBatchTxCount = 8;
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
|
||||
@@ -113,8 +113,8 @@ public:
|
||||
// have lower unsigned integer representations.
|
||||
using value_type = std::uint64_t;
|
||||
|
||||
static const int minTickSize = 3;
|
||||
static const int maxTickSize = 16;
|
||||
static int const minTickSize = 3;
|
||||
static int const maxTickSize = 16;
|
||||
|
||||
private:
|
||||
// This has the same representation as STAmount, see the comment on the
|
||||
|
||||
@@ -23,9 +23,9 @@ optional fields easier to read:
|
||||
if it exists, or nothing if it doesn't." This usage of the
|
||||
tilde/bitwise NOT operator is not standard outside of the
|
||||
`rippled` codebase.
|
||||
- As a consequence of this, `x[~sfFoo] = y[~sfFoo]`
|
||||
assigns the value of Foo from y to x, including omitting
|
||||
Foo from x if it doesn't exist in y.
|
||||
- As a consequence of this, `x[~sfFoo] = y[~sfFoo]`
|
||||
assigns the value of Foo from y to x, including omitting
|
||||
Foo from x if it doesn't exist in y.
|
||||
|
||||
Typically, for things that are guaranteed to exist, you use
|
||||
`x[sfFoo]` and avoid having to deal with a container that may
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user