mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-22 19:47:17 +00:00
Compare commits
56
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7add7ce15 | ||
|
|
6d6ab2d067 | ||
|
|
00e6407514 | ||
|
|
00c06edffb | ||
|
|
de5053ae0d | ||
|
|
1940ec5c2a | ||
|
|
19c94c73f4 | ||
|
|
cd005ff60d | ||
|
|
578224f2e6 | ||
|
|
3857ce21cd | ||
|
|
aa490df46b | ||
|
|
88c1f1e7ac | ||
|
|
ede8af8191 | ||
|
|
3c24b605a1 | ||
|
|
1a1924dd30 | ||
|
|
99859d2458 | ||
|
|
7642bc6671 | ||
|
|
add33d853c | ||
|
|
be0baf1b53 | ||
|
|
b394730bd0 | ||
|
|
8290eb3024 | ||
|
|
d537684df5 | ||
|
|
4085361251 | ||
|
|
1de7c130b0 | ||
|
|
2a678a1157 | ||
|
|
5c254aadf2 | ||
|
|
ad2db1962e | ||
|
|
4dae405762 | ||
|
|
b21b3596f8 | ||
|
|
d648539b62 | ||
|
|
50644c6d30 | ||
|
|
88c248077e | ||
|
|
bad40d7e10 | ||
|
|
74d0c375ec | ||
|
|
200ab3f694 | ||
|
|
a7a4357022 | ||
|
|
e0230a1e22 | ||
|
|
5f1a98397c | ||
|
|
c8ca624974 | ||
|
|
4489cda841 | ||
|
|
784774005e | ||
|
|
904b39a3d3 | ||
|
|
eadfabfe4f | ||
|
|
d991f81e87 | ||
|
|
a34a96e233 | ||
|
|
a3a277518b | ||
|
|
8438698c54 | ||
|
|
0597047d79 | ||
|
|
992c6f525d | ||
|
|
9a870c36e2 | ||
|
|
a4462e65bc | ||
|
|
f0596c0a5d | ||
|
|
dd99bc3ce8 | ||
|
|
25cd7730e5 | ||
|
|
8dcbcb22c2 | ||
|
|
f44dfc89cc |
No files matched your search
+16
@@ -5,7 +5,10 @@ Checks: "-*,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-signed-bitwise,
|
||||
-bugprone-std-exception-baseclass,
|
||||
-bugprone-throwing-static-initialization,
|
||||
-bugprone-unhandled-code-paths,
|
||||
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-avoid-c-arrays,
|
||||
@@ -14,6 +17,7 @@ Checks: "-*,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-cppcoreguidelines-c-copy-assignment-signature,
|
||||
-cppcoreguidelines-explicit-constructor,
|
||||
-cppcoreguidelines-interfaces-global-init,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-missing-std-forward,
|
||||
@@ -32,6 +36,7 @@ Checks: "-*,
|
||||
llvm-namespace-comment,
|
||||
|
||||
misc-*,
|
||||
-misc-explicit-constructor,
|
||||
-misc-multiple-inheritance,
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
@@ -45,6 +50,8 @@ Checks: "-*,
|
||||
-modernize-avoid-c-style-cast,
|
||||
-modernize-return-braced-init-list,
|
||||
-modernize-use-integer-sign-comparison,
|
||||
-modernize-use-string-view,
|
||||
-modernize-use-structured-binding,
|
||||
-modernize-use-trailing-return-type,
|
||||
|
||||
performance-*,
|
||||
@@ -53,6 +60,7 @@ Checks: "-*,
|
||||
-performance-noexcept-move-constructor,
|
||||
-performance-unnecessary-copy-initialization,
|
||||
-performance-unnecessary-value-param,
|
||||
-performance-use-std-move,
|
||||
|
||||
readability-*,
|
||||
-readability-avoid-const-params-in-decls,
|
||||
@@ -65,7 +73,11 @@ Checks: "-*,
|
||||
-readability-named-parameter,
|
||||
-readability-qualified-auto,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-redundant-nested-if,
|
||||
-readability-redundant-qualified-alias,
|
||||
-readability-static-accessed-through-instance,
|
||||
-readability-trailing-comma,
|
||||
-readability-trivial-switch,
|
||||
-readability-uppercase-literal-suffix
|
||||
"
|
||||
# ---
|
||||
@@ -81,6 +93,10 @@ CheckOptions:
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
|
||||
# New in clang-tidy 23; disabled until the code is updated
|
||||
misc-const-correctness.AnalyzeAutoVariables: false
|
||||
misc-const-correctness.AnalyzeLambdas: false
|
||||
misc-const-correctness.AnalyzeParameters: false
|
||||
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/.*;openssl/obj_mac\\.h"
|
||||
|
||||
readability-braces-around-statements.ShortStatementLines: 2
|
||||
|
||||
@@ -15,9 +15,9 @@ inputs:
|
||||
required: false
|
||||
default: "false"
|
||||
log_verbosity:
|
||||
description: "The logging verbosity."
|
||||
description: 'The logging verbosity ("quiet", "verbose"), or empty to use the Conan defaults.'
|
||||
required: false
|
||||
default: "verbose"
|
||||
default: ""
|
||||
sanitizers:
|
||||
description: "The sanitizers to enable."
|
||||
required: false
|
||||
@@ -35,6 +35,16 @@ runs:
|
||||
LOG_VERBOSITY: ${{ inputs.log_verbosity }}
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
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 \
|
||||
--profile:all ci \
|
||||
--build="${BUILD_OPTION}" \
|
||||
@@ -42,8 +52,7 @@ runs:
|
||||
--options:host='&:xrpld=True' \
|
||||
--settings:all build_type="${BUILD_TYPE}" \
|
||||
--conf:all tools.build:jobs=${BUILD_NPROC} \
|
||||
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
|
||||
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
|
||||
"${VERBOSITY_ARGS[@]}" \
|
||||
--format=json \
|
||||
. >"${RUNNER_TEMP}/conan-graph.json"
|
||||
|
||||
@@ -52,4 +61,4 @@ runs:
|
||||
- name: Check build-context packages for Nix store dependencies (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: ./bin/check-build-context-runtime.sh "${RUNNER_TEMP}/conan-graph.json"
|
||||
run: ./bin/nix/check-build-context-runtime.sh "${RUNNER_TEMP}/conan-graph.json"
|
||||
@@ -12,7 +12,7 @@ on:
|
||||
- "!nix/docker/README.md"
|
||||
- "!nix/devshell.nix"
|
||||
- "!nix/check-tools/**"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "bin/nix/default-loader-path.sh"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build-nix-images.yml"
|
||||
@@ -24,8 +24,8 @@ on:
|
||||
- "!nix/devshell.nix"
|
||||
- "!nix/check-tools/**"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "bin/install-sanitizer-libs.sh"
|
||||
- "bin/nix/default-loader-path.sh"
|
||||
- "bin/install/sanitizer-libs.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
|
||||
@@ -5,12 +5,12 @@ on:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- "bin/install-packaging-tools.sh"
|
||||
- "bin/install/packaging-tools.sh"
|
||||
- "package/images/packaging/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build-packaging-images.yml"
|
||||
- "bin/install-packaging-tools.sh"
|
||||
- "bin/install/packaging-tools.sh"
|
||||
- "package/images/packaging/**"
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
@@ -93,9 +93,8 @@ jobs:
|
||||
.github/workflows/reusable-upload-recipe.yml
|
||||
.clang-tidy
|
||||
.codecov.yml
|
||||
bin/check-nix-store-refs.sh
|
||||
bin/check-tools.sh
|
||||
bin/default-loader-path.sh
|
||||
bin/nix/**
|
||||
cfg/**
|
||||
cmake/**
|
||||
conan/**
|
||||
|
||||
@@ -31,9 +31,8 @@ on:
|
||||
- ".github/workflows/reusable-upload-recipe.yml"
|
||||
- ".clang-tidy"
|
||||
- ".codecov.yml"
|
||||
- "bin/check-nix-store-refs.sh"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "bin/nix/**"
|
||||
- "cfg/**"
|
||||
- "cmake/**"
|
||||
- "conan/**"
|
||||
|
||||
@@ -186,9 +186,6 @@ jobs:
|
||||
with:
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
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 }}
|
||||
|
||||
- name: Configure CMake
|
||||
@@ -257,20 +254,20 @@ jobs:
|
||||
# cache included, since what it holds is what gets uploaded and reused.
|
||||
- name: Check the build output for Nix store references (Nix toolchain)
|
||||
if: ${{ inputs.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${BUILD_DIR}"
|
||||
run: ./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}"
|
||||
|
||||
- name: Check the Conan cache for Nix store references (Nix toolchain)
|
||||
if: ${{ inputs.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
run: ./bin/nix/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
|
||||
# Only what PatchNixBinary.cmake retargets: the toolchain in the Linux
|
||||
# images always references the store. Same condition it uses.
|
||||
- name: Check for Nix store references (Linux)
|
||||
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
|
||||
run: |
|
||||
./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpld"
|
||||
./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpl_tests"
|
||||
./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpld_tests"
|
||||
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpld"
|
||||
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpl_tests"
|
||||
./bin/nix/check-nix-store-refs.sh "${BUILD_DIR}/xrpld_tests"
|
||||
|
||||
- name: Show ccache statistics
|
||||
if: ${{ inputs.ccache_enabled }}
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
needs: [determine-files]
|
||||
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
|
||||
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
|
||||
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-ed96e60"
|
||||
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-3d526d4"
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
@@ -73,7 +73,6 @@ jobs:
|
||||
with:
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ env.BUILD_TYPE }}
|
||||
log_verbosity: verbose
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
|
||||
@@ -108,14 +108,11 @@ jobs:
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
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 }}
|
||||
|
||||
- name: Check the Conan cache for Nix store references (Nix toolchain)
|
||||
if: ${{ matrix.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
run: ./bin/nix/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
|
||||
- name: Log into Conan remote
|
||||
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ Version 3.5.0 is not yet released.
|
||||
|
||||
### Additions in 3.5.0
|
||||
|
||||
- `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))
|
||||
- `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))
|
||||
- `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
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -11,7 +11,7 @@
|
||||
# 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/check-build-context-runtime.sh <graph.json>
|
||||
# Usage: bin/nix/check-build-context-runtime.sh <graph.json>
|
||||
# <graph.json> is the output of `conan install --format=json`.
|
||||
|
||||
set -euo pipefail
|
||||
@@ -10,7 +10,7 @@
|
||||
# alone; the scripts in a Conan cache are all git hook samples and autotools
|
||||
# scratch, 36 false positives to 0 real.
|
||||
#
|
||||
# Usage: bin/check-nix-store-refs.sh <path>
|
||||
# Usage: bin/nix/check-nix-store-refs.sh <path>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
File renamed without changes.
@@ -17,7 +17,7 @@
|
||||
(runtime libraries resolved through the rpath) are skipped too.
|
||||
Everywhere else `patch_nix_binary` is a no-op.
|
||||
|
||||
The default loader is resolved by bin/default-loader-path.sh.
|
||||
The default loader is resolved by bin/nix/default-loader-path.sh.
|
||||
#]===================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
@@ -25,7 +25,7 @@ include_guard(GLOBAL)
|
||||
include(CompilationEnv)
|
||||
|
||||
# Resolves the system default ELF loader path for the current architecture.
|
||||
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
|
||||
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/nix/default-loader-path.sh")
|
||||
|
||||
if(
|
||||
is_linux
|
||||
|
||||
+13
-7
@@ -60,8 +60,20 @@ tools.build:exelinkflags+={{ static_runtime_flags }}
|
||||
tools.info.package_id:confs+=["tools.build:exelinkflags"]
|
||||
{% endif %}
|
||||
|
||||
{% if os == "Macos" %}
|
||||
{% 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" %}
|
||||
{# os.version adds -mmacosx-version-min to compiler command lines, #}
|
||||
{# but Boost.Context's b2 assembly (.S) rule ignores it, #}
|
||||
{# so those objects keep the host SDK version and still warn at link time. #}
|
||||
@@ -71,11 +83,5 @@ boost/*:MACOSX_DEPLOYMENT_TARGET={{ min_macos_version }}
|
||||
{% 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. #}
|
||||
[options]
|
||||
b2/*:use_cxx_env=True
|
||||
|
||||
[buildenv]
|
||||
b2/*:CXXFLAGS={{ static_runtime_flags | join(" ") }}
|
||||
{% endif %}
|
||||
+1
-1
@@ -154,7 +154,7 @@ class Xrpl(ConanFile):
|
||||
self.requires("xxhash/0.8.3", transitive_headers=True)
|
||||
|
||||
exports_sources = (
|
||||
"bin/default-loader-path.sh",
|
||||
"bin/nix/default-loader-path.sh",
|
||||
"CMakeLists.txt",
|
||||
"cfg/*",
|
||||
"cmake/*",
|
||||
|
||||
Vendored
+6
-6
@@ -183,14 +183,14 @@ at link or run time.
|
||||
> configuration CI covers, and no dependency binaries are published for it.
|
||||
|
||||
This is checked rather than assumed.
|
||||
[`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) takes one file
|
||||
or directory and fails if a binary under it resolves a store path at run time.
|
||||
[`bin/nix/check-nix-store-refs.sh`](../../bin/nix/check-nix-store-refs.sh) takes one
|
||||
file 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
|
||||
before anything is published. You can run it yourself:
|
||||
|
||||
```bash
|
||||
bin/check-nix-store-refs.sh build
|
||||
bin/check-nix-store-refs.sh ~/.conan2-nix
|
||||
bin/nix/check-nix-store-refs.sh build
|
||||
bin/nix/check-nix-store-refs.sh ~/.conan2-nix
|
||||
```
|
||||
|
||||
It works on Linux too, but asserts something narrower there: the toolchain always
|
||||
@@ -204,7 +204,7 @@ instrument them. CI checks that they load nothing from the store but glibc, from
|
||||
the graph `conan install --format=json` writes:
|
||||
|
||||
```bash
|
||||
bin/check-build-context-runtime.sh graph.json
|
||||
bin/nix/check-build-context-runtime.sh graph.json
|
||||
```
|
||||
|
||||
Only the binaries [`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake)
|
||||
@@ -212,7 +212,7 @@ retargets to the system loader have to be fully clean, and those are what CI
|
||||
checks:
|
||||
|
||||
```bash
|
||||
bin/check-nix-store-refs.sh build/xrpld
|
||||
bin/nix/check-nix-store-refs.sh build/xrpld
|
||||
```
|
||||
|
||||
### The libresolv stub
|
||||
|
||||
Vendored
+3
-3
@@ -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
|
||||
```
|
||||
|
||||
[`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) finds the same
|
||||
thing without having to run anything, and names the file:
|
||||
[`bin/nix/check-nix-store-refs.sh`](../../bin/nix/check-nix-store-refs.sh) finds the
|
||||
same thing without having to run anything, and names the file:
|
||||
|
||||
```
|
||||
$ bin/check-nix-store-refs.sh ~/.conan2-nix
|
||||
$ bin/nix/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
|
||||
/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig
|
||||
/nix/store/p4lp3xq4imd1qzqh08x8vcq2zfhi7rca-libresolv-93/lib/libresolv.9.dylib
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
|
||||
/**
|
||||
* RAII class to check if an Item is already being processed on another thread,
|
||||
* as indicated by it's presence in a Collection.
|
||||
*
|
||||
* If the Item is not in the Collection, it will be added under lock in the
|
||||
* ctor, and removed under lock in the dtor. The object will be considered
|
||||
* "usable" and evaluate to `true`.
|
||||
*
|
||||
* If the Item is in the Collection, no changes will be made to the collection,
|
||||
* and the CanProcess object will be considered "unusable".
|
||||
*
|
||||
* It's up to the caller to decide what "usable" and "unusable" mean. (e.g.
|
||||
* Process or skip a block of code, or set a flag.)
|
||||
*
|
||||
* The current use is to avoid lock contention that would be involved in
|
||||
* processing something associated with the Item.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* void IncomingLedgers::acquireAsync(LedgerHash const& hash, ...)
|
||||
* {
|
||||
* if (CanProcess check{acquiresMutex_, pendingAcquires_, hash})
|
||||
* {
|
||||
* acquire(hash, ...);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* bool
|
||||
* NetworkOPsImp::recvValidation(
|
||||
* std::shared_ptr<STValidation> const& val,
|
||||
* std::string const& source)
|
||||
* {
|
||||
* CanProcess check(
|
||||
* validationsMutex_, pendingValidations_, val->getLedgerHash());
|
||||
* BypassAccept bypassAccept =
|
||||
* check ? BypassAccept::no : BypassAccept::yes;
|
||||
* handleNewValidation(app_, val, source, bypassAccept, m_journal);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
class CanProcess
|
||||
{
|
||||
public:
|
||||
template <class Mutex, class Collection, class Item>
|
||||
CanProcess(Mutex& mtx, Collection& collection, Item const& item)
|
||||
: cleanup_(insert(mtx, collection, item))
|
||||
{
|
||||
}
|
||||
|
||||
~CanProcess()
|
||||
{
|
||||
if (cleanup_)
|
||||
cleanup_();
|
||||
}
|
||||
|
||||
CanProcess(CanProcess const&) = delete;
|
||||
|
||||
CanProcess&
|
||||
operator=(CanProcess const&) = delete;
|
||||
|
||||
explicit
|
||||
operator bool() const
|
||||
{
|
||||
return static_cast<bool>(cleanup_);
|
||||
}
|
||||
|
||||
private:
|
||||
template <bool useIterator, class Mutex, class Collection, class Item>
|
||||
std::function<void()>
|
||||
doInsert(Mutex& mtx, Collection& collection, Item const& item)
|
||||
{
|
||||
std::unique_lock<Mutex> lock(mtx);
|
||||
// TODO: Use structured binding once LLVM 16 is the minimum supported
|
||||
// version. See also: https://github.com/llvm/llvm-project/issues/48582
|
||||
// https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
|
||||
auto const insertResult = collection.insert(item);
|
||||
auto const it = insertResult.first;
|
||||
if (!insertResult.second)
|
||||
return {};
|
||||
if constexpr (useIterator)
|
||||
return [&, it]() {
|
||||
std::unique_lock<Mutex> lock(mtx);
|
||||
collection.erase(it);
|
||||
};
|
||||
else
|
||||
return [&]() {
|
||||
std::unique_lock<Mutex> lock(mtx);
|
||||
collection.erase(item);
|
||||
};
|
||||
}
|
||||
|
||||
// Generic insert() function doesn't use iterators because they may get
|
||||
// invalidated
|
||||
template <class Mutex, class Collection, class Item>
|
||||
std::function<void()>
|
||||
insert(Mutex& mtx, Collection& collection, Item const& item)
|
||||
{
|
||||
return doInsert<false>(mtx, collection, item);
|
||||
}
|
||||
|
||||
// Specialize insert() for std::set, which does not invalidate iterators for
|
||||
// insert and erase
|
||||
template <class Mutex, class Item>
|
||||
std::function<void()>
|
||||
insert(Mutex& mtx, std::set<Item>& collection, Item const& item)
|
||||
{
|
||||
return doInsert<true>(mtx, collection, item);
|
||||
}
|
||||
|
||||
// If set, then the item is "usable"
|
||||
std::function<void()> cleanup_;
|
||||
};
|
||||
@@ -3,9 +3,84 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
/**
|
||||
* 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]
|
||||
|
||||
@@ -36,7 +36,7 @@ template <typename 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>;
|
||||
|
||||
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{};
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
|
||||
@@ -783,7 +783,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&)
|
||||
{
|
||||
return std::thread([&, this]() {
|
||||
return std::thread([&, this] {
|
||||
int cacheRemovals = 0;
|
||||
int mapRemovals = 0;
|
||||
|
||||
@@ -863,7 +863,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
|
||||
std::atomic<int>& allRemovals,
|
||||
std::scoped_lock<std::recursive_mutex> const&)
|
||||
{
|
||||
return std::thread([&, this]() {
|
||||
return std::thread([&, this] {
|
||||
// NOLINTBEGIN https://github.com/XRPLF/rippled/issues/7056
|
||||
int cacheRemovals = 0;
|
||||
int mapRemovals = 0;
|
||||
|
||||
@@ -1604,7 +1604,7 @@ AgedOrderedContainer<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::erase(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
|
||||
requires(!IsBoostReverseIterator<Iterator>::value)
|
||||
{
|
||||
unlinkAndDeleteElement(&*((pos++).iterator()));
|
||||
unlinkAndDeleteElement(&*(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)
|
||||
{
|
||||
for (; first != last;)
|
||||
unlinkAndDeleteElement(&*((first++).iterator()));
|
||||
unlinkAndDeleteElement(&*(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(
|
||||
beast::detail::AgedContainerIterator<IsConst, Iterator> pos)
|
||||
{
|
||||
unlinkAndDeleteElement(&*((pos++).iterator()));
|
||||
unlinkAndDeleteElement(&*(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)
|
||||
{
|
||||
for (; first != last;)
|
||||
unlinkAndDeleteElement(&*((first++).iterator()));
|
||||
unlinkAndDeleteElement(&*(first++).iterator());
|
||||
|
||||
return beast::detail::AgedContainerIterator<false, Iterator>(first.iterator());
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ void
|
||||
hash_append(Hasher& h, boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
|
||||
requires(IsContiguouslyHashable<Key, Hasher>::value)
|
||||
{
|
||||
h(&(v.begin()), v.size() * sizeof(Key));
|
||||
h(&v.begin(), v.size() * sizeof(Key));
|
||||
}
|
||||
// tuple
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace beast::insight {
|
||||
class HookImpl : public std::enable_shared_from_this<HookImpl>
|
||||
{
|
||||
public:
|
||||
using HandlerType = std::function<void(void)>;
|
||||
using HandlerType = std::function<void()>;
|
||||
|
||||
virtual ~HookImpl() = 0;
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ isMulticast(Address const& addr)
|
||||
inline bool
|
||||
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
|
||||
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
|
||||
|
||||
@@ -34,7 +34,7 @@ typeName()
|
||||
name += " volatile";
|
||||
if (std::is_lvalue_reference_v<T>)
|
||||
{
|
||||
name += "&";
|
||||
name += '&';
|
||||
}
|
||||
else if (std::is_rvalue_reference_v<T>)
|
||||
{
|
||||
|
||||
@@ -47,8 +47,8 @@ public:
|
||||
template <class F, class... Args>
|
||||
explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s)
|
||||
{
|
||||
std::function<void(void)> b = [f = std::forward<F>(f),
|
||||
... args = std::forward<Args>(args)]() mutable {
|
||||
std::function<void()> b = [f = std::forward<F>(f),
|
||||
... args = std::forward<Args>(args)] mutable {
|
||||
std::invoke(f, args...);
|
||||
};
|
||||
t_ = std::thread(&Thread::run, this, std::move(b));
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
|
||||
private:
|
||||
void
|
||||
run(std::function<void(void)> f)
|
||||
run(std::function<void()> f)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ JobQueue::Coro::post()
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -130,7 +130,7 @@ inline void
|
||||
JobQueue::Coro::join()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(mutexRun_);
|
||||
cv_.wait(lk, [this]() { return !running_; });
|
||||
cv_.wait(lk, [this] { return !running_; });
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
/**
|
||||
* Add a suppression peer and get message's relay status.
|
||||
* Return pair:
|
||||
* element 1: true if the peer is added.
|
||||
* element 1: true if the key is added.
|
||||
* element 2: optional is seated to the relay time point or
|
||||
* is unseated if has not relayed yet.
|
||||
*/
|
||||
|
||||
@@ -353,7 +353,7 @@ changeSpotPriceQuality(
|
||||
}
|
||||
if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
|
||||
{
|
||||
auto const nTakerPays = [&]() {
|
||||
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 /
|
||||
@@ -372,8 +372,8 @@ changeSpotPriceQuality(
|
||||
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 &&
|
||||
auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
|
||||
if (Quality{amounts} < quality &&
|
||||
!withinRelativeDistance(Quality{amounts}, quality, Number(1, -7)))
|
||||
{
|
||||
JLOG(j.error()) << "changeSpotPriceQuality failed: " << to_string(pool.in) << " "
|
||||
@@ -382,21 +382,19 @@ changeSpotPriceQuality(
|
||||
<< " " << 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 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 = [&]() {
|
||||
auto amounts = [&] {
|
||||
bool const inIntegral = getAsset(pool.in).integral();
|
||||
bool const outIntegral = getAsset(pool.out).integral();
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
void
|
||||
asyncHandshake(HandshakeType type, Callback cbFunc)
|
||||
{
|
||||
if ((type == SslSocket::client) || (secure_))
|
||||
if ((type == SslSocket::client) || secure_)
|
||||
{
|
||||
// must be ssl
|
||||
secure_ = true;
|
||||
|
||||
@@ -67,7 +67,7 @@ class EncodedBlob
|
||||
|
||||
public:
|
||||
explicit EncodedBlob(std::shared_ptr<NodeObject> const& obj)
|
||||
: size_([&obj]() {
|
||||
: size_([&obj] {
|
||||
XRPL_ASSERT(obj, "xrpl::node_store::EncodedBlob::EncodedBlob : non-null input");
|
||||
|
||||
if (!obj)
|
||||
|
||||
@@ -55,7 +55,7 @@ hash_append(Hasher& h, Book const& b)
|
||||
using beast::hash_append;
|
||||
hash_append(h, b.in, b.out);
|
||||
if (b.domain)
|
||||
hash_append(h, *(b.domain));
|
||||
hash_append(h, *b.domain);
|
||||
}
|
||||
|
||||
Book
|
||||
|
||||
@@ -208,7 +208,10 @@ enum LedgerEntryType : std::uint16_t {
|
||||
\
|
||||
LEDGER_OBJECT(Sponsorship, \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForFee, 0x00010000) \
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000))
|
||||
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000)) \
|
||||
\
|
||||
LEDGER_OBJECT(LoanBroker, \
|
||||
LSF_FLAG(lsfLoanBrokerPrivate, 0x00010000))
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ struct LedgerHeader
|
||||
|
||||
// If validated is false, it means "not yet validated."
|
||||
// Once validated is true, it will never be set false at a later time.
|
||||
// NOTE: If you are accessing this directly, you are probably doing it
|
||||
// wrong. Use LedgerMaster::isValidated().
|
||||
// VFALCO TODO Make this not mutable
|
||||
bool mutable validated = false;
|
||||
bool accepted = false;
|
||||
|
||||
@@ -457,9 +457,7 @@ private:
|
||||
// The remove_cv and remove_reference are necessitated by the STBitString
|
||||
// types. Their value() returns by const ref. We return those types
|
||||
// by value.
|
||||
template <
|
||||
typename T,
|
||||
typename V = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<T>().value())>>>
|
||||
template <typename T, typename V = std::remove_cvref_t<decltype(std::declval<T>().value())>>
|
||||
V
|
||||
getFieldByValue(SField const& field) const;
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ private:
|
||||
template <class LookupNodeID>
|
||||
STValidation::STValidation(SerialIter& sit, LookupNodeID&& lookupNodeID, DeserializeOptions options)
|
||||
: STObject(validationFormat(), sit, sfValidation, options.requireCanonicalOrder)
|
||||
, signingPubKey_([this]() {
|
||||
, signingPubKey_([this] {
|
||||
auto const spk = getFieldVL(sfSigningPubKey);
|
||||
|
||||
if (publicKeyType(makeSlice(spk)) != KeyType::Secp256k1)
|
||||
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
{
|
||||
auto success = (offset + (Bits / 8)) <= data_.size();
|
||||
if (success)
|
||||
memcpy(data.begin(), &(data_.front()) + offset, (Bits / 8));
|
||||
memcpy(data.begin(), &data_.front() + offset, (Bits / 8));
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -449,7 +449,7 @@ public:
|
||||
// Trait tells the requires-clause which types are allowed for construction.
|
||||
template <typename T>
|
||||
constexpr TERSubset(T rhs)
|
||||
requires(Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value)
|
||||
requires(Trait<std::remove_cvref_t<T>>::value)
|
||||
: code_(TERtoInt(rhs))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -226,6 +226,10 @@ inline constexpr FlagValue tfUniversalMask = ~tfUniversal;
|
||||
TF_FLAG(tfLoanUnimpair, 0x00040000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(LoanBrokerSet, \
|
||||
TF_FLAG(tfLoanBrokerPrivate, 0x00010000), \
|
||||
MASK_ADJ(0)) \
|
||||
\
|
||||
TRANSACTION(SponsorshipSet, \
|
||||
TF_FLAG(tfSponsorshipSetRequireSignForFee, 0x00010000) \
|
||||
TF_FLAG(tfSponsorshipClearRequireSignForFee, 0x00020000) \
|
||||
|
||||
@@ -20,6 +20,7 @@ XRPL_FEATURE(SmartEscrow, Supported::No, VoteBehavior::DefaultN
|
||||
XRPL_FEATURE(LendingProtocolV1_2, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (Cleanup3_5_0, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(ConfidentialMPTKeyRotation, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchV1_2, Supported::Yes, VoteBehavior::DefaultYes)
|
||||
XRPL_FIX (Cleanup3_4_0, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Sponsor, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(BatchV1_1, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -549,6 +549,7 @@ LEDGER_ENTRY(ltLOAN_BROKER, 0x0088, LoanBroker, loan_broker, ({
|
||||
{sfCoverAvailable, SoeDefault},
|
||||
{sfCoverRateMinimum, SoeDefault},
|
||||
{sfCoverRateLiquidation, SoeDefault},
|
||||
{sfDomainID, SoeOptional},
|
||||
}))
|
||||
|
||||
/** A ledger object representing a loan between a Borrower and a Loan Broker
|
||||
|
||||
@@ -900,6 +900,7 @@ TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet,
|
||||
{sfDebtMaximum, SoeOptional},
|
||||
{sfCoverRateMinimum, SoeOptional},
|
||||
{sfCoverRateLiquidation, SoeOptional},
|
||||
{sfDomainID, SoeOptional},
|
||||
}))
|
||||
|
||||
/** This transaction deletes a Loan Broker */
|
||||
|
||||
@@ -335,6 +335,30 @@ public:
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfCoverRateLiquidation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfDomainID (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_UINT256::type::value_type>
|
||||
getDomainID() const
|
||||
{
|
||||
if (hasDomainID())
|
||||
return this->sle_->at(sfDomainID);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfDomainID is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasDomainID() const
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfDomainID);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -578,6 +602,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfDomainID (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
LoanBrokerBuilder&
|
||||
setDomainID(std::decay_t<typename SF_UINT256::type::value_type> const& value)
|
||||
{
|
||||
object_[sfDomainID] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the completed LoanBroker wrapper.
|
||||
* @param index The ledger entry index.
|
||||
|
||||
@@ -213,6 +213,32 @@ public:
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfCoverRateLiquidation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfDomainID (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_UINT256::type::value_type>
|
||||
getDomainID() const
|
||||
{
|
||||
if (hasDomainID())
|
||||
{
|
||||
return this->tx_->at(sfDomainID);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfDomainID is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasDomainID() const
|
||||
{
|
||||
return this->tx_->isFieldPresent(sfDomainID);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -336,6 +362,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfDomainID (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
LoanBrokerSetBuilder&
|
||||
setDomainID(std::decay_t<typename SF_UINT256::type::value_type> const& value)
|
||||
{
|
||||
object_[sfDomainID] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the LoanBrokerSet wrapper.
|
||||
* @param publicKey The public key for signing.
|
||||
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
LockedSociSession session = perf::measureDurationAndLog(
|
||||
[&]() { return LockedSociSession(session_, lock_); }, "checkoutDb", 10ms, j_);
|
||||
[&] { return LockedSociSession(session_, lock_); }, "checkoutDb", 10ms, j_);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ public:
|
||||
virtual bool
|
||||
unsubPeerStatus(std::uint64_t uListener) = 0;
|
||||
virtual void
|
||||
pubPeerStatus(std::function<json::Value(void)> const&) = 0;
|
||||
pubPeerStatus(std::function<json::Value()> const&) = 0;
|
||||
|
||||
virtual bool
|
||||
subConsensus(Ref ispListener) = 0;
|
||||
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
virtual bool
|
||||
isFull() = 0;
|
||||
virtual void
|
||||
setMode(OperatingMode om) = 0;
|
||||
setMode(OperatingMode om, char const* reason) = 0;
|
||||
virtual bool
|
||||
isBlocked() = 0;
|
||||
virtual bool
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
}
|
||||
|
||||
bool
|
||||
prepare(std::size_t bytes, std::function<void(void)>) override
|
||||
prepare(std::size_t bytes, std::function<void()>) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
* empty vector.
|
||||
*/
|
||||
virtual std::pair<boost::tribool, std::vector<boost::asio::const_buffer>>
|
||||
prepare(std::size_t bytes, std::function<void(void)> resume) = 0;
|
||||
prepare(std::size_t bytes, std::function<void()> resume) = 0;
|
||||
};
|
||||
|
||||
template <class Streambuf>
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
|
||||
std::pair<boost::tribool, std::vector<boost::asio::const_buffer>>
|
||||
prepare(std::size_t bytes, std::function<void(void)>) override
|
||||
prepare(std::size_t bytes, std::function<void()>) override
|
||||
{
|
||||
if (sb_.size() == 0)
|
||||
return {true, {}};
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
* @return `true` if the writer is ready to provide more data.
|
||||
*/
|
||||
virtual bool
|
||||
prepare(std::size_t bytes, std::function<void(void)> resume) = 0;
|
||||
prepare(std::size_t bytes, std::function<void()> resume) = 0;
|
||||
|
||||
/**
|
||||
* Returns a ConstBufferSequence representing the input sequence.
|
||||
|
||||
@@ -342,10 +342,10 @@ BaseHTTPPeer<Handler, Impl>::doWriter(
|
||||
bool keepAlive,
|
||||
YieldContext doYield)
|
||||
{
|
||||
std::function<void(void)> resume;
|
||||
std::function<void()> resume;
|
||||
{
|
||||
auto const p = impl().shared_from_this();
|
||||
resume = std::function<void(void)>([this, p, writer, keepAlive]() {
|
||||
resume = std::function<void()>([this, p, writer, keepAlive] {
|
||||
util::spawn(strand_, [p, writer, keepAlive](YieldContext doYield) {
|
||||
p->doWriter(writer, keepAlive, doYield);
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@ private:
|
||||
port_.protocol.contains("wss2") || port_.protocol.contains("peer")};
|
||||
bool plain_{
|
||||
port_.protocol.contains("http") || port_.protocol.contains("ws") ||
|
||||
(port_.protocol.contains("ws2"))};
|
||||
port_.protocol.contains("ws2")};
|
||||
static constexpr std::chrono::milliseconds kInitialAcceptDelay{50};
|
||||
static constexpr std::chrono::milliseconds kMaxAcceptDelay{2000};
|
||||
std::chrono::milliseconds acceptDelay_{kInitialAcceptDelay};
|
||||
|
||||
@@ -60,7 +60,7 @@ private:
|
||||
bool closed_ = false;
|
||||
std::condition_variable cv_;
|
||||
boost::container::flat_map<Work*, std::weak_ptr<Work>> map_;
|
||||
std::function<void(void)> f_;
|
||||
std::function<void()> f_;
|
||||
|
||||
public:
|
||||
IOList() = default;
|
||||
@@ -171,7 +171,7 @@ IOList::Work::destroy()
|
||||
{
|
||||
if (!ios_)
|
||||
return;
|
||||
std::function<void(void)> f;
|
||||
std::function<void()> f;
|
||||
{
|
||||
std::scoped_lock const lock(ios_->m_);
|
||||
ios_->map_.erase(this);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
|
||||
#include <xrpl/tx/invariants/VaultInvariant.h>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -139,7 +141,7 @@ public:
|
||||
*/
|
||||
class XRPNotCreated
|
||||
{
|
||||
std::int64_t drops_ = 0;
|
||||
boost::multiprecision::int128_t drops_ = 0;
|
||||
|
||||
public:
|
||||
void
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/MathUtilities.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -23,6 +25,7 @@
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -502,6 +505,46 @@ public:
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
/** @cond INTERNAL */
|
||||
template <class T>
|
||||
[[nodiscard]] std::optional<T>
|
||||
checkedStepAddOpt(T const& lhs, T const& rhs)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, XRPAmount>)
|
||||
{
|
||||
if (auto const r = checkedAdd(lhs.drops(), rhs.drops()))
|
||||
return XRPAmount{*r};
|
||||
return std::nullopt;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, MPTAmount>)
|
||||
{
|
||||
if (auto const r = checkedAdd(lhs.value(), rhs.value()))
|
||||
return MPTAmount{*r};
|
||||
return std::nullopt;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, IOUAmount>)
|
||||
{
|
||||
// IOUAmount is Number-backed and throws on overflow.
|
||||
return lhs + rhs;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A new amount type must decide explicitly how to add; do not fall back
|
||||
// to an unchecked add.
|
||||
static_assert(sizeof(T) == 0, "checkedStepAddOpt: unsupported amount type");
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
[[nodiscard]] T
|
||||
checkedStepAdd(T const& lhs, T const& rhs)
|
||||
{
|
||||
if (auto const r = checkedStepAddOpt(lhs, rhs))
|
||||
return *r;
|
||||
Throw<FlowException>(tecPATH_DRY);
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
/** @cond INTERNAL */
|
||||
// Check equal with tolerance
|
||||
bool
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
@@ -408,7 +407,7 @@ limitOut(
|
||||
if (!qf || qf->isConst())
|
||||
return remainingOut;
|
||||
|
||||
auto const out = [&]() {
|
||||
auto const out = [&] {
|
||||
auto const out = qf->outFromAvgQ(limitQuality);
|
||||
if (!out)
|
||||
return remainingOut;
|
||||
@@ -646,11 +645,21 @@ flow(
|
||||
boost::container::flat_multiset<TOutAmt> savedOuts;
|
||||
savedOuts.reserve(maxTries);
|
||||
|
||||
auto sum = [](auto const& col) {
|
||||
// Returns std::nullopt if the aggregate overflows; callers treat that as a
|
||||
// dry path.
|
||||
auto sum = [](auto const& col) -> std::optional<std::decay_t<decltype(*col.begin())>> {
|
||||
using TResult = std::decay_t<decltype(*col.begin())>;
|
||||
if (col.empty())
|
||||
return TResult{beast::kZero};
|
||||
return std::accumulate(col.begin() + 1, col.end(), *col.begin());
|
||||
TResult total = *col.begin();
|
||||
for (auto it = col.begin() + 1; it != col.end(); ++it)
|
||||
{
|
||||
auto const next = checkedStepAddOpt(total, *it);
|
||||
if (!next)
|
||||
return std::nullopt;
|
||||
total = *next;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
|
||||
// These offers only need to be removed if the payment is not
|
||||
@@ -670,7 +679,7 @@ flow(
|
||||
ammContext.setMultiPath(activeStrands.size() > 1);
|
||||
|
||||
// Limit only if one strand and limitQuality
|
||||
auto const limitRemainingOut = [&]() {
|
||||
auto const limitRemainingOut = [&] {
|
||||
if (activeStrands.size() == 1 && limitQuality)
|
||||
{
|
||||
if (auto const strand = activeStrands.get(0))
|
||||
@@ -749,9 +758,17 @@ flow(
|
||||
{
|
||||
savedIns.insert(best->in);
|
||||
savedOuts.insert(best->out);
|
||||
remainingOut = outReq - sum(savedOuts);
|
||||
auto const sumOut = sum(savedOuts);
|
||||
if (!sumOut)
|
||||
return {tecPATH_DRY, std::move(ofrsToRmOnFail)};
|
||||
remainingOut = outReq - *sumOut;
|
||||
if (sendMax)
|
||||
remainingIn = *sendMax - sum(savedIns);
|
||||
{
|
||||
auto const sumIn = sum(savedIns);
|
||||
if (!sumIn)
|
||||
return {tecPATH_DRY, std::move(ofrsToRmOnFail)};
|
||||
remainingIn = *sendMax - *sumIn;
|
||||
}
|
||||
|
||||
if (flowDebugInfo)
|
||||
{
|
||||
@@ -786,8 +803,12 @@ flow(
|
||||
break;
|
||||
}
|
||||
|
||||
auto const actualOut = sum(savedOuts);
|
||||
auto const actualIn = sum(savedIns);
|
||||
auto const actualOutOpt = sum(savedOuts);
|
||||
auto const actualInOpt = sum(savedIns);
|
||||
if (!actualOutOpt || !actualInOpt)
|
||||
return {tecPATH_DRY, std::move(ofrsToRmOnFail)};
|
||||
auto const actualOut = *actualOutOpt;
|
||||
auto const actualIn = *actualInOpt;
|
||||
|
||||
JLOG(j.trace()) << "Total flow: in: " << to_string(actualIn)
|
||||
<< " out: " << to_string(actualOut);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/Transactor.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -32,6 +33,9 @@ public:
|
||||
static std::vector<OptionaledField<STNumber>> const&
|
||||
getValueFields();
|
||||
|
||||
static std::uint32_t
|
||||
getFlagsMask(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ ENV GIT_SSL_CAINFO="/nix/ci-env/etc/ssl/certs/ca-bundle.crt"
|
||||
# Externally-built dynamically-linked ELF binaries hard-code the loader path
|
||||
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Install it
|
||||
# from the Nix store when the base image doesn't already provide one.
|
||||
COPY bin/default-loader-path.sh /tmp/loader-path.sh
|
||||
COPY bin/nix/default-loader-path.sh /usr/local/bin/default-loader-path.sh
|
||||
|
||||
RUN <<EOF
|
||||
target="$(/tmp/loader-path.sh)"
|
||||
target="$(/usr/local/bin/default-loader-path.sh)"
|
||||
|
||||
if [ ! -e "${target}" ]; then
|
||||
# Use the loader from the same glibc that gcc links libc against, so
|
||||
@@ -101,7 +101,7 @@ RUN if echo "${BASE_IMAGE}" | grep -qiE 'nixos'; then \
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
|
||||
# Sanity-check that the built binaries run correctly in the vanilla base image, with the necessary sanitizer runtime libraries installed.
|
||||
COPY bin/install-sanitizer-libs.sh /tmp/install-sanitizer-libs.sh
|
||||
COPY bin/install/sanitizer-libs.sh /tmp/install-sanitizer-libs.sh
|
||||
COPY nix/docker/test_files/cpp/run-binaries.sh /tmp/test_files/cpp/run-binaries.sh
|
||||
COPY nix/docker/test_files/rust/run-binaries.sh /tmp/test_files/rust/run-binaries.sh
|
||||
COPY --from=final /tmp/cpp-bins /tmp/cpp-bins
|
||||
|
||||
+15
-14
@@ -52,10 +52,10 @@ work without `ca-certificates` being installed in the base image.
|
||||
workspace with `cargo` to exercise proc-macro dylib loading.
|
||||
3. **`tester`** — Start again from a clean `BASE_IMAGE` (no Nix toolchain),
|
||||
install only the sanitizer runtime libraries
|
||||
([`install-sanitizer-libs.sh`](./install-sanitizer-libs.sh)), and run the
|
||||
binaries compiled in `final`. This proves the binaries built with the Nix
|
||||
toolchain actually run on a vanilla base image. On `nixos/nix` this step is
|
||||
skipped (the binaries are patched for a conventional FHS loader).
|
||||
([`bin/install/sanitizer-libs.sh`](../../bin/install/sanitizer-libs.sh)),
|
||||
and run the binaries compiled in `final`. This proves the binaries built with
|
||||
the Nix toolchain actually run on a vanilla base image. On `nixos/nix` this
|
||||
step is skipped (the binaries are patched for a conventional FHS loader).
|
||||
4. **Output** — The final image is gated on the tester succeeding: it copies a
|
||||
sentinel file out of `tester`, so a failed test run fails the whole build.
|
||||
|
||||
@@ -75,9 +75,10 @@ toolchain being present at runtime. Two pieces make that work:
|
||||
|
||||
- **An expected dynamic linker in the image.**
|
||||
Binaries built in Nix environments reference a dynamic linker from Nix store paths, which won't be present in the base image. However,
|
||||
[`bin/default-loader-path.sh`](../../bin/default-loader-path.sh) reports the
|
||||
[`bin/nix/default-loader-path.sh`](../../bin/nix/default-loader-path.sh) reports the
|
||||
expected loader path for the current architecture, so we can patch the binaries
|
||||
to use the correct loader.
|
||||
to use the correct loader. The image ships it as
|
||||
`/usr/local/bin/default-loader-path.sh`.
|
||||
|
||||
The build then verifies all of this end to end, and the C++ and Rust programs
|
||||
go through the same pipeline: each is compiled in `final`, has its `PT_INTERP`
|
||||
@@ -91,11 +92,11 @@ whose resulting binary is patched and run like the others.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [`./Dockerfile`](./Dockerfile) | Multi-stage build described above. |
|
||||
| [`./test_files/cpp/`](./test_files/cpp) | C++ sanitizer smoke test: sources + compile/run scripts. |
|
||||
| [`./test_files/rust/`](./test_files/rust) | Rust smoke test: rustc sources + a cargo proc-macro workspace + compile/run scripts. |
|
||||
| [`/bin/check-tools.sh`](../../bin/check-tools.sh) | Verify every expected tools are present and runnable. |
|
||||
| [`/bin/default-loader-path.sh`](../../bin/default-loader-path.sh) | Print the dynamic-linker (`PT_INTERP`) path for the current architecture. |
|
||||
| [`/bin/install-sanitizer-libs.sh`](../../bin/install-sanitizer-libs.sh) | Install `libasan`/`libtsan`/`libubsan` runtimes on the supported base images. |
|
||||
| File | Purpose |
|
||||
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [`./Dockerfile`](./Dockerfile) | Multi-stage build described above. |
|
||||
| [`./test_files/cpp/`](./test_files/cpp) | C++ sanitizer smoke test: sources + compile/run scripts. |
|
||||
| [`./test_files/rust/`](./test_files/rust) | Rust smoke test: rustc sources + a cargo proc-macro workspace + compile/run scripts. |
|
||||
| [`/bin/check-tools.sh`](../../bin/check-tools.sh) | Verify every expected tools are present and runnable. |
|
||||
| [`/bin/nix/default-loader-path.sh`](../../bin/nix/default-loader-path.sh) | Print the dynamic-linker (`PT_INTERP`) path for the current architecture. |
|
||||
| [`/bin/install/sanitizer-libs.sh`](../../bin/install/sanitizer-libs.sh) | Install `libasan`/`libtsan`/`libubsan` runtimes on the supported base images. |
|
||||
@@ -8,7 +8,7 @@ set -eo pipefail
|
||||
src_dir="${1:?usage: $0 <src_dir> <dst_dir>}"
|
||||
dst_dir="${2:?usage: $0 <src_dir> <dst_dir>}"
|
||||
|
||||
loader="$(/tmp/loader-path.sh)"
|
||||
loader="$(/usr/local/bin/default-loader-path.sh)"
|
||||
|
||||
mkdir -p "${dst_dir}"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ set -eo pipefail
|
||||
src_dir="${1:?usage: $0 <src_dir> <dst_dir>}"
|
||||
dst_dir="${2:?usage: $0 <src_dir> <dst_dir>}"
|
||||
|
||||
loader="$(/tmp/loader-path.sh)"
|
||||
loader="$(/usr/local/bin/default-loader-path.sh)"
|
||||
|
||||
mkdir -p "${dst_dir}"
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ package/
|
||||
sign_rpm.py Signs the built RPMs (called by CI when publishing)
|
||||
images/
|
||||
packaging/
|
||||
Dockerfile Packaging image, built by `build-packaging-images.yml`; installs its tooling with `bin/install-packaging-tools.sh`
|
||||
Dockerfile Packaging image, built by `build-packaging-images.yml`; installs its tooling with `bin/install/packaging-tools.sh`
|
||||
publish_pkg.py Uploads built packages to the XRPLF Nexus repositories (called by CI, and shipped in that image)
|
||||
xrpld/
|
||||
Dockerfile The xrpld Docker images, installing the built DEB on Ubuntu (see "Docker images")
|
||||
|
||||
@@ -2,7 +2,7 @@ ARG BASE_IMAGE=debian:trixie
|
||||
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
RUN --mount=type=bind,source=bin/install-packaging-tools.sh,target=/install-packaging-tools.sh \
|
||||
RUN --mount=type=bind,source=bin/install/packaging-tools.sh,target=/install-packaging-tools.sh \
|
||||
/install-packaging-tools.sh
|
||||
|
||||
# See package/README.md, "Publishing from other repositories".
|
||||
|
||||
@@ -130,6 +130,13 @@ unsigned-integer-overflow:__chrono/duration.h
|
||||
# distinct header from the bits/ directory so it needs its own entry.
|
||||
unsigned-integer-overflow:include/c++/*/bit
|
||||
|
||||
# libstdc++ <format> takes the magnitude of a negative integer with
|
||||
# -static_cast<make_unsigned_t<T>>(v), which wraps by design for the most
|
||||
# negative value (std::format("{}", INT_MIN)). std::to_string avoids the report
|
||||
# only because it spells the same thing (unsigned)~v + 1u. Like <bit>, <format>
|
||||
# is a top-level header rather than one under bits/.
|
||||
unsigned-integer-overflow:include/c++/*/format
|
||||
|
||||
# =============================================================================
|
||||
# Rippled code suppressions
|
||||
# =============================================================================
|
||||
|
||||
@@ -259,7 +259,7 @@ Logs::format(
|
||||
|
||||
output = xrpl::to_string(std::chrono::system_clock::now());
|
||||
|
||||
output += " ";
|
||||
output += ' ';
|
||||
if (!partition.empty())
|
||||
output += partition + ":";
|
||||
|
||||
|
||||
@@ -1557,7 +1557,7 @@ root(Number f, unsigned d)
|
||||
// Scale f into the range (0, 1) such that f's exponent is a multiple of d
|
||||
auto e = f.exponent_ + Number::mantissaLog() + 1;
|
||||
auto const di = static_cast<int>(d);
|
||||
auto ex = [e = e, di = di]() // Euclidean remainder of e/d
|
||||
auto ex = [e = e, di = di] // Euclidean remainder of e/d
|
||||
{
|
||||
int const k = (e >= 0 ? e : e - (di - 1)) / di;
|
||||
int const k2 = e - (k * di);
|
||||
|
||||
@@ -94,7 +94,7 @@ initAnonymous(boost::asio::ssl::context& context)
|
||||
{
|
||||
using namespace openssl;
|
||||
|
||||
static auto kDefaultRsa = []() {
|
||||
static auto kDefaultRsa = [] {
|
||||
BIGNUM* bn = BN_new();
|
||||
BN_set_word(bn, RSA_F4);
|
||||
|
||||
@@ -111,7 +111,7 @@ initAnonymous(boost::asio::ssl::context& context)
|
||||
return rsa;
|
||||
}();
|
||||
|
||||
static auto kDefaultEphemeralPrivateKey = []() {
|
||||
static auto kDefaultEphemeralPrivateKey = [] {
|
||||
auto pkey = EVP_PKEY_new();
|
||||
|
||||
if (!pkey)
|
||||
@@ -128,7 +128,7 @@ initAnonymous(boost::asio::ssl::context& context)
|
||||
return pkey;
|
||||
}();
|
||||
|
||||
static auto kDefaultCert = []() {
|
||||
static auto kDefaultCert = [] {
|
||||
auto x509 = X509_new();
|
||||
|
||||
if (x509 == nullptr)
|
||||
|
||||
@@ -22,7 +22,7 @@ printIdentifiers(SemanticVersion::IdentifierList const& list)
|
||||
for (auto const& x : list)
|
||||
{
|
||||
if (!ret.empty())
|
||||
ret += ".";
|
||||
ret += '.';
|
||||
ret += x;
|
||||
}
|
||||
|
||||
@@ -219,13 +219,13 @@ SemanticVersion::print() const
|
||||
|
||||
if (!preReleaseIdentifiers.empty())
|
||||
{
|
||||
s += "-";
|
||||
s += '-';
|
||||
s += printIdentifiers(preReleaseIdentifiers);
|
||||
}
|
||||
|
||||
if (!metaData.empty())
|
||||
{
|
||||
s += "+";
|
||||
s += '+';
|
||||
s += printIdentifiers(metaData);
|
||||
}
|
||||
|
||||
|
||||
@@ -844,7 +844,7 @@ Reader::addErrorAndRecover(std::string const& message, Token& token, TokenType s
|
||||
Value&
|
||||
Reader::currentValue()
|
||||
{
|
||||
return *(nodes_.top());
|
||||
return *nodes_.top();
|
||||
}
|
||||
|
||||
Reader::Char
|
||||
|
||||
@@ -111,7 +111,7 @@ Value::CZString::CZString(CZString const& other)
|
||||
other.cstr_ != nullptr
|
||||
? valueAllocator()->makeMemberName(other.cstr_)
|
||||
: other.cstr_)
|
||||
, index_([&]() -> int {
|
||||
, index_([&] -> int {
|
||||
if (!other.cstr_)
|
||||
return other.index_;
|
||||
return other.index_ == static_cast<int>(DuplicationPolicy::NoDuplication)
|
||||
@@ -940,7 +940,7 @@ Value::resolveReference(char const* key, bool isStatic)
|
||||
Value
|
||||
Value::get(UInt index, Value const& defaultValue) const
|
||||
{
|
||||
Value const* value = &((*this)[index]);
|
||||
Value const* value = &(*this)[index];
|
||||
return value == &kNull ? defaultValue : *value;
|
||||
}
|
||||
|
||||
@@ -1008,7 +1008,7 @@ Value::append(Value&& value)
|
||||
Value
|
||||
Value::get(char const* key, Value const& defaultValue) const
|
||||
{
|
||||
Value const* value = &((*this)[key]);
|
||||
Value const* value = &(*this)[key];
|
||||
return value == &kNull ? defaultValue : *value;
|
||||
}
|
||||
|
||||
@@ -1051,7 +1051,7 @@ Value::isMember(char const* key) const
|
||||
if (type_ != ValueType::Object)
|
||||
return false;
|
||||
|
||||
Value const* value = &((*this)[key]);
|
||||
Value const* value = &(*this)[key];
|
||||
return value != &kNull;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ valueToQuotedString(char const* value)
|
||||
unsigned const maxsize = (strlen(value) * 2) + 3; // all-escaped+quotes+NULL
|
||||
std::string result;
|
||||
result.reserve(maxsize); // to avoid lots of mallocs
|
||||
result += "\"";
|
||||
result += '"';
|
||||
|
||||
for (char const* c = value; *c != 0; ++c)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ valueToQuotedString(char const* value)
|
||||
}
|
||||
}
|
||||
|
||||
result += "\"";
|
||||
result += '"';
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -213,38 +213,38 @@ FastWriter::writeValue(Value const& value)
|
||||
break;
|
||||
|
||||
case ValueType::Array: {
|
||||
document_ += "[";
|
||||
document_ += '[';
|
||||
int const size = value.size();
|
||||
|
||||
for (int index = 0; index < size; ++index)
|
||||
{
|
||||
if (index > 0)
|
||||
document_ += ",";
|
||||
document_ += ',';
|
||||
|
||||
writeValue(value[index]);
|
||||
}
|
||||
|
||||
document_ += "]";
|
||||
document_ += ']';
|
||||
}
|
||||
break;
|
||||
|
||||
case ValueType::Object: {
|
||||
Value::Members members(value.getMemberNames());
|
||||
document_ += "{";
|
||||
document_ += '{';
|
||||
|
||||
for (auto it = members.begin(); it != members.end(); ++it)
|
||||
{
|
||||
std::string const& name = *it;
|
||||
|
||||
if (it != members.begin())
|
||||
document_ += ",";
|
||||
document_ += ',';
|
||||
|
||||
document_ += valueToQuotedString(name.c_str());
|
||||
document_ += ":";
|
||||
document_ += ':';
|
||||
writeValue(value[name]);
|
||||
}
|
||||
|
||||
document_ += "}";
|
||||
document_ += '}';
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ StyledWriter::write(Value const& root)
|
||||
addChildValues_ = false;
|
||||
indentString_ = "";
|
||||
writeValue(root);
|
||||
document_ += "\n";
|
||||
document_ += '\n';
|
||||
return document_;
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ StyledWriter::writeValue(Value const& value)
|
||||
if (++it; it == members.end())
|
||||
break;
|
||||
|
||||
document_ += ",";
|
||||
document_ += ',';
|
||||
}
|
||||
|
||||
unindent();
|
||||
@@ -371,7 +371,7 @@ StyledWriter::writeArrayValue(Value const& value)
|
||||
if (++index == size)
|
||||
break;
|
||||
|
||||
document_ += ",";
|
||||
document_ += ',';
|
||||
}
|
||||
|
||||
unindent();
|
||||
|
||||
@@ -27,7 +27,7 @@ CachedViewImpl::read(Keylet const& k) const
|
||||
bool cacheHit = false;
|
||||
bool baseRead = false;
|
||||
|
||||
auto const digest = [&]() -> std::optional<UInt256> {
|
||||
auto const digest = [&] -> std::optional<UInt256> {
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
auto const iter = map_.find(k.key);
|
||||
@@ -41,7 +41,7 @@ CachedViewImpl::read(Keylet const& k) const
|
||||
}();
|
||||
if (!digest)
|
||||
return nullptr;
|
||||
auto sle = cache_.fetch(*digest, [&]() {
|
||||
auto sle = cache_.fetch(*digest, [&] {
|
||||
baseRead = true;
|
||||
return base_.read(k);
|
||||
});
|
||||
|
||||
@@ -213,7 +213,7 @@ adjustAmountsByLPTokens(
|
||||
|
||||
if (lpTokensActual < lpTokens)
|
||||
{
|
||||
bool const ammRoundingEnabled = [&]() {
|
||||
bool const ammRoundingEnabled = [&] {
|
||||
if (auto const& rules = getCurrentTransactionRules();
|
||||
rules && rules->enabled(fixAMMv1_1))
|
||||
return true;
|
||||
@@ -238,7 +238,7 @@ adjustAmountsByLPTokens(
|
||||
}
|
||||
|
||||
// Single trade
|
||||
auto const amountActual = [&]() {
|
||||
auto const amountActual = [&] {
|
||||
if (isDeposit == IsDeposit::Yes)
|
||||
{
|
||||
return ammAssetIn(amountBalance, lptAMMBalance, lpTokensActual, tfee);
|
||||
@@ -481,7 +481,7 @@ ammHolds(
|
||||
AuthHandling authHandling,
|
||||
beast::Journal const j)
|
||||
{
|
||||
auto const assets = [&]() -> std::optional<std::pair<Asset, Asset>> {
|
||||
auto const assets = [&] -> std::optional<std::pair<Asset, Asset>> {
|
||||
auto const asset1 = ammSle[sfAsset];
|
||||
auto const asset2 = ammSle[sfAsset2];
|
||||
if (optAsset1 && optAsset2)
|
||||
|
||||
@@ -522,7 +522,7 @@ pseudoAccountAddress(ReadView const& view, UInt256 const& pseudoOwnerKey)
|
||||
[[nodiscard]] std::vector<SField const*> const&
|
||||
getPseudoAccountFields()
|
||||
{
|
||||
static std::vector<SField const*> const kPseudoFields = []() {
|
||||
static std::vector<SField const*> const kPseudoFields = [] {
|
||||
auto const ar = LedgerFormats::getInstance().findByType(ltACCOUNT_ROOT);
|
||||
if (!ar)
|
||||
{
|
||||
|
||||
@@ -744,7 +744,7 @@ tryOverpayment(
|
||||
// Calculate what the new loan state should be with the new periodic payment,
|
||||
// including the preserved rounding errors.
|
||||
|
||||
auto const newTheoreticalState = [&]() {
|
||||
auto const newTheoreticalState = [&] {
|
||||
auto const state = computeTheoreticalLoanState(
|
||||
rules,
|
||||
newLoanProperties.periodicPayment,
|
||||
@@ -2179,7 +2179,7 @@ computeLoanProperties(
|
||||
auto const periodicPayment =
|
||||
detail::loanPeriodicPayment(rules, principalOutstanding, periodicRate, paymentsRemaining);
|
||||
|
||||
auto const [totalValueOutstanding, loanScale] = [&]() {
|
||||
auto const [totalValueOutstanding, loanScale] = [&] {
|
||||
// only round up if there should be interest
|
||||
NumberRoundModeGuard const mg(
|
||||
periodicRate == 0 ? Number::RoundingMode::ToNearest : Number::RoundingMode::Upward);
|
||||
@@ -2221,7 +2221,7 @@ computeLoanProperties(
|
||||
// Compute the principal part of the first payment. This is needed
|
||||
// because the principal part may be rounded down to zero, which
|
||||
// would prevent the principal from ever being paid down.
|
||||
auto const firstPaymentPrincipal = [&]() {
|
||||
auto const firstPaymentPrincipal = [&] {
|
||||
// Compute the parts for the first payment. Ensure that the
|
||||
// principal payment will actually change the principal.
|
||||
auto const startingState = computeTheoreticalLoanState(
|
||||
|
||||
@@ -500,7 +500,7 @@ enforceMPTokenAuthorization(
|
||||
auto const sleToken = ctx.view.read(keylet); // NOTE: might be null
|
||||
auto const maybeDomainID = sleIssuance->at(~sfDomainID);
|
||||
bool expired = false;
|
||||
bool const authorizedByDomain = [&]() -> bool {
|
||||
bool const authorizedByDomain = [&] -> bool {
|
||||
// NOTE: defensive here, should be checked in preclaim
|
||||
if (!maybeDomainID.has_value())
|
||||
return false; // LCOV_EXCL_LINE
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/MathUtilities.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
@@ -1157,6 +1158,10 @@ accountSendMultiIOU(
|
||||
|
||||
if (receiver)
|
||||
{
|
||||
// Confirm the running debit will not overflow before crediting.
|
||||
if (!checkedAdd(takeFromSender.xrp().drops(), amount.xrp().drops()))
|
||||
return tecINTERNAL;
|
||||
|
||||
// Increment XRP balance.
|
||||
auto const rcvBal = receiver->getFieldAmount(sfBalance);
|
||||
receiver->setFieldAmount(sfBalance, rcvBal + amount);
|
||||
@@ -1164,7 +1169,7 @@ accountSendMultiIOU(
|
||||
|
||||
view.update(receiver);
|
||||
|
||||
// Take what is actually sent
|
||||
// Take what is actually sent.
|
||||
takeFromSender += amount;
|
||||
}
|
||||
|
||||
@@ -1457,6 +1462,8 @@ directSendNoLimitMultiMPT(
|
||||
}
|
||||
|
||||
// Direct send: redeeming MPTs and/or sending own MPTs.
|
||||
if (!checkedAdd(actual.mpt().value(), amount.mpt().value()))
|
||||
return tecINTERNAL;
|
||||
if (auto const ter = directSendNoFeeMPT(view, senderID, receiverID, amount, j);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
@@ -1484,6 +1491,10 @@ directSendNoLimitMultiMPT(
|
||||
actualSend = multiply(amount, rate);
|
||||
}
|
||||
}
|
||||
// actual is a superset of takeFromSender, so checking it before both add
|
||||
// sites also protects the debit accumulator.
|
||||
if (!checkedAdd(actual.mpt().value(), actualSend.mpt().value()))
|
||||
return tecINTERNAL;
|
||||
actual += actualSend;
|
||||
takeFromSender += actualSend;
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB)
|
||||
{
|
||||
Batch batch;
|
||||
batch.reserve(kBatchWritePreallocationSize);
|
||||
auto storeBatch = [&, fname = __func__]() {
|
||||
auto storeBatch = [&, fname = __func__] {
|
||||
try
|
||||
{
|
||||
dstBackend.storeBatch(batch);
|
||||
|
||||
@@ -249,7 +249,7 @@ FeatureCollections::registerFeature(std::string const& name, Supported support,
|
||||
|
||||
features_.emplace_back(name, f);
|
||||
|
||||
auto const getAmendmentSupport = [=]() {
|
||||
auto const getAmendmentSupport = [=] {
|
||||
if (vote == VoteBehavior::Obsolete)
|
||||
return AmendmentSupport::Retired;
|
||||
return support == Supported::Yes ? AmendmentSupport::Supported
|
||||
|
||||
@@ -240,8 +240,7 @@ skip(LedgerIndex ledger) noexcept
|
||||
{
|
||||
return {
|
||||
ltLEDGER_HASHES,
|
||||
indexHash(
|
||||
LedgerNameSpace::SkipList, std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
|
||||
indexHash(LedgerNameSpace::SkipList, static_cast<std::uint32_t>(ledger) >> 16)};
|
||||
}
|
||||
|
||||
Keylet const&
|
||||
|
||||
@@ -182,7 +182,7 @@ InnerObjectFormats::findSOTemplateBySField(SField const& sField) const
|
||||
{
|
||||
auto itemPtr = findByType(sField.getCode());
|
||||
if (itemPtr != nullptr)
|
||||
return &(itemPtr->getSOTemplate());
|
||||
return &itemPtr->getSOTemplate();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@ Issue::getText() const
|
||||
|
||||
if (!isXRP(currency))
|
||||
{
|
||||
ret += "/";
|
||||
ret += '/';
|
||||
|
||||
if (isXRP(account))
|
||||
{
|
||||
ret += "0";
|
||||
ret += '0';
|
||||
}
|
||||
else if (account == noAccount())
|
||||
{
|
||||
ret += "1";
|
||||
ret += '1';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ setCurrentTransactionRules(std::optional<Rules> r)
|
||||
// the value is needed. That could get expensive fast.
|
||||
|
||||
// Declare the range this way to keep clang-tidy from complaining
|
||||
auto const range = [&r]() {
|
||||
auto const range = [&r] {
|
||||
// If any new conditions with new amendments are added to "enableLargeNumbers", those
|
||||
// amendments must also be added to useRulesGuards.
|
||||
bool const enableLargeNumbers = !r ||
|
||||
|
||||
@@ -111,7 +111,7 @@ SField::getField(int code)
|
||||
|
||||
if (it != knownCodeToField.end())
|
||||
{
|
||||
return *(it->second);
|
||||
return *it->second;
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ SField::getField(std::string const& fieldName)
|
||||
|
||||
if (it != knownNameToField.end())
|
||||
{
|
||||
return *(it->second);
|
||||
return *it->second;
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
@@ -864,7 +864,7 @@ STAmount::canonicalize()
|
||||
{
|
||||
Throw<std::runtime_error>("Native currency amount out of range");
|
||||
}
|
||||
else if (!native() && value_ > kMaxMpTokenAmount)
|
||||
if (!native() && value_ > kMaxMpTokenAmount)
|
||||
{
|
||||
Throw<std::runtime_error>("MPT amount out of range");
|
||||
}
|
||||
@@ -927,7 +927,7 @@ amountFromJson(SField const& name, json::Value const& v)
|
||||
{
|
||||
Throw<std::runtime_error>("XRP may not be specified with a null Json value");
|
||||
}
|
||||
else if (v.isObject())
|
||||
if (v.isObject())
|
||||
{
|
||||
if (!validJSONAsset(v))
|
||||
Throw<std::runtime_error>("Invalid Asset's Json specification");
|
||||
@@ -1590,7 +1590,7 @@ mulRoundImpl(STAmount const& v1, STAmount const& v2, Asset const& asset, bool ro
|
||||
{
|
||||
CanonicalizeFunc(asset.integral(), amount, offset, roundUp);
|
||||
}
|
||||
STAmount result = [&]() {
|
||||
STAmount result = [&] {
|
||||
// If appropriate, tell Number to round down. This gives the desired
|
||||
// result from STAmount::canonicalize.
|
||||
MightSaveRound const savedRound(Number::RoundingMode::TowardsZero);
|
||||
@@ -1695,7 +1695,7 @@ divRoundImpl(STAmount const& num, STAmount const& den, Asset const& asset, bool
|
||||
if (resultNegative != roundUp)
|
||||
canonicalizeRound(asset.integral(), amount, offset, roundUp);
|
||||
|
||||
STAmount result = [&]() {
|
||||
STAmount result = [&] {
|
||||
// If appropriate, tell Number the rounding mode we are using.
|
||||
// Note that "roundUp == true" actually means "round away from zero".
|
||||
// Otherwise, round toward zero.
|
||||
|
||||
@@ -98,13 +98,13 @@ STArray::getFullText() const
|
||||
for (auto const& obj : v_)
|
||||
{
|
||||
if (!first)
|
||||
r += ",";
|
||||
r += ',';
|
||||
|
||||
r += obj.getFullText();
|
||||
first = false;
|
||||
}
|
||||
|
||||
r += "]";
|
||||
r += ']';
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -117,13 +117,13 @@ STArray::getText() const
|
||||
for (STObject const& o : v_)
|
||||
{
|
||||
if (!first)
|
||||
r += ",";
|
||||
r += ',';
|
||||
|
||||
r += o.getText();
|
||||
first = false;
|
||||
}
|
||||
|
||||
r += "]";
|
||||
r += ']';
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ STLedgerEntry::getFullText() const
|
||||
ret += format->getName();
|
||||
ret += ", ";
|
||||
ret += STObject::getFullText();
|
||||
ret += "}";
|
||||
ret += '}';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ partsFromString(std::string const& number)
|
||||
{
|
||||
// integer and fraction
|
||||
mantissa = boost::lexical_cast<std::uint64_t>(match[2] + match[4]);
|
||||
exponent = -(match[4].length());
|
||||
exponent = -match[4].length();
|
||||
}
|
||||
|
||||
if (match[5].matched)
|
||||
|
||||
@@ -262,7 +262,7 @@ STObject::set(SerialIter& sit, int depth, bool requireCanonicalOrder)
|
||||
v_.emplace_back(sit, fn, depth + 1);
|
||||
|
||||
// If the object type has a known SOTemplate then set it.
|
||||
if (auto const obj = dynamic_cast<STObject*>(&(v_.back().get())))
|
||||
if (auto const obj = dynamic_cast<STObject*>(&v_.back().get()))
|
||||
obj->applyTemplateFromSField(fn); // May throw
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ STObject::getFullText() const
|
||||
}
|
||||
}
|
||||
|
||||
ret += "}";
|
||||
ret += '}';
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ STObject::getText() const
|
||||
|
||||
ret += elem->getText();
|
||||
}
|
||||
ret += "}";
|
||||
ret += '}';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ STTx::getFullText() const
|
||||
ret += to_string(getTransactionID());
|
||||
ret += "\" = {";
|
||||
ret += STObject::getFullText();
|
||||
ret += "}";
|
||||
ret += '}';
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -739,7 +739,7 @@ isMemoOkay(STObject const& st, std::string& reason)
|
||||
// The only allowed characters for MemoType and MemoFormat are the
|
||||
// characters allowed in URLs per RFC 3986: alphanumerics and the
|
||||
// following symbols: -._~:/?#[]@!$&'()*+,;=%
|
||||
static constexpr std::array<char, 256> const kAllowedSymbols = []() {
|
||||
static constexpr std::array<char, 256> const kAllowedSymbols = [] {
|
||||
std::array<char, 256> a{};
|
||||
|
||||
std::string_view const symbols(
|
||||
|
||||
@@ -136,7 +136,7 @@ template <typename... Args>
|
||||
void
|
||||
STVar::constructST(SerializedTypeID id, int depth, Args&&... args)
|
||||
{
|
||||
auto constructWithDepth = [&]<typename T>() {
|
||||
auto constructWithDepth = [&]<typename T> {
|
||||
if constexpr (std::is_same_v<std::tuple<std::remove_cvref_t<Args>...>, std::tuple<SField>>)
|
||||
{
|
||||
construct<T>(std::forward<Args>(args)...);
|
||||
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
operator()(std::size_t ordinal) const
|
||||
{
|
||||
// Generates Nth secret key:
|
||||
auto gsk = [this, tweak = calculateTweak(ordinal)]() {
|
||||
auto gsk = [this, tweak = calculateTweak(ordinal)] {
|
||||
auto rpk = root_;
|
||||
|
||||
if (secp256k1_ec_seckey_tweak_add(secp256k1Context(), rpk.data(), tweak.data()) == 1)
|
||||
|
||||
@@ -226,7 +226,7 @@ TxMeta::getAffectedNode(UInt256 const& node)
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("xrpl::TxMeta::getAffectedNode(UInt256) : node not found");
|
||||
Throw<std::runtime_error>("Affected node not found");
|
||||
return *(nodes_.begin()); // Silence compiler warning.
|
||||
return *nodes_.begin(); // Silence compiler warning.
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace xrpl {
|
||||
static constexpr char const* kAlphabetForward =
|
||||
"rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz";
|
||||
|
||||
static constexpr std::array<int, 256> const kAlphabetReverse = []() {
|
||||
static constexpr std::array<int, 256> const kAlphabetReverse = [] {
|
||||
std::array<int, 256> map{};
|
||||
for (auto& m : map)
|
||||
m = -1;
|
||||
@@ -226,7 +226,7 @@ encodeBase58(void const* message, std::size_t size, void* temp, std::size_t temp
|
||||
// Apply "b58 = b58 * 256 + ch".
|
||||
for (auto iter = b58end; iter != b58begin; --iter)
|
||||
{
|
||||
carry += 256 * (iter[-1]);
|
||||
carry += 256 * iter[-1];
|
||||
iter[-1] = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
@@ -378,7 +378,7 @@ b256ToB58Be(std::span<std::uint8_t const> input, std::span<std::uint8_t> out)
|
||||
// Allocate enough base 2^64 coeff for encoding 38 bytes
|
||||
// log(2^(38*8),2^64)) ~= 4.75. So 5 coeff are enough
|
||||
std::array<std::uint64_t, 5> base264CoeffBuf{};
|
||||
std::span<std::uint64_t> const base264Coeff = [&]() -> std::span<std::uint64_t> {
|
||||
std::span<std::uint64_t> const base264Coeff = [&] -> std::span<std::uint64_t> {
|
||||
// convert input from big endian to native u64, lowest coeff first
|
||||
std::size_t numCoeff = 0;
|
||||
for (int i = 0; i < base264CoeffBuf.size(); ++i)
|
||||
@@ -505,13 +505,13 @@ b58ToB256Be(std::string_view input, std::span<std::uint8_t> out)
|
||||
// (33 bytes for nodepublic + 1 byte token + 4 bytes checksum)
|
||||
// log(2^(38*8),58^10)) ~= 5.18. So 6 coeff are enough
|
||||
std::array<std::uint64_t, 6> b5810Coeff{};
|
||||
auto [num_full_coeffs, partial_coeff_len] = xrpl::b58_fast::detail::divRem(input.size(), 10);
|
||||
auto const numPartialCoeffs = (partial_coeff_len != 0u) ? 1 : 0;
|
||||
auto const numB5810Coeffs = num_full_coeffs + numPartialCoeffs;
|
||||
auto [numFullCoeffs, partialCoeffLen] = xrpl::b58_fast::detail::divRem(input.size(), 10);
|
||||
auto const numPartialCoeffs = (partialCoeffLen != 0u) ? 1 : 0;
|
||||
auto const numB5810Coeffs = numFullCoeffs + numPartialCoeffs;
|
||||
XRPL_ASSERT(
|
||||
numB5810Coeffs <= b5810Coeff.size(),
|
||||
"xrpl::b58_fast::detail::b58_to_b256_be : maximum coeff");
|
||||
for (unsigned char const c : input.substr(0, partial_coeff_len))
|
||||
for (unsigned char const c : input.substr(0, partialCoeffLen))
|
||||
{
|
||||
auto curVal = ::xrpl::kAlphabetReverse[c];
|
||||
if (curVal < 0)
|
||||
@@ -523,9 +523,9 @@ b58ToB256Be(std::string_view input, std::span<std::uint8_t> out)
|
||||
}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
for (int j = 0; j < num_full_coeffs; ++j)
|
||||
for (int j = 0; j < numFullCoeffs; ++j)
|
||||
{
|
||||
unsigned char const c = input[partial_coeff_len + (j * 10) + i];
|
||||
unsigned char const c = input[partialCoeffLen + (j * 10) + i];
|
||||
auto curVal = ::xrpl::kAlphabetReverse[c];
|
||||
if (curVal < 0)
|
||||
{
|
||||
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
// There is a separate check in `checkpoint` for a valid
|
||||
// connection in the rare case when the DatabaseCon is destroyed
|
||||
// after locking this weak_ptr
|
||||
[wp = std::weak_ptr<Checkpointer>{shared_from_this()}]() {
|
||||
[wp = std::weak_ptr<Checkpointer>{shared_from_this()}] {
|
||||
if (auto self = wp.lock())
|
||||
self->checkpoint();
|
||||
}))
|
||||
|
||||
Loaded 100 of 329 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user