Compare commits

..

12 Commits

361 changed files with 4487 additions and 7947 deletions

View File

@@ -5,10 +5,7 @@ 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,
@@ -17,7 +14,6 @@ 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,
@@ -36,7 +32,6 @@ Checks: "-*,
llvm-namespace-comment,
misc-*,
-misc-explicit-constructor,
-misc-multiple-inheritance,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
@@ -50,8 +45,6 @@ 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-*,
@@ -60,7 +53,6 @@ Checks: "-*,
-performance-noexcept-move-constructor,
-performance-unnecessary-copy-initialization,
-performance-unnecessary-value-param,
-performance-use-std-move,
readability-*,
-readability-avoid-const-params-in-decls,
@@ -73,11 +65,7 @@ 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
"
# ---
@@ -93,10 +81,6 @@ 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

View File

@@ -15,9 +15,9 @@ inputs:
required: false
default: "false"
log_verbosity:
description: 'The logging verbosity ("quiet", "verbose"), or empty to use the Conan defaults.'
description: "The logging verbosity."
required: false
default: ""
default: "verbose"
sanitizers:
description: "The sanitizers to enable."
required: false
@@ -35,16 +35,6 @@ 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}" \
@@ -52,7 +42,8 @@ runs:
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
"${VERBOSITY_ARGS[@]}" \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
--format=json \
. >"${RUNNER_TEMP}/conan-graph.json"
@@ -61,4 +52,4 @@ runs:
- 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"
run: ./bin/check-build-context-runtime.sh "${RUNNER_TEMP}/conan-graph.json"

View File

@@ -75,6 +75,7 @@ test.app > xrpl.json
test.app > xrpl.ledger
test.app > xrpl.nodestore
test.app > xrpl.protocol
test.app > xrpl.rdb
test.app > xrpl.resource
test.app > xrpl.server
test.app > xrpl.shamap
@@ -174,7 +175,6 @@ test.server > xrpl.basics
test.server > xrpl.config
test.server > xrpld.app
test.server > xrpld.core
test.server > xrpld.rpc
test.server > xrpl.json
test.server > xrpl.protocol
test.server > xrpl.server

View File

@@ -12,7 +12,7 @@ on:
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "!nix/check-tools/**"
- "bin/nix/default-loader-path.sh"
- "bin/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/nix/default-loader-path.sh"
- "bin/install/sanitizer-libs.sh"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
workflow_dispatch:
concurrency:

View File

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

View File

@@ -93,8 +93,9 @@ jobs:
.github/workflows/reusable-upload-recipe.yml
.clang-tidy
.codecov.yml
bin/check-nix-store-refs.sh
bin/check-tools.sh
bin/nix/**
bin/default-loader-path.sh
cfg/**
cmake/**
conan/**

View File

@@ -31,8 +31,9 @@ on:
- ".github/workflows/reusable-upload-recipe.yml"
- ".clang-tidy"
- ".codecov.yml"
- "bin/check-nix-store-refs.sh"
- "bin/check-tools.sh"
- "bin/nix/**"
- "bin/default-loader-path.sh"
- "cfg/**"
- "cmake/**"
- "conan/**"

View File

@@ -186,6 +186,9 @@ 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
@@ -254,20 +257,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/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)
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
# 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/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"
./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"
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}

View File

@@ -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-3d526d4"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-ed96e60"
permissions:
contents: read
issues: write
@@ -73,6 +73,7 @@ jobs:
with:
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ env.BUILD_TYPE }}
log_verbosity: verbose
- name: Configure CMake
working-directory: ${{ env.BUILD_DIR }}

View File

@@ -108,11 +108,14 @@ 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/nix/check-nix-store-refs.sh "${CONAN_HOME}"
run: ./bin/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') }}

View File

@@ -22,23 +22,13 @@ API version 2 is available in `xrpld` version 2.0.0 and later. See [API-VERSION-
This version is supported by all `xrpld` versions. For WebSocket and HTTP JSON-RPC requests, it is currently the default API version used when no `api_version` is specified.
## Unreleased
### Bugfixes
- A request echoed back in an error reply now has every credential-bearing field masked: `admin_password`, `admin_user`, `passphrase`, `password`, `secret`, `seed`, `seed_hex`, `url_password`, `url_username` and `username`. Nesting no longer matters, so a credential inside `params` is masked too. The same masking is applied to every request and reply written to the log, and it covers six further names that only a reply carries: `master_key`, `master_seed`, `master_seed_hex`, `validation_key`, `validation_private_key` and `validation_seed`, which is how `wallet_propose` and `validation_create` used to write a live private key to the log. A request or reply written to the log is truncated at 10,000 characters.
- The command line client no longer prints a credential the operator did not type. A failing command echoes the request it built under `request_sent`, which carries the `admin_password` the client copies out of `[port_rpc]` in the config, so `./xrpld account_info rBogus` printed that password to stdout and into any captured output. `request_sent` is now masked. The `rpc` member beside it, which echoes the arguments as they were typed, is unchanged. The command line client also no longer writes an unparsed `json` or `ripple_path_find` argument to its trace log before parsing it, where a `secret` inside that argument could not be masked; it logs the parsed request instead, masked. The reply it receives is logged the same way, parsed and masked, where the raw body was written before, a `validation_create` answer included.
- A WebSocket frame that does not parse, or exceeds the request size limit, is answered `{"type": "error", "error": "jsonInvalid", "size": <bytes>}`. The frame's body is reported by size rather than echoed back in a `value` member, since a body that does not parse has no fields to mask. A client that read `value` gets `size` instead.
- Four error codes that named no HTTP status of their own, and so answered 200 on a reply reporting an error, now name one: `actMalformed`, `alreadyMultisig` and `alreadySingleSig` answer 400, and `actNotFound` answers 404. **No shipped envelope reports these four.** A request sending `ripplerpc: "3.0"` still receives 200 for all four, as it always has, so `account_info` on a malformed account or one the ledger does not hold answers 200 exactly as before.
- `submit`, `simulate`, `transaction_entry`, `ledger_entry` and `ledger_accept`: Errors from these methods now include `error_code` and `error_message` alongside the `error` token, as every other method already did. Each error now answers the status its code names: 400 for a malformed request, 404 for `transactionNotFound`, 500 for an internal failure, and 501 for `notYetImplemented` and `notStandAlone`. That status change reaches only a request sending `ripplerpc: "3.0"`, which is the envelope that derives the status from the error. With `ripplerpc` `"1.0"` the status stays 200 and the two new members appear beside `error`; with `"2.0"` the status stays 200, `error_code` appears, and the `code` and `message` members carry the code and the message rather than null, since that envelope copies them from `error_code` and `error_message` and drops `error_message`.
## XRP Ledger server version 3.5.0
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 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
@@ -92,6 +82,7 @@ This release contains bug fixes only and no API changes.
### Additions in 3.2.0
- `tx`: A validated `Batch` transaction now includes `inner_results`, an array in `RawTransactions` order with one entry per inner transaction that was evaluated, whether or not it was applied: `hash`, `result` (the transaction result code) and `applied` (whether its changes ended up in the ledger; `false` for an inner transaction that failed with a `ter`/`tem`/`tef` code, and for every inner transaction of a `tfAllOrNothing` batch that rolled back). `tfOnlyOne` stops evaluating after the first inner that returns `tesSUCCESS`, not merely applies (an applied `tec` does not stop it), and `tfUntilFailure` stops after the first inner that fails, so later `RawTransactions` entries have no corresponding `inner_results` entry. Inner transactions that fail are not in the ledger, so this is the only record of them. The field is present only when this node built the validated ledger itself and has `[ledger_tx_tables]` enabled; a node that acquired the ledger from the network omits it.
- `ledger_entry`, `account_objects`: The `Delegate` ledger entry now includes an optional `DestinationNode` field, which stores the index into the authorized account's owner directory. This field is present on entries created after bidirectional directory tracking was introduced and may appear in RPC responses for those entries. ([#6681](https://github.com/XRPLF/rippled/pull/6681))
- `server_definitions`: Added the following new sections to the response ([#6321](https://github.com/XRPLF/rippled/pull/6321)):
- `TRANSACTION_FORMATS`: Describes the fields and their optionality for each transaction type, including common fields shared across all transactions.

View File

@@ -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/nix/check-build-context-runtime.sh <graph.json>
# Usage: bin/check-build-context-runtime.sh <graph.json>
# <graph.json> is the output of `conan install --format=json`.
set -euo pipefail

View File

@@ -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/nix/check-nix-store-refs.sh <path>
# Usage: bin/check-nix-store-refs.sh <path>
set -euo pipefail

View File

@@ -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/nix/default-loader-path.sh.
The default loader is resolved by bin/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/nix/default-loader-path.sh")
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
if(
is_linux

View File

@@ -60,20 +60,8 @@ 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" %}
[buildenv]
{# 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. #}
@@ -83,5 +71,11 @@ 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 %}

View File

@@ -154,7 +154,7 @@ class Xrpl(ConanFile):
self.requires("xxhash/0.8.3", transitive_headers=True)
exports_sources = (
"bin/nix/default-loader-path.sh",
"bin/default-loader-path.sh",
"CMakeLists.txt",
"cfg/*",
"cmake/*",

12
docs/build/nix.md vendored
View File

@@ -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/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.
[`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.
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/nix/check-nix-store-refs.sh build
bin/nix/check-nix-store-refs.sh ~/.conan2-nix
bin/check-nix-store-refs.sh build
bin/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/nix/check-build-context-runtime.sh graph.json
bin/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/nix/check-nix-store-refs.sh build/xrpld
bin/check-nix-store-refs.sh build/xrpld
```
### The libresolv stub

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
```
[`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`](../../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 ~/.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
/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig
/nix/store/p4lp3xq4imd1qzqh08x8vcq2zfhi7rca-libresolv-93/lib/libresolv.9.dylib

View File

@@ -3,84 +3,9 @@
#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]

View File

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

View File

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

View File

@@ -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());
}

View File

@@ -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());
}

View File

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

View File

@@ -8,7 +8,7 @@ namespace beast::insight {
class HookImpl : public std::enable_shared_from_this<HookImpl>
{
public:
using HandlerType = std::function<void()>;
using HandlerType = std::function<void(void)>;
virtual ~HookImpl() = 0;
};

View File

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

View File

@@ -34,7 +34,7 @@ typeName()
name += " volatile";
if (std::is_lvalue_reference_v<T>)
{
name += '&';
name += "&";
}
else if (std::is_rvalue_reference_v<T>)
{

View File

@@ -47,8 +47,8 @@ public:
template <class F, class... Args>
explicit Thread(Suite& s, F&& f, Args&&... args) : s_(&s)
{
std::function<void()> b = [f = std::forward<F>(f),
... args = std::forward<Args>(args)] mutable {
std::function<void(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()> f)
run(std::function<void(void)> f)
{
try
{

View File

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

View File

@@ -3,13 +3,11 @@
#include <xrpl/basics/Number.h>
#include <xrpl/json/json_forwards.h>
#include <concepts>
#include <cstring>
#include <iterator>
#include <limits>
#include <map>
#include <string>
#include <string_view>
#include <vector>
/**
@@ -200,15 +198,6 @@ public:
*/
Value(StaticString const& value);
Value(std::string const& value);
/**
* @brief Constructs a value from a string view.
*
* The characters are copied, so the view need not outlive the call and need
* not be NUL-terminated.
*
* @param value The characters to copy.
*/
Value(std::string_view value);
Value(bool value);
Value(Value const& other);
~Value();
@@ -483,32 +472,6 @@ toJson(xrpl::Number const& number)
bool
operator==(Value const&, Value const&);
/**
* Compares a value with a string view, reading the value's characters in place
* rather than building a Value from the view.
*
* Constrained to the exact type: a string literal converts equally well to a
* view and to a Value, so a plain overload makes `value == "literal"`
* ambiguous.
*
* @param x The value to compare.
* @param y The characters to compare it against.
* @return Whether `x` is a string whose characters up to its first NUL are
* exactly the characters of `y`.
*/
template <class T>
requires std::same_as<T, std::string_view>
bool
operator==(Value const& x, T y)
{
if (!x.isString())
return false;
// A string `Value` can hold a null pointer, which names no characters, so it equals no view.
char const* const s = x.asCString();
return s != nullptr && std::string_view{s} == y;
}
bool
operator<(Value const&, Value const&);

View File

@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/CachedView.h>
#include <xrpl/ledger/RawView.h>
#include <xrpl/protocol/BatchInnerResult.h>
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerHeader.h>
@@ -325,6 +326,24 @@ public:
bool
addSLE(SLE const& sle);
/**
* @brief Inner Batch outcomes observed while this node built the ledger.
*
* Empty for a ledger acquired from the network or loaded from the database. Not part of
* the ledger hash; persisted to the transaction tables when the ledger is saved.
*/
void
setBatchInnerResults(std::vector<BatchInnerResult> results)
{
batchInnerResults_ = std::move(results);
}
std::vector<BatchInnerResult> const&
batchInnerResults() const
{
return batchInnerResults_;
}
//--------------------------------------------------------------------------
void
@@ -433,6 +452,7 @@ private:
Rules rules_;
LedgerHeader header_;
beast::Journal j_;
std::vector<BatchInnerResult> batchInnerResults_;
};
/**

View File

@@ -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
auto amounts = TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
if (Quality{amounts} < quality &&
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) << " "
@@ -382,19 +382,21 @@ changeSpotPriceQuality(
<< " " << to_string(amounts.out);
Throw<std::runtime_error>("changeSpotPriceQuality failed");
}
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;
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 = [&] {
auto amounts = [&]() {
bool const inIntegral = getAsset(pool.in).integral();
bool const outIntegral = getAsset(pool.out).integral();

View File

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

View File

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

View File

@@ -6,21 +6,31 @@
#include <xrpl/protocol/jss.h>
#include <cstddef>
#include <string_view>
#include <type_traits>
#include <utility>
namespace xrpl {
/**
* The `api_version` numbers this server serves.
* API version numbers used in later API versions
*
* A request naming a version in [kApiMinimumSupportedVersion,
* kApiMaximumSupportedVersion] is served. With `[beta_rpc_api]` set to `1` in
* the config the range extends to kApiBetaVersion.
* Requests with a version number in the range
* [apiMinimumSupportedVersion, apiMaximumSupportedVersion]
* are supported.
*
* A request naming no version is served at kApiVersionIfUnspecified, which is 1
* because a request wanting any later version states it.
* If [beta_rpc_api] is enabled in config, the version numbers
* in the range [apiMinimumSupportedVersion, apiBetaVersion]
* are supported.
*
* Network Requests without explicit version numbers use
* apiVersionIfUnspecified. apiVersionIfUnspecified is 1,
* because all the RPC requests with a version >= 2 must
* explicitly specify the version in the requests.
* Note that apiVersionIfUnspecified will be lower than
* apiMinimumSupportedVersion when we stop supporting API
* version 1.
*
* Command line Requests use apiCommandLineVersion.
*/
namespace rpc {
@@ -47,16 +57,6 @@ static_assert(kApiMaximumSupportedVersion >= kApiMinimumSupportedVersion);
static_assert(kApiBetaVersion >= kApiMaximumSupportedVersion);
static_assert(kApiMaximumValidVersion >= kApiMaximumSupportedVersion);
/**
* Values accepted in the `ripplerpc` request field, which selects the shape of
* the JSON-RPC reply envelope. Distinct from `kJsonRpcVersion` in JsonRpc.h,
* which names the JSON-RPC protocol itself, and from the `api_version`
* constants above, which select the content of the response.
*/
inline constexpr std::string_view kRippleRpcVersion1{"1.0"};
inline constexpr std::string_view kRippleRpcVersion2{"2.0"};
inline constexpr std::string_view kRippleRpcVersion3{"3.0"};
inline void
setVersion(json::Value& parent, unsigned int apiVersion, bool betaEnabled)
{

View File

@@ -0,0 +1,37 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/protocol/TER.h>
#include <cstdint>
namespace xrpl {
/**
* @brief Outcome of one inner transaction of a Batch, recorded while the outer Batch was
* applied.
*
* Inner transactions that fail with a ter/tem/tef result are never applied and leave no
* metadata in the ledger, and a tfAllOrNothing rollback discards the ones that did apply.
* This record is the only place those outcomes survive. It is node-local and not part of
* the ledger hash.
*/
struct BatchInnerResult
{
uint256 parentBatchId;
uint256 innerTxId;
/**
* @brief Position in the outer transaction's RawTransactions.
*/
std::uint32_t index = 0;
TER ter = tesSUCCESS;
/**
* @brief True if the inner transaction's changes ended up in the ledger.
*/
bool applied = false;
};
} // namespace xrpl

View File

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

View File

@@ -144,27 +144,7 @@ enum ErrorCodeI {
RpcEntryNotFound = 98,
RpcUnexpectedLedgerType = 99,
// submit + simulate
RpcInvalidTransaction = 100,
RpcInternalSubmit = 101,
RpcInternalJson = 102,
RpcInternalSimulate = 103,
// transaction_entry
RpcFieldNotFoundTransaction = 104,
RpcNotYetImplemented = 105,
RpcTransactionNotFound = 106,
// transaction_entry + ledger_entry
RpcMalformedRequest = 107,
// ledger_accept
RpcNotStandAlone = 108,
// ledger_entry, API version 1 only
RpcUnknownOption = 109,
RpcLast = RpcUnknownOption // rpcLAST should always equal the last code.
RpcLast = RpcUnexpectedLedgerType // rpcLAST should always equal the last code.
};
/**
@@ -200,6 +180,11 @@ struct ErrorInfo
{
}
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message)
: code(code), token(token), message(message), httpStatus(200)
{
}
constexpr ErrorInfo(ErrorCodeI code, char const* token, char const* message, int httpStatus)
: code(code), token(token), message(message), httpStatus(httpStatus)
{

View File

@@ -1,20 +0,0 @@
#pragma once
#include <string_view>
namespace xrpl::rpc {
/**
* Constants of the JSON-RPC 2.0 protocol itself.
*
* Kept apart from the `api_version` and `ripplerpc` constants in ApiVersion.h,
* which go when support for API versions 1 and 2 goes.
*/
/**
* Value of the `jsonrpc` member of a request and of its reply, fixed at "2.0"
* by the JSON-RPC specification.
*/
inline constexpr std::string_view kJsonRpcVersion{"2.0"};
} // namespace xrpl::rpc

View File

@@ -208,10 +208,7 @@ enum LedgerEntryType : std::uint16_t {
\
LEDGER_OBJECT(Sponsorship, \
LSF_FLAG(lsfSponsorshipRequireSignForFee, 0x00010000) \
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000)) \
\
LEDGER_OBJECT(LoanBroker, \
LSF_FLAG(lsfLoanBrokerPrivate, 0x00010000))
LSF_FLAG(lsfSponsorshipRequireSignForReserve, 0x00020000))
// clang-format on

View File

@@ -457,7 +457,9 @@ 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_cvref_t<decltype(std::declval<T>().value())>>
template <
typename T,
typename V = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<T>().value())>>>
V
getFieldByValue(SField const& field) const;

View File

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

View File

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

View File

@@ -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_cvref_t<T>>::value)
requires(Trait<std::remove_cv_t<std::remove_reference_t<T>>>::value)
: code_(TERtoInt(rhs))
{
}

View File

@@ -226,10 +226,6 @@ 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) \

View File

@@ -20,7 +20,6 @@ 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)

View File

@@ -549,7 +549,6 @@ 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

View File

@@ -900,7 +900,6 @@ TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet,
{sfDebtMaximum, SoeOptional},
{sfCoverRateMinimum, SoeOptional},
{sfCoverRateLiquidation, SoeOptional},
{sfDomainID, SoeOptional},
}))
/** This transaction deletes a Loan Broker */

View File

@@ -245,7 +245,7 @@ JSS(ephemeral_key); // out: ValidatorInfo
JSS(error); // out: error
JSS(errored); //
JSS(error_code); // out: error
JSS(error_exception); // out: Submit, Simulate
JSS(error_exception); // out: Submit
JSS(error_message); // out: error
JSS(expand); // in: handler/Ledger
JSS(expected_date); // out: any (warnings)
@@ -300,6 +300,7 @@ JSS(in); // out: OverlayImpl
JSS(inLedger); // out: tx/Transaction
JSS(inbound); // out: PeerImp
JSS(index); // in: LedgerEntry
JSS(inner_results); // out: Tx
// out: STLedgerEntry, LedgerEntry, TxHistory, LedgerData
JSS(info); // out: ServerInfo, ConsensusInfo, FetchInfo
JSS(initial_sync_duration_us); //
@@ -559,7 +560,7 @@ JSS(signing_key); // out: NetworkOPs
JSS(signing_keys); // out: ValidatorList
JSS(signing_time); // out: NetworkOPs
JSS(signer_lists); // in/out: AccountInfo
JSS(size); // out: get_aggregate_price, ServerHandler
JSS(size); // out: get_aggregate_price
JSS(snapshot); // in: Subscribe
JSS(source_account); // in: PathRequest, RipplePathFind
JSS(source_amount); // in: PathRequest, RipplePathFind

View File

@@ -335,30 +335,6 @@ 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);
}
};
/**
@@ -602,17 +578,6 @@ 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.

View File

@@ -213,32 +213,6 @@ 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);
}
};
/**
@@ -362,17 +336,6 @@ 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.

View File

@@ -72,7 +72,7 @@ inline constexpr std::array<char const*, 5> kLgrDbInit{
// Transaction database holds transactions and public keys
inline constexpr auto kTxDbName{"transaction.db"};
inline constexpr std::array<char const*, 8> kTxDbInit{
inline constexpr std::array<char const*, 10> kTxDbInit{
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS Transactions ( \
@@ -101,6 +101,21 @@ inline constexpr std::array<char const*, 8> kTxDbInit{
"CREATE INDEX IF NOT EXISTS AcctLgrIndex ON \
AccountTransactions(LedgerSeq, Account, TransID);",
// Outcome of each inner transaction of a Batch this node applied while building a
// validated ledger. Inner transactions that failed are not in the ledger, so this is
// the only record of them. See BatchInnerResult.
"CREATE TABLE IF NOT EXISTS BatchInnerResults ( \
ParentBatchID CHARACTER(64) NOT NULL, \
InnerTxnID CHARACTER(64) NOT NULL, \
TxnIndex INTEGER NOT NULL, \
LedgerSeq BIGINT UNSIGNED NOT NULL, \
TERResult INTEGER NOT NULL, \
Applied INTEGER NOT NULL, \
PRIMARY KEY (ParentBatchID, InnerTxnID) \
);",
"CREATE INDEX IF NOT EXISTS BatchInnerLgrIndex ON \
BatchInnerResults(LedgerSeq);",
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////

View File

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

View File

@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/BatchInnerResult.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <xrpl/protocol/LedgerHeader.h>
#include <xrpl/protocol/Protocol.h>
@@ -212,6 +213,18 @@ public:
virtual std::optional<LedgerIndex>
getAccountTransactionsMinLedgerSeq() = 0;
/**
* @brief getBatchInnerResults Returns the recorded inner-transaction outcomes of a
* Batch this node applied while building a validated ledger.
* @param parentBatchId Hash of the outer Batch transaction.
* @param ledgerSeq Ledger sequence the outer Batch transaction is validated in; rows
* recorded for any other sequence are not this ledger's and are excluded.
* @return Outcomes in RawTransactions order; empty if the tx tables are disabled or
* nothing was recorded (a ledger acquired from the network records nothing).
*/
virtual std::vector<BatchInnerResult>
getBatchInnerResults(uint256 const& parentBatchId, LedgerIndex ledgerSeq) = 0;
/**
* @brief deleteTransactionByLedgerSeq Deletes transactions from the ledger
* with the given sequence.

View File

@@ -279,7 +279,7 @@ public:
virtual bool
unsubPeerStatus(std::uint64_t uListener) = 0;
virtual void
pubPeerStatus(std::function<json::Value()> const&) = 0;
pubPeerStatus(std::function<json::Value(void)> const&) = 0;
virtual bool
subConsensus(Ref ispListener) = 0;

View File

@@ -41,7 +41,7 @@ public:
}
bool
prepare(std::size_t bytes, std::function<void()>) override
prepare(std::size_t bytes, std::function<void(void)>) override
{
return true;
}

View File

@@ -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()> resume) = 0;
prepare(std::size_t bytes, std::function<void(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()>) override
prepare(std::size_t bytes, std::function<void(void)>) override
{
if (sb_.size() == 0)
return {true, {}};

View File

@@ -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()> resume) = 0;
prepare(std::size_t bytes, std::function<void(void)> resume) = 0;
/**
* Returns a ConstBufferSequence representing the input sequence.

View File

@@ -342,10 +342,10 @@ BaseHTTPPeer<Handler, Impl>::doWriter(
bool keepAlive,
YieldContext doYield)
{
std::function<void()> resume;
std::function<void(void)> resume;
{
auto const p = impl().shared_from_this();
resume = std::function<void()>([this, p, writer, keepAlive] {
resume = std::function<void(void)>([this, p, writer, keepAlive]() {
util::spawn(strand_, [p, writer, keepAlive](YieldContext doYield) {
p->doWriter(writer, keepAlive, doYield);
});

View File

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

View File

@@ -7,18 +7,6 @@
namespace xrpl {
/**
* Writes an HTTP reply carrying @p strMsg with status @p nStatus to @p output,
* and logs the status at trace. The body is not logged here: it may carry a
* credential this library cannot mask, so the caller logs it masked.
*
* A 401 with an empty body is answered with the fixed authentication page.
*
* @param nStatus The HTTP status code.
* @param strMsg The body.
* @param output Where the reply bytes are written.
* @param j The journal the status is logged to.
*/
void
httpReply(int nStatus, std::string const& strMsg, json::Output const&, beast::Journal j);

View File

@@ -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()> f_;
std::function<void(void)> f_;
public:
IOList() = default;
@@ -171,7 +171,7 @@ IOList::Work::destroy()
{
if (!ios_)
return;
std::function<void()> f;
std::function<void(void)> f;
{
std::scoped_lock const lock(ios_->m_);
ios_->map_.erase(this);

View File

@@ -4,12 +4,14 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OpenView.h>
#include <xrpl/protocol/BatchInnerResult.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/tx/applySteps.h>
#include <string>
#include <utility>
#include <vector>
namespace xrpl {
@@ -142,6 +144,7 @@ enum class ApplyTransactionResult {
* Provides more detailed logging and decodes the
* correct behavior based on the `TER` type
*
* @param innerResults If set, receives one entry per inner transaction the outer Batch ran.
* @see ApplyTransactionResult
*/
ApplyTransactionResult
@@ -151,6 +154,7 @@ applyTransaction(
STTx const& tx,
bool retryAssured,
ApplyFlags flags,
beast::Journal journal);
beast::Journal journal,
std::vector<BatchInnerResult>* innerResults = nullptr);
} // namespace xrpl

View File

@@ -18,8 +18,6 @@
#include <xrpl/tx/invariants/SponsorshipInvariant.h>
#include <xrpl/tx/invariants/VaultInvariant.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <cstdint>
#include <set>
#include <string>
@@ -141,7 +139,7 @@ public:
*/
class XRPNotCreated
{
boost::multiprecision::int128_t drops_ = 0;
std::int64_t drops_ = 0;
public:
void

View File

@@ -1,8 +1,6 @@
#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>
@@ -25,7 +23,6 @@
#include <ostream>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
@@ -505,46 +502,6 @@ 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

View File

@@ -31,6 +31,7 @@
#include <cstdint>
#include <iterator>
#include <memory>
#include <numeric>
#include <optional>
#include <tuple>
#include <type_traits>
@@ -407,7 +408,7 @@ limitOut(
if (!qf || qf->isConst())
return remainingOut;
auto const out = [&] {
auto const out = [&]() {
auto const out = qf->outFromAvgQ(limitQuality);
if (!out)
return remainingOut;
@@ -645,21 +646,11 @@ flow(
boost::container::flat_multiset<TOutAmt> savedOuts;
savedOuts.reserve(maxTries);
// 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())>> {
auto sum = [](auto const& col) {
using TResult = std::decay_t<decltype(*col.begin())>;
if (col.empty())
return TResult{beast::kZero};
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;
return std::accumulate(col.begin() + 1, col.end(), *col.begin());
};
// These offers only need to be removed if the payment is not
@@ -679,7 +670,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))
@@ -758,17 +749,9 @@ flow(
{
savedIns.insert(best->in);
savedOuts.insert(best->out);
auto const sumOut = sum(savedOuts);
if (!sumOut)
return {tecPATH_DRY, std::move(ofrsToRmOnFail)};
remainingOut = outReq - *sumOut;
remainingOut = outReq - sum(savedOuts);
if (sendMax)
{
auto const sumIn = sum(savedIns);
if (!sumIn)
return {tecPATH_DRY, std::move(ofrsToRmOnFail)};
remainingIn = *sendMax - *sumIn;
}
remainingIn = *sendMax - sum(savedIns);
if (flowDebugInfo)
{
@@ -803,12 +786,8 @@ flow(
break;
}
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;
auto const actualOut = sum(savedOuts);
auto const actualIn = sum(savedIns);
JLOG(j.trace()) << "Total flow: in: " << to_string(actualIn)
<< " out: " << to_string(actualOut);

View File

@@ -10,7 +10,6 @@
#include <xrpl/tx/ApplyContext.h>
#include <xrpl/tx/Transactor.h>
#include <cstdint>
#include <vector>
namespace xrpl {
@@ -33,9 +32,6 @@ public:
static std::vector<OptionaledField<STNumber>> const&
getValueFields();
static std::uint32_t
getFlagsMask(PreflightContext const& ctx);
static TER
preclaim(PreclaimContext const& ctx);

View File

@@ -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/nix/default-loader-path.sh /usr/local/bin/default-loader-path.sh
COPY bin/default-loader-path.sh /tmp/loader-path.sh
RUN <<EOF
target="$(/usr/local/bin/default-loader-path.sh)"
target="$(/tmp/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

View File

@@ -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
([`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).
([`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).
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,10 +75,9 @@ 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/nix/default-loader-path.sh`](../../bin/nix/default-loader-path.sh) reports the
[`bin/default-loader-path.sh`](../../bin/default-loader-path.sh) reports the
expected loader path for the current architecture, so we can patch the binaries
to use the correct loader. The image ships it as
`/usr/local/bin/default-loader-path.sh`.
to use the correct loader.
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`
@@ -92,11 +91,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/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. |
| 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. |

View File

@@ -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="$(/usr/local/bin/default-loader-path.sh)"
loader="$(/tmp/loader-path.sh)"
mkdir -p "${dst_dir}"

View File

@@ -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="$(/usr/local/bin/default-loader-path.sh)"
loader="$(/tmp/loader-path.sh)"
mkdir -p "${dst_dir}"

View File

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

View File

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

View File

@@ -130,13 +130,6 @@ 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
# =============================================================================

View File

@@ -259,7 +259,7 @@ Logs::format(
output = xrpl::to_string(std::chrono::system_clock::now());
output += ' ';
output += " ";
if (!partition.empty())
output += partition + ":";

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,6 @@
#include <cstring>
#include <limits>
#include <string>
#include <string_view>
#include <utility>
namespace json {
@@ -112,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)
@@ -242,14 +241,10 @@ Value::Value(xrpl::Number const& value) : type_(ValueType::String), allocated_(t
value_.stringVal = valueAllocator()->duplicateStringValue(tmp.c_str(), tmp.length());
}
Value::Value(std::string const& value) : Value(std::string_view{value})
Value::Value(std::string const& value) : type_(ValueType::String), allocated_(true)
{
}
Value::Value(std::string_view value) : type_(ValueType::String), allocated_(true)
{
value_.stringVal = valueAllocator()->duplicateStringValue(
value.data(), static_cast<unsigned int>(value.length()));
value_.stringVal =
valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length());
}
Value::Value(StaticString const& value) : type_(ValueType::String)
@@ -945,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;
}
@@ -1013,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;
}
@@ -1056,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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,6 @@
#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>
@@ -1158,10 +1157,6 @@ 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);
@@ -1169,7 +1164,7 @@ accountSendMultiIOU(
view.update(receiver);
// Take what is actually sent.
// Take what is actually sent
takeFromSender += amount;
}
@@ -1462,8 +1457,6 @@ 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;
@@ -1491,10 +1484,6 @@ 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;

View File

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

View File

@@ -20,102 +20,88 @@ namespace detail {
// will remain in the object file. But the string literals will remain.
//
// There's a certain amount of tension in determining the correct HTTP
// status to associate with a given RPC error. Every row below names its
// HTTP status, and a row that omits it does not compile, since ErrorInfo has
// no constructor that leaves the status out.
// status to associate with a given RPC error. Initially all RPC errors
// returned 200 (OK). And that's the default behavior if no HTTP status code
// is specified below.
//
// The codes currently selected target the load balancer fail-over use case.
// If a query fails on one node but is likely to have a positive outcome
// on a different node, then the failure should return a 4xx/5xx range
// status code.
// The rows below are aligned by hand into four columns, so that a wrong status or a mistyped token
// is visible by scanning one column. That cannot be had inside the 100-column limit once the
// longest enumerator and the longest message sit in one row. So this region is exempt from the
// limit by design rather than by oversight.
// clang-format off
static constexpr ErrorInfo kUnorderedErrorInfos[]{
{RpcActMalformed, "actMalformed", "Account malformed.", 400},
{RpcActNotFound, "actNotFound", "Account not found.", 404},
{RpcAlreadyMultisig, "alreadyMultisig", "Already multisigned.", 400},
{RpcAlreadySingleSig, "alreadySingleSig", "Already single-signed.", 400},
{RpcAmendmentBlocked, "amendmentBlocked", "Amendment blocked, need upgrade.", 503},
{RpcExpiredValidatorList, "unlBlocked", "Validator list expired.", 503},
{RpcAtxDeprecated, "deprecated", "Use the new API or specify a ledger range.", 400},
{RpcBadKeyType, "badKeyType", "Bad key type.", 400},
{RpcBadFeature, "badFeature", "Feature unknown or invalid.", 500},
{RpcBadIssuer, "badIssuer", "Issuer account malformed.", 400},
{RpcBadMarket, "badMarket", "No such market.", 404},
{RpcBadSecret, "badSecret", "Secret does not match account.", 403},
{RpcBadSeed, "badSeed", "Disallowed seed.", 403},
{RpcBadSyntax, "badSyntax", "Syntax error.", 400},
{RpcChannelMalformed, "channelMalformed", "Payment channel is malformed.", 400},
{RpcChannelAmtMalformed, "channelAmtMalformed", "Payment channel amount is malformed.", 400},
{RpcCommandMissing, "commandMissing", "Missing command entry.", 400},
{RpcDbDeserialization, "dbDeserialization", "Database deserialization error.", 502},
{RpcDstActMalformed, "dstActMalformed", "Destination account is malformed.", 400},
{RpcDstActMissing, "dstActMissing", "Destination account not provided.", 400},
{RpcDstActNotFound, "dstActNotFound", "Destination account not found.", 404},
{RpcDstAmtMalformed, "dstAmtMalformed", "Destination amount/currency/issuer is malformed.", 400},
{RpcDstAmtMissing, "dstAmtMissing", "Destination amount/currency/issuer is missing.", 400},
{RpcDstIsrMalformed, "dstIsrMalformed", "Destination issuer is malformed.", 400},
{RpcExcessiveLgrRange, "excessiveLgrRange", "Ledger range exceeds 1000.", 400},
{RpcForbidden, "forbidden", "Bad credentials.", 403},
{RpcHighFee, "highFee", "Current transaction fee exceeds your limit.", 402},
{RpcInternal, "internal", "Internal error.", 500},
{RpcInvalidLgrRange, "invalidLgrRange", "Ledger range is invalid.", 400},
{RpcInvalidParams, "invalidParams", "Invalid parameters.", 400},
{RpcInvalidHotwallet, "invalidHotWallet", "Invalid hotwallet.", 400},
{RpcIssueMalformed, "issueMalformed", "Issue is malformed.", 400},
{RpcJsonRpc, "json_rpc", "JSON-RPC transport error.", 500},
{RpcLgrIdxsInvalid, "lgrIdxsInvalid", "Ledger indexes invalid.", 400},
{RpcLgrIdxMalformed, "lgrIdxMalformed", "Ledger index malformed.", 400},
{RpcLgrNotFound, "lgrNotFound", "Ledger not found.", 404},
{RpcLgrNotValidated, "lgrNotValidated", "Ledger not validated.", 202},
{RpcMasterDisabled, "masterDisabled", "Master key is disabled.", 403},
{RpcNotEnabled, "notEnabled", "Not enabled in configuration.", 501},
{RpcNotImpl, "notImpl", "Not implemented.", 501},
{RpcNotReady, "notReady", "Not ready to handle this request.", 503},
{RpcNotSupported, "notSupported", "Operation not supported.", 501},
{RpcNoClosed, "noClosed", "Closed ledger is unavailable.", 503},
{RpcNoCurrent, "noCurrent", "Current ledger is unavailable.", 503},
{RpcNotSynced, "notSynced", "Not synced to the network.", 503},
{RpcNoEvents, "noEvents", "Current transport does not support events.", 405},
{RpcNoNetwork, "noNetwork", "Not synced to the network.", 503},
{RpcWrongNetwork, "wrongNetwork", "Wrong network.", 503},
{RpcNoPermission, "noPermission", "You don't have permission for this command.", 401},
{RpcNoPfRequest, "noPathRequest", "No pathfinding request in progress.", 404},
{RpcObjectNotFound, "objectNotFound", "The requested object was not found.", 404},
{RpcPublicMalformed, "publicMalformed", "Public key is malformed.", 400},
{RpcSendmaxMalformed, "sendMaxMalformed", "SendMax amount malformed.", 400},
{RpcSigningMalformed, "signingMalformed", "Signing of transaction is malformed.", 400},
{RpcSlowDown, "slowDown", "You are placing too much load on the server.", 429},
{RpcSrcActMalformed, "srcActMalformed", "Source account is malformed.", 400},
{RpcSrcActMissing, "srcActMissing", "Source account not provided.", 400},
{RpcSrcActNotFound, "srcActNotFound", "Source account not found.", 404},
{RpcDelegateActNotFound, "delegateActNotFound", "Delegate account not found.", 404},
{RpcSrcCurMalformed, "srcCurMalformed", "Source currency is malformed.", 400},
{RpcSrcIsrMalformed, "srcIsrMalformed", "Source issuer is malformed.", 400},
{RpcStreamMalformed, "malformedStream", "Stream malformed.", 400},
{RpcTooBusy, "tooBusy", "The server is too busy to help you now.", 503},
{RpcTxnNotFound, "txnNotFound", "Transaction not found.", 404},
{RpcUnknownCommand, "unknownCmd", "Unknown method.", 405},
{RpcOracleMalformed, "oracleMalformed", "Oracle request is malformed.", 400},
{RpcBadCredentials, "badCredentials", "Credentials do not exist, are not accepted, or have expired.", 400},
{RpcTxSigned, "transactionSigned", "Transaction should not be signed.", 400},
{RpcDomainMalformed, "domainMalformed", "Domain is malformed.", 400},
{RpcEntryNotFound, "entryNotFound", "Entry not found.", 400},
{RpcUnexpectedLedgerType, "unexpectedLedgerType", "Unexpected ledger type.", 400},
{RpcInvalidTransaction, "invalidTransaction", "Transaction is invalid.", 400},
{RpcInternalSubmit, "internalSubmit", "Internal error during submit.", 500},
{RpcInternalJson, "internalJson", "Internal error during JSON handling.", 500},
{RpcInternalSimulate, "internalSimulate", "Internal error during simulate.", 500},
{RpcFieldNotFoundTransaction, "fieldNotFoundTransaction", "Missing required field.", 400},
{RpcNotYetImplemented, "notYetImplemented", "Not yet implemented.", 501},
{RpcTransactionNotFound, "transactionNotFound", "Transaction not found.", 404},
{RpcMalformedRequest, "malformedRequest", "Request is malformed.", 400},
{RpcNotStandAlone, "notStandAlone", "Server is not running stand-alone.", 501},
{RpcUnknownOption, "unknownOption", "Unknown option.", 400},
{RpcActMalformed, "actMalformed", "Account malformed."},
{RpcActNotFound, "actNotFound", "Account not found."},
{RpcAlreadyMultisig, "alreadyMultisig", "Already multisigned."},
{RpcAlreadySingleSig, "alreadySingleSig", "Already single-signed."},
{RpcAmendmentBlocked, "amendmentBlocked", "Amendment blocked, need upgrade.", 503},
{RpcExpiredValidatorList, "unlBlocked", "Validator list expired.", 503},
{RpcAtxDeprecated, "deprecated", "Use the new API or specify a ledger range.", 400},
{RpcBadKeyType, "badKeyType", "Bad key type.", 400},
{RpcBadFeature, "badFeature", "Feature unknown or invalid.", 500},
{RpcBadIssuer, "badIssuer", "Issuer account malformed.", 400},
{RpcBadMarket, "badMarket", "No such market.", 404},
{RpcBadSecret, "badSecret", "Secret does not match account.", 403},
{RpcBadSeed, "badSeed", "Disallowed seed.", 403},
{RpcBadSyntax, "badSyntax", "Syntax error.", 400},
{RpcChannelMalformed, "channelMalformed", "Payment channel is malformed.", 400},
{RpcChannelAmtMalformed, "channelAmtMalformed", "Payment channel amount is malformed.", 400},
{RpcCommandMissing, "commandMissing", "Missing command entry.", 400},
{RpcDbDeserialization, "dbDeserialization", "Database deserialization error.", 502},
{RpcDstActMalformed, "dstActMalformed", "Destination account is malformed.", 400},
{RpcDstActMissing, "dstActMissing", "Destination account not provided.", 400},
{RpcDstActNotFound, "dstActNotFound", "Destination account not found.", 404},
{RpcDstAmtMalformed, "dstAmtMalformed", "Destination amount/currency/issuer is malformed.", 400},
{RpcDstAmtMissing, "dstAmtMissing", "Destination amount/currency/issuer is missing.", 400},
{RpcDstIsrMalformed, "dstIsrMalformed", "Destination issuer is malformed.", 400},
{RpcExcessiveLgrRange, "excessiveLgrRange", "Ledger range exceeds 1000.", 400},
{RpcForbidden, "forbidden", "Bad credentials.", 403},
{RpcHighFee, "highFee", "Current transaction fee exceeds your limit.", 402},
{RpcInternal, "internal", "Internal error.", 500},
{RpcInvalidLgrRange, "invalidLgrRange", "Ledger range is invalid.", 400},
{RpcInvalidParams, "invalidParams", "Invalid parameters.", 400},
{RpcInvalidHotwallet, "invalidHotWallet", "Invalid hotwallet.", 400},
{RpcIssueMalformed, "issueMalformed", "Issue is malformed.", 400},
{RpcJsonRpc, "json_rpc", "JSON-RPC transport error.", 500},
{RpcLgrIdxsInvalid, "lgrIdxsInvalid", "Ledger indexes invalid.", 400},
{RpcLgrIdxMalformed, "lgrIdxMalformed", "Ledger index malformed.", 400},
{RpcLgrNotFound, "lgrNotFound", "Ledger not found.", 404},
{RpcLgrNotValidated, "lgrNotValidated", "Ledger not validated.", 202},
{RpcMasterDisabled, "masterDisabled", "Master key is disabled.", 403},
{RpcNotEnabled, "notEnabled", "Not enabled in configuration.", 501},
{RpcNotImpl, "notImpl", "Not implemented.", 501},
{RpcNotReady, "notReady", "Not ready to handle this request.", 503},
{RpcNotSupported, "notSupported", "Operation not supported.", 501},
{RpcNoClosed, "noClosed", "Closed ledger is unavailable.", 503},
{RpcNoCurrent, "noCurrent", "Current ledger is unavailable.", 503},
{RpcNotSynced, "notSynced", "Not synced to the network.", 503},
{RpcNoEvents, "noEvents", "Current transport does not support events.", 405},
{RpcNoNetwork, "noNetwork", "Not synced to the network.", 503},
{RpcWrongNetwork, "wrongNetwork", "Wrong network.", 503},
{RpcNoPermission, "noPermission", "You don't have permission for this command.", 401},
{RpcNoPfRequest, "noPathRequest", "No pathfinding request in progress.", 404},
{RpcObjectNotFound, "objectNotFound", "The requested object was not found.", 404},
{RpcPublicMalformed, "publicMalformed", "Public key is malformed.", 400},
{RpcSendmaxMalformed, "sendMaxMalformed", "SendMax amount malformed.", 400},
{RpcSigningMalformed, "signingMalformed", "Signing of transaction is malformed.", 400},
{RpcSlowDown, "slowDown", "You are placing too much load on the server.", 429},
{RpcSrcActMalformed, "srcActMalformed", "Source account is malformed.", 400},
{RpcSrcActMissing, "srcActMissing", "Source account not provided.", 400},
{RpcSrcActNotFound, "srcActNotFound", "Source account not found.", 404},
{RpcDelegateActNotFound, "delegateActNotFound", "Delegate account not found.", 404},
{RpcSrcCurMalformed, "srcCurMalformed", "Source currency is malformed.", 400},
{RpcSrcIsrMalformed, "srcIsrMalformed", "Source issuer is malformed.", 400},
{RpcStreamMalformed, "malformedStream", "Stream malformed.", 400},
{RpcTooBusy, "tooBusy", "The server is too busy to help you now.", 503},
{RpcTxnNotFound, "txnNotFound", "Transaction not found.", 404},
{RpcUnknownCommand, "unknownCmd", "Unknown method.", 405},
{RpcOracleMalformed, "oracleMalformed", "Oracle request is malformed.", 400},
{RpcBadCredentials, "badCredentials", "Credentials do not exist, are not accepted, or have expired.", 400},
{RpcTxSigned, "transactionSigned", "Transaction should not be signed.", 400},
{RpcDomainMalformed, "domainMalformed", "Domain is malformed.", 400},
{RpcEntryNotFound, "entryNotFound", "Entry not found.", 400},
{RpcUnexpectedLedgerType, "unexpectedLedgerType", "Unexpected ledger type.", 400},
};
// clang-format on

View File

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

View File

@@ -240,7 +240,8 @@ skip(LedgerIndex ledger) noexcept
{
return {
ltLEDGER_HASHES,
indexHash(LedgerNameSpace::SkipList, static_cast<std::uint32_t>(ledger) >> 16)};
indexHash(
LedgerNameSpace::SkipList, std::uint32_t(static_cast<std::uint32_t>(ledger) >> 16))};
}
Keylet const&

View File

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

View File

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

View File

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

View File

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

View File

@@ -864,7 +864,7 @@ STAmount::canonicalize()
{
Throw<std::runtime_error>("Native currency amount out of range");
}
if (!native() && value_ > kMaxMpTokenAmount)
else 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");
}
if (v.isObject())
else 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.

View File

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

Some files were not shown because too many files have changed in this diff Show More