Compare commits

..

1 Commits

Author SHA1 Message Date
Denis Angell
c7bfd6a7e1 feat: export ledger name spaces via server_definitions 2026-07-16 20:54:14 -04:00
20 changed files with 193 additions and 279 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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' }}

View File

@@ -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" }'

View File

@@ -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 }}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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

View File

@@ -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 /

View File

@@ -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 #}

View File

@@ -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.

View File

@@ -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)

View 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')

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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_);