Compare commits

..
Author SHA1 Message Date
Mayukha Vadari 16389dcb2e refactor: Move decreaseOwnerCount onto AccountRootEntry
Replace the entry-taking decreaseOwnerCount free function with a
writable member of AccountRootEntry, and drop the temporary friend
declaration from the previous change. The member uses the entry's view
and journal, so call sites pass their journal to the entry constructor.
The AccountID-based overload stays as a shim.
2026-10-05 15:46:48 +01:00
Mayukha Vadari 97a780b29f refactor: Move increaseOwnerCount onto AccountRootEntry
Replace both entry-taking increaseOwnerCount free functions with
writable members of AccountRootEntry. The members use the entry's view
and journal, so call sites pass their journal to the entry constructor.
The AccountID-based overload stays as a shim.

adjustOwnerCountSigned becomes a private member. decreaseOwnerCount is
a temporary friend so it can still call it until it moves too.
adjustOwnerCountImpl moves to namespace detail, because
adjustLoanBrokerOwnerCount also uses it.
2026-10-05 15:46:44 +01:00
Mayukha Vadari 654edc9a08 refactor: Move checkReserve onto AccountRootEntry
Replace both entry-taking checkReserve free functions with const members
of AccountRootEntry. The members keep the ApplyViewContext parameter,
because the check needs the transaction, and drop the journal parameter:
call sites pass their journal to the entry constructor instead.
2026-10-05 15:46:39 +01:00
Mayukha Vadari 658d04f694 Document confineOwnerCount parameters 2026-10-05 15:46:31 +01:00
Mayukha Vadari 93498952b1 refactor: Move ownerCount onto AccountRootEntry
Replace the entry-taking ownerCount(sle, j, adj) free function with the
const member AccountRootEntry::ownerCount(adj). The member uses the
entry's journal, so call sites pass their journal to the entry
constructor.

confineOwnerCount moves from the anonymous namespace to namespace
detail, because both the member and the owner-count helpers use it.
2026-10-05 15:45:43 +01:00
Mayukha Vadari 269f79e568 Include Keylet.h in the SLEBase test
(cherry picked from commit 3cca9d3266)
2026-10-05 15:45:38 +01:00
Mayukha Vadari e7a8e0336a test: Drop extern template declarations from SLEBase test
An explicit instantiation declaration stops clang from emitting the
inline constructors of the header-only entries at -O0, so the debug
builds fail to link xrpl_tests (undefined AccountRootEntry constructors).
Naming each class in a static_assert already instantiates its definition,
which is all the exhaustiveness check needs.

(cherry picked from commit 611415e1f9)
2026-10-05 15:45:38 +01:00
Mayukha Vadari 1d7e40777a refactor: Move accountReserve onto AccountRootEntry
Replace the entry-taking accountReserve(view, sle, j, adj) free function
with the const member AccountRootEntry::reserve(adj). The member uses the
entry's own view and journal, so call sites now pass their journal to the
entry constructor. The AccountID-based accountReserve overload stays as a
one-line shim.

Adjustment moves to AccountRootEntry.h, since the member takes it.
accountCountImpl moves from the anonymous namespace to namespace detail,
because both reserve() and xrpLiquid() use it.
2026-10-05 15:45:38 +01:00
Mayukha Vadari 7bb43a243b test: Declare, not define, entry instantiations in SLEBase test
The exhaustive per-entry-type check in the SLEBase gtest used explicit
instantiation definitions. Once an entry class gets out-of-line member
bodies in its own .cpp (with the explicit instantiation definition
there), the test would instantiate the class a second time, and MSVC
rejects it with C4661 because those member bodies are not visible in
the test translation unit. Explicit instantiation declarations still
instantiate the class definition, which is all the check needs.

(cherry picked from commit 8b07abc3cd)
2026-10-05 15:45:37 +01:00
Mayukha Vadari d697b7843c Document escrowDestNotAccountResult and isPseudoAccountSle parameters and return value 2026-10-05 15:45:24 +01:00
Mayukha Vadari 2de5140f20 Drop unused include from SponsorshipTransfer.cpp 2026-10-05 13:33:31 +01:00
Mayukha Vadari edf085a697 Declare canWithdraw with AccountRootEntryR in View.h 2026-10-05 13:33:31 +01:00
Mayukha Vadari c35ac1339b fix: Do not adopt the escrow SLE into an AccountRootEntry
Before fixCleanup3_2_0, EscrowCancel passes the escrow SLE to
escrowUnlockApplyHelper as sleDest. Wrapping it in AccountRootEntryR
fires the "adopted SLE matches bound entry type" assertion in Debug
builds (xrpl.app.EscrowToken "IOU Cancel DoApply").

When sleDest is not an AccountRoot, return what the old code returned
for it: the tx reserve sponsor's error if the escrow owner submitted
the tx, else tefINTERNAL from checkReserve's type check.

(cherry picked from commit 90bb3930be)
2026-10-05 13:33:31 +01:00
Mayukha Vadari dc1cfbc474 Drop unused include from AccountRootHelpers.h 2026-10-05 13:33:30 +01:00
Mayukha Vadari 3044073401 refactor: Use AccountRootEntry everywhere
Replace raw AccountRoot SLE pointers with the AccountRootEntryR and
AccountRootEntryW wrappers in src/libxrpl and src/xrpld/app.

- view.read(keylet::account(...)) becomes AccountRootEntryR and
  view.peek(keylet::account(...)) becomes AccountRootEntryW.
- AccountRoot helpers (accountReserve, checkReserve, ownerCount,
  increase/decreaseOwnerCount, isPseudoAccount,
  checkDestinationAndTag) and the sponsor helpers
  (getTxReserveSponsor, getEffectiveTxReserveSponsor,
  getLedgerEntryReserveSponsor) take or return the wrappers. A missing
  sponsor is std::nullopt instead of a null pointer.
- Generic functions that are not migrated yet (trustCreate, dirLink,
  addSponsorToLedgerEntry, ...) get rawSle() or mutableRawSle().
- Invariant checks cannot build a view-bound entry, so they use
  isPseudoAccountSle(), now declared in InvariantCheck.h.

This changes pointers only. No helper moves onto the wrapper. It is a
pure refactor with no behavior change and no amendment.
2026-10-05 13:33:30 +01:00
828 changed files with 24804 additions and 42356 deletions

No files matched your search

-11
View File
@@ -5,10 +5,7 @@ Checks: "-*,
-bugprone-exception-escape, -bugprone-exception-escape,
-bugprone-implicit-widening-of-multiplication-result, -bugprone-implicit-widening-of-multiplication-result,
-bugprone-narrowing-conversions, -bugprone-narrowing-conversions,
-bugprone-signed-bitwise,
-bugprone-std-exception-baseclass,
-bugprone-throwing-static-initialization, -bugprone-throwing-static-initialization,
-bugprone-unhandled-code-paths,
cppcoreguidelines-*, cppcoreguidelines-*,
-cppcoreguidelines-avoid-c-arrays, -cppcoreguidelines-avoid-c-arrays,
@@ -17,7 +14,6 @@ Checks: "-*,
-cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables, -cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-c-copy-assignment-signature, -cppcoreguidelines-c-copy-assignment-signature,
-cppcoreguidelines-explicit-constructor,
-cppcoreguidelines-interfaces-global-init, -cppcoreguidelines-interfaces-global-init,
-cppcoreguidelines-macro-usage, -cppcoreguidelines-macro-usage,
-cppcoreguidelines-missing-std-forward, -cppcoreguidelines-missing-std-forward,
@@ -36,7 +32,6 @@ Checks: "-*,
llvm-namespace-comment, llvm-namespace-comment,
misc-*, misc-*,
-misc-explicit-constructor,
-misc-multiple-inheritance, -misc-multiple-inheritance,
-misc-no-recursion, -misc-no-recursion,
-misc-non-private-member-variables-in-classes, -misc-non-private-member-variables-in-classes,
@@ -50,8 +45,6 @@ Checks: "-*,
-modernize-avoid-c-style-cast, -modernize-avoid-c-style-cast,
-modernize-return-braced-init-list, -modernize-return-braced-init-list,
-modernize-use-integer-sign-comparison, -modernize-use-integer-sign-comparison,
-modernize-use-string-view,
-modernize-use-structured-binding,
-modernize-use-trailing-return-type, -modernize-use-trailing-return-type,
performance-*, performance-*,
@@ -60,7 +53,6 @@ Checks: "-*,
-performance-noexcept-move-constructor, -performance-noexcept-move-constructor,
-performance-unnecessary-copy-initialization, -performance-unnecessary-copy-initialization,
-performance-unnecessary-value-param, -performance-unnecessary-value-param,
-performance-use-std-move,
readability-*, readability-*,
-readability-avoid-const-params-in-decls, -readability-avoid-const-params-in-decls,
@@ -73,10 +65,7 @@ Checks: "-*,
-readability-named-parameter, -readability-named-parameter,
-readability-qualified-auto, -readability-qualified-auto,
-readability-redundant-access-specifiers, -readability-redundant-access-specifiers,
-readability-redundant-nested-if,
-readability-redundant-qualified-alias,
-readability-static-accessed-through-instance, -readability-static-accessed-through-instance,
-readability-trivial-switch,
-readability-uppercase-literal-suffix -readability-uppercase-literal-suffix
" "
# --- # ---
-72
View File
@@ -108,75 +108,3 @@ endfunction()
function(patch_nix_binary target) function(patch_nix_binary target)
endfunction() endfunction()
function(rpcspec_generate_instantiations)
set(options)
set(oneValueArgs OUT_VAR VALUE_TYPE VIEW_HEADER INCLUDE_DIR)
set(multiValueArgs HANDLERS)
cmake_parse_arguments(
THIS_FUNCTION_PREFIX
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
endfunction()
function(corrosion_import_crate)
set(options
ALL_FEATURES
NO_DEFAULT_FEATURES
NO_STD
NO_LINKER_OVERRIDE
NO_USES_TERMINAL
LOCKED
FROZEN
)
set(oneValueArgs MANIFEST_PATH PROFILE IMPORTED_CRATES)
set(multiValueArgs
CRATE_TYPES
CRATES
FEATURES
FLAGS
OVERRIDE_CRATE_TYPE
)
cmake_parse_arguments(
THIS_FUNCTION_PREFIX
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
endfunction()
function(corrosion_set_env_vars target_name env_var)
endfunction()
function(corrosion_add_cxxbridge cxx_target)
set(options)
set(oneValueArgs CRATE)
set(multiValueArgs FILES)
cmake_parse_arguments(
THIS_FUNCTION_PREFIX
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
endfunction()
function(_unlink_libgcc_s crate)
endfunction()
function(add_xrpl_crate name)
set(options)
set(oneValueArgs CRATE)
set(multiValueArgs FILES)
cmake_parse_arguments(
THIS_FUNCTION_PREFIX
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
endfunction()
+5 -22
View File
@@ -15,9 +15,9 @@ inputs:
required: false required: false
default: "false" default: "false"
log_verbosity: log_verbosity:
description: 'The logging verbosity ("quiet", "verbose"), or empty to use the Conan defaults.' description: "The logging verbosity."
required: false required: false
default: "" default: "verbose"
sanitizers: sanitizers:
description: "The sanitizers to enable." description: "The sanitizers to enable."
required: false required: false
@@ -35,16 +35,6 @@ runs:
LOG_VERBOSITY: ${{ inputs.log_verbosity }} LOG_VERBOSITY: ${{ inputs.log_verbosity }}
SANITIZERS: ${{ inputs.sanitizers }} SANITIZERS: ${{ inputs.sanitizers }}
run: | run: |
# By default, leave the verbosity unset, so CMake configure output is
# shown, but compile commands and Boost's b2 debug output (~85k lines
# when "verbose") are not.
VERBOSITY_ARGS=()
if [[ -n "${LOG_VERBOSITY}" ]]; then
VERBOSITY_ARGS=(
--conf:all tools.build:verbosity="${LOG_VERBOSITY}"
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}"
)
fi
conan install \ conan install \
--profile:all ci \ --profile:all ci \
--build="${BUILD_OPTION}" \ --build="${BUILD_OPTION}" \
@@ -52,13 +42,6 @@ runs:
--options:host='&:xrpld=True' \ --options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \ --settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \ --conf:all tools.build:jobs=${BUILD_NPROC} \
"${VERBOSITY_ARGS[@]}" \ --conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--format=json \ --conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
. >"${RUNNER_TEMP}/conan-graph.json" .
# Tools that run during the build may only load glibc from the Nix store,
# as their package ID survives a GCC runtime update.
- name: Check build-context packages for Nix store dependencies (Linux)
if: ${{ runner.os == 'Linux' }}
shell: bash
run: ./bin/nix/check-build-context-runtime.sh "${RUNNER_TEMP}/conan-graph.json"
-15
View File
@@ -36,18 +36,3 @@ updates:
rust-dependencies: rust-dependencies:
patterns: patterns:
- "*" - "*"
- package-ecosystem: uv
directory: /cmake/scripts/codegen
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "chore: [DEPENDABOT] "
target-branch: develop
groups:
codegen-dependencies:
patterns:
- "*"
+4 -4
View File
@@ -1,5 +1,5 @@
{ {
"image_tag": "sha-3d526d4", "image_tag": "sha-060957e",
"configs": { "configs": {
"ubuntu": [ "ubuntu": [
{ {
@@ -74,7 +74,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON", "extra_cmake_args": "-Dvalidator_keys=ON",
"package": { "package": {
"type": "deb", "type": "deb",
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-e6055dd" "image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-3a2d19f"
} }
}, },
{ {
@@ -86,7 +86,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON -Dassert=ON", "extra_cmake_args": "-Dvalidator_keys=ON -Dassert=ON",
"package": { "package": {
"type": "deb", "type": "deb",
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-e6055dd", "image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-3a2d19f",
"variant": "assert" "variant": "assert"
} }
} }
@@ -101,7 +101,7 @@
"extra_cmake_args": "-Dvalidator_keys=ON", "extra_cmake_args": "-Dvalidator_keys=ON",
"package": { "package": {
"type": "rpm", "type": "rpm",
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-e6055dd" "image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-3a2d19f"
} }
} }
] ]
+4 -3
View File
@@ -12,7 +12,8 @@ on:
- "!nix/docker/README.md" - "!nix/docker/README.md"
- "!nix/devshell.nix" - "!nix/devshell.nix"
- "!nix/check-tools/**" - "!nix/check-tools/**"
- "bin/nix/default-loader-path.sh" - "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
pull_request: pull_request:
paths: paths:
- ".github/workflows/build-nix-images.yml" - ".github/workflows/build-nix-images.yml"
@@ -24,8 +25,8 @@ on:
- "!nix/devshell.nix" - "!nix/devshell.nix"
- "!nix/check-tools/**" - "!nix/check-tools/**"
- "bin/check-tools.sh" - "bin/check-tools.sh"
- "bin/nix/default-loader-path.sh" - "bin/default-loader-path.sh"
- "bin/install/sanitizer-libs.sh" - "bin/install-sanitizer-libs.sh"
workflow_dispatch: workflow_dispatch:
concurrency: concurrency:
+3 -2
View File
@@ -5,12 +5,13 @@ on:
branches: branches:
- develop - develop
paths: paths:
- "bin/install/packaging-tools.sh" - ".github/workflows/build-packaging-images.yml"
- "bin/install-packaging-tools.sh"
- "package/images/packaging/**" - "package/images/packaging/**"
pull_request: pull_request:
paths: paths:
- ".github/workflows/build-packaging-images.yml" - ".github/workflows/build-packaging-images.yml"
- "bin/install/packaging-tools.sh" - "bin/install-packaging-tools.sh"
- "package/images/packaging/**" - "package/images/packaging/**"
workflow_dispatch: workflow_dispatch:
@@ -5,6 +5,7 @@ on:
branches: branches:
- develop - develop
paths: paths:
- ".github/workflows/build-pre-commit-image.yml"
- "bin/pre-commit/Dockerfile" - "bin/pre-commit/Dockerfile"
- "rust-toolchain.toml" - "rust-toolchain.toml"
pull_request: pull_request:
+2 -2
View File
@@ -34,7 +34,7 @@ permissions:
jobs: jobs:
audit: audit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
permissions: permissions:
contents: read contents: read
# Needed to open an issue on scheduled failures. # Needed to open an issue on scheduled failures.
@@ -66,7 +66,7 @@ jobs:
- name: Create issue - name: Create issue
if: ${{ steps.audit.outcome != 'success' && github.event_name == 'schedule' }} if: ${{ steps.audit.outcome != 'success' && github.event_name == 'schedule' }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with: with:
title: "cargo audit found vulnerabilities" title: "cargo audit found vulnerabilities"
body_file: /tmp/cargo-audit-issue.md body_file: /tmp/cargo-audit-issue.md
+1 -1
View File
@@ -53,7 +53,7 @@ jobs:
- name: Create issue - name: Create issue
if: ${{ failure() && github.event_name == 'schedule' && github.repository == 'XRPLF/rippled' }} if: ${{ failure() && github.event_name == 'schedule' && github.repository == 'XRPLF/rippled' }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with: with:
title: "Releases not merged back into develop" title: "Releases not merged back into develop"
body_file: ${{ env.ISSUE_FILE }} body_file: ${{ env.ISSUE_FILE }}
+2 -2
View File
@@ -79,7 +79,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
@@ -108,7 +108,7 @@ jobs:
- name: Upload regenerated snapshot - name: Upload regenerated snapshot
if: failure() if: failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: check-tools-${{ runner.os }}-${{ runner.arch }} name: check-tools-${{ runner.os }}-${{ runner.arch }}
path: ${{ matrix.snapshot }} path: ${{ matrix.snapshot }}
+2 -1
View File
@@ -93,8 +93,9 @@ jobs:
.github/workflows/reusable-upload-recipe.yml .github/workflows/reusable-upload-recipe.yml
.clang-tidy .clang-tidy
.codecov.yml .codecov.yml
bin/check-nix-store-refs.sh
bin/check-tools.sh bin/check-tools.sh
bin/nix/** bin/default-loader-path.sh
cfg/** cfg/**
cmake/** cmake/**
conan/** conan/**
+2 -1
View File
@@ -31,8 +31,9 @@ on:
- ".github/workflows/reusable-upload-recipe.yml" - ".github/workflows/reusable-upload-recipe.yml"
- ".clang-tidy" - ".clang-tidy"
- ".codecov.yml" - ".codecov.yml"
- "bin/check-nix-store-refs.sh"
- "bin/check-tools.sh" - "bin/check-tools.sh"
- "bin/nix/**" - "bin/default-loader-path.sh"
- "cfg/**" - "cfg/**"
- "cmake/**" - "cmake/**"
- "conan/**" - "conan/**"
+2 -2
View File
@@ -14,7 +14,7 @@ on:
jobs: jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks. # Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks: run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@d7f2acb47d9662e1e2f8b1f5feffa6d21cc3290a uses: XRPLF/actions/.github/workflows/pre-commit.yml@279ec358f4a1be4088be3e024b07916fa97c75b6
with: with:
runs_on: ubuntu-latest runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-70b8fd3" }' container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-473fe44" }'
+2 -2
View File
@@ -41,13 +41,13 @@ env:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
@@ -129,7 +129,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: ${{ inputs.ccache_enabled }} enable_ccache: ${{ inputs.ccache_enabled }}
@@ -186,6 +186,9 @@ jobs:
with: with:
build_nproc: ${{ steps.nproc.outputs.nproc }} build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ inputs.build_type }} build_type: ${{ inputs.build_type }}
# Set the verbosity to "quiet" for Windows to avoid an excessive
# amount of logs. For other OSes, the "verbose" logs are more useful.
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
sanitizers: ${{ inputs.sanitizers }} sanitizers: ${{ inputs.sanitizers }}
- name: Configure CMake - name: Configure CMake
@@ -254,20 +257,20 @@ jobs:
# cache included, since what it holds is what gets uploaded and reused. # cache included, since what it holds is what gets uploaded and reused.
- name: Check the build output for Nix store references (Nix toolchain) - name: Check the build output for Nix store references (Nix toolchain)
if: ${{ inputs.toolchain == 'nix' }} if: ${{ inputs.toolchain == 'nix' }}
run: ./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}" run: ./bin/check-nix-store-refs.sh "${BUILD_DIR}"
- name: Check the Conan cache for Nix store references (Nix toolchain) - name: Check the Conan cache for Nix store references (Nix toolchain)
if: ${{ inputs.toolchain == 'nix' }} if: ${{ inputs.toolchain == 'nix' }}
run: ./bin/nix/check-nix-store-refs.sh "${CONAN_HOME}" run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
# Only what PatchNixBinary.cmake retargets: the toolchain in the Linux # Only what PatchNixBinary.cmake retargets: the toolchain in the Linux
# images always references the store. Same condition it uses. # images always references the store. Same condition it uses.
- name: Check for Nix store references (Linux) - name: Check for Nix store references (Linux)
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }} if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
run: | run: |
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpld" ./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpld"
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpl_tests" ./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpl_tests"
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpld_tests" ./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpld_tests"
- name: Show ccache statistics - name: Show ccache statistics
if: ${{ inputs.ccache_enabled }} if: ${{ inputs.ccache_enabled }}
@@ -280,7 +283,7 @@ jobs:
- name: Upload the binary (Linux) - name: Upload the binary (Linux)
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && runner.os == 'Linux' }} if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && runner.os == 'Linux' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: xrpld-${{ inputs.config_name }} name: xrpld-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpld path: ${{ env.BUILD_DIR }}/xrpld
@@ -294,7 +297,7 @@ jobs:
- name: Upload the validator-keys binary - name: Upload the validator-keys binary
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && env.VALIDATOR_KEYS_ENABLED == 'true' }} if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && env.VALIDATOR_KEYS_ENABLED == 'true' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: validator-keys-${{ inputs.config_name }} name: validator-keys-${{ inputs.config_name }}
path: | path: |
@@ -305,7 +308,7 @@ jobs:
- name: Upload the test binary (Linux) - name: Upload the test binary (Linux)
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }} if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: xrpl_tests-${{ inputs.config_name }} name: xrpl_tests-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpl_tests path: ${{ env.BUILD_DIR }}/xrpl_tests
@@ -321,7 +324,7 @@ jobs:
- name: Upload server definitions - name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }} if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: server-definitions name: server-definitions
path: ${{ env.BUILD_DIR }}/server_definitions.json path: ${{ env.BUILD_DIR }}/server_definitions.json
+6 -5
View File
@@ -34,7 +34,7 @@ jobs:
needs: [determine-files] needs: [determine-files]
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }} if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"] runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-3d526d4" container: "ghcr.io/xrplf/xrpld/nix-debian:sha-060957e"
permissions: permissions:
contents: read contents: read
issues: write issues: write
@@ -43,7 +43,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
@@ -73,6 +73,7 @@ jobs:
with: with:
build_nproc: ${{ steps.nproc.outputs.nproc }} build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ env.BUILD_TYPE }} build_type: ${{ env.BUILD_TYPE }}
log_verbosity: verbose
- name: Configure CMake - name: Configure CMake
working-directory: ${{ env.BUILD_DIR }} working-directory: ${{ env.BUILD_DIR }}
@@ -109,7 +110,7 @@ jobs:
- name: Upload clang-tidy output - name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }} if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
path: ${{ env.OUTPUT_FILE }} path: ${{ env.OUTPUT_FILE }}
archive: false archive: false
@@ -133,7 +134,7 @@ jobs:
- name: Upload clang-tidy diff output - name: Upload clang-tidy diff output
if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }} if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
path: ${{ env.DIFF_FILE }} path: ${{ env.DIFF_FILE }}
archive: false archive: false
@@ -185,7 +186,7 @@ jobs:
- name: Create issue - name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }} if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
uses: XRPLF/actions/create-issue@b489c21d53928f7dab4874912fec40e4f6c9e85e uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with: with:
title: "Clang-tidy check failed" title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }} body_file: ${{ env.ISSUE_FILE }}
@@ -44,7 +44,7 @@ jobs:
# Every package lands in one directory; the step below picks its own, # Every package lands in one directory; the step below picks its own,
# which keeps this independent of the artifact names. # which keeps this independent of the artifact names.
- name: Download package artifacts - name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
pattern: "*-pkg" pattern: "*-pkg"
merge-multiple: true merge-multiple: true
@@ -95,15 +95,11 @@ jobs:
apt-get update -qq apt-get update -qq
apt-get install -y "./${PACKAGE}" apt-get install -y "./${PACKAGE}"
# Rocky Linux and AlmaLinux pick a mirror from a mirrorlist, and now and
# then get one that serves the repository metadata at a few hundred kB/s,
# which alone outlasts the job's timeout. dnf only abandons a mirror below
# 1000 B/s for 30 s, so raise that floor to fail over to the next one fast.
- name: Install the RPM - name: Install the RPM
if: ${{ inputs.package_type == 'rpm' }} if: ${{ inputs.package_type == 'rpm' }}
env: env:
PACKAGE: ${{ steps.find.outputs.package }} PACKAGE: ${{ steps.find.outputs.package }}
run: dnf install -y --setopt=minrate=1M --setopt=timeout=10 "./${PACKAGE}" run: dnf install -y "./${PACKAGE}"
- name: Run xrpld - name: Run xrpld
run: xrpld --version run: xrpld --version
+9 -9
View File
@@ -100,18 +100,18 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
- name: Download pre-built xrpld binary - name: Download pre-built xrpld binary
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
name: ${{ matrix.xrpld_artifact_name }} name: ${{ matrix.xrpld_artifact_name }}
path: ${{ env.BUILD_DIR }} path: ${{ env.BUILD_DIR }}
- name: Download pre-built validator-keys binary - name: Download pre-built validator-keys binary
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
name: ${{ matrix.validator_keys_artifact_name }} name: ${{ matrix.validator_keys_artifact_name }}
path: ${{ env.BUILD_DIR }} path: ${{ env.BUILD_DIR }}
@@ -151,7 +151,7 @@ jobs:
# version starts with a digit and a longer name does not, so that one digit # version starts with a digit and a longer name does not, so that one digit
# is what tells 'xrpld-3.4.1-...' from 'xrpld-assert-3.4.1-...'. # is what tells 'xrpld-3.4.1-...' from 'xrpld-assert-3.4.1-...'.
- name: Upload package artifact - name: Upload package artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: ${{ matrix.xrpld_artifact_name }}-pkg name: ${{ matrix.xrpld_artifact_name }}-pkg
path: | path: |
@@ -160,7 +160,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload debug symbol artifact - name: Upload debug symbol artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: ${{ matrix.xrpld_artifact_name }}-pkg-debug name: ${{ matrix.xrpld_artifact_name }}-pkg-debug
path: | path: |
@@ -225,13 +225,13 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
# Both artifacts, so the debug symbols are published alongside the package. # Both artifacts, so the debug symbols are published alongside the package.
- name: Download package artifacts - name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
pattern: ${{ matrix.xrpld_artifact_name }}-pkg* pattern: ${{ matrix.xrpld_artifact_name }}-pkg*
merge-multiple: true merge-multiple: true
@@ -287,7 +287,7 @@ jobs:
run: echo "PUSH=${PUSH}" | tee -a "${GITHUB_ENV}" run: echo "PUSH=${PUSH}" | tee -a "${GITHUB_ENV}"
- name: Download package artifacts - name: Download package artifacts
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
pattern: "*-pkg" pattern: "*-pkg"
merge-multiple: true merge-multiple: true
@@ -295,7 +295,7 @@ jobs:
- name: Download voidstar binary - name: Download voidstar binary
if: ${{ matrix.target == 'voidstar' }} if: ${{ matrix.target == 'voidstar' }}
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
name: xrpld-ubuntu-clang-debug-amd64-voidstar name: xrpld-ubuntu-clang-debug-amd64-voidstar
path: ${{ env.CONTEXT }} path: ${{ env.CONTEXT }}
+3 -3
View File
@@ -28,7 +28,7 @@ permissions:
jobs: jobs:
clippy: clippy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -41,7 +41,7 @@ jobs:
coverage: coverage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -70,7 +70,7 @@ jobs:
doc: doc:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+2 -2
View File
@@ -40,7 +40,7 @@ defaults:
jobs: jobs:
upload: upload:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3d526d4 container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-060957e
env: env:
REMOTE_NAME: ${{ inputs.remote_name }} REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }} CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
@@ -50,7 +50,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
+5 -2
View File
@@ -68,7 +68,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner - name: Prepare runner
uses: XRPLF/actions/prepare-runner@8e98d61f011fd2a67f3fde5f0f075662c099a527 uses: XRPLF/actions/prepare-runner@b3e255d74d785d053e4903da8ac90983cd7d9e82
with: with:
enable_ccache: false enable_ccache: false
@@ -108,11 +108,14 @@ jobs:
build_nproc: ${{ steps.nproc.outputs.nproc }} build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ matrix.build_type }} build_type: ${{ matrix.build_type }}
force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }} force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
# Set the verbosity to "quiet" for Windows to avoid an excessive
# amount of logs. For other OSes, the "verbose" logs are more useful.
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
sanitizers: ${{ matrix.sanitizers }} sanitizers: ${{ matrix.sanitizers }}
- name: Check the Conan cache for Nix store references (Nix toolchain) - name: Check the Conan cache for Nix store references (Nix toolchain)
if: ${{ matrix.toolchain == 'nix' }} if: ${{ matrix.toolchain == 'nix' }}
run: ./bin/nix/check-nix-store-refs.sh "${CONAN_HOME}" run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
- name: Log into Conan remote - name: Log into Conan remote
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }} if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
+5 -6
View File
@@ -60,7 +60,7 @@ repos:
types_or: [c++, c] types_or: [c++, c]
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: a9a8a861f30ed207ead7d5a3b7e8032283ba5da7 # frozen: v23.1.2 rev: e2b496dc2bd8340c2524cb9a2d2a943cde1bb6df # frozen: v23.1.1
hooks: hooks:
- id: clang-format - id: clang-format
args: [--style=file] args: [--style=file]
@@ -82,10 +82,9 @@ repos:
files: ^crates/.*\.rs$ files: ^crates/.*\.rs$
- repo: https://github.com/BlankSpruce/gersemi-pre-commit - repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: 28010ddd6016e1a0f7bd232acb6536ef996ae897 # frozen: 0.29.2 rev: f1c4833f8cf23c6d952673abc73525411a5719e8 # frozen: 0.29.1
hooks: hooks:
- id: gersemi - id: gersemi
args: [-i, --warnings-as-errors]
- repo: https://github.com/rbubley/mirrors-prettier - repo: https://github.com/rbubley/mirrors-prettier
rev: ef4a397f916211b4a39ccf9d3d9cbb6562157251 # frozen: v3.9.9 rev: ef4a397f916211b4a39ccf9d3d9cbb6562157251 # frozen: v3.9.9
@@ -96,19 +95,19 @@ repos:
# Scoped to package/: the rest of the repo's Python has pre-existing findings, # Scoped to package/: the rest of the repo's Python has pre-existing findings,
# so widening these is its own change. # so widening these is its own change.
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: f12be1ebaa5351c1fc76472de98db2c3446c8253 # frozen: v0.16.10 rev: a56c0b927e6465d37cae3e97d35d4d18ab2b96cd # frozen: v0.16.9
hooks: hooks:
- id: ruff-check - id: ruff-check
args: [--fix] args: [--fix]
files: ^package/.*\.py$ files: ^package/.*\.py$
- repo: https://github.com/psf/black-pre-commit-mirror - repo: https://github.com/psf/black-pre-commit-mirror
rev: 96ae3e5802f3fe2d551e703e18f0a367d1a81ac2 # frozen: 26.10.0 rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
hooks: hooks:
- id: black - id: black
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: 2834ec6639549dd6796205c8f011dedcd587288b # frozen: v2.4.0 rev: 7ff8d35ae36a7d2b968f2f90b4c723e292e594ee # frozen: v2.3.1
hooks: hooks:
- id: mypy - id: mypy
args: [--strict] args: [--strict]
+1 -13
View File
@@ -28,18 +28,7 @@ Version 3.5.0 is not yet released.
### Additions in 3.5.0 ### Additions in 3.5.0
- `subscribe`, `unsubscribe`: Added an optional `mpt_issuances` request field, an array of MPT issuance IDs (hex strings). Subscribers receive the same `transaction` message as the `transactions` stream for each validated transaction whose metadata affects a subscribed issuance. MPT issuance subscriptions count toward the per-connection subscription limit. An empty array, a non-array value, or an invalid ID returns `invalidParams`. ([#5671](https://github.com/XRPLF/rippled/pull/5671)) - `subscribe`, `unsubscribe`: Added an optional `mpt_issuances` request field, an array of MPT issuance IDs (hex strings). Subscribers receive a message with `type` `mptTransaction` for each validated transaction whose metadata affects a subscribed issuance; the message has the same fields as the `transactions` stream. MPT issuance subscriptions count toward the per-connection subscription limit. An empty array, a non-array value, or an invalid ID returns `invalidParams`. ([#5671](https://github.com/XRPLF/rippled/pull/5671))
- `ledger_entry`: Add full support for checks, NFT offers, payment channels, and signer lists. ([#6319](https://github.com/XRPLF/rippled/pull/6319))
### Bugfixes in 3.5.0
- `channel_authorize`: The `channel_id` field now returns an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
- `channel_verify`: The `channel_id` and `signature` fields now return an `invalidParams` error if the value is not a string. [#7582](https://github.com/XRPLF/rippled/pull/7582)
- `account_currencies`, `account_nfts`, `account_offers`: A request with more than one problem may now report a different one of them. An invalid `ledger_hash` or `ledger_index` is reported before an invalid or missing `account`. An invalid `limit` or `marker` is reported before `lgrNotFound` or `actNotFound`, and for `account_offers` also before `actMalformed`. A request with a single problem returns the same error as before. [#8561](https://github.com/XRPLF/rippled/pull/8561)
### Bugfixes in 3.5.0
- `feature`: The admin-only `vetoed` field now returns `invalidParams` unless its value is a boolean. [#7583](https://github.com/XRPLF/rippled/pull/7583)
## XRP Ledger server version 3.4.0 ## XRP Ledger server version 3.4.0
@@ -61,7 +50,6 @@ Version 3.4.0 is not yet released. These changes are available in the 3.4.0 beta
- `account_lines`: The `peer` field now returns an error if the value is not a string. [#7728](https://github.com/XRPLF/rippled/pull/7728) - `account_lines`: The `peer` field now returns an error if the value is not a string. [#7728](https://github.com/XRPLF/rippled/pull/7728)
- `ledger`: `delivered_amount` is now included in the metadata of successful `AccountDelete` transactions when transactions are expanded (`expand`, or admin-only `full`). Previously it was only added for `Payment` and `CheckCash`, which made `ledger` inconsistent with `tx` and `account_tx`. [#5706](https://github.com/XRPLF/rippled/pull/5706) - `ledger`: `delivered_amount` is now included in the metadata of successful `AccountDelete` transactions when transactions are expanded (`expand`, or admin-only `full`). Previously it was only added for `Payment` and `CheckCash`, which made `ledger` inconsistent with `tx` and `account_tx`. [#5706](https://github.com/XRPLF/rippled/pull/5706)
- `noripple_check`: The `transactions` field is no longer included in error responses; it is still returned (possibly as an empty array) whenever `transactions` is `true` and the request succeeds. A malformed `account` is now rejected before the ledger is looked up, so that error response no longer carries the `ledger_hash`, `ledger_index`, and `validated` fields ([#6303](https://github.com/XRPLF/rippled/pull/6303)). - `noripple_check`: The `transactions` field is no longer included in error responses; it is still returned (possibly as an empty array) whenever `transactions` is `true` and the request succeeds. A malformed `account` is now rejected before the ledger is looked up, so that error response no longer carries the `ledger_hash`, `ledger_index`, and `validated` fields ([#6303](https://github.com/XRPLF/rippled/pull/6303)).
- `transaction_entry`: An object or an array in `tx_hash` now returns `malformedRequest`, like any other value that is not a hex hash, instead of an `internal` error.
## XRP Ledger server version 3.3.0 ## XRP Ledger server version 3.3.0
+10 -16
View File
@@ -34,7 +34,7 @@ so tools can filter them and protection rules can target `release/*` and `stagin
- **Branches only move forward.** - **Branches only move forward.**
`develop`, `staging/X.Y.x`, and `release/X.Y.x` are never rewritten. `develop`, `staging/X.Y.x`, and `release/X.Y.x` are never rewritten.
- **Cherry-picking only goes from `develop` to a staging branch**, - **Cherry-picking only goes from `develop` to a staging branch**,
for fixes that must get into a release after the [code freeze](#release-candidates) for fixes that must get into a release after the code freeze
(see [Emergency Fixes From `develop`](#emergency-fixes-from-develop)). (see [Emergency Fixes From `develop`](#emergency-fixes-from-develop)).
- **Security fixes are prepared privately and published with the release that contains them**, - **Security fixes are prepared privately and published with the release that contains them**,
so vulnerabilities are not disclosed prematurely. so vulnerabilities are not disclosed prematurely.
@@ -49,7 +49,6 @@ develop staging/X.Y.x & release/X.Y.x
│ │
├── Tag: X.Y.0-b1 ├── Tag: X.Y.0-b1
├── Tag: X.Y.0-bN ├── Tag: X.Y.0-bN
│ (2 weeks before rc1: freeze on large changes starts)
├── Tag: X.Y.0-rc1 ───────────────┐ (branches created) ├── Tag: X.Y.0-rc1 ───────────────┐ (branches created)
│ │ │ │
│ (development continues) ├── Fixes │ (development continues) ├── Fixes
@@ -76,20 +75,16 @@ develop staging/X.Y.x & release/X.Y.x
3. **Branches:** `staging/X.Y.x` and `release/X.Y.x` are created from `develop` 3. **Branches:** `staging/X.Y.x` and `release/X.Y.x` are created from `develop`
at the commit tagged `X.Y.0-rc1`. at the commit tagged `X.Y.0-rc1`.
The first RC also kicks off the QE process. The first RC also kicks off the QE process.
4. **Code freeze:** No new features or unrelated changes are pulled from `develop`
### Freeze on Large Changes into `staging/X.Y.x` or `release/X.Y.x`.
Only critical stabilization fixes go into the line.
From two weeks before `X.Y.0-rc1` until `X.Y.0` is [merged back](#merging-back-into-develop), 5. **No large changes on `develop`:** Until `X.Y.0` is [merged back](#merging-back-into-develop),
large changes (e.g., big refactors, moving or renaming many files, mass reformatting) large changes (e.g., big refactors, moving or renaming many files, mass reformatting)
are not merged into `develop`. are not merged into `develop`,
so that fixes on the line and the merge back don't run into conflicts.
### Release Candidates ### Release Candidates
After branching, the line is in code freeze:
no new features or unrelated changes are pulled from `develop`
into `staging/X.Y.x` or `release/X.Y.x`.
Only critical stabilization fixes go into the line.
1. Fixes are developed against `staging/X.Y.x`. 1. Fixes are developed against `staging/X.Y.x`.
2. When ready, a new RC is created on `staging/X.Y.x`, 2. When ready, a new RC is created on `staging/X.Y.x`,
and `release/X.Y.x` is fast-forwarded to it. and `release/X.Y.x` is fast-forwarded to it.
@@ -111,8 +106,7 @@ one right after the other.
2. `release/X.Y.x` is fast-forwarded to `staging/X.Y.x`, 2. `release/X.Y.x` is fast-forwarded to `staging/X.Y.x`,
and the release is tagged on it. and the release is tagged on it.
3. The release is immediately [merged back into `develop`](#merging-back-into-develop). 3. The release is immediately [merged back into `develop`](#merging-back-into-develop).
For a major-minor release, this lifts the [freeze on large changes](#freeze-on-large-changes) For a major-minor release, this lifts the freeze on large changes in `develop`.
in `develop`.
### Merging Back Into `develop` ### Merging Back Into `develop`
@@ -133,7 +127,7 @@ After the merge, `git log develop..<tag>` must be empty.
### Emergency Fixes From `develop` ### Emergency Fixes From `develop`
If a commit was merged to `develop` If a commit was merged to `develop`
and needs to be included in a release after the [code freeze](#release-candidates): and needs to be included in a release after the code freeze:
1. Create a PR that cherry-picks the commit onto `staging/X.Y.x`. 1. Create a PR that cherry-picks the commit onto `staging/X.Y.x`.
2. Leave `develop` as it is, with no reverts. 2. Leave `develop` as it is, with no reverts.
@@ -10,7 +10,7 @@
# alone; the scripts in a Conan cache are all git hook samples and autotools # alone; the scripts in a Conan cache are all git hook samples and autotools
# scratch, 36 false positives to 0 real. # scratch, 36 false positives to 0 real.
# #
# Usage: bin/nix/check-nix-store-refs.sh <path> # Usage: bin/check-nix-store-refs.sh <path>
set -euo pipefail set -euo pipefail
+6 -17
View File
@@ -20,11 +20,9 @@
# development setups, but not in the macOS CI environment. They are checked # development setups, but not in the macOS CI environment. They are checked
# everywhere except when running in CI on macOS. # everywhere except when running in CI on macOS.
# #
# Tools that Nix also exposes under a version-suffixed name # Tools that Nix also exposes under a version-suffixed name (`clang-tidy-22`,
# (`clang-tidy-<v>`, `g++-<v>`, ...) are probed under both names: # `g++-15`, ...) are probed under both names: a suffixed name can break while
# a suffixed name can break while the plain one still works # the plain one still works (see mkVersionedToolLinks in nix/packages.nix).
# (see mkVersionedToolLinks in nix/packages.nix).
# The suffix is the major version of the plain `clang` / `gcc` on PATH.
# #
# Tools scoped to a single dev shell rather than to commonPackages are checked # Tools scoped to a single dev shell rather than to commonPackages are checked
# only in that shell, keyed off XRPL_DEVSHELL. # only in that shell, keyed off XRPL_DEVSHELL.
@@ -36,16 +34,9 @@
set -uo pipefail set -uo pipefail
# major_version <compiler> # Version suffixes of the Nix tool links, tracking nix/packages.nix.
# Major version of a compiler on PATH, or "unknown" when it isn't there. gcc_version=15
major_version() { llvm_version=22
local version
version="$("$1" -dumpversion 2>/dev/null)" || version=""
version="${version%%.*}"
printf '%s' "${version:-unknown}"
}
llvm_version="$(major_version clang)"
missing=() missing=()
checked=0 checked=0
@@ -121,7 +112,6 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check ClangBuildAnalyzer check ClangBuildAnalyzer
check curl check curl
check file check file
check jq
check less check less
check make check make
# net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no # net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no
@@ -190,7 +180,6 @@ fi
if [ "${os}" = "linux" ]; then if [ "${os}" = "linux" ]; then
echo echo
echo "GCC toolchain:" echo "GCC toolchain:"
gcc_version="$(major_version gcc)"
check gcc check gcc
check "gcc-${gcc_version}" check "gcc-${gcc_version}"
check g++ check g++
File renamed without changes.
File renamed without changes.
File renamed without changes.
-65
View File
@@ -1,65 +0,0 @@
#!/usr/bin/env bash
# Fail if a binary of a build-context Conan package loads anything from the Nix
# store other than glibc, or cannot resolve a library at all.
#
# Only binaries linked by the Nix toolchain are checked, i.e. those recording a
# store path as their interpreter or RUNPATH. Prebuilt upstream binaries (such
# as the ones the cmake package ships) use the system loader instead.
#
# Build-context packages provide the tools that run during the build (protoc,
# grpc_cpp_plugin, ...). Their package ID does not change when a Nix toolchain
# update moves the GCC runtime to a new store path, so a cached binary has to
# get by with the pinned glibc alone. See docs/build/nix.md.
#
# Usage: bin/nix/check-build-context-runtime.sh <graph.json>
# <graph.json> is the output of `conan install --format=json`.
set -euo pipefail
if [ "$#" -ne 1 ]; then
echo "usage: $0 <graph.json>" >&2
exit 2
fi
if [ "$(uname -s)" != "Linux" ]; then
echo "$0: Linux only" >&2
exit 2
fi
folders="$(jq -r '.graph.nodes[] | select(.context == "build" and .package_folder) | .package_folder' "$1" | sort -u)"
checked=0
failed=0
while IFS= read -r file; do
case "$(file -b "${file}")" in
ELF*) ;;
*) continue ;;
esac
[[ "$(readelf -ldW "${file}")" == */nix/store/* ]] || continue
checked=$((checked + 1))
# `ldd` lists the interpreter and every library as the loader resolves them.
if deps="$(ldd "${file}" 2>&1)"; then
bad="$(printf '%s\n' "${deps}" |
grep -E 'not found|/nix/store/' |
grep -vE '/nix/store/[^/]+-glibc-[^/]+/' || true)"
else
case "${deps}" in
*"not a dynamic executable"*) continue ;;
esac
bad="${deps}"
fi
if [ -n "${bad}" ]; then
failed=$((failed + 1))
echo "::error file=${file}::loads a library from the Nix store other than glibc"
echo "${file}"
echo "${bad}" | sed 's/^/ /'
fi
done < <(
# shellcheck disable=SC2086 # one folder per line, no spaces in Conan paths
[ -z "${folders}" ] || find ${folders} -type f \( -perm -u+x -o -name '*.so*' \)
)
echo "Build-context packages: checked ${checked} binaries, ${failed} failed."
[ "${failed}" -eq 0 ]
+1 -1
View File
@@ -23,7 +23,7 @@ apt-get clean
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
EOF EOF
ARG PRE_COMMIT_VERSION=4.6.2 ARG PRE_COMMIT_VERSION=4.6.0
RUN pip install --no-cache --break-system-packages \ RUN pip install --no-cache --break-system-packages \
pre-commit==${PRE_COMMIT_VERSION} pre-commit==${PRE_COMMIT_VERSION}
+7 -20
View File
@@ -26,6 +26,8 @@ import sys
import tempfile import tempfile
from pathlib import Path from pathlib import Path
CLANG_TIDY_VERSION = 22
# Extensions run-clang-tidy can analyse: `.cpp` translation units and, thanks to # Extensions run-clang-tidy can analyse: `.cpp` translation units and, thanks to
# the `verify_headers` build option, `.h`/`.hpp` headers (each has its own # the `verify_headers` build option, `.h`/`.hpp` headers (each has its own
# compile_commands.json entry). `.ipp` fragments have no entry and are skipped. # compile_commands.json entry). `.ipp` fragments have no entry and are skipped.
@@ -37,21 +39,8 @@ TIDY_EXTENSIONS = {".cpp", ".h", ".hpp"}
FILEPATH_RE = re.compile(r"^(\s*(?:-\s+)?FilePath:\s*)'((?:[^']|'')*)'\s*$") FILEPATH_RE = re.compile(r"^(\s*(?:-\s+)?FilePath:\s*)'((?:[^']|'')*)'\s*$")
def clang_tidy_major() -> str | None: def find_tool(name: str) -> str | None:
"""Major version of the `clang-tidy` on PATH, which run-clang-tidy invokes.""" for candidate in (f"{name}-{CLANG_TIDY_VERSION}", name):
if not (clang_tidy := shutil.which("clang-tidy")):
return None
output = subprocess.run(
[clang_tidy, "--version"], capture_output=True, text=True
).stdout
m = re.search(r"LLVM version (\d+)", output)
return m.group(1) if m else None
def find_tool(name: str, version: str | None) -> str | None:
"""Prefer `<name>-<version>`, so a host tool of another version can't win."""
candidates = ([f"{name}-{version}"] if version else []) + [name]
for candidate in candidates:
if path := shutil.which(candidate): if path := shutil.which(candidate):
return path return path
return None return None
@@ -114,9 +103,8 @@ def main():
if not files: if not files:
return 0 return 0
version = clang_tidy_major() run_clang_tidy = find_tool("run-clang-tidy")
run_clang_tidy = find_tool("run-clang-tidy", version) clang_apply_replacements = find_tool("clang-apply-replacements")
clang_apply_replacements = find_tool("clang-apply-replacements", version)
missing = [ missing = [
name name
for name, path in ( for name, path in (
@@ -126,10 +114,9 @@ def main():
if not path if not path
] ]
if missing: if missing:
tried = f" (tried the '-{version}' suffix too)" if version else ""
print( print(
f"clang-tidy check failed: TIDY is enabled but {' and '.join(missing)} " f"clang-tidy check failed: TIDY is enabled but {' and '.join(missing)} "
f"was not found in PATH{tried}.", f"was not found in PATH (tried the '-{CLANG_TIDY_VERSION}' suffix too).",
file=sys.stderr, file=sys.stderr,
) )
return 1 return 1
+2 -2
View File
@@ -17,7 +17,7 @@
(runtime libraries resolved through the rpath) are skipped too. (runtime libraries resolved through the rpath) are skipped too.
Everywhere else `patch_nix_binary` is a no-op. Everywhere else `patch_nix_binary` is a no-op.
The default loader is resolved by bin/nix/default-loader-path.sh. The default loader is resolved by bin/default-loader-path.sh.
#]===================================================================] #]===================================================================]
include_guard(GLOBAL) include_guard(GLOBAL)
@@ -25,7 +25,7 @@ include_guard(GLOBAL)
include(CompilationEnv) include(CompilationEnv)
# Resolves the system default ELF loader path for the current architecture. # Resolves the system default ELF loader path for the current architecture.
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/nix/default-loader-path.sh") set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
if( if(
is_linux is_linux
-15
View File
@@ -292,20 +292,6 @@ if(xrpld)
) )
target_sources(xrpld PRIVATE ${sources}) target_sources(xrpld PRIVATE ${sources})
rpcspec_generate_instantiations(
OUT_VAR rpcspec_instantiations
VALUE_TYPE "::json::Value"
VIEW_HEADER "xrpld/rpc/detail/JsonObjectView.hpp"
HANDLERS
account_currencies
account_nfts
account_offers
book_changes
ledger
transaction_entry
)
target_sources(xrpld PRIVATE ${rpcspec_instantiations})
if(tests) if(tests)
file( file(
GLOB_RECURSE sources GLOB_RECURSE sources
@@ -336,7 +322,6 @@ if(xrpld)
# antithesis_instrumentation.h, which is not exported as INTERFACE # antithesis_instrumentation.h, which is not exported as INTERFACE
target_include_directories( target_include_directories(
xrpld xrpld
SYSTEM
PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk PRIVATE ${CMAKE_SOURCE_DIR}/external/antithesis-sdk
) )
endif() endif()
+1 -6
View File
@@ -77,24 +77,19 @@ if(is_clang)
message(STATUS " Ignorelist: ${ignorelist_path}") message(STATUS " Ignorelist: ${ignorelist_path}")
endif() endif()
# Define the SANITIZERS macro for BuildInfo.cpp, plus one of XRPL_ASAN, # Define SANITIZERS macro for BuildInfo.cpp
# XRPL_TSAN and XRPL_UBSAN per active sanitizer, so that code can test for a
# specific one with #ifdef instead of parsing the dot-joined SANITIZERS string.
set(sanitizers_list) set(sanitizers_list)
if(SANITIZERS MATCHES "address") if(SANITIZERS MATCHES "address")
set(enable_asan ON) set(enable_asan ON)
list(APPEND sanitizers_list "ASAN") list(APPEND sanitizers_list "ASAN")
target_compile_definitions(common INTERFACE XRPL_ASAN)
endif() endif()
if(SANITIZERS MATCHES "thread") if(SANITIZERS MATCHES "thread")
set(enable_tsan ON) set(enable_tsan ON)
list(APPEND sanitizers_list "TSAN") list(APPEND sanitizers_list "TSAN")
target_compile_definitions(common INTERFACE XRPL_TSAN)
endif() endif()
if(SANITIZERS MATCHES "undefinedbehavior") if(SANITIZERS MATCHES "undefinedbehavior")
set(enable_ubsan ON) set(enable_ubsan ON)
list(APPEND sanitizers_list "UBSAN") list(APPEND sanitizers_list "UBSAN")
target_compile_definitions(common INTERFACE XRPL_UBSAN)
endif() endif()
if(sanitizers_list) if(sanitizers_list)
+2 -2
View File
@@ -7,7 +7,7 @@
pcpp>=1.30 pcpp>=1.30
# Parser combinator library - used to parse the macro DSL # Parser combinator library - used to parse the macro DSL
pyparsing>=3.3.3 pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates # Template engine - used to generate C++ code from templates
Mako>=1.4.2 Mako>=1.2.2
+6 -6
View File
@@ -1,8 +1,8 @@
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv pip compile requirements.in --generate-hashes --output-file requirements.txt # uv pip compile requirements.in --generate-hashes --output-file requirements.txt
mako==1.4.3 \ mako==1.3.12 \
--hash=sha256:723296007c870bfd6b3f0c3230dba7198096e5269297ebf5e4eff9e7ffa39d4f \ --hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
--hash=sha256:cd6537fe88d5fec315c55c2f8529bc4ce7a9a352ad7db3eeaa6a66e2dd4ec37a --hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
# via -r requirements.in # via -r requirements.in
markupsafe==3.0.3 \ markupsafe==3.0.3 \
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \ --hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
@@ -99,7 +99,7 @@ pcpp==1.30 \
--hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \ --hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \
--hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1 --hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1
# via -r requirements.in # via -r requirements.in
pyparsing==3.3.3 \ pyparsing==3.3.2 \
--hash=sha256:928ae7e20211f3b6f3915a72f06a0cfd29ab9d24279dd6346b6b1a7146397d36 \ --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
--hash=sha256:ece8c00a69cf01b45d0b1dedabb469c90d8caf996d4fda40f147627a122849a4 --hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
# via -r requirements.in # via -r requirements.in
+2 -6
View File
@@ -3,7 +3,7 @@
"requires": [ "requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708", "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688", "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"xrpl-rpc-spec/0.1.23#56e8946f5b3fb949a3732e1a51135ca2%1790977482.197086", "xrpl-rpc-spec/0.1.19#870b2d3abcfbbf13b61c2d3c69495060%1790348286.187549",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447", "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521", "soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
@@ -20,7 +20,7 @@
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892", "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228", "jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979", "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.81.1#aaa93ab6cda2f2baa6a84490582c8adf%1791284951.826256", "grpc/1.81.1#b87796a4269034856cbc1a2522db16eb%1788275071.530512",
"fast_float/8.2.10#f6f28d6bb22112078e7dbda611caf681%1785888854.601666", "fast_float/8.2.10#f6f28d6bb22112078e7dbda611caf681%1785888854.601666",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562", "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
@@ -34,15 +34,11 @@
"build_requires": [ "build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708", "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1782395692.540639", "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1782395692.540639",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1782392402.431897",
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933", "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.3#f806de8933e3bf6f01016c6a888cee2e%1783945160.863288",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649", "msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#1727f439cf74e83826ec96d0b4904eee%1784541921.659", "m4/1.4.19#1727f439cf74e83826ec96d0b4904eee%1784541921.659",
"grpc/1.81.1#aaa93ab6cda2f2baa6a84490582c8adf%1791284951.826256",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091", "cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226", "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56", "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86", "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
+1 -9
View File
@@ -3,13 +3,5 @@
core:non_interactive=True core:non_interactive=True
core.download:parallel={{ os.cpu_count() }} core.download:parallel={{ os.cpu_count() }}
core.upload:parallel={{ os.cpu_count() }} core.upload:parallel={{ os.cpu_count() }}
# Fall back to Conan Center's source backups when a recipe's upstream URL is down tools.files.download:retry=5
# (e.g. the GNU FTP mirrors), see
# https://github.com/conan-io/conan-center-index/issues/28147#issuecomment-3183544772
# The backups are only tried once every upstream URL has used up its retries,
# so keep the retries low.
core.sources:download_urls=["origin", "https://c3i.jfrog.io/artifactory/conan-center-backup-sources"]
tools.files.download:retry=1
tools.files.download:retry_wait=10 tools.files.download:retry_wait=10
# Fail fast on unreachable hosts (default connect timeout is 30s), keep the 60s read timeout.
core.net.http:timeout=(5, 60)
+4 -31
View File
@@ -29,9 +29,9 @@ os.version={{ min_macos_version }}
[conf] [conf]
{# The Boost recipe builds with b2, which doesn't use Conan's toolchain files. #} {# The Boost recipe builds with b2, which doesn't use Conan's toolchain files. #}
{# Instead it hand-rolls the compiler for user-config.jam, #} {# Instead it hand-rolls the compiler for user-config.jam, #}
{# and its fallback probes a version-suffixed binary (e.g. `g++-<major>`) before plain `g++`. #} {# 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 `-<major>` suffix), #} {# Inside the Nix shell the wrapper only provides `g++`/`gcc` (no `-15` suffix), #}
{# so on a host that also has a system `g++-<major>` the probe escapes Nix #} {# 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 picks the system compiler, which is mismatched with the Nix libraries #}
{# and breaks the build (e.g. Boost.Stacktrace link checks fail). #} {# 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) #} {# Pinning the executables here short-circuits that probe so Boost (and the rest of the toolchain) #}
@@ -49,31 +49,8 @@ tools.build:compiler_executables={'c':'{{ cc_exe }}','cpp':'{{ cxx_exe }}'}
user.package:cppstd_version=23 user.package:cppstd_version=23
tools.info.package_id:confs+=["user.package:cppstd_version"] tools.info.package_id:confs+=["user.package:cppstd_version"]
{% if os == "Linux" and context == "build" %}
{# Build-context executables (protoc, grpc_cpp_plugin, build tools) run during the build #}
{# and would otherwise load libstdc++/libgcc from a Nix store path #}
{# that might change with a Nix toolchain update. #}
{# --as-needed drops the ones they link but don't use, #}
{# such as libatomic for grpc_cpp_plugin on arm64. #}
{% set static_runtime_flags = ["-static-libstdc++", "-static-libgcc", "-Wl,--as-needed"] %}
tools.build:exelinkflags+={{ static_runtime_flags }}
tools.info.package_id:confs+=["tools.build:exelinkflags"]
{% endif %}
{% if os == "Linux" and context == "build" %}
{# b2 links itself with its own script, which ignores exelinkflags #}
{# and only takes CXXFLAGS when use_cxx_env is set (see [buildenv] below). #}
[options]
b2/*:use_cxx_env=True
{% endif %}
[buildenv]
{# gRPC emits thousands of compiler warnings that we cannot act on. #}
{# CMake picks up CXXFLAGS, and unlike tools.build:cxxflags, #}
{# this is not part of the package ID, so binaries stay shareable. #}
grpc/*:CXXFLAGS=-w
{% if os == "Macos" %} {% if os == "Macos" %}
[buildenv]
{# os.version adds -mmacosx-version-min to compiler command lines, #} {# os.version adds -mmacosx-version-min to compiler command lines, #}
{# but Boost.Context's b2 assembly (.S) rule ignores it, #} {# but Boost.Context's b2 assembly (.S) rule ignores it, #}
{# so those objects keep the host SDK version and still warn at link time. #} {# so those objects keep the host SDK version and still warn at link time. #}
@@ -81,7 +58,3 @@ grpc/*:CXXFLAGS=-w
{# Scoped to boost/* since it is the only gap. #} {# Scoped to boost/* since it is the only gap. #}
boost/*:MACOSX_DEPLOYMENT_TARGET={{ min_macos_version }} boost/*:MACOSX_DEPLOYMENT_TARGET={{ min_macos_version }}
{% endif %} {% endif %}
{% if os == "Linux" and context == "build" %}
b2/*:CXXFLAGS={{ static_runtime_flags | join(" ") }}
{% endif %}
-3
View File
@@ -5,9 +5,6 @@ include(default)
{% if not sanitizers %} {% if not sanitizers %}
{# Sanitizers not configured; no additional settings needed #} {# Sanitizers not configured; no additional settings needed #}
{% elif context == "build" %}
{# Build-context packages are tools we run, not code we test, #}
{# so don't instrument them #}
{% else %} {% else %}
{% if compiler == "msvc" %} {% if compiler == "msvc" %}
+3 -8
View File
@@ -40,7 +40,7 @@ class Xrpl(ConanFile):
"nudb/2.0.9", "nudb/2.0.9",
"openssl/3.6.3", "openssl/3.6.3",
"soci/4.0.3", "soci/4.0.3",
"xrpl-rpc-spec/0.1.23", "xrpl-rpc-spec/0.1.19",
"zlib/1.3.2", "zlib/1.3.2",
] ]
@@ -49,8 +49,7 @@ class Xrpl(ConanFile):
] ]
tool_requires = [ tool_requires = [
"grpc/<host_version>", "protobuf/6.33.5",
"protobuf/<host_version>",
] ]
default_options = { default_options = {
@@ -124,10 +123,6 @@ class Xrpl(ConanFile):
"xxhash/*:shared": False, "xxhash/*:shared": False,
} }
# default_options only reach the host context;
# give tool_requires (and their dependencies) the same dependency options.
default_build_options = {k: v for k, v in default_options.items() if "/" in k}
def set_version(self): def set_version(self):
self.version = self.version or DEV_VERSION self.version = self.version or DEV_VERSION
@@ -154,7 +149,7 @@ class Xrpl(ConanFile):
self.requires("xxhash/0.8.3", transitive_headers=True) self.requires("xxhash/0.8.3", transitive_headers=True)
exports_sources = ( exports_sources = (
"bin/nix/default-loader-path.sh", "bin/default-loader-path.sh",
"CMakeLists.txt", "CMakeLists.txt",
"cfg/*", "cfg/*",
"cmake/*", "cmake/*",
+6 -5
View File
@@ -80,12 +80,13 @@ function(add_xrpl_crate name)
# `cc` picks its runtime flag from `crt-static` alone, so it compiles a # `cc` picks its runtime flag from `crt-static` alone, so it compiles a
# crate's C++ with `-MT`; Debug needs `-MTd` (to match cmake/XrplCompiler.cmake). # crate's C++ with `-MT`; Debug needs `-MTd` (to match cmake/XrplCompiler.cmake).
if(is_msvc) if(is_msvc)
corrosion_set_env_vars(${ARG_CRATE} "$<$<CONFIG:Debug>:CXXFLAGS=-MTd>") corrosion_set_env_vars(
${ARG_CRATE}
"$<$<CONFIG:Debug>:CXXFLAGS=-MTd>"
)
endif() endif()
corrosion_add_cxxbridge( corrosion_add_cxxbridge(${name}_cxxbridge CRATE ${ARG_CRATE} FILES
${name}_cxxbridge ${ARG_FILES}
CRATE ${ARG_CRATE}
FILES ${ARG_FILES}
) )
# Generated cxxbridge headers don't exist at configure time; CMake 3.28+ # Generated cxxbridge headers don't exist at configure time; CMake 3.28+
# validates INTERFACE_SOURCES on consuming targets. Clear it to skip the # validates INTERFACE_SOURCES on consuming targets. Clear it to skip the
+10 -10
View File
@@ -57,9 +57,9 @@ dependencies = [
[[package]] [[package]]
name = "cxx" name = "cxx"
version = "1.0.205" version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8a02bfeba9074b2bbb39492c9b0908ec854f455a3cccdcde7a1de55e2315e40" checksum = "13f6de320895f42e6e081abb5c7983bedcf0b6d0ff9323de0d33f620c8ac1199"
dependencies = [ dependencies = [
"cc", "cc",
"cxx-build", "cxx-build",
@@ -72,9 +72,9 @@ dependencies = [
[[package]] [[package]]
name = "cxx-build" name = "cxx-build"
version = "1.0.205" version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc2ac76997619d2d888b58ad79488f1c835de41ca4dd3dd7082acf4ecb0a50f" checksum = "4fde53ca86b9704a943fef0f1e1d836239a6aedca5de3c65fa9f97ec0bd46d39"
dependencies = [ dependencies = [
"cc", "cc",
"codespan-reporting", "codespan-reporting",
@@ -87,9 +87,9 @@ dependencies = [
[[package]] [[package]]
name = "cxxbridge-cmd" name = "cxxbridge-cmd"
version = "1.0.205" version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a486ed16a3f2a053fe7f5b98db4c1a59846a23e8cb9e49f9d1bd48830d51a2" checksum = "07bae89236c811fd4d08ed3441759ac4ac98d752cbfd3de341315ba16ad20ec3"
dependencies = [ dependencies = [
"clap", "clap",
"codespan-reporting", "codespan-reporting",
@@ -101,15 +101,15 @@ dependencies = [
[[package]] [[package]]
name = "cxxbridge-flags" name = "cxxbridge-flags"
version = "1.0.205" version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c72569be94e2283764d334cd285980b747dbe221e27e315484eb6bcd93fa808a" checksum = "49045042e5fced01b80742aba5508de82aa4f13677ed3fa2b4cda709c40c5918"
[[package]] [[package]]
name = "cxxbridge-macro" name = "cxxbridge-macro"
version = "1.0.205" version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "423e795284a7f7b3f843c956a5322c4bc497b60c2dd1a6339da10313cb18d575" checksum = "b181252e2e3d3b5d183afbdc033a3958b445eb3e1a0ae65fc3d4f5259f5da6fd"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"proc-macro2", "proc-macro2",
+7 -9
View File
@@ -10,15 +10,14 @@ This document explains how to set one up.
support it — see [compiler support for C++23][cpp23-support]. support it — see [compiler support for C++23][cpp23-support].
The versions currently tested in CI are: The versions currently tested in CI are:
| Compiler | Version | | Compiler | Version |
| ----------- | ------------------------------- | | ----------- | ------------------ |
| GCC | `gccVersion` in [packages.nix] | | GCC | 15.2 |
| Clang | `llvmVersion` in [packages.nix] | | Clang | 22 |
| Apple Clang | 21 | | Apple Clang | 21 |
| MSVC | Visual Studio 2026 | | MSVC | Visual Studio 2026 |
LLVM tools (`clang-tidy` and `clang-format`) LLVM tools (`clang-tidy` and `clang-format`) are also pinned to version 22.
come from the same LLVM release as Clang.
### Older compilers ### Older compilers
@@ -157,4 +156,3 @@ version out of the box — run it via `run-clang-tidy`. No separate installation
is needed. is needed.
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23 [cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23
[packages.nix]: ../../nix/packages.nix
+9 -21
View File
@@ -183,36 +183,24 @@ at link or run time.
> configuration CI covers, and no dependency binaries are published for it. > configuration CI covers, and no dependency binaries are published for it.
This is checked rather than assumed. This is checked rather than assumed.
[`bin/nix/check-nix-store-refs.sh`](../../bin/nix/check-nix-store-refs.sh) takes one [`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) takes one file
file or directory and fails if a binary under it resolves a store path at run time. or directory and fails if a binary under it resolves a store path at run time.
CI runs it over the build output and the Conan cache, and again in the upload job CI runs it over the build output and the Conan cache, and again in the upload job
before anything is published. You can run it yourself: before anything is published. You can run it yourself:
```bash ```bash
bin/nix/check-nix-store-refs.sh build bin/check-nix-store-refs.sh build
bin/nix/check-nix-store-refs.sh ~/.conan2-nix bin/check-nix-store-refs.sh ~/.conan2-nix
``` ```
It works on Linux too, but asserts something narrower there: the toolchain always It works on Linux too, but asserts something narrower there: the toolchain always
writes the store into `PT_INTERP` and `RUNPATH`. That is fine for the pinned writes the store into `PT_INTERP` and `RUNPATH`, and CI builds inside an image
glibc, whose path does not move, but not for the GCC runtime, which moves with whose store is fixed for its lifetime, so that is fine. Only the binaries
every GCC update. So [`conan/profiles/default`](../../conan/profiles/default) [`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake) retargets to the
links build-context packages, whose executables run during the build, with system loader have to be clean, and those are what CI checks:
`-static-libstdc++ -static-libgcc -Wl,--as-needed`, and
[`conan/profiles/sanitizers`](../../conan/profiles/sanitizers) does not
instrument them. CI checks that they load nothing from the store but glibc, from
the graph `conan install --format=json` writes:
```bash ```bash
bin/nix/check-build-context-runtime.sh graph.json bin/check-nix-store-refs.sh build/xrpld
```
Only the binaries [`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake)
retargets to the system loader have to be fully clean, and those are what CI
checks:
```bash
bin/nix/check-nix-store-refs.sh build/xrpld
``` ```
### The libresolv stub ### The libresolv stub
+3 -3
View File
@@ -178,11 +178,11 @@ A binary stops starting after a `nix flake update`, or after
dyld[57271]: Library not loaded: /nix/store/…-libresolv-93/lib/libresolv.9.dylib dyld[57271]: Library not loaded: /nix/store/…-libresolv-93/lib/libresolv.9.dylib
``` ```
[`bin/nix/check-nix-store-refs.sh`](../../bin/nix/check-nix-store-refs.sh) finds the [`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) finds the same
same thing without having to run anything, and names the file: thing without having to run anything, and names the file:
``` ```
$ bin/nix/check-nix-store-refs.sh ~/.conan2-nix $ bin/check-nix-store-refs.sh ~/.conan2-nix
::error file=/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig::references the Nix store at run time ::error file=/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig::references the Nix store at run time
/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig /Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig
/nix/store/p4lp3xq4imd1qzqh08x8vcq2zfhi7rca-libresolv-93/lib/libresolv.9.dylib /nix/store/p4lp3xq4imd1qzqh08x8vcq2zfhi7rca-libresolv-93/lib/libresolv.9.dylib
+1 -1
View File
@@ -6,7 +6,7 @@ project(antithesis-sdk-cpp VERSION 0.4.4 LANGUAGES CXX)
add_library(antithesis-sdk-cpp INTERFACE antithesis_sdk.h) add_library(antithesis-sdk-cpp INTERFACE antithesis_sdk.h)
# Note, both sections below created by xrpld project # Note, both sections below created by xrpld project
target_include_directories(antithesis-sdk-cpp SYSTEM INTERFACE target_include_directories(antithesis-sdk-cpp INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
) )
Generated
+6 -6
View File
@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1791130267, "lastModified": 1781173989,
"narHash": "sha256-1sjwcQMcgAbmiip/VivBSiK8p2bTkQGOvCuO7vnwfx4=", "narHash": "sha256-fnzKKPvS+oieI/pTzotA5tkoM47EB1NpaBcgk4R97hE=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9013764fcc0ea99fa16cf7aa7decf8a5c3889dd2", "rev": "8c91a71d13451abc40eb9dae8910f972f979852f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -47,11 +47,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1791189933, "lastModified": 1784611586,
"narHash": "sha256-Y8eN7ki0Urx4Ojf4w1xSpWg8uk/3lJqK+E0Oth77rH0=", "narHash": "sha256-OfqgY+0hp/zseZB7uyH0U8kIDPS4scZZCyAurEplvG0=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "e60029353d0c48d216bc4b065168ccd4079c166f", "rev": "14f58845249f3552a89b07772626b8d3c632fa86",
"type": "github" "type": "github"
}, },
"original": { "original": {
+1 -1
View File
@@ -34,7 +34,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
// data // data
auto compressed = bf(outCapacity); auto compressed = bf(outCapacity);
auto const compressedSize = LZ4_compress_default( auto compressedSize = LZ4_compress_default(
reinterpret_cast<char const*>(in), reinterpret_cast<char const*>(in),
reinterpret_cast<char*>(compressed), reinterpret_cast<char*>(compressed),
inSize, inSize,
+30 -38
View File
@@ -20,14 +20,12 @@ SharedIntrusive<T>::SharedIntrusive(T* p, TAdoptTag) noexcept : ptr_{p}
template <class T> template <class T>
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive const& rhs) SharedIntrusive<T>::SharedIntrusive(SharedIntrusive const& rhs)
: ptr_{ : ptr_{[&] {
[&] { auto p = rhs.unsafeGetRawPtr();
auto p = rhs.unsafeGetRawPtr(); if (p)
if (p) p->addStrongRef();
p->addStrongRef(); return p;
return p; }()}
}(),
}
{ {
} }
@@ -35,14 +33,12 @@ template <class T>
template <class TT> template <class TT>
requires std::convertible_to<TT*, T*> requires std::convertible_to<TT*, T*>
SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT> const& rhs) SharedIntrusive<T>::SharedIntrusive(SharedIntrusive<TT> const& rhs)
: ptr_{ : ptr_{[&] {
[&] { auto p = rhs.unsafeGetRawPtr();
auto p = rhs.unsafeGetRawPtr(); if (p)
if (p) p->addStrongRef();
p->addStrongRef(); return p;
return p; }()}
}(),
}
{ {
} }
@@ -144,14 +140,12 @@ SharedIntrusive<T>::~SharedIntrusive()
template <class T> template <class T>
template <class TT> template <class TT>
SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs) SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
: ptr_{ : ptr_{[&] {
[&] { auto p = static_cast<T*>(rhs.unsafeGetRawPtr());
auto p = static_cast<T*>(rhs.unsafeGetRawPtr()); if (p)
if (p) p->addStrongRef();
p->addStrongRef(); return p;
return p; }()}
}(),
}
{ {
} }
@@ -165,14 +159,12 @@ SharedIntrusive<T>::SharedIntrusive(StaticCastTagSharedIntrusive, SharedIntrusiv
template <class T> template <class T>
template <class TT> template <class TT>
SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs) SharedIntrusive<T>::SharedIntrusive(DynamicCastTagSharedIntrusive, SharedIntrusive<TT> const& rhs)
: ptr_{ : ptr_{[&] {
[&] { auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr());
auto p = dynamic_cast<T*>(rhs.unsafeGetRawPtr()); if (p)
if (p) p->addStrongRef();
p->addStrongRef(); return p;
return p; }()}
}(),
}
{ {
} }
@@ -268,7 +260,7 @@ SharedIntrusive<T>::unsafeReleaseAndStore(T* next)
return; return;
using enum ReleaseStrongRefAction; using enum ReleaseStrongRefAction;
auto const action = prev->releaseStrongRef(); auto action = prev->releaseStrongRef();
switch (action) switch (action)
{ {
case NoOp: case NoOp:
@@ -369,7 +361,7 @@ WeakIntrusive<T>::unsafeReleaseNoStore()
return; return;
using enum ReleaseWeakRefAction; using enum ReleaseWeakRefAction;
auto const action = ptr_->releaseWeakRef(); auto action = ptr_->releaseWeakRef();
switch (action) switch (action)
{ {
case NoOp: case NoOp:
@@ -588,7 +580,7 @@ SharedWeakUnion<T>::convertToStrong()
auto p = unsafeGetRawPtr(); auto p = unsafeGetRawPtr();
if (p && p->checkoutStrongRefFromWeak()) if (p && p->checkoutStrongRefFromWeak())
{ {
[[maybe_unused]] auto const action = p->releaseWeakRef(); [[maybe_unused]] auto action = p->releaseWeakRef();
XRPL_ASSERT( XRPL_ASSERT(
(action == ReleaseWeakRefAction::NoOp), (action == ReleaseWeakRefAction::NoOp),
"xrpl::SharedWeakUnion::convertToStrong : " "xrpl::SharedWeakUnion::convertToStrong : "
@@ -611,7 +603,7 @@ SharedWeakUnion<T>::convertToWeak()
return false; return false;
using enum ReleaseStrongRefAction; using enum ReleaseStrongRefAction;
auto const action = p->addWeakReleaseStrongRef(); auto action = p->addWeakReleaseStrongRef();
switch (action) switch (action)
{ {
case NoOp: case NoOp:
@@ -678,7 +670,7 @@ SharedWeakUnion<T>::unsafeReleaseNoStore()
if (isStrong()) if (isStrong())
{ {
using enum ReleaseStrongRefAction; using enum ReleaseStrongRefAction;
auto const strongAction = p->releaseStrongRef(); auto strongAction = p->releaseStrongRef();
switch (strongAction) switch (strongAction)
{ {
case NoOp: case NoOp:
@@ -696,7 +688,7 @@ SharedWeakUnion<T>::unsafeReleaseNoStore()
else else
{ {
using enum ReleaseWeakRefAction; using enum ReleaseWeakRefAction;
auto const weakAction = p->releaseWeakRef(); auto weakAction = p->releaseWeakRef();
switch (weakAction) switch (weakAction)
{ {
case NoOp: case NoOp:
+2 -2
View File
@@ -406,10 +406,10 @@ IntrusiveRefCounts::useCount() const noexcept
inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
{ {
#ifndef NDEBUG #ifndef NDEBUG
auto const v = refCounts_.load(std::memory_order_acquire); auto v = refCounts_.load(std::memory_order_acquire);
XRPL_ASSERT( XRPL_ASSERT(
(!(v & kValueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero"); (!(v & kValueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
auto const t = v & kTagMask; auto t = v & kTagMask;
XRPL_ASSERT((!t || t == kTagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag"); XRPL_ASSERT((!t || t == kTagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
#endif #endif
} }
-147
View File
@@ -3,156 +3,9 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
namespace xrpl { namespace xrpl {
/**
* Add two signed 64-bit integers, returning std::nullopt when the exact
* mathematical sum is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedAdd(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if ((b > 0 && a > L::max() - b) || (b < 0 && a < L::min() - b))
return std::nullopt;
return a + b;
}
/**
* Subtract two signed 64-bit integers, returning std::nullopt when the exact
* mathematical difference is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedSub(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if ((b > 0 && a < L::min() + b) || (b < 0 && a > L::max() + b))
return std::nullopt;
return a - b;
}
/**
* Multiply two signed 64-bit integers, returning std::nullopt when the exact
* mathematical product is not representable in std::int64_t.
*/
[[nodiscard]] constexpr std::optional<std::int64_t>
checkedMul(std::int64_t a, std::int64_t b) noexcept
{
using L = std::numeric_limits<std::int64_t>;
if (a == 0 || b == 0)
return 0;
if (a > 0)
{
if (b > 0 ? a > L::max() / b : b < L::min() / a)
return std::nullopt;
}
else if (b > 0 ? a < L::min() / b : b < L::max() / a)
{
return std::nullopt;
}
return a * b;
}
static_assert(checkedAdd(0, 0) == 0);
static_assert(checkedAdd(1, -1) == 0);
static_assert(checkedAdd(-5, 2) == -3);
static_assert(!checkedAdd(std::numeric_limits<std::int64_t>::max(), 1).has_value());
static_assert(!checkedAdd(std::numeric_limits<std::int64_t>::min(), -1).has_value());
static_assert(
checkedAdd(std::numeric_limits<std::int64_t>::max() - 1, 1) ==
std::numeric_limits<std::int64_t>::max());
static_assert(
checkedAdd(
std::numeric_limits<std::int64_t>::min(),
std::numeric_limits<std::int64_t>::max()) == -1);
static_assert(
checkedAdd(
std::numeric_limits<std::int64_t>::max(),
std::numeric_limits<std::int64_t>::min()) == -1);
static_assert(
!checkedAdd(std::numeric_limits<std::int64_t>::max(), std::numeric_limits<std::int64_t>::max())
.has_value());
static_assert(
!checkedAdd(std::numeric_limits<std::int64_t>::min(), std::numeric_limits<std::int64_t>::min())
.has_value());
static_assert(checkedSub(0, 0) == 0);
static_assert(checkedSub(1, 1) == 0);
static_assert(checkedSub(-5, 2) == -7);
static_assert(checkedSub(-5, -2) == -3);
static_assert(!checkedSub(std::numeric_limits<std::int64_t>::min(), 1).has_value());
static_assert(!checkedSub(std::numeric_limits<std::int64_t>::max(), -1).has_value());
static_assert(
checkedSub(std::numeric_limits<std::int64_t>::min() + 1, 1) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
checkedSub(-1, std::numeric_limits<std::int64_t>::max()) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
!checkedSub(std::numeric_limits<std::int64_t>::max(), std::numeric_limits<std::int64_t>::min())
.has_value());
static_assert(
!checkedSub(std::numeric_limits<std::int64_t>::min(), std::numeric_limits<std::int64_t>::max())
.has_value());
static_assert(checkedMul(0, std::numeric_limits<std::int64_t>::min()) == 0);
static_assert(checkedMul(std::numeric_limits<std::int64_t>::min(), 0) == 0);
static_assert(checkedMul(-1, -1) == 1);
// a > 0, b > 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max(), 1) ==
std::numeric_limits<std::int64_t>::max());
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max() / 2, 2) ==
std::numeric_limits<std::int64_t>::max() - 1);
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 1, 2).has_value());
static_assert(!checkedMul(2, (std::numeric_limits<std::int64_t>::max() / 2) + 1).has_value());
// a > 0, b < 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::max(), -1) ==
-std::numeric_limits<std::int64_t>::max());
static_assert(
checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 1, -2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::max() / 2) + 2, -2).has_value());
static_assert(
checkedMul(1, std::numeric_limits<std::int64_t>::min()) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
checkedMul(2, std::numeric_limits<std::int64_t>::min() / 2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul(2, (std::numeric_limits<std::int64_t>::min() / 2) - 1).has_value());
// a < 0, b > 0
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::min(), 1) ==
std::numeric_limits<std::int64_t>::min());
static_assert(
checkedMul(std::numeric_limits<std::int64_t>::min() / 2, 2) ==
std::numeric_limits<std::int64_t>::min());
static_assert(!checkedMul((std::numeric_limits<std::int64_t>::min() / 2) - 1, 2).has_value());
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min(), 2).has_value());
// a < 0, b < 0
static_assert(
checkedMul(-(std::numeric_limits<std::int64_t>::max() / 2), -2) ==
std::numeric_limits<std::int64_t>::max() - 1);
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min() / 2, -2).has_value());
static_assert(
checkedMul(-1, -std::numeric_limits<std::int64_t>::max()) ==
std::numeric_limits<std::int64_t>::max());
static_assert(!checkedMul(std::numeric_limits<std::int64_t>::min(), -1).has_value());
static_assert(!checkedMul(-1, std::numeric_limits<std::int64_t>::min()).has_value());
/** /**
* Calculate one number divided by another number in percentage. * Calculate one number divided by another number in percentage.
* The result is rounded up to the next integer, and capped in the range [0,100] * The result is rounded up to the next integer, and capped in the range [0,100]
+1 -1
View File
@@ -340,7 +340,7 @@ public:
for (auto const& c : cfg) for (auto const& c : cfg)
{ {
auto const& a = allocators_.emplace_back(c.extra_, c.alloc_, c.align_); auto& a = allocators_.emplace_back(c.extra_, c.alloc_, c.align_);
if (a.size() > maxSize_) if (a.size() > maxSize_)
maxSize_ = a.size(); maxSize_ = a.size();
+1 -1
View File
@@ -36,7 +36,7 @@ template <typename T>
concept SomeChar = std::same_as<std::remove_cvref_t<T>, int8_t> || concept SomeChar = std::same_as<std::remove_cvref_t<T>, int8_t> ||
std::same_as<std::remove_cvref_t<T>, char> || std::same_as<std::remove_cvref_t<T>, uint8_t>; std::same_as<std::remove_cvref_t<T>, char> || std::same_as<std::remove_cvref_t<T>, uint8_t>;
inline constexpr std::array<std::optional<int>, 256> const kDigitLookupTable = [] { inline constexpr std::array<std::optional<int>, 256> const kDigitLookupTable = []() {
std::array<std::optional<int>, 256> t{}; std::array<std::optional<int>, 256> t{};
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
+3 -34
View File
@@ -153,24 +153,6 @@ private:
Policy policy, Policy policy,
Callback&& replaceCallback = nullptr); Callback&& replaceCallback = nullptr);
/**
* canonicalizeImpl variant for callers that already hold `mutex_`.
*
* The unnamed `scoped_lock<MutexType> const&` parameter is proof of
* ownership; this overload does not acquire the lock. Use it from other
* methods (e.g. fetchAndModify) that need to compose canonicalize with
* additional work under a single critical section, without relying on
* recursive-mutex re-entry.
*/
template <class Policy, class Callback = std::nullptr_t>
bool
canonicalizeImpl(
std::scoped_lock<MutexType> const&,
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback = nullptr);
public: public:
/** /**
* Replace aliased objects with originals. * Replace aliased objects with originals.
@@ -257,6 +239,9 @@ public:
bool bool
retrieve(key_type const& key, T& data); retrieve(key_type const& key, T& data);
MutexType&
peekMutex();
std::vector<key_type> std::vector<key_type>
getKeys() const; getKeys() const;
@@ -278,22 +263,6 @@ public:
fetch(key_type const& digest, Handler const& h); fetch(key_type const& digest, Handler const& h);
// End CachedSLEs functions. // End CachedSLEs functions.
/**
* Fetch or create an entry and execute a callback while holding the lock.
*
* The entry for the given key is fetched from the cache or created if it
* doesn't exist. The callback is then invoked with a reference to the
* entry while the cache mutex is still held, allowing safe modification
* of the cached object.
*
* @param key The key to fetch or create
* @param callback Function to call with the entry under lock.
* Signature: void(T&)
*/
template <class Callback>
void
fetchAndModify(key_type const& key, Callback&& callback);
private: private:
SharedPointerType SharedPointerType
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l); initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l);
+27 -76
View File
@@ -4,7 +4,6 @@
#include <xrpl/basics/Log.h> // IWYU pragma: keep #include <xrpl/basics/Log.h> // IWYU pragma: keep
#include <xrpl/basics/TaggedCache.h> #include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/scope.h> #include <xrpl/basics/scope.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <algorithm> #include <algorithm>
@@ -301,7 +300,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// Remove from cache, if !valid, remove from map too. Returns true if removed from cache // Remove from cache, if !valid, remove from map too. Returns true if removed from cache
std::scoped_lock const lock(mutex_); std::scoped_lock const lock(mutex_);
auto const cit = cache_.find(key); auto cit = cache_.find(key);
if (cit == cache_.end()) if (cit == cache_.end())
return false; return false;
@@ -336,29 +335,6 @@ template <class Policy, class Callback>
inline bool inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl( canonicalizeImpl(
key_type const& key,
CanonicalizeClientPointerType<Policy> data,
Policy policy,
Callback&& replaceCallback)
{
std::scoped_lock<MutexType> const lock(mutex_);
return canonicalizeImpl(lock, key, data, policy, std::forward<Callback>(replaceCallback));
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Policy, class Callback>
inline bool
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
canonicalizeImpl(
std::scoped_lock<MutexType> const&,
key_type const& key, key_type const& key,
CanonicalizeClientPointerType<Policy> data, CanonicalizeClientPointerType<Policy> data,
[[maybe_unused]] Policy policy, [[maybe_unused]] Policy policy,
@@ -378,7 +354,9 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
// passing a const argument is a compile error. // passing a const argument is a compile error.
constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>; constexpr bool replaceCached = std::is_same_v<Policy, detail::ReplaceCached>;
auto const cit = cache_.find(key); std::scoped_lock const lock(mutex_);
auto cit = cache_.find(key);
if (cit == cache_.end()) if (cit == cache_.end())
{ {
@@ -393,7 +371,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
Entry& entry = cit->second; Entry& entry = cit->second;
entry.touch(clock_.now()); entry.touch(clock_.now());
auto const shouldReplaceCached = [&] { auto shouldReplaceCached = [&] {
if constexpr (replaceCached) if constexpr (replaceCached)
{ {
return true; return true;
@@ -422,7 +400,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return true; return true;
} }
auto const cachedData = entry.lock(); auto cachedData = entry.lock();
if (cachedData) if (cachedData)
{ {
@@ -585,7 +563,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
retrieve(key_type const& key, T& data) retrieve(key_type const& key, T& data)
{ {
// retrieve the value of the stored data // retrieve the value of the stored data
auto const entry = fetch(key); auto entry = fetch(key);
if (!entry) if (!entry)
return false; return false;
@@ -594,6 +572,22 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return true; return true;
} }
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
inline auto
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
peekMutex() -> MutexType&
{
return mutex_;
}
template < template <
class Key, class Key,
class T, class T,
@@ -693,7 +687,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return ret; return ret;
} }
auto const sle = h(); auto sle = h();
if (!sle) if (!sle)
return {}; return {};
@@ -706,49 +700,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
} }
// End CachedSLEs functions. // End CachedSLEs functions.
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
template <class Callback>
inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
fetchAndModify(key_type const& key, Callback&& callback)
{
static_assert(
!IsKeyCache, "fetchAndModify is only supported for value caches, not key-only caches");
static_assert(
std::is_same_v<std::shared_ptr<T>, SharedPointerType> ||
std::is_same_v<intr_ptr::SharedPtr<T>, SharedPointerType>,
"fetchAndModify requires std::shared_ptr<T> or intr_ptr::SharedPtr<T>");
std::scoped_lock<MutexType> const lock(mutex_);
// Same pointer-type dispatch as insert(): the placeholder must have exactly
// SharedPointerType so canonicalizeImpl can write the cached pointer back.
SharedPointerType entry = [] {
if constexpr (std::is_same_v<std::shared_ptr<T>, SharedPointerType>)
{
return std::make_shared<T>();
}
else
{
return intr_ptr::makeShared<T>();
}
}();
canonicalizeImpl(lock, key, entry, detail::ReplaceClient{});
ALWAYS(
entry != nullptr, "xrpl::TaggedCache::fetchAndModify : entry present after canonicalize");
callback(*entry);
}
template < template <
class Key, class Key,
class T, class T,
@@ -762,7 +713,7 @@ inline SharedPointerType
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>:: TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l) initialFetch(key_type const& key, std::scoped_lock<MutexType> const& l)
{ {
auto const cit = cache_.find(key); auto cit = cache_.find(key);
if (cit == cache_.end()) if (cit == cache_.end())
return {}; return {};
@@ -832,7 +783,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&) std::scoped_lock<std::recursive_mutex> const&)
{ {
return std::thread([&, this] { return std::thread([&, this]() {
int cacheRemovals = 0; int cacheRemovals = 0;
int mapRemovals = 0; int mapRemovals = 0;
@@ -912,7 +863,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
std::atomic<int>& allRemovals, std::atomic<int>& allRemovals,
std::scoped_lock<std::recursive_mutex> const&) std::scoped_lock<std::recursive_mutex> const&)
{ {
return std::thread([&, this] { return std::thread([&, this]() {
// NOLINTBEGIN https://github.com/XRPLF/rippled/issues/7056 // NOLINTBEGIN https://github.com/XRPLF/rippled/issues/7056
int cacheRemovals = 0; int cacheRemovals = 0;
int mapRemovals = 0; int mapRemovals = 0;
+2 -3
View File
@@ -195,8 +195,7 @@ private:
{ {
// Local lambda that converts a single hex char to four bits and // Local lambda that converts a single hex char to four bits and
// ORs those bits into a uint32_t. // ORs those bits into a uint32_t.
auto const hexCharToUInt = auto hexCharToUInt = [](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult {
[](char c, std::uint32_t shift, std::uint32_t& accum) -> ParseResult {
std::uint32_t nibble = 0xFFu; std::uint32_t nibble = 0xFFu;
if (c < '0' || c > 'f') if (c < '0' || c > 'f')
return ParseResult::BadChar; return ParseResult::BadChar;
@@ -454,7 +453,7 @@ public:
{ {
for (int i = kWidth - 1; i >= 0; --i) for (int i = kWidth - 1; i >= 0; --i)
{ {
auto const prev = data_[i]; auto prev = data_[i];
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1); data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1);
if (prev != 0) if (prev != 0)
@@ -17,7 +17,7 @@
namespace xrpl { namespace xrpl {
template <typename Key> template <typename Key>
std::size_t static std::size_t
extract(Key const& key) extract(Key const& key)
{ {
return key; return key;
@@ -365,7 +365,7 @@ public:
size() const size() const
{ {
std::size_t ret = 0; std::size_t ret = 0;
for (auto const& p : map_) for (auto& p : map_)
ret += p.size(); ret += p.size();
return ret; return ret;
} }
@@ -1604,7 +1604,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos) beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
requires(!IsBoostReverseIterator<Iterator>::value) requires(!IsBoostReverseIterator<Iterator>::value)
{ {
unlinkAndDeleteElement(&*(pos++).iterator()); unlinkAndDeleteElement(&*((pos++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator()); return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator());
} }
@@ -1617,7 +1617,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
requires(!IsBoostReverseIterator<Iterator>::value) requires(!IsBoostReverseIterator<Iterator>::value)
{ {
for (; first != last;) for (; first != last;)
unlinkAndDeleteElement(&*(first++).iterator()); unlinkAndDeleteElement(&*((first++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(first.iterator()); return beast::detail::AgedContainerIterator<false, Iterator>(first.iterator());
} }
@@ -2404,7 +2404,7 @@ beast::detail::AgedContainerIterator<false, Iterator>
AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::erase( AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::erase(
beast::detail::AgedContainerIterator<IsConst, Iterator> pos) beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
{ {
unlinkAndDeleteElement(&*(pos++).iterator()); unlinkAndDeleteElement(&*((pos++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator()); return beast::detail::AgedContainerIterator<false, Iterator>(pos.iterator());
} }
@@ -2424,7 +2424,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
beast::detail::AgedContainerIterator<IsConst, Iterator> last) beast::detail::AgedContainerIterator<IsConst, Iterator> last)
{ {
for (; first != last;) for (; first != last;)
unlinkAndDeleteElement(&*(first++).iterator()); unlinkAndDeleteElement(&*((first++).iterator()));
return beast::detail::AgedContainerIterator<false, Iterator>(first.iterator()); return beast::detail::AgedContainerIterator<false, Iterator>(first.iterator());
} }
@@ -2536,7 +2536,7 @@ AgedUnorderedContainer<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>
return false; return false;
for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); iter != last; ++iter) for (auto iter(cbegin()), last(cend()), otherLast(other.cend()); iter != last; ++iter)
{ {
auto const otherIter(other.find(extract(*iter))); auto otherIter(other.find(extract(*iter)));
if (otherIter == otherLast) if (otherIter == otherLast)
return false; return false;
} }
+1 -1
View File
@@ -68,7 +68,7 @@ struct LexicalCast<Out, std::string_view>
if (first != last && *first == '+') if (first != last && *first == '+')
++first; ++first;
auto const ret = std::from_chars(first, last, out); auto ret = std::from_chars(first, last, out);
return ret.ec == std::errc() && ret.ptr == last; return ret.ec == std::errc() && ret.ptr == last;
} }
+1 -1
View File
@@ -390,7 +390,7 @@ void
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
requires(IsContiguouslyHashable<Key, Hasher>::value) requires(IsContiguouslyHashable<Key, Hasher>::value)
{ {
h(&v.begin(), v.size() * sizeof(Key)); h(&(v.begin()), v.size() * sizeof(Key));
} }
// tuple // tuple
+1 -1
View File
@@ -8,7 +8,7 @@ namespace beast::insight {
class HookImpl : public std::enable_shared_from_this<HookImpl> class HookImpl : public std::enable_shared_from_this<HookImpl>
{ {
public: public:
using HandlerType = std::function<void()>; using HandlerType = std::function<void(void)>;
virtual ~HookImpl() = 0; virtual ~HookImpl() = 0;
}; };
+2 -2
View File
@@ -61,7 +61,7 @@ isMulticast(Address const& addr)
inline bool inline bool
isPrivate(Address const& addr) isPrivate(Address const& addr)
{ {
return addr.is_v4() ? isPrivate(addr.to_v4()) : isPrivate(addr.to_v6()); return (addr.is_v4()) ? isPrivate(addr.to_v4()) : isPrivate(addr.to_v6());
} }
/** /**
@@ -70,7 +70,7 @@ isPrivate(Address const& addr)
inline bool inline bool
isPublic(Address const& addr) isPublic(Address const& addr)
{ {
return addr.is_v4() ? isPublic(addr.to_v4()) : isPublic(addr.to_v6()); return (addr.is_v4()) ? isPublic(addr.to_v4()) : isPublic(addr.to_v6());
} }
} // namespace ip } // namespace ip
+1 -1
View File
@@ -83,7 +83,7 @@ trimRight(String const& s)
{ {
using std::begin; using std::begin;
using std::end; using std::end;
auto const first(begin(s)); auto first(begin(s));
auto last(end(s)); auto last(end(s));
last = trimRight(first, last); last = trimRight(first, last);
return {first, last}; return {first, last};
+1 -1
View File
@@ -34,7 +34,7 @@ typeName()
name += " volatile"; name += " volatile";
if (std::is_lvalue_reference_v<T>) if (std::is_lvalue_reference_v<T>)
{ {
name += '&'; name += "&";
} }
else if (std::is_rvalue_reference_v<T>) else if (std::is_rvalue_reference_v<T>)
{ {
+1 -1
View File
@@ -32,7 +32,7 @@ public:
Module, Module,
// Match nothing (used internally) // Match nothing (used internally)
None, None
}; };
private: private:
+1 -1
View File
@@ -20,7 +20,7 @@ namespace beast::unit_test {
namespace detail { namespace detail {
template <class String> template <class String>
std::string static std::string
makeReason(String const& reason, char const* file, int line) makeReason(String const& reason, char const* file, int line)
{ {
std::string s(reason); std::string s(reason);
+3 -3
View File
@@ -47,8 +47,8 @@ public:
template <class F, class... Args> template <class F, class... Args>
explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s) explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s)
{ {
std::function<void()> b = [f = std::forward<F>(f), std::function<void(void)> b = [f = std::forward<F>(f),
... args = std::forward<Args>(args)] mutable { ... args = std::forward<Args>(args)]() mutable {
std::invoke(f, args...); std::invoke(f, args...);
}; };
t_ = std::thread(&Thread::run, this, std::move(b)); t_ = std::thread(&Thread::run, this, std::move(b));
@@ -94,7 +94,7 @@ public:
private: private:
void void
run(std::function<void()> f) run(std::function<void(void)> f)
{ {
try try
{ {
+1 -1
View File
@@ -24,7 +24,7 @@ enum class Severity : std::uint8_t {
Fatal = 5, Fatal = 5,
Disabled = 6, Disabled = 6,
None = Disabled, None = Disabled
}; };
/** /**
+1 -1
View File
@@ -18,7 +18,7 @@ enum class Type : std::uint8_t {
PrefixSha256 = 1, PrefixSha256 = 1,
ThresholdSha256 = 2, ThresholdSha256 = 2,
RsaSha256 = 3, RsaSha256 = 3,
Ed25519Sha256 = 4, Ed25519Sha256 = 4
}; };
class Condition class Condition
@@ -49,7 +49,7 @@ public:
using namespace der; using namespace der;
auto const p = parsePreamble(s, ec); auto p = parsePreamble(s, ec);
if (ec) if (ec)
return nullptr; return nullptr;
+1 -1
View File
@@ -21,7 +21,7 @@ enum class Error {
UnexpectedTag, UnexpectedTag,
LongTag, LongTag,
LargeSize, LargeSize,
PreimageTooLong, PreimageTooLong
}; };
std::error_code std::error_code
+1 -1
View File
@@ -396,7 +396,7 @@ inline bool
getIfExists<bool>(Section const& section, std::string const& name, bool& v) getIfExists<bool>(Section const& section, std::string const& name, bool& v)
{ {
int intVal = 0; int intVal = 0;
auto const stat = getIfExists(section, name, intVal); auto stat = getIfExists(section, name, intVal);
if (stat) if (stat)
v = bool(intVal); v = bool(intVal);
return stat; return stat;
+2 -2
View File
@@ -93,14 +93,14 @@ public:
void void
check(std::vector<TxID> accepted, Predicate&& pred) check(std::vector<TxID> accepted, Predicate&& pred)
{ {
auto const acceptTxid = accepted.begin(); auto acceptTxid = accepted.begin();
auto const ae = accepted.end(); auto const ae = accepted.end();
std::sort(acceptTxid, ae); std::sort(acceptTxid, ae);
// We want to remove all tracking entries for transactions that were // We want to remove all tracking entries for transactions that were
// accepted as well as those which match the predicate. // accepted as well as those which match the predicate.
auto const i = removeIfIntersectOrMatch( auto i = removeIfIntersectOrMatch(
tracker_.begin(), tracker_.begin(),
tracker_.end(), tracker_.end(),
accepted.begin(), accepted.begin(),
+9 -10
View File
@@ -779,7 +779,7 @@ Consensus<Adaptor>::peerProposalInternal(
{ {
// update current position // update current position
auto const peerPosIt = currPeerPositions_.find(peerID); auto peerPosIt = currPeerPositions_.find(peerID);
if (peerPosIt != currPeerPositions_.end()) if (peerPosIt != currPeerPositions_.end())
{ {
@@ -1110,7 +1110,7 @@ Consensus<Adaptor>::checkLedger(std::unique_ptr<std::stringstream> const& clog)
{ {
CLOG(clog) << "checkLedger. "; CLOG(clog) << "checkLedger. ";
auto const netLgr = adaptor_.getPrevLedger(prevLedgerID_, previousLedger_, mode_.get()); auto netLgr = adaptor_.getPrevLedger(prevLedgerID_, previousLedger_, mode_.get());
CLOG(clog) << "network ledgerid " << netLgr << ", " CLOG(clog) << "network ledgerid " << netLgr << ", "
<< "previous ledger " << prevLedgerID_ << ". "; << "previous ledger " << prevLedgerID_ << ". ";
@@ -1159,8 +1159,8 @@ Consensus<Adaptor>::phaseOpen(std::unique_ptr<std::stringstream> const& clog)
// it is shortly before ledger close time // it is shortly before ledger close time
bool const anyTransactions = adaptor_.hasOpenTransactions(); bool const anyTransactions = adaptor_.hasOpenTransactions();
auto const proposersClosed = currPeerPositions_.size(); auto proposersClosed = currPeerPositions_.size();
auto const proposersValidated = adaptor_.proposersValidated(prevLedgerID_); auto proposersValidated = adaptor_.proposersValidated(prevLedgerID_);
openTime_.tick(clock_.now()); openTime_.tick(clock_.now());
@@ -1669,7 +1669,7 @@ Consensus<Adaptor>::haveConsensus(std::unique_ptr<std::stringstream> const& clog
// CHECKME: should possibly count unacquired TX sets as disagreeing // CHECKME: should possibly count unacquired TX sets as disagreeing
int agree = 0, disagree = 0; int agree = 0, disagree = 0;
auto const ourPosition = result_->position.position(); auto ourPosition = result_->position.position();
// Count number of agreements/disagreements with our position // Count number of agreements/disagreements with our position
for (auto const& [nodeId, peerPos] : currPeerPositions_) for (auto const& [nodeId, peerPos] : currPeerPositions_)
@@ -1686,7 +1686,7 @@ Consensus<Adaptor>::haveConsensus(std::unique_ptr<std::stringstream> const& clog
++disagree; ++disagree;
} }
} }
auto const currentFinished = adaptor_.proposersFinished(previousLedger_, prevLedgerID_); auto currentFinished = adaptor_.proposersFinished(previousLedger_, prevLedgerID_);
JLOG(j_.debug()) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree; JLOG(j_.debug()) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
@@ -1812,7 +1812,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
<< ". "; << ". ";
JLOG(j_.debug()) << "createDisputes " << result_->txns.id() << " to " << o.id(); JLOG(j_.debug()) << "createDisputes " << result_->txns.id() << " to " << o.id();
auto const differences = result_->txns.compare(o); auto differences = result_->txns.compare(o);
int dc = 0; int dc = 0;
@@ -1826,7 +1826,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
"xrpl::Consensus::createDisputes : has disputed transactions"); "xrpl::Consensus::createDisputes : has disputed transactions");
TxT const tx = inThisSet ? result_->txns.find(txId) : o.find(txId); TxT const tx = inThisSet ? result_->txns.find(txId) : o.find(txId);
auto const txID = tx.id(); auto txID = tx.id();
if (result_->disputes.find(txID) != result_->disputes.end()) if (result_->disputes.find(txID) != result_->disputes.end())
continue; continue;
@@ -1837,8 +1837,7 @@ Consensus<Adaptor>::createDisputes(TxSetT const& o, std::unique_ptr<std::strings
tx, tx,
result_->txns.exists(txID), result_->txns.exists(txID),
std::max(prevProposers_, currPeerPositions_.size()), std::max(prevProposers_, currPeerPositions_.size()),
j_, j_};
};
// Update all of the available peer's votes on the disputed transaction // Update all of the available peer's votes on the disputed transaction
for (auto const& [nodeId, peerPos] : currPeerPositions_) for (auto const& [nodeId, peerPos] : currPeerPositions_)
+8 -16
View File
@@ -145,26 +145,18 @@ struct ConsensusParms
std::map<AvalancheState, AvalancheCutoff> const avalancheCutoffs{ std::map<AvalancheState, AvalancheCutoff> const avalancheCutoffs{
// {state, {time, percent, nextState}}, // {state, {time, percent, nextState}},
// Initial state: 50% of nodes must vote yes // Initial state: 50% of nodes must vote yes
{ {AvalancheState::Init,
AvalancheState::Init, {.consensusTime = 0, .consensusPct = 50, .next = AvalancheState::Mid}},
{.consensusTime = 0, .consensusPct = 50, .next = AvalancheState::Mid},
},
// mid-consensus starts after 50% of the previous round time, and // mid-consensus starts after 50% of the previous round time, and
// requires 65% yes // requires 65% yes
{ {AvalancheState::Mid,
AvalancheState::Mid, {.consensusTime = 50, .consensusPct = 65, .next = AvalancheState::Late}},
{.consensusTime = 50, .consensusPct = 65, .next = AvalancheState::Late},
},
// late consensus starts after 85% time, and requires 70% yes // late consensus starts after 85% time, and requires 70% yes
{ {AvalancheState::Late,
AvalancheState::Late, {.consensusTime = 85, .consensusPct = 70, .next = AvalancheState::Stuck}},
{.consensusTime = 85, .consensusPct = 70, .next = AvalancheState::Stuck},
},
// we're stuck after 2x time, requires 95% yes votes // we're stuck after 2x time, requires 95% yes votes
{ {AvalancheState::Stuck,
AvalancheState::Stuck, {.consensusTime = 200, .consensusPct = 95, .next = AvalancheState::Stuck}},
{.consensusTime = 200, .consensusPct = 95, .next = AvalancheState::Stuck},
},
}; };
/** /**
+3 -3
View File
@@ -59,7 +59,7 @@ enum class ConsensusMode {
* if we entered the round observing, but is used to indicate we did * if we entered the round observing, but is used to indicate we did
* have the wrongLedger at some point. * have the wrongLedger at some point.
*/ */
SwitchedLedger, SwitchedLedger
}; };
inline std::string inline std::string
@@ -222,7 +222,7 @@ medianCloseOffset(ConsensusCloseTimes const& times)
// Accumulate weight in time order; the first bin to reach halfWeight is // Accumulate weight in time order; the first bin to reach halfWeight is
// the (lower) weighted median. Returns true once that bin is found. // the (lower) weighted median. Returns true once that bin is found.
auto const step = [&](time_point t, std::int64_t w) { auto step = [&](time_point t, std::int64_t w) {
XRPL_ASSERT(tally < halfWeight, "xrpl::medianCloseOffset::step : median not yet found"); XRPL_ASSERT(tally < halfWeight, "xrpl::medianCloseOffset::step : median not yet found");
tally += w; tally += w;
if (tally >= halfWeight) if (tally >= halfWeight)
@@ -267,7 +267,7 @@ enum class ConsensusState {
No, ///< We do not have consensus No, ///< We do not have consensus
MovedOn, ///< The network has consensus without us MovedOn, ///< The network has consensus without us
Expired, ///< Consensus time limit has hard-expired Expired, ///< Consensus time limit has hard-expired
Yes, ///< We have consensus along with the network Yes ///< We have consensus along with the network
}; };
/** /**
+1 -1
View File
@@ -266,7 +266,7 @@ template <class Tx, class NodeId>
void void
DisputedTx<Tx, NodeId>::unVote(NodeId const& peer) DisputedTx<Tx, NodeId>::unVote(NodeId const& peer)
{ {
auto const it = votes_.find(peer); auto it = votes_.find(peer);
if (it != votes_.end()) if (it != votes_.end())
{ {
+1 -1
View File
@@ -211,7 +211,7 @@ struct Node
void void
erase(Node const* child) erase(Node const* child)
{ {
auto const it = std::ranges::find_if( auto it = std::ranges::find_if(
children, [child](std::unique_ptr<Node> const& curr) { return curr.get() == child; }); children, [child](std::unique_ptr<Node> const& curr) { return curr.get() == child; });
XRPL_ASSERT(it != children.end(), "xrpl::Node::erase : valid input"); XRPL_ASSERT(it != children.end(), "xrpl::Node::erase : valid input");
std::swap(*it, children.back()); std::swap(*it, children.back());
+9 -9
View File
@@ -184,7 +184,7 @@ enum class ValStatus {
/** /**
* Multiple validations by a validator for different ledgers * Multiple validations by a validator for different ledgers
*/ */
Conflicting, Conflicting
}; };
inline std::string inline std::string
@@ -366,7 +366,7 @@ private:
removeTrie(std::scoped_lock<Mutex> const&, NodeID const& nodeID, Validation const& val) removeTrie(std::scoped_lock<Mutex> const&, NodeID const& nodeID, Validation const& val)
{ {
{ {
auto const it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID())); auto it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
if (it != acquiring_.end()) if (it != acquiring_.end())
{ {
it->second.erase(nodeID); it->second.erase(nodeID);
@@ -375,7 +375,7 @@ private:
} }
} }
{ {
auto const it = lastLedger_.find(nodeID); auto it = lastLedger_.find(nodeID);
if (it != lastLedger_.end() && it->second.id() == val.ledgerID()) if (it != lastLedger_.end() && it->second.id() == val.ledgerID())
{ {
trie_.remove(it->second); trie_.remove(it->second);
@@ -443,7 +443,7 @@ private:
// Clear any prior acquiring ledger for this node // Clear any prior acquiring ledger for this node
if (prior) if (prior)
{ {
auto const it = acquiring_.find(*prior); auto it = acquiring_.find(*prior);
if (it != acquiring_.end()) if (it != acquiring_.end())
{ {
it->second.erase(nodeID); it->second.erase(nodeID);
@@ -455,7 +455,7 @@ private:
checkAcquired(lock); checkAcquired(lock);
std::pair<Seq, ID> const valPair{val.seq(), val.ledgerID()}; std::pair<Seq, ID> const valPair{val.seq(), val.ledgerID()};
auto const it = acquiring_.find(valPair); auto it = acquiring_.find(valPair);
if (it != acquiring_.end()) if (it != acquiring_.end())
{ {
it->second.insert(nodeID); it->second.insert(nodeID);
@@ -529,7 +529,7 @@ private:
} }
else else
{ {
auto const cit = typename decltype(current_)::const_iterator{it}; auto cit = typename decltype(current_)::const_iterator{it};
// contains a live record // contains a live record
f(cit->first, cit->second); f(cit->first, cit->second);
++it; ++it;
@@ -554,7 +554,7 @@ private:
void void
byLedger(std::scoped_lock<Mutex> const&, ID const& ledgerID, Pre&& pre, F&& f) byLedger(std::scoped_lock<Mutex> const&, ID const& ledgerID, Pre&& pre, F&& f)
{ {
auto const it = byLedger_.find(ledgerID); auto it = byLedger_.find(ledgerID);
if (it != byLedger_.end()) if (it != byLedger_.end())
{ {
// Update set time since it is being used // Update set time since it is being used
@@ -857,7 +857,7 @@ public:
if (!preferred) if (!preferred)
{ {
// fall back to majority over acquiring ledgers // fall back to majority over acquiring ledgers
auto const it = std::ranges::max_element(acquiring_, [](auto const& a, auto const& b) { auto it = std::ranges::max_element(acquiring_, [](auto const& a, auto const& b) {
std::pair<Seq, ID> const& aKey = a.first; std::pair<Seq, ID> const& aKey = a.first;
typename HashSet<NodeID>::size_type const& aSize = a.second.size(); typename HashSet<NodeID>::size_type const& aSize = a.second.size();
std::pair<Seq, ID> const& bKey = b.first; std::pair<Seq, ID> const& bKey = b.first;
@@ -937,7 +937,7 @@ public:
return (preferred->first >= minSeq) ? preferred->second : lcl.id(); return (preferred->first >= minSeq) ? preferred->second : lcl.id();
// Otherwise, rely on peer ledgers // Otherwise, rely on peer ledgers
auto const it = std::ranges::max_element(peerCounts, [](auto const& a, auto const& b) { auto it = std::ranges::max_element(peerCounts, [](auto const& a, auto const& b) {
// Prefer larger counts, then larger ids on ties // Prefer larger counts, then larger ids on ties
// (max_element expects this to return true if a < b) // (max_element expects this to return true if a < b)
return std::tie(a.second, a.first) < std::tie(b.second, b.first); return std::tie(a.second, a.first) < std::tie(b.second, b.first);
+1 -1
View File
@@ -156,7 +156,7 @@ public:
{ {
if (!allClosuresDoneCond_.wait_for(lock, wait, [this] { return closureCount_ == 0; })) if (!allClosuresDoneCond_.wait_for(lock, wait, [this] { return closureCount_ == 0; }))
{ {
if (auto const stream = j.error()) if (auto stream = j.error())
stream << name << " waiting for ClosureCounter::join()."; stream << name << " waiting for ClosureCounter::join().";
allClosuresDoneCond_.wait(lock, [this] { return closureCount_ == 0; }); allClosuresDoneCond_.wait(lock, [this] { return closureCount_ == 0; });
} }
+2 -2
View File
@@ -54,7 +54,7 @@ JobQueue::Coro::post()
} }
// sp keeps 'this' alive // sp keeps 'this' alive
if (jq_.addJob(type_, name_, [this, sp = shared_from_this()] { resume(); })) if (jq_.addJob(type_, name_, [this, sp = shared_from_this()]() { resume(); }))
{ {
return true; return true;
} }
@@ -130,7 +130,7 @@ inline void
JobQueue::Coro::join() JobQueue::Coro::join()
{ {
std::unique_lock<std::mutex> lk(mutexRun_); std::unique_lock<std::mutex> lk(mutexRun_);
cv_.wait(lk, [this] { return !running_; }); cv_.wait(lk, [this]() { return !running_; });
} }
} // namespace xrpl } // namespace xrpl
+1 -1
View File
@@ -37,7 +37,7 @@ enum class HashRouterFlags : std::uint16_t {
PRIVATE6 = 0x2000, PRIVATE6 = 0x2000,
// Used in apply.cpp // Used in apply.cpp
PRIVATE7 = 0x4000, PRIVATE7 = 0x4000,
PRIVATE8 = 0x8000, PRIVATE8 = 0x8000
}; };
constexpr HashRouterFlags constexpr HashRouterFlags
+6 -6
View File
@@ -30,12 +30,12 @@ private:
using namespace std::chrono_literals; using namespace std::chrono_literals;
int const maxLimit = std::numeric_limits<int>::max(); int const maxLimit = std::numeric_limits<int>::max();
auto const add = [this]( auto add = [this](
JobType jt, JobType jt,
std::string name, std::string name,
int limit, int limit,
std::chrono::milliseconds avgLatency, std::chrono::milliseconds avgLatency,
std::chrono::milliseconds peakLatency) { std::chrono::milliseconds peakLatency) {
XRPL_ASSERT(!map.contains(jt), "xrpl::JobTypes::JobTypes::add : unique job type input"); XRPL_ASSERT(!map.contains(jt), "xrpl::JobTypes::JobTypes::add : unique job type input");
[[maybe_unused]] auto const inserted = [[maybe_unused]] auto const inserted =
+3 -4
View File
@@ -177,13 +177,12 @@ measureDurationAndLog(
std::chrono::duration<Rep, Period> maxDelay, std::chrono::duration<Rep, Period> maxDelay,
beast::Journal const& journal) beast::Journal const& journal)
{ {
auto const startTime = std::chrono::high_resolution_clock::now(); auto startTime = std::chrono::high_resolution_clock::now();
auto result = func(); auto result = func();
auto const endTime = std::chrono::high_resolution_clock::now(); auto endTime = std::chrono::high_resolution_clock::now();
auto const duration = auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
if (duration > maxDelay) if (duration > maxDelay)
{ {
JLOG(journal.warn()) << actionDescription << " took " << duration.count() << " ms"; JLOG(journal.warn()) << actionDescription << " took " << duration.count() << " ms";
+1 -1
View File
@@ -95,7 +95,7 @@ private:
ArraySeparator, ArraySeparator,
MemberSeparator, MemberSeparator,
Comment, Comment,
Error, Error
}; };
class Token class Token
+1 -1
View File
@@ -26,7 +26,7 @@ enum class ValueType {
String, ///< UTF-8 string value String, ///< UTF-8 string value
Boolean, ///< bool value Boolean, ///< bool value
Array, ///< array value (ordered list) Array, ///< array value (ordered list)
Object, ///< object value (collection of name/value pairs). Object ///< object value (collection of name/value pairs).
}; };
/** /**
+1 -1
View File
@@ -165,7 +165,7 @@ public:
beast::Journal j) beast::Journal j)
{ {
// Ask implementation what to do // Ask implementation what to do
auto const actions = doVoting( auto actions = doVoting(
lastClosedLedger->rules(), lastClosedLedger->rules(),
lastClosedLedger->parentCloseTime(), lastClosedLedger->parentCloseTime(),
getEnabledAmendments(*lastClosedLedger), getEnabledAmendments(*lastClosedLedger),
+1 -1
View File
@@ -50,7 +50,7 @@ enum ApplyFlags : std::uint32_t {
// afterward, so signature-presence checks (e.g. Batch signer matching) // afterward, so signature-presence checks (e.g. Batch signer matching)
// are skipped at proposal-creation time (On-Chain Cosigner spec // are skipped at proposal-creation time (On-Chain Cosigner spec
// §5.3.1.2). // §5.3.1.2).
TapProposal = 0x2000, TapProposal = 0x2000
}; };
constexpr ApplyFlags constexpr ApplyFlags
+1 -2
View File
@@ -20,8 +20,7 @@ constexpr std::chrono::seconds kLedgerPossibleTimeResolutions[] = {
std::chrono::seconds{30}, std::chrono::seconds{30},
std::chrono::seconds{60}, std::chrono::seconds{60},
std::chrono::seconds{90}, std::chrono::seconds{90},
std::chrono::seconds{120}, std::chrono::seconds{120}};
};
/** /**
* Initial resolution of ledger close time. * Initial resolution of ledger close time.
+2 -2
View File
@@ -35,7 +35,7 @@ public:
{ {
std::scoped_lock const lock(mutex_); std::scoped_lock const lock(mutex_);
auto const it = map_.find(seq); auto it = map_.find(seq);
if ((it == map_.end()) || it->second) if ((it == map_.end()) || it->second)
{ {
@@ -88,7 +88,7 @@ public:
std::unique_lock<std::mutex> lock(mutex_); std::unique_lock<std::mutex> lock(mutex_);
do do
{ {
auto const it = map_.find(seq); auto it = map_.find(seq);
if (it == map_.end()) if (it == map_.end())
{ {
+5 -4
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h> #include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
@@ -164,7 +165,7 @@ getCandidateLedger(LedgerIndex requested)
areCompatible( areCompatible(
ReadView const& validLedger, ReadView const& validLedger,
ReadView const& testLedger, ReadView const& testLedger,
beast::Journal::Stream const& s, beast::Journal::Stream& s,
char const* reason); char const* reason);
[[nodiscard]] bool [[nodiscard]] bool
@@ -172,7 +173,7 @@ areCompatible(
UInt256 const& validHash, UInt256 const& validHash,
LedgerIndex validIndex, LedgerIndex validIndex,
ReadView const& testLedger, ReadView const& testLedger,
beast::Journal::Stream const& s, beast::Journal::Stream& s,
char const* reason); char const* reason);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -185,7 +186,7 @@ areCompatible(
dirLink( dirLink(
ApplyView& view, ApplyView& view,
AccountID const& owner, AccountID const& owner,
SLE::pointer const& object, SLE::pointer& object,
SF_UINT64 const& node = sfOwnerNode); SF_UINT64 const& node = sfOwnerNode);
/** /**
@@ -211,7 +212,7 @@ canWithdraw(
ReadView const& view, ReadView const& view,
AccountID const& from, AccountID const& from,
AccountID const& to, AccountID const& to,
SLE::ConstRef toSle, AccountRootEntryR const& toSle,
STAmount const& amount, STAmount const& amount,
bool hasDestinationTag, bool hasDestinationTag,
std::optional<std::vector<UInt256>> const& credentialIDs = std::nullopt); std::optional<std::vector<UInt256>> const& credentialIDs = std::nullopt);
+4 -8
View File
@@ -30,17 +30,13 @@ public:
static constexpr size_t kInitialBufferSize = kilobytes(256); static constexpr size_t kInitialBufferSize = kilobytes(256);
RawStateTable() RawStateTable()
: monotonicResource_{ : monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
std::make_unique<boost::container::pmr::monotonic_buffer_resource>( kInitialBufferSize)}
kInitialBufferSize),
}
, items_{monotonicResource_.get()} {}; , items_{monotonicResource_.get()} {};
RawStateTable(RawStateTable const& rhs) RawStateTable(RawStateTable const& rhs)
: monotonicResource_{ : monotonicResource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
std::make_unique<boost::container::pmr::monotonic_buffer_resource>( kInitialBufferSize)}
kInitialBufferSize),
}
, items_{rhs.items_, monotonicResource_.get()} , items_{rhs.items_, monotonicResource_.get()}
, dropsDestroyed_{rhs.dropsDestroyed_} {}; , dropsDestroyed_{rhs.dropsDestroyed_} {};
@@ -7,9 +7,20 @@
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <optional>
namespace xrpl { namespace xrpl {
struct Adjustment
{
std::int32_t ownerCountDelta = 0;
std::int32_t accountCountDelta = 0;
};
template <typename ViewT> template <typename ViewT>
class AccountRootEntry : public SLEBase<ViewT, ltACCOUNT_ROOT> class AccountRootEntry : public SLEBase<ViewT, ltACCOUNT_ROOT>
{ {
@@ -27,6 +38,123 @@ public:
: Base(keylet::account(id), view, j) : Base(keylet::account(id), view, j)
{ {
} }
/**
* Returns the account reserve, in drops.
*
* Actual owner count can be adjusted by delta in ownerCountAdj
* Actual reserve count can be adjusted by delta in accountCountAdj
* The reserve is calculated as:
* (ownerCount + "sponsoring object count" - "sponsored object count" + additionalOwnerCount) *
* increment + (1 if not sponsored account + sponsoringAccountCount) * "reserve base"
*
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative
* to subtract.
* @return The account reserve amount in drops
*/
[[nodiscard]] XRPAmount
reserve(Adjustment adj = {}) const;
/**
* Return number of the objects which reserve is covered by the account (so called "owner
* count"). Actual owner count can be adjusted by delta in ownerCountAdj.
*
* @param ownerCountAdj Adjustment to the owner count (default: 0)
* @return The adjusted owner count
*/
[[nodiscard]] std::uint32_t
ownerCount(std::int32_t ownerCountAdj = 0) const;
/**
* Check if this account has sufficient reserve.
*
* @param ctx The apply-view context (view + tx)
* @param accBalance The account's balance
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative
* to subtract.
* @param insufReserveCode The transaction result code to return if the reserve is
* insufficient (default: tecINSUFFICIENT_RESERVE).
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(
ApplyViewContext ctx,
XRPAmount accBalance,
std::optional<AccountRootEntry<ReadView>> const& sponsorSle,
Adjustment adj,
TER insufReserveCode = tecINSUFFICIENT_RESERVE) const;
/**
* Check if this account has sufficient reserve, deriving the sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, *this) instead of taking it explicitly. Use this
* in the common case where the sponsor is simply the transaction's reserve
* sponsor for this account. Callers that must force the account's-own-reserve branch
* (passing a null sponsor) or supply a different sponsor should use the
* explicit overload above.
*
* @param ctx The apply-view context (view + tx)
* @param accBalance The account's balance
* @param adj Reserve adjustments (owner/account count deltas)
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(ApplyViewContext ctx, XRPAmount accBalance, Adjustment adj) const;
/**
* Increase owner-count fields when the caller supplies the sponsor.
*
* This helper does not create a ledger object. It updates reserve accounting
* after the caller has created/updated an object.
* If sponsorSle is provided, this also adjusts the account's sponsored count
* and the sponsor's sponsoring count.
*
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to add to the owner count
*/
void
increaseOwnerCount(std::optional<AccountRootEntry<ApplyView>>& sponsorSle, std::uint32_t count)
requires Base::kIsWritable;
/**
* Increase owner-count fields, deriving the tx reserve sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, *this) instead of taking it explicitly. Use
* this when the sponsor is the transaction's reserve sponsor for this account
* (the common create path). Deletion paths, which derive the sponsor from an
* object's sfSponsor field, should keep using the explicit overload.
*
* @param ctx The apply-view context (view + tx)
* @param count Amount to add to the owner count
*/
void
increaseOwnerCount(ApplyViewContext ctx, std::uint32_t count)
requires Base::kIsWritable;
/**
* Decrease owner-count fields when the caller supplies the sponsor.
*
* This helper does not delete a ledger object. It updates reserve accounting
* after the caller has removed an owner-counted reserve, or for special
* owner-count changes whose sponsor cannot be derived from an object's
* sfSponsor field.
*
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to remove from the owner count
*/
void
decreaseOwnerCount(std::optional<AccountRootEntry<ApplyView>>& sponsorSle, std::uint32_t count)
requires Base::kIsWritable;
private:
void
adjustOwnerCountSigned(
std::optional<AccountRootEntry<ApplyView>>& sponsorSle,
std::int32_t adjustment)
requires Base::kIsWritable;
}; };
using AccountRootEntryR = AccountRootEntry<ReadView>; using AccountRootEntryR = AccountRootEntry<ReadView>;
@@ -1,17 +1,11 @@
#pragma once #pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/SLEBase.h> #include <xrpl/ledger/entries/SLEBase.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
#include <map>
#include <set>
namespace xrpl { namespace xrpl {
@@ -31,52 +25,6 @@ public:
: Base(keylet::amendments(), view, j) : Base(keylet::amendments(), view, j)
{ {
} }
/**
* Returns the set of amendments this entry reports as enabled.
*
* @return the set of enabled amendments.
*/
[[nodiscard]] std::set<UInt256>
enabledAmendments() const
{
std::set<UInt256> amendments;
if (this->exists() && (*this)->isFieldPresent(sfAmendments))
{
auto const& v = (*this)->getFieldV256(sfAmendments);
amendments.insert_range(v);
}
return amendments;
}
/**
* Returns a map of amendments that have achieved majority, to the time
* majority was reached.
*
* @return a map of amendment to the time majority was reached.
*/
[[nodiscard]] std::map<UInt256, NetClock::time_point>
majorityAmendments() const
{
std::map<UInt256, NetClock::time_point> ret;
if (this->exists() && (*this)->isFieldPresent(sfMajorities))
{
using TimePoint = NetClock::time_point;
using Duration = TimePoint::duration;
auto const majorities = (*this)->getFieldArray(sfMajorities);
for (auto const& m : majorities)
{
ret[m.getFieldH256(sfAmendment)] = TimePoint(Duration(m.getFieldU32(sfCloseTime)));
}
}
return ret;
}
}; };
using AmendmentsEntryR = AmendmentsEntry<ReadView>; using AmendmentsEntryR = AmendmentsEntry<ReadView>;
@@ -1,17 +1,11 @@
#pragma once #pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/SLEBase.h> #include <xrpl/ledger/entries/SLEBase.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STVector256.h>
#include <cstddef>
#include <optional>
namespace xrpl { namespace xrpl {
@@ -31,31 +25,6 @@ public:
: Base(keylet::skip(), view, j) : Base(keylet::skip(), view, j)
{ {
} }
/**
* Looks up a hash `diff` slots back from the most recent entry in the
* sfHashes vector (diff == 0 is the most recent entry).
*
* Callers decide which skip list entry to read and how to translate a
* target ledger sequence into `diff`; this only does the bounds check
* and vector indexing shared by both the recent (stride 1) and distant
* (stride 256) skip lists.
*
* @param diff how many slots back from the most recent hash to look up;
* 0 is the most recent hash.
* @return the hash at that slot, or std::nullopt if the entry does not
* exist or `diff` is out of range.
*/
[[nodiscard]] std::optional<UInt256>
hashAt(std::size_t diff) const
{
if (!this->exists())
return std::nullopt;
STVector256 const vec = (*this)->getFieldV256(sfHashes);
if (vec.size() > diff)
return vec[vec.size() - diff - 1];
return std::nullopt;
}
}; };
using LedgerHashesEntryR = LedgerHashesEntry<ReadView>; using LedgerHashesEntryR = LedgerHashesEntry<ReadView>;
+168 -87
View File
@@ -2,6 +2,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h> #include <xrpl/basics/Number.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
@@ -28,6 +29,7 @@
#include <expected> #include <expected>
#include <functional> #include <functional>
#include <optional> #include <optional>
#include <stdexcept>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
@@ -222,7 +224,7 @@ getAMMOfferStartWithTakerGets(
if (nTakerGetsConstraint < *nTakerGets) if (nTakerGetsConstraint < *nTakerGets)
nTakerGets = nTakerGetsConstraint; nTakerGets = nTakerGetsConstraint;
auto const getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) { auto getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) {
// Round downward to minimize the offer and to maximize the quality. // Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerGets is integral. // This has the most impact when takerGets is integral.
auto const takerGets = auto const takerGets =
@@ -290,7 +292,7 @@ getAMMOfferStartWithTakerPays(
if (nTakerPaysConstraint < *nTakerPays) if (nTakerPaysConstraint < *nTakerPays)
nTakerPays = nTakerPaysConstraint; nTakerPays = nTakerPaysConstraint;
auto const getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) { auto getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) {
// Round downward to minimize the offer and to maximize the quality. // Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerPays is integral. // This has the most impact when takerPays is integral.
auto const takerPays = auto const takerPays =
@@ -311,11 +313,11 @@ getAMMOfferStartWithTakerPays(
* is equal to LOB quality (in this case AMM offer quality is * is equal to LOB quality (in this case AMM offer quality is
* better than LOB quality) or AMM offer is equal to LOB quality * better than LOB quality) or AMM offer is equal to LOB quality
* (in this case SPQ is better than LOB quality). * (in this case SPQ is better than LOB quality).
* The economically coarser integral offer side is calculated first. The * Pre-amendment code calculates takerPays first. If takerGets is the
* result is rounded down, which makes the offer quality better. Calculating * economically coarser integral side, it is rounded down, which results in
* takerPays first instead would round down takerGets when that is the coarser * worse offer quality than LOB quality, and the offer might fail to generate.
* side, giving worse quality than LOB quality, and the offer might fail to * Post-amendment code calculates the economically coarser integral offer side
* generate. * first. The result is rounded down, which makes the offer quality better.
* It might not be possible to match either SPQ or AMM offer to LOB * It might not be possible to match either SPQ or AMM offer to LOB
* quality. This generally happens at higher fees. * quality. This generally happens at higher fees.
* @param pool AMM pool balances * @param pool AMM pool balances
@@ -329,9 +331,72 @@ changeSpotPriceQuality(
TAmounts<TIn, TOut> const& pool, TAmounts<TIn, TOut> const& pool,
Quality const& quality, Quality const& quality,
std::uint16_t tfee, std::uint16_t tfee,
Rules const& rules,
beast::Journal j) beast::Journal j)
{ {
auto amounts = [&] { if (!rules.enabled(fixAMMv1_1))
{
// Finds takerPays (i) and takerGets (o) such that given pool
// composition poolGets(I) and poolPays(O): (O - o) / (I + i) = quality.
// Where takerGets is calculated as the swapAssetIn (see below).
// The above equation produces the quadratic equation:
// i^2*(1-fee) + i*I*(2-fee) + I^2 - I*O/quality,
// which is solved for i, and o is found with swapAssetIn().
auto const f = feeMult(tfee); // 1 - fee
auto const& a = f;
auto const b = pool.in * (1 + f);
Number const c = pool.in * pool.in - pool.in * pool.out * quality.rate();
auto const res = b * b - 4 * a * c;
if (res < 0)
{
return std::nullopt; // LCOV_EXCL_LINE
}
if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
{
auto const nTakerPays = [&]() {
// The fee might make the AMM offer quality less than CLOB
// quality. Therefore, AMM offer has to satisfy this constraint:
// o / i >= q. Substituting o with swapAssetIn() gives: i <= O /
// q - I / (1 - fee).
auto const nTakerPaysConstraint = pool.out * quality.rate() - pool.in / f;
if (nTakerPaysPropose > nTakerPaysConstraint)
return nTakerPaysConstraint;
return nTakerPaysPropose;
}();
if (nTakerPays <= 0)
{
JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in)
<< " " << to_string(pool.out) << " " << quality << " " << tfee;
return std::nullopt;
}
auto const takerPays =
toAmount<TIn>(getAsset(pool.in), nTakerPays, Number::RoundingMode::Upward);
// should not fail
if (auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
Quality{amounts} < quality &&
!withinRelativeDistance(Quality{amounts}, quality, Number(1, -7)))
{
JLOG(j.error()) << "changeSpotPriceQuality failed: " << to_string(pool.in) << " "
<< to_string(pool.out) << " "
<< " " << quality << " " << tfee << " " << to_string(amounts.in)
<< " " << to_string(amounts.out);
Throw<std::runtime_error>("changeSpotPriceQuality failed");
}
else
{
JLOG(j.trace()) << "changeSpotPriceQuality succeeded: " << to_string(pool.in) << " "
<< to_string(pool.out) << " "
<< " " << quality << " " << tfee << " " << to_string(amounts.in)
<< " " << to_string(amounts.out);
return amounts;
}
}
JLOG(j.trace()) << "changeSpotPriceQuality calc failed: " << to_string(pool.in) << " "
<< to_string(pool.out) << " " << quality << " " << tfee;
return std::nullopt;
}
auto amounts = [&]() {
bool const inIntegral = getAsset(pool.in).integral(); bool const inIntegral = getAsset(pool.in).integral();
bool const outIntegral = getAsset(pool.out).integral(); bool const outIntegral = getAsset(pool.out).integral();
@@ -396,49 +461,57 @@ template <typename TIn, typename TOut>
TOut TOut
swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t tfee) swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t tfee)
{ {
// set rounding to always favor the amm. Clip to zero. if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1))
// calculate: {
// pool.out - // set rounding to always favor the amm. Clip to zero.
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), // calculate:
// and explicitly set the rounding modes // pool.out -
// Favoring the amm means we should: // (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// minimize: // and explicitly set the rounding modes
// pool.out - // Favoring the amm means we should:
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), // minimize:
// maximize: // pool.out -
// (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)), // (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// (pool.in * pool.out) // maximize:
// minimize: // (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
// (pool.in + assetIn * feeMult(tfee)), // (pool.in * pool.out)
// minimize: // minimize:
// assetIn * feeMult(tfee) // (pool.in + assetIn * feeMult(tfee)),
// feeMult is: (1-fee), fee is tfee/100000 // minimize:
// minimize: // assetIn * feeMult(tfee)
// 1-fee // feeMult is: (1-fee), fee is tfee/100000
// maximize: // minimize:
// fee // 1-fee
SaveNumberRoundMode const _{Number::getround()}; // maximize:
// fee
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward); Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out; auto const numerator = pool.in * pool.out;
auto const fee = getFee(tfee); auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Downward); Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.in + assetIn * (1 - fee); auto const denom = pool.in + assetIn * (1 - fee);
if (denom.signum() <= 0) if (denom.signum() <= 0)
return toAmount<TOut>(getAsset(pool.out), 0); return toAmount<TOut>(getAsset(pool.out), 0);
Number::setround(Number::RoundingMode::Upward); Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom; auto const ratio = numerator / denom;
Number::setround(Number::RoundingMode::Downward); Number::setround(Number::RoundingMode::Downward);
auto const swapOut = pool.out - ratio; auto const swapOut = pool.out - ratio;
if (swapOut.signum() < 0) if (swapOut.signum() < 0)
return toAmount<TOut>(getAsset(pool.out), 0); return toAmount<TOut>(getAsset(pool.out), 0);
return toAmount<TOut>(getAsset(pool.out), swapOut, Number::RoundingMode::Downward); return toAmount<TOut>(getAsset(pool.out), swapOut, Number::RoundingMode::Downward);
}
return toAmount<TOut>(
getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::RoundingMode::Downward);
} }
/** /**
@@ -455,49 +528,57 @@ template <typename TIn, typename TOut>
TIn TIn
swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_t tfee) swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_t tfee)
{ {
// set rounding to always favor the amm. Clip to zero. if (auto const& rules = getCurrentTransactionRules(); rules && rules->enabled(fixAMMv1_1))
// calculate:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) /
// (1-tfee/100000)
// maximize:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in)
// maximize:
// (pool.in * pool.out) / (pool.out - assetOut)
// maximize:
// (pool.in * pool.out)
// minimize
// (pool.out - assetOut)
// minimize:
// (1-tfee/100000)
// maximize:
// tfee/100000
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.out - assetOut;
if (denom.signum() <= 0)
{ {
return toMaxAmount<TIn>(getAsset(pool.in)); // set rounding to always favor the amm. Clip to zero.
// calculate:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) /
// (1-tfee/100000)
// maximize:
// ((pool.in * pool.out) / (pool.out - assetOut) - pool.in)
// maximize:
// (pool.in * pool.out) / (pool.out - assetOut)
// maximize:
// (pool.in * pool.out)
// minimize
// (pool.out - assetOut)
// minimize:
// (1-tfee/100000)
// maximize:
// tfee/100000
SaveNumberRoundMode const _{Number::getround()};
Number::setround(Number::RoundingMode::Upward);
auto const numerator = pool.in * pool.out;
Number::setround(Number::RoundingMode::Downward);
auto const denom = pool.out - assetOut;
if (denom.signum() <= 0)
{
return toMaxAmount<TIn>(getAsset(pool.in));
}
Number::setround(Number::RoundingMode::Upward);
auto const ratio = numerator / denom;
auto const numerator2 = ratio - pool.in;
auto const fee = getFee(tfee);
Number::setround(Number::RoundingMode::Downward);
auto const feeMult = 1 - fee;
Number::setround(Number::RoundingMode::Upward);
auto const swapIn = numerator2 / feeMult;
if (swapIn.signum() < 0)
return toAmount<TIn>(getAsset(pool.in), 0);
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::RoundingMode::Upward);
} }
Number::setround(Number::RoundingMode::Upward); return toAmount<TIn>(
auto const ratio = numerator / denom; getAsset(pool.in),
auto const numerator2 = ratio - pool.in; ((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
auto const fee = getFee(tfee); Number::RoundingMode::Upward);
Number::setround(Number::RoundingMode::Downward);
auto const feeMult = 1 - fee;
Number::setround(Number::RoundingMode::Upward);
auto const swapIn = numerator2 / feeMult;
if (swapIn.signum() < 0)
return toAmount<TIn>(getAsset(pool.in), 0);
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::RoundingMode::Upward);
} }
/** /**
@@ -791,8 +872,8 @@ deleteAMMAccount(Sandbox& view, Asset const& asset, Asset const& asset2, beast::
*/ */
void void
initializeFeeAuctionVote( initializeFeeAuctionVote(
ApplyView const& view, ApplyView& view,
SLE::pointer const& ammSle, SLE::pointer& ammSle,
AccountID const& account, AccountID const& account,
Asset const& lptAsset, Asset const& lptAsset,
std::uint16_t tfee); std::uint16_t tfee);
@@ -814,7 +895,7 @@ std::expected<bool, TER>
verifyAndAdjustLPTokenBalance( verifyAndAdjustLPTokenBalance(
Sandbox& sb, Sandbox& sb,
STAmount const& lpTokens, STAmount const& lpTokens,
SLE::pointer const& ammSle, SLE::pointer& ammSle,
AccountID const& account); AccountID const& account);
} // namespace xrpl } // namespace xrpl
Loaded 100 of 828 files, more files were not shown because too many files have changed in this diff. Show more