Compare commits

...

62 Commits

Author SHA1 Message Date
Mayukha Vadari
5a76baabb3 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-08-17 22:02:17 -04:00
Copilot
820ca5b332 refactor: Convert boost::beast::string_view to std::string_view (#6306)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Timur Yalymov <36795566+tyalymov@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-08-17 23:19:56 +00:00
Gregory Tsipenyuk
1b226c8b2e perf: Optimize MPT freeze checks to reduce redundant state reads (#7411)
Co-authored-by: Chenna Keshava B S <21219765+ckeshava@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-17 21:15:16 +00:00
Gregory Tsipenyuk
ca6121c5b3 feat: Enforce MPT CanTransfer on AMM LPTokens transfers (#7418) 2026-08-17 20:58:46 +00:00
Gregory Tsipenyuk
c49789086a fix: Extend locked-MPToken unauthorize check to fixCleanup3_4_0 (#8004) 2026-08-17 12:52:20 +00:00
Bart
5337d028a2 refactor: Use unsigned int for branch-related operations (#7938)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 10:07:14 +00:00
Ed Hennis
43d842926a refactor: Rewrite Transactor::operator() to early return (#8003) 2026-08-14 20:18:33 +00:00
Bart
2adffaef72 refactor: Remove support for protocol version 2.1 (#7432)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 15:36:47 +00:00
Ayaz Salikhov
bd87edfc75 test: Check versioned tools in check-tools & print nicely (#8030) 2026-08-14 14:07:55 +00:00
Mayukha Vadari
d34aa37b3c refactor: Use std::format instead of boost::format where it fits (#7996)
Co-authored-by: Timur Yalymov <36795566+tyalymov@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-08-14 13:49:08 +00:00
Ayaz Salikhov
a0074f83d3 build: Fix versioned tools for exec wrappers (#8027) 2026-08-14 10:06:49 +00:00
Ayaz Salikhov
028ccea7a1 build: Add curl to packaging images (#8024) 2026-08-13 17:48:35 +00:00
Pratik Mankawde
df85d43d8a test: Make Drop50 message drop deterministic in LedgerReplayer test (#7964)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-08-13 16:54:58 +00:00
Jingchen
8e9b1791c5 feat: Add a new closed ended vault to extend SAV (#7921)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-08-12 17:07:43 +00:00
Ayaz Salikhov
946827b9bd build: Respect lld linker if it gets auto-selected (#8011) 2026-08-12 12:11:28 -04:00
Vito Tumas
91360c5126 test: Fix LoanBatch broker cover rates and schedule overflow (#7967) 2026-08-12 12:11:28 -04:00
Timur Yalymov
af36890c11 test: Verify private-vault DEX permissions survive domain loss (#7937) 2026-08-12 12:11:28 -04:00
Timur Yalymov
1281c7a222 refactor: Drop unnecessary associateAsset calls from loan delete paths (#7986)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 12:10:17 -04:00
Mayukha Vadari
373952a62c Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-08-12 11:07:38 -04:00
Ayaz Salikhov
739ef8639a build: Respect lld linker if it gets auto-selected (#8011) 2026-08-12 14:03:37 +00:00
Vito Tumas
dc8973053e test: Fix LoanBatch broker cover rates and schedule overflow (#7967) 2026-08-12 13:42:55 +00:00
Timur Yalymov
d06a03baa6 test: Verify private-vault DEX permissions survive domain loss (#7937) 2026-08-12 13:42:02 +00:00
Timur Yalymov
050dbc628f refactor: Drop dead associateAsset calls from loan delete paths (#7986)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 13:41:30 +00:00
Copilot
153b7839a7 refactor: Replace boost::filesystem with std::filesystem across the codebase (#7012)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2026-08-12 13:40:39 +00:00
Mayukha Vadari
261b5201e0 fix: use lowercase rpc namespace after rename 2026-08-11 15:02:12 -04:00
Mayukha Vadari
890b2cfa17 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-08-11 14:21:43 -04:00
Gregory Tsipenyuk
26cc683ec1 fix: Assorted MPT/DEX fixes (#7299)
Co-authored-by: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com>
2026-08-11 18:15:51 +00:00
Mayukha Vadari
6ca2fb84d4 refactor: Replace Boost trim and to_lower with libxrpl helpers (#7995) 2026-08-11 18:15:35 +00:00
klemenfn
a3147740f2 build: Fix GCC 14 compilation (#7981)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-08-11 13:24:56 +00:00
luisfernandomendozav
d43e5acaa7 fix: Validate account/ident type in gateway_balances (#7655) 2026-08-11 13:23:07 +00:00
Ayaz Salikhov
c74724a719 build: Reimagine linker warnings in different scenarios (#7974) 2026-08-11 12:44:01 +00:00
Alex Kremer
0a572833ea chore: Gtest migration followups second pass (#7888) 2026-08-11 12:38:40 +00:00
Chenna Keshava B S
639943123c fix: Validate buy/sell flag in nft RPC input (#7725) 2026-08-11 00:49:02 +00:00
Bryan
909cc5bba9 fix: Prevent silent zero AMM clawbacks due to integer MPT rounding (#7704)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-08-10 21:37:53 +00:00
Peter Chen
6f5de9067a chore: Mark unreachable branches in Confidential Transfer with UNREACHABLE (#7903) 2026-08-10 21:37:38 +00:00
Kassaking7
60291c3ed6 fix: Allow OverrideFreeze to bypass individual/deep freeze on AMM trust lines (#6959) 2026-08-10 21:34:28 +00:00
Braedon Klock
4173f7e499 fix: Validate account_lines peer field type (#7728)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-10 21:30:06 +00:00
Mayukha Vadari
f03f890511 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-08-10 14:53:17 -04:00
Ayaz Salikhov
9c292fbe4f build: Install conan configuration/profiles inside Nix devshell (#7997) 2026-08-10 17:49:29 +00:00
yinyiqian1
b19c3c64f2 fix: Add zero keylet check in credential (#7971) 2026-08-10 17:47:16 +00:00
Mayukha Vadari
a0e1e578a0 refactor: Remove operator!= overloads that C++20 synthesizes (#7994) 2026-08-10 17:23:02 +00:00
Mayukha Vadari
07aa97fda4 test: Use std::string::starts_with/ends_with instead of Boost (#7992) 2026-08-10 17:22:40 +00:00
Mayukha Vadari
4f8819565a fix: Assorted cleanup fixes (#7988) 2026-08-10 17:18:22 +00:00
Mayukha Vadari
6580b200db refactor: Replace boost::lexical_cast with existing alternatives (#7991) 2026-08-10 17:10:18 +00:00
Mayukha Vadari
2967f1f0cc chore: Remove unreferenced legacy documents (#7989) 2026-08-10 17:06:29 +00:00
Mayukha Vadari
71e972cbed refactor: Act on TODOs that are unblocked by C++23 (#7990) 2026-08-10 17:05:18 +00:00
Ayaz Salikhov
a24caaa6ea docs: Rearrange & simplify build/nix/environment docs (#7985) 2026-08-10 15:00:30 +00:00
Ayaz Salikhov
07b9c59b89 build: Remove protobuf dependencies from Nix (#7984) 2026-08-10 13:08:15 +00:00
Sergey Kuznetsov
63d8772f69 chore: Remove corrosion from nix (#7982) 2026-08-10 11:58:49 +00:00
Mayukha Vadari
553a36ac6f Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-07-27 15:39:37 -04:00
Mayukha Vadari
e6d849dd01 fix pre-commit 2026-07-27 15:39:18 -04:00
Mayukha Vadari
a1ac0a31de fix changelog 2026-07-21 18:41:28 -04:00
Mayukha Vadari
1368a1cdf1 fix clang-tidy 2026-07-21 18:40:38 -04:00
Mayukha Vadari
91724750fb fix build issues 2026-07-21 18:38:48 -04:00
Mayukha Vadari
8febef6777 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-07-21 17:59:01 -04:00
copilot-swe-agent[bot]
3bc338211a Merge develop and resolve conflicts
- Updated Json::Value to json::Value (lowercase namespace)
- Updated safe_cast to safeCast
- Updated constant naming (e.g., defaultAutoFillFeeMultiplier to kDefaultAutoFillFeeMultiplier)
- Merged testAugmentedFields with testFailHardValidation in Submit_test.cpp
- Updated namespace from xrpl to xrpl::test for test files
- Updated beast::unit_test::suite to beast::unit_test::Suite

Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-05-15 17:50:26 +00:00
Mayukha Vadari
1b05dba80b fix pre-commit issues 2026-04-03 11:00:23 -04:00
Mayukha Vadari
3595ad0928 fix issues 2026-04-03 10:56:04 -04:00
copilot-swe-agent[bot]
0af23e1466 Extract helper function to avoid code duplication and update API-CHANGELOG
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-04-03 10:55:42 -04:00
copilot-swe-agent[bot]
cfcf1d30e2 Fix includes in Submit_test.cpp
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-04-03 10:54:51 -04:00
copilot-swe-agent[bot]
6f8618b2f2 Fix test to properly construct transaction JSON for sign-and-submit
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-04-03 10:54:51 -04:00
copilot-swe-agent[bot]
361f3469b8 Add augmented fields to sign-and-submit mode and create test
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-04-03 10:54:51 -04:00
266 changed files with 8978 additions and 3057 deletions

View File

@@ -7,6 +7,7 @@ ignorePaths:
- cmake/**
- LICENSE.md
- .clang-tidy
- nix/check-tools/*.txt # generated, and full of Nix store hashes
language: en
allowCompoundWords: true # TODO (#6334)
ignoreRandomStrings: true
@@ -365,6 +366,7 @@ words:
- xchain
- ximinez
- XMACRO
- xored
- xrpkuwait
- xrpl
- xrpld

4
.envrc
View File

@@ -1,3 +1,7 @@
watch_file nix/*.nix
# The dev shell derivation includes all of conan/ (see nix/devshell.nix), so any
# change in there has to invalidate direnv's cached environment.
watch_dir conan
use flake

View File

@@ -1,5 +1,5 @@
{
"image_tag": "sha-fecfc0c",
"image_tag": "sha-a0074f8",
"configs": {
"ubuntu": [
{

View File

@@ -41,7 +41,7 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

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-fecfc0c"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-a0074f8"
permissions:
contents: read
issues: write

View File

@@ -40,7 +40,7 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
env:
REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}

View File

@@ -39,6 +39,7 @@ This section contains changes targeting a future version.
- `TRANSACTION_FLAGS`: Maps transaction type names to their supported flags and flag values.
- `LEDGER_ENTRY_FLAGS`: Maps ledger entry type names to their flags and flag values.
- `ACCOUNT_SET_FLAGS`: Maps AccountSet flag names (asf flags) to their numeric values.
- `submit`: Augmented response fields (`accepted`, `applied`, `broadcast`, `queued`, `kept`, `account_sequence_next`, `account_sequence_available`, `open_ledger_cost`, `validated_ledger_index`) are now included in sign-and-submit mode. Previously, these fields were only returned when submitting a binary transaction blob.
### Bugfixes
@@ -54,6 +55,8 @@ This section contains changes targeting a future version.
- `submit`: The `fail_hard` field now returns an error if the value is not a boolean. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- `subscribe`: The `taker` field in the `books` array now returns `actMalformed` instead of `badIssuer` if the value is not a valid account. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- Fixed a bug in `Forwarded` HTTP header parsing where the extracted IP address could be incorrect when no comma or semicolon delimiter follows the address. This could cause the server to misidentify a client's IP address when operating behind a reverse proxy. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- `gateway_balances`: The `account` and `ident` fields now return an `invalidParams` error if the value is not a string, instead of an `internal` error. [#7655](https://github.com/XRPLF/rippled/pull/7655)
- `account_lines`: The `peer` field now returns an error if the value is not a string. [#7728](https://github.com/XRPLF/rippled/pull/7728)
## XRP Ledger server version 3.1.0

View File

@@ -4,34 +4,14 @@
## Minimum Requirements
See [System Requirements](https://xrpl.org/system-requirements.html).
For the hardware needed to run a node, see
[System Requirements](https://xrpl.org/system-requirements.html).
Building xrpld generally requires Git, Python, Conan, CMake, and a C++
compiler.
- [Python](https://www.python.org/downloads/)
- [Conan](https://conan.io/downloads.html)
- [CMake](https://cmake.org/download/)
You can verify that the required tools are installed and runnable with:
```bash
./bin/check-tools.sh
```
`xrpld` is written in the C++23 dialect. The [tested compiler versions][cpp23-support] are:
| Compiler | Version |
| ----------- | --------------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 21 |
| MSVC | 19.44[^windows] |
For the software needed to build xrpld, see the
[environment setup guide](./docs/build/environment.md).
## Operating Systems
Please see the [environment setup guide](./docs/build/environment.md) for detailed instructions for all platforms.
### Linux
The Ubuntu Linux distribution has received the highest level of quality
@@ -47,9 +27,8 @@ CI testing is done in macOS 26 (Tahoe), but the build defaults `CMAKE_OSX_DEPLOY
### Windows
Windows is used by some engineers for development only.
[^windows]: Windows is not recommended for production use.
Windows is used by some engineers for development only, and is not recommended
for production use.
## Steps
@@ -74,37 +53,25 @@ releases](https://github.com/XRPLF/rippled/releases).
### Set Up Conan
After you have a [C++ development environment](./docs/build/environment.md) ready with Git, Python,
Conan, CMake, and a C++ compiler, you may need to set up your Conan profile.
These instructions assume a basic familiarity with Conan and CMake. If you are
unfamiliar with Conan, then please read [this crash course](./docs/build/conan.md) or the official
[Getting Started][conan-getting-started] walkthrough.
#### Profiles
We recommend that you install our Conan profiles:
Once your [development environment](./docs/build/environment.md) is ready, set
Conan up for this repository:
```bash
conan config install conan/profiles/ -tf $(conan config home)/profiles/
./conan/init.sh
```
You can check your Conan profile by running:
That installs our [`global.conf`](./conan/global.conf), our Conan
[profiles](./conan/profiles), and the `xrplf` remote that hosts some of our
dependencies. It honours `CONAN_HOME` and never deletes an existing Conan home,
so it is safe to re-run — it only overwrites the files it manages.
```bash
conan profile show
```
> [!TIP]
> In the [Nix development shell](./docs/build/nix.md#conan-configuration) this is
> already done for you: the script runs on entry.
If the default profile is not suitable for your environment, you can create a custom profile and pass it to Conan.
More information on customizing Conan can be found in the [Advanced Conan configuration](./docs/build/advanced_conan.md).
#### Add xrplf remote
Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
```bash
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
```
You can inspect the resulting profile with `conan profile show`. If it is not
suitable for your environment, create a custom profile and pass it to Conan — see
[Advanced Conan configuration](./docs/build/advanced_conan.md).
### Set Up Ccache
@@ -269,10 +236,14 @@ which is only enabled when the `coverage` option is set, e.g. with
Prerequisites for the coverage report:
- [gcovr tool][gcovr] (can be installed e.g. with [pip][python-pip])
- `gcov` for GCC (installed with the compiler by default) or
- `llvm-cov` for Clang (installed with the compiler by default)
- `gcov` for GCC or `llvm-cov` for Clang, usually installed with the compiler
- `Debug` build type
> [!NOTE]
> Clang coverage is not available in the [Nix development shell](./docs/build/nix.md#building-xrpld-in-the-nix-shell):
> its `clang` shells do not ship `llvm-cov`. Use a `gcc` shell instead (`.#gcc`,
> or `.#gcc-plain` on Linux), which provides a `gcov` matching its compiler.
A coverage report is created when the following steps are completed, in order:
1. `xrpld` binary built with instrumentation data, enabled by the `coverage`
@@ -389,10 +360,14 @@ After any updates or changes to dependencies, you may need to do the following:
4. [Regenerate lockfile](./docs/build/advanced_conan.md#conan-lockfile).
5. Re-run [conan install](#build-and-test).
If you are using the Nix development shell, whether prebuilt Conan binaries apply
depends on your platform — see
[Prebuilt packages](./docs/build/nix.md#prebuilt-packages).
#### ERROR: Package not resolved
If you're seeing an error like `ERROR: Package 'snappy/1.1.10' not resolved: Unable to find 'snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246' in remotes.`,
please [add `xrplf` remote](#add-xrplf-remote) or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes).
please [set Conan up](#set-up-conan) so the `xrplf` remote is configured, or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes).
### `protobuf/port_def.inc` file not found
@@ -412,7 +387,6 @@ For example, if you want to build Debug:
1. For conan install, pass `--settings build_type=Debug`
2. For cmake, pass `-DCMAKE_BUILD_TYPE=Debug`
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23
[conan-getting-started]: https://docs.conan.io/en/latest/getting_started.html
[unity-build]: https://en.wikipedia.org/wiki/Unity_build
[gcovr]: https://gcovr.com/en/stable/getting-started.html

View File

@@ -15,10 +15,14 @@
# - Windows: the core build tools only (CMake, Conan, Git, Python).
# MSVC is expected to be provided separately and is not checked here.
#
# Some tools (clang-format, doxygen, gcovr, gh, git-cliff, gpg, pre-commit,
# run-clang-tidy) are present in our Linux CI images and in local development
# setups, but not in the macOS CI environment. They are checked everywhere
# except when running in CI on macOS.
# Some tools (clang-format, clang-tidy, doxygen, gcovr, gh, git-cliff, gpg,
# pre-commit, run-clang-tidy) are present in our Linux CI images and in local
# development setups, but not in the macOS CI environment. They are checked
# everywhere except when running in CI on macOS.
#
# Tools that Nix also exposes under a version-suffixed name (`clang-tidy-22`,
# `g++-15`, ...) are probed under both names: a suffixed name can break while
# the plain one still works (see mkVersionedToolLinks in nix/packages.nix).
#
# Environment variables:
# CI if set, skip the tools above when on macOS.
@@ -26,14 +30,27 @@
set -uo pipefail
# Version suffixes of the Nix tool links, tracking nix/packages.nix.
gcc_version=15
llvm_version=22
missing=()
checked=0
# tool_path <name>
# Fully resolved path of a tool, so the snapshots record which derivation
# provides it. Prints nothing when it isn't on PATH.
tool_path() {
local path
path="$(command -v "$1" 2>/dev/null)" || return 0
readlink -f "${path}" 2>/dev/null || printf '%s' "${path}"
}
# check <name> [probe-command...]
# Runs the probe (default: "<name> --version"), capturing both stdout and
# stderr, and prints one aligned line: the status, the name, and the first
# non-blank line of the probe output (its version). Records <name> as missing
# if the command is not found or exits non-zero.
# stderr, and prints three lines: the status and name, the first non-blank line
# of the probe output (its version, or the error when it failed), and the tool's
# resolved path. Records <name> as missing if it is not found or exits non-zero.
check() {
local name="$1"
shift
@@ -43,14 +60,17 @@ check() {
fi
checked=$((checked + 1))
local output version
local output version path
path="$(tool_path "${name}")"
if output="$("${probe[@]}" 2>&1)"; then
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
printf ' [ ok ] %-20s %s\n' "${name}" "${version}"
printf '%s\n' "${name}"
else
printf ' [MISS] %s\n' "${name}"
printf ' %s\n' "${name}"
missing+=("${name}")
fi
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
printf ' %s\n' "${version:-(no output)}"
printf ' %s\n' "${path:-(not found)}"
}
case "$(uname -s)" in
@@ -82,7 +102,9 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
echo "Development tooling:"
check ccache
check clang
check "clang-${llvm_version}"
check clang++
check "clang++-${llvm_version}"
check ClangBuildAnalyzer
check curl
check file
@@ -101,7 +123,14 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
# setups, but not in the macOS CI environment. So check them everywhere
# except when running in CI on macOS.
if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then
check clang-apply-replacements
check "clang-apply-replacements-${llvm_version}"
check clang-format
check "clang-format-${llvm_version}"
# clang-tidy leads --version with the LLVM banner, not the version.
tidy_probe="--version | grep -m1 -oE 'LLVM version [0-9.]+'"
check clang-tidy sh -c "clang-tidy ${tidy_probe}"
check "clang-tidy-${llvm_version}" sh -c "clang-tidy-${llvm_version} ${tidy_probe}"
check dot
check doxygen
check gcovr
@@ -112,6 +141,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
# pre-commit, or its alternative implementation prek
check pre-commit sh -c 'pre-commit --version || prek --version'
check run-clang-tidy run-clang-tidy --help
check "run-clang-tidy-${llvm_version}" "run-clang-tidy-${llvm_version}" --help
fi
fi
@@ -126,7 +156,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check cargo-audit cargo audit --version
check cargo-llvm-cov cargo llvm-cov --version
check cargo-nextest cargo nextest --version
check clippy clippy-driver --version
check clippy-driver
check rust-analyzer
check rustc
check rustfmt
@@ -138,7 +168,11 @@ if [ "${os}" = "linux" ]; then
echo
echo "GCC toolchain:"
check gcc
check "gcc-${gcc_version}"
check g++
check "g++-${gcc_version}"
check cpp
check "cpp-${gcc_version}"
check gcov
echo
@@ -163,9 +197,9 @@ else
checked=$((checked + 1))
tmp_clone="$(mktemp -d)"
if git clone --depth 1 https://github.com/XRPLF/actions.git "${tmp_clone}/actions" >/dev/null 2>&1; then
printf ' [ ok ] git clone over HTTPS\n'
printf ' git clone over HTTPS\n'
else
printf ' [MISS] git clone over HTTPS\n'
printf ' git clone over HTTPS\n'
missing+=("git-https-clone")
fi
rm -rf "${tmp_clone}"
@@ -173,9 +207,9 @@ fi
echo
if [ "${#missing[@]}" -eq 0 ]; then
echo "All ${checked} checked tools are present and runnable."
echo "All ${checked} checked tools are present and runnable."
else
echo "Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2
echo "Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2
for tool in "${missing[@]}"; do
echo " - ${tool}" >&2
done

View File

@@ -266,10 +266,50 @@ elseif(use_lld)
)
if("${LD_VERSION}" MATCHES "LLD")
target_link_libraries(common INTERFACE -fuse-ld=lld)
# remembered for the linker flag probe below
set(fuse_ld_flag "-fuse-ld=lld")
endif()
unset(LD_VERSION)
endif()
# Linker warnings are errors where we control the toolchain and the dependencies: CI and the Nix dev shell.
# On non-Nix macOS we suppress the deployment target warning: an old Conan profile may not pin os.version.
# Only the new Apple linker understands the flag, so probe the actual linker (lld may be selected above).
if(is_macos OR is_linux)
if(is_ci OR is_nix_compiler)
if(is_macos)
set(fatal_warnings_flag "-Wl,-fatal_warnings")
else()
set(fatal_warnings_flag "-Wl,--fatal-warnings")
endif()
message(
STATUS
"Treating all linker warnings as errors (${fatal_warnings_flag})"
)
target_link_options(common INTERFACE "${fatal_warnings_flag}")
unset(fatal_warnings_flag)
elseif(is_macos)
set(silence_flag "-Wl,-deployment_target_mismatches,suppress")
set(probe_flags ${fuse_ld_flag} "${silence_flag}")
include(CheckLinkerFlag)
check_linker_flag(
CXX
"${probe_flags}"
have_deployment_target_mismatches
)
if(have_deployment_target_mismatches)
message(
STATUS
"Silencing macOS deployment target mismatch warnings (${silence_flag})"
)
target_link_options(common INTERFACE "${silence_flag}")
endif()
unset(probe_flags)
unset(silence_flag)
endif()
endif()
unset(fuse_ld_flag)
if(assert)
foreach(var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
string(REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")

View File

@@ -44,6 +44,7 @@ setup_target_for_coverage_gcovr(
EXCLUDE
"src/test"
"src/tests"
"src/benchmarks"
"include/xrpl/beast/test"
"include/xrpl/beast/unit_test"
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"

21
conan/init.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Install our Conan configuration, profiles and the xrplf remote into CONAN_HOME.
# Safe to re-run; never deletes the Conan home.
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CONAN_DIR="$(conan config home)"
echo "Installing Conan configuration into ${CONAN_DIR}"
conan config install "${SCRIPT_DIR}/global.conf"
conan config install "${SCRIPT_DIR}/profiles" -tf "${CONAN_DIR}/profiles"
# This script manages these files, so make them read-only - Conan does not
# preserve the source mode. Only the files: the directories must stay writable
# for `conan config install` to replace them.
chmod a-w "${CONAN_DIR}/global.conf"
find "${CONAN_DIR}/profiles" -type f -exec chmod a-w {} +
echo "Adding the xrplf Conan remote"
# --index 0: our patched recipes must win over Conan Center.
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/

View File

@@ -1,10 +1,7 @@
{% set os = detect_api.detect_os() %}
{% set arch = detect_api.detect_arch() %}
{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}
{% set compiler_version = version %}
{% if os == "Linux" %}
{% set compiler_version = detect_api.default_compiler_version(compiler, version) %}
{% endif %}
{% if os == "Macos" %}
{# Minimum macOS the dependencies target. #}
{# Without this, Conan builds each dependency against the (possibly newer) host SDK, so the #}

View File

@@ -6,22 +6,52 @@ This document explains how to set one up.
## Tested compiler versions
`xrpld` is built in the **C++23** dialect by default.
Make sure your toolchain is recent enough — the compiler versions currently tested in CI are:
`xrpld` is built in the **C++23** dialect by default, so your toolchain has to
support it — see [compiler support for C++23][cpp23-support].
The versions currently tested in CI are:
| Compiler | Version |
| ----------- | ------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| MSVC | 19.44 |
| Compiler | Version |
| ----------- | ------------------ |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 21 |
| MSVC | Visual Studio 2026 |
LLVM tools (`clang-tidy` and `clang-format`) are also pinned to version 22.
### Older compilers
Older compilers may fail to build the latest `develop` code: the codebase now
relies on C++23 features and has been adjusted for `clang-tidy`.
If the latest code doesn't build for you, update your build toolchain first.
If updating isn't an option for you, we do accept pull requests that fix builds
on older compilers, as long as the change is small and doesn't make the code
harder to read. What we can't promise is that older compilers will keep working:
only the versions in the table above are tested in CI, and we won't hold back
the use of C++23 features or add invasive workarounds to keep an untested
compiler building. Treat support for anything outside the table as best-effort.
## Required tools
Besides a compiler, building `xrpld` requires:
| Tool | Minimum version |
| ------------------------------------------- | --------------- |
| [Git](https://git-scm.com/downloads) | any recent |
| [Python](https://www.python.org/downloads/) | 3.11 |
| [Conan](https://conan.io/downloads.html) | 2.17 |
| [CMake](https://cmake.org/download/) | 3.16 |
On Linux and macOS, the [Nix development shell](./nix.md) provides all of them
(see below). On Windows they have to be installed manually.
Once they are in place, verify that everything is installed and runnable with:
```bash
./bin/check-tools.sh
```
## Linux and macOS
The **recommended way** to get a development environment on Linux and macOS is
@@ -39,20 +69,15 @@ Clang. If you instead opt to use your system-wide Apple Clang (via
below).
See [Using the Nix development shell](./nix.md) for installation and usage
details, including how to select a different compiler.
> [!NOTE]
> Using Nix is not mandatory. Any custom environment (Homebrew packages or
> anything else) will continue to work, but then it is up to you to keep it in
> sync with the environment used in CI. Nix unifies the development environment
> for everyone and synchronizes updates, which is why we recommend it.
details, including how to select a different compiler and why we recommend Nix
over a hand-maintained environment.
### macOS: managing the Apple Clang version
If you use your system-wide Apple Clang on macOS (via `nix develop .#apple-clang`),
the compiler version is whatever your installed Xcode (or Command Line Tools)
provides. The following command should return a version greater than or equal to
the [minimum required](#tested-compiler-versions):
the [tested one](#tested-compiler-versions):
```bash
clang --version
@@ -89,23 +114,23 @@ building xrpld. You may want to install and pin a specific version of Xcode:
Nix is not available on Windows, so the required tools have to be installed
manually:
- [Visual Studio 2022](https://visualstudio.microsoft.com/) with the
- [Visual Studio 2026](https://visualstudio.microsoft.com/) with the
**"Desktop development with C++"** workload — this provides MSVC and the
"x64 Native Tools Command Prompt".
"x64 Native Tools Command Prompt". CI configures CMake with the
`Visual Studio 18 2026` generator.
- [Git for Windows](https://git-scm.com/download/win)
- [Python 3.11](https://www.python.org/downloads/), or higher
- [Conan 2.17](https://conan.io/downloads.html), or higher
- [CMake 3.22](https://cmake.org/download/), or higher
> [!NOTE]
> Windows is used for development only and is not recommended for production.
- Python, Conan, and CMake, at the versions listed in
[Required tools](#required-tools).
## Clang-tidy
`clang-tidy` is required to run static analysis checks locally (see
[CONTRIBUTING.md](../../CONTRIBUTING.md)). It is not required to build the
project. This project currently uses `clang-tidy` version 22.
project. The version this project uses is listed in
[Tested compiler versions](#tested-compiler-versions).
On Linux and macOS, the [Nix development shell](./nix.md) provides `clang-tidy`
22 out of the box — run it via `run-clang-tidy`. No separate installation is
needed.
On Linux and macOS, the [Nix development shell](./nix.md) provides that exact
version out of the box — run it via `run-clang-tidy`. No separate installation
is needed.
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23

32
docs/build/nix.md vendored
View File

@@ -120,7 +120,7 @@ nix develop -c "$SHELL"
>
> If it doesn't, either adjust your shell configuration so it doesn't override `$PATH`, or use [direnv](#automatic-activation-with-direnv) (below), which loads the environment _after_ your shell config and so takes precedence regardless of the shell you use.
## Building xrpld with Nix
## Building xrpld in the Nix shell
Once inside the Nix development shell, follow the standard [build instructions](../../BUILD.md#steps). The Nix shell provides all necessary tools (CMake, Ninja, Conan, etc.).
@@ -128,6 +128,28 @@ Coverage builds (`-Dcoverage=ON`) work in the `gcc` shell (and `gcc-plain` on Li
each ships a `gcov` matching its compiler, since Nix's cc-wrapper does not expose one.
The `clang` shells do not include `llvm-cov`, so use a `gcc` shell for coverage.
## Conan configuration
The shell runs [`conan/init.sh`](../../conan/init.sh) on entry, so
[Set Up Conan](../../BUILD.md#set-up-conan) is already done for you. It installs
into the shell's own Conan home: `CONAN_HOME=~/.conan2-nix`.
### Prebuilt packages
On **Linux**, the binaries on the `xrplf` remote are built in this same Nix
environment — CI runs in Docker images that bundle the dev shell's toolchain (see
[`nix/docker`](../../nix/docker)) — so `.#gcc` and `.#clang` can reuse them. The
`-plain` shells do not match that toolchain's glibc, so binaries from the remote
are not a reliable match there.
On **macOS**, CI builds with Apple Clang, so the remote holds nothing for the Nix
`clang` toolchain and dependencies are compiled locally. We do not publish
Nix-built macOS binaries because a Conan package ID records the compiler version
but not the nixpkgs revision.
To compile everything from source, add `--build '*'` to the `conan install`
command.
## Automatic Activation with direnv
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
@@ -142,14 +164,6 @@ The repository already ships an `.envrc` at its root that activates the Nix flak
> [!NOTE]
> direnv only caches the `.direnv` directory (already listed in `.gitignore`); no other repository files are affected.
## Conan and Prebuilt Packages
Please note that there is no guarantee that binaries from conan cache will work when using nix. If you encounter any errors, please use `--build '*'` to force conan to compile everything from source:
```bash
conan install .. --output-folder . --build '*' --settings build_type=Release
```
## Updating `flake.lock` file
To update `flake.lock` to the latest revision use `nix flake update` command.

View File

@@ -1,24 +0,0 @@
/*!
\page somestatechart Example state diagram
\startuml SomeState "my state diagram"
scale 600 width
[*] -> State1
State1 --> State2 : Succeeded
State1 --> [*] : Aborted
State2 --> State3 : Succeeded
State2 --> [*] : Aborted
state State3 {
state "Accumulate Enough Data\nLong State Name" as long1
long1 : Just a test
[*] --> long1
long1 --> long1 : New Data
long1 --> ProcessData : Enough Data
}
State3 --> State3 : Failed
State3 --> [*] : Succeeded / Save Result
State3 --> [*] : Aborted
\enduml
*/

View File

@@ -1,6 +1,6 @@
#pragma once
#include <boost/filesystem.hpp>
#include <filesystem>
namespace xrpl {
@@ -13,6 +13,6 @@ namespace xrpl {
* @throws runtime_error
*/
void
extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst);
extractTarLz4(std::filesystem::path const& src, std::filesystem::path const& dst);
} // namespace xrpl

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Slice.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
@@ -156,6 +157,19 @@ public:
}
/** @} */
/**
* Set every byte in the buffer to the given value.
*
* The size is unchanged, and this is a no-op on an empty buffer.
*
* @param value the byte to write to every position.
*/
void
fill(std::uint8_t value) noexcept
{
std::fill_n(p_.get(), size_, value);
}
/**
* Reset the buffer.
* All memory is deallocated. The resulting size is 0.
@@ -226,10 +240,4 @@ operator==(Buffer const& lhs, Buffer const& rhs) noexcept
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
inline bool
operator!=(Buffer const& lhs, Buffer const& rhs) noexcept
{
return !(lhs == rhs);
}
} // namespace xrpl

View File

@@ -1,24 +1,79 @@
#pragma once
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <cstddef>
#include <filesystem>
#include <optional>
#include <string>
#include <system_error>
namespace xrpl {
std::string
getFileContents(
boost::system::error_code& ec,
boost::filesystem::path const& sourcePath,
std::error_code& ec,
std::filesystem::path const& sourcePath,
std::optional<std::size_t> maxSize = std::nullopt);
void
writeFileContents(
boost::system::error_code& ec,
boost::filesystem::path const& destPath,
std::error_code& ec,
std::filesystem::path const& destPath,
std::string const& contents);
/**
* Generate a unique, non-existing path under @p base whose filename starts with
* @p prefix and ends with a random hex suffix.
*
* Attempts up to @p maxAttempts paths. Throws `std::runtime_error` if a unique
* path cannot be found or if the filesystem returns an error while checking for
* existence.
*/
std::filesystem::path
uniqueRandomPath(
std::filesystem::path const& base,
std::string const& prefix = "",
std::size_t maxAttempts = 100);
/**
* RAII temporary directory.
*
* The directory and all its contents are deleted when
* the instance of `TempDir` is destroyed.
*/
class TempDir
{
std::filesystem::path path_;
public:
#if !GENERATING_DOCS
TempDir(TempDir const&) = delete;
TempDir&
operator=(TempDir const&) = delete;
#endif
/**
* Construct a temporary directory.
*/
TempDir();
/**
* Destroy a temporary directory.
*/
~TempDir();
/**
* Get the native path for the temporary directory.
*/
[[nodiscard]] std::string
path() const;
/**
* Get the native path for a file.
*
* The file does not need to exist.
*/
[[nodiscard]] std::string
file(std::string const& name) const;
};
} // namespace xrpl

View File

@@ -96,9 +96,6 @@ public:
SharedIntrusive&
operator=(SharedIntrusive const& rhs);
bool
operator!=(std::nullptr_t) const;
bool
operator==(std::nullptr_t) const;

View File

@@ -111,13 +111,6 @@ SharedIntrusive<T>::operator=(SharedIntrusive<TT>&& rhs)
return *this;
}
template <class T>
bool
SharedIntrusive<T>::operator!=(std::nullptr_t) const
{
return this->get() != nullptr;
}
template <class T>
bool
SharedIntrusive<T>::operator==(std::nullptr_t) const

View File

@@ -3,8 +3,8 @@
#include <xrpl/beast/utility/Journal.h>
#include <boost/beast/core/string.hpp>
#include <boost/filesystem.hpp>
#include <filesystem>
#include <fstream>
#include <map>
#include <memory>
@@ -84,7 +84,7 @@ private:
* @return `true` if the file was opened.
*/
bool
open(boost::filesystem::path const& path);
open(std::filesystem::path const& path);
/**
* Close and re-open the system file associated with the log
@@ -133,7 +133,7 @@ private:
private:
std::unique_ptr<std::ofstream> stream_;
boost::filesystem::path path_;
std::filesystem::path path_;
};
std::mutex mutable mutex_;
@@ -152,7 +152,7 @@ public:
virtual ~Logs() = default;
bool
open(boost::filesystem::path const& pathToLogFile);
open(std::filesystem::path const& pathToLogFile);
beast::Journal::Sink&
get(std::string const& name);

View File

@@ -304,7 +304,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
* on-ledger are non-negative. This is due to implementation details of
* several operations which use unsigned arithmetic internally. This is
* sufficient to represent all valid XRP values (where the absolute value
* can not exceed INITIAL_XRP: 10^17), and MPT values (where the absolute
* can not exceed kInitialXRP: 10^17), and MPT values (where the absolute
* value can not exceed maxMPTokenAmount: 2^63-1).
*
* ---- Mantissa Range Switching ----
@@ -449,12 +449,6 @@ public:
x.exponent_ == y.exponent_;
}
friend constexpr bool
operator!=(Number const& x, Number const& y) noexcept
{
return !(x == y);
}
friend constexpr bool
operator<(Number const& l, Number const& r) noexcept
{

View File

@@ -85,12 +85,6 @@ public:
}
};
inline bool
operator!=(SHAMapHash const& x, SHAMapHash const& y)
{
return !(x == y);
}
template <>
inline std::size_t
extract(SHAMapHash const& key)

View File

@@ -208,12 +208,6 @@ operator==(Slice const& lhs, Slice const& rhs) noexcept
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
inline bool
operator!=(Slice const& lhs, Slice const& rhs) noexcept
{
return !(lhs == rhs);
}
inline bool
operator<(Slice const& lhs, Slice const& rhs) noexcept
{

View File

@@ -2,7 +2,6 @@
#include <xrpl/basics/Blob.h>
#include <boost/format.hpp>
#include <boost/utility/string_view.hpp>
#include <array>
@@ -125,9 +124,31 @@ struct ParsedUrl
bool
parseUrl(ParsedUrl& pUrl, std::string const& strUrl);
/**
* Remove leading and trailing ASCII whitespace.
*
* Whitespace is the fixed set " \t\n\v\f\r"; the current locale is not
* consulted, so the result depends only on the input.
*
* @param str The string to trim.
* @return @p str without leading or trailing whitespace.
*/
std::string
trimWhitespace(std::string str);
/**
* Fold ASCII upper case letters to lower case.
*
* Only 'A' through 'Z' are remapped; every other byte is left alone and the
* current locale is not consulted, so the result depends only on the input.
*
* @param str The string to fold.
* @return @p str with each ASCII upper case letter replaced by its lower case
* equivalent.
*/
std::string
toLower(std::string str);
std::optional<std::uint64_t>
toUInt64(std::string const& s);

View File

@@ -116,12 +116,6 @@ public:
{
return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
}
friend bool
operator!=(Iterator const& lhs, Iterator const& rhs)
{
return !(lhs == rhs);
}
};
struct ConstIterator
@@ -189,12 +183,6 @@ public:
{
return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
}
friend bool
operator!=(ConstIterator const& lhs, ConstIterator const& rhs)
{
return !(lhs == rhs);
}
};
private:

View File

@@ -1038,25 +1038,6 @@ public:
Compare,
OtherAllocator> const& other) const;
template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool
operator!=(AgedOrderedContainer<
OtherIsMulti,
OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{
return !(this->operator==(other));
}
template <
bool OtherIsMulti,
bool OtherIsMap,

View File

@@ -1340,28 +1340,6 @@ public:
OtherAllocator> const& other) const
requires MaybeMulti;
template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherKey,
class OtherT,
class OtherDuration,
class OtherHash,
class OtherAllocator>
bool
operator!=(AgedUnorderedContainer<
OtherIsMulti,
OtherIsMap,
OtherKey,
OtherT,
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
{
return !(this->operator==(other));
}
private:
bool
wouldExceed(size_type additional) const

View File

@@ -82,13 +82,6 @@ public:
return node_ == other.node_;
}
template <typename M>
bool
operator!=(ListIterator<M> const& other) const noexcept
{
return !((*this) == other);
}
reference
operator*() const noexcept
{

View File

@@ -110,12 +110,6 @@ public:
operator==(Endpoint const& lhs, Endpoint const& rhs);
friend bool
operator<(Endpoint const& lhs, Endpoint const& rhs);
friend bool
operator!=(Endpoint const& lhs, Endpoint const& rhs)
{
return !(lhs == rhs);
}
friend bool
operator>(Endpoint const& lhs, Endpoint const& rhs)
{

View File

@@ -11,6 +11,7 @@
#include <cstddef>
#include <iterator>
#include <string>
#include <string_view>
#include <vector>
namespace beast::rfc2616 {
@@ -186,7 +187,7 @@ splitCommas(FwdIt first, FwdIt last)
template <class Result = std::vector<std::string>>
Result
splitCommas(boost::beast::string_view const& s)
splitCommas(std::string_view s)
{
return splitCommas(s.begin(), s.end());
}
@@ -229,12 +230,6 @@ public:
return other.it_ == it_ && other.end_ == end_ && other.value_.size() == value_.size();
}
bool
operator!=(ListIterator const& other) const
{
return !(*this == other);
}
reference
operator*() const
{

View File

@@ -8,7 +8,6 @@
#include <xrpl/beast/unit_test/runner.h>
#include <xrpl/beast/unit_test/suite_info.h>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <algorithm>
@@ -188,7 +187,7 @@ Reporter<Unused>::fmtdur(clock_type::duration const& d)
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);
if (ms < seconds{1})
return boost::lexical_cast<std::string>(ms.count()) + "ms";
return std::to_string(ms.count()) + "ms";
std::stringstream ss;
ss << std::fixed << std::setprecision(1) << (ms.count() / 1000.) << "s";
return ss.str();

View File

@@ -6,11 +6,10 @@
#include <xrpl/beast/unit_test/runner.h>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/throw_exception.hpp>
#include <exception>
#include <filesystem>
#include <memory>
#include <ostream>
#include <sstream>
@@ -27,10 +26,10 @@ makeReason(String const& reason, char const* file, int line)
std::string s(reason);
if (!s.empty())
s.append(": ");
namespace fs = boost::filesystem;
namespace fs = std::filesystem;
s.append(fs::path{file}.filename().string());
s.append("(");
s.append(boost::lexical_cast<std::string>(line));
s.append(std::to_string(line));
s.append(")");
return s;
}

View File

@@ -1,71 +0,0 @@
#pragma once
#include <boost/filesystem.hpp>
#include <string>
namespace beast {
/**
* RAII temporary directory.
*
* The directory and all its contents are deleted when
* the instance of `temp_dir` is destroyed.
*/
class TempDir
{
boost::filesystem::path path_;
public:
#if !GENERATING_DOCS
TempDir(TempDir const&) = delete;
TempDir&
operator=(TempDir const&) = delete;
#endif
/**
* Construct a temporary directory.
*/
TempDir()
{
auto const dir = boost::filesystem::temp_directory_path();
do
{
path_ = dir / boost::filesystem::unique_path();
} while (boost::filesystem::exists(path_));
boost::filesystem::create_directory(path_);
}
/**
* Destroy a temporary directory.
*/
~TempDir()
{
// use non-throwing calls in the destructor
boost::system::error_code ec;
boost::filesystem::remove_all(path_, ec);
// TODO: warn/notify if ec set ?
}
/**
* Get the native path for the temporary directory
*/
[[nodiscard]] std::string
path() const
{
return path_.string();
}
/**
* Get the native path for the a file.
*
* The file does not need to exist.
*/
[[nodiscard]] std::string
file(std::string const& name) const
{
return (path_ / name).string();
}
};
} // namespace beast

View File

@@ -92,10 +92,4 @@ operator==(Condition const& lhs, Condition const& rhs)
lhs.fingerprint == rhs.fingerprint;
}
inline bool
operator!=(Condition const& lhs, Condition const& rhs)
{
return !(lhs == rhs);
}
} // namespace xrpl::cryptoconditions

View File

@@ -93,12 +93,6 @@ operator==(Fulfillment const& lhs, Fulfillment const& rhs)
lhs.fingerprint() == rhs.fingerprint();
}
inline bool
operator!=(Fulfillment const& lhs, Fulfillment const& rhs)
{
return !(lhs == rhs);
}
/**
* Determine whether the given fulfillment and condition match
*/

View File

@@ -2,7 +2,6 @@
#include <xrpl/basics/contract.h>
#include <boost/beast/core/string.hpp>
#include <boost/lexical_cast.hpp>
#include <algorithm>

View File

@@ -4,10 +4,9 @@
#include <xrpl/core/Job.h>
#include <xrpl/json/json_value.h>
#include <boost/filesystem.hpp>
#include <chrono>
#include <cstdint>
#include <filesystem>
#include <functional>
#include <memory>
#include <string>
@@ -44,7 +43,7 @@ public:
*/
struct Setup
{
boost::filesystem::path perfLog;
std::filesystem::path perfLog;
// log_interval is in milliseconds to support faster testing.
milliseconds logInterval{seconds(1)};
};
@@ -149,7 +148,7 @@ public:
};
PerfLog::Setup
setupPerfLog(Section const& section, boost::filesystem::path const& configDir);
setupPerfLog(Section const& section, std::filesystem::path const& configDir);
std::unique_ptr<PerfLog>
makePerfLog(

View File

@@ -1,20 +1,19 @@
#pragma once
#include <boost/beast/core/string.hpp>
#include <functional>
#include <string>
#include <string_view>
namespace json {
class Value;
using Output = std::function<void(boost::beast::string_view const&)>;
using Output = std::function<void(std::string_view)>;
inline Output
stringOutput(std::string& s)
{
return [&](boost::beast::string_view const& b) { s.append(b.data(), b.size()); };
return [&](std::string_view b) { s.append(b.data(), b.size()); };
}
/**

View File

@@ -4,6 +4,7 @@
#include <xrpl/json/json_forwards.h>
#include <cstring>
#include <iterator>
#include <limits>
#include <map>
#include <string>
@@ -72,36 +73,18 @@ operator==(StaticString x, StaticString y)
return strcmp(x.cStr(), y.cStr()) == 0;
}
inline bool
operator!=(StaticString x, StaticString y)
{
return !(x == y);
}
inline bool
operator==(std::string const& x, StaticString y)
{
return strcmp(x.c_str(), y.cStr()) == 0;
}
inline bool
operator!=(std::string const& x, StaticString y)
{
return !(x == y);
}
inline bool
operator==(StaticString x, std::string const& y)
{
return y == x;
}
inline bool
operator!=(StaticString x, std::string const& y)
{
return !(y == x);
}
/**
* @brief Represents a <a HREF="http://www.json.org">JSON</a> value.
*
@@ -489,12 +472,6 @@ toJson(xrpl::Number const& number)
bool
operator==(Value const&, Value const&);
inline bool
operator!=(Value const& x, Value const& y)
{
return !(x == y);
}
bool
operator<(Value const&, Value const&);
@@ -548,6 +525,7 @@ public:
class ValueIteratorBase
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using size_t = unsigned int;
using difference_type = int;
using SelfType = ValueIteratorBase;
@@ -562,12 +540,6 @@ public:
return isEqual(other);
}
bool
operator!=(SelfType const& other) const
{
return !isEqual(other);
}
/**
* Return either the index or the member name of the referenced value as a
* Value.

View File

@@ -49,12 +49,6 @@ public:
bool
operator==(const_iterator const& other) const;
bool
operator!=(const_iterator const& other) const
{
return !(*this == other);
}
reference
operator*() const;

View File

@@ -59,12 +59,6 @@ private:
return lhs.txId_ == rhs.txId_;
}
friend bool
operator!=(Key const& lhs, Key const& rhs)
{
return !(lhs == rhs);
}
[[nodiscard]] uint256 const&
getAccount() const
{

View File

@@ -59,12 +59,6 @@ public:
bool
operator==(ConstIterator const& other) const;
bool
operator!=(ConstIterator const& other) const
{
return !(*this == other);
}
reference
operator*() const;

View File

@@ -35,6 +35,11 @@ enum class SkipEntry : bool { No = false, Yes };
//
//------------------------------------------------------------------------------
/**
* Whether an expiration check should be inclusive or exclusive.
*/
enum class ExpiryComparison { Inclusive, Exclusive };
/**
* Determines whether the given expiration time has passed.
*
@@ -54,11 +59,16 @@ enum class SkipEntry : bool { No = false, Yes };
*
* @param view The ledger whose parent time is used as the clock.
* @param exp The optional expiration time we want to check.
* @param comparison Whether the boundary is inclusive (`now >= exp`, the
* default) or exclusive (`now > exp`).
*
* @return `true` if `exp` is in the past; `false` otherwise.
*/
[[nodiscard]] bool
hasExpired(ReadView const& view, std::optional<std::uint32_t> const& exp);
hasExpired(
ReadView const& view,
std::optional<std::uint32_t> const& exp,
ExpiryComparison comparison = ExpiryComparison::Inclusive);
// Note, depth parameter is used to limit the recursion depth
[[nodiscard]] bool
@@ -68,6 +78,13 @@ isVaultPseudoAccountFrozen(
MPTIssue const& mptShare,
std::uint8_t depth);
[[nodiscard]] bool
isVaultPseudoAccountFrozen(
ReadView const& view,
AccountID const& account,
SLE const& issuanceSle,
std::uint8_t depth);
[[nodiscard]] bool
isLPTokenFrozen(
ReadView const& view,
@@ -75,6 +92,26 @@ isLPTokenFrozen(
Asset const& asset,
Asset const& asset2);
/**
* Check whether an AMM LPToken may be transferred between @p from and @p to.
*
* @p lpTokenIssuer is the issuer of the LPToken being moved. If it is not an
* AMM account the token is not an LPToken and the transfer is unconditionally
* permitted. Otherwise, for each MPT pool asset of that AMM, canTransfer() must
* permit the transfer (which exempts the MPT issuer). Non-MPT pool assets are
* always transferable by this check, so it is implicitly gated by
* featureMPTokensV2 (MPTs can only be AMM pool assets once V2 is enabled).
*
* @return tesSUCCESS if permitted, otherwise the canTransfer() failure code
* (e.g. tecNO_AUTH) of the first MPT pool asset that disallows it.
*/
[[nodiscard]] TER
canTransferLPToken(
ReadView const& view,
AccountID const& from,
AccountID const& to,
AccountID const& lpTokenIssuer);
// Return the list of enabled amendments
[[nodiscard]] std::set<uint256>
getEnabledAmendments(ReadView const& view);

View File

@@ -85,9 +85,6 @@ public:
bool
operator==(Iterator const& other) const;
bool
operator!=(Iterator const& other) const;
// Can throw
reference
operator*() const;

View File

@@ -64,13 +64,6 @@ ReadViewFwdRange<ValueType>::Iterator::operator==(Iterator const& other) const
return impl_ == other.impl_;
}
template <class ValueType>
bool
ReadViewFwdRange<ValueType>::Iterator::operator!=(Iterator const& other) const
{
return !(*this == other);
}
template <class ValueType>
auto
ReadViewFwdRange<ValueType>::Iterator::operator*() const -> reference

View File

@@ -226,7 +226,7 @@ getAMMOfferStartWithTakerGets(
auto getAmounts = [&pool, &tfee](Number const& nTakerGetsProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerGets is XRP.
// This has the most impact when takerGets is integral.
auto const takerGets =
toAmount<TOut>(getAsset(pool.out), nTakerGetsProposed, Number::RoundingMode::Downward);
return TAmounts<TIn, TOut>{swapAssetOut(pool, takerGets, tfee), takerGets};
@@ -294,7 +294,7 @@ getAMMOfferStartWithTakerPays(
auto getAmounts = [&pool, &tfee](Number const& nTakerPaysProposed) {
// Round downward to minimize the offer and to maximize the quality.
// This has the most impact when takerPays is XRP.
// This has the most impact when takerPays is integral.
auto const takerPays =
toAmount<TIn>(getAsset(pool.in), nTakerPaysProposed, Number::RoundingMode::Downward);
return TAmounts<TIn, TOut>{takerPays, swapAssetIn(pool, takerPays, tfee)};
@@ -313,11 +313,11 @@ getAMMOfferStartWithTakerPays(
* is equal to LOB quality (in this case AMM offer quality is
* better than LOB quality) or AMM offer is equal to LOB quality
* (in this case SPQ is better than LOB quality).
* Pre-amendment code calculates takerPays first. If takerGets is XRP,
* it is rounded down, which results in worse offer quality than
* LOB quality, and the offer might fail to generate.
* Post-amendment code calculates the XRP offer side first. The result
* is rounded down, which makes the offer quality better.
* Pre-amendment code calculates takerPays first. If takerGets is the
* economically coarser integral side, it is rounded down, which results in
* worse offer quality than LOB quality, and the offer might fail to generate.
* Post-amendment code calculates the economically coarser integral offer side
* first. The result is rounded down, which makes the offer quality better.
* It might not be possible to match either SPQ or AMM offer to LOB
* quality. This generally happens at higher fees.
* @param pool AMM pool balances
@@ -396,10 +396,18 @@ changeSpotPriceQuality(
return std::nullopt;
}
// Generate the offer starting with XRP side. Return seated offer amounts
// if the offer can be generated, otherwise nullopt.
auto amounts = [&]() {
if (isXRP(getAsset(pool.out)))
bool const inIntegral = getAsset(pool.in).integral();
bool const outIntegral = getAsset(pool.out).integral();
// Preserve historical behavior for fractional pairs and XRP/IOU-style
// one-integral-side pairs. For two integral assets, pick the side whose
// minimum unit is economically coarser at this quality.
//
// Quality::rate() is input units per output unit, so one output unit is
// coarser when it costs at least one input unit. Ties use takerGets,
// matching the historical XRP-output behavior.
if (outIntegral && (!inIntegral || Number(quality.rate()) >= 1))
return getAMMOfferStartWithTakerGets(pool, quality, tfee);
return getAMMOfferStartWithTakerPays(pool, quality, tfee);
}();

View File

@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STArray.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
@@ -34,7 +35,7 @@ deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j);
// Amendment and parameters checks for sfCredentialIDs field
NotTEC
checkFields(STTx const& tx, beast::Journal j);
checkFields(STTx const& tx, Rules const& rules, beast::Journal j);
// Accessing the ledger to check if provided credentials are valid. Do not use
// in doApply (only in preclaim) since it does not remove expired credentials.

View File

@@ -29,6 +29,9 @@ namespace xrpl {
[[nodiscard]] bool
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
[[nodiscard]] bool
isGlobalFrozen(SLE const& issuanceSle);
/**
* Returns true if @p account's MPToken for @p mptIssue carries the
* individual-lock flag (lsfMPTLocked).
@@ -40,9 +43,29 @@ isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
* receive tokens — it combines isIndividualFrozen, isGlobalFrozen, and
* isVaultPseudoAccountFrozen into a single complete check.
*/
[[nodiscard]] bool
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
[[nodiscard]] bool
isIndividualFrozen(SLE const& mptSle);
/**
* Returns true if @p account cannot send or receive tokens of @p mptIssue
* because a freeze applies. This is the complete check callers should use
* before moving MPT value: it combines @ref isGlobalFrozen (issuance-level
* lock), @ref isIndividualFrozen (per-holder lock bit), and the transitive
* vault pseudo-account check (if @p mptIssue is a vault share, the underlying
* asset is checked, and so on recursively up to @c maxAssetCheckDepth).
*
* The @c SLE overload takes an already-loaded ltMPTOKEN or ltMPTOKEN_ISSUANCE
* ledger entry; for ltMPTOKEN it can skip the per-holder individual-lock lookup.
* @ref isAnyFrozen answers the same question for a set of accounts and returns true
* if the freeze applies to any of them.
*
* @param depth Current recursion depth for the vault-share walk. Callers
* outside this module should leave it at the default.
*/
[[nodiscard]] bool
isFrozen(
ReadView const& view,
@@ -50,6 +73,18 @@ isFrozen(
MPTIssue const& mptIssue,
std::uint8_t depth = 0);
/**
* SLE overload: pass an already-loaded ltMPTOKEN (holder row) or
* ltMPTOKEN_ISSUANCE to reuse it for the freeze checks and avoid re-reading
* the same object. For an ltMPTOKEN, @p sle is used directly for the
* individual-lock check and the issuance is read once for global-freeze and
* vault-pseudo-account. For an ltMPTOKEN_ISSUANCE, @p sle is used directly
* for global-freeze and vault-pseudo-account, and the caller's holder row is
* read for the individual-lock check.
*/
[[nodiscard]] bool
isFrozen(ReadView const& view, AccountID const& account, SLE const& sle, std::uint8_t depth = 0);
[[nodiscard]] bool
isAnyFrozen(
ReadView const& view,
@@ -261,6 +296,14 @@ checkCreateMPT(
xrpl::MPTIssue const& mptIssue,
xrpl::AccountID const& holder,
SLE::ref sponsorSle,
std::uint32_t flags,
beast::Journal j);
TER
checkCreateMPT(
xrpl::ApplyView& view,
xrpl::MPTIssue const& mptIssue,
xrpl::AccountID const& holder,
beast::Journal j);
//------------------------------------------------------------------------------

View File

@@ -6,10 +6,13 @@
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <cstdint>
#include <optional>
namespace xrpl {
class STTx;
/**
* From the perspective of a vault, return the number of shares to give
* depositor when they offer a fixed amount of assets. Note, since shares are
@@ -123,4 +126,82 @@ isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref
[[nodiscard]] VaultVersion
getVaultVersion(SLE::const_ref vault);
/**
* Resolves the VaultKind of a vault SLE. Returns VaultKind::ClosedEnded when
* sfVaultKind is present and equal to that value; anything else (including an
* absent field or an unrecognised value) is treated as VaultKind::OpenEnded.
*
* @param vault The vault SLE.
*/
[[nodiscard]] VaultKind
getVaultKind(SLE::const_ref vault);
/**
* Reads sfVaultKind from a transaction. An absent field resolves to
* VaultKind::OpenEnded (matching the on-ledger default); any unrecognised
* value is also treated as VaultKind::OpenEnded, mirroring the SLE overload.
* Callers that need to reject out-of-range values (e.g. preflight) should
* gate on isValidVaultKind() first.
*
* @param tx The transaction.
*/
[[nodiscard]] VaultKind
getVaultKind(STTx const& tx);
/**
* Returns true iff sfVaultKind is either absent from @p tx or is present and
* equal to a recognised VaultKind enumerator. Intended for use in preflight
* to reject malformed transactions before decoding with getVaultKind().
*
* @param tx The transaction.
*/
[[nodiscard]] bool
isValidVaultKind(STTx const& tx);
/**
* Returns true iff the (SubscriptionDate, RedemptionDate) gap of a
* closed-ended vault satisfies
* kMinInvestmentPeriod <= (red - sub) < kMaxInvestmentPeriod. The arithmetic
* is performed in std::int64_t so that @p sub near UINT32_MAX does not
* overflow. Shared by VaultCreate::preflight and the ValidVault invariant.
*
* @param sub The value of sfSubscriptionDate.
* @param red The value of sfRedemptionDate.
*/
[[nodiscard]] bool
isValidClosedEndedGap(std::uint32_t sub, std::uint32_t red);
/**
* Returns the current lifecycle phase of a vault. Open-ended
* vaults are always NoPhase. For closed-ended vaults the phase is derived
* from the parent ledger close time and the vault's immutable
* SubscriptionDate and RedemptionDate.
*
* @param view The ledger view whose parent close time is used as the clock.
* @param vault The vault SLE.
*/
[[nodiscard]] VaultPhase
getVaultPhase(ReadView const& view, SLE::const_ref vault);
/**
* Raw-fields overload of getVaultPhase. Derives the phase from an already
* decomposed vault snapshot: an absent or non-ClosedEnded @p vaultKind
* resolves to VaultPhase::NoPhase; otherwise the phase is computed from
* @p subscriptionDate and @p redemptionDate against the view's parent
* close time using the same boundary semantics as the SLE overload
* (Subscription is inclusive of now == SubscriptionDate; Investment starts
* strictly after).
*
* @param view The ledger view whose parent close time is used as the clock.
* @param vaultKind The value of sfVaultKind, or nullopt if absent.
* @param subscriptionDate The value of sfSubscriptionDate, or nullopt if absent.
* @param redemptionDate The value of sfRedemptionDate, or nullopt if absent.
*/
[[nodiscard]] VaultPhase
getVaultPhase(
ReadView const& view,
std::optional<std::uint8_t> vaultKind,
std::optional<std::uint32_t> subscriptionDate,
std::optional<std::uint32_t> redemptionDate);
} // namespace xrpl

View File

@@ -8,11 +8,11 @@
#include <boost/asio.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/format.hpp>
#include <openssl/err.h>
#include <openssl/tls1.h>
#include <format>
#include <stdexcept>
#include <string>
#include <type_traits>
@@ -38,8 +38,8 @@ public:
if (ec && sslVerifyDir.empty())
{
Throw<std::runtime_error>(boost::str(
boost::format("Failed to set_default_verify_paths: %s") % ec.message()));
Throw<std::runtime_error>(
std::format("Failed to set_default_verify_paths: {}", ec.message()));
}
}
else
@@ -54,7 +54,7 @@ public:
if (ec)
{
Throw<std::runtime_error>(
boost::str(boost::format("Failed to add verify path: %s") % ec.message()));
std::format("Failed to add verify path: {}", ec.message()));
}
}
}

View File

@@ -1,10 +1,10 @@
syntax = "proto2";
package protocol;
// Unused numbers in the list below may have been used previously. Please don't
// reassign them for reuse unless you are 100% certain that there won't be a
// conflict. Even if you're sure, it's probably best to assign a new type.
enum MessageType {
// Previously used - don't reuse.
reserved 0 to 1, 4, 6 to 14, 16 to 29, 36 to 40, 43 to 54, 61 to 62;
mtMANIFESTS = 2;
mtPING = 3;
mtCLUSTER = 5;
@@ -17,7 +17,6 @@ enum MessageType {
mtHAVE_SET = 35;
mtVALIDATION = 41;
mtGET_OBJECTS = 42;
mtVALIDATOR_LIST = 54;
mtSQUELCH = 55;
mtVALIDATOR_LIST_COLLECTION = 56;
mtPROOF_PATH_REQ = 57;
@@ -162,14 +161,6 @@ message TMHaveTransactionSet {
required bytes hash = 2;
}
// Validator list (UNL)
message TMValidatorList {
required bytes manifest = 1;
required bytes blob = 2;
required bytes signature = 3;
required uint32 version = 4;
}
// Validator List v2
message ValidatorBlobInfo {
optional bytes manifest = 1;

View File

@@ -47,7 +47,7 @@ ammLPTIssue(Asset const& asset1, Asset const& asset2, AccountID const& ammAccoun
/**
* Validate the amount.
* If validZero is false and amount is beast::zero then invalid amount.
* If validZero is false and amount is beast::kZero then invalid amount.
* Return error code if invalid amount.
* If pair then validate amount's issue matches one of the pair's issue.
*/

View File

@@ -154,7 +154,7 @@ T
toAmount(Asset const& asset, Number const& n, Number::RoundingMode mode = Number::getround())
{
SaveNumberRoundMode const rm(Number::getround());
if (isXRP(asset))
if (asset.integral())
Number::setround(mode);
if constexpr (std::is_same_v<IOUAmount, T>)

View File

@@ -9,6 +9,7 @@
#include <mpt_protocol.h>
#include <secp256k1_mpt.h>
#include <chrono>
#include <cstddef>
#include <cstdint>
@@ -327,6 +328,36 @@ enum class VaultVersion : uint8_t {
CashBasis,
};
/**
* Vault kind. Distinguishes closed-ended vaults from the default open-ended
* kind. Persisted as sfVaultKind (UINT8); absent means OpenEnded.
*/
enum class VaultKind : std::uint8_t {
OpenEnded = 0,
ClosedEnded = 1,
};
/**
* Lifecycle phase of a vault. Open-ended vaults are always NoPhase; the other
* three values are the phases of a closed-ended vault.
*/
enum class VaultPhase : std::uint8_t {
NoPhase = 0,
Subscription,
Investment,
Redemption,
};
/**
* Bounds on the length of a closed-ended vault's Investment phase
* (RedemptionDate - SubscriptionDate). At vault creation the gap must satisfy
* kMinInvestmentPeriod <= gap < kMaxInvestmentPeriod.
*/
constexpr std::uint32_t kMinInvestmentPeriod =
std::chrono::seconds{std::chrono::minutes{1}}.count();
// This is 946708560 seconds which 30 x 365.2425 days (the average length of a Gregorian year).
constexpr std::uint32_t kMaxInvestmentPeriod = std::chrono::seconds{std::chrono::years{30}}.count();
/**
* Maximum recursion depth for vault shares being put as an asset inside
* another vault; counted from 0

View File

@@ -75,13 +75,6 @@ operator==(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
return lhs.in == rhs.in && lhs.out == rhs.out;
}
template <class In, class Out>
bool
operator!=(TAmounts<In, Out> const& lhs, TAmounts<In, Out> const& rhs) noexcept
{
return !(lhs == rhs);
}
//------------------------------------------------------------------------------
// XRPL specific constant used for parsing qualities and other things
@@ -271,12 +264,6 @@ public:
return lhs.value_ == rhs.value_;
}
friend bool
operator!=(Quality const& lhs, Quality const& rhs) noexcept
{
return !(lhs == rhs);
}
friend std::ostream&
operator<<(std::ostream& os, Quality const& quality)
{

View File

@@ -60,6 +60,15 @@ public:
std::optional<Number>
outFromAvgQ(Quality const& quality);
/**
* Return whether `out` produces at least the requested
* average quality.
* @param quality requested average quality (quality limit)
* @param out output amount to test
*/
[[nodiscard]] bool
satisfiesAvgQ(Quality const& quality, Number const& out) const;
/**
* Return true if the quality function is constant
*/

View File

@@ -98,9 +98,6 @@ public:
*/
bool
operator==(Rules const&) const;
bool
operator!=(Rules const& other) const;
};
std::optional<Rules> const&

View File

@@ -642,12 +642,6 @@ operator==(STAmount const& lhs, STAmount const& rhs);
bool
operator<(STAmount const& lhs, STAmount const& rhs);
inline bool
operator!=(STAmount const& lhs, STAmount const& rhs)
{
return !(lhs == rhs);
}
inline bool
operator>(STAmount const& lhs, STAmount const& rhs)
{

View File

@@ -133,9 +133,6 @@ public:
bool
operator==(STArray const& s) const;
bool
operator!=(STArray const& s) const;
iterator
erase(iterator pos);
@@ -283,12 +280,6 @@ STArray::operator==(STArray const& s) const
return v_ == s.v_;
}
inline bool
STArray::operator!=(STArray const& s) const
{
return v_ != s.v_;
}
inline STArray::iterator
STArray::erase(iterator pos)
{

View File

@@ -140,8 +140,6 @@ public:
bool
operator==(STBase const& t) const;
bool
operator!=(STBase const& t) const;
template <class D>
D&

View File

@@ -93,12 +93,6 @@ operator==(STCurrency const& lhs, STCurrency const& rhs)
return lhs.currency() == rhs.currency();
}
inline bool
operator!=(STCurrency const& lhs, STCurrency const& rhs)
{
return !operator==(lhs, rhs);
}
inline bool
operator<(STCurrency const& lhs, STCurrency const& rhs)
{

View File

@@ -432,8 +432,6 @@ public:
bool
operator==(STObject const& o) const;
bool
operator!=(STObject const& o) const;
class FieldErr;
@@ -667,36 +665,6 @@ public:
return !lhs.engaged() || *lhs == *rhs;
}
friend bool
operator!=(OptionalProxy const& lhs, std::nullopt_t) noexcept
{
return !(lhs == std::nullopt);
}
friend bool
operator!=(std::nullopt_t, OptionalProxy const& rhs) noexcept
{
return !(rhs == std::nullopt);
}
friend bool
operator!=(OptionalProxy const& lhs, optional_type const& rhs) noexcept
{
return !(lhs == rhs);
}
friend bool
operator!=(optional_type const& lhs, OptionalProxy const& rhs) noexcept
{
return !(lhs == rhs);
}
friend bool
operator!=(OptionalProxy const& lhs, OptionalProxy const& rhs) noexcept
{
return !(lhs == rhs);
}
// Emulate std::optional::value_or
[[nodiscard]] value_type
valueOr(value_type val) const;
@@ -1202,12 +1170,6 @@ STObject::setFieldH160(SField const& field, BaseUInt<160, Tag> const& v)
}
}
inline bool
STObject::operator!=(STObject const& o) const
{
return !(*this == o);
}
template <typename T, typename V>
V
STObject::getFieldByValue(SField const& field) const

View File

@@ -115,9 +115,6 @@ public:
bool
operator==(STPathElement const& t) const;
bool
operator!=(STPathElement const& t) const;
private:
static std::size_t
getHash(STPathElement const& element);
@@ -432,12 +429,6 @@ STPathElement::operator==(STPathElement const& t) const
accountID_ == t.accountID_ && assetID_ == t.assetID_ && issuerID_ == t.issuerID_;
}
inline bool
STPathElement::operator!=(STPathElement const& t) const
{
return !operator==(t);
}
// ------------ STPath ------------
inline STPath::STPath(std::vector<STPathElement> p) : path_(std::move(p))

View File

@@ -123,12 +123,6 @@ public:
return (lhs.value() == rhs.value());
}
friend constexpr bool
operator!=(SeqProxy lhs, SeqProxy rhs)
{
return !(lhs == rhs);
}
friend constexpr bool
operator<(SeqProxy lhs, SeqProxy rhs)
{

View File

@@ -265,20 +265,10 @@ public:
return v == data_;
}
bool
operator!=(Blob const& v) const
{
return v != data_;
}
bool
operator==(Serializer const& v) const
{
return v.data_ == data_;
}
bool
operator!=(Serializer const& v) const
{
return v.data_ != data_;
}
static int
decodeLengthLength(int b1);

View File

@@ -425,8 +425,7 @@ inline constexpr FlagValue tfDepositSubTx =
ASF_FLAG(asfDefaultRipple, 8) \
ASF_FLAG(asfDepositAuth, 9) \
ASF_FLAG(asfAuthorizedNFTokenMinter, 10) \
/* 11 is reserved for Hooks amendment */ \
/* ASF_FLAG(asfTshCollect, 11) */ \
/* 11 is unused */ \
ASF_FLAG(asfDisallowIncomingNFTokenOffer, 12) \
ASF_FLAG(asfDisallowIncomingCheck, 13) \
ASF_FLAG(asfDisallowIncomingPayChan, 14) \

View File

@@ -258,13 +258,6 @@ public:
return value_ == other;
}
template <Compatible<ValueUnit> Other>
constexpr bool
operator!=(ValueUnit<unit_type, Other> const& other) const
{
return !operator==(other);
}
constexpr bool
operator<(ValueUnit const& other) const
{

View File

@@ -152,10 +152,4 @@ operator==(STVar const& lhs, STVar const& rhs)
return lhs.get().isEquivalent(rhs.get());
}
inline bool
operator!=(STVar const& lhs, STVar const& rhs)
{
return !(lhs == rhs);
}
} // namespace xrpl::detail

View File

@@ -506,6 +506,9 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({
{sfWithdrawalPolicy, SoeRequired},
{sfScale, SoeDefault},
{sfLEVersion, SoeDefault},
{sfVaultKind, SoeDefault},
{sfSubscriptionDate, SoeOptional},
{sfRedemptionDate, SoeOptional},
// no SharesTotal ever (use MPTIssuance.sfOutstandingAmount)
// no PermissionedDomainID ever (use MPTIssuance.sfDomainID)
}))

View File

@@ -23,9 +23,11 @@ TYPED_SFIELD(sfLEVersion, UINT8, 6)
// 8-bit integers (uncommon)
TYPED_SFIELD(sfTickSize, UINT8, 16)
TYPED_SFIELD(sfUNLModifyDisabling, UINT8, 17)
TYPED_SFIELD(sfHookResult, UINT8, 18)
// 18 unused
TYPED_SFIELD(sfWasLockingChainSend, UINT8, 19)
TYPED_SFIELD(sfWithdrawalPolicy, UINT8, 20)
TYPED_SFIELD(sfContractResult, UINT8, 21)
TYPED_SFIELD(sfVaultKind, UINT8, 22)
// 16-bit integers (common)
TYPED_SFIELD(sfLedgerEntryType, UINT16, 1, SField::kSmdNever)
@@ -37,10 +39,7 @@ TYPED_SFIELD(sfDiscountedFee, UINT16, 6)
// 16-bit integers (uncommon)
TYPED_SFIELD(sfVersion, UINT16, 16)
TYPED_SFIELD(sfHookStateChangeCount, UINT16, 17)
TYPED_SFIELD(sfHookEmitCount, UINT16, 18)
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
// 17 to 20 unused
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
TYPED_SFIELD(sfManagementFeeRate, UINT16, 22) // 1/10 basis points (bips)
@@ -91,9 +90,7 @@ TYPED_SFIELD(sfTicketSequence, UINT32, 41)
TYPED_SFIELD(sfNFTokenTaxon, UINT32, 42)
TYPED_SFIELD(sfMintedNFTokens, UINT32, 43)
TYPED_SFIELD(sfBurnedNFTokens, UINT32, 44)
TYPED_SFIELD(sfHookStateCount, UINT32, 45)
TYPED_SFIELD(sfEmitGeneration, UINT32, 46)
// 47 reserved for Hooks
// 45 to 47 unused
TYPED_SFIELD(sfVoteWeight, UINT32, 48)
TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50)
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
@@ -120,6 +117,8 @@ TYPED_SFIELD(sfSponsoringOwnerCount, UINT32, 71)
TYPED_SFIELD(sfSponsoringAccountCount, UINT32, 72)
TYPED_SFIELD(sfRemainingOwnerCount, UINT32, 73)
TYPED_SFIELD(sfSponsorFlags, UINT32, 74)
TYPED_SFIELD(sfSubscriptionDate, UINT32, 75)
TYPED_SFIELD(sfRedemptionDate, UINT32, 76)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -137,9 +136,7 @@ TYPED_SFIELD(sfNFTokenOfferNode, UINT64, 12)
TYPED_SFIELD(sfEmitBurden, UINT64, 13)
// 64-bit integers (uncommon)
TYPED_SFIELD(sfHookOn, UINT64, 16)
TYPED_SFIELD(sfHookInstructionCount, UINT64, 17)
TYPED_SFIELD(sfHookReturnCode, UINT64, 18)
// 16 to 18 unused
TYPED_SFIELD(sfReferenceCount, UINT64, 19)
TYPED_SFIELD(sfXChainClaimID, UINT64, 20)
TYPED_SFIELD(sfXChainAccountCreateCount, UINT64, 21)
@@ -203,10 +200,7 @@ TYPED_SFIELD(sfPreviousPageMin, UINT256, 26)
TYPED_SFIELD(sfNextPageMin, UINT256, 27)
TYPED_SFIELD(sfNFTokenBuyOffer, UINT256, 28)
TYPED_SFIELD(sfNFTokenSellOffer, UINT256, 29)
TYPED_SFIELD(sfHookStateKey, UINT256, 30)
TYPED_SFIELD(sfHookHash, UINT256, 31)
TYPED_SFIELD(sfHookNamespace, UINT256, 32)
TYPED_SFIELD(sfHookSetTxnID, UINT256, 33)
// 30 to 33 unused
TYPED_SFIELD(sfDomainID, UINT256, 34)
TYPED_SFIELD(sfVaultID, UINT256, 35,
SField::kSmdPseudoAccount | SField::kSmdDefault)
@@ -237,7 +231,7 @@ TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::kSmdNeedsAsset
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::kSmdNeedsAsset | SField::kSmdDefault)
// int32
// 32-bit signed (common)
TYPED_SFIELD(sfLoanScale, INT32, 1)
TYPED_SFIELD(sfRemainingOwnerCountDelta, INT32, 2)
@@ -261,15 +255,13 @@ TYPED_SFIELD(sfMinimumOffer, AMOUNT, 16)
TYPED_SFIELD(sfRippleEscrow, AMOUNT, 17)
TYPED_SFIELD(sfDeliveredAmount, AMOUNT, 18)
TYPED_SFIELD(sfNFTokenBrokerFee, AMOUNT, 19)
// Reserve 20 & 21 for Hooks.
// 20 to 21 unused
// currency amount (fees)
TYPED_SFIELD(sfBaseFeeDrops, AMOUNT, 22)
TYPED_SFIELD(sfReserveBaseDrops, AMOUNT, 23)
TYPED_SFIELD(sfReserveIncrementDrops, AMOUNT, 24)
// currency amount (AMM)
// currency amount (more)
TYPED_SFIELD(sfLPTokenOut, AMOUNT, 25)
TYPED_SFIELD(sfLPTokenIn, AMOUNT, 26)
TYPED_SFIELD(sfEPrice, AMOUNT, 27)
@@ -304,10 +296,7 @@ TYPED_SFIELD(sfMasterSignature, VL, 18, SField::kSmdDefault, SFi
TYPED_SFIELD(sfUNLModifyValidator, VL, 19)
TYPED_SFIELD(sfValidatorToDisable, VL, 20)
TYPED_SFIELD(sfValidatorToReEnable, VL, 21)
TYPED_SFIELD(sfHookStateData, VL, 22)
TYPED_SFIELD(sfHookReturnString, VL, 23)
TYPED_SFIELD(sfHookParameterName, VL, 24)
TYPED_SFIELD(sfHookParameterValue, VL, 25)
// 22 to 25 unused
TYPED_SFIELD(sfDIDDocument, VL, 26)
TYPED_SFIELD(sfData, VL, 27)
TYPED_SFIELD(sfAssetClass, VL, 28)
@@ -345,7 +334,7 @@ TYPED_SFIELD(sfHolder, ACCOUNT, 11)
TYPED_SFIELD(sfDelegate, ACCOUNT, 12)
// account (uncommon)
TYPED_SFIELD(sfHookAccount, ACCOUNT, 16)
// 16 unused
TYPED_SFIELD(sfOtherChainSource, ACCOUNT, 18)
TYPED_SFIELD(sfOtherChainDestination, ACCOUNT, 19)
TYPED_SFIELD(sfAttestationSignerAccount, ACCOUNT, 20)
@@ -398,7 +387,7 @@ UNTYPED_SFIELD(sfMemo, OBJECT, 10)
UNTYPED_SFIELD(sfSignerEntry, OBJECT, 11)
UNTYPED_SFIELD(sfNFToken, OBJECT, 12)
UNTYPED_SFIELD(sfEmitDetails, OBJECT, 13)
UNTYPED_SFIELD(sfHook, OBJECT, 14)
// 14 unused
UNTYPED_SFIELD(sfPermission, OBJECT, 15)
// inner object (uncommon)
@@ -406,11 +395,7 @@ UNTYPED_SFIELD(sfSigner, OBJECT, 16)
// 17 unused
UNTYPED_SFIELD(sfMajority, OBJECT, 18)
UNTYPED_SFIELD(sfDisabledValidator, OBJECT, 19)
UNTYPED_SFIELD(sfEmittedTxn, OBJECT, 20)
UNTYPED_SFIELD(sfHookExecution, OBJECT, 21)
UNTYPED_SFIELD(sfHookDefinition, OBJECT, 22)
UNTYPED_SFIELD(sfHookParameter, OBJECT, 23)
UNTYPED_SFIELD(sfHookGrant, OBJECT, 24)
// 20 to 24 unused
UNTYPED_SFIELD(sfVoteEntry, OBJECT, 25)
UNTYPED_SFIELD(sfAuctionSlot, OBJECT, 26)
UNTYPED_SFIELD(sfAuthAccount, OBJECT, 27)
@@ -438,16 +423,14 @@ UNTYPED_SFIELD(sfSufficient, ARRAY, 7)
UNTYPED_SFIELD(sfAffectedNodes, ARRAY, 8)
UNTYPED_SFIELD(sfMemos, ARRAY, 9)
UNTYPED_SFIELD(sfNFTokens, ARRAY, 10)
UNTYPED_SFIELD(sfHooks, ARRAY, 11)
// 11 unused
UNTYPED_SFIELD(sfVoteSlots, ARRAY, 12)
UNTYPED_SFIELD(sfAdditionalBooks, ARRAY, 13)
// array of objects (uncommon)
UNTYPED_SFIELD(sfMajorities, ARRAY, 16)
UNTYPED_SFIELD(sfDisabledValidators, ARRAY, 17)
UNTYPED_SFIELD(sfHookExecutions, ARRAY, 18)
UNTYPED_SFIELD(sfHookParameters, ARRAY, 19)
UNTYPED_SFIELD(sfHookGrants, ARRAY, 20)
// 18 to 20 unused
UNTYPED_SFIELD(sfXChainClaimAttestations, ARRAY, 21)
UNTYPED_SFIELD(sfXChainCreateAccountAttestations, ARRAY, 22)
// 23 unused

View File

@@ -862,6 +862,9 @@ TRANSACTION(ttVAULT_CREATE, 65, VaultCreate,
{sfWithdrawalPolicy, SoeOptional},
{sfData, SoeOptional},
{sfScale, SoeOptional},
{sfVaultKind, SoeOptional},
{sfSubscriptionDate, SoeOptional},
{sfRedemptionDate, SoeOptional},
}))
/** This transaction updates a single asset vault. */

View File

@@ -311,6 +311,78 @@ public:
{
return this->sle_->isFieldPresent(sfLEVersion);
}
/**
* @brief Get sfVaultKind (SoeDefault)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT8::type::value_type>
getVaultKind() const
{
if (hasVaultKind())
return this->sle_->at(sfVaultKind);
return std::nullopt;
}
/**
* @brief Check if sfVaultKind is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasVaultKind() const
{
return this->sle_->isFieldPresent(sfVaultKind);
}
/**
* @brief Get sfSubscriptionDate (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getSubscriptionDate() const
{
if (hasSubscriptionDate())
return this->sle_->at(sfSubscriptionDate);
return std::nullopt;
}
/**
* @brief Check if sfSubscriptionDate is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSubscriptionDate() const
{
return this->sle_->isFieldPresent(sfSubscriptionDate);
}
/**
* @brief Get sfRedemptionDate (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getRedemptionDate() const
{
if (hasRedemptionDate())
return this->sle_->at(sfRedemptionDate);
return std::nullopt;
}
/**
* @brief Check if sfRedemptionDate is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasRedemptionDate() const
{
return this->sle_->isFieldPresent(sfRedemptionDate);
}
};
/**
@@ -543,6 +615,39 @@ public:
return *this;
}
/**
* @brief Set sfVaultKind (SoeDefault)
* @return Reference to this builder for method chaining.
*/
VaultBuilder&
setVaultKind(std::decay_t<typename SF_UINT8::type::value_type> const& value)
{
object_[sfVaultKind] = value;
return *this;
}
/**
* @brief Set sfSubscriptionDate (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultBuilder&
setSubscriptionDate(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfSubscriptionDate] = value;
return *this;
}
/**
* @brief Set sfRedemptionDate (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultBuilder&
setRedemptionDate(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfRedemptionDate] = value;
return *this;
}
/**
* @brief Build and return the completed Vault wrapper.
* @param index The ledger entry index.

View File

@@ -214,6 +214,84 @@ public:
{
return this->tx_->isFieldPresent(sfScale);
}
/**
* @brief Get sfVaultKind (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT8::type::value_type>
getVaultKind() const
{
if (hasVaultKind())
{
return this->tx_->at(sfVaultKind);
}
return std::nullopt;
}
/**
* @brief Check if sfVaultKind is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasVaultKind() const
{
return this->tx_->isFieldPresent(sfVaultKind);
}
/**
* @brief Get sfSubscriptionDate (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getSubscriptionDate() const
{
if (hasSubscriptionDate())
{
return this->tx_->at(sfSubscriptionDate);
}
return std::nullopt;
}
/**
* @brief Check if sfSubscriptionDate is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasSubscriptionDate() const
{
return this->tx_->isFieldPresent(sfSubscriptionDate);
}
/**
* @brief Get sfRedemptionDate (SoeOptional)
* @return The field value, or std::nullopt if not present.
*/
[[nodiscard]]
protocol_autogen::Optional<SF_UINT32::type::value_type>
getRedemptionDate() const
{
if (hasRedemptionDate())
{
return this->tx_->at(sfRedemptionDate);
}
return std::nullopt;
}
/**
* @brief Check if sfRedemptionDate is present.
* @return True if the field is present, false otherwise.
*/
[[nodiscard]]
bool
hasRedemptionDate() const
{
return this->tx_->isFieldPresent(sfRedemptionDate);
}
};
/**
@@ -338,6 +416,39 @@ public:
return *this;
}
/**
* @brief Set sfVaultKind (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultCreateBuilder&
setVaultKind(std::decay_t<typename SF_UINT8::type::value_type> const& value)
{
object_[sfVaultKind] = value;
return *this;
}
/**
* @brief Set sfSubscriptionDate (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultCreateBuilder&
setSubscriptionDate(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfSubscriptionDate] = value;
return *this;
}
/**
* @brief Set sfRedemptionDate (SoeOptional)
* @return Reference to this builder for method chaining.
*/
VaultCreateBuilder&
setRedemptionDate(std::decay_t<typename SF_UINT32::type::value_type> const& value)
{
object_[sfRedemptionDate] = value;
return *this;
}
/**
* @brief Build and return the VaultCreate wrapper.
* @param publicKey The public key for signing.

View File

@@ -2,6 +2,9 @@
#include <array>
#include <cstdint>
#include <format>
#include <string>
#include <string_view>
namespace xrpl {
@@ -9,9 +12,29 @@ namespace xrpl {
// These pragmas are built at startup and applied to all database
// connections, unless otherwise noted.
inline constexpr char const* kCommonDbPragmaJournal{"PRAGMA journal_mode=%s;"};
inline constexpr char const* kCommonDbPragmaSync{"PRAGMA synchronous=%s;"};
inline constexpr char const* kCommonDbPragmaTemp{"PRAGMA temp_store=%s;"};
//
// They are exposed as functions rather than as format-string constants so
// that the un-substituted template can never reach sqlite: an unrecognized
// pragma value is silently ignored, so forgetting to interpolate would
// leave the setting at its default instead of failing loudly.
[[nodiscard]] inline std::string
commonDbPragmaJournal(std::string_view journalMode)
{
return std::format("PRAGMA journal_mode={};", journalMode);
}
[[nodiscard]] inline std::string
commonDbPragmaSync(std::string_view synchronous)
{
return std::format("PRAGMA synchronous={};", synchronous);
}
[[nodiscard]] inline std::string
commonDbPragmaTemp(std::string_view tempStore)
{
return std::format("PRAGMA temp_store={};", tempStore);
}
// A warning will be logged if any lower-safety sqlite tuning settings
// are used and at least this much ledger history is configured. This
// includes full history nodes. This is because such a large amount of

View File

@@ -6,13 +6,12 @@
#include <xrpl/core/StartUpType.h>
#include <xrpl/rdb/SociDB.h>
#include <boost/filesystem/path.hpp>
#include <soci/statement.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <functional>
#include <memory>
#include <mutex>
@@ -80,7 +79,7 @@ public:
StartUpType startUp = StartUpType::Normal;
bool standAlone = false;
boost::filesystem::path dataDir;
std::filesystem::path dataDir;
// Indicates whether or not to return the `globalPragma`
// from commonPragma()
bool useGlobalPragma = false;
@@ -143,7 +142,7 @@ public:
template <std::size_t N, std::size_t M>
DatabaseCon(
boost::filesystem::path const& dataDir,
std::filesystem::path const& dataDir,
std::string const& dbName,
std::array<std::string, N> const& pragma,
std::array<char const*, M> const& initSQL,
@@ -155,7 +154,7 @@ public:
// Use this constructor to setup checkpointing
template <std::size_t N, std::size_t M>
DatabaseCon(
boost::filesystem::path const& dataDir,
std::filesystem::path const& dataDir,
std::string const& dbName,
std::array<std::string, N> const& pragma,
std::array<char const*, M> const& initSQL,
@@ -190,7 +189,7 @@ private:
template <std::size_t N, std::size_t M>
DatabaseCon(
boost::filesystem::path const& pPath,
std::filesystem::path const& pPath,
std::vector<std::string> const* commonPragma,
std::array<std::string, N> const& pragma,
std::array<char const*, M> const& initSQL,

View File

@@ -14,7 +14,6 @@
#include <xrpl/protocol/TxMeta.h>
#include <xrpl/protocol/TxSearched.h>
#include <boost/filesystem.hpp>
#include <boost/variant.hpp>
#include <concepts>

View File

@@ -306,12 +306,6 @@ operator==(Manifest const& lhs, Manifest const& rhs)
lhs.serialized == rhs.serialized;
}
inline bool
operator!=(Manifest const& lhs, Manifest const& rhs)
{
return !(lhs == rhs);
}
struct ValidatorToken
{
std::string manifest;

View File

@@ -4,8 +4,6 @@
#include <xrpl/rdb/DatabaseCon.h>
#include <xrpl/rdb/SociDB.h>
#include <boost/filesystem.hpp>
#include <string>
namespace xrpl {

View File

@@ -10,6 +10,10 @@
#include <xrpl/rdb/DatabaseCon.h>
#include <xrpl/server/Manifest.h>
// boost::optional (not std::optional) appears in the declarations below,
// because SOCI's into()/use() bindings only support boost::optional.
#include <boost/optional/optional.hpp>
#include <functional>
#include <memory>
#include <string>

View File

@@ -25,6 +25,7 @@
#include <iterator>
#include <list>
#include <memory>
#include <string_view>
#include <utility>
#include <vector>
@@ -62,8 +63,7 @@ private:
bool pingActive_ = false;
boost::beast::websocket::ping_data payload_;
error_code ec_;
std::function<void(boost::beast::websocket::frame_type, boost::beast::string_view)>
controlCallback_;
std::function<void(boost::beast::websocket::frame_type, std::string_view)> controlCallback_;
public:
template <class Body, class Headers>
@@ -151,7 +151,7 @@ protected:
onPing(error_code const& ec);
void
onPingPong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload);
onPingPong(boost::beast::websocket::frame_type kind, std::string_view payload);
void
onTimer(error_code ec);
@@ -189,9 +189,9 @@ BaseWSPeer<Handler, Impl>::run()
impl().ws_.set_option(port().pmdOptions);
// Must manage the control callback memory outside of the `control_callback`
// function
controlCallback_ = [this](
boost::beast::websocket::frame_type kind,
boost::beast::string_view payload) { onPingPong(kind, payload); };
controlCallback_ = [this](boost::beast::websocket::frame_type kind, std::string_view payload) {
onPingPong(kind, payload);
};
impl().ws_.control_callback(controlCallback_);
startTimer();
closeOnTimer_ = true;
@@ -430,11 +430,11 @@ template <class Handler, class Impl>
void
BaseWSPeer<Handler, Impl>::onPingPong(
boost::beast::websocket::frame_type kind,
boost::beast::string_view payload)
std::string_view payload)
{
if (kind == boost::beast::websocket::frame_type::pong)
{
boost::beast::string_view const p(payload_.begin());
std::string_view const p(payload_.begin(), payload_.size());
if (payload == p)
{
closeOnTimer_ = false;

View File

@@ -484,31 +484,36 @@ private:
// returns the first item at or below this node
SHAMapLeafNode*
firstBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, int branch = 0) const;
firstBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, unsigned int branch = 0u) const;
// returns the last item at or below this node
SHAMapLeafNode*
lastBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, int branch = kBranchFactor) const;
lastBelow(
SHAMapTreeNodePtr node,
SharedPtrNodeStack& stack,
unsigned int branch = kBranchFactor) const;
// direction in which belowHelper scans an inner node's branches
enum class BelowDirection { First, Last };
// helper function for firstBelow and lastBelow
SHAMapLeafNode*
belowHelper(
SHAMapTreeNodePtr node,
SharedPtrNodeStack& stack,
int branch,
std::tuple<int, std::function<bool(int)>, std::function<void(int&)>> const& loopParams)
const;
unsigned int branch,
BelowDirection direction) const;
// Simple descent
// Get a child of the specified node
SHAMapTreeNode*
descend(SHAMapInnerNode*, int branch) const;
descend(SHAMapInnerNode*, unsigned int branch) const;
SHAMapTreeNode*
descendThrow(SHAMapInnerNode*, int branch) const;
descendThrow(SHAMapInnerNode*, unsigned int branch) const;
SHAMapTreeNodePtr
descend(SHAMapInnerNode&, int branch) const;
descend(SHAMapInnerNode&, unsigned int branch) const;
SHAMapTreeNodePtr
descendThrow(SHAMapInnerNode&, int branch) const;
descendThrow(SHAMapInnerNode&, unsigned int branch) const;
// Descend with filter
// If pending, callback is called as if it called fetchNodeNT
@@ -516,7 +521,7 @@ private:
SHAMapTreeNode*
descendAsync(
SHAMapInnerNode* parent,
int branch,
unsigned int branch,
SHAMapSyncFilter const* filter,
bool& pending,
descendCallback&&) const;
@@ -525,13 +530,13 @@ private:
descend(
SHAMapInnerNode* parent,
SHAMapNodeID const& parentID,
int branch,
unsigned int branch,
SHAMapSyncFilter const* filter) const;
// Non-storing
// Does not hook the returned node to its parent
SHAMapTreeNodePtr
descendNoStore(SHAMapInnerNode&, int branch) const;
descendNoStore(SHAMapInnerNode&, unsigned int branch) const;
/**
* If there is only one leaf below this node, get its contents
@@ -581,8 +586,8 @@ private:
using StackEntry = std::tuple<
SHAMapInnerNode*, // pointer to the node
SHAMapNodeID, // the node's ID
int, // while child we check first
int, // which child we check next
unsigned int, // which child we check first
unsigned int, // which child we check next
bool>; // whether we've found any missing children yet
// We explicitly choose to specify the use of std::deque here, because
@@ -596,7 +601,7 @@ private:
using DeferredNode = std::tuple<
SHAMapInnerNode*, // parent node
SHAMapNodeID, // parent node ID
int, // branch
unsigned int, // branch
SHAMapTreeNodePtr>; // node
int deferred;
@@ -789,12 +794,6 @@ operator==(SHAMap::ConstIterator const& x, SHAMap::ConstIterator const& y)
return x.item_ == y.item_;
}
inline bool
operator!=(SHAMap::ConstIterator const& x, SHAMap::ConstIterator const& y)
{
return !(x == y);
}
inline SHAMap::ConstIterator
SHAMap::begin() const
{

View File

@@ -62,8 +62,8 @@ private:
*
* @param i index of the requested child
*/
std::optional<int>
getChildIndex(int i) const;
std::optional<unsigned int>
getChildIndex(unsigned int i) const;
/**
* Call the `f` callback for all 16 (branchFactor) branches - even if
@@ -125,28 +125,28 @@ public:
isEmpty() const;
bool
isEmptyBranch(int m) const;
isEmptyBranch(unsigned int branch) const;
int
unsigned int
getBranchCount() const;
SHAMapHash const&
getChildHash(int m) const;
getChildHash(unsigned int branch) const;
void
setChild(int m, SHAMapTreeNodePtr child);
setChild(unsigned int branch, SHAMapTreeNodePtr child);
void
shareChild(int m, SHAMapTreeNodePtr const& child);
shareChild(unsigned int branch, SHAMapTreeNodePtr const& child);
SHAMapTreeNode*
getChildPointer(int branch);
getChildPointer(unsigned int branch);
SHAMapTreeNodePtr
getChild(int branch);
getChild(unsigned int branch);
SHAMapTreeNodePtr
canonicalizeChild(int branch, SHAMapTreeNodePtr node);
canonicalizeChild(unsigned int branch, SHAMapTreeNodePtr node);
// sync functions
bool
@@ -190,12 +190,12 @@ SHAMapInnerNode::isEmpty() const
}
inline bool
SHAMapInnerNode::isEmptyBranch(int m) const
SHAMapInnerNode::isEmptyBranch(unsigned int branch) const
{
return (isBranch_ & (1 << m)) == 0;
return (isBranch_ & (1u << branch)) == 0u;
}
inline int
inline unsigned int
SHAMapInnerNode::getBranchCount() const
{
return popcnt16(isBranch_);

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/base_uint.h>
#include <compare>
#include <cstddef>
#include <optional>
#include <ostream>
@@ -52,7 +53,7 @@ public:
}
[[nodiscard]] SHAMapNodeID
getChildNodeID(unsigned int m) const;
getChildNodeID(unsigned int branch) const;
/**
* Create a SHAMapNodeID of a node with the depth of the node and
@@ -63,47 +64,34 @@ public:
* @return SHAMapNodeID of the node
*/
static SHAMapNodeID
createID(int depth, uint256 const& key);
createID(unsigned int depth, uint256 const& key);
// FIXME-C++20: use spaceship and operator synthesis
/**
* Comparison operators
*
* <, >, <= and >= are synthesized from the spaceship. It is written out
* rather than defaulted because the ordering is by depth first, and the
* members are not declared in that order.
*/
bool
operator<(SHAMapNodeID const& n) const
std::strong_ordering
operator<=>(SHAMapNodeID const& n) const
{
return std::tie(depth_, id_) < std::tie(n.depth_, n.id_);
}
bool
operator>(SHAMapNodeID const& n) const
{
return n < *this;
}
bool
operator<=(SHAMapNodeID const& n) const
{
return !(n < *this);
}
bool
operator>=(SHAMapNodeID const& n) const
{
return !(*this < n);
return std::tie(depth_, id_) <=> std::tie(n.depth_, n.id_);
}
/**
* Equality, which the spaceship above does not provide.
*
* Only a *defaulted* operator<=> implicitly declares a defaulted
* operator==; the one above is user-provided, so == has to be written.
* It cannot be defaulted either, because a defaulted == would also compare
* the CountedObject base, which is not equality comparable.
*/
bool
operator==(SHAMapNodeID const& n) const
{
return (depth_ == n.depth_) && (id_ == n.id_);
}
bool
operator!=(SHAMapNodeID const& n) const
{
return !(*this == n);
}
};
inline std::string

View File

@@ -219,11 +219,11 @@ public:
*
* @param i index of the requested child
*/
[[nodiscard]] std::optional<int>
getChildIndex(std::uint16_t isBranch, int i) const;
[[nodiscard]] std::optional<unsigned int>
getChildIndex(std::uint16_t isBranch, unsigned int i) const;
};
[[nodiscard]] inline int
[[nodiscard]] inline unsigned int
popcnt16(std::uint16_t a)
{
#if __cpp_lib_bitops
@@ -234,11 +234,11 @@ popcnt16(std::uint16_t a)
// fallback to table lookup
static constexpr auto tbl = []() {
std::array<std::uint8_t, 256> ret{};
for (int i = 0; i != 256; ++i)
for (auto i = 0u; i != 256u; ++i)
{
for (int j = 0; j != 8; ++j)
for (auto j = 0u; j != 8u; ++j)
{
if (i & (1 << j))
if (i & (1u << j))
ret[i]++;
}
}

View File

@@ -22,6 +22,11 @@ static_assert(
static_assert(
kBoundaries.back() == SHAMapInnerNode::kBranchFactor,
"Last element of boundaries must be number of children in a dense array");
static_assert(
kBoundaries.front() >= 1,
"TaggedPointer.ipp subtracts 1 from a numAllocated value derived from "
"kBoundaries, as an unsigned quantity, in several places; the smallest "
"boundary must stay non-zero or those subtractions underflow.");
// Terminology: A chunk is the memory being allocated from a block. A block
// contains multiple chunks. This is the terminology the boost documentation
@@ -148,16 +153,16 @@ TaggedPointer::iterChildren(std::uint16_t isBranch, F&& f) const
if (numAllocated == SHAMapInnerNode::kBranchFactor)
{
// dense case
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
f(hashes[i]);
}
else
{
// sparse case
int curHashI = 0;
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
auto curHashI = 0u;
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
if ((1 << i) & isBranch)
if ((1u << i) & isBranch)
{
f(hashes[curHashI++]);
}
@@ -176,9 +181,9 @@ TaggedPointer::iterNonEmptyChildIndexes(std::uint16_t isBranch, F&& f) const
if (capacity() == SHAMapInnerNode::kBranchFactor)
{
// dense case
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
if ((1 << i) & isBranch)
if ((1u << i) & isBranch)
{
f(i, i);
}
@@ -187,10 +192,10 @@ TaggedPointer::iterNonEmptyChildIndexes(std::uint16_t isBranch, F&& f) const
else
{
// sparse case
int curHashI = 0;
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
auto curHashI = 0u;
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
if ((1 << i) & isBranch)
if ((1u << i) & isBranch)
{
f(i, curHashI++);
}
@@ -216,14 +221,14 @@ TaggedPointer::destroyHashesAndChildren()
deallocateArrays(tag, ptr);
}
inline std::optional<int>
TaggedPointer::getChildIndex(std::uint16_t isBranch, int i) const
inline std::optional<unsigned int>
TaggedPointer::getChildIndex(std::uint16_t isBranch, unsigned int i) const
{
if (isDense())
return i;
// Sparse case
if ((isBranch & (1 << i)) == 0)
if ((isBranch & (1u << i)) == 0u)
{
// Empty branch. Sparse children do not store empty branches
return {};
@@ -273,10 +278,10 @@ inline TaggedPointer::TaggedPointer(
*this = std::move(other);
auto [srcDstNumAllocated, srcDstHashes, srcDstChildren] = getHashesAndChildren();
bool const srcDstIsDense = isDense();
int srcDstIndex = 0;
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
auto srcDstIndex = 0u;
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
auto const mask = (1 << i);
auto const mask = (1u << i);
bool const inSrc = (srcBranches & mask) != 0;
bool const inDst = (dstBranches & mask) != 0;
if (inSrc && inDst)
@@ -298,13 +303,13 @@ inline TaggedPointer::TaggedPointer(
// sparse
// need to shift all the elements to the left by
// one
for (int c = srcDstIndex; c < srcDstNumAllocated - 1; ++c)
for (auto c = srcDstIndex; c + 1 < srcDstNumAllocated; ++c)
{
srcDstHashes[c] = srcDstHashes[c + 1];
srcDstChildren[c] = std::move(srcDstChildren[c + 1]);
}
srcDstHashes[srcDstNumAllocated - 1].zero();
srcDstChildren[srcDstNumAllocated - 1].reset();
srcDstHashes[srcDstNumAllocated - 1u].zero();
srcDstChildren[srcDstNumAllocated - 1u].reset();
// do not increment the index
}
}
@@ -321,7 +326,7 @@ inline TaggedPointer::TaggedPointer(
// sparse
// need to create a hole by shifting all the elements to the
// right by one
for (int c = srcDstNumAllocated - 1; c > srcDstIndex; --c)
for (auto c = srcDstNumAllocated - 1u; c > srcDstIndex; --c)
{
srcDstHashes[c] = srcDstHashes[c - 1];
srcDstChildren[c] = std::move(srcDstChildren[c - 1]);
@@ -352,10 +357,10 @@ inline TaggedPointer::TaggedPointer(
auto [srcNumAllocated, srcHashes, srcChildren] = src.getHashesAndChildren();
bool const srcIsDense = src.isDense();
bool const dstIsDense = dst.isDense();
int srcIndex = 0, dstIndex = 0;
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
auto srcIndex = 0u, dstIndex = 0u;
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
auto const mask = (1 << i);
auto const mask = (1u << i);
bool const inSrc = (srcBranches & mask) != 0;
bool const inDst = (dstBranches & mask) != 0;
if (inSrc && inDst)
@@ -409,7 +414,7 @@ inline TaggedPointer::TaggedPointer(
!dstIsDense || dstIndex == dstNumAllocated,
"xrpl::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : "
"non-sparse or valid sparse");
for (int i = dstIndex; i < dstNumAllocated; ++i)
for (auto i = dstIndex; i < dstNumAllocated; ++i)
{
new (&dstHashes[i]) SHAMapHash{};
new (&dstChildren[i]) SHAMapTreeNodePtr{};
@@ -448,9 +453,9 @@ inline TaggedPointer::TaggedPointer(
new (&newChildren[branchNum]) SHAMapTreeNodePtr{std::move(oldChildren[indexNum])};
});
// Run the constructors for the remaining elements
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
{
if (((1 << i) & isBranch) != 0)
if (((1u << i) & isBranch) != 0u)
continue;
new (&newHashes[i]) SHAMapHash{};
new (&newChildren[i]) SHAMapTreeNodePtr{};
@@ -459,7 +464,7 @@ inline TaggedPointer::TaggedPointer(
else
{
// new arrays are sparse, old arrays may be sparse or dense
int curCompressedIndex = 0;
auto curCompressedIndex = 0u;
iterNonEmptyChildIndexes(isBranch, [&](auto branchNum, auto indexNum) {
new (&newHashes[curCompressedIndex]) SHAMapHash{oldHashes[indexNum]};
new (&newChildren[curCompressedIndex])
@@ -467,7 +472,7 @@ inline TaggedPointer::TaggedPointer(
++curCompressedIndex;
});
// Run the constructors for the remaining elements
for (int i = curCompressedIndex; i < newNumAllocated; ++i)
for (auto i = curCompressedIndex; i < newNumAllocated; ++i)
{
new (&newHashes[i]) SHAMapHash{};
new (&newChildren[i]) SHAMapTreeNodePtr{};

View File

@@ -69,7 +69,8 @@ private:
IssuerChanges const& changes,
STTx const& tx,
beast::Journal const& j,
bool enforce);
bool enforce,
bool fixOverrideFreeze);
static bool
validateFrozenState(
@@ -78,7 +79,8 @@ private:
STTx const& tx,
beast::Journal const& j,
bool enforce,
bool globalFreeze);
bool globalFreeze,
bool fixOverrideFreeze);
};
} // namespace xrpl

View File

@@ -198,7 +198,7 @@ public:
/**
* @brief Invariant: An account XRP balance must be in XRP and take a value
* between 0 and INITIAL_XRP drops, inclusive.
* between 0 and kInitialXRP drops, inclusive.
*
* We iterate all account roots modified by the transaction and ensure that
* their XRP balances are reasonable.
@@ -290,7 +290,7 @@ public:
/**
* @brief Invariant: an escrow entry must take a value between 0 and
* INITIAL_XRP drops exclusive.
* kInitialXRP drops exclusive.
*/
class NoZeroEscrow
{

View File

@@ -16,6 +16,8 @@ namespace xrpl {
* @brief Invariants: Loans are internally consistent
*
* 1. If `Loan.PaymentRemaining = 0` then `Loan.PrincipalOutstanding = 0`
* 2. A newly-created Loan against a closed-ended vault must satisfy
* `StartDate + PaymentInterval * PaymentRemaining < Vault.RedemptionDate`.
*
*/
class ValidLoan

View File

@@ -38,7 +38,17 @@ namespace xrpl {
* - vault set must not alter the vault assets or shares balance
* - no vault transaction can change loss unrealized (it's updated by loan
* transactions)
* - a created closed-ended vault must satisfy
* MIN_INVESTMENT_PERIOD <= RedemptionDate - SubscriptionDate <
* MAX_INVESTMENT_PERIOD
* - vault deposit may only succeed when the vault phase is NoPhase or
* Subscription
* - vault withdrawal may not succeed when the vault phase is Investment
* - closed-ended loan origination (ttLOAN_SET) may only succeed when the
* vault phase is Investment
*
* Immutability of VaultKind, SubscriptionDate and RedemptionDate is enforced
* by NoModifiedUnmodifiableFields (see InvariantCheck.cpp).
*/
class ValidVault
{
@@ -55,6 +65,9 @@ class ValidVault
Number assetsAvailable = 0;
Number assetsMaximum = 0;
Number lossUnrealized = 0;
std::optional<std::uint8_t> vaultKind;
std::optional<std::uint32_t> subscriptionDate;
std::optional<std::uint32_t> redemptionDate;
Vault static make(SLE const&);
};
@@ -153,6 +166,17 @@ private:
[[nodiscard]] static bool
isVaultEmpty(Vault const& vault);
/**
* @brief Invariant check for @c ttLOAN_SET.
*
* For a closed-ended vault, a loan may only be originated while the vault is in the Investment
* phase (strictly past @c SubscriptionDate and before @c RedemptionDate). Open-ended vaults (@c
* NoPhase) are unaffected. The complementary maturity bound (final payment strictly precedes @c
* RedemptionDate) is enforced by @c ValidLoan.
*/
[[nodiscard]] bool
finalizeLoanSet(ReadView const& view, beast::Journal const& j) const;
public:
// Compute the coarsest scale required to represent all numbers
[[nodiscard]] static std::int32_t

View File

@@ -274,19 +274,6 @@ public:
return lhs.equal(rhs);
}
/**
* Return true if lhs != rhs.
*
* @param lhs Step to compare.
* @param rhs Step to compare.
* @return true if lhs != rhs.
*/
friend bool
operator!=(Step const& lhs, Step const& rhs)
{
return !(lhs == rhs);
}
/**
* Streaming operator for a Step.
*/

View File

@@ -1,6 +1,7 @@
#pragma once
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/Zero.h>
@@ -373,7 +374,7 @@ qualityUpperBound(ReadView const& v, Strand const& strand)
* increases quality of AMM steps, increasing the strand's composite
* quality as the result.
*/
template <typename TOutAmt>
template <StepAmount TOutAmt>
inline TOutAmt
limitOut(
ReadView const& v,
@@ -411,21 +412,29 @@ limitOut(
auto const out = qf->outFromAvgQ(limitQuality);
if (!out)
return remainingOut;
if constexpr (std::is_same_v<TOutAmt, XRPAmount>)
if constexpr (std::is_same_v<TOutAmt, XRPAmount> || std::is_same_v<TOutAmt, MPTAmount>)
{
return XRPAmount{*out};
auto const roundedOut = TOutAmt{*out};
// Integral outputs that round above the continuous target can
// realize worse average quality than the requested limit. Keep the
// default rounded value when it still satisfies the limit, since it
// is the largest matching offer; otherwise round down.
if (v.rules().enabled(featureMPTokensV2) && roundedOut > *out &&
!qf->satisfiesAvgQ(limitQuality, roundedOut))
{
NumberRoundModeGuard const g(Number::RoundingMode::Downward);
return TOutAmt{*out};
}
return roundedOut;
}
else if constexpr (std::is_same_v<TOutAmt, IOUAmount>)
{
return IOUAmount{*out};
}
else if constexpr (std::is_same_v<TOutAmt, MPTAmount>)
{
return MPTAmount{*out};
}
else
{
return STAmount{remainingOut.asset(), out->mantissa(), out->exponent()};
static constexpr bool kAlwaysFalse = !std::is_same_v<TOutAmt, TOutAmt>;
static_assert(kAlwaysFalse, "Unhandled StepAmount type");
}
}();
// A tiny difference could be due to the round off

View File

@@ -118,6 +118,7 @@ public:
Sandbox& view,
SLE const& ammSle,
AccountID const account,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& ammAccount,
STAmount const& amountBalance,
STAmount const& amount2Balance,
@@ -138,6 +139,11 @@ public:
* @param view
* @param ammSle AMM ledger entry
* @param ammAccount AMM account
* @param clawbackIssuer when set (AMMClawback path), the issuer performing
* the clawback. A recreated MPToken is only auto-authorized when the
* asset's issuer matches this account, so a clawback cannot grant
* authorization on behalf of a different (paired-asset) issuer.
* @param account LP account
* @param amountBalance current LP asset1 balance
* @param amountWithdraw asset1 withdraw amount
* @param amount2Withdraw asset2 withdraw amount
@@ -153,6 +159,7 @@ public:
Sandbox& view,
SLE const& ammSle,
AccountID const& ammAccount,
std::optional<AccountID> const& clawbackIssuer,
AccountID const& account,
STAmount const& amountBalance,
STAmount const& amountWithdraw,

View File

@@ -1,7 +1,8 @@
# check-tools snapshots
These files capture the output of [`bin/check-tools.sh`](../../bin/check-tools.sh)
— the versions of the development tooling — in each Nix environment:
— the version and resolved store path of each development tool — in each Nix
environment:
| File | Environment |
| ---------------------- | ------------------------------------ |
@@ -17,9 +18,13 @@ So if you change the environment (bump the image tag in
and commit the affected snapshots.
Each snapshot is `check-tools.sh` stdout with the git-clone connectivity check
skipped (`CHECK_TOOLS_SKIP_CLONE=1`), so it contains only deterministic version
data. On macOS the dev-shell greeting that `nix develop` prints first is dropped
with `sed -n '/^Detected OS:/,$p'`.
skipped (`CHECK_TOOLS_SKIP_CLONE=1`), so it is deterministic for a given
environment. On macOS the dev-shell greeting that `nix develop` prints first is
dropped with `sed -n '/^Detected OS:/,$p'`.
The store paths carry their derivation hash, so they change whenever a tool is
rebuilt — a `flake.lock` update generally rewrites most of them even when no
version moves. That is deliberate: it makes tooling changes visible in review.
## Regenerating

View File

@@ -1,47 +1,143 @@
Detected OS: macos (Darwin arm64)
Core build tools:
[ ok ] cmake cmake version 4.1.2
[ ok ] conan Conan version 2.28.1
[ ok ] git git version 2.54.0
[ ok ] python3 Python 3.13.13
✅ cmake
cmake version 4.1.2
/nix/store/gvabsb4yqb5xsqzqph54rijnn4zpihnp-cmake-4.1.2/bin/cmake
✅ conan
Conan version 2.28.1
/nix/store/9jiyxmkpwmn6dcqs0765s83riw3l5ail-conan-2.28.1/bin/conan
✅ git
git version 2.54.0
/nix/store/a14yxcqvv9x2l9mllgpirzhvz93pgprg-git-2.54.0/bin/git
✅ python3
Python 3.13.13
/nix/store/ygxqin6ydzjfawywqpp5pal8wv6sf5bh-python3-3.13.13/bin/python3.13
Development tooling:
[ ok ] ccache ccache version 4.13.6
[ ok ] clang clang version 22.1.7
[ ok ] clang++ clang version 22.1.7
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
[ ok ] curl curl 8.20.0 (aarch64-apple-darwin25.3.0) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
[ ok ] file file-5.47
[ ok ] less less 692 (PCRE2 regular expressions)
[ ok ] make GNU Make 4.4.1
[ ok ] netstat present
[ ok ] ninja 1.13.2
[ ok ] perl v5.42.0
[ ok ] pkg-config 0.29.2
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
[ ok ] zip Zip 3.0
[ ok ] clang-format clang-format version 22.1.7
[ ok ] dot dot - graphviz version 12.2.1 (0)
[ ok ] doxygen 1.16.1
[ ok ] gcovr gcovr 8.4
[ ok ] gh gh version 2.94.0 (nixpkgs)
[ ok ] git-cliff git-cliff 2.13.1
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; darwin arm64; go 1.26.3)
[ ok ] gpg gpg (GnuPG) 2.4.9
[ ok ] pre-commit pre-commit 4.5.1
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
ccache
ccache version 4.13.6
/nix/store/57davyvs6p6dkrl3svzwg1ph18wsy4cz-ccache-4.13.6/bin/ccache
✅ clang
clang version 22.1.7
/nix/store/192glrb2cldvziyf3378mzjqbzx3ih4g-clang-wrapper-22.1.7/bin/clang
✅ clang-22
clang version 22.1.7
/nix/store/rbap7zqq7mw00fyqa02p5rj7gqjp4w5i-clang-22/bin/clang-22
✅ clang++
clang version 22.1.7
/nix/store/192glrb2cldvziyf3378mzjqbzx3ih4g-clang-wrapper-22.1.7/bin/clang++
✅ clang++-22
clang version 22.1.7
/nix/store/v9haf787f7bcz0mq1sad4bpyx21pj6li-clang++-22/bin/clang++-22
✅ ClangBuildAnalyzer
ClangBuildAnalyzer 1.6.0
/nix/store/4l50ds9fa2mkvh7wg8qzrlbmjs12sb8l-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
✅ curl
curl 8.20.0 (aarch64-apple-darwin25.3.0) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
/nix/store/kclq0czaxvsgh4ym9ld7b6iwy50l1snk-curl-8.20.0-bin/bin/curl
✅ file
file-5.47
/nix/store/dax63li7wwcbqxxkkgzc4g2rx7d4w86x-file-5.47/bin/file
✅ less
less 692 (PCRE2 regular expressions)
/nix/store/lvr16y75r1pdxpdv0aph5ak2yd0hkvqm-less-692/bin/less
✅ make
GNU Make 4.4.1
/nix/store/8wwiw8pwyhrkzyq28hqzxfl4z84lks81-gnumake-4.4.1/bin/make
✅ netstat
present
/nix/store/qsd1kzqb0ahrk433vmyl245gp623j19s-network_cmds-730.80.3/bin/netstat
✅ ninja
1.13.2
/nix/store/bqykhrblarkj4fl0hz2mf8ngwfv6x6bz-ninja-1.13.2/bin/ninja
✅ perl
v5.42.0
/nix/store/js13ri9fvm0ajk1fpd3acigys2a9whdv-perl-5.42.0/bin/perl
✅ pkg-config
0.29.2
/nix/store/lzrwr375jqhhbca116kja96xf1md83l8-pkg-config-wrapper-0.29.2/bin/pkg-config
✅ vim
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
/nix/store/6vbkykg92w603c0sw3mkk7p7mfaawbns-vim-9.2.0389/bin/vim
✅ zip
Zip 3.0
/nix/store/z6ph729vcakbvz3wh8ln1wk6mi06w487-zip-3.0/bin/zip
✅ clang-apply-replacements
clang-apply-replacements version 22.1.7
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-apply-replacements
✅ clang-apply-replacements-22
clang-apply-replacements version 22.1.7
/nix/store/m3ii69rca4077lf4wlk7m3jcag1fs577-clang-apply-replacements-22/bin/clang-apply-replacements-22
✅ clang-format
clang-format version 22.1.7
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-format
✅ clang-format-22
clang-format version 22.1.7
/nix/store/4fawqy6ngqcsqd2ygyyzm93q0xy3f5gs-clang-format-22/bin/clang-format-22
✅ clang-tidy
LLVM version 22.1.7
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-tidy
✅ clang-tidy-22
LLVM version 22.1.7
/nix/store/jqw4280saixaxxihwdba9ldm2fsm6dr3-clang-tidy-22/bin/clang-tidy-22
✅ dot
dot - graphviz version 12.2.1 (0)
/nix/store/ijb4fbnqa6wzlpqnhb6q9knqpf7qqn5z-graphviz-12.2.1/bin/dot
✅ doxygen
1.16.1
/nix/store/kbryjdpq9jizjb0ws0nzbf2h2ymbdiwm-doxygen-1.16.1/bin/doxygen
✅ gcovr
gcovr 8.4
/nix/store/wn8jiyh9p0bybs96s4163qp3k8vfmczx-python3.13-gcovr-8.4/bin/gcovr
✅ gh
gh version 2.94.0 (nixpkgs)
/nix/store/fhnpw0hs0gjms1ha6ap02jq7rx13gkbp-gh-2.94.0/bin/gh
✅ git-cliff
git-cliff 2.13.1
/nix/store/cy0wwhgxa7yvrz97zydbq6sqmixc90fq-git-cliff-2.13.1/bin/git-cliff
✅ git-lfs
git-lfs/3.7.1 (3.7.1; darwin arm64; go 1.26.3)
/nix/store/k9r7zjfjplqa4d5s71cqvf2iv73jd9mc-git-lfs-3.7.1/bin/git-lfs
✅ gpg
gpg (GnuPG) 2.4.9
/nix/store/cgh6iwzz5jgx9z5whka4vgj210i6npc6-gnupg-2.4.9/bin/gpg
✅ pre-commit
pre-commit 4.5.1
/nix/store/z3cca68620w0w10f090szgzdnmh1waf2-pre-commit-4.5.1/bin/pre-commit
✅ run-clang-tidy
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/4x28x911z2f9y7adqlh3qspp4a16dig7-run-clang-tidy/bin/run-clang-tidy
✅ run-clang-tidy-22
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/x8iymrh76sk5q91ryg5pa7i32s6gfh34-run-clang-tidy-22/bin/run-clang-tidy-22
Rust toolchain:
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
[ ok ] cargo-audit cargo-audit-audit 0.22.1
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
[ ok ] cargo-nextest cargo-nextest 0.9.137
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
[ ok ] rust-analyzer rust-analyzer 1.95.0 (59807616 2026-04-14)
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
✅ cargo
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/cargo
cargo-audit
cargo-audit-audit 0.22.1
/nix/store/snwkga2f5gyf404h7mmp9wriwxb8v65f-cargo-audit-0.22.1/bin/cargo-audit
✅ cargo-llvm-cov
cargo-llvm-cov 0.8.5
/nix/store/fpiqdh91gwyxalqp409ynm0s0g086w7w-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
✅ cargo-nextest
cargo-nextest 0.9.137
/nix/store/ylz7m947mhkgsp6i7611id3s3gcd58nq-cargo-nextest-0.9.137/bin/cargo-nextest
✅ clippy-driver
clippy 0.1.95 (59807616e1 2026-04-14)
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/clippy-driver
✅ rust-analyzer
rust-analyzer 1.95.0 (59807616 2026-04-14)
/nix/store/jqvjap2727r9cjpr25fkw5glv2kbxrdx-rust-analyzer-preview-1.95.0-aarch64-apple-darwin/bin/rust-analyzer
✅ rustc
rustc 1.95.0 (59807616e 2026-04-14)
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/rustc
✅ rustfmt
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
/nix/store/03x750yj6fakl7shbhicpnkxiwqxjrrs-rustfmt-preview-1.95.0-aarch64-apple-darwin/bin/rustfmt
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
All 36 checked tools are present and runnable.
All 44 checked tools are present and runnable.

View File

@@ -1,55 +1,171 @@
Detected OS: linux (Linux x86_64)
Core build tools:
[ ok ] cmake cmake version 4.1.2
[ ok ] conan Conan version 2.28.1
[ ok ] git git version 2.54.0
[ ok ] python3 Python 3.13.13
✅ cmake
cmake version 4.1.2
/nix/store/r9941n32g4wyvggz2703dlplbdq8a6rd-cmake-4.1.2/bin/cmake
✅ conan
Conan version 2.28.1
/nix/store/lxny9y4jvjdws7hgz1mygvb7hjrpmna5-conan-2.28.1/bin/conan
✅ git
git version 2.54.0
/nix/store/bcnisk3ydfgv26v2gw3zlky24g00yww2-git-2.54.0/bin/git
✅ python3
Python 3.13.13
/nix/store/60m4rxhg2fldqaak400c0lry96ijrzqn-python3-3.13.13/bin/python3.13
Development tooling:
[ ok ] ccache ccache version 4.13.6
[ ok ] clang clang version 22.1.7
[ ok ] clang++ clang version 22.1.7
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
[ ok ] curl curl 8.20.0 (x86_64-pc-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
[ ok ] file file-5.47
[ ok ] less less 692 (PCRE2 regular expressions)
[ ok ] make GNU Make 4.4.1
[ ok ] netstat net-tools 2.10
[ ok ] ninja 1.13.2
[ ok ] perl v5.42.0
[ ok ] pkg-config 0.29.2
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
[ ok ] zip Zip 3.0
[ ok ] clang-format clang-format version 22.1.7
[ ok ] dot dot - graphviz version 12.2.1 (0)
[ ok ] doxygen 1.16.1
[ ok ] gcovr gcovr 8.4
[ ok ] gh gh version 2.94.0 (nixpkgs)
[ ok ] git-cliff git-cliff 2.13.1
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; linux amd64; go 1.26.3)
[ ok ] gpg gpg (GnuPG) 2.4.9
[ ok ] pre-commit pre-commit 4.5.1
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
ccache
ccache version 4.13.6
/nix/store/c9wwl7s5i6rsfwvf4v0xbbmzx5m6jgfr-ccache-4.13.6/bin/ccache
✅ clang
clang version 22.1.7
/nix/store/ff0hrp9r9i3pa5arkdw0sgmzp8d576qi-clang-wrapper-22.1.7/bin/clang
✅ clang-22
clang version 22.1.7
/nix/store/dagc2rq44gfbr7w7yvvqca3yqpc9gqbq-clang-22/bin/clang-22
✅ clang++
clang version 22.1.7
/nix/store/ff0hrp9r9i3pa5arkdw0sgmzp8d576qi-clang-wrapper-22.1.7/bin/clang++
✅ clang++-22
clang version 22.1.7
/nix/store/l5m8clin1npl605wdkd8mr18ggxww3z4-clang++-22/bin/clang++-22
✅ ClangBuildAnalyzer
ClangBuildAnalyzer 1.6.0
/nix/store/bshlmn8fqw55nsnm581xqlfbahfkykxx-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
✅ curl
curl 8.20.0 (x86_64-pc-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
/nix/store/zbwymrp4lcfjc4kkk0n4779v0kjjz58z-curl-8.20.0-bin/bin/curl
✅ file
file-5.47
/nix/store/bizyfqdw0h67wzqmp10knmf9s2pqahdb-file-5.47/bin/file
✅ less
less 692 (PCRE2 regular expressions)
/nix/store/c6bacbn93qg4a7g9n4czww8rg24dvysr-less-692/bin/less
✅ make
GNU Make 4.4.1
/nix/store/d3bwqm6bymhy3pdgbvf7vxjqfp31m3j1-gnumake-4.4.1/bin/make
✅ netstat
net-tools 2.10
/nix/store/jmyzqvgflnswmws7rnxx6g3zbj680xvd-net-tools-2.10/bin/netstat
✅ ninja
1.13.2
/nix/store/7a235m7crqbb4h49sak20fqxpw3n7hr0-ninja-1.13.2/bin/ninja
✅ perl
v5.42.0
/nix/store/6plwsm6pkq79yjv4xvy8csk2pd4hzr67-perl-5.42.0/bin/perl
✅ pkg-config
0.29.2
/nix/store/1m05k7xgfnw6jc21xxk5681ni3ar97wf-pkg-config-wrapper-0.29.2/bin/pkg-config
✅ vim
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
/nix/store/hvyqx52g4g2fxhgpans3fksjj6lmlyaw-vim-9.2.0389/bin/vim
✅ zip
Zip 3.0
/nix/store/qnd2ag67hrjj0b6vbmisdshf50r6s72n-zip-3.0/bin/zip
✅ clang-apply-replacements
clang-apply-replacements version 22.1.7
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-apply-replacements
✅ clang-apply-replacements-22
clang-apply-replacements version 22.1.7
/nix/store/py2wihg0a96qcppv4hjmww547xabr0fb-clang-apply-replacements-22/bin/clang-apply-replacements-22
✅ clang-format
clang-format version 22.1.7
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-format
✅ clang-format-22
clang-format version 22.1.7
/nix/store/kz820ccifjlwqnwqjsx7kbiajrgsmbrh-clang-format-22/bin/clang-format-22
✅ clang-tidy
LLVM version 22.1.7
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-tidy
✅ clang-tidy-22
LLVM version 22.1.7
/nix/store/gdrkvpw846lkyzh8y9p3zx50g6ml2v84-clang-tidy-22/bin/clang-tidy-22
✅ dot
dot - graphviz version 12.2.1 (0)
/nix/store/12rgns2296s4qcja778gvcbx61z77rc4-graphviz-12.2.1/bin/dot
✅ doxygen
1.16.1
/nix/store/k0vzr5lvgq1byraknzwvk51wcgpnsrkh-doxygen-1.16.1/bin/doxygen
✅ gcovr
gcovr 8.4
/nix/store/iyzi7fpyclqrha054adnizvif02lg49x-python3.13-gcovr-8.4/bin/gcovr
✅ gh
gh version 2.94.0 (nixpkgs)
/nix/store/pidh15szlsb1vc41xdsa3xbdghdazvby-gh-2.94.0/bin/gh
✅ git-cliff
git-cliff 2.13.1
/nix/store/1q851fs62shgjhc03fxxdkpzxdjg7k11-git-cliff-2.13.1/bin/git-cliff
✅ git-lfs
git-lfs/3.7.1 (3.7.1; linux amd64; go 1.26.3)
/nix/store/6ljwpal7b1756708m33vj0crpral7mvl-git-lfs-3.7.1/bin/git-lfs
✅ gpg
gpg (GnuPG) 2.4.9
/nix/store/wx7vk8babxkgy813r70yc67vcwnmagbx-gnupg-2.4.9/bin/gpg
✅ pre-commit
pre-commit 4.5.1
/nix/store/bj6i9vl34cij5h0r165y40hrjqak0bmz-pre-commit-4.5.1/bin/pre-commit
✅ run-clang-tidy
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/sbg911hs9dbclrzlp04br3iyfpgnaj6r-run-clang-tidy/bin/run-clang-tidy
✅ run-clang-tidy-22
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/n8yak1ap308gvi7gmrniw0ybsx80fjws-run-clang-tidy-22/bin/run-clang-tidy-22
Rust toolchain:
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
[ ok ] cargo-audit cargo-audit-audit 0.22.1
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
[ ok ] cargo-nextest cargo-nextest 0.9.137
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
[ ok ] rust-analyzer rust-analyzer 1.95.0 (5980761 2026-04-14)
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
✅ cargo
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
/nix/store/85qbwr3vzfs58m7ywnjblz105p8ahbrv-cargo-1.95.0-x86_64-unknown-linux-gnu/bin/cargo
cargo-audit
cargo-audit-audit 0.22.1
/nix/store/2w9if868piw98xz057sz97jnjvf7hnvf-cargo-audit-0.22.1/bin/cargo-audit
✅ cargo-llvm-cov
cargo-llvm-cov 0.8.5
/nix/store/jjpdf1l6izz6607a346ykra9sndzaw7h-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
✅ cargo-nextest
cargo-nextest 0.9.137
/nix/store/jhkr7gwyrchkml33gyns9cy0yn7b57qc-cargo-nextest-0.9.137/bin/cargo-nextest
✅ clippy-driver
clippy 0.1.95 (59807616e1 2026-04-14)
/nix/store/bnvg9nmdq4g98dd9v3r6nvjg5h2rr8i7-rust-minimal-1.95.0/bin/clippy-driver
✅ rust-analyzer
rust-analyzer 1.95.0 (5980761 2026-04-14)
/nix/store/i3cnpngfwa3k4jn431pl6ji1r4qmxky9-rust-analyzer-preview-1.95.0-x86_64-unknown-linux-gnu/bin/rust-analyzer
✅ rustc
rustc 1.95.0 (59807616e 2026-04-14)
/nix/store/bnvg9nmdq4g98dd9v3r6nvjg5h2rr8i7-rust-minimal-1.95.0/bin/rustc
✅ rustfmt
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
/nix/store/366hhk2dgwxmnf4hgrj4b8llhjr3hf0i-rustfmt-preview-1.95.0-x86_64-unknown-linux-gnu/bin/rustfmt
GCC toolchain:
[ ok ] gcc gcc (GCC) 15.2.0
[ ok ] g++ g++ (GCC) 15.2.0
[ ok ] gcov gcov (GCC) 15.2.0
✅ gcc
gcc (GCC) 15.2.0
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/gcc
✅ gcc-15
gcc (GCC) 15.2.0
/nix/store/d6iri2s6bzqq5ac3fg25j6hgnn1lz44f-gcc-15/bin/gcc-15
✅ g++
g++ (GCC) 15.2.0
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/g++
✅ g++-15
g++ (GCC) 15.2.0
/nix/store/gm3msmmxq055lm9gprkfjj9d2gdz1mpg-g++-15/bin/g++-15
✅ cpp
cpp (GCC) 15.2.0
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/cpp
✅ cpp-15
cpp (GCC) 15.2.0
/nix/store/bn3gmn0m7g4gn2i0yml46fljc7mghiq5-cpp-15/bin/cpp-15
✅ gcov
gcov (GCC) 15.2.0
/nix/store/xvv5sm5i8x0ks6ypfkzl7c4j9srnxz7k-gcc-15.2.0/bin/gcov
Mold:
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
✅ mold
mold 2.41.0 (compatible with GNU ld)
/nix/store/2w6fpgxjzzyqmd25wzplm23dfa49a0p2-mold-unwrapped-wrapper-2.41.0/bin/mold
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
All 40 checked tools are present and runnable.
All 52 checked tools are present and runnable.

View File

@@ -1,55 +1,171 @@
Detected OS: linux (Linux aarch64)
Core build tools:
[ ok ] cmake cmake version 4.1.2
[ ok ] conan Conan version 2.28.1
[ ok ] git git version 2.54.0
[ ok ] python3 Python 3.13.13
✅ cmake
cmake version 4.1.2
/nix/store/nkcpxjifkambzlrwh27a8igvhnbchibg-cmake-4.1.2/bin/cmake
✅ conan
Conan version 2.28.1
/nix/store/8i2gyqgc00xvxg9xm6y7n0ilncdv8imw-conan-2.28.1/bin/conan
✅ git
git version 2.54.0
/nix/store/ixp98f9avf8ikpdrmp40cj33g0dazyp9-git-2.54.0/bin/git
✅ python3
Python 3.13.13
/nix/store/lqn6mbgzzdrqq2qkwddcmxj9z6amdd86-python3-3.13.13/bin/python3.13
Development tooling:
[ ok ] ccache ccache version 4.13.6
[ ok ] clang clang version 22.1.7
[ ok ] clang++ clang version 22.1.7
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
[ ok ] curl curl 8.20.0 (aarch64-unknown-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
[ ok ] file file-5.47
[ ok ] less less 692 (PCRE2 regular expressions)
[ ok ] make GNU Make 4.4.1
[ ok ] netstat net-tools 2.10
[ ok ] ninja 1.13.2
[ ok ] perl v5.42.0
[ ok ] pkg-config 0.29.2
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
[ ok ] zip Zip 3.0
[ ok ] clang-format clang-format version 22.1.7
[ ok ] dot dot - graphviz version 12.2.1 (0)
[ ok ] doxygen 1.16.1
[ ok ] gcovr gcovr 8.4
[ ok ] gh gh version 2.94.0 (nixpkgs)
[ ok ] git-cliff git-cliff 2.13.1
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; linux arm64; go 1.26.3)
[ ok ] gpg gpg (GnuPG) 2.4.9
[ ok ] pre-commit pre-commit 4.5.1
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
ccache
ccache version 4.13.6
/nix/store/2q39xi2kbi04ibga7635f2sl148d1mzv-ccache-4.13.6/bin/ccache
✅ clang
clang version 22.1.7
/nix/store/xjqffrq9i7la058s9865ig71l9sp1ys5-clang-wrapper-22.1.7/bin/clang
✅ clang-22
clang version 22.1.7
/nix/store/vcf6ilfwn57828hwzyp6zlyr24j9j6yw-clang-22/bin/clang-22
✅ clang++
clang version 22.1.7
/nix/store/xjqffrq9i7la058s9865ig71l9sp1ys5-clang-wrapper-22.1.7/bin/clang++
✅ clang++-22
clang version 22.1.7
/nix/store/xby0f6gamr7m27zp5cndsvghbp9lgb3c-clang++-22/bin/clang++-22
✅ ClangBuildAnalyzer
ClangBuildAnalyzer 1.6.0
/nix/store/h893hd4q1bb6ily2lby5dzyfrrzd2nvj-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
✅ curl
curl 8.20.0 (aarch64-unknown-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
/nix/store/i1s0lqwlrmjd2dxzgy2p84cxqqsb0bmk-curl-8.20.0-bin/bin/curl
✅ file
file-5.47
/nix/store/dx973zg9km2w9albsib2vw9wyvacfrlw-file-5.47/bin/file
✅ less
less 692 (PCRE2 regular expressions)
/nix/store/1blb3s7hhsr77wqi598m6k1qkfp3ms0w-less-692/bin/less
✅ make
GNU Make 4.4.1
/nix/store/9ngw1ippk25jjj5fjxv36xbp6iq7rxdx-gnumake-4.4.1/bin/make
✅ netstat
net-tools 2.10
/nix/store/7vdsz21f0s499s5yyqzp5s4676q4yxdd-net-tools-2.10/bin/netstat
✅ ninja
1.13.2
/nix/store/8ksx98gsbn5lmlizcmw57yd4sg0k2p58-ninja-1.13.2/bin/ninja
✅ perl
v5.42.0
/nix/store/5wnly69vv1i3y97al4v3xrqymf9hlzgq-perl-5.42.0/bin/perl
✅ pkg-config
0.29.2
/nix/store/c7vwy0gl1q0agl2h22gi0m9dg7xxad2l-pkg-config-wrapper-0.29.2/bin/pkg-config
✅ vim
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
/nix/store/v8c7pvx26irvy9k5sbwd183cyvckzzb3-vim-9.2.0389/bin/vim
✅ zip
Zip 3.0
/nix/store/5mh19mvbv9ym2sm9vymyyaac5l2cj2jq-zip-3.0/bin/zip
✅ clang-apply-replacements
clang-apply-replacements version 22.1.7
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-apply-replacements
✅ clang-apply-replacements-22
clang-apply-replacements version 22.1.7
/nix/store/bg4kn8z81hk7b9284rjqvr51wpfjqc24-clang-apply-replacements-22/bin/clang-apply-replacements-22
✅ clang-format
clang-format version 22.1.7
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-format
✅ clang-format-22
clang-format version 22.1.7
/nix/store/79v57mzcw8ng8kl7p961ck08ymhp31v7-clang-format-22/bin/clang-format-22
✅ clang-tidy
LLVM version 22.1.7
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-tidy
✅ clang-tidy-22
LLVM version 22.1.7
/nix/store/wdyd6cb9z1lyi37lbzvwldgcc7yv1n5c-clang-tidy-22/bin/clang-tidy-22
✅ dot
dot - graphviz version 12.2.1 (0)
/nix/store/58rrk4yzwpmyxvl8cqm18h3dhv24zf00-graphviz-12.2.1/bin/dot
✅ doxygen
1.16.1
/nix/store/hq32kzwpl89wgr49iq0gmqn9r5n072zq-doxygen-1.16.1/bin/doxygen
✅ gcovr
gcovr 8.4
/nix/store/sml3xbbfhhlhk6h7jnlg19pdbx9b764b-python3.13-gcovr-8.4/bin/gcovr
✅ gh
gh version 2.94.0 (nixpkgs)
/nix/store/7hh2qi0gj2ifbxbl56cjzbiyfc379bji-gh-2.94.0/bin/gh
✅ git-cliff
git-cliff 2.13.1
/nix/store/bidn3pz53yd6qlg711917xx0q10hqmqv-git-cliff-2.13.1/bin/git-cliff
✅ git-lfs
git-lfs/3.7.1 (3.7.1; linux arm64; go 1.26.3)
/nix/store/4rsklvkbac5bayy0zv12kxyvspi4sshd-git-lfs-3.7.1/bin/git-lfs
✅ gpg
gpg (GnuPG) 2.4.9
/nix/store/ka4i8zz5ni3rzqnzcxbfvwr95fk8pn6q-gnupg-2.4.9/bin/gpg
✅ pre-commit
pre-commit 4.5.1
/nix/store/n981w6hjfar2l81kxbxs2wxl64vwa5kj-pre-commit-4.5.1/bin/pre-commit
✅ run-clang-tidy
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/4z2fyklg78klallr7x9j02kz92hnxp4m-run-clang-tidy/bin/run-clang-tidy
✅ run-clang-tidy-22
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
/nix/store/f8m0p9ad40brp9ahy4i0h27kqjkya1j9-run-clang-tidy-22/bin/run-clang-tidy-22
Rust toolchain:
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
[ ok ] cargo-audit cargo-audit-audit 0.22.1
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
[ ok ] cargo-nextest cargo-nextest 0.9.137
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
[ ok ] rust-analyzer rust-analyzer 1.95.0 (5980761 2026-04-14)
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
✅ cargo
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
/nix/store/yw1rs50s6qpsw0zyl7j3dpm18swbl0ag-cargo-1.95.0-aarch64-unknown-linux-gnu/bin/cargo
cargo-audit
cargo-audit-audit 0.22.1
/nix/store/9rxbrn9aa2r1z96186s69pc7vzizyfch-cargo-audit-0.22.1/bin/cargo-audit
✅ cargo-llvm-cov
cargo-llvm-cov 0.8.5
/nix/store/vwjsi159n89szrx4yh5pc3jlf2gp4fld-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
✅ cargo-nextest
cargo-nextest 0.9.137
/nix/store/qb6bcg2fjvm3r9s9j98nmffmf9xwh45s-cargo-nextest-0.9.137/bin/cargo-nextest
✅ clippy-driver
clippy 0.1.95 (59807616e1 2026-04-14)
/nix/store/nz4qv12pf16c092qr9hh4dsn0fzf47da-rust-minimal-1.95.0/bin/clippy-driver
✅ rust-analyzer
rust-analyzer 1.95.0 (5980761 2026-04-14)
/nix/store/m1rn67sqfz8s44idcxqallg680ifk71r-rust-analyzer-preview-1.95.0-aarch64-unknown-linux-gnu/bin/rust-analyzer
✅ rustc
rustc 1.95.0 (59807616e 2026-04-14)
/nix/store/nz4qv12pf16c092qr9hh4dsn0fzf47da-rust-minimal-1.95.0/bin/rustc
✅ rustfmt
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
/nix/store/jidfsprj2820glyzjn54ldn3j1fmz8c5-rustfmt-preview-1.95.0-aarch64-unknown-linux-gnu/bin/rustfmt
GCC toolchain:
[ ok ] gcc gcc (GCC) 15.2.0
[ ok ] g++ g++ (GCC) 15.2.0
[ ok ] gcov gcov (GCC) 15.2.0
✅ gcc
gcc (GCC) 15.2.0
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/gcc
✅ gcc-15
gcc (GCC) 15.2.0
/nix/store/h489d1rmjisfbxh5kmsb0a7c35j8qsdf-gcc-15/bin/gcc-15
✅ g++
g++ (GCC) 15.2.0
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/g++
✅ g++-15
g++ (GCC) 15.2.0
/nix/store/9ywmhz8bmzknrn3pn84g46z8hj3vrmw5-g++-15/bin/g++-15
✅ cpp
cpp (GCC) 15.2.0
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/cpp
✅ cpp-15
cpp (GCC) 15.2.0
/nix/store/vmjilh1b830qz9yh0a1jj5ads0jxizdk-cpp-15/bin/cpp-15
✅ gcov
gcov (GCC) 15.2.0
/nix/store/rmwf5hpi1y2m1wpnfvlxmrhksm4djk2j-gcc-15.2.0/bin/gcov
Mold:
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
✅ mold
mold 2.41.0 (compatible with GNU ld)
/nix/store/f5qh5a0bx1dslmnf5n5gx0s6aljbswq3-mold-unwrapped-wrapper-2.41.0/bin/mold
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
All 40 checked tools are present and runnable.
All 52 checked tools are present and runnable.

View File

@@ -30,10 +30,29 @@ let
};
customGccGcov = if pkgs.stdenv.isLinux then customCompilers.customGcov else plainGcov;
# Whole directory: init.sh locates the profiles relative to itself.
conanDir = ../conan;
# Own Conan home, so Nix-built packages never share a cache with a system
# Conan. The stamp holds a content-addressed store path, so init.sh re-runs
# only when something in conan/ changes.
conanHook = ''
export CONAN_HOME=~/.conan2-nix
_xrpl_conan_stamp="$CONAN_HOME/.xrpld-devshell"
if [ "$(cat "$_xrpl_conan_stamp" 2>/dev/null)" != "${conanDir}" ]; then
if ${conanDir}/init.sh; then
printf '%s' "${conanDir}" >"$_xrpl_conan_stamp"
else
echo " Conan setup failed - run ./conan/init.sh from the repository root to retry."
fi
fi
unset _xrpl_conan_stamp
'';
# Shown when entering a *-plain shell. These exist only on Linux (see below),
# where the stock toolchain diverges from CI.
plainWarningHook = ''
echo " WARNING: this is the stock nixpkgs toolchain and does not match CI's glibc. Prefer 'nix develop .#gcc' / '.#clang' unless you need to skip the custom-glibc build."
echo " WARNING: this is the stock nixpkgs toolchain and does not match CI's glibc. Prefer 'nix develop .#gcc' / '.#clang' unless you need to skip the custom-glibc build."
'';
# Tools to expose under version-suffixed names (see mkVersionedToolLinks).
@@ -87,6 +106,7 @@ let
shellHook = ''
echo "Welcome to xrpld development shell";
${compilerVersionHook}
${conanHook}
${warningHook}
'';
}

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