Compare commits

..

1 Commits

Author SHA1 Message Date
Denis Angell
472e4dc207 feat: Add parallel apply access-set scheduler 2026-05-30 05:37:53 +02:00
333 changed files with 3998 additions and 3932 deletions

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check if PRs are dirty
uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
with:
dirtyLabel: "PR: has conflicts"
repoToken: "${{ secrets.GITHUB_TOKEN }}"

2
.gitignore vendored
View File

@@ -86,3 +86,5 @@ __pycache__
# clangd cache
/.cache
labrun/
build-release/

View File

@@ -953,21 +953,6 @@
#
# Optional keys for NuDB and RocksDB:
#
# cache_size Size of cache for database records. Default is 16384.
# Setting this value to 0 will use the default value.
#
# cache_age Length of time in minutes to keep database records
# cached. Default is 5 minutes. Setting this value to
# 0 will use the default value.
#
# Note: if cache_size or cache_age is not specified,
# default values will be used for the unspecified
# parameter.
#
# Note: the cache will not be created if online_delete
# is specified, because the rotating NodeStore does
# not use this cache).
#
# fast_load Boolean. If set, load the last persisted ledger
# from disk upon process start before syncing to
# the network. This is likely to improve performance

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a ${name} ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit ${name}(SLE::const_pointer sle)
explicit ${name}(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -168,7 +168,7 @@ ${field['typeData']['setter_type']} ${field['paramName']}${',' if i < len(requir
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
${name}Builder(SLE::const_pointer sle)
${name}Builder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ${tag})
{

48
docker/check-sanitizers.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
# Sanity-check that the sanitizer runtimes shipped with g++/clang++ work
# end-to-end against the system loader: compile each example with both
# compilers, run it, and confirm the expected diagnostic is emitted.
set -eo pipefail
cpp_files_dir="${1:?usage: $0 <cpp_files_dir>}"
case "$(uname -m)" in
x86_64) loader=/lib64/ld-linux-x86-64.so.2 ;;
aarch64) loader=/lib/ld-linux-aarch64.so.1 ;;
*)
echo "Unsupported arch: $(uname -m)" >&2
exit 1
;;
esac
declare -A sanitize=(
[asan]="-fsanitize=address"
[tsan]="-fsanitize=thread"
[ubsan]="-fsanitize=undefined"
)
declare -A expect=(
[asan]="heap-use-after-free"
[tsan]="data race"
[ubsan]="signed integer overflow"
)
for compiler in g++ clang++; do
for name in asan tsan ubsan; do
bin="/tmp/${name}-${compiler}"
echo "=== Build ${name} with ${compiler} ==="
"$compiler" -std=c++20 -O1 -g ${sanitize[$name]} \
-Wl,--dynamic-linker=$loader \
"${cpp_files_dir}/${name}.cpp" -o "$bin"
echo "=== Run ${name}-${compiler} ==="
output=$("$bin" 2>&1) || true
echo "$output"
echo "$output" | grep -q "${expect[$name]}" ||
{
echo "expected '${expect[$name]}' from $bin"
exit 1
}
rm -f "$bin"
done
done

View File

@@ -1,12 +0,0 @@
#!/bin/bash
case "$(uname -m)" in
x86_64) LOADER=/lib64/ld-linux-x86-64.so.2 ;;
aarch64) LOADER=/lib/ld-linux-aarch64.so.1 ;;
*)
echo "Unsupported arch: $(uname -m)" >&2
exit 1
;;
esac
echo "${LOADER}"

View File

@@ -27,9 +27,7 @@ RUN mkdir /tmp/nix-store-closure && \
cp -R $(nix-store -qR result/) /tmp/nix-store-closure
# Final image
FROM ${BASE_IMAGE} AS final
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
# bash is not located at /bin/bash in nixos/nix, so we need to create a symlink to it.
RUN if [ -d /nix ]; then \
@@ -45,23 +43,25 @@ ENTRYPOINT ["/bin/bash"]
COPY --from=builder /tmp/nix-store-closure /nix/store
COPY --from=builder /tmp/build/result /nix/ci-env
ENV PATH="/nix/ci-env/bin:${PATH}"
ENV PATH="/nix/ci-env/bin:$PATH"
# Externally-built dynamically-linked ELF binaries hard-code the loader path
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Install it
# from the Nix store when the base image doesn't already provide one.
COPY docker/loader-path.sh /tmp/loader-path.sh
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Copy the
# loader from the Nix store to that path when the base image doesn't already
# provide one (i.e. on nixos/nix).
RUN <<EOF
target="$(/tmp/loader-path.sh)"
if [ ! -e "${target}" ]; then
case "$(uname -m)" in
x86_64) target=/lib64/ld-linux-x86-64.so.2 ;;
aarch64) target=/lib/ld-linux-aarch64.so.1 ;;
*) echo "Unsupported arch: $(uname -m)" >&2; exit 1 ;;
esac
if [ ! -e "$target" ]; then
# Use the loader from the same glibc that gcc links libc against, so
# ld-linux and libc/libpthread share GLIBC_PRIVATE symbols at runtime.
src="$(dirname "$(gcc -print-file-name=libc.so.6)")/$(basename "${target}")"
[ -e "${src}" ] || { echo "ld-linux not found at ${src}" >&2; exit 1; }
mkdir -p "$(dirname "${target}")"
cp "${src}" "${target}"
src="$(dirname "$(gcc -print-file-name=libc.so.6)")/$(basename "$target")"
[ -e "$src" ] || { echo "ld-linux not found at $src" >&2; exit 1; }
mkdir -p "$(dirname "$target")"
cp "$src" "$target"
fi
EOF
@@ -87,16 +87,9 @@ run-clang-tidy --help
vim --version
EOF
# Sanity-check that the sanitizer runtimes shipped with g++/clang++ are able to build binaries
COPY docker/test_files/cpp_sources/ /tmp/cpp_sources/
COPY docker/test_files/compile-cpp-sources.sh /tmp/compile-cpp-sources.sh
RUN /tmp/compile-cpp-sources.sh /tmp/cpp_sources /tmp/bins
# Sanity-check that the sanitizer runtimes shipped with g++/clang++ work
# end-to-end against the system loader.
COPY docker/cpp_files/ /tmp/cpp_files/
COPY docker/check-sanitizers.sh /tmp/check-sanitizers.sh
# Sanity-check that the built binaries are able to run.
# We only support running the test binaries on Ubuntu and NixOS right now (will be fixed in the future)
#
# When build and test images will be separate, we will be to run on vanilla images.
COPY docker/test_files/run-test-binaries.sh /tmp/run-test-binaries.sh
RUN if echo "${BASE_IMAGE}" | grep -qiE '(ubuntu|nixos)'; then \
/tmp/run-test-binaries.sh /tmp/bins; \
fi
RUN grep -qi ubuntu /etc/os-release 2>/dev/null && /tmp/check-sanitizers.sh /tmp/cpp_files || true

View File

@@ -1,50 +0,0 @@
#!/bin/bash
# Compile all C++ test binaries during the Docker image build.
# Each binary has the target system's ELF PT_INTERP (dynamic-linker path)
# baked in so it can run on the (potentially minimal) final BASE_IMAGE.
set -eo pipefail
src_dir="${1:?usage: $0 <src_dir> <dst_dir>}"
dst_dir="${2:?usage: $0 <src_dir> <dst_dir>}"
loader="$(/tmp/loader-path.sh)"
mkdir -p "${dst_dir}"
function compile() {
local compiler="${1}"
local name="${2}"
local san_flag="${3:-}"
local src="${src_dir}/${name}.cpp"
local binary="${dst_dir}/${name}-${compiler}"
echo "=== Compile ${name} with ${compiler} ==="
cmd="${compiler} -std=c++23 -O1 -g \
-pthread \
-Wl,--dynamic-linker=${loader} \
${san_flag} \
${src} -o ${binary}"
echo "Command: ${cmd}"
eval "${cmd}"
}
declare -A sanitize=(
[regular]=""
[asan]="-fsanitize=address"
[tsan]="-fsanitize=thread"
[ubsan]="-fsanitize=undefined -fno-sanitize-recover=all"
)
for name in regular asan tsan ubsan; do
san_flag="${sanitize[${name}]}"
for compiler in g++ clang++; do
compile "${compiler}" "${name}" "${san_flag}"
done
done
echo "=== All binaries compiled ==="
ls -la "${dst_dir}"

View File

@@ -1,28 +0,0 @@
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
static std::mutex gMutex;
void
worker(int id)
{
std::lock_guard<std::mutex> lock(gMutex);
std::cout << "Hello from thread " << id << "\n";
}
int
main()
{
constexpr int kNumThreads = 10;
std::vector<std::thread> threads;
threads.reserve(kNumThreads);
for (int i = 0; i < kNumThreads; ++i)
threads.emplace_back(worker, i);
for (auto& t : threads)
t.join();
std::cout << "Hello from main thread\n";
return 0;
}

View File

@@ -1,62 +0,0 @@
#!/bin/bash
# Run pre-compiled sanitizer binaries and confirm each emits its expected diagnostic.
# Binaries must already exist in <bins_dir> with the layout:
# <name>-g++ and <name>-clang++ for name in {regular,asan,tsan,ubsan}
set -eo pipefail
bins_dir="${1:?usage: $0 <bins_dir>}"
# Run a binary and verify its exit code and output.
# Usage: run <binary> <expected_output> <expected_rc>
function run() {
local binary="${1}"
local expected_output="${2}"
local expected_rc="${3}"
local out_file
out_file="$(mktemp)"
echo "=== Run ${binary} ==="
local rc=0
"${binary}" >"${out_file}" 2>&1 || rc=$?
cat "${out_file}"
if [ "${expected_rc}" = "nonzero" ]; then
if [ "${rc}" -eq 0 ]; then
echo "ERROR: expected non-zero exit code from ${binary}, got ${rc}" >&2
exit 1
fi
elif [ "${rc}" -ne "${expected_rc}" ]; then
echo "ERROR: expected exit code ${expected_rc} from ${binary}, got ${rc}" >&2
exit 1
fi
grep -q "${expected_output}" "${out_file}" ||
{
echo "ERROR: expected '${expected_output}' from ${binary}" >&2
exit 1
}
echo "OK: '${expected_output}' detected"
}
declare -A expect=(
[regular]="Hello from main thread"
[asan]="heap-use-after-free"
[tsan]="data race"
[ubsan]="signed integer overflow"
)
for compiler in g++ clang++; do
for name in regular asan tsan ubsan; do
binary="${bins_dir}/${name}-${compiler}"
if [ "${name}" = "regular" ]; then
expected_rc=0
else
expected_rc=nonzero
fi
run "${binary}" "${expect[$name]}" "${expected_rc}"
done
done

View File

@@ -2,14 +2,12 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <array>
#include <cstdint>
#include <functional>
#include <limits>
#include <optional>
#include <ostream>
#include <set>
#include <stdexcept>
#include <string>
#include <unordered_map>
@@ -42,47 +40,6 @@ isPowerOfTen(T value)
return logTen(value).has_value();
}
namespace detail {
/** Builds a table of the powers of 10
*
* This function is marked consteval, so it can only be run in
* a constexpr context. This assures that it is and can only be run at
* compile time. Doing it at runtime would be pretty wasteful and
* inefficient.
*/
constexpr std::size_t kInt64Digits = 20;
consteval std::array<std::uint64_t, kInt64Digits>
buildPowersOfTen()
{
std::array<std::uint64_t, kInt64Digits> result{};
std::uint64_t power = 1;
std::size_t exponent = 0;
// end the loop early so it doesn't overflow;
for (; exponent < result.size() - 1; ++exponent, power *= 10)
{
result[exponent] = power;
if (power > std::numeric_limits<std::uint64_t>::max() / 10)
throw std::logic_error("Power of 10 table is too big");
}
result[exponent] = power;
if (power < std::numeric_limits<std::uint64_t>::max() / 10)
throw std::logic_error("Power of 10 table is not big enough for the uint64_t type");
return result;
}
} // namespace detail
constexpr std::array<std::uint64_t, detail::kInt64Digits> kPowerOfTen = detail::buildPowersOfTen();
static_assert(kPowerOfTen[0] == 1);
static_assert(kPowerOfTen[1] == 10);
static_assert(kPowerOfTen[10] == 10'000'000'000);
static_assert(
isPowerOfTen(kPowerOfTen.back()) && *logTen(kPowerOfTen.back()) == detail::kInt64Digits - 1);
/** MantissaRange defines a range for the mantissa of a normalized Number.
*
* The mantissa is in the range [min, max], where
@@ -119,7 +76,6 @@ static_assert(
struct MantissaRange final
{
using rep = std::uint64_t;
enum class MantissaScale {
Small,
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
@@ -133,15 +89,19 @@ struct MantissaRange final
Enabled = true,
};
explicit constexpr MantissaRange(MantissaScale sc) : scale(sc)
explicit constexpr MantissaRange(MantissaScale scale)
: min(getMin(scale))
, cuspRoundingFixEnabled(isCuspFixEnabled(scale))
, log(logTen(min).value_or(-1))
, scale(scale)
{
}
MantissaScale const scale;
int const log{getExponent(scale)};
rep const min{getMin(scale, log)};
rep const max{(min * 10) - 1};
CuspRoundingFix const cuspRoundingFixEnabled{isCuspFixEnabled(scale)};
rep min;
rep max{(min * 10) - 1};
CuspRoundingFix cuspRoundingFixEnabled;
int log;
MantissaScale scale;
static MantissaRange const&
getMantissaRange(MantissaScale scale);
@@ -150,35 +110,23 @@ struct MantissaRange final
getAllScales();
private:
static constexpr int
getExponent(MantissaScale scale)
static constexpr rep
getMin(MantissaScale scale)
{
switch (scale)
{
case MantissaScale::Small:
return 15;
return 1'000'000'000'000'000ULL;
case MantissaScale::LargeLegacy:
case MantissaScale::Large:
return 18;
// LCOV_EXCL_START
return 1'000'000'000'000'000'000ULL;
default:
// If called in a constexpr context, this throw assures that the build fails if an
// invalid scale is used.
throw std::runtime_error("Unknown mantissa scale");
// LCOV_EXCL_STOP
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
}
}
// Keep this function for future use with different ways to compute
// the ranges.
static constexpr rep
getMin(MantissaScale scale, int exponent)
{
if (exponent < 0 || exponent >= kPowerOfTen.size())
throw std::runtime_error("Invalid exponent"); // LCOV_EXCL_LINE
return kPowerOfTen[exponent];
}
static constexpr CuspRoundingFix
isCuspFixEnabled(MantissaScale scale)
{
@@ -529,7 +477,8 @@ public:
template <
auto MinMantissa,
auto MaxMantissa,
Integral64 T = std::decay_t<decltype(MinMantissa)>>
Integral64 T = std::decay_t<decltype(MinMantissa)>,
Integral64 TMax = std::decay_t<decltype(MaxMantissa)>>
[[nodiscard]]
std::pair<T, int>
normalizeToRange() const;
@@ -570,8 +519,7 @@ private:
int& exponent,
MantissaRange::rep const& minMantissa,
MantissaRange::rep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled,
bool dropped);
MantissaRange::CuspRoundingFix cuspRoundingFixEnabled);
[[nodiscard]] bool
isnormal() const noexcept;
@@ -777,18 +725,16 @@ Number::isnormal() const noexcept
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
}
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
template <auto MinMantissa, auto MaxMantissa, Integral64 T, Integral64 TMax>
std::pair<T, int>
Number::normalizeToRange() const
{
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::int64_t>);
static_assert(std::is_same_v<T, std::decay_t<decltype(MinMantissa)>>);
static_assert(std::is_same_v<T, std::decay_t<decltype(MaxMantissa)>>);
static_assert(std::is_same_v<T, TMax>);
auto constexpr kMIN = static_cast<T>(MinMantissa);
auto constexpr kMAX = static_cast<T>(MaxMantissa);
static_assert(kMIN > 0);
static_assert(kMIN % 10 == 0);
static_assert(isPowerOfTen(kMIN));
static_assert(kMAX % 10 == 9);
static_assert((kMAX + 1) / 10 == kMIN);

View File

@@ -157,7 +157,7 @@ public:
/** Fetch an item from the cache.
If the digest was not found, Handler
will be called with this signature:
SLE::const_pointer(void)
std::shared_ptr<SLE const>(void)
*/
template <class Handler>
SharedPointerType

View File

@@ -123,7 +123,7 @@ private:
bool preserveOrder,
Keylet const& directory,
uint256 const& key,
std::function<void(SLE::ref)> const& describe);
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
public:
ApplyView() = default;
@@ -153,7 +153,7 @@ public:
@return `nullptr` if the key is not present
*/
virtual SLE::pointer
virtual std::shared_ptr<SLE>
peek(Keylet const& k) = 0;
/** Remove a peeked SLE.
@@ -168,7 +168,7 @@ public:
The key is no longer associated with the SLE.
*/
virtual void
erase(SLE::ref sle) = 0;
erase(std::shared_ptr<SLE> const& sle) = 0;
/** Insert a new state SLE
@@ -189,7 +189,7 @@ public:
@note The key is taken from the SLE
*/
virtual void
insert(SLE::ref sle) = 0;
insert(std::shared_ptr<SLE> const& sle) = 0;
/** Indicate changes to a peeked SLE
@@ -208,7 +208,7 @@ public:
*/
/** @{ */
virtual void
update(SLE::ref sle) = 0;
update(std::shared_ptr<SLE> const& sle) = 0;
//--------------------------------------------------------------------------
@@ -301,7 +301,7 @@ public:
dirAppend(
Keylet const& directory,
Keylet const& key,
std::function<void(SLE::ref)> const& describe)
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
{
if (key.type != ltOFFER)
{
@@ -340,7 +340,7 @@ public:
dirInsert(
Keylet const& directory,
uint256 const& key,
std::function<void(SLE::ref)> const& describe)
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
{
return dirAdd(false, directory, key, describe);
}
@@ -349,7 +349,7 @@ public:
dirInsert(
Keylet const& directory,
Keylet const& key,
std::function<void(SLE::ref)> const& describe)
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
{
return dirAdd(false, directory, key.key, describe);
}
@@ -411,7 +411,7 @@ createRoot(
ApplyView& view,
Keylet const& directory,
uint256 const& key,
std::function<void(SLE::ref)> const& describe);
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
auto
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start);
@@ -434,7 +434,7 @@ insertPage(
SLE::ref next,
uint256 const& key,
Keylet const& directory,
std::function<void(SLE::ref)> const& describe);
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
} // namespace directory
} // namespace xrpl

View File

@@ -67,8 +67,8 @@ public:
std::function<void(
uint256 const& key,
bool isDelete,
SLE::const_ref before,
SLE::const_ref after)> const& func);
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)> const& func);
private:
std::optional<STAmount> deliver_;

View File

@@ -11,13 +11,13 @@ private:
uint256 const root_;
uint256 const nextQuality_;
uint256 const key_;
SLE::const_pointer sle_ = nullptr;
std::shared_ptr<SLE const> sle_ = nullptr;
unsigned int entry_ = 0;
uint256 index_;
public:
class const_iterator; // NOLINT(readability-identifier-naming)
using value_type = SLE::const_pointer;
using value_type = std::shared_ptr<SLE const>;
BookDirs(ReadView const&, Book const&);
@@ -76,7 +76,7 @@ private:
uint256 nextQuality_;
uint256 key_;
uint256 curKey_;
SLE::const_pointer sle_;
std::shared_ptr<SLE const> sle_;
unsigned int entry_ = 0;
uint256 index_;
std::optional<value_type> mutable cache_;

View File

@@ -36,7 +36,7 @@ public:
bool
exists(Keylet const& k) const override;
SLE::const_pointer
std::shared_ptr<SLE const>
read(Keylet const& k) const override;
bool

View File

@@ -22,12 +22,12 @@ class Dir
private:
ReadView const* view_ = nullptr;
Keylet root_;
SLE::const_pointer sle_;
std::shared_ptr<SLE const> sle_;
STVector256 const* indexes_ = nullptr;
public:
class ConstIterator;
using value_type = SLE::const_pointer;
using value_type = std::shared_ptr<SLE const>;
Dir(ReadView const&, Keylet const&);
@@ -102,7 +102,7 @@ private:
Keylet page_;
uint256 index_;
std::optional<value_type> mutable cache_;
SLE::const_pointer sle_;
std::shared_ptr<SLE const> sle_;
STVector256 const* indexes_ = nullptr;
std::vector<uint256>::const_iterator it_;
};

View File

@@ -166,7 +166,7 @@ public:
std::optional<uint256>
succ(uint256 const& key, std::optional<uint256> const& last = std::nullopt) const override;
SLE::const_pointer
std::shared_ptr<SLE const>
read(Keylet const& k) const override;
std::unique_ptr<SlesType::iter_base>
@@ -202,16 +202,16 @@ public:
//
void
rawErase(SLE::ref sle) override;
rawErase(std::shared_ptr<SLE> const& sle) override;
void
rawInsert(SLE::ref sle) override;
rawInsert(std::shared_ptr<SLE> const& sle) override;
void
rawErase(uint256 const& key);
void
rawReplace(SLE::ref sle) override;
rawReplace(std::shared_ptr<SLE> const& sle) override;
void
rawDestroyXRP(XRPAmount const& fee) override
@@ -361,7 +361,7 @@ public:
bool
isVotingLedger() const;
SLE::pointer
std::shared_ptr<SLE>
peek(Keylet const& k) const;
private:

View File

@@ -197,7 +197,7 @@ public:
std::optional<key_type>
succ(key_type const& key, std::optional<key_type> const& last = std::nullopt) const override;
SLE::const_pointer
std::shared_ptr<SLE const>
read(Keylet const& k) const override;
std::unique_ptr<SlesType::iter_base>
@@ -224,13 +224,13 @@ public:
// RawView
void
rawErase(SLE::ref sle) override;
rawErase(std::shared_ptr<SLE> const& sle) override;
void
rawInsert(SLE::ref sle) override;
rawInsert(std::shared_ptr<SLE> const& sle) override;
void
rawReplace(SLE::ref sle) override;
rawReplace(std::shared_ptr<SLE> const& sle) override;
void
rawDestroyXRP(XRPAmount const& fee) override;

View File

@@ -25,7 +25,7 @@ public:
can calculate metadata.
*/
virtual void
rawErase(SLE::ref sle) = 0;
rawErase(std::shared_ptr<SLE> const& sle) = 0;
/** Unconditionally insert a state item.
@@ -39,7 +39,7 @@ public:
@note The key is taken from the SLE
*/
virtual void
rawInsert(SLE::ref sle) = 0;
rawInsert(std::shared_ptr<SLE> const& sle) = 0;
/** Unconditionally replace a state item.
@@ -54,7 +54,7 @@ public:
@note The key is taken from the SLE
*/
virtual void
rawReplace(SLE::ref sle) = 0;
rawReplace(std::shared_ptr<SLE> const& sle) = 0;
/** Destroy XRP.

View File

@@ -34,9 +34,9 @@ public:
using key_type = uint256;
using mapped_type = SLE::const_pointer;
using mapped_type = std::shared_ptr<SLE const>;
struct SlesType : detail::ReadViewFwdRange<SLE::const_pointer>
struct SlesType : detail::ReadViewFwdRange<std::shared_ptr<SLE const>>
{
explicit SlesType(ReadView const& view);
[[nodiscard]] Iterator
@@ -143,7 +143,7 @@ public:
@return `nullptr` if the key is not present or
if the type does not match.
*/
[[nodiscard]] virtual SLE::const_pointer
[[nodiscard]] 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

View File

@@ -12,6 +12,7 @@
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <utility>
@@ -134,7 +135,7 @@ areCompatible(
dirLink(
ApplyView& view,
AccountID const& owner,
SLE::pointer& object,
std::shared_ptr<SLE>& object,
SF_UINT64 const& node = sfOwnerNode);
/** Checks that can withdraw funds from an object to itself or a destination.
@@ -214,8 +215,8 @@ doWithdraw(
* (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&, SLE::pointer&)>;
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

View File

@@ -4,10 +4,16 @@
#include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/RawView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxMeta.h>
#include <xrpl/protocol/XRPAmount.h>
#include <memory>
#ifndef NDEBUG
#include <map>
#endif
namespace xrpl::detail {
// Helper class that buffers modifications
@@ -24,7 +30,7 @@ private:
Modify,
};
using items_t = std::map<key_type, std::pair<Action, SLE::pointer>>;
using items_t = std::map<key_type, std::pair<Action, std::shared_ptr<SLE>>>;
items_t items_;
XRPAmount dropsDestroyed_{0};
@@ -58,10 +64,10 @@ public:
[[nodiscard]] std::optional<key_type>
succ(ReadView const& base, key_type const& key, std::optional<key_type> const& last) const;
[[nodiscard]] SLE::const_pointer
[[nodiscard]] std::shared_ptr<SLE const>
read(ReadView const& base, Keylet const& k) const;
SLE::pointer
std::shared_ptr<SLE>
peek(ReadView const& base, Keylet const& k);
[[nodiscard]] std::size_t
@@ -73,23 +79,23 @@ public:
std::function<void(
uint256 const& key,
bool isDelete,
SLE::const_ref before,
SLE::const_ref after)> const& func) const;
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)> const& func) const;
void
erase(ReadView const& base, SLE::ref sle);
erase(ReadView const& base, std::shared_ptr<SLE> const& sle);
void
rawErase(ReadView const& base, SLE::ref sle);
rawErase(ReadView const& base, std::shared_ptr<SLE> const& sle);
void
insert(ReadView const& base, SLE::ref sle);
insert(ReadView const& base, std::shared_ptr<SLE> const& sle);
void
update(ReadView const& base, SLE::ref sle);
update(ReadView const& base, std::shared_ptr<SLE> const& sle);
void
replace(ReadView const& base, SLE::ref sle);
replace(ReadView const& base, std::shared_ptr<SLE> const& sle);
void
destroyXRP(XRPAmount const& fee);
@@ -101,13 +107,45 @@ public:
return dropsDestroyed_;
}
#ifndef NDEBUG
/** Every ledger entry this table has read or written, mapped to its type.
Populated in DEBUG builds by the access methods below (reads via
read/exists/peek and writes via insert/update/replace/erase). Directory
iteration via succ() is deliberately NOT recorded — see AccessSet for
why directory entries are out of scope for conflict tracking. Used by
the parallel-apply access-set assertion to verify a transactor's
declared footprint is a superset of what it actually touched.
*/
[[nodiscard]] std::map<key_type, LedgerEntryType> const&
touchedEntries() const
{
return touched_;
}
#endif
private:
using Mods = hash_map<key_type, SLE::pointer>;
#ifndef NDEBUG
void
recordTouch(key_type const& key, LedgerEntryType type) const
{
// Prefer ltDIR_NODE on collision so directory pages stay identifiable
// regardless of access order; non-dir objects are never accessed via a
// directory keylet, so this never mislabels a real object.
auto const [it, inserted] = touched_.try_emplace(key, type);
if (!inserted && type == ltDIR_NODE)
it->second = ltDIR_NODE;
}
mutable std::map<key_type, LedgerEntryType> touched_;
#endif
using Mods = hash_map<key_type, std::shared_ptr<SLE>>;
static void
threadItem(TxMeta& meta, SLE::ref to);
threadItem(TxMeta& meta, std::shared_ptr<SLE> const& to);
SLE::pointer
std::shared_ptr<SLE>
getForMod(ReadView const& base, key_type const& key, Mods& mods, beast::Journal j);
void
@@ -117,7 +155,7 @@ private:
threadOwners(
ReadView const& base,
TxMeta& meta,
SLE::const_ref sle,
std::shared_ptr<SLE const> const& sle,
Mods& mods,
beast::Journal j);
};

View File

@@ -40,7 +40,7 @@ public:
[[nodiscard]] std::optional<key_type>
succ(key_type const& key, std::optional<key_type> const& last = std::nullopt) const override;
[[nodiscard]] SLE::const_pointer
[[nodiscard]] std::shared_ptr<SLE const>
read(Keylet const& k) const override;
[[nodiscard]] std::unique_ptr<SlesType::iter_base>
@@ -69,32 +69,42 @@ public:
[[nodiscard]] ApplyFlags
flags() const override;
SLE::pointer
std::shared_ptr<SLE>
peek(Keylet const& k) override;
void
erase(SLE::ref sle) override;
erase(std::shared_ptr<SLE> const& sle) override;
void
insert(SLE::ref sle) override;
insert(std::shared_ptr<SLE> const& sle) override;
void
update(SLE::ref sle) override;
update(std::shared_ptr<SLE> const& sle) override;
// RawView
void
rawErase(SLE::ref sle) override;
rawErase(std::shared_ptr<SLE> const& sle) override;
void
rawInsert(SLE::ref sle) override;
rawInsert(std::shared_ptr<SLE> const& sle) override;
void
rawReplace(SLE::ref sle) override;
rawReplace(std::shared_ptr<SLE> const& sle) override;
void
rawDestroyXRP(XRPAmount const& feeDrops) override;
#ifndef NDEBUG
/** Every ledger entry touched (read or written) by this view, with type.
DEBUG-only; backs the parallel-apply access-set assertion. */
[[nodiscard]] std::map<uint256, LedgerEntryType> const&
touchedEntries() const
{
return items_.touchedEntries();
}
#endif
protected:
ApplyFlags flags_;
ReadView const* base_;

View File

@@ -49,15 +49,15 @@ public:
succ(ReadView const& base, key_type const& key, std::optional<key_type> const& last) const;
void
erase(SLE::ref sle);
erase(std::shared_ptr<SLE> const& sle);
void
insert(SLE::ref sle);
insert(std::shared_ptr<SLE> const& sle);
void
replace(SLE::ref sle);
replace(std::shared_ptr<SLE> const& sle);
[[nodiscard]] SLE::const_pointer
[[nodiscard]] std::shared_ptr<SLE const>
read(ReadView const& base, Keylet const& k) const;
void
@@ -84,10 +84,10 @@ private:
struct SleAction
{
Action action;
SLE::pointer sle;
std::shared_ptr<SLE> sle;
// Constructor needed for emplacement in std::map
SleAction(Action action, SLE::pointer sle) : action(action), sle(std::move(sle))
SleAction(Action action, std::shared_ptr<SLE> const& sle) : action(action), sle(sle)
{
}
};

View File

@@ -200,7 +200,7 @@ getAMMOfferStartWithTakerGets(
auto getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerGets is integral.
// This has the most impact when takerGets is XRP.
auto const takerGets =
toAmount<TOut>(getAsset(pool.out), nTakerGetsProposed, Number::RoundingMode::Downward);
return TAmounts<TIn, TOut>{swapAssetOut(pool, takerGets, tfee), takerGets};
@@ -215,7 +215,7 @@ getAMMOfferStartWithTakerGets(
}
/** Generate AMM offer starting with takerPays when AMM pool
* from the payment perspective has a fractional output asset.
* from the payment perspective is XRP(in)/IOU(out) or IOU(in)/IOU(out).
* Equations:
* Spot Price Quality after the offer is consumed:
* Qsp = (O - o) / (I + i) -- equation (1)
@@ -267,7 +267,7 @@ getAMMOfferStartWithTakerPays(
auto getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerPays is integral.
// This has the most impact when takerPays is XRP.
auto const takerPays =
toAmount<TIn>(getAsset(pool.in), nTakerPaysProposed, Number::RoundingMode::Downward);
return TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
@@ -285,11 +285,11 @@ getAMMOfferStartWithTakerPays(
* is equal to LOB quality (in this case AMM offer quality is
* better than LOB quality) or AMM offer is equal to LOB quality
* (in this case SPQ is better than LOB quality).
* Pre-amendment code calculates takerPays first. If takerGets is the
* economically coarser integral side, it is rounded down, which results in
* worse offer quality than LOB quality, and the offer might fail to generate.
* Post-amendment code calculates the economically coarser integral offer side
* first. The result is rounded down, which makes the offer quality better.
* Pre-amendment code calculates takerPays first. If takerGets is XRP,
* it is rounded down, which results in worse offer quality than
* LOB quality, and the offer might fail to generate.
* Post-amendment code calculates the XRP offer side first. The result
* is rounded down, which makes the offer quality better.
* It might not be possible to match either SPQ or AMM offer to LOB
* quality. This generally happens at higher fees.
* @param pool AMM pool balances
@@ -368,18 +368,10 @@ changeSpotPriceQuality(
return std::nullopt;
}
// Generate the offer starting with XRP side. Return seated offer amounts
// if the offer can be generated, otherwise nullopt.
auto amounts = [&]() {
bool const inIntegral = getAsset(pool.in).integral();
bool const outIntegral = getAsset(pool.out).integral();
// Preserve historical behavior for fractional pairs and XRP/IOU-style
// one-integral-side pairs. For two integral assets, pick the side whose
// minimum unit is economically coarser at this quality.
//
// Quality::rate() is input units per output unit, so one output unit is
// coarser when it costs at least one input unit. Ties use takerGets,
// matching the historical XRP-output behavior.
if (outIntegral && (!inIntegral || Number(quality.rate()) >= 1))
if (isXRP(getAsset(pool.out)))
return getAMMOfferStartWithTakerGets(pool, quality, tfee);
return getAMMOfferStartWithTakerPays(pool, quality, tfee);
}();
@@ -800,7 +792,7 @@ deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::
void
initializeFeeAuctionVote(
ApplyView& view,
SLE::pointer& ammSle,
std::shared_ptr<SLE>& ammSle,
AccountID const& account,
Asset const& lptAsset,
std::uint16_t tfee);
@@ -820,7 +812,7 @@ Expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
SLE::pointer& ammSle,
std::shared_ptr<SLE>& ammSle,
AccountID const& account);
} // namespace xrpl

View File

@@ -9,6 +9,7 @@
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <memory>
#include <set>
#include <vector>
@@ -35,7 +36,11 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
/** Adjust the owner count up or down. */
void
adjustOwnerCount(ApplyView& view, SLE::ref sle, std::int32_t amount, beast::Journal j);
adjustOwnerCount(
ApplyView& view,
std::shared_ptr<SLE> const& sle,
std::int32_t amount,
beast::Journal j);
/** Returns IOU issuer transfer fee as Rate. Rate specifies
* the fee as fractions of 1 billion. For example, 1% transfer rate
@@ -71,7 +76,9 @@ getPseudoAccountFields();
- null pointer
*/
[[nodiscard]] bool
isPseudoAccount(SLE::const_pointer sleAcct, std::set<SField const*> const& pseudoFieldFilter = {});
isPseudoAccount(
std::shared_ptr<SLE const> sleAcct,
std::set<SField const*> const& pseudoFieldFilter = {});
/** Convenience overload that reads the account from the view. */
[[nodiscard]] inline bool
@@ -91,7 +98,7 @@ isPseudoAccount(
* before using a field. The amendment check is **not** performed in
* createPseudoAccount.
*/
[[nodiscard]] Expected<SLE::pointer, TER>
[[nodiscard]] Expected<std::shared_ptr<SLE>, TER>
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
/** Checks the destination and tag.

View File

@@ -23,7 +23,7 @@ checkExpired(SLE const& sleCredential, NetClock::time_point const& closed);
// Actually remove a credentials object from the ledger
[[nodiscard]] TER
deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j);
deleteSLE(ApplyView& view, std::shared_ptr<SLE> const& sleCredential, beast::Journal j);
// Amendment and parameters checks for sfCredentialIDs field
NotTEC
@@ -70,7 +70,7 @@ verifyDepositPreauth(
ApplyView& view,
AccountID const& src,
AccountID const& dst,
SLE::const_ref sleDst,
std::shared_ptr<SLE const> const& sleDst,
beast::Journal j);
} // namespace xrpl

View File

@@ -15,7 +15,7 @@ namespace xrpl {
* if not.
*/
NotTEC
checkTxPermission(SLE::const_ref delegate, STTx const& tx);
checkTxPermission(std::shared_ptr<SLE const> const& delegate, STTx const& tx);
/**
* Load the granular permissions granted to the delegate account for the
@@ -28,7 +28,7 @@ checkTxPermission(SLE::const_ref delegate, STTx const& tx);
*/
void
loadGranularPermission(
SLE::const_ref delegate,
std::shared_ptr<SLE const> const& delegate,
TxType const& type,
std::unordered_set<GranularPermissionType>& granularPermissions);

View File

@@ -115,7 +115,7 @@ bool
cdirFirst(
ReadView const& view,
uint256 const& root,
SLE::const_pointer& page,
std::shared_ptr<SLE const>& page,
unsigned int& index,
uint256& entry);
@@ -123,7 +123,7 @@ bool
dirFirst(
ApplyView& view,
uint256 const& root,
SLE::pointer& page,
std::shared_ptr<SLE>& page,
unsigned int& index,
uint256& entry);
/** @} */
@@ -147,7 +147,7 @@ bool
cdirNext(
ReadView const& view,
uint256 const& root,
SLE::const_pointer& page,
std::shared_ptr<SLE const>& page,
unsigned int& index,
uint256& entry);
@@ -155,14 +155,17 @@ bool
dirNext(
ApplyView& view,
uint256 const& root,
SLE::pointer& page,
std::shared_ptr<SLE>& page,
unsigned int& index,
uint256& entry);
/** @} */
/** Iterate all items in the given directory. */
void
forEachItem(ReadView const& view, Keylet const& root, std::function<void(SLE::const_ref)> const& f);
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
@@ -177,11 +180,14 @@ forEachItemAfter(
uint256 const& after,
std::uint64_t const hint,
unsigned int limit,
std::function<bool(SLE::const_ref)> const& f);
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(SLE::const_ref)> const& f)
forEachItem(
ReadView const& view,
AccountID const& id,
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
{
forEachItem(view, keylet::ownerDir(id), f);
}
@@ -199,7 +205,7 @@ forEachItemAfter(
uint256 const& after,
std::uint64_t const hint,
unsigned int limit,
std::function<bool(SLE::const_ref)> const& f)
std::function<bool(std::shared_ptr<SLE const> const&)> const& f)
{
return forEachItemAfter(view, keylet::ownerDir(id), after, hint, limit, f);
}

View File

@@ -18,7 +18,7 @@ TER
escrowUnlockApplyHelper(
ApplyView& view,
Rate lockedRate,
SLE::ref sleDest,
std::shared_ptr<SLE> const& sleDest,
STAmount const& xrpBalance,
STAmount const& amount,
AccountID const& issuer,
@@ -32,7 +32,7 @@ inline TER
escrowUnlockApplyHelper<Issue>(
ApplyView& view,
Rate lockedRate,
SLE::ref sleDest,
std::shared_ptr<SLE> const& sleDest,
STAmount const& xrpBalance,
STAmount const& amount,
AccountID const& issuer,
@@ -162,7 +162,7 @@ inline TER
escrowUnlockApplyHelper<MPTIssue>(
ApplyView& view,
Rate lockedRate,
SLE::ref sleDest,
std::shared_ptr<SLE> const& sleDest,
STAmount const& xrpBalance,
STAmount const& amount,
AccountID const& issuer,

View File

@@ -461,7 +461,6 @@ loanAccruedInterest(
ExtendedPaymentComponents
computeOverpaymentComponents(
Rules const& rules,
Asset const& asset,
int32_t const loanScale,
Number const& overpayment,

View File

@@ -230,14 +230,6 @@ createMPToken(
AccountID const& account,
std::uint32_t const flags);
TER
checkCreateMPT(
xrpl::ApplyView& view,
xrpl::MPTIssue const& mptIssue,
xrpl::AccountID const& holder,
std::uint32_t flags,
beast::Journal j);
TER
checkCreateMPT(
xrpl::ApplyView& view,

View File

@@ -28,9 +28,10 @@ findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID
struct TokenAndPage
{
STObject token;
SLE::pointer page;
std::shared_ptr<SLE> page;
TokenAndPage(STObject token, SLE::pointer page) : token(std::move(token)), page(std::move(page))
TokenAndPage(STObject token, std::shared_ptr<SLE> page)
: token(std::move(token)), page(std::move(page))
{
}
};
@@ -46,7 +47,11 @@ TER
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID);
TER
removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, SLE::ref page);
removeToken(
ApplyView& view,
AccountID const& owner,
uint256 const& nftokenID,
std::shared_ptr<SLE> const& page);
/** Deletes the given token offer.
@@ -58,7 +63,7 @@ removeToken(ApplyView& view, AccountID const& owner, uint256 const& nftokenID, S
The offer also consumes one incremental reserve.
*/
bool
deleteTokenOffer(ApplyView& view, SLE::ref offer);
deleteTokenOffer(ApplyView& view, std::shared_ptr<SLE> const& offer);
/** Repairs the links in an NFTokenPage directory.

View File

@@ -5,6 +5,8 @@
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <memory>
namespace xrpl {
/** Delete an offer.
@@ -21,6 +23,6 @@ namespace xrpl {
*/
// [[nodiscard]] // nodiscard commented out so Flow, BookTip and others compile.
TER
offerDelete(ApplyView& view, SLE::ref sle, beast::Journal j);
offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j);
} // namespace xrpl

View File

@@ -8,6 +8,10 @@
namespace xrpl {
TER
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j);
closeChannel(
std::shared_ptr<SLE> const& slep,
ApplyView& view,
uint256 const& key,
beast::Journal j);
} // namespace xrpl

View File

@@ -154,7 +154,7 @@ trustCreate(
[[nodiscard]] TER
trustDelete(
ApplyView& view,
SLE::ref sleRippleState,
std::shared_ptr<SLE> const& sleRippleState,
AccountID const& uLowAccountID,
AccountID const& uHighAccountID,
beast::Journal j);
@@ -248,7 +248,7 @@ removeEmptyHolding(
[[nodiscard]] TER
deleteAMMTrustLine(
ApplyView& view,
SLE::pointer sleState,
std::shared_ptr<SLE> sleState,
std::optional<AccountID> const& ammAccountID,
beast::Journal j);
@@ -258,7 +258,7 @@ deleteAMMTrustLine(
[[nodiscard]] TER
deleteAMMMPToken(
ApplyView& view,
SLE::pointer sleMPT,
std::shared_ptr<SLE> sleMPT,
AccountID const& ammAccountID,
beast::Journal j);

View File

@@ -5,6 +5,7 @@
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <memory>
#include <optional>
namespace xrpl {
@@ -20,7 +21,10 @@ namespace xrpl {
@return The number of shares, or nullopt on error.
*/
[[nodiscard]] std::optional<STAmount>
assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& assets);
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
@@ -33,7 +37,10 @@ assetsToSharesDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount co
@return The number of assets, or nullopt on error.
*/
[[nodiscard]] std::optional<STAmount>
sharesToAssetsDeposit(SLE::const_ref vault, SLE::const_ref issuance, STAmount const& shares);
sharesToAssetsDeposit(
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
STAmount const& shares);
/** Controls whether to truncate shares instead of rounding. */
enum class TruncateShares : bool { No = false, Yes = true };
@@ -62,8 +69,8 @@ enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
*/
[[nodiscard]] std::optional<STAmount>
assetsToSharesWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
STAmount const& assets,
TruncateShares truncate = TruncateShares::No,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
@@ -82,8 +89,8 @@ assetsToSharesWithdraw(
*/
[[nodiscard]] std::optional<STAmount>
sharesToAssetsWithdraw(
SLE::const_ref vault,
SLE::const_ref issuance,
std::shared_ptr<SLE const> const& vault,
std::shared_ptr<SLE const> const& issuance,
STAmount const& shares,
WaiveUnrealizedLoss waive = WaiveUnrealizedLoss::No);
@@ -97,6 +104,9 @@ sharesToAssetsWithdraw(
both the share MPTID and the outstanding-amount total.
*/
[[nodiscard]] bool
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance);
isSoleShareholder(
ReadView const& view,
AccountID const& account,
std::shared_ptr<SLE const> const& issuance);
} // namespace xrpl

View File

@@ -131,10 +131,6 @@ public:
std::uint32_t ledgerSeq,
std::function<void(std::shared_ptr<NodeObject> const&)>&& callback);
/** Remove expired entries from the positive and negative caches. */
virtual void
sweep() = 0;
/** Gather statistics pertaining to read and write activities.
*
* @param obj Json object reference into which to place counters.

View File

@@ -22,32 +22,6 @@ public:
beast::Journal j)
: Database(scheduler, readThreads, config, j), backend_(std::move(backend))
{
std::optional<int> cacheSize, cacheAge;
if (config.exists("cache_size"))
{
cacheSize = get<int>(config, "cache_size");
if (cacheSize.value() < 0)
Throw<std::runtime_error>("Specified negative value for cache_size");
}
if (config.exists("cache_age"))
{
cacheAge = get<int>(config, "cache_age");
if (cacheAge.value() < 0)
Throw<std::runtime_error>("Specified negative value for cache_age");
}
if (cacheSize.has_value() || cacheAge.has_value())
{
cache_ = std::make_shared<TaggedCache<uint256, NodeObject>>(
"DatabaseNodeImp",
cacheSize.value_or(0),
std::chrono::minutes(cacheAge.value_or(0)),
stopwatch(),
j);
}
XRPL_ASSERT(
backend_,
"xrpl::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null "
@@ -99,13 +73,7 @@ public:
std::uint32_t ledgerSeq,
std::function<void(std::shared_ptr<NodeObject> const&)>&& callback) override;
void
sweep() override;
private:
// Cache for database objects. This cache is not always initialized. Check
// for null before using.
std::shared_ptr<TaggedCache<uint256, NodeObject>> cache_;
// Persistent key/value storage
std::shared_ptr<Backend> backend_;

View File

@@ -55,9 +55,6 @@ public:
void
sync() override;
void
sweep() override;
private:
std::shared_ptr<Backend> writableBackend_;
std::shared_ptr<Backend> archiveBackend_;

View File

@@ -144,7 +144,7 @@ T
toAmount(Asset const& asset, Number const& n, Number::RoundingMode mode = Number::getround())
{
SaveNumberRoundMode const rm(Number::getround());
if (asset.integral())
if (isXRP(asset))
Number::setround(mode);
if constexpr (std::is_same_v<IOUAmount, T>)

View File

@@ -51,14 +51,6 @@ public:
std::optional<Number>
outFromAvgQ(Quality const& quality);
/** Return whether `out` produces at least the requested
* average quality.
* @param quality requested average quality (quality limit)
* @param out output amount to test
*/
[[nodiscard]] bool
satisfiesAvgQ(Quality const& quality, Number const& out) const;
/** Return true if the quality function is constant
*/
[[nodiscard]] bool

View File

@@ -27,7 +27,7 @@ public:
* @brief Construct a ledger entry wrapper from an existing SLE object.
* @param sle The underlying serialized ledger entry to wrap
*/
explicit LedgerEntryBase(SLE::const_pointer sle) : sle_(std::move(sle))
explicit LedgerEntryBase(std::shared_ptr<SLE const> sle) : sle_(std::move(sle))
{
}
@@ -151,7 +151,7 @@ public:
* @return A constant reference to the underlying SLE object
*/
[[nodiscard]]
SLE::const_pointer
std::shared_ptr<SLE const>
getSle() const
{
return sle_;
@@ -159,7 +159,7 @@ public:
protected:
/** @brief The underlying serialized ledger entry being wrapped. */
SLE::const_pointer sle_;
std::shared_ptr<SLE const> sle_;
};
} // namespace xrpl::ledger_entries

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a AMM ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit AMM(SLE::const_pointer sle)
explicit AMM(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -256,7 +256,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
AMMBuilder(SLE::const_pointer sle)
AMMBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltAMM)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a AccountRoot ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit AccountRoot(SLE::const_pointer sle)
explicit AccountRoot(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -555,7 +555,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
AccountRootBuilder(SLE::const_pointer sle)
AccountRootBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltACCOUNT_ROOT)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Amendments ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Amendments(SLE::const_pointer sle)
explicit Amendments(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -166,7 +166,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
AmendmentsBuilder(SLE::const_pointer sle)
AmendmentsBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltAMENDMENTS)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Bridge ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Bridge(SLE::const_pointer sle)
explicit Bridge(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -210,7 +210,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
BridgeBuilder(SLE::const_pointer sle)
BridgeBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltBRIDGE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Check ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Check(SLE::const_pointer sle)
explicit Check(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -269,7 +269,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
CheckBuilder(SLE::const_pointer sle)
CheckBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltCHECK)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Credential ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Credential(SLE::const_pointer sle)
explicit Credential(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -219,7 +219,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
CredentialBuilder(SLE::const_pointer sle)
CredentialBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltCREDENTIAL)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a DID ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit DID(SLE::const_pointer sle)
explicit DID(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -193,7 +193,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
DIDBuilder(SLE::const_pointer sle)
DIDBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltDID)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Delegate ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Delegate(SLE::const_pointer sle)
explicit Delegate(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -172,7 +172,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
DelegateBuilder(SLE::const_pointer sle)
DelegateBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltDELEGATE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a DepositPreauth ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit DepositPreauth(SLE::const_pointer sle)
explicit DepositPreauth(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -170,7 +170,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
DepositPreauthBuilder(SLE::const_pointer sle)
DepositPreauthBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltDEPOSIT_PREAUTH)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a DirectoryNode ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit DirectoryNode(SLE::const_pointer sle)
explicit DirectoryNode(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -431,7 +431,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
DirectoryNodeBuilder(SLE::const_pointer sle)
DirectoryNodeBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltDIR_NODE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Escrow ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Escrow(SLE::const_pointer sle)
explicit Escrow(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -363,7 +363,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
EscrowBuilder(SLE::const_pointer sle)
EscrowBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltESCROW)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a FeeSettings ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit FeeSettings(SLE::const_pointer sle)
explicit FeeSettings(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -285,7 +285,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
FeeSettingsBuilder(SLE::const_pointer sle)
FeeSettingsBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltFEE_SETTINGS)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a LedgerHashes ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit LedgerHashes(SLE::const_pointer sle)
explicit LedgerHashes(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -130,7 +130,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
LedgerHashesBuilder(SLE::const_pointer sle)
LedgerHashesBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltLEDGER_HASHES)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Loan ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Loan(SLE::const_pointer sle)
explicit Loan(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -607,7 +607,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
LoanBuilder(SLE::const_pointer sle)
LoanBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltLOAN)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a LoanBroker ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit LoanBroker(SLE::const_pointer sle)
explicit LoanBroker(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -378,7 +378,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
LoanBrokerBuilder(SLE::const_pointer sle)
LoanBrokerBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltLOAN_BROKER)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a MPToken ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit MPToken(SLE::const_pointer sle)
explicit MPToken(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -182,7 +182,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
MPTokenBuilder(SLE::const_pointer sle)
MPTokenBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltMPTOKEN)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a MPTokenIssuance ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit MPTokenIssuance(SLE::const_pointer sle)
explicit MPTokenIssuance(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -339,7 +339,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
MPTokenIssuanceBuilder(SLE::const_pointer sle)
MPTokenIssuanceBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltMPTOKEN_ISSUANCE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a NFTokenOffer ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit NFTokenOffer(SLE::const_pointer sle)
explicit NFTokenOffer(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -208,7 +208,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
NFTokenOfferBuilder(SLE::const_pointer sle)
NFTokenOfferBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltNFTOKEN_OFFER)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a NFTokenPage ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit NFTokenPage(SLE::const_pointer sle)
explicit NFTokenPage(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -157,7 +157,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
NFTokenPageBuilder(SLE::const_pointer sle)
NFTokenPageBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltNFTOKEN_PAGE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a NegativeUNL ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit NegativeUNL(SLE::const_pointer sle)
explicit NegativeUNL(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -190,7 +190,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
NegativeUNLBuilder(SLE::const_pointer sle)
NegativeUNLBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltNEGATIVE_UNL)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Offer ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Offer(SLE::const_pointer sle)
explicit Offer(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -259,7 +259,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
OfferBuilder(SLE::const_pointer sle)
OfferBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltOFFER)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Oracle ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Oracle(SLE::const_pointer sle)
explicit Oracle(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -222,7 +222,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
OracleBuilder(SLE::const_pointer sle)
OracleBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltORACLE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a PayChannel ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit PayChannel(SLE::const_pointer sle)
explicit PayChannel(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -330,7 +330,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
PayChannelBuilder(SLE::const_pointer sle)
PayChannelBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltPAYCHAN)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a PermissionedDomain ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit PermissionedDomain(SLE::const_pointer sle)
explicit PermissionedDomain(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -148,7 +148,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
PermissionedDomainBuilder(SLE::const_pointer sle)
PermissionedDomainBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltPERMISSIONED_DOMAIN)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a RippleState ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit RippleState(SLE::const_pointer sle)
explicit RippleState(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -278,7 +278,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
RippleStateBuilder(SLE::const_pointer sle)
RippleStateBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltRIPPLE_STATE)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a SignerList ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit SignerList(SLE::const_pointer sle)
explicit SignerList(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -172,7 +172,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
SignerListBuilder(SLE::const_pointer sle)
SignerListBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltSIGNER_LIST)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Ticket ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Ticket(SLE::const_pointer sle)
explicit Ticket(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -134,7 +134,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
TicketBuilder(SLE::const_pointer sle)
TicketBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltTICKET)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a Vault ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit Vault(SLE::const_pointer sle)
explicit Vault(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -330,7 +330,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
VaultBuilder(SLE::const_pointer sle)
VaultBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltVAULT)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a XChainOwnedClaimID ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit XChainOwnedClaimID(SLE::const_pointer sle)
explicit XChainOwnedClaimID(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -187,7 +187,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
XChainOwnedClaimIDBuilder(SLE::const_pointer sle)
XChainOwnedClaimIDBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltXCHAIN_OWNED_CLAIM_ID)
{

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a XChainOwnedCreateAccountClaimID ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit XChainOwnedCreateAccountClaimID(SLE::const_pointer sle)
explicit XChainOwnedCreateAccountClaimID(std::shared_ptr<SLE const> sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -161,7 +161,7 @@ public:
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
XChainOwnedCreateAccountClaimIDBuilder(SLE::const_pointer sle)
XChainOwnedCreateAccountClaimIDBuilder(std::shared_ptr<SLE const> sle)
{
if (sle->at(sfLedgerEntryType) != ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID)
{

View File

@@ -0,0 +1,92 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <boost/container/flat_set.hpp>
#include <set>
namespace xrpl {
/** The statically-declared ledger footprint of a single transaction.
An AccessSet enumerates the ledger entries a transaction may read or write,
grouped by category for readability. It is produced by `accessSetOf()` from
the signed transaction body (and, where required, a read-only snapshot of
the closed ledger) — never from another transaction's in-flight writes.
Two transactions are independent (safe to apply concurrently) iff their
AccessSets do not conflict; see `conflictsWith()`. A transaction whose
footprint cannot be enumerated statically sets `touchesGlobal` and is
serialized against everything.
Directory-node (ltDIR_NODE) entries are intentionally NOT represented here.
Owner-directory bookkeeping is a consequence of mutating the owning account,
whose AccountRoot is already declared; shared (book) directories belong only
to transactors that are `touchesGlobal` in this version. Conflict detection
on directories is therefore subsumed by the account/object entries.
The category split is for human readability and future scheduler heuristics;
conflict detection itself operates on the flat union, `keys()`.
*/
struct AccessSet
{
boost::container::flat_set<uint256> accounts; // AccountRoot entries
boost::container::flat_set<uint256> trustlines; // RippleState entries
boost::container::flat_set<uint256> offerBooks; // book directory roots
boost::container::flat_set<uint256> ammPools; // AMM root entries
boost::container::flat_set<uint256> nftPages; // NFToken page roots
boost::container::flat_set<uint256> miscObjects; // escrow/check/ticket/etc.
/** When true, the footprint is not statically known; serialize this tx. */
bool touchesGlobal = false;
/** The conservative "I touch everything" footprint. */
[[nodiscard]] static AccessSet
global()
{
AccessSet a;
a.touchesGlobal = true;
return a;
}
/** The flat union of every declared entry key, across all categories. */
[[nodiscard]] std::set<uint256>
keys() const
{
std::set<uint256> out;
for (auto const* s :
{&accounts, &trustlines, &offerBooks, &ammPools, &nftPages, &miscObjects})
out.insert(s->begin(), s->end());
return out;
}
/** True if these two transactions cannot safely apply concurrently.
Either side touching global state forces a conflict; otherwise the two
conflict iff their declared key sets intersect.
*/
[[nodiscard]] bool
conflictsWith(AccessSet const& other) const
{
if (touchesGlobal || other.touchesGlobal)
return true;
auto const a = keys();
auto const b = other.keys();
auto i = a.begin();
auto j = b.begin();
while (i != a.end() && j != b.end())
{
if (*i < *j)
++i;
else if (*j < *i)
++j;
else
return true;
}
return false;
}
};
} // namespace xrpl

View File

@@ -93,8 +93,8 @@ public:
std::function<void(
uint256 const& key,
bool isDelete,
SLE::const_ref before,
SLE::const_ref after)> const& func);
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)> const& func);
void
destroyXRP(XRPAmount const& fee)
@@ -112,6 +112,24 @@ public:
TER
checkInvariants(TER const result, XRPAmount const fee);
#ifndef NDEBUG
/** The read-only base (closed-ledger) snapshot this tx applies against. */
[[nodiscard]] ReadView const&
baseView() const
{
return base_;
}
/** Every ledger entry touched during apply, with type. Backs the
access-set assertion in Transactor::operator(). */
[[nodiscard]] std::map<uint256, LedgerEntryType> const&
touchedEntries() const
{
// NOLINTNEXTLINE(bugprone-unchecked-optional-access) view_ emplaced in ctor
return view_->touchedEntries();
}
#endif
private:
static TER
failInvariantCheck(TER const result);

128
include/xrpl/tx/Schedule.h Normal file
View File

@@ -0,0 +1,128 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/RawView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/tx/AccessSet.h>
#include <cstddef>
#include <memory>
#include <vector>
namespace xrpl {
class ServiceRegistry;
/** A maximal set of transactions that conflict (transitively) with each other.
The transactions are held in canonical (input) order, which is significant:
within a group they must be applied serially in this order. Two distinct
groups are independent by construction — their declared access sets are
disjoint — so groups may be applied concurrently, and the order in which
groups are applied does not affect the resulting state.
*/
struct ConflictGroup
{
std::vector<std::shared_ptr<STTx const>> txns;
};
/** The partitioning of a canonically-ordered transaction set for parallel
application.
Either the set was partitioned into independent `groups` (the parallel
case), or scheduling fell back to a single serial ordering in `serial`
(the conservative case — see `scheduleApply`). Exactly one of the two is
populated; `fullySerial` says which.
*/
struct Schedule
{
std::vector<ConflictGroup> groups;
std::vector<std::shared_ptr<STTx const>> serial;
bool fullySerial = false;
/** Total transactions scheduled, across groups or the serial list. */
[[nodiscard]] std::size_t
size() const
{
if (fullySerial)
return serial.size();
std::size_t n = 0;
for (auto const& g : groups)
n += g.txns.size();
return n;
}
};
/** Partition a canonically-ordered transaction set into independent groups by
static access-set conflict, for parallel application.
For each transaction, `accessSetOf` is consulted against `base` (the closed
-ledger snapshot the round applies to). Transactions are unioned into the
same group iff their access sets conflict — i.e. they share any declared
ledger entry, or (implicitly, via the access set) act on the same account.
If ANY transaction declares `touchesGlobal` (a pseudo-transaction such as
SetFee/EnableAmendment/UNLModify, or any not-yet-migrated transactor), the
schedule falls back to fully serial in canonical order. This is the
conservative flag-ledger handling: correctness over throughput, at a cost of
~1/256 of ledgers. A later version may apply the global transactions first
and parallelize the remainder.
Deterministic: identical input yields an identical schedule (groups are
ordered by their lowest canonical index, transactions within a group keep
canonical order). Applies nothing and reads only `base`.
*/
Schedule
scheduleApply(std::vector<std::shared_ptr<STTx const>> const& txns, ReadView const& base);
/** Outcome of applyScheduled. */
struct ScheduledApplyResult
{
std::size_t groupCount = 0; // independent groups (1 if fully serial)
std::size_t applied = 0; // transactions that applied successfully
bool fullySerial = false;
};
/** Apply a canonically-ordered transaction set via its schedule.
Schedules `txns` (see `scheduleApply`), then applies each independent group
in its own `OpenView` layered over the immutable `closed` snapshot, and
merges the per-group write-sets into `to`. Because distinct groups have
disjoint access sets, their write-sets are disjoint and the merge is
order-independent — so the resulting state in `to` is byte-identical to a
serial canonical apply. (That equivalence is what the differential test
asserts, and it is the correctness contract a parallel executor relies on.)
`workers` controls concurrency of the per-group apply phase:
- `workers <= 1`: groups applied sequentially (deterministic baseline).
- `workers > 1`: up to `workers` groups apply concurrently, each in its own
view over the immutable `closed` snapshot; the write-sets are then merged
into `to` sequentially in deterministic group order.
The result is identical for any `workers` value (the merge is order-
independent because groups are disjoint, and is performed in a fixed order).
NOTE on the threaded path: it is correct by construction here, but it is NOT
certified for production consensus use. A non-deterministic apply forks the
network, so before the threaded path may be trusted it needs ThreadSanitizer
clean runs, adversarial scheduling (Antithesis), and a mainnet-history replay
differential — none of which a unit test establishes. The concurrent reads
of `closed` and the shared `registry` are the surfaces that must be cleared.
@param registry service registry used by the apply pipeline.
@param closed the immutable closed-ledger snapshot to read and schedule against.
@param to the target ledger receiving the merged writes.
@param txns transactions in canonical order.
@param j journal.
@param workers max concurrent group-apply threads (default 1 = sequential).
*/
ScheduledApplyResult
applyScheduled(
ServiceRegistry& registry,
ReadView const& closed,
TxsRawView& to,
std::vector<std::shared_ptr<STTx const>> const& txns,
beast::Journal j,
unsigned workers = 1);
} // namespace xrpl

View File

@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/WrappedSink.h>
#include <xrpl/protocol/Permissions.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/AccessSet.h>
#include <xrpl/tx/ApplyContext.h>
#include <xrpl/tx/applySteps.h>
@@ -222,10 +223,39 @@ public:
return tesSUCCESS;
}
/** The static ledger footprint this transaction may read or write.
Consumed by the parallel-apply scheduler to decide which transactions
can apply concurrently. The base implementation is fail-safe: it
declares `touchesGlobal`, so an un-migrated transactor is serialized
against everything. A transactor opts into concurrency by hiding this
with its own static `accessSetOf` that enumerates exactly what it
touches. Like preclaim/calculateBaseFee, this is dispatched by
compile-time name hiding, not virtual dispatch.
@param tx the signed transaction.
@param base a read-only snapshot of the ledger the tx applies to, for
the few transactors whose footprint needs a state lookup
(e.g. resolving an AMM pseudo-account). Most ignore it.
*/
static AccessSet
accessSetOf(STTx const& tx, ReadView const& base)
{
return AccessSet::global();
}
static NotTEC
checkPermission(ReadView const& view, STTx const& tx);
/////////////////////////////////////////////////////
/** The ledger footprint every transaction incurs, regardless of type: the
actor's AccountRoot, the fee-payer's AccountRoot (when delegated), and
the consumed Ticket object (when ticket-sequenced). Directory pages are
excluded by design — see AccessSet. A migrated `accessSetOf` seeds its
result with this and adds its type-specific entries. */
static AccessSet
commonAccountFootprint(STTx const& tx);
// Interface used by AccountDelete
static TER
ticketDelete(
@@ -263,7 +293,10 @@ protected:
* to detect deletions.
*/
virtual void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) = 0;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) = 0;
/** Check transaction-specific post-conditions after all entries have
* been visited.
@@ -365,7 +398,7 @@ private:
ReadView const& view,
AccountID const& idSigner,
AccountID const& idAccount,
SLE::const_pointer sleAccount,
std::shared_ptr<SLE const> sleAccount,
beast::Journal const j);
static NotTEC
checkMultiSign(
@@ -377,6 +410,15 @@ private:
void trapTransaction(uint256) const;
#ifndef NDEBUG
/** DEBUG: assert the transaction's actual ledger footprint is a subset of
the access set declared by `accessSetOf`, or — for `touchesGlobal`
transactors — optionally record the measured footprint for the
hard-transactor audit. Called only on a clean tesSUCCESS apply. */
void
verifyAccessSet() const;
#endif
/** Performs early sanity checks on the account and fee fields.
(And passes flagMask to preflight0)

View File

@@ -2,6 +2,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyViewImpl.h>
#include <xrpl/tx/AccessSet.h>
namespace xrpl {
@@ -308,6 +309,19 @@ preclaim(PreflightResult const& preflightResult, ServiceRegistry& registry, Open
XRPAmount
calculateBaseFee(ReadView const& view, STTx const& tx);
/** Compute the static ledger footprint of a transaction.
Dispatches to the concrete transactor's `accessSetOf`. Un-migrated
transactors return `touchesGlobal`. Used by the parallel-apply scheduler
(and the DEBUG access-set assertion) to reason about which transactions can
apply concurrently. No validation is implied.
@param tx the transaction.
@param base a read-only snapshot of the ledger the tx applies to.
*/
AccessSet
accessSetOf(STTx const& tx, ReadView const& base);
/** Return the minimum fee that an "ordinary" transaction would pay.
When computing the FeeLevel for a transaction the TxQ sometimes needs

View File

@@ -22,7 +22,7 @@ public:
ValidAMM() = default;
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -22,7 +22,7 @@ class TransfersNotFrozen
{
struct BalanceChange
{
SLE::const_pointer const line;
std::shared_ptr<SLE const> const line;
int const balanceChangeSign;
};
@@ -35,34 +35,37 @@ class TransfersNotFrozen
using ByIssuer = std::map<Issue, IssuerChanges>;
ByIssuer balanceChanges_;
std::map<AccountID, SLE::const_pointer const> possibleIssuers_;
std::map<AccountID, std::shared_ptr<SLE const> const> possibleIssuers_;
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
private:
bool
isValidEntry(SLE::const_ref before, SLE::const_ref after);
isValidEntry(std::shared_ptr<SLE const> const& before, std::shared_ptr<SLE const> const& after);
static STAmount
calculateBalanceChange(SLE::const_ref before, SLE::const_ref after, bool isDelete);
calculateBalanceChange(
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after,
bool isDelete);
void
recordBalance(Issue const& issue, BalanceChange change);
void
recordBalanceChanges(SLE::const_ref after, STAmount const& balanceChange);
recordBalanceChanges(std::shared_ptr<SLE const> const& after, STAmount const& balanceChange);
SLE::const_pointer
std::shared_ptr<SLE const>
findIssuer(AccountID const& issuerID, ReadView const& view);
static bool
validateIssuerChanges(
SLE::const_ref issuer,
std::shared_ptr<SLE const> const& issuer,
IssuerChanges const& changes,
STTx const& tx,
beast::Journal const& j,

View File

@@ -70,7 +70,10 @@ public:
* @param after ledger entry after modification by the transaction
*/
void
visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after);
visitEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after);
/**
* @brief called after all ledger entries have been visited to determine
@@ -108,7 +111,7 @@ class TransactionFeeCheck
{
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
static bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
@@ -128,7 +131,7 @@ class XRPNotCreated
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -148,7 +151,7 @@ class AccountRootsNotDeleted
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -171,11 +174,11 @@ class AccountRootsDeletedClean
// deleted, it can still be found. After is used specifically for any checks
// that are expected as part of the deletion, such as zeroing out the
// balance.
std::vector<std::pair<SLE::const_pointer, SLE::const_pointer>> accountsDeleted_;
std::vector<std::pair<std::shared_ptr<SLE const>, std::shared_ptr<SLE const>>> accountsDeleted_;
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
@@ -194,7 +197,7 @@ class XRPBalanceChecks
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -211,7 +214,7 @@ class LedgerEntryTypesMatch
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -229,7 +232,7 @@ class NoXRPTrustLines
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -248,7 +251,7 @@ class NoDeepFreezeTrustLinesWithoutFreeze
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -267,7 +270,7 @@ class NoBadOffers
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -283,7 +286,7 @@ class NoZeroEscrow
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -303,7 +306,7 @@ class ValidNewAccountRoot
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -324,7 +327,7 @@ class ValidClawback
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -344,7 +347,7 @@ class ValidPseudoAccounts
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);
@@ -364,7 +367,7 @@ class NoModifiedUnmodifiableFields
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -46,7 +46,7 @@ class ValidLoanBroker
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -23,7 +23,7 @@ class ValidLoan
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -37,7 +37,7 @@ class ValidMPTIssuance
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -65,7 +65,7 @@ class ValidMPTPayment
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -33,7 +33,7 @@ class ValidNFTokenPage
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;
@@ -61,7 +61,7 @@ class NFTokenCountTracking
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
[[nodiscard]] bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&) const;

View File

@@ -18,7 +18,7 @@ class ValidPermissionedDEX
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -32,7 +32,7 @@ class ValidPermissionedDomain
public:
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -154,7 +154,7 @@ public:
computeCoarsestScale(std::vector<DeltaInfo> const& numbers);
void
visitEntry(bool, SLE::const_ref, SLE::const_ref);
visitEntry(bool, std::shared_ptr<SLE const> const&, std::shared_ptr<SLE const> const&);
bool
finalize(STTx const&, TER const, XRPAmount const, ReadView const&, beast::Journal const&);

View File

@@ -21,7 +21,7 @@ private:
uint256 end_;
uint256 dir_;
uint256 index_;
SLE::pointer entry_;
std::shared_ptr<SLE> entry_;
Quality quality_{};
public:

View File

@@ -352,7 +352,7 @@ qualityUpperBound(ReadView const& v, Strand const& strand)
* increases quality of AMM steps, increasing the strand's composite
* quality as the result.
*/
template <StepAmount TOutAmt>
template <typename TOutAmt>
inline TOutAmt
limitOut(
ReadView const& v,
@@ -390,29 +390,21 @@ limitOut(
auto const out = qf->outFromAvgQ(limitQuality);
if (!out)
return remainingOut;
if constexpr (std::is_same_v<TOutAmt, XRPAmount> || std::is_same_v<TOutAmt, MPTAmount>)
if constexpr (std::is_same_v<TOutAmt, XRPAmount>)
{
auto const roundedOut = TOutAmt{*out};
// Integral outputs that round above the continuous target can
// realize worse average quality than the requested limit. Keep the
// default rounded value when it still satisfies the limit, since it
// is the largest matching offer; otherwise round down.
if (v.rules().enabled(featureMPTokensV2) && roundedOut > *out &&
!qf->satisfiesAvgQ(limitQuality, roundedOut))
{
NumberRoundModeGuard const g(Number::RoundingMode::Downward);
return TOutAmt{*out};
}
return roundedOut;
return XRPAmount{*out};
}
else if constexpr (std::is_same_v<TOutAmt, IOUAmount>)
{
return IOUAmount{*out};
}
else if constexpr (std::is_same_v<TOutAmt, MPTAmount>)
{
return MPTAmount{*out};
}
else
{
static constexpr bool kAlwaysFalse = !std::is_same_v<TOutAmt, TOutAmt>;
static_assert(kAlwaysFalse, "Unhandled StepAmount type");
return STAmount{remainingOut.asset(), out->mantissa(), out->exponent()};
}
}();
// A tiny difference could be due to the round off

View File

@@ -29,7 +29,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

View File

@@ -29,11 +29,17 @@ public:
static TER
preclaim(PreclaimContext const& ctx);
static AccessSet
accessSetOf(STTx const& tx, ReadView const& base);
TER
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

View File

@@ -19,11 +19,17 @@ public:
static XRPAmount
calculateBaseFee(ReadView const& view, STTx const& tx);
static AccessSet
accessSetOf(STTx const& tx, ReadView const& base);
TER
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

View File

@@ -36,13 +36,19 @@ public:
static NotTEC
preflight(PreflightContext const& ctx);
static AccessSet
accessSetOf(STTx const& tx, ReadView const& base);
TER
doApply() override;
void
preCompute() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

View File

@@ -28,7 +28,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -61,7 +64,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -105,7 +111,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -143,7 +152,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -183,7 +195,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -223,7 +238,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -254,7 +272,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(
@@ -309,7 +330,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

View File

@@ -23,7 +23,10 @@ public:
doApply() override;
void
visitInvariantEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) override;
visitInvariantEntry(
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after) override;
[[nodiscard]] bool
finalizeInvariants(

Some files were not shown because too many files have changed in this diff Show More