From 648ec747f2e52a6a53e241c53d1df9e2a0af41f6 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 13 May 2026 16:10:53 +0100 Subject: [PATCH 1/7] feat: Implement nix-based Dockerfile for CI (#7083) --- .github/workflows/build-nix-image.yml | 101 ++++++++++++++++++++++++++ .pre-commit-config.yaml | 6 +- cspell.config.yaml | 1 + docker/nix.Dockerfile | 66 +++++++++++++++++ flake.lock | 26 ++++++- flake.nix | 13 +++- nix/ci-env.nix | 54 ++++++++++++++ nix/devshell.nix | 15 +--- nix/packages.nix | 27 +++++++ nix/utils.nix | 40 +++++----- 10 files changed, 309 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/build-nix-image.yml create mode 100644 docker/nix.Dockerfile create mode 100644 nix/ci-env.nix create mode 100644 nix/packages.nix diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml new file mode 100644 index 0000000000..6554cf6c08 --- /dev/null +++ b/.github/workflows/build-nix-image.yml @@ -0,0 +1,101 @@ +name: Build Nix Docker image + +on: + push: + branches: + - develop + paths: + - ".github/workflows/build-nix-image.yml" + - "docker/nix.Dockerfile" + - "flake.nix" + - "flake.lock" + - "nix/**" + pull_request: + paths: + - ".github/workflows/build-nix-image.yml" + - "docker/nix.Dockerfile" + - "flake.nix" + - "flake.lock" + - "nix/**" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +env: + UBUNTU_VERSION: "20.04" + RHEL_VERSION: "9" + DEBIAN_VERSION: "bookworm" + +jobs: + build: + name: Build and push Nix image (${{ matrix.distro }}) + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + matrix: + include: + - distro: nixos + - distro: ubuntu + - distro: rhel + - distro: debian + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Determine base image + id: vars + run: | + case "${{ matrix.distro }}" in + nixos) + echo "base_image=nixos/nix:latest" >> $GITHUB_OUTPUT + ;; + ubuntu) + echo "base_image=ubuntu:${UBUNTU_VERSION}" >> $GITHUB_OUTPUT + ;; + rhel) + echo "base_image=registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest" >> $GITHUB_OUTPUT + ;; + debian) + echo "base_image=debian:${DEBIAN_VERSION}" >> $GITHUB_OUTPUT + ;; + esac + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + + - name: Login to GitHub Container Registry + if: github.event_name == 'push' + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + with: + images: ghcr.io/xrplf/ci/nix-${{ matrix.distro }} + tags: | + type=sha,prefix=sha-,format=short + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + with: + context: . + file: docker/nix.Dockerfile + platforms: linux/amd64 + push: ${{ github.event_name == 'push' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: BASE_IMAGE=${{ steps.vars.outputs.base_image }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1c0dc94550..1313ad567c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -70,7 +70,11 @@ repos: rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0 hooks: - id: cspell # Spell check changed files - exclude: (.config/cspell.config.yaml|^include/xrpl/protocol_autogen/(transactions|ledger_entries)/) + exclude: | + (?x)^( + .config/cspell.config.yaml| + include/xrpl/protocol_autogen/(transactions|ledger_entries)/.* + )$ - id: cspell # Spell check the commit message name: check commit message spelling args: diff --git a/cspell.config.yaml b/cspell.config.yaml index 8b8589a8c9..34482d9d8f 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -63,6 +63,7 @@ words: - Bougalis - Britto - Btrfs + - Buildx - canonicality - changespq - checkme diff --git a/docker/nix.Dockerfile b/docker/nix.Dockerfile new file mode 100644 index 0000000000..52faa8b8dc --- /dev/null +++ b/docker/nix.Dockerfile @@ -0,0 +1,66 @@ +ARG BASE_IMAGE=nixos/nix:latest + +# Nix builder +FROM nixos/nix:latest AS builder-source + +RUN mkdir -p ~/.config/nix && \ + echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf + +# Copy our source and setup our working dir. +COPY nix/ci-env.nix /tmp/build/nix/ci-env.nix +COPY nix/packages.nix /tmp/build/nix/packages.nix +COPY nix/utils.nix /tmp/build/nix/utils.nix +COPY flake.nix /tmp/build/ +COPY flake.lock /tmp/build/ +WORKDIR /tmp/build + +FROM builder-source AS builder + +# Build our Nix CI environment (all build tools in a single store path) +RUN nix \ + --option filter-syscalls false \ + build + +# Copy the Nix store closure into a directory. The Nix store closure is the +# entire set of Nix store values that we need for our build. +RUN mkdir /tmp/nix-store-closure && \ + cp -R $(nix-store -qR result/) /tmp/nix-store-closure + +# Final 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 \ + ln -s /root/.nix-profile/bin/bash /bin/bash; \ + fi + +# Use Bash as the default shell for RUN commands, using the options +# `set -o errexit -o pipefail`, and as the entrypoint. +SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] +ENTRYPOINT ["/bin/bash"] + +# Copy /nix/store and the env symlink tree +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" + +RUN < Date: Wed, 13 May 2026 17:03:57 +0100 Subject: [PATCH 2/7] fix: Check network ID in `transactionSignFor` (#7102) --- include/xrpl/basics/Expected.h | 24 ++++++++++++----- src/xrpld/rpc/detail/TransactionSign.cpp | 33 ++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/include/xrpl/basics/Expected.h b/include/xrpl/basics/Expected.h index 74a0e76eef..3796151777 100644 --- a/include/xrpl/basics/Expected.h +++ b/include/xrpl/basics/Expected.h @@ -148,17 +148,23 @@ public: } [[nodiscard]] constexpr E const& - error() const + error() const& { return Base::error(); } - constexpr E& - error() + [[nodiscard]] constexpr E& + error() & { return Base::error(); } + [[nodiscard]] constexpr E&& + error() && + { + return std::move(Base::error()); + } + constexpr explicit operator bool() const { @@ -215,17 +221,23 @@ public: } [[nodiscard]] constexpr E const& - error() const + error() const& { return Base::error(); } - constexpr E& - error() + [[nodiscard]] constexpr E& + error() & { return Base::error(); } + [[nodiscard]] constexpr E&& + error() && + { + return std::move(Base::error()); + } + constexpr explicit operator bool() const { diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index f745bd9e1b..0fdc1bfdc7 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include +#include #include #include #include @@ -405,6 +407,25 @@ checkTxJsonFields( return ret; } +static Expected +checkNetworkID(json::Value const& txJson, uint32_t appNetworkId) +{ + if (appNetworkId > 1024) + { + if (!txJson.isMember(jss::NetworkID)) + { + return Unexpected( + RPC::makeError(RpcInvalidParams, RPC::missingFieldMessage("tx_json.NetworkID"))); + } + if (!txJson[jss::NetworkID].isIntegral() || txJson[jss::NetworkID].asUInt() != appNetworkId) + { + return Unexpected( + RPC::makeError(RpcInvalidParams, RPC::invalidFieldMessage("tx_json.NetworkID"))); + } + } + return Expected(); +} + //------------------------------------------------------------------------------ // A move-only struct that makes it easy to return either a json::Value or a @@ -1165,8 +1186,16 @@ transactionSignFor( if (!txJson.isObject()) return RPC::objectFieldError(jss::tx_json); - // If the tx_json.SigningPubKey field is missing, - // insert an empty one. + if (auto checkResult = + detail::checkNetworkID(txJson, app.getNetworkIDService().getNetworkID()); + !checkResult) + { + return std::move(checkResult).error(); + } + + // If the tx_json.SigningPubKey field is missing, insert an empty one, + // in order for the `checkMultiSignFields` to not return an error + // for non-multisign transactions. if (!txJson.isMember(sfSigningPubKey.getJsonName())) txJson[sfSigningPubKey.getJsonName()] = ""; } From aa5e4ff89f1871c02c96b7f97ab7fa7d13274281 Mon Sep 17 00:00:00 2001 From: Luc des Trois Maisons Date: Wed, 13 May 2026 12:48:38 -0400 Subject: [PATCH 3/7] refactor: Improve Forwarded header field parsing (#7126) --- src/xrpld/rpc/detail/Role.cpp | 49 +++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/xrpld/rpc/detail/Role.cpp b/src/xrpld/rpc/detail/Role.cpp index 998eea15c9..638ef22630 100644 --- a/src/xrpld/rpc/detail/Role.cpp +++ b/src/xrpld/rpc/detail/Role.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -252,32 +253,46 @@ forwardedFor(http_request_type const& request) // Look for the Forwarded field in the request. if (auto it = request.find(boost::beast::http::field::forwarded); it != request.end()) { - auto asciiTolower = [](char c) -> char { + auto asciiToLower = [](char c) -> char { return ((static_cast(c) - 65U) < 26) ? c + 'a' - 'A' : c; }; - // Look for the first (case insensitive) "for=" - static std::string const kFOR_STR{"for="}; - char const* found = std::search( - it->value().begin(), - it->value().end(), - kFOR_STR.begin(), - kFOR_STR.end(), - [&asciiTolower](char c1, char c2) { return asciiTolower(c1) == asciiTolower(c2); }); + // Look for the first (case insensitive) "for=" at a directive + // boundary (start of value, or preceded by , ; or OWS). + static constexpr std::string_view kFOR_STR{"for="}; + auto const atFieldBoundary = [begin = it->value().begin()](auto p) { + return p == begin || p[-1] == ';' || p[-1] == ',' || p[-1] == ' ' || p[-1] == '\t'; + }; + auto found = it->value().begin(); + while (true) + { + found = std::search( + found, + it->value().end(), + kFOR_STR.begin(), + kFOR_STR.end(), + [&asciiToLower](char c1, char c2) { return asciiToLower(c1) == asciiToLower(c2); }); - if (found == it->value().end()) - return {}; + if (found == it->value().end()) + return {}; - found += kFOR_STR.size(); + if (atFieldBoundary(found)) + break; + + ++found; + } + + std::advance(found, kFOR_STR.size()); // We found a "for=". Scan for the end of the IP address. - std::size_t const pos = [&found, &it]() { - auto const remaining = static_cast(it->value().end() - found); - if (std::size_t const pos = std::string_view(found, remaining).find_first_of(",;"); - pos != std::string_view::npos) + auto const end = it->value().end(); + std::size_t const pos = [&found, &end]() { + std::size_t const pos = + std::string_view(found, std::distance(found, end)).find_first_of(",;"); + if (pos != std::string_view::npos) return pos; - return remaining; + return static_cast(std::distance(found, end)); }(); return extractIpAddrFromField({found, pos}); From 551f3c3b9622e6d8afb49ed1afe44b490bd55d16 Mon Sep 17 00:00:00 2001 From: Sergey Kuznetsov Date: Wed, 13 May 2026 18:48:43 +0100 Subject: [PATCH 4/7] refactor: Move unhex lookup table out of function (#7104) --- include/xrpl/basics/StringUtilities.h | 66 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/include/xrpl/basics/StringUtilities.h b/include/xrpl/basics/StringUtilities.h index 13c4f04e0c..f4bdd61f6a 100644 --- a/include/xrpl/basics/StringUtilities.h +++ b/include/xrpl/basics/StringUtilities.h @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include namespace xrpl { @@ -26,28 +28,39 @@ namespace xrpl { std::string sqlBlobLiteral(Blob const& blob); +namespace detail { + +template +concept SomeChar = std::same_as, int8_t> || + std::same_as, char> || std::same_as, uint8_t>; + +inline constexpr std::array, 256> const kDIGIT_LOOKUP_TABLE = []() { + std::array, 256> t{}; + + for (int i = 0; i < 10; ++i) + t['0' + i] = i; + + for (int i = 0; i < 6; ++i) + { + t['A' + i] = 10 + i; + t['a' + i] = 10 + i; + } + + return t; +}(); + +inline std::optional +hexCharToInt(SomeChar auto hexChar) +{ + return kDIGIT_LOOKUP_TABLE[static_cast(hexChar)]; +} + +} // namespace detail + template std::optional strUnHex(std::size_t strSize, Iterator begin, Iterator end) { - static constexpr std::array const kDIGIT_LOOKUP_TABLE = []() { - std::array t{}; - - for (auto& x : t) - x = -1; - - for (int i = 0; i < 10; ++i) - t['0' + i] = i; - - for (int i = 0; i < 6; ++i) - { - t['A' + i] = 10 + i; - t['a' + i] = 10 + i; - } - - return t; - }(); - Blob out; out.reserve((strSize + 1) / 2); @@ -56,27 +69,26 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end) if (strSize & 1) { - int c = kDIGIT_LOOKUP_TABLE[*iter++]; - - if (c < 0) + auto const c = detail::hexCharToInt(*iter++); + if (!c.has_value()) return {}; - out.push_back(c); + out.push_back(static_cast(*c)); } while (iter != end) { - int const cHigh = kDIGIT_LOOKUP_TABLE[*iter++]; + auto const cHigh = detail::hexCharToInt(*iter++); - if (cHigh < 0) + if (!cHigh.has_value()) return {}; - int const cLow = kDIGIT_LOOKUP_TABLE[*iter++]; + auto const cLow = detail::hexCharToInt(*iter++); - if (cLow < 0) + if (!cLow.has_value()) return {}; - out.push_back(static_cast((cHigh << 4) | cLow)); + out.push_back(static_cast((*cHigh << 4) | *cLow)); } return {std::move(out)}; From d4ebd6a1687405445c1604ea30435171d0614fa9 Mon Sep 17 00:00:00 2001 From: Olek <115580134+oleks-rip@users.noreply.github.com> Date: Wed, 13 May 2026 15:22:29 -0400 Subject: [PATCH 5/7] fix: Backport Permissioned Domains fixes (#7016) --- src/test/app/Invariants_test.cpp | 4 ++-- src/test/app/PermissionedDomains_test.cpp | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index b0f1aee03c..99de5be302 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -1291,8 +1291,8 @@ class Invariants_test : public beast::unit_test::Suite if (numCreds != 0u) { - // This array is sorted naturally, but if you willing to change this - // behavior don't forget to use credentials::makeSorted + // This array is sorted naturally, but if you are going to change + // this behavior, don't forget to use credentials::makeSorted STArray credentials(sfAcceptedCredentials, numCreds); for (std::size_t n = 0; n < numCreds; ++n) { diff --git a/src/test/app/PermissionedDomains_test.cpp b/src/test/app/PermissionedDomains_test.cpp index 78ce82b497..008f54ddd8 100644 --- a/src/test/app/PermissionedDomains_test.cpp +++ b/src/test/app/PermissionedDomains_test.cpp @@ -49,14 +49,13 @@ exceptionExpected(Env& env, json::Value const& jv) class PermissionedDomains_test : public beast::unit_test::Suite { - FeatureBitset withoutFeature_{testableAmendments() - featurePermissionedDomains}; FeatureBitset withFeature_{ - testableAmendments() // - | featurePermissionedDomains | featureCredentials}; - + (testableAmendments() // + | featurePermissionedDomains | featureCredentials) - + fixPermissionedDomainInvariant}; FeatureBitset withFix_{ testableAmendments() // - | featurePermissionedDomains | featureCredentials}; + | featurePermissionedDomains | featureCredentials | fixPermissionedDomainInvariant}; // Verify that each tx type can execute if the feature is enabled. void @@ -98,7 +97,7 @@ class PermissionedDomains_test : public beast::unit_test::Suite { testcase("Disabled"); Account const alice("alice"); - Env env(*this, withoutFeature_); + Env env(*this, testableAmendments() - featurePermissionedDomains); env.fund(XRP(1000), alice); pdomain::Credentials const credentials{{alice, "first credential"}}; env(pdomain::setTx(alice, credentials), Ter(temDISABLED)); From 2f65cb561011fadf323b4599f8e732297c487b8c Mon Sep 17 00:00:00 2001 From: Michael Legleux Date: Wed, 13 May 2026 12:34:46 -0700 Subject: [PATCH 6/7] ci: Add Conan retry (#7147) --- conan/global.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conan/global.conf b/conan/global.conf index 37b329a5c5..cc803dc801 100644 --- a/conan/global.conf +++ b/conan/global.conf @@ -3,3 +3,5 @@ core:non_interactive=True core.download:parallel={{ os.cpu_count() }} core.upload:parallel={{ os.cpu_count() }} +tools.files.download:retry=5 +tools.files.download:retry_wait=10 From afbccf971a553625d795502d9dab437997cc3c51 Mon Sep 17 00:00:00 2001 From: Bart Date: Wed, 13 May 2026 16:46:30 -0400 Subject: [PATCH 7/7] chore: Consolidate fix amendments (#7134) Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com> --- include/xrpl/protocol/detail/features.macro | 9 ++- .../PermissionedDomainInvariant.cpp | 2 +- .../PermissionedDomainSet.cpp | 4 +- src/test/app/Invariants_test.cpp | 72 +++++++++---------- src/test/app/PermissionedDEX_test.cpp | 6 +- src/test/app/PermissionedDomains_test.cpp | 7 +- 6 files changed, 45 insertions(+), 55 deletions(-) diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index dc26a5a43b..fd62b74d59 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -15,11 +15,10 @@ // Add new amendments to the top of this list. // Keep it sorted in reverse chronological order. -XRPL_FIX (Cleanup3_2_0, Supported::No, VoteBehavior::DefaultNo) -XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo) +XRPL_FIX (Cleanup3_2_0, Supported::No, VoteBehavior::DefaultNo) +XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo) XRPL_FIX (Cleanup3_1_3, Supported::Yes, VoteBehavior::DefaultYes) -XRPL_FIX (PermissionedDomainInvariant, Supported::Yes, VoteBehavior::DefaultNo) -XRPL_FIX (BatchInnerSigs, Supported::No, VoteBehavior::DefaultNo) +XRPL_FIX (BatchInnerSigs, Supported::No, VoteBehavior::DefaultNo) XRPL_FEATURE(LendingProtocol, Supported::Yes, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionDelegationV1_1, Supported::No, VoteBehavior::DefaultNo) XRPL_FIX (DirectoryLimit, Supported::Yes, VoteBehavior::DefaultNo) @@ -34,7 +33,7 @@ XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::Yes, VoteBehavior::DefaultN XRPL_FIX (AMMv1_3, Supported::Yes, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionedDEX, Supported::Yes, VoteBehavior::DefaultNo) XRPL_FEATURE(Batch, Supported::No, VoteBehavior::DefaultNo) -XRPL_FEATURE(SingleAssetVault, Supported::Yes, VoteBehavior::DefaultNo) +XRPL_FEATURE(SingleAssetVault, Supported::Yes, VoteBehavior::DefaultNo) XRPL_FIX (PayChanCancelAfter, Supported::Yes, VoteBehavior::DefaultNo) // Check flags in Credential transactions XRPL_FIX (InvalidTxFlags, Supported::Yes, VoteBehavior::DefaultNo) diff --git a/src/libxrpl/tx/invariants/PermissionedDomainInvariant.cpp b/src/libxrpl/tx/invariants/PermissionedDomainInvariant.cpp index 784a2503ca..60cc897f99 100644 --- a/src/libxrpl/tx/invariants/PermissionedDomainInvariant.cpp +++ b/src/libxrpl/tx/invariants/PermissionedDomainInvariant.cpp @@ -102,7 +102,7 @@ ValidPermissionedDomain::finalize( return true; }; - if (view.rules().enabled(fixPermissionedDomainInvariant)) + if (view.rules().enabled(fixCleanup3_1_3)) { // No permissioned domains should be affected if the transaction failed if (!isTesSuccess(result)) diff --git a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp index 3258dda409..83921e8526 100644 --- a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp +++ b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp @@ -110,8 +110,8 @@ PermissionedDomainSet::doApply() if (balance < reserve) return tecINSUFFICIENT_RESERVE; - bool const fix313 = view().rules().enabled(fixCleanup3_1_3); - auto const seq = fix313 ? ctx_.tx.getSeqValue() : ctx_.tx.getFieldU32(sfSequence); + bool const fixEnabled = view().rules().enabled(fixCleanup3_1_3); + auto const seq = fixEnabled ? ctx_.tx.getSeqValue() : ctx_.tx.getFieldU32(sfSequence); Keylet const pdKeylet = keylet::permissionedDomain(account_, seq); auto slePd = std::make_shared(pdKeylet); diff --git a/src/test/app/Invariants_test.cpp b/src/test/app/Invariants_test.cpp index 99de5be302..d9670ed6a3 100644 --- a/src/test/app/Invariants_test.cpp +++ b/src/test/app/Invariants_test.cpp @@ -1314,11 +1314,11 @@ class Invariants_test : public beast::unit_test::Suite { using namespace test::jtx; - bool const fixPDEnabled = features[fixPermissionedDomainInvariant]; + bool const fixEnabled = features[fixCleanup3_1_3]; std::initializer_list const badTers = {tecINVARIANT_FAILED, tecINVARIANT_FAILED}; std::initializer_list const failTers = {tecINVARIANT_FAILED, tefINVARIANT_FAILED}; - testcase << "PermissionedDomain" + std::string(fixPDEnabled ? " fix" : ""); + testcase << "PermissionedDomain" + std::string(fixEnabled ? " fix" : ""); doInvariantCheck( Env(*this, features), @@ -1328,7 +1328,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain 2"; @@ -1341,7 +1341,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain 3"; doInvariantCheck( @@ -1365,7 +1365,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain 4"; doInvariantCheck( @@ -1388,7 +1388,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain Set 1"; doInvariantCheck( @@ -1409,7 +1409,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain Set 2"; doInvariantCheck( @@ -1440,7 +1440,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain Set 3"; doInvariantCheck( @@ -1470,7 +1470,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); testcase << "PermissionedDomain Set 4"; doInvariantCheck( @@ -1498,7 +1498,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : badTers); + fixEnabled ? failTers : badTers); std::initializer_list const goodTers = {tesSUCCESS, tesSUCCESS}; @@ -1516,7 +1516,7 @@ class Invariants_test : public beast::unit_test::Suite testcase << "PermissionedDomain set 2 domains "; doInvariantCheck( Env(*this, features), - fixPDEnabled ? badMoreThan1 : emptyV, + fixEnabled ? badMoreThan1 : emptyV, [](Account const& a1, Account const& a2, ApplyContext& ac) { createPermissionedDomain(ac, a1, a2); createPermissionedDomain(ac, a1, a2, 2, 11); @@ -1524,7 +1524,7 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : goodTers); + fixEnabled ? failTers : goodTers); } { @@ -1545,7 +1545,7 @@ class Invariants_test : public beast::unit_test::Suite std::move(env1), a1, a2, - fixPDEnabled ? badMoreThan1 : emptyV, + fixEnabled ? badMoreThan1 : emptyV, [&pd1, &pd2](Account const&, Account const&, ApplyContext& ac) { auto sle1 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd1}); auto sle2 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd2}); @@ -1555,18 +1555,18 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}}, - fixPDEnabled ? failTers : goodTers); + fixEnabled ? failTers : goodTers); } { testcase << "PermissionedDomain set 0 domains "; doInvariantCheck( Env(*this, features), - fixPDEnabled ? badNoDomains : emptyV, + fixEnabled ? badNoDomains : emptyV, [](Account const&, Account const&, ApplyContext&) { return true; }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? badTers : goodTers); + fixEnabled ? badTers : goodTers); } { @@ -1587,11 +1587,11 @@ class Invariants_test : public beast::unit_test::Suite Env(*this, features), a1, a2, - fixPDEnabled ? badNoDomains : emptyV, + fixEnabled ? badNoDomains : emptyV, [](Account const&, Account const&, ApplyContext&) { return true; }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}}, - fixPDEnabled ? badTers : goodTers); + fixEnabled ? badTers : goodTers); } { @@ -1611,7 +1611,7 @@ class Invariants_test : public beast::unit_test::Suite std::move(env1), a1, a2, - fixPDEnabled ? badDeleted : emptyV, + fixEnabled ? badDeleted : emptyV, [&pd1](Account const&, Account const&, ApplyContext& ac) { auto sle1 = ac.view().peek({ltPERMISSIONED_DOMAIN, pd1}); ac.view().erase(sle1); @@ -1619,28 +1619,28 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_SET, [](STObject&) {}}, - fixPDEnabled ? failTers : goodTers); + fixEnabled ? failTers : goodTers); } { testcase << "PermissionedDomain del, create domain "; doInvariantCheck( Env(*this, features), - fixPDEnabled ? badNotDeleted : emptyV, + fixEnabled ? badNotDeleted : emptyV, [](Account const& a1, Account const& a2, ApplyContext& ac) { createPermissionedDomain(ac, a1, a2); return true; }, XRPAmount{}, STTx{ttPERMISSIONED_DOMAIN_DELETE, [](STObject&) {}}, - fixPDEnabled ? failTers : goodTers); + fixEnabled ? failTers : goodTers); } { testcase << "PermissionedDomain invalid tx"; doInvariantCheck( - fixPDEnabled ? badTx : emptyV, + fixEnabled ? badTx : emptyV, [&](Account const& a1, Account const& a2, ApplyContext& ac) { createPermissionedDomain(ac, a1, a2); return true; @@ -1800,11 +1800,9 @@ class Invariants_test : public beast::unit_test::Suite { using namespace test::jtx; - bool const fixPDEnabled = features[fixPermissionedDomainInvariant]; - bool const fixS313Enabled = features[fixCleanup3_1_3]; + bool const fixEnabled = features[fixCleanup3_1_3]; - testcase << "PermissionedDEX" + std::string(fixPDEnabled ? " fixPD" : "") + - std::string(fixS313Enabled ? " fixS313" : ""); + testcase << "PermissionedDEX" + std::string(fixEnabled ? " fix" : ""); doInvariantCheck( Env(*this, features), @@ -1908,8 +1906,8 @@ class Invariants_test : public beast::unit_test::Suite std::move(env1), a1, a2, - fixS313Enabled ? std::vector{{"hybrid offer is malformed"}} - : std::vector{}, + fixEnabled ? std::vector{{"hybrid offer is malformed"}} + : std::vector{}, [&pd1](Account const& a1, Account const& a2, ApplyContext& ac) { Keylet const offerKey = keylet::offer(a2.id(), 10); auto sleOffer = std::make_shared(offerKey); @@ -1926,9 +1924,8 @@ class Invariants_test : public beast::unit_test::Suite }, XRPAmount{}, STTx{ttOFFER_CREATE, [&](STObject&) {}}, - fixS313Enabled - ? std::initializer_list{tecINVARIANT_FAILED, tecINVARIANT_FAILED} - : std::initializer_list{tesSUCCESS, tesSUCCESS}); + fixEnabled ? std::initializer_list{tecINVARIANT_FAILED, tecINVARIANT_FAILED} + : std::initializer_list{tesSUCCESS, tesSUCCESS}); } // hybrid offer missing sfAdditionalBooks @@ -4380,13 +4377,10 @@ public: testNoZeroEscrow(); testValidNewAccountRoot(); testNFTokenPageInvariants(); - testPermissionedDomainInvariants(defaultAmendments() | fixPermissionedDomainInvariant); - testPermissionedDomainInvariants(defaultAmendments() - fixPermissionedDomainInvariant); - testPermissionedDEX(defaultAmendments() | fixPermissionedDomainInvariant); - testPermissionedDEX(defaultAmendments() - fixPermissionedDomainInvariant); - testPermissionedDEX( - (defaultAmendments() | fixPermissionedDomainInvariant) - fixCleanup3_1_3); - testPermissionedDEX(defaultAmendments() - fixPermissionedDomainInvariant - fixCleanup3_1_3); + testPermissionedDomainInvariants(defaultAmendments() | fixCleanup3_1_3); + testPermissionedDomainInvariants(defaultAmendments() - fixCleanup3_1_3); + testPermissionedDEX(defaultAmendments() | fixCleanup3_1_3); + testPermissionedDEX(defaultAmendments() - fixCleanup3_1_3); testNoModifiedUnmodifiableFields(); testValidPseudoAccounts(); testValidLoanBroker(); diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index 21e6bd8baa..45b4a58901 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -1392,10 +1392,10 @@ class PermissionedDEX_test : public beast::unit_test::Suite void testHybridMalformedOffer(FeatureBitset features) { - bool const fixS313Enabled = features[fixCleanup3_1_3]; + bool const fixEnabled = features[fixCleanup3_1_3]; testcase << "Hybrid offer with empty AdditionalBooks" - << (fixS313Enabled ? " (fixCleanup3_1_3 enabled)" : " (fixCleanup3_1_3 disabled)"); + << (fixEnabled ? " (fixCleanup3_1_3 enabled)" : " (fixCleanup3_1_3 disabled)"); // offerInDomain has two code paths gated by fixCleanup3_1_3: // @@ -1436,7 +1436,7 @@ class PermissionedDEX_test : public beast::unit_test::Suite return true; }); - if (fixS313Enabled) + if (fixEnabled) { // post-fixCleanup3_1_3: offerInDomain rejects the malformed // offer (size == 0), so no valid domain offer is found. diff --git a/src/test/app/PermissionedDomains_test.cpp b/src/test/app/PermissionedDomains_test.cpp index 008f54ddd8..0593b06eaa 100644 --- a/src/test/app/PermissionedDomains_test.cpp +++ b/src/test/app/PermissionedDomains_test.cpp @@ -50,12 +50,9 @@ exceptionExpected(Env& env, json::Value const& jv) class PermissionedDomains_test : public beast::unit_test::Suite { FeatureBitset withFeature_{ - (testableAmendments() // - | featurePermissionedDomains | featureCredentials) - - fixPermissionedDomainInvariant}; + (testableAmendments() | featurePermissionedDomains | featureCredentials) - fixCleanup3_1_3}; FeatureBitset withFix_{ - testableAmendments() // - | featurePermissionedDomains | featureCredentials | fixPermissionedDomainInvariant}; + testableAmendments() | featurePermissionedDomains | featureCredentials | fixCleanup3_1_3}; // Verify that each tx type can execute if the feature is enabled. void