mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-23 23:20:33 +00:00
Compare commits
1 Commits
ximinez/di
...
dangell7/e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7bfd6a7e1 |
4
.github/workflows/build-nix-images.yml
vendored
4
.github/workflows/build-nix-images.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Build `nix` Docker images
|
||||
name: Build Nix Docker images
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -36,7 +36,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build-merge:
|
||||
name: Build and push `nix-${{ matrix.distro.name }}` image
|
||||
name: Build and push nix-${{ matrix.distro.name }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
4
.github/workflows/build-packaging-images.yml
vendored
4
.github/workflows/build-packaging-images.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Build `packaging` Docker images
|
||||
name: Build packaging Docker images
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -26,7 +26,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
build-merge:
|
||||
name: Build and push `packaging-${{ matrix.distro.name }}` image
|
||||
name: Build and push packaging-${{ matrix.distro.name }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
38
.github/workflows/build-pre-commit-image.yml
vendored
38
.github/workflows/build-pre-commit-image.yml
vendored
@@ -1,38 +0,0 @@
|
||||
name: Build `pre-commit` Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- ".github/workflows/build-pre-commit-image.yml"
|
||||
- "bin/pre-commit/Dockerfile"
|
||||
- "rust-toolchain.toml"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build-pre-commit-image.yml"
|
||||
- "bin/pre-commit/Dockerfile"
|
||||
- "rust-toolchain.toml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# Read `on-trigger.yml` for the rationale behind this concurrency group name.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' && github.sha || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build-merge:
|
||||
name: Build and push `pre-commit` image
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@ee03d31bcc4501d7599dc1b1ecd7a34af582ad1c
|
||||
with:
|
||||
image_name: xrpld/pre-commit
|
||||
dockerfile: bin/pre-commit/Dockerfile
|
||||
base_image: ubuntu:26.04
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -17,4 +17,4 @@ jobs:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@1bde119a1ab71305ba5d3716e7a82cea1c7bdede
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-f56b79f" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
|
||||
|
||||
42
.github/workflows/reusable-build-test-config.yml
vendored
42
.github/workflows/reusable-build-test-config.yml
vendored
@@ -223,13 +223,11 @@ jobs:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}" \
|
||||
2>&1 | tee "${GITHUB_WORKSPACE}/build.log"
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Show ccache statistics
|
||||
if: ${{ inputs.ccache_enabled }}
|
||||
@@ -324,7 +322,7 @@ jobs:
|
||||
PRELOAD=""
|
||||
fi
|
||||
|
||||
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee "${GITHUB_WORKSPACE}/unittest.log"
|
||||
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
|
||||
|
||||
# Smoke-run every benchmark module with a single repetition to confirm the
|
||||
# benchmarks still build and execute. This is a correctness check, not a
|
||||
@@ -343,27 +341,25 @@ jobs:
|
||||
done < <(find src/benchmarks -type f -perm -u+x -name 'xrpl.bench.*')
|
||||
exit "${rc}"
|
||||
|
||||
- name: Show build/test failure summary
|
||||
if: ${{ failure() }}
|
||||
- name: Show test failure summary
|
||||
if: ${{ failure() && !inputs.build_only }}
|
||||
env:
|
||||
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
|
||||
run: |
|
||||
cd "${GITHUB_WORKSPACE}"
|
||||
if [ ! -d "${WORKING_DIR}" ]; then
|
||||
echo "Working directory '${WORKING_DIR}' does not exist."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -f unittest.log ]; then
|
||||
if ! grep -E "failed" unittest.log | grep -vE "^I[0-9]|^[0-9]+> (ERR:|FTL:)"; then
|
||||
echo "unittest.log present but no failure lines found."
|
||||
fi
|
||||
elif [ -f build.log ]; then
|
||||
# GCC/Clang emit "error:" (covers "fatal error:"); MSVC emits
|
||||
# "error C####:", "error LNK####:", and "fatal error LNK####:".
|
||||
# -A6 prints the lines that follow each match (source line, caret,
|
||||
# notes, and the "N errors generated" tally) to capture the whole
|
||||
# diagnostic block.
|
||||
if ! grep -E -A6 "error:|error C[0-9]{4}|error LNK[0-9]{4}|fatal error" build.log; then
|
||||
echo "build.log present but no compile errors found."
|
||||
fi
|
||||
else
|
||||
echo "unittest.log/build.log not found; something went wrong."
|
||||
exit 1
|
||||
cd "${WORKING_DIR}"
|
||||
|
||||
if [ ! -f unittest.log ]; then
|
||||
echo "unittest.log not found; embedded tests may not have run."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! grep -E "failed" unittest.log; then
|
||||
echo "Log present but no failure lines found in unittest.log."
|
||||
fi
|
||||
- name: Debug failure (Linux)
|
||||
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
|
||||
|
||||
2
.github/workflows/reusable-package.yml
vendored
2
.github/workflows/reusable-package.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||||
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ repos:
|
||||
types_or: [c++, c]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: f4d7745e17a28aad7eed2f4874ca8d1568c11c4c # frozen: v22.1.8
|
||||
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=file]
|
||||
@@ -68,7 +68,7 @@ repos:
|
||||
- id: gersemi
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: 9337a74165b178ae2c766f60bee7252a0f06f3e8 # frozen: v3.9.5
|
||||
rev: 39e2973981e6d2f9b6c543b0086a2d2393abdc89 # frozen: v3.9.4
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: [--end-of-line=auto]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# By default, anyone can review changes.
|
||||
|
||||
# The CI tooling team should review changes to the CI configuration.
|
||||
/.github/ @XRPLF/ci-tooling
|
||||
@@ -1,55 +0,0 @@
|
||||
ARG BASE_IMAGE=ubuntu:26.04
|
||||
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN <<EOF
|
||||
pkgs=()
|
||||
pkgs+=(curl) # Required to install nix.
|
||||
pkgs+=(doxygen) # Needed for Clio's check-doxygen-docs.sh.
|
||||
pkgs+=(git) # Required for prepare-runner.
|
||||
pkgs+=(libatomic1) # Required to run pre-commit provided `node`.
|
||||
pkgs+=(python3) # Python 3 interpreter.
|
||||
pkgs+=(python3-pip) # Package manager for Python applications.
|
||||
pkgs+=(xz-utils) # Required to install nix
|
||||
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends "${pkgs[@]}"
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
EOF
|
||||
|
||||
ARG PRE_COMMIT_VERSION=4.6.0
|
||||
RUN pip install --no-cache --break-system-packages \
|
||||
pre-commit==${PRE_COMMIT_VERSION}
|
||||
|
||||
RUN sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) --daemon --yes
|
||||
|
||||
# Add nix to PATH and set NIX environment variables,
|
||||
# so nix is available in all shells including non-interactive shells (e.g., GitHub Actions).
|
||||
ENV PATH="/nix/var/nix/profiles/default/bin:${PATH}"
|
||||
ENV NIX_PROFILES="/nix/var/nix/profiles/default"
|
||||
ENV NIX_SSL_CERT_FILE="/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
|
||||
# Verify nix installation
|
||||
RUN nix --version
|
||||
|
||||
ENV RUSTUP_HOME="/opt/rust/rustup"
|
||||
ENV CARGO_HOME="/opt/rust/cargo"
|
||||
ENV PATH="/opt/rust/cargo/bin:${PATH}"
|
||||
|
||||
WORKDIR /tmp
|
||||
COPY rust-toolchain.toml /tmp/rust-toolchain.toml
|
||||
RUN <<EOF
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
|
||||
| sh -s -- -y --no-modify-path --profile minimal --default-toolchain none
|
||||
rustup toolchain install
|
||||
rustup show
|
||||
cargo fmt --version
|
||||
EOF
|
||||
|
||||
WORKDIR /
|
||||
@@ -20,22 +20,6 @@ compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
|
||||
{% endif %}
|
||||
|
||||
[conf]
|
||||
{# The Boost recipe builds with b2, which doesn't use Conan's toolchain files. #}
|
||||
{# Instead it hand-rolls the compiler for user-config.jam, #}
|
||||
{# and its fallback probes a version-suffixed binary (e.g. `g++-15`) before plain `g++`. #}
|
||||
{# Inside the Nix shell the wrapper only provides `g++`/`gcc` (no `-15` suffix), #}
|
||||
{# so on a host that also has a system `g++-15` the probe escapes Nix #}
|
||||
{# and picks the system compiler, which is mismatched with the Nix libraries #}
|
||||
{# and breaks the build (e.g. Boost.Stacktrace link checks fail). #}
|
||||
{# Pinning the executables here short-circuits that probe so Boost (and the rest of the toolchain) #}
|
||||
{# resolve the same compiler. #}
|
||||
{# Not part of the package ID, so binaries stay shareable. #}
|
||||
{% if os != "Windows" %}
|
||||
{% set cc_exe = {"gcc": "gcc", "clang": "clang", "apple-clang": "clang"}.get(compiler) %}
|
||||
{% set cxx_exe = {"gcc": "g++", "clang": "clang++", "apple-clang": "clang++"}.get(compiler) %}
|
||||
tools.build:compiler_executables={'c':'{{ cc_exe }}','cpp':'{{ cxx_exe }}'}
|
||||
{% endif %}
|
||||
|
||||
{# By default, Conan tries to reuse binaries built with different cppstd versions. #}
|
||||
{# We want to avoid that to improve reproduceability, so we add the cppstd version to the package ID. #}
|
||||
{# More info: https://docs.conan.io/2/reference/extensions/binary_compatibility.html #}
|
||||
|
||||
@@ -17,11 +17,46 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* Type-specific prefix for calculating ledger indices.
|
||||
*
|
||||
* The identifier for a given object within the ledger is calculated based
|
||||
* on some object-specific parameters. To ensure that different types of
|
||||
* objects have different indices, even if they happen to use the same set
|
||||
* of parameters, we use "tagged hashing" by adding a type-specific prefix.
|
||||
*
|
||||
* The name spaces are listed in detail/ledger_name_spaces.macro.
|
||||
*/
|
||||
#pragma push_macro("LEDGER_NAME_SPACE")
|
||||
#undef LEDGER_NAME_SPACE
|
||||
#pragma push_macro("LEDGER_NAME_SPACE_DEPRECATED")
|
||||
#undef LEDGER_NAME_SPACE_DEPRECATED
|
||||
|
||||
#define LEDGER_NAME_SPACE(name, value) name = (value),
|
||||
#define LEDGER_NAME_SPACE_DEPRECATED(name, value) name [[deprecated]] = (value),
|
||||
|
||||
enum class LedgerNameSpace : std::uint16_t {
|
||||
#include <xrpl/protocol/detail/ledger_name_spaces.macro>
|
||||
};
|
||||
|
||||
#undef LEDGER_NAME_SPACE_DEPRECATED
|
||||
#pragma pop_macro("LEDGER_NAME_SPACE_DEPRECATED")
|
||||
#undef LEDGER_NAME_SPACE
|
||||
#pragma pop_macro("LEDGER_NAME_SPACE")
|
||||
|
||||
/**
|
||||
* The name->value map of active (non-deprecated) ledger name spaces.
|
||||
*/
|
||||
std::map<std::string, std::uint16_t> const&
|
||||
ledgerNameSpaceMap();
|
||||
|
||||
class SeqProxy;
|
||||
/**
|
||||
* Keylet computation functions.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(DefragDirectories, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Sponsor, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(BatchV1_1, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocolV1_1, Supported::No, VoteBehavior::DefaultNo)
|
||||
|
||||
59
include/xrpl/protocol/detail/ledger_name_spaces.macro
Normal file
59
include/xrpl/protocol/detail/ledger_name_spaces.macro
Normal file
@@ -0,0 +1,59 @@
|
||||
#if !defined(LEDGER_NAME_SPACE)
|
||||
#error "undefined macro: LEDGER_NAME_SPACE"
|
||||
#endif
|
||||
#if !defined(LEDGER_NAME_SPACE_DEPRECATED)
|
||||
#error "undefined macro: LEDGER_NAME_SPACE_DEPRECATED"
|
||||
#endif
|
||||
|
||||
// Active ledger name spaces.
|
||||
//
|
||||
// @note These values are part of the protocol and *CANNOT* be arbitrarily
|
||||
// changed. If they were, on-ledger objects may no longer be able to
|
||||
// be located or addressed.
|
||||
//
|
||||
// Additions to this list are OK, but changing existing entries to
|
||||
// assign them a different values should never be needed.
|
||||
//
|
||||
// Entries that are removed should be moved to the deprecated list
|
||||
// below to prevent accidental reuse.
|
||||
LEDGER_NAME_SPACE(Account, 'a')
|
||||
LEDGER_NAME_SPACE(DirNode, 'd')
|
||||
LEDGER_NAME_SPACE(TrustLine, 'r')
|
||||
LEDGER_NAME_SPACE(Offer, 'o')
|
||||
LEDGER_NAME_SPACE(OwnerDir, 'O')
|
||||
LEDGER_NAME_SPACE(BookDir, 'B')
|
||||
LEDGER_NAME_SPACE(SkipList, 's')
|
||||
LEDGER_NAME_SPACE(Escrow, 'u')
|
||||
LEDGER_NAME_SPACE(Amendments, 'f')
|
||||
LEDGER_NAME_SPACE(FeeSettings, 'e')
|
||||
LEDGER_NAME_SPACE(Ticket, 'T')
|
||||
LEDGER_NAME_SPACE(SignerList, 'S')
|
||||
LEDGER_NAME_SPACE(XRPPaymentChannel, 'x')
|
||||
LEDGER_NAME_SPACE(Check, 'C')
|
||||
LEDGER_NAME_SPACE(DepositPreauth, 'p')
|
||||
LEDGER_NAME_SPACE(DepositPreauthCredentials, 'P')
|
||||
LEDGER_NAME_SPACE(NegativeUnl, 'N')
|
||||
LEDGER_NAME_SPACE(NftokenOffer, 'q')
|
||||
LEDGER_NAME_SPACE(NftokenBuyOffers, 'h')
|
||||
LEDGER_NAME_SPACE(NftokenSellOffers, 'i')
|
||||
LEDGER_NAME_SPACE(Amm, 'A')
|
||||
LEDGER_NAME_SPACE(Bridge, 'H')
|
||||
LEDGER_NAME_SPACE(XchainClaimId, 'Q')
|
||||
LEDGER_NAME_SPACE(XchainCreateAccountClaimId, 'K')
|
||||
LEDGER_NAME_SPACE(Did, 'I')
|
||||
LEDGER_NAME_SPACE(Oracle, 'R')
|
||||
LEDGER_NAME_SPACE(MPTokenIssuance, '~')
|
||||
LEDGER_NAME_SPACE(MPToken, 't')
|
||||
LEDGER_NAME_SPACE(Credential, 'D')
|
||||
LEDGER_NAME_SPACE(PermissionedDomain, 'm')
|
||||
LEDGER_NAME_SPACE(Delegate, 'E')
|
||||
LEDGER_NAME_SPACE(Vault, 'V')
|
||||
LEDGER_NAME_SPACE(LoanBroker, 'l') // lower-case L
|
||||
LEDGER_NAME_SPACE(Loan, 'L')
|
||||
LEDGER_NAME_SPACE(Sponsorship, '>')
|
||||
|
||||
// No longer used or supported. Left here to reserve the space to avoid
|
||||
// accidental reuse, and intentionally not exported to clients.
|
||||
LEDGER_NAME_SPACE_DEPRECATED(Contract, 'c')
|
||||
LEDGER_NAME_SPACE_DEPRECATED(Generator, 'g')
|
||||
LEDGER_NAME_SPACE_DEPRECATED(Nickname, 'n')
|
||||
@@ -350,6 +350,7 @@ JSS(LEDGER_ENTRY_TYPES); // out: RPC server_definitions
|
||||
// matches definitions.json format
|
||||
JSS(LEDGER_ENTRY_FLAGS); // out: RPC server_definitions
|
||||
JSS(LEDGER_ENTRY_FORMATS); // out: RPC server_definitions
|
||||
JSS(LEDGER_NAME_SPACES); // out: RPC server_definitions
|
||||
JSS(levels); // LogLevels
|
||||
JSS(limit); // in/out: AccountTx*, AccountOffers, AccountLines, AccountObjects
|
||||
// in: LedgerData, BookOffers
|
||||
|
||||
@@ -26,14 +26,6 @@ namespace xrpl {
|
||||
|
||||
namespace directory {
|
||||
|
||||
struct Gap
|
||||
{
|
||||
uint64_t const page;
|
||||
SLE::pointer node;
|
||||
uint64_t const nextPage;
|
||||
SLE::pointer next;
|
||||
};
|
||||
|
||||
std::uint64_t
|
||||
createRoot(
|
||||
ApplyView& view,
|
||||
@@ -134,9 +126,7 @@ insertPage(
|
||||
if (page == 0)
|
||||
return std::nullopt;
|
||||
if (!view.rules().enabled(fixDirectoryLimit) && page >= kDirNodeMaxPages) // Old pages limit
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// We are about to create a new node; we'll link it to
|
||||
// the chain first:
|
||||
@@ -157,8 +147,12 @@ insertPage(
|
||||
// Save some space by not specifying the value 0 since it's the default.
|
||||
if (page != 1)
|
||||
node->setFieldU64(sfIndexPrevious, page - 1);
|
||||
XRPL_ASSERT_PARTS(!nextPage, "xrpl::directory::insertPage", "nextPage has default value");
|
||||
/* Reserved for future use when directory pages may be inserted in
|
||||
* between two other pages instead of only at the end of the chain.
|
||||
if (nextPage)
|
||||
node->setFieldU64(sfIndexNext, nextPage);
|
||||
*/
|
||||
describe(node);
|
||||
view.insert(node);
|
||||
|
||||
@@ -174,7 +168,7 @@ ApplyView::dirAdd(
|
||||
uint256 const& key,
|
||||
std::function<void(SLE::ref)> const& describe)
|
||||
{
|
||||
auto const root = peek(directory);
|
||||
auto root = peek(directory);
|
||||
|
||||
if (!root)
|
||||
{
|
||||
@@ -184,43 +178,6 @@ ApplyView::dirAdd(
|
||||
|
||||
auto [page, node, indexes] = directory::findPreviousPage(*this, directory, root);
|
||||
|
||||
if (rules().enabled(featureDefragDirectories))
|
||||
{
|
||||
// If there are more nodes than just the root, and there's no space in
|
||||
// the last one, walk backwards to find one with space, or to find one
|
||||
// missing.
|
||||
std::optional<directory::Gap> gapPages;
|
||||
while (page && indexes.size() >= kDIR_NODE_MAX_PAGES)
|
||||
{
|
||||
// Find a page with space, or a gap in pages.
|
||||
auto [prevPage, prevNode, prevIndexes] =
|
||||
directory::findPreviousPage(*this, directory, node);
|
||||
if (!gapPages && prevPage != page - 1)
|
||||
gapPages.emplace(prevPage, prevNode, page, node);
|
||||
page = prevPage;
|
||||
node = prevNode;
|
||||
indexes = prevIndexes;
|
||||
}
|
||||
// We looped through all the pages back to the root.
|
||||
if (!page)
|
||||
{
|
||||
// If we found a gap, use it.
|
||||
if (gapPages)
|
||||
{
|
||||
return directory::insertPage(
|
||||
*this,
|
||||
gapPages->page,
|
||||
gapPages->node,
|
||||
gapPages->nextPage,
|
||||
gapPages->next,
|
||||
key,
|
||||
directory,
|
||||
describe);
|
||||
}
|
||||
std::tie(page, node, indexes) = directory::findPreviousPage(*this, directory, root);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's space, we use it:
|
||||
if (indexes.size() < kDirNodeMaxEntries)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
@@ -50,66 +52,28 @@ std::array<KeyletDesc<AccountID const&>, 6> const kDirectAccountKeylets{
|
||||
.includeInTests = true},
|
||||
{.function = &keylet::did, .expectedLEName = jss::DID, .includeInTests = true}}};
|
||||
|
||||
/**
|
||||
* Type-specific prefix for calculating ledger indices.
|
||||
*
|
||||
* The identifier for a given object within the ledger is calculated based
|
||||
* on some object-specific parameters. To ensure that different types of
|
||||
* objects have different indices, even if they happen to use the same set
|
||||
* of parameters, we use "tagged hashing" by adding a type-specific prefix.
|
||||
*
|
||||
* @note These values are part of the protocol and *CANNOT* be arbitrarily
|
||||
* changed. If they were, on-ledger objects may no longer be able to
|
||||
* be located or addressed.
|
||||
*
|
||||
* Additions to this list are OK, but changing existing entries to
|
||||
* assign them a different values should never be needed.
|
||||
*
|
||||
* Entries that are removed should be moved to the bottom of the enum
|
||||
* and marked as [[deprecated]] to prevent accidental reuse.
|
||||
*/
|
||||
enum class LedgerNameSpace : std::uint16_t {
|
||||
Account = 'a',
|
||||
DirNode = 'd',
|
||||
TrustLine = 'r',
|
||||
Offer = 'o',
|
||||
OwnerDir = 'O',
|
||||
BookDir = 'B',
|
||||
SkipList = 's',
|
||||
Escrow = 'u',
|
||||
Amendments = 'f',
|
||||
FeeSettings = 'e',
|
||||
Ticket = 'T',
|
||||
SignerList = 'S',
|
||||
XRPPaymentChannel = 'x',
|
||||
Check = 'C',
|
||||
DepositPreauth = 'p',
|
||||
DepositPreauthCredentials = 'P',
|
||||
NegativeUnl = 'N',
|
||||
NftokenOffer = 'q',
|
||||
NftokenBuyOffers = 'h',
|
||||
NftokenSellOffers = 'i',
|
||||
Amm = 'A',
|
||||
Bridge = 'H',
|
||||
XchainClaimId = 'Q',
|
||||
XchainCreateAccountClaimId = 'K',
|
||||
Did = 'I',
|
||||
Oracle = 'R',
|
||||
MPTokenIssuance = '~',
|
||||
MPToken = 't',
|
||||
Credential = 'D',
|
||||
PermissionedDomain = 'm',
|
||||
Delegate = 'E',
|
||||
Vault = 'V',
|
||||
LoanBroker = 'l', // lower-case L
|
||||
Loan = 'L',
|
||||
Sponsorship = '>',
|
||||
std::map<std::string, std::uint16_t> const&
|
||||
ledgerNameSpaceMap()
|
||||
{
|
||||
#pragma push_macro("LEDGER_NAME_SPACE")
|
||||
#undef LEDGER_NAME_SPACE
|
||||
#pragma push_macro("LEDGER_NAME_SPACE_DEPRECATED")
|
||||
#undef LEDGER_NAME_SPACE_DEPRECATED
|
||||
|
||||
// No longer used or supported. Left here to reserve the space to avoid accidental reuse.
|
||||
Contract [[deprecated]] = 'c',
|
||||
Generator [[deprecated]] = 'g',
|
||||
Nickname [[deprecated]] = 'n',
|
||||
};
|
||||
#define LEDGER_NAME_SPACE(name, value) {#name, static_cast<std::uint16_t>(LedgerNameSpace::name)},
|
||||
#define LEDGER_NAME_SPACE_DEPRECATED(name, value)
|
||||
|
||||
static std::map<std::string, std::uint16_t> const kMap{
|
||||
#include <xrpl/protocol/detail/ledger_name_spaces.macro>
|
||||
};
|
||||
|
||||
#undef LEDGER_NAME_SPACE_DEPRECATED
|
||||
#pragma pop_macro("LEDGER_NAME_SPACE_DEPRECATED")
|
||||
#undef LEDGER_NAME_SPACE
|
||||
#pragma pop_macro("LEDGER_NAME_SPACE")
|
||||
|
||||
return kMap;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
static uint256
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <test/jtx/Env.h>
|
||||
#include <test/jtx/TestHelpers.h>
|
||||
#include <test/jtx/amount.h>
|
||||
#include <test/jtx/envconfig.h>
|
||||
#include <test/jtx/fee.h>
|
||||
#include <test/jtx/mpt.h>
|
||||
#include <test/jtx/pay.h>
|
||||
@@ -102,12 +101,6 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
return xrpl::test::jtx::testableAmendments() | fixCleanup3_1_3 | fixCleanup3_2_0;
|
||||
}
|
||||
|
||||
test::jtx::Env
|
||||
makeEnv(FeatureBitset features)
|
||||
{
|
||||
return {*this, test::jtx::envconfig(), features, nullptr, beast::Severity::Disabled};
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a specific test case to put the ledger into a state that will be
|
||||
* detected by an invariant. Simulates the actions of a transaction that
|
||||
@@ -137,7 +130,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
TxAccount setTxAccount = TxAccount::None)
|
||||
{
|
||||
doInvariantCheck(
|
||||
makeEnv(defaultAmendments()),
|
||||
test::jtx::Env(*this, defaultAmendments()),
|
||||
expectLogs,
|
||||
precheck,
|
||||
fee,
|
||||
@@ -1501,7 +1494,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
testcase << "PermissionedDomain" + std::string(fixEnabled ? " fix" : "");
|
||||
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain with no rules."}},
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
return createPermissionedDomain(ac, a1, a2, 0).get();
|
||||
@@ -1514,7 +1507,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
static constexpr auto kTooBig = kMaxPermissionedDomainCredentialsArraySize + 1;
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain bad credentials size " + std::to_string(kTooBig)}},
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
return !!createPermissionedDomain(ac, a1, a2, kTooBig);
|
||||
@@ -1525,7 +1518,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain 3";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't sorted"}},
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
auto slePd = createPermissionedDomain(ac, a1, a2, 0);
|
||||
@@ -1549,7 +1542,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain 4";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't unique"}},
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
auto slePd = createPermissionedDomain(ac, a1, a2, 0);
|
||||
@@ -1572,7 +1565,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain Set 1";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain with no rules."}},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
// create PD
|
||||
@@ -1593,7 +1586,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain Set 2";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain bad credentials size " + std::to_string(kTooBig)}},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
// create PD
|
||||
@@ -1624,7 +1617,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain Set 3";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't sorted"}},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
// create PD
|
||||
@@ -1654,7 +1647,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
testcase << "PermissionedDomain Set 4";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"permissioned domain credentials aren't unique"}},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
// create PD
|
||||
@@ -1695,7 +1688,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
{
|
||||
testcase << "PermissionedDomain set 2 domains ";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? badMoreThan1 : emptyV,
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
createPermissionedDomain(ac, a1, a2);
|
||||
@@ -1741,7 +1734,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
{
|
||||
testcase << "PermissionedDomain set 0 domains ";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? badNoDomains : emptyV,
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{},
|
||||
@@ -1764,7 +1757,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
env1.close();
|
||||
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
a1,
|
||||
a2,
|
||||
fixEnabled ? badNoDomains : emptyV,
|
||||
@@ -1805,7 +1798,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
{
|
||||
testcase << "PermissionedDomain del, create domain ";
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? badNotDeleted : emptyV,
|
||||
[](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
createPermissionedDomain(ac, a1, a2);
|
||||
@@ -2002,7 +1995,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
testcase << "PermissionedDEX" + std::string(fixEnabled ? " fix" : "");
|
||||
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"domain doesn't exist"}},
|
||||
[](Account const& a1, Account const&, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(a1.id(), 10);
|
||||
@@ -2029,7 +2022,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
|
||||
// missing domain ID in offer object
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
{{"hybrid offer is malformed"}},
|
||||
[&](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
Keylet const offerKey = keylet::offer(a2.id(), 10);
|
||||
@@ -4349,7 +4342,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
};
|
||||
|
||||
doInvariantCheck(
|
||||
makeEnv(defaultAmendments() - fixCleanup3_2_0),
|
||||
Env{*this, defaultAmendments() - fixCleanup3_2_0},
|
||||
{},
|
||||
[](Account const&, Account const&, ApplyContext&) { return true; },
|
||||
XRPAmount{},
|
||||
@@ -5475,7 +5468,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
// sfHighLimit issue, not the keylet currency).
|
||||
testcase << "overwrite: NoXRPTrustLines" + std::string(fixEnabled ? " fix" : "");
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? std::vector<std::string>{{"an XRP trust line was created"}}
|
||||
: std::vector<std::string>{},
|
||||
[&insertOrderedTrustLinePair](Account const& a1, Account const& a2, ApplyContext& ac) {
|
||||
@@ -5503,7 +5496,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
// Regression: bad deep-freeze trust line followed by a valid one.
|
||||
testcase << "overwrite: NoDeepFreeze" + std::string(fixEnabled ? " fix" : "");
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? std::vector<std::string>{{"a trust line with deep freeze flag without "
|
||||
"normal freeze was created"}}
|
||||
: std::vector<std::string>{},
|
||||
@@ -5537,7 +5530,7 @@ class Invariants_test : public beast::unit_test::Suite
|
||||
// still fires ("a MPT issuance was created").
|
||||
testcase << "overwrite: NoZeroEscrow MPT" + std::string(fixEnabled ? " fix" : "");
|
||||
doInvariantCheck(
|
||||
makeEnv(features),
|
||||
Env(*this, features),
|
||||
fixEnabled ? std::vector<std::string>{{"escrow specifies invalid amount"}}
|
||||
: std::vector<std::string>{{"a MPT issuance was created"}},
|
||||
[](Account const& a1, Account const&, ApplyContext& ac) {
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
BEAST_EXPECT(result[jss::result][jss::status] == "success");
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::FIELDS));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_NAME_SPACES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_RESULTS));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TYPES));
|
||||
@@ -107,6 +108,18 @@ public:
|
||||
BEAST_EXPECT(result[jss::result][jss::TRANSACTION_TYPES]["Payment"].asUInt() == 0);
|
||||
BEAST_EXPECT(result[jss::result][jss::TYPES]["AccountID"].asUInt() == 8);
|
||||
|
||||
// test the properties of the LEDGER_NAME_SPACES section
|
||||
{
|
||||
json::Value const& nameSpaces = result[jss::result][jss::LEDGER_NAME_SPACES];
|
||||
BEAST_EXPECT(nameSpaces["Account"].asUInt() == 97); // 'a'
|
||||
BEAST_EXPECT(nameSpaces["Vault"].asUInt() == 86); // 'V'
|
||||
|
||||
// deprecated name spaces are not exported
|
||||
BEAST_EXPECT(!nameSpaces.isMember("Contract"));
|
||||
BEAST_EXPECT(!nameSpaces.isMember("Generator"));
|
||||
BEAST_EXPECT(!nameSpaces.isMember("Nickname"));
|
||||
}
|
||||
|
||||
// test the properties of the LEDGER_ENTRY_FLAGS section
|
||||
{
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_FLAGS));
|
||||
@@ -441,6 +454,7 @@ public:
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::LEDGER_ENTRY_FLAGS));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::LEDGER_ENTRY_FORMATS));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::LEDGER_NAME_SPACES));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_RESULTS));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_TYPES));
|
||||
BEAST_EXPECT(!result[jss::result].isMember(jss::TRANSACTION_FLAGS));
|
||||
@@ -464,6 +478,7 @@ public:
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_TYPES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_FLAGS));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_ENTRY_FORMATS));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::LEDGER_NAME_SPACES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_RESULTS));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_TYPES));
|
||||
BEAST_EXPECT(result[jss::result].isMember(jss::TRANSACTION_FLAGS));
|
||||
@@ -486,6 +501,7 @@ public:
|
||||
jss::LEDGER_ENTRY_FLAGS,
|
||||
jss::LEDGER_ENTRY_FORMATS,
|
||||
jss::LEDGER_ENTRY_TYPES,
|
||||
jss::LEDGER_NAME_SPACES,
|
||||
jss::TRANSACTION_FLAGS,
|
||||
jss::TRANSACTION_FORMATS,
|
||||
jss::TRANSACTION_RESULTS,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/json/json_writer.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
@@ -358,6 +359,12 @@ ServerDefinitions::ServerDefinitions() : defs_{json::ValueType::Object}
|
||||
defs_[jss::ACCOUNT_SET_FLAGS][name] = value;
|
||||
}
|
||||
|
||||
defs_[jss::LEDGER_NAME_SPACES] = json::ValueType::Object;
|
||||
for (auto const& [name, value] : ledgerNameSpaceMap())
|
||||
{
|
||||
defs_[jss::LEDGER_NAME_SPACES][name] = value;
|
||||
}
|
||||
|
||||
// generate hash
|
||||
{
|
||||
std::string const out = json::FastWriter().write(defs_);
|
||||
|
||||
Reference in New Issue
Block a user