mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-27 09:10:56 +00:00
Compare commits
42 Commits
token-payc
...
ximinez/di
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e06a9ba8 | ||
|
|
b3141d91fa | ||
|
|
1b1cd4c260 | ||
|
|
a482d6aced | ||
|
|
299627298f | ||
|
|
640798696b | ||
|
|
47512afad5 | ||
|
|
ff3708a757 | ||
|
|
391a1e442c | ||
|
|
9e77212900 | ||
|
|
93f5a0e217 | ||
|
|
71367f361c | ||
|
|
931d21b2a7 | ||
|
|
c99feb82e7 | ||
|
|
7b53a5e0c5 | ||
|
|
4a02518497 | ||
|
|
0b6c3630cc | ||
|
|
4d04ba5be5 | ||
|
|
ed53557d41 | ||
|
|
e4d10393f3 | ||
|
|
fcc7f57e82 | ||
|
|
a25229f154 | ||
|
|
eb6eaf2532 | ||
|
|
ff987fc7c6 | ||
|
|
d21137c4c1 | ||
|
|
ac7db2e621 | ||
|
|
42005a8080 | ||
|
|
1f7b1b3a78 | ||
|
|
80b90544c5 | ||
|
|
00b9a8cd67 | ||
|
|
3be49f814a | ||
|
|
1674fabe81 | ||
|
|
6dfa47ce7a | ||
|
|
bef095be65 | ||
|
|
8e5d774c36 | ||
|
|
fb8fb30f6c | ||
|
|
a553001125 | ||
|
|
57782e84ee | ||
|
|
9d5076c8a9 | ||
|
|
1af379e09f | ||
|
|
1ced0875ae | ||
|
|
53e6d7580a |
@@ -75,8 +75,6 @@ Checks: "-*,
|
||||
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
|
||||
# ---
|
||||
|
||||
FormatStyle: file
|
||||
|
||||
CheckOptions:
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
|
||||
@@ -174,6 +174,7 @@ words:
|
||||
- MPTAMM
|
||||
- MPTDEX
|
||||
- Merkle
|
||||
- Metafuncton
|
||||
- misprediction
|
||||
- missingok
|
||||
- mptbalance
|
||||
|
||||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -15,7 +15,3 @@ updates:
|
||||
commit-message:
|
||||
prefix: "ci: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
@@ -130,9 +130,12 @@ test.ledger > xrpl.json
|
||||
test.ledger > xrpl.ledger
|
||||
test.ledger > xrpl.protocol
|
||||
test.nodestore > test.jtx
|
||||
test.nodestore > test.unit_test
|
||||
test.nodestore > xrpl.basics
|
||||
test.nodestore > xrpl.config
|
||||
test.nodestore > xrpld.core
|
||||
test.nodestore > xrpl.nodestore
|
||||
test.nodestore > xrpl.protocol
|
||||
test.nodestore > xrpl.rdb
|
||||
test.overlay > test.jtx
|
||||
test.overlay > test.unit_test
|
||||
|
||||
3
.github/scripts/rename/namespace.sh
vendored
3
.github/scripts/rename/namespace.sh
vendored
@@ -46,6 +46,9 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do
|
||||
done
|
||||
done
|
||||
|
||||
# Special case for NuDBFactory that has ripple twice in the test suite name.
|
||||
${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' src/test/nodestore/NuDBFactory_test.cpp
|
||||
|
||||
DIRECTORY=$1
|
||||
find "${DIRECTORY}" -type f -name "*.md" | while read -r FILE; do
|
||||
echo "Processing file: ${FILE}"
|
||||
|
||||
19
.github/scripts/strategy-matrix/linux.json
vendored
19
.github/scripts/strategy-matrix/linux.json
vendored
@@ -1,22 +1,13 @@
|
||||
{
|
||||
"image_tag": "sha-fecfc0c",
|
||||
"image_tag": "sha-3122de8",
|
||||
"configs": {
|
||||
"ubuntu": [
|
||||
{
|
||||
"compiler": ["gcc"],
|
||||
"build_type": ["Debug"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": true,
|
||||
"suffix": "coverage",
|
||||
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
|
||||
},
|
||||
{
|
||||
"compiler": ["clang"],
|
||||
"build_type": ["Release"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": true
|
||||
},
|
||||
|
||||
{
|
||||
"compiler": ["gcc"],
|
||||
"build_type": ["Release"],
|
||||
@@ -38,6 +29,14 @@
|
||||
"sanitizers": ["address", "undefinedbehavior"]
|
||||
},
|
||||
|
||||
{
|
||||
"compiler": ["gcc"],
|
||||
"build_type": ["Debug"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": true,
|
||||
"suffix": "coverage",
|
||||
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
|
||||
},
|
||||
{
|
||||
"compiler": ["clang"],
|
||||
"build_type": ["Debug"],
|
||||
|
||||
2
.github/workflows/build-nix-images.yml
vendored
2
.github/workflows/build-nix-images.yml
vendored
@@ -13,7 +13,6 @@ on:
|
||||
- "!nix/docker/README.md"
|
||||
- "!nix/devshell.nix"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "bin/install-sanitizer-libs.sh"
|
||||
pull_request:
|
||||
paths:
|
||||
@@ -25,7 +24,6 @@ on:
|
||||
- "!nix/docker/README.md"
|
||||
- "!nix/devshell.nix"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "bin/install-sanitizer-libs.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
2
.github/workflows/check-pr-description.yml
vendored
2
.github/workflows/check-pr-description.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Write PR body to file
|
||||
env:
|
||||
|
||||
114
.github/workflows/check-tools.yml
vendored
114
.github/workflows/check-tools.yml
vendored
@@ -1,114 +0,0 @@
|
||||
# Verifies the committed snapshots of `bin/check-tools.sh` output for each Nix
|
||||
# environment (see nix/check-tools/). If the environment changes — a new image
|
||||
# tag, an updated flake.lock, a different tool list — without the matching
|
||||
# snapshot being regenerated and committed, this workflow fails so the drift is
|
||||
# caught in review.
|
||||
#
|
||||
# To regenerate the snapshots, see nix/check-tools/README.md.
|
||||
name: Check tools
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/check-tools.yml"
|
||||
- ".github/scripts/strategy-matrix/linux.json"
|
||||
- "bin/check-tools.sh"
|
||||
- "nix/**"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "rust-toolchain.toml"
|
||||
push:
|
||||
branches:
|
||||
- "develop"
|
||||
paths:
|
||||
- ".github/workflows/check-tools.yml"
|
||||
- ".github/scripts/strategy-matrix/linux.json"
|
||||
- "bin/check-tools.sh"
|
||||
- "nix/**"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "rust-toolchain.toml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
# The nix-nixos image tag is pinned alongside the build matrix in linux.json,
|
||||
# so snapshots are checked against the exact image CI builds against.
|
||||
linux-image-tag:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Read nix image tag
|
||||
id: tag
|
||||
run: echo "tag=$(jq -r .image_tag .github/scripts/strategy-matrix/linux.json)" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
# One job for all environments; they differ only in whether the tools come
|
||||
# from the nix-nixos container (Linux) or `nix develop` (macOS).
|
||||
check-tools:
|
||||
needs: linux-image-tag
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-latest
|
||||
snapshot: nix/check-tools/nix-ubuntu-amd64.txt
|
||||
nix_develop: false
|
||||
- runner: ubuntu-24.04-arm
|
||||
snapshot: nix/check-tools/nix-ubuntu-arm64.txt
|
||||
nix_develop: false
|
||||
- runner: macos-26-apple-clang-21
|
||||
snapshot: nix/check-tools/macos.txt
|
||||
nix_develop: true
|
||||
runs-on: ${{ matrix.runner }}
|
||||
# Linux runs inside the pinned nix-nixos image; macOS runs natively and uses
|
||||
# the flake's dev shell instead (see the run step below).
|
||||
container: ${{ !matrix.nix_develop && format('ghcr.io/xrplf/xrpld/nix-ubuntu:{0}', needs.linux-image-tag.outputs.tag) || null }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
- name: Regenerate snapshot
|
||||
env:
|
||||
CHECK_TOOLS_SKIP_CLONE: "1"
|
||||
# check-tools.sh skips some macOS tools when CI is set; the snapshots
|
||||
# capture the full `nix develop` environment, so unset it here.
|
||||
CI: ""
|
||||
run: |
|
||||
if [ "${{ matrix.nix_develop }}" = "true" ]; then
|
||||
# `nix develop` prints the dev-shell greeting first; keep only the
|
||||
# check-tools.sh output (from the "Detected OS:" line onward).
|
||||
nix --extra-experimental-features "nix-command flakes" develop \
|
||||
-c bash bin/check-tools.sh | sed -n '/^Detected OS:/,$p' >"${{ matrix.snapshot }}"
|
||||
else
|
||||
bash bin/check-tools.sh >"${{ matrix.snapshot }}"
|
||||
fi
|
||||
|
||||
- name: Verify snapshot is up to date
|
||||
run: |
|
||||
if ! git diff --exit-code -- "${{ matrix.snapshot }}"; then
|
||||
echo "::error::${{ matrix.snapshot }} is out of date. Regenerate it (see nix/check-tools/README.md) and commit the result."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload regenerated snapshot
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: check-tools-${{ runner.os }}-${{ runner.arch }}
|
||||
path: ${{ matrix.snapshot }}
|
||||
3
.github/workflows/on-pr.yml
vendored
3
.github/workflows/on-pr.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Determine changed files
|
||||
# This step checks whether any files have changed that should
|
||||
# cause the next jobs to run. We do it this way rather than
|
||||
@@ -90,7 +90,6 @@ jobs:
|
||||
.clang-tidy
|
||||
.codecov.yml
|
||||
bin/check-tools.sh
|
||||
bin/default-loader-path.sh
|
||||
cfg/**
|
||||
cmake/**
|
||||
conan/**
|
||||
|
||||
1
.github/workflows/on-trigger.yml
vendored
1
.github/workflows/on-trigger.yml
vendored
@@ -28,7 +28,6 @@ on:
|
||||
- ".clang-tidy"
|
||||
- ".codecov.yml"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "cfg/**"
|
||||
- "cmake/**"
|
||||
- "conan/**"
|
||||
|
||||
6
.github/workflows/publish-docs.yml
vendored
6
.github/workflows/publish-docs.yml
vendored
@@ -41,13 +41,13 @@ env:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3122de8
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
|
||||
@@ -110,10 +110,10 @@ jobs:
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
|
||||
with:
|
||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
||||
|
||||
@@ -266,7 +266,7 @@ jobs:
|
||||
./xrpld --definitions | python3 -m json.tool >server_definitions.json
|
||||
|
||||
- name: Upload server definitions
|
||||
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
|
||||
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: server-definitions
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Check levelization
|
||||
run: python .github/scripts/levelization/generate.py
|
||||
- name: Check for differences
|
||||
|
||||
2
.github/workflows/reusable-check-rename.yml
vendored
2
.github/workflows/reusable-check-rename.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
- name: Check definitions
|
||||
run: .github/scripts/rename/definitions.sh .
|
||||
- name: Check copyright notices
|
||||
|
||||
8
.github/workflows/reusable-clang-tidy.yml
vendored
8
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -34,16 +34,16 @@ 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-3122de8"
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
TARGETS: ${{ needs.determine-files.outputs.need_full_run != 'true' && needs.determine-files.outputs.cpp_changed_files || 'include src tests' }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -format -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
|
||||
- name: Print filtered clang-tidy errors
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
|
||||
4
.github/workflows/reusable-package.yml
vendored
4
.github/workflows/reusable-package.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Download pre-built binary
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
||||
|
||||
4
.github/workflows/reusable-upload-recipe.yml
vendored
4
.github/workflows/reusable-upload-recipe.yml
vendored
@@ -40,14 +40,14 @@ defaults:
|
||||
jobs:
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3122de8
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
|
||||
CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Generate build version number
|
||||
id: version
|
||||
|
||||
4
.github/workflows/upload-conan-deps.yml
vendored
4
.github/workflows/upload-conan-deps.yml
vendored
@@ -65,10 +65,10 @@ jobs:
|
||||
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
|
||||
@@ -348,14 +348,12 @@ run-clang-tidy -p build -allow-no-checks src tests
|
||||
```
|
||||
|
||||
This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory.
|
||||
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix -format` to the above command:
|
||||
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
|
||||
|
||||
```
|
||||
run-clang-tidy -p build -quiet -fix -format -allow-no-checks src tests
|
||||
run-clang-tidy -p build -quiet -fix -allow-no-checks src tests
|
||||
```
|
||||
|
||||
`-format` reformats the fixed code with [`.clang-format`](./.clang-format); without it the fixes are inserted in LLVM style and the `clang-format` hook rewrites them afterwards.
|
||||
|
||||
## Contracts and instrumentation
|
||||
|
||||
We are using [Antithesis](https://antithesis.com/) for continuous fuzzing,
|
||||
|
||||
@@ -30,10 +30,8 @@ missing=()
|
||||
checked=0
|
||||
|
||||
# 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.
|
||||
# Runs the probe (default: "<name> --version") quietly. Records <name> as
|
||||
# missing if the command is not found or exits non-zero.
|
||||
check() {
|
||||
local name="$1"
|
||||
shift
|
||||
@@ -42,11 +40,10 @@ check() {
|
||||
probe=("${name}" --version)
|
||||
fi
|
||||
|
||||
echo "Checking ${name}..."
|
||||
checked=$((checked + 1))
|
||||
local output version
|
||||
if output="$("${probe[@]}" 2>&1)"; then
|
||||
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
|
||||
printf ' [ ok ] %-20s %s\n' "${name}" "${version}"
|
||||
if "${probe[@]}" | head -n 1; then
|
||||
printf ' [ ok ] %s\n' "${name}"
|
||||
else
|
||||
printf ' [MISS] %s\n' "${name}"
|
||||
missing+=("${name}")
|
||||
@@ -88,14 +85,12 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
|
||||
check file
|
||||
check less
|
||||
check make
|
||||
# net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no
|
||||
# version flag, so fall back to a presence marker there.
|
||||
check netstat sh -c 'command -v netstat >/dev/null && { netstat --version 2>&1 | grep -m1 -oE "net-tools [0-9.]+" || echo present; }'
|
||||
check netstat which netstat
|
||||
check ninja
|
||||
check perl perl -e 'print "$^V\n"'
|
||||
check perl
|
||||
check pkg-config
|
||||
check vim
|
||||
check zip bash -c 'zip --version 2>&1 | grep -m1 -oE "Zip [0-9.]+"'
|
||||
check zip
|
||||
|
||||
# These tools are present in our Linux CI images and in local development
|
||||
# setups, but not in the macOS CI environment. So check them everywhere
|
||||
|
||||
@@ -144,11 +144,7 @@ def main():
|
||||
+ files
|
||||
)
|
||||
canonicalize_fix_paths(Path(fixes_dir))
|
||||
# `FormatStyle` in .clang-tidy does not reach this path,
|
||||
# so ask for the repository style here.
|
||||
applied = subprocess.run(
|
||||
[clang_apply_replacements, "--format", "--style=file", fixes_dir]
|
||||
)
|
||||
applied = subprocess.run([clang_apply_replacements, fixes_dir])
|
||||
|
||||
return result.returncode or applied.returncode
|
||||
|
||||
|
||||
@@ -29,27 +29,6 @@ if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(is_xcode TRUE)
|
||||
endif()
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Nix toolchain detection
|
||||
# --------------------------------------------------------------------
|
||||
# True when the C++ compiler resolves into the Nix store. CMAKE_CXX_COMPILER may
|
||||
# be referenced through a symlink outside the store (a Nix profile, a /usr/bin
|
||||
# alternative, ...), so resolve the real path before matching.
|
||||
set(is_nix_compiler FALSE)
|
||||
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
|
||||
if(_cxx_real MATCHES "^/nix/store/")
|
||||
set(is_nix_compiler TRUE)
|
||||
endif()
|
||||
unset(_cxx_real)
|
||||
|
||||
# True inside the Nix CI Docker image, identified by the /nix/ci-env tree it
|
||||
# ships (see nix/docker/Dockerfile). The dev shell and bare systems don't have
|
||||
# it, so it distinguishes the CI image from other Nix-compiler environments.
|
||||
set(is_ci_image FALSE)
|
||||
if(EXISTS "/nix/ci-env/bin")
|
||||
set(is_ci_image TRUE)
|
||||
endif()
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Operating system detection
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
@@ -1,37 +1,26 @@
|
||||
#[===================================================================[
|
||||
Patch executables to run in non-Nix environments.
|
||||
|
||||
The Nix toolchain links binaries against an ELF interpreter (loader)
|
||||
that lives in the Nix store, so the resulting binaries don't run elsewhere.
|
||||
`patch_nix_binary` adds a POST_BUILD step that resets the interpreter
|
||||
to the system default loader and drops the rpath.
|
||||
The Nix-based CI image links binaries against an ELF interpreter (loader)
|
||||
that lives in the Nix store, so the resulting binaries don't run elsewhere
|
||||
(including once installed from the .deb package). `patch_nix_binary` adds a
|
||||
POST_BUILD step that resets the interpreter to the system default loader and
|
||||
drops the rpath.
|
||||
|
||||
This runs by default for Nix-toolchain builds (determined by whether the compiler resolves under /nix/store/).
|
||||
Those builds are where binaries get a Nix-store loader.
|
||||
It is opted out of by setting the XRPLD_NO_PATCH_NIX_BINARY environment variable —
|
||||
the plain Nix dev shells set it, since their binaries link a newer glibc
|
||||
and must not be retargeted to the system loader.
|
||||
|
||||
Non-Nix builds (a system compiler, already using the system loader) and sanitizer builds
|
||||
(runtime libraries resolved through the rpath) are skipped too.
|
||||
Everywhere else `patch_nix_binary` is a no-op.
|
||||
|
||||
The default loader is resolved by bin/default-loader-path.sh.
|
||||
This is only active inside the Nix-based image, detected by the presence of
|
||||
/tmp/loader-path.sh (shipped by that image, resolves the default loader). It
|
||||
is skipped for sanitizer builds, whose runtime libraries are resolved through
|
||||
the rpath. Everywhere else `patch_nix_binary` is a no-op.
|
||||
#]===================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
|
||||
include(CompilationEnv)
|
||||
|
||||
# Resolves the system default ELF loader path for the current architecture.
|
||||
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
|
||||
# Provided by the Nix-based CI image; prints the system default ELF loader path.
|
||||
set(_loader_path_script "/tmp/loader-path.sh")
|
||||
|
||||
if(
|
||||
is_linux
|
||||
AND NOT SANITIZERS_ENABLED
|
||||
AND is_nix_compiler
|
||||
AND NOT DEFINED ENV{XRPLD_NO_PATCH_NIX_BINARY}
|
||||
)
|
||||
if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}")
|
||||
execute_process(
|
||||
COMMAND "${_loader_path_script}"
|
||||
OUTPUT_VARIABLE DEFAULT_LOADER_PATH
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
include_guard()
|
||||
|
||||
include(isolate_headers)
|
||||
|
||||
# Define a benchmark executable for the module `name`.
|
||||
|
||||
@@ -171,8 +171,9 @@ else()
|
||||
# Clang wrapper supplies those paths itself (via -nostdinc++), so at compile time the
|
||||
# flag is unused -> Clang errors under our -Werror. At link time the flag IS consumed
|
||||
# (it selects the C++ runtime), so we move it there instead of dropping it entirely.
|
||||
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
|
||||
if(
|
||||
is_nix_compiler
|
||||
_cxx_real MATCHES "^/nix/store/"
|
||||
AND is_linux
|
||||
AND is_clang
|
||||
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"
|
||||
|
||||
@@ -36,19 +36,6 @@ elseif(is_gcc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# A Nix compiler is only meant to be used from a managed environment: the xrpld
|
||||
# dev shell (which exports XRPL_DEVSHELL) or the CI image. Using one from a bare
|
||||
# shell usually means a leaked toolchain (picked up via PATH or a Conan profile)
|
||||
# and leads to confusing breakage, so fail early with guidance.
|
||||
if(is_nix_compiler AND NOT is_ci_image AND NOT DEFINED ENV{XRPL_DEVSHELL})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"A Nix compiler (${CMAKE_CXX_COMPILER}) is being used outside the xrpld "
|
||||
"dev shell. Enter it with `nix develop` (see docs/build/nix.md) before "
|
||||
"configuring the build."
|
||||
)
|
||||
endif()
|
||||
|
||||
# check for in-source build and fail
|
||||
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
message(
|
||||
|
||||
8
docs/build/nix.md
vendored
8
docs/build/nix.md
vendored
@@ -154,14 +154,6 @@ conan install .. --output-folder . --build '*' --settings build_type=Release
|
||||
|
||||
To update `flake.lock` to the latest revision use `nix flake update` command.
|
||||
|
||||
## Tooling snapshots
|
||||
|
||||
The tool versions in each Nix environment are recorded in
|
||||
[`nix/check-tools/`](../../nix/check-tools) and verified by CI. If you change the
|
||||
environment (bump the CI image tag, update `flake.lock`, or edit the tool list in
|
||||
`bin/check-tools.sh`), CI fails until you regenerate and commit the affected
|
||||
snapshot — see [`nix/check-tools/README.md`](../../nix/check-tools/README.md).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [Troubleshooting Nix problems](./nix_troubleshooting.md) for common issues,
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
@@ -252,11 +251,4 @@ makeSlice(std::basic_string<char, Traits, Alloc> const& s)
|
||||
return Slice(s.data(), s.size());
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
Slice
|
||||
makeSlice(std::basic_string_view<char, Traits> s)
|
||||
{
|
||||
return Slice(s.data(), s.size());
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -58,7 +58,7 @@ struct LexicalCast<Out, std::string_view>
|
||||
"beast::LexicalCast can only be used with integral types");
|
||||
|
||||
template <class Integral = Out>
|
||||
constexpr bool
|
||||
bool
|
||||
operator()(Integral& out, std::string_view in) const
|
||||
requires(std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>)
|
||||
{
|
||||
@@ -110,7 +110,7 @@ struct LexicalCast<Out, boost::core::basic_string_view<char>>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
constexpr bool
|
||||
bool
|
||||
operator()(Out& out, boost::core::basic_string_view<char> in) const
|
||||
{
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
@@ -123,7 +123,7 @@ struct LexicalCast<Out, std::string>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
constexpr bool
|
||||
bool
|
||||
operator()(Out& out, std::string in) const
|
||||
{
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
@@ -136,7 +136,7 @@ struct LexicalCast<Out, char const*>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
constexpr bool
|
||||
bool
|
||||
operator()(Out& out, char const* in) const
|
||||
{
|
||||
XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input");
|
||||
@@ -151,7 +151,7 @@ struct LexicalCast<Out, char*>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
constexpr bool
|
||||
bool
|
||||
operator()(Out& out, char* in) const
|
||||
{
|
||||
XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
|
||||
@@ -177,7 +177,7 @@ struct BadLexicalCast : public std::bad_cast
|
||||
* @return `false` if there was a parsing or range error
|
||||
*/
|
||||
template <class Out, class In>
|
||||
constexpr bool
|
||||
bool
|
||||
lexicalCastChecked(Out& out, In in)
|
||||
{
|
||||
return detail::LexicalCast<Out, In>()(out, in);
|
||||
@@ -191,7 +191,7 @@ lexicalCastChecked(Out& out, In in)
|
||||
* @return The new type.
|
||||
*/
|
||||
template <class Out, class In>
|
||||
constexpr Out
|
||||
Out
|
||||
lexicalCastThrow(In in)
|
||||
{
|
||||
if (Out out; lexicalCastChecked(out, in))
|
||||
@@ -207,7 +207,7 @@ lexicalCastThrow(In in)
|
||||
* @return The new type.
|
||||
*/
|
||||
template <class Out, class In>
|
||||
constexpr Out
|
||||
Out
|
||||
lexicalCast(In in, Out defaultValue = Out())
|
||||
{
|
||||
if (Out out; lexicalCastChecked(out, in))
|
||||
|
||||
@@ -17,14 +17,14 @@ namespace beast {
|
||||
class SemanticVersion
|
||||
{
|
||||
public:
|
||||
using IdentifierList = std::vector<std::string>;
|
||||
using identifier_list = std::vector<std::string>;
|
||||
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
int patchVersion;
|
||||
|
||||
IdentifierList preReleaseIdentifiers;
|
||||
IdentifierList metaData;
|
||||
identifier_list preReleaseIdentifiers;
|
||||
identifier_list metaData;
|
||||
|
||||
SemanticVersion();
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
namespace xrpl {
|
||||
|
||||
// Forward declarations
|
||||
namespace node_store {
|
||||
namespace NodeStore {
|
||||
class Database;
|
||||
} // namespace node_store
|
||||
} // namespace NodeStore
|
||||
namespace Resource {
|
||||
class Manager;
|
||||
} // namespace Resource
|
||||
@@ -164,7 +164,7 @@ public:
|
||||
getResourceManager() = 0;
|
||||
|
||||
// Storage services
|
||||
virtual node_store::Database&
|
||||
virtual NodeStore::Database&
|
||||
getNodeStore() = 0;
|
||||
|
||||
virtual SHAMapStore&
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
@@ -27,291 +25,6 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* Validate that @p account may lock @p amount of a token for later delivery
|
||||
* to @p dest.
|
||||
*
|
||||
* The lock-side counterpart of escrowUnlockPreclaimHelper: every issuer
|
||||
* control (locking opt-in, authorization, freeze/lock, transferability,
|
||||
* spendable balance) that gates locking token value lives here, so any
|
||||
* transactor that locks funds applies the same rules. The signature is
|
||||
* view-based rather than PreclaimContext-based so it can also run from
|
||||
* doApply.
|
||||
*/
|
||||
template <ValidIssueType T>
|
||||
TER
|
||||
escrowLockPreclaimHelper(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
AccountID const& dest,
|
||||
STAmount const& amount,
|
||||
beast::Journal j);
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowLockPreclaimHelper<Issue>(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
AccountID const& dest,
|
||||
STAmount const& amount,
|
||||
beast::Journal j)
|
||||
{
|
||||
auto const& issue = amount.get<Issue>();
|
||||
auto const& issuer = amount.getIssuer();
|
||||
// If the issuer is the same as the account, return tecNO_PERMISSION
|
||||
if (issuer == account)
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION
|
||||
auto const sleIssuer = view.read(keylet::account(issuer));
|
||||
if (!sleIssuer)
|
||||
return tecNO_ISSUER;
|
||||
if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// If the account does not have a trustline to the issuer, return tecNO_LINE
|
||||
auto const sleRippleState = view.read(keylet::trustLine(account, issuer, issue.currency));
|
||||
if (!sleRippleState)
|
||||
return tecNO_LINE;
|
||||
|
||||
STAmount const balance = (*sleRippleState)[sfBalance];
|
||||
|
||||
// If balance is positive, issuer must have higher address than account
|
||||
if (balance > beast::kZero && issuer < account)
|
||||
return tecNO_PERMISSION; // LCOV_EXCL_LINE
|
||||
|
||||
// If balance is negative, issuer must have lower address than account
|
||||
if (balance < beast::kZero && issuer > account)
|
||||
return tecNO_PERMISSION; // LCOV_EXCL_LINE
|
||||
|
||||
// If the issuer has requireAuth set, check if the account is authorized
|
||||
if (auto const ter = requireAuth(view, issue, account); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has requireAuth set, check if the destination is authorized
|
||||
if (auto const ter = requireAuth(view, issue, dest); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has frozen the account, return tecFROZEN
|
||||
if (isFrozen(view, account, issue))
|
||||
return tecFROZEN;
|
||||
|
||||
// If the issuer has frozen the destination, return tecFROZEN
|
||||
if (isFrozen(view, dest, issue))
|
||||
return tecFROZEN;
|
||||
|
||||
STAmount const spendableAmount =
|
||||
accountHolds(view, account, issue.currency, issuer, FreezeHandling::IgnoreFreeze, j);
|
||||
|
||||
// If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
|
||||
if (spendableAmount <= beast::kZero)
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
|
||||
// If the spendable amount is less than the amount, return
|
||||
// tecINSUFFICIENT_FUNDS
|
||||
if (spendableAmount < amount)
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
|
||||
// If the amount is not addable to the balance, return tecPRECISION_LOSS
|
||||
if (!canAdd(spendableAmount, amount))
|
||||
return tecPRECISION_LOSS;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowLockPreclaimHelper<MPTIssue>(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
AccountID const& dest,
|
||||
STAmount const& amount,
|
||||
beast::Journal j)
|
||||
{
|
||||
AccountID const issuer = amount.getIssuer();
|
||||
// If the issuer is the same as the account, return tecNO_PERMISSION
|
||||
if (issuer == account)
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// If the mpt does not exist, return tecOBJECT_NOT_FOUND
|
||||
auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
|
||||
auto const sleIssuance = view.read(issuanceKey);
|
||||
if (!sleIssuance)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
|
||||
// If the lsfMPTCanEscrow is not enabled, return tecNO_PERMISSION
|
||||
if (!sleIssuance->isFlag(lsfMPTCanEscrow))
|
||||
return tecNO_PERMISSION;
|
||||
|
||||
// If the issuer is not the same as the issuer of the mpt, return
|
||||
// tecNO_PERMISSION
|
||||
if (sleIssuance->getAccountID(sfIssuer) != issuer)
|
||||
return tecNO_PERMISSION; // LCOV_EXCL_LINE
|
||||
|
||||
// If the account does not have the mpt, return tecOBJECT_NOT_FOUND
|
||||
if (!view.exists(keylet::mptoken(issuanceKey.key, account)))
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
|
||||
// If the issuer has requireAuth set, check if the account is
|
||||
// authorized
|
||||
auto const& mptIssue = amount.get<MPTIssue>();
|
||||
if (auto const ter = requireAuth(view, mptIssue, account, AuthType::WeakAuth);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has requireAuth set, check if the destination is
|
||||
// authorized
|
||||
if (auto const ter = requireAuth(view, mptIssue, dest, AuthType::WeakAuth); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has frozen the account, return tecLOCKED
|
||||
if (isFrozen(view, account, mptIssue))
|
||||
return tecLOCKED;
|
||||
|
||||
// If the issuer has frozen the destination, return tecLOCKED
|
||||
if (isFrozen(view, dest, mptIssue))
|
||||
return tecLOCKED;
|
||||
|
||||
// If the mpt cannot be transferred, return tecNO_AUTH
|
||||
if (auto const ter = canTransfer(view, mptIssue, account, dest); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
STAmount const spendableAmount = accountHolds(
|
||||
view,
|
||||
account,
|
||||
amount.get<MPTIssue>(),
|
||||
FreezeHandling::IgnoreFreeze,
|
||||
AuthHandling::IgnoreAuth,
|
||||
j);
|
||||
|
||||
// If the balance is less than or equal to 0, return tecINSUFFICIENT_FUNDS
|
||||
if (spendableAmount <= beast::kZero)
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
|
||||
// If the spendable amount is less than the amount, return
|
||||
// tecINSUFFICIENT_FUNDS
|
||||
if (spendableAmount < amount)
|
||||
return tecINSUFFICIENT_FUNDS;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <ValidIssueType T>
|
||||
TER
|
||||
escrowLockApplyHelper(
|
||||
ApplyView& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& sender,
|
||||
STAmount const& amount,
|
||||
beast::Journal journal);
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowLockApplyHelper<Issue>(
|
||||
ApplyView& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& sender,
|
||||
STAmount const& amount,
|
||||
beast::Journal journal)
|
||||
{
|
||||
// Defensive: Issuer cannot create an escrow
|
||||
if (issuer == sender)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const ter =
|
||||
directSendNoFee(view, sender, issuer, amount, !amount.holds<MPTIssue>(), journal);
|
||||
if (!isTesSuccess(ter))
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowLockApplyHelper<MPTIssue>(
|
||||
ApplyView& view,
|
||||
AccountID const& issuer,
|
||||
AccountID const& sender,
|
||||
STAmount const& amount,
|
||||
beast::Journal journal)
|
||||
{
|
||||
// Defensive: Issuer cannot create an escrow
|
||||
if (issuer == sender)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const ter = lockEscrowMPT(view, sender, amount, journal);
|
||||
if (!isTesSuccess(ter))
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <ValidIssueType T>
|
||||
TER
|
||||
escrowUnlockPreclaimHelper(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
STAmount const& amount,
|
||||
bool checkFreeze = true);
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowUnlockPreclaimHelper<Issue>(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
STAmount const& amount,
|
||||
bool checkFreeze)
|
||||
{
|
||||
AccountID const& issuer = amount.getIssuer();
|
||||
// If the issuer is the same as the account, return tesSUCCESS
|
||||
if (issuer == account)
|
||||
return tesSUCCESS;
|
||||
|
||||
// If the issuer has requireAuth set, check if the destination is authorized
|
||||
if (auto const ter = requireAuth(view, amount.get<Issue>(), account); !isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has deep frozen the destination, return tecFROZEN
|
||||
if (checkFreeze &&
|
||||
isDeepFrozen(view, account, amount.get<Issue>().currency, amount.getIssuer()))
|
||||
return tecFROZEN;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline TER
|
||||
escrowUnlockPreclaimHelper<MPTIssue>(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
STAmount const& amount,
|
||||
bool checkFreeze)
|
||||
{
|
||||
AccountID const& issuer = amount.getIssuer();
|
||||
// If the issuer is the same as the account, return tesSUCCESS
|
||||
if (issuer == account)
|
||||
return tesSUCCESS;
|
||||
|
||||
// If the mpt does not exist, return tecOBJECT_NOT_FOUND
|
||||
auto const issuanceKey = keylet::mptokenIssuance(amount.get<MPTIssue>().getMptID());
|
||||
auto const sleIssuance = view.read(issuanceKey);
|
||||
if (!sleIssuance)
|
||||
return tecOBJECT_NOT_FOUND;
|
||||
|
||||
// If the issuer has requireAuth set, check if the account is
|
||||
// authorized
|
||||
auto const& mptIssue = amount.get<MPTIssue>();
|
||||
if (auto const ter = requireAuth(view, mptIssue, account, AuthType::WeakAuth);
|
||||
!isTesSuccess(ter))
|
||||
return ter;
|
||||
|
||||
// If the issuer has frozen the account, return tecLOCKED
|
||||
if (checkFreeze && isFrozen(view, account, mptIssue))
|
||||
return tecLOCKED;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <ValidIssueType T>
|
||||
TER
|
||||
escrowUnlockApplyHelper(
|
||||
@@ -340,6 +53,9 @@ escrowUnlockApplyHelper<Issue>(
|
||||
bool createAsset,
|
||||
beast::Journal journal)
|
||||
{
|
||||
auto const& issue = amount.get<Issue>();
|
||||
Keylet const trustLineKey = keylet::trustLine(receiver, issue);
|
||||
bool const recvLow = issuer > receiver;
|
||||
bool const senderIssuer = issuer == sender;
|
||||
bool const receiverIssuer = issuer == receiver;
|
||||
|
||||
@@ -349,10 +65,6 @@ escrowUnlockApplyHelper<Issue>(
|
||||
if (receiverIssuer)
|
||||
return tesSUCCESS;
|
||||
|
||||
auto const& issue = amount.get<Issue>();
|
||||
Keylet const trustLineKey = keylet::trustLine(receiver, issue);
|
||||
bool const recvLow = issuer > receiver;
|
||||
|
||||
if (!ctx.view.exists(trustLineKey) && createAsset)
|
||||
{
|
||||
// Can the account cover the trust line's reserve?
|
||||
|
||||
@@ -286,77 +286,6 @@ computeFullPaymentInterest(
|
||||
std::uint32_t startDate,
|
||||
TenthBips32 closeInterestRate);
|
||||
|
||||
// Deltas applied to Vault.AssetsTotal and LoanBroker.DebtTotal at a single
|
||||
// accounting touch point (origination, payment, impair/unimpair/default).
|
||||
struct AccountingDeltas
|
||||
{
|
||||
Number assetsTotalDelta;
|
||||
Number debtTotalDelta;
|
||||
};
|
||||
|
||||
// Whole-life (pre-LendingProtocolV1_1) recognition model: interest is
|
||||
// recognized into AssetsTotal/DebtTotal up front, at origination.
|
||||
namespace Accrual {
|
||||
|
||||
// LoanSet origination: what's added to Vault.AssetsTotal and LoanBroker.DebtTotal
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(Number const& principalRequested, Number const& interestDue);
|
||||
|
||||
// LoanSet origination: would recognizing this loan's interest push
|
||||
// Vault.AssetsTotal past Vault.AssetsMaximum?
|
||||
bool
|
||||
loanOriginationExceedsVaultMaximum(
|
||||
Number const& vaultMaximum,
|
||||
Number const& vaultTotal,
|
||||
Number const& interestDue);
|
||||
|
||||
// LoanManage impair/unimpair/default: the vault's exposure to this loan
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref loanSle);
|
||||
|
||||
// LoanPay: what's added to Vault.AssetsTotal and subtracted from LoanBroker.DebtTotal for a payment
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(LoanPaymentParts const& parts);
|
||||
|
||||
} // namespace Accrual
|
||||
|
||||
// Cash-basis (LendingProtocolV1_1) recognition model: AssetsTotal/DebtTotal
|
||||
// are principal-only, interest is recognized only as it's actually paid.
|
||||
namespace CashBasis {
|
||||
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(Number const& principalRequested);
|
||||
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref loanSle);
|
||||
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(LoanPaymentParts const& parts);
|
||||
|
||||
} // namespace CashBasis
|
||||
|
||||
// Public dispatchers: pick CashBasis:: if featureLendingProtocolV1_1 is
|
||||
// enabled AND the Vault's LEVersion (VaultHelpers::getVaultVersion) is
|
||||
// VaultVersion::CashBasis, else Accrual::. These are the only entry points
|
||||
// transactors call.
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(
|
||||
SLE::const_ref vaultSle,
|
||||
Number const& principalRequested,
|
||||
Number const& interestDue);
|
||||
|
||||
bool
|
||||
loanOriginationExceedsVaultMaximum(
|
||||
SLE::const_ref vaultSle,
|
||||
Number const& vaultTotal,
|
||||
Number const& interestDue);
|
||||
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref vaultSle, SLE::const_ref loanSle);
|
||||
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(SLE::const_ref vaultSle, LoanPaymentParts const& parts);
|
||||
|
||||
namespace detail {
|
||||
// These classes and functions should only be accessed by LendingHelper
|
||||
// functions and unit tests
|
||||
|
||||
@@ -2,85 +2,28 @@
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Concepts.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* Validate the token amount of a PaymentChannelCreate or PaymentChannelFund
|
||||
* transaction during preflight.
|
||||
*
|
||||
* @param rules The current ledger rules used to check amendment status.
|
||||
* @param amount The channel or funding amount from the transaction.
|
||||
* @return tesSUCCESS if the amount is valid; temBAD_AMOUNT, temBAD_CURRENCY,
|
||||
* or temDISABLED otherwise.
|
||||
*/
|
||||
template <ValidIssueType T>
|
||||
NotTEC
|
||||
payChanAmountPreflightHelper(Rules const& rules, STAmount const& amount);
|
||||
|
||||
template <>
|
||||
inline NotTEC
|
||||
payChanAmountPreflightHelper<Issue>(Rules const&, STAmount const& amount)
|
||||
{
|
||||
if (amount.native() || amount <= beast::kZero)
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
if (badCurrency() == amount.get<Issue>().currency)
|
||||
return temBAD_CURRENCY;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline NotTEC
|
||||
payChanAmountPreflightHelper<MPTIssue>(Rules const& rules, STAmount const& amount)
|
||||
{
|
||||
if (!rules.enabled(fixCleanup3_2_0) && !rules.enabled(featureMPTokensV1))
|
||||
return temDISABLED;
|
||||
|
||||
if (amount.native() || amount.mpt() > MPTAmount{kMaxMpTokenAmount} || amount <= beast::kZero)
|
||||
return temBAD_AMOUNT;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a payment channel and return its remaining funds to the channel owner.
|
||||
*
|
||||
* @param slep The SLE for the PayChannel object to close.
|
||||
* @param ctx The apply view context (view and transaction) in which ledger
|
||||
* state modifications are made.
|
||||
* @param key The ledger key identifying the PayChannel entry.
|
||||
* @param txAccount The account submitting the transaction that closes the
|
||||
* channel.
|
||||
* @param j Journal used for fatal-level diagnostic messages.
|
||||
* @return tesSUCCESS on success; tefBAD_LEDGER if a directory removal
|
||||
* fails; tefINTERNAL if the source account SLE cannot be found.
|
||||
* @param slep The SLE for the PayChannel object to close.
|
||||
* @param view The apply view in which ledger state modifications are made.
|
||||
* @param key The ledger key identifying the PayChannel entry.
|
||||
* @param j Journal used for fatal-level diagnostic messages.
|
||||
* @return tesSUCCESS on success; tefBAD_LEDGER if a directory removal
|
||||
* fails; tefINTERNAL if the source account SLE cannot be found.
|
||||
*/
|
||||
TER
|
||||
closeChannel(
|
||||
SLE::ref slep,
|
||||
ApplyViewContext ctx,
|
||||
uint256 const& key,
|
||||
AccountID const& txAccount,
|
||||
beast::Journal j);
|
||||
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j);
|
||||
|
||||
/**
|
||||
* Add two uint32_t values with saturation at UINT32_MAX.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
@@ -108,19 +107,4 @@ sharesToAssetsWithdraw(
|
||||
[[nodiscard]] bool
|
||||
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance);
|
||||
|
||||
/**
|
||||
* Resolves a Vault's LEVersion, the single point every accounting touch
|
||||
* point should call to determine which recognition model (accrual vs.
|
||||
* cash-basis) a Vault uses. Vaults created before featureLendingProtocolV1_1
|
||||
* activated never have sfLEVersion set, which resolves here to
|
||||
* VaultVersion::Legacy.
|
||||
*
|
||||
* @param vault The vault SLE.
|
||||
*
|
||||
* @return The Vault's LEVersion, or VaultVersion::Legacy if the field is
|
||||
* absent.
|
||||
*/
|
||||
[[nodiscard]] VaultVersion
|
||||
getVaultVersion(SLE::const_ref vault);
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* A backend used for the NodeStore.
|
||||
@@ -163,4 +163,4 @@ public:
|
||||
fdRequired() const = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace xrpl {
|
||||
class Section;
|
||||
} // namespace xrpl
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Persistency layer for NodeObject
|
||||
@@ -248,7 +248,7 @@ protected:
|
||||
void
|
||||
storeStats(std::uint64_t count, std::uint64_t sz)
|
||||
{
|
||||
XRPL_ASSERT(count <= sz, "xrpl::node_store::Database::storeStats : valid inputs");
|
||||
XRPL_ASSERT(count <= sz, "xrpl::NodeStore::Database::storeStats : valid inputs");
|
||||
storeCount_ += count;
|
||||
storeSz_ += sz;
|
||||
}
|
||||
@@ -308,4 +308,4 @@ private:
|
||||
threadEntry();
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/* This class has two key-value store Backend objects for persisting SHAMap
|
||||
* records. This facilitates online deletion of data. New backends are
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
*/
|
||||
virtual void
|
||||
rotate(
|
||||
std::unique_ptr<node_store::Backend>&& newBackend,
|
||||
std::unique_ptr<NodeStore::Backend>&& newBackend,
|
||||
std::function<void(std::string const& writableName, std::string const& archiveName)> const&
|
||||
f) = 0;
|
||||
|
||||
@@ -56,4 +56,4 @@ public:
|
||||
setRotationInFlight(bool inFlight) = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Task.h>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Simple NodeStore Scheduler that just performs the tasks synchronously.
|
||||
@@ -21,4 +21,4 @@ public:
|
||||
onBatchWrite(BatchWriteReport const& report) override;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace xrpl {
|
||||
class Section;
|
||||
} // namespace xrpl
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Base class for backend factories.
|
||||
@@ -70,4 +70,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Singleton for managing NodeStore factories and back ends.
|
||||
@@ -98,4 +98,4 @@ public:
|
||||
beast::Journal journal) = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
// VFALCO NOTE Intentionally not in the node_store namespace
|
||||
// VFALCO NOTE Intentionally not in the NodeStore namespace
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
enum class FetchType { Synchronous, Async };
|
||||
|
||||
@@ -71,4 +71,4 @@ public:
|
||||
onBatchWrite(BatchWriteReport const& report) = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Derived classes perform scheduled tasks.
|
||||
@@ -17,4 +17,4 @@ struct Task
|
||||
performScheduledTask() = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
// This is only used to pre-allocate the array for
|
||||
// batch objects and does not affect the amount written.
|
||||
@@ -36,4 +36,4 @@ enum class Status {
|
||||
*/
|
||||
using Batch = std::vector<std::shared_ptr<NodeObject>>;
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Batch-writing assist logic.
|
||||
@@ -86,4 +86,4 @@ private:
|
||||
Batch writeSet_;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
class DatabaseNodeImp : public Database
|
||||
{
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
XRPL_ASSERT(
|
||||
backend_,
|
||||
"xrpl::node_store::DatabaseNodeImp::DatabaseNodeImp : non-null "
|
||||
"xrpl::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null "
|
||||
"backend");
|
||||
}
|
||||
|
||||
@@ -138,4 +138,4 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
class DatabaseRotatingImp : public DatabaseRotating
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
void
|
||||
rotate(
|
||||
std::unique_ptr<node_store::Backend>&& newBackend,
|
||||
std::unique_ptr<NodeStore::Backend>&& newBackend,
|
||||
std::function<void(std::string const& writableName, std::string const& archiveName)> const&
|
||||
f) override;
|
||||
|
||||
@@ -94,4 +94,4 @@ private:
|
||||
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Parsed key/value blob into NodeObject components.
|
||||
@@ -49,4 +49,4 @@ private:
|
||||
int dataBytes_;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
/**
|
||||
* Convert a NodeObject from in-memory to database format.
|
||||
@@ -68,7 +68,7 @@ class EncodedBlob
|
||||
public:
|
||||
explicit EncodedBlob(std::shared_ptr<NodeObject> const& obj)
|
||||
: size_([&obj]() {
|
||||
XRPL_ASSERT(obj, "xrpl::node_store::EncodedBlob::EncodedBlob : non-null input");
|
||||
XRPL_ASSERT(obj, "xrpl::NodeStore::EncodedBlob::EncodedBlob : non-null input");
|
||||
|
||||
if (!obj)
|
||||
throw std::runtime_error("EncodedBlob: unseated std::shared_ptr used.");
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
XRPL_ASSERT(
|
||||
((ptr_ == payload_.data()) && (size_ <= payload_.size())) ||
|
||||
((ptr_ != payload_.data()) && (size_ > payload_.size())),
|
||||
"xrpl::node_store::EncodedBlob::~EncodedBlob : valid payload "
|
||||
"xrpl::NodeStore::EncodedBlob::~EncodedBlob : valid payload "
|
||||
"pointer");
|
||||
|
||||
if (ptr_ != payload_.data())
|
||||
@@ -114,4 +114,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
class ManagerImp : public Manager
|
||||
{
|
||||
@@ -57,4 +57,4 @@ public:
|
||||
beast::Journal journal) override;
|
||||
};
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/nodestore/NodeObject.h>
|
||||
#include <xrpl/nodestore/detail/Varint.h>
|
||||
#include <xrpl/nodestore/detail/varint.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
|
||||
#include <nudb/detail/field.hpp>
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
template <class BufferFactory>
|
||||
std::pair<void const*, std::size_t>
|
||||
@@ -59,7 +59,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
using std::runtime_error;
|
||||
using namespace nudb::detail;
|
||||
std::pair<void const*, std::size_t> result;
|
||||
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
auto const n = writeVarint(vi.data(), inSize);
|
||||
auto const outMax = LZ4_compressBound(inSize);
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
|
||||
@@ -240,7 +240,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
|
||||
result.first = out;
|
||||
ostream os(out, result.second);
|
||||
write<Varint>(os, type);
|
||||
write<varint>(os, type);
|
||||
write<std::uint16_t>(os, mask);
|
||||
write(os, vh.data(), n * 32);
|
||||
return result;
|
||||
@@ -252,13 +252,13 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
|
||||
result.first = out;
|
||||
ostream os(out, result.second);
|
||||
write<Varint>(os, type);
|
||||
write<varint>(os, type);
|
||||
write(os, vh.data(), n * 32);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
|
||||
static constexpr std::size_t kCodecType = 1;
|
||||
auto const vn = writeVarint(vi.data(), kCodecType);
|
||||
@@ -269,7 +269,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
case 1: // lz4
|
||||
{
|
||||
std::uint8_t* p = nullptr;
|
||||
auto const lzr = node_store::lz4Compress(in, inSize, [&p, &vn, &bf](std::size_t n) {
|
||||
auto const lzr = NodeStore::lz4Compress(in, inSize, [&p, &vn, &bf](std::size_t n) {
|
||||
p = reinterpret_cast<std::uint8_t*>(bf(vn + n));
|
||||
return p + vn;
|
||||
});
|
||||
@@ -316,4 +316,4 @@ filterInner(void* in, std::size_t inSize)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -6,25 +6,25 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
// This is a variant of the base128 varint format from
|
||||
// google protocol buffers:
|
||||
// https://developers.google.com/protocol-buffers/docs/encoding#varints
|
||||
|
||||
// field tag
|
||||
struct Varint;
|
||||
struct varint;
|
||||
|
||||
// Metafunction to return largest
|
||||
// Metafuncton to return largest
|
||||
// possible size of T represented as varint.
|
||||
// T must be unsigned
|
||||
template <class T, bool = std::is_unsigned_v<T>>
|
||||
struct VarintTraits;
|
||||
struct varint_traits;
|
||||
|
||||
template <class T>
|
||||
struct VarintTraits<T, true>
|
||||
struct varint_traits<T, true>
|
||||
{
|
||||
explicit VarintTraits() = default;
|
||||
explicit varint_traits() = default;
|
||||
|
||||
static constexpr std::size_t kMax = ((8 * sizeof(T)) + 6) / 7;
|
||||
};
|
||||
@@ -104,7 +104,7 @@ writeVarint(void* p0, std::size_t v)
|
||||
template <class T>
|
||||
void
|
||||
read(nudb::detail::istream& is, std::size_t& u)
|
||||
requires(std::is_same_v<T, Varint>)
|
||||
requires(std::is_same_v<T, varint>)
|
||||
{
|
||||
auto p0 = is(1);
|
||||
auto p1 = p0;
|
||||
@@ -118,9 +118,9 @@ read(nudb::detail::istream& is, std::size_t& u)
|
||||
template <class T>
|
||||
void
|
||||
write(nudb::detail::ostream& os, std::size_t t)
|
||||
requires(std::is_same_v<T, Varint>)
|
||||
requires(std::is_same_v<T, varint>)
|
||||
{
|
||||
writeVarint(os.data(sizeVarint(t)), t);
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
@@ -246,15 +246,7 @@ message TMGetObjectByHash {
|
||||
|
||||
message TMLedgerNode {
|
||||
required bytes nodedata = 1;
|
||||
|
||||
// Used when protocol version <2.3. Not set for ledger base data.
|
||||
optional bytes nodeid = 2;
|
||||
|
||||
// Used when protocol version >=2.3. Neither value is set for ledger base data.
|
||||
oneof reference {
|
||||
bytes id = 3; // Set for inner nodes.
|
||||
uint32 depth = 4; // Set for leaf nodes.
|
||||
}
|
||||
optional bytes nodeid = 2; // missing for ledger base data
|
||||
}
|
||||
|
||||
enum TMLedgerInfoType {
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/HashPrefix.h>
|
||||
#include <xrpl/protocol/IOUAmount.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MPTAmount.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
inline void
|
||||
@@ -25,70 +15,4 @@ serializePayChanAuthorization(Serializer& msg, uint256 const& key, XRPAmount con
|
||||
msg.add64(amt.drops());
|
||||
}
|
||||
|
||||
inline void
|
||||
serializePayChanAuthorization(
|
||||
Serializer& msg,
|
||||
uint256 const& key,
|
||||
IOUAmount const& amt,
|
||||
Currency const& cur,
|
||||
AccountID const& iss)
|
||||
{
|
||||
msg.add32(HashPrefix::PaymentChannelClaim);
|
||||
msg.addBitString(key);
|
||||
if (amt == beast::kZero)
|
||||
{
|
||||
msg.add64(STAmount::kIssuedCurrency);
|
||||
}
|
||||
else if (amt.signum() == -1)
|
||||
{ // 512 = not native; the sign is encoded by omitting the 256 flag, so
|
||||
// the mantissa must be serialized as its absolute value
|
||||
msg.add64(
|
||||
static_cast<std::uint64_t>(-amt.mantissa()) |
|
||||
(static_cast<std::uint64_t>(amt.exponent() + 512 + 97) << (64 - 10)));
|
||||
}
|
||||
else
|
||||
{ // 256 = positive
|
||||
msg.add64(
|
||||
amt.mantissa() |
|
||||
(static_cast<std::uint64_t>(amt.exponent() + 512 + 256 + 97) << (64 - 10)));
|
||||
}
|
||||
msg.addBitString(cur);
|
||||
msg.addBitString(iss);
|
||||
}
|
||||
|
||||
inline void
|
||||
serializePayChanAuthorization(
|
||||
Serializer& msg,
|
||||
uint256 const& key,
|
||||
MPTAmount const& amt,
|
||||
MPTID const& mptID,
|
||||
AccountID const& iss)
|
||||
{
|
||||
msg.add32(HashPrefix::PaymentChannelClaim);
|
||||
msg.addBitString(key);
|
||||
msg.add64(amt.value());
|
||||
msg.addBitString(mptID);
|
||||
msg.addBitString(iss);
|
||||
}
|
||||
|
||||
inline void
|
||||
serializePayChanAuthorization(Serializer& msg, uint256 const& key, STAmount const& amt)
|
||||
{
|
||||
if (amt.native())
|
||||
{
|
||||
serializePayChanAuthorization(msg, key, amt.xrp());
|
||||
}
|
||||
else if (amt.holds<Issue>())
|
||||
{
|
||||
serializePayChanAuthorization(
|
||||
msg, key, amt.iou(), amt.get<Issue>().currency, amt.get<Issue>().account);
|
||||
}
|
||||
else if (amt.holds<MPTIssue>())
|
||||
{
|
||||
auto const& mpt = amt.get<MPTIssue>();
|
||||
auto const& mptID = mpt.getMptID();
|
||||
serializePayChanAuthorization(msg, key, amt.mpt(), mptID, amt.getIssuer());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -316,17 +316,6 @@ constexpr std::uint8_t kVaultDefaultIouScale = 6;
|
||||
*/
|
||||
constexpr std::uint8_t kVaultMaximumIouScale = 18;
|
||||
|
||||
/**
|
||||
* Vault ledger-entry schema versions. Assigned to newly created
|
||||
* Vaults once featureLendingProtocolV1_1 is enabled. Vaults created before
|
||||
* activation are left without LEVersion (implicit legacy version 0,
|
||||
* accrual-basis accounting).
|
||||
*/
|
||||
enum class VaultVersion : uint8_t {
|
||||
Legacy = 0,
|
||||
CashBasis,
|
||||
};
|
||||
|
||||
/**
|
||||
* Maximum recursion depth for vault shares being put as an asset inside
|
||||
* another vault; counted from 0
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(DefragDirectories, Supported::No, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (Cleanup3_4_0, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(TokenPaychan, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Sponsor, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(BatchV1_1, Supported::Yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocolV1_1, Supported::No, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -369,8 +369,6 @@ LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, ({
|
||||
{sfPreviousTxnID, SoeRequired},
|
||||
{sfPreviousTxnLgrSeq, SoeRequired},
|
||||
{sfDestinationNode, SoeOptional},
|
||||
{sfTransferRate, SoeOptional},
|
||||
{sfIssuerNode, SoeOptional},
|
||||
}))
|
||||
|
||||
/** The ledger object which tracks the AMM.
|
||||
@@ -507,7 +505,6 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({
|
||||
{sfShareMPTID, SoeRequired},
|
||||
{sfWithdrawalPolicy, SoeRequired},
|
||||
{sfScale, SoeDefault},
|
||||
{sfLEVersion, SoeDefault},
|
||||
// no SharesTotal ever (use MPTIssuance.sfOutstandingAmount)
|
||||
// no PermissionedDomainID ever (use MPTIssuance.sfDomainID)
|
||||
}))
|
||||
|
||||
@@ -18,7 +18,6 @@ TYPED_SFIELD(sfMethod, UINT8, 2)
|
||||
TYPED_SFIELD(sfTransactionResult, UINT8, 3)
|
||||
TYPED_SFIELD(sfScale, UINT8, 4)
|
||||
TYPED_SFIELD(sfAssetScale, UINT8, 5)
|
||||
TYPED_SFIELD(sfLEVersion, UINT8, 6)
|
||||
|
||||
// 8-bit integers (uncommon)
|
||||
TYPED_SFIELD(sfTickSize, UINT8, 16)
|
||||
|
||||
@@ -191,7 +191,7 @@ TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate,
|
||||
NoPriv,
|
||||
({
|
||||
{sfDestination, SoeRequired},
|
||||
{sfAmount, SoeRequired, SoeMptSupported},
|
||||
{sfAmount, SoeRequired},
|
||||
{sfSettleDelay, SoeRequired},
|
||||
{sfPublicKey, SoeRequired},
|
||||
{sfCancelAfter, SoeOptional},
|
||||
@@ -208,7 +208,7 @@ TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund,
|
||||
NoPriv,
|
||||
({
|
||||
{sfChannel, SoeRequired},
|
||||
{sfAmount, SoeRequired, SoeMptSupported},
|
||||
{sfAmount, SoeRequired},
|
||||
{sfExpiration, SoeOptional},
|
||||
}))
|
||||
|
||||
@@ -222,8 +222,8 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim,
|
||||
NoPriv,
|
||||
({
|
||||
{sfChannel, SoeRequired},
|
||||
{sfAmount, SoeOptional, SoeMptSupported},
|
||||
{sfBalance, SoeOptional, SoeMptSupported},
|
||||
{sfAmount, SoeOptional},
|
||||
{sfBalance, SoeOptional},
|
||||
{sfSignature, SoeOptional},
|
||||
{sfPublicKey, SoeOptional},
|
||||
{sfCredentialIDs, SoeOptional},
|
||||
|
||||
@@ -287,54 +287,6 @@ public:
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfDestinationNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfTransferRate (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_UINT32::type::value_type>
|
||||
getTransferRate() const
|
||||
{
|
||||
if (hasTransferRate())
|
||||
return this->sle_->at(sfTransferRate);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfTransferRate is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasTransferRate() const
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfTransferRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfIssuerNode (SoeOptional)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_UINT64::type::value_type>
|
||||
getIssuerNode() const
|
||||
{
|
||||
if (hasIssuerNode())
|
||||
return this->sle_->at(sfIssuerNode);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfIssuerNode is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasIssuerNode() const
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfIssuerNode);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -556,28 +508,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfTransferRate (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PayChannelBuilder&
|
||||
setTransferRate(std::decay_t<typename SF_UINT32::type::value_type> const& value)
|
||||
{
|
||||
object_[sfTransferRate] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfIssuerNode (SoeOptional)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PayChannelBuilder&
|
||||
setIssuerNode(std::decay_t<typename SF_UINT64::type::value_type> const& value)
|
||||
{
|
||||
object_[sfIssuerNode] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the completed PayChannel wrapper.
|
||||
* @param index The ledger entry index.
|
||||
|
||||
@@ -287,30 +287,6 @@ public:
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sfLEVersion (SoeDefault)
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
protocol_autogen::Optional<SF_UINT8::type::value_type>
|
||||
getLEVersion() const
|
||||
{
|
||||
if (hasLEVersion())
|
||||
return this->sle_->at(sfLEVersion);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if sfLEVersion is present.
|
||||
* @return True if the field is present, false otherwise.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool
|
||||
hasLEVersion() const
|
||||
{
|
||||
return this->sle_->isFieldPresent(sfLEVersion);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -532,17 +508,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set sfLEVersion (SoeDefault)
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
VaultBuilder&
|
||||
setLEVersion(std::decay_t<typename SF_UINT8::type::value_type> const& value)
|
||||
{
|
||||
object_[sfLEVersion] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build and return the completed Vault wrapper.
|
||||
* @param index The ledger entry index.
|
||||
|
||||
@@ -60,7 +60,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Get sfAmount (SoeOptional)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
@@ -87,7 +86,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Get sfBalance (SoeOptional)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return The field value, or std::nullopt if not present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
@@ -248,7 +246,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Set sfAmount (SoeOptional)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PaymentChannelClaimBuilder&
|
||||
@@ -260,7 +257,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Set sfBalance (SoeOptional)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PaymentChannelClaimBuilder&
|
||||
|
||||
@@ -60,7 +60,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Get sfAmount (SoeRequired)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return The field value.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
@@ -208,7 +207,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Set sfAmount (SoeRequired)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PaymentChannelCreateBuilder&
|
||||
|
||||
@@ -60,7 +60,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Get sfAmount (SoeRequired)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return The field value.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
@@ -156,7 +155,6 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Set sfAmount (SoeRequired)
|
||||
* @note This field supports MPT (Multi-Purpose Token) amounts.
|
||||
* @return Reference to this builder for method chaining.
|
||||
*/
|
||||
PaymentChannelFundBuilder&
|
||||
|
||||
@@ -26,10 +26,10 @@ public:
|
||||
explicit Family() = default;
|
||||
virtual ~Family() = default;
|
||||
|
||||
virtual node_store::Database&
|
||||
virtual NodeStore::Database&
|
||||
db() = 0;
|
||||
|
||||
[[nodiscard]] virtual node_store::Database const&
|
||||
[[nodiscard]] virtual NodeStore::Database const&
|
||||
db() const = 0;
|
||||
|
||||
virtual beast::Journal const&
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/basics/Blob.h>
|
||||
#include <xrpl/basics/IntrusivePointer.h>
|
||||
#include <xrpl/basics/SHAMapHash.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
@@ -94,21 +95,6 @@ enum class SHAMapState {
|
||||
*
|
||||
* See https://en.wikipedia.org/wiki/Merkle_tree
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds a SHAMap node's identity, leaf status, and serialized data. Used by
|
||||
* getNodeFat to return node data for peer synchronization.
|
||||
*/
|
||||
struct SHAMapNodeData
|
||||
{
|
||||
SHAMapNodeID nodeID;
|
||||
// The `data` field (a Blob, 8-byte aligned) needs 4 bytes of padding after the `nodeID` field
|
||||
// (36 bytes, 4-byte aligned) regardless of what comes between them, so `isLeaf` costs nothing
|
||||
// extra here. Moving it after `data` would add 8 bytes to the size of this struct instead.
|
||||
bool isLeaf;
|
||||
Blob data;
|
||||
};
|
||||
|
||||
class SHAMap
|
||||
{
|
||||
private:
|
||||
@@ -303,10 +289,10 @@ public:
|
||||
std::vector<std::pair<SHAMapNodeID, uint256>>
|
||||
getMissingNodes(int maxNodes, SHAMapSyncFilter const* filter);
|
||||
|
||||
[[nodiscard]] bool
|
||||
bool
|
||||
getNodeFat(
|
||||
SHAMapNodeID const& wanted,
|
||||
std::vector<SHAMapNodeData>& data,
|
||||
std::vector<std::pair<SHAMapNodeID, Blob>>& data,
|
||||
bool fatLeaves,
|
||||
std::uint32_t depth) const;
|
||||
|
||||
@@ -335,45 +321,10 @@ public:
|
||||
void
|
||||
serializeRoot(Serializer& s) const;
|
||||
|
||||
/**
|
||||
* Add a root node to the SHAMap during synchronization.
|
||||
*
|
||||
* This function is used when receiving the root node of a SHAMap from a peer during ledger
|
||||
* synchronization. The node must already have been deserialized.
|
||||
*
|
||||
* @param hash The expected hash of the root node.
|
||||
* @param rootNode A deserialized root node to add.
|
||||
* @param filter Optional sync filter to track received nodes.
|
||||
* @return Status indicating whether the node was useful, duplicate, or invalid.
|
||||
*
|
||||
* @note This function expects the rootNode to be a valid, deserialized SHAMapTreeNode. The
|
||||
* caller is responsible for deserialization and basic validation before calling this
|
||||
* function.
|
||||
*/
|
||||
SHAMapAddNode
|
||||
addRootNode(SHAMapHash const& hash, SHAMapTreeNodePtr rootNode, SHAMapSyncFilter const* filter);
|
||||
|
||||
/**
|
||||
* Add a known node at a specific position in the SHAMap during synchronization.
|
||||
*
|
||||
* This function is used when receiving nodes from peers during ledger synchronization. The node
|
||||
* is inserted at the position specified by nodeID. The node must already have been
|
||||
* deserialized.
|
||||
*
|
||||
* @param nodeID The position in the tree where this node belongs.
|
||||
* @param treeNode A deserialized tree node to add.
|
||||
* @param filter Optional sync filter to track received nodes.
|
||||
* @return Status indicating whether the node was useful, duplicate, or invalid.
|
||||
*
|
||||
* @note This function expects the treeNode to be a valid, deserialized SHAMapTreeNode. The
|
||||
* caller is responsible for deserialization and basic validation before calling this
|
||||
* function. This also means that the nodeID must be consistent with the node's content.
|
||||
*/
|
||||
addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter const* filter);
|
||||
SHAMapAddNode
|
||||
addKnownNode(
|
||||
SHAMapNodeID const& nodeID,
|
||||
SHAMapTreeNodePtr treeNode,
|
||||
SHAMapSyncFilter const* filter);
|
||||
addKnownNode(SHAMapNodeID const& nodeID, Slice const& rawNode, SHAMapSyncFilter const* filter);
|
||||
|
||||
// status functions
|
||||
void
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/SHAMapHash.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/shamap/SHAMapItem.h>
|
||||
#include <xrpl/shamap/SHAMapNodeID.h>
|
||||
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||
@@ -63,16 +60,4 @@ public:
|
||||
getString(SHAMapNodeID const&) const final;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the key of the item held by a SHAMap leaf node.
|
||||
*
|
||||
* @param node a node known to be a leaf (see SHAMapTreeNode::isLeaf).
|
||||
*/
|
||||
inline uint256 const&
|
||||
leafKey(SHAMapTreeNode const& node)
|
||||
{
|
||||
XRPL_ASSERT(node.isLeaf(), "xrpl::leafKey : node is a leaf");
|
||||
return safeDowncast<SHAMapLeafNode const&>(node).peekItem()->key();
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -23,9 +23,6 @@ public:
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
|
||||
@@ -23,15 +23,9 @@ public:
|
||||
static TxConsequences
|
||||
makeTxConsequences(PreflightContext const& ctx);
|
||||
|
||||
static bool
|
||||
checkExtraFeatures(PreflightContext const& ctx);
|
||||
|
||||
static NotTEC
|
||||
preflight(PreflightContext const& ctx);
|
||||
|
||||
static TER
|
||||
preclaim(PreclaimContext const& ctx);
|
||||
|
||||
TER
|
||||
doApply() override;
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# 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:
|
||||
|
||||
| File | Environment |
|
||||
| ---------------------- | ------------------------------------ |
|
||||
| `nix-ubuntu-amd64.txt` | `nix-ubuntu` CI image, `linux/amd64` |
|
||||
| `nix-ubuntu-arm64.txt` | `nix-ubuntu` CI image, `linux/arm64` |
|
||||
| `macos.txt` | macOS, inside `nix develop` |
|
||||
|
||||
The [`check-tools`](../../.github/workflows/check-tools.yml) workflow regenerates
|
||||
each snapshot in its environment and fails if it differs from the committed file.
|
||||
So if you change the environment (bump the image tag in
|
||||
[`linux.json`](../../.github/scripts/strategy-matrix/linux.json), update
|
||||
`flake.lock`, change the tool list in `check-tools.sh`, …) you must regenerate
|
||||
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'`.
|
||||
|
||||
## Regenerating
|
||||
|
||||
The two Linux snapshots come from the `nix-ubuntu` image (Docker or a compatible
|
||||
runtime such as Apple `container`). The image tag is pinned in `linux.json`:
|
||||
|
||||
```bash
|
||||
img="ghcr.io/xrplf/xrpld/nix-ubuntu:$(jq -r .image_tag .github/scripts/strategy-matrix/linux.json)"
|
||||
|
||||
for arch in amd64 arm64; do
|
||||
container run --rm -i -e CHECK_TOOLS_SKIP_CLONE=1 -a "${arch}" --entrypoint bash "${img}" -s \
|
||||
<bin/check-tools.sh >"nix/check-tools/nix-ubuntu-${arch}.txt"
|
||||
done
|
||||
```
|
||||
|
||||
(With Docker, replace `container run … -a "${arch}"` with
|
||||
`docker run … --platform "linux/${arch}"`.)
|
||||
|
||||
The macOS snapshot is generated locally. `CI=` is unset so `check-tools.sh`
|
||||
checks the full dev-shell tool set (it otherwise skips some tools when `CI` is
|
||||
set):
|
||||
|
||||
```bash
|
||||
CI= nix develop -c bash -c 'CHECK_TOOLS_SKIP_CLONE=1 bash bin/check-tools.sh' |
|
||||
sed -n '/^Detected OS:/,$p' \
|
||||
>nix/check-tools/macos.txt
|
||||
```
|
||||
@@ -1,47 +0,0 @@
|
||||
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
|
||||
|
||||
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]
|
||||
|
||||
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)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
All 36 checked tools are present and runnable.
|
||||
@@ -1,55 +0,0 @@
|
||||
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
|
||||
|
||||
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]
|
||||
|
||||
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)
|
||||
|
||||
GCC toolchain:
|
||||
[ ok ] gcc gcc (GCC) 15.2.0
|
||||
[ ok ] g++ g++ (GCC) 15.2.0
|
||||
[ ok ] gcov gcov (GCC) 15.2.0
|
||||
|
||||
Mold:
|
||||
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
All 40 checked tools are present and runnable.
|
||||
@@ -1,55 +0,0 @@
|
||||
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
|
||||
|
||||
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]
|
||||
|
||||
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)
|
||||
|
||||
GCC toolchain:
|
||||
[ ok ] gcc gcc (GCC) 15.2.0
|
||||
[ ok ] g++ g++ (GCC) 15.2.0
|
||||
[ ok ] gcov gcov (GCC) 15.2.0
|
||||
|
||||
Mold:
|
||||
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
All 40 checked tools are present and runnable.
|
||||
@@ -50,17 +50,12 @@ let
|
||||
# compilerName is the command used to print the version, or null for none.
|
||||
makeShell =
|
||||
{
|
||||
shellName,
|
||||
stdenv,
|
||||
compilerName,
|
||||
version ? null,
|
||||
versionedTools ? [ ],
|
||||
extraPackages ? [ ],
|
||||
warningHook ? "",
|
||||
# Opt out of PatchNixBinary.cmake retargeting binaries to the system
|
||||
# loader. The plain toolchain links a newer glibc, so it must not be
|
||||
# patched; the custom toolchain patches by default.
|
||||
noPatchNixBinary ? false,
|
||||
}:
|
||||
let
|
||||
compilerVersionHook =
|
||||
@@ -78,20 +73,14 @@ let
|
||||
tools = versionedTools;
|
||||
});
|
||||
in
|
||||
(pkgs.mkShell.override { inherit stdenv; }) (
|
||||
{
|
||||
packages = commonPackages ++ versionedLinks ++ extraPackages;
|
||||
# Marks a managed dev shell, so the build (XrplSanity.cmake) can tell an
|
||||
# intentional Nix toolchain from one leaked into a bare shell.
|
||||
XRPL_DEVSHELL = shellName;
|
||||
shellHook = ''
|
||||
echo "Welcome to xrpld development shell";
|
||||
${compilerVersionHook}
|
||||
${warningHook}
|
||||
'';
|
||||
}
|
||||
// pkgs.lib.optionalAttrs noPatchNixBinary { XRPLD_NO_PATCH_NIX_BINARY = "1"; }
|
||||
);
|
||||
(pkgs.mkShell.override { inherit stdenv; }) {
|
||||
packages = commonPackages ++ versionedLinks ++ extraPackages;
|
||||
shellHook = ''
|
||||
echo "Welcome to xrpld development shell";
|
||||
${compilerVersionHook}
|
||||
${warningHook}
|
||||
'';
|
||||
};
|
||||
in
|
||||
rec {
|
||||
# macOS: Nix Clang. Linux: Nix GCC.
|
||||
@@ -100,7 +89,6 @@ rec {
|
||||
# gcc/clang use the custom-glibc toolchain, matching CI. On darwin there is no
|
||||
# custom glibc, so they fall back to the plain nixpkgs toolchain.
|
||||
gcc = makeShell {
|
||||
shellName = "gcc";
|
||||
stdenv = customGccStdenv;
|
||||
compilerName = "gcc";
|
||||
version = gccVersion;
|
||||
@@ -109,7 +97,6 @@ rec {
|
||||
};
|
||||
|
||||
clang = makeShell {
|
||||
shellName = "clang";
|
||||
stdenv = customClangStdenv;
|
||||
compilerName = "clang";
|
||||
version = llvmVersion;
|
||||
@@ -118,7 +105,6 @@ rec {
|
||||
|
||||
# Nix provides no compiler; use the one from your system (e.g. Apple Clang).
|
||||
no-compiler = makeShell {
|
||||
shellName = "no-compiler";
|
||||
stdenv = pkgs.stdenvNoCC;
|
||||
compilerName = null;
|
||||
};
|
||||
@@ -129,23 +115,19 @@ rec {
|
||||
# makes `nix develop .#gcc-plain` fail there rather than silently aliasing gcc.
|
||||
// pkgs.lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||
gcc-plain = makeShell {
|
||||
shellName = "gcc-plain";
|
||||
stdenv = plainGccStdenv;
|
||||
compilerName = "gcc";
|
||||
version = gccVersion;
|
||||
versionedTools = gccVersionedTools;
|
||||
extraPackages = [ plainGcov ];
|
||||
warningHook = plainWarningHook;
|
||||
noPatchNixBinary = true;
|
||||
};
|
||||
|
||||
clang-plain = makeShell {
|
||||
shellName = "clang-plain";
|
||||
stdenv = plainClangStdenv;
|
||||
compilerName = "clang";
|
||||
version = llvmVersion;
|
||||
versionedTools = clangVersionedTools;
|
||||
warningHook = plainWarningHook;
|
||||
noPatchNixBinary = true;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ ENV GIT_SSL_CAINFO="/nix/ci-env/etc/ssl/certs/ca-bundle.crt"
|
||||
# Externally-built dynamically-linked ELF binaries hard-code the loader path
|
||||
# (e.g. /lib64/ld-linux-x86-64.so.2) in their PT_INTERP header. Install it
|
||||
# from the Nix store when the base image doesn't already provide one.
|
||||
COPY bin/default-loader-path.sh /tmp/loader-path.sh
|
||||
COPY nix/docker/loader-path.sh /tmp/loader-path.sh
|
||||
|
||||
RUN <<EOF
|
||||
target="$(/tmp/loader-path.sh)"
|
||||
|
||||
@@ -75,9 +75,8 @@ toolchain being present at runtime. Two pieces make that work:
|
||||
|
||||
- **An expected dynamic linker in the image.**
|
||||
Binaries built in Nix environments reference a dynamic linker from Nix store paths, which won't be present in the base image. However,
|
||||
[`bin/default-loader-path.sh`](../../bin/default-loader-path.sh) reports the
|
||||
expected loader path for the current architecture, so we can patch the binaries
|
||||
to use the correct loader.
|
||||
[`loader-path.sh`](./loader-path.sh) reports the expected loader path for the
|
||||
current architecture, so we can patch the binaries to use the correct loader.
|
||||
|
||||
The build then verifies all of this end to end, and the C++ and Rust programs
|
||||
go through the same pipeline: each is compiled in `final`, has its `PT_INTERP`
|
||||
@@ -94,8 +93,8 @@ whose resulting binary is patched and run like the others.
|
||||
| File | Purpose |
|
||||
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [`./Dockerfile`](./Dockerfile) | Multi-stage build described above. |
|
||||
| [`./loader-path.sh`](./loader-path.sh) | Print the dynamic-linker (`PT_INTERP`) path for the current architecture. |
|
||||
| [`./test_files/cpp/`](./test_files/cpp) | C++ sanitizer smoke test: sources + compile/run scripts. |
|
||||
| [`./test_files/rust/`](./test_files/rust) | Rust smoke test: rustc sources + a cargo proc-macro workspace + compile/run scripts. |
|
||||
| [`/bin/check-tools.sh`](../../bin/check-tools.sh) | Verify every expected tools are present and runnable. |
|
||||
| [`/bin/default-loader-path.sh`](../../bin/default-loader-path.sh) | Print the dynamic-linker (`PT_INTERP`) path for the current architecture. |
|
||||
| [`/bin/install-sanitizer-libs.sh`](../../bin/install-sanitizer-libs.sh) | Install `libasan`/`libtsan`/`libubsan` runtimes on the supported base images. |
|
||||
|
||||
@@ -16,23 +16,7 @@ let
|
||||
exec ${pkgs.python3}/bin/python3 ${llvmPackages.clang-unwrapped}/bin/run-clang-tidy "$@"
|
||||
'';
|
||||
|
||||
# rust-overlay's toolchain propagates the *default* stdenv.cc onto the PATH (so
|
||||
# cargo has a linker). That default may be different from the clang we pin here,
|
||||
# so it shadows our clang and the build can silently use a different compiler
|
||||
# version. Drop that cc from every propagation channel instead of pinning a
|
||||
# replacement: the toolchain then carries no compiler and cargo just uses the
|
||||
# active shell's stdenv cc. Must cover all channels — rust-overlay uses both
|
||||
# propagatedBuildInputs and depsHostHostPropagated.
|
||||
rustToolchainBase = pkgs.rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
|
||||
rustToolchain =
|
||||
let
|
||||
defaultCc = pkgs.stdenv.cc; # default compiler from nixpkgs stdenv
|
||||
withoutDefaultCc = builtins.filter (dep: (dep.outPath or "") != defaultCc.outPath);
|
||||
in
|
||||
rustToolchainBase.overrideAttrs (old: {
|
||||
propagatedBuildInputs = withoutDefaultCc (old.propagatedBuildInputs or [ ]);
|
||||
depsHostHostPropagated = withoutDefaultCc (old.depsHostHostPropagated or [ ]);
|
||||
});
|
||||
rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
|
||||
|
||||
# Nix wraps its toolchain so that binaries are exposed only under unsuffixed
|
||||
# names (gcc, g++, clang-tidy, ...). Several tools probe for a
|
||||
|
||||
@@ -192,7 +192,6 @@ unsigned-integer-overflow:rpc/handlers/orderbook/GetAggregatePrice.cpp
|
||||
# Test-only intentional overflow/underflow in fixture and unit-test arithmetic.
|
||||
unsigned-integer-overflow:tests/libxrpl/basics/RangeSet.cpp
|
||||
unsigned-integer-overflow:test/app/Batch_test.cpp
|
||||
unsigned-integer-overflow:test/app/ConfidentialTransfer_test.cpp
|
||||
unsigned-integer-overflow:test/app/Invariants_test.cpp
|
||||
unsigned-integer-overflow:test/app/Loan_test.cpp
|
||||
unsigned-integer-overflow:test/app/NFToken_test.cpp
|
||||
|
||||
@@ -17,25 +17,24 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
namespace {
|
||||
|
||||
constexpr auto kPoolSizes = std::to_array<std::size_t>({1000, 10000, 100000});
|
||||
constexpr auto kThreadCounts = std::to_array<std::size_t>({1, 4, 8});
|
||||
constexpr std::size_t kPoolSizes[] = {1000, 10000, 100000};
|
||||
constexpr int kThreadCounts[] = {1, 4, 8};
|
||||
constexpr std::size_t kBatchSize = 256;
|
||||
constexpr std::size_t kMissRatio = 5;
|
||||
|
||||
constexpr std::string_view kNamePrefix = "BM_Backend_";
|
||||
constexpr std::string_view kNameSeparator = "/";
|
||||
|
||||
struct RunState
|
||||
{
|
||||
std::unique_ptr<BackendHarness> harness; ///< backend under test, rebuilt per run
|
||||
Batch present; ///< prefix-1 objects, eligible to be stored
|
||||
Batch recent; ///< prefix-1 objects in the "future" key space
|
||||
std::vector<uint256> missing; ///< prefix-2 keys that are never stored
|
||||
std::vector<std::size_t> shuffle; ///< [0, poolSize) permutation for random-like access
|
||||
std::size_t avgPayload = 0; ///< mean getData().size() over `present`
|
||||
std::unique_ptr<BackendHarness> harness;
|
||||
Batch present; // prefix-1 objects, eligible to be stored
|
||||
Batch recent; // prefix-1 objects in the "future" key space
|
||||
std::vector<uint256> missing; // prefix-2 keys that are never stored
|
||||
std::vector<std::size_t> shuffle; // [0, poolSize) permutation for random-like access
|
||||
std::size_t avgPayload = 0; // mean getData().size() over `present`
|
||||
|
||||
void
|
||||
release()
|
||||
@@ -86,7 +85,7 @@ Workload const kInsert{
|
||||
},
|
||||
.iterate =
|
||||
[](IterateContext const& ctx) {
|
||||
auto const& [rs, backend, index, poolSize] = ctx;
|
||||
auto& [rs, backend, index, poolSize] = ctx;
|
||||
backend.store(rs.present[index % poolSize]);
|
||||
},
|
||||
.reportBytes = true,
|
||||
@@ -105,7 +104,7 @@ Workload const kFetch{
|
||||
},
|
||||
.iterate =
|
||||
[](IterateContext const& ctx) {
|
||||
auto const& [rs, backend, index, poolSize] = ctx;
|
||||
auto& [rs, backend, index, poolSize] = ctx;
|
||||
std::shared_ptr<NodeObject> result;
|
||||
backend.fetch(rs.present[index % poolSize]->getHash(), &result);
|
||||
benchmark::DoNotOptimize(result);
|
||||
@@ -119,7 +118,7 @@ Workload const kMissing{
|
||||
.setup = [](SetupContext const& ctx) { ctx.rs.missing = makeMissingKeys(ctx.poolSize); },
|
||||
.iterate =
|
||||
[](IterateContext const& ctx) {
|
||||
auto const& [rs, backend, index, poolSize] = ctx;
|
||||
auto& [rs, backend, index, poolSize] = ctx;
|
||||
std::shared_ptr<NodeObject> result;
|
||||
backend.fetch(rs.missing[index % poolSize], &result);
|
||||
benchmark::DoNotOptimize(result);
|
||||
@@ -140,10 +139,10 @@ Workload const kMixed{
|
||||
},
|
||||
.iterate =
|
||||
[](IterateContext const& ctx) {
|
||||
auto const& [rs, backend, index, poolSize] = ctx;
|
||||
auto& [rs, backend, index, poolSize] = ctx;
|
||||
std::shared_ptr<NodeObject> result;
|
||||
auto const pick = rs.shuffle[index % poolSize];
|
||||
if (index % kMissRatio == 0)
|
||||
if (index % 5 == 0)
|
||||
{
|
||||
backend.fetch(rs.missing[pick], &result);
|
||||
}
|
||||
@@ -171,7 +170,7 @@ Workload const kWork{
|
||||
},
|
||||
.iterate =
|
||||
[](IterateContext const& ctx) {
|
||||
auto const& [rs, backend, index, poolSize] = ctx;
|
||||
auto& [rs, backend, index, poolSize] = ctx;
|
||||
auto const slot = index % poolSize;
|
||||
auto const pick = rs.shuffle[slot];
|
||||
|
||||
@@ -240,7 +239,7 @@ registerWorkload(BackendConfig const& bc, Workload const& w)
|
||||
{
|
||||
auto rs = std::make_shared<RunState>();
|
||||
auto* b = benchmark::RegisterBenchmark(name, makeRunner(w, cfg, rs));
|
||||
b->RangeMultiplier(10)->Range(kPoolSizes.front(), kPoolSizes.back());
|
||||
b->RangeMultiplier(10)->Range(kPoolSizes[0], kPoolSizes[std::size(kPoolSizes) - 1]);
|
||||
b->Threads(1)->Threads(4)->Threads(8)->UseRealTime();
|
||||
|
||||
return;
|
||||
@@ -250,14 +249,14 @@ registerWorkload(BackendConfig const& bc, Workload const& w)
|
||||
{
|
||||
for (auto const threads : kThreadCounts)
|
||||
{
|
||||
if (poolSize % threads != 0)
|
||||
if (poolSize % static_cast<std::size_t>(threads) != 0)
|
||||
continue;
|
||||
|
||||
auto rs = std::make_shared<RunState>();
|
||||
benchmark::RegisterBenchmark(name, makeRunner(w, cfg, rs))
|
||||
->Arg(poolSize)
|
||||
->Iterations(poolSize / threads)
|
||||
->Threads(static_cast<int>(threads))
|
||||
->Iterations(poolSize / static_cast<std::size_t>(threads))
|
||||
->Threads(threads)
|
||||
->UseRealTime();
|
||||
}
|
||||
}
|
||||
@@ -290,7 +289,7 @@ registerStoreBatch(BackendConfig const& bc)
|
||||
rs->harness = std::make_unique<BackendHarness>(cfg);
|
||||
rs->present = makePool(1, poolSize);
|
||||
rs->avgPayload = averagePayload(rs->present);
|
||||
std::vector<Batch> const batches = sliceFixedBatches(rs->present, kBatchSize);
|
||||
std::vector<Batch> const batches = sliceBatches(rs->present, kBatchSize);
|
||||
if (batches.empty())
|
||||
{
|
||||
state.SkipWithError("pool smaller than one batch");
|
||||
@@ -327,4 +326,4 @@ registerStoreBatch(BackendConfig const& bc)
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
namespace {
|
||||
|
||||
// Number of distinct objects pre-generated per run.
|
||||
@@ -240,4 +240,4 @@ registerWorkload(BackendConfig const& bc, Workload const& w)
|
||||
}();
|
||||
|
||||
} // namespace
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -26,14 +26,13 @@
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// Shared helpers for the NodeStore benchmarks.
|
||||
//
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
// Fill `bytes` of memory at `buffer` with random bits drawn from `g`.
|
||||
template <class Generator>
|
||||
@@ -41,13 +40,18 @@ inline void
|
||||
rngcpy(void* buffer, std::size_t bytes, Generator& g)
|
||||
{
|
||||
using result_type = typename Generator::result_type;
|
||||
while (bytes > 0)
|
||||
while (bytes >= sizeof(result_type))
|
||||
{
|
||||
auto const v = g();
|
||||
auto const chunk = std::min(bytes, sizeof(result_type));
|
||||
std::memcpy(buffer, &v, chunk);
|
||||
buffer = reinterpret_cast<std::uint8_t*>(buffer) + chunk;
|
||||
bytes -= chunk;
|
||||
std::memcpy(buffer, &v, sizeof(v));
|
||||
buffer = reinterpret_cast<std::uint8_t*>(buffer) + sizeof(v);
|
||||
bytes -= sizeof(v);
|
||||
}
|
||||
|
||||
if (bytes > 0)
|
||||
{
|
||||
auto const v = g();
|
||||
std::memcpy(buffer, &v, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +145,7 @@ makePool(std::uint8_t prefix, std::size_t count, std::size_t start = 0)
|
||||
Sequence seq(prefix);
|
||||
Batch pool;
|
||||
pool.reserve(count);
|
||||
for (auto i = 0uz; i < count; ++i)
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
pool.push_back(seq.obj(start + i));
|
||||
return pool;
|
||||
}
|
||||
@@ -154,7 +158,7 @@ makeMissingKeys(std::size_t count)
|
||||
Sequence seq(2);
|
||||
std::vector<uint256> keys;
|
||||
keys.reserve(count);
|
||||
for (auto i = 0uz; i < count; ++i)
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
keys.push_back(seq.key(i));
|
||||
return keys;
|
||||
}
|
||||
@@ -202,16 +206,16 @@ inline std::vector<std::size_t>
|
||||
makeShuffle(std::size_t size, std::uint64_t seed)
|
||||
{
|
||||
std::vector<std::size_t> v(size);
|
||||
std::ranges::iota(v, 0uz);
|
||||
std::iota(v.begin(), v.end(), std::size_t{0});
|
||||
beast::xor_shift_engine gen(seed);
|
||||
std::ranges::shuffle(v, gen);
|
||||
std::shuffle(v.begin(), v.end(), gen);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Partition a pool into fixed-size batches. Any trailing remainder shorter than
|
||||
// `batchSize` is dropped, so every returned batch has exactly `batchSize`.
|
||||
inline std::vector<Batch>
|
||||
sliceFixedBatches(Batch const& pool, std::size_t batchSize)
|
||||
sliceBatches(Batch const& pool, std::size_t batchSize)
|
||||
{
|
||||
std::vector<Batch> batches;
|
||||
if (batchSize == 0)
|
||||
@@ -224,10 +228,13 @@ sliceFixedBatches(Batch const& pool, std::size_t batchSize)
|
||||
|
||||
/**
|
||||
* @brief RAII owner of a NodeStore Backend opened on a private temporary directory.
|
||||
*
|
||||
* Member declaration order matters: `tempDir` is declared first so it is
|
||||
* destroyed last, after the backend has closed and released its files.
|
||||
*/
|
||||
struct BackendHarness
|
||||
{
|
||||
beast::TempDir tempDir; ///< Declared first so it is destroyed last
|
||||
beast::TempDir tempDir;
|
||||
DummyScheduler scheduler;
|
||||
beast::Journal journal{beast::Journal::getNullSink()};
|
||||
std::unique_ptr<Backend> backend;
|
||||
@@ -308,4 +315,4 @@ backendConfigs()
|
||||
return kConfigs;
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace beast {
|
||||
|
||||
std::string
|
||||
printIdentifiers(SemanticVersion::IdentifierList const& list)
|
||||
printIdentifiers(SemanticVersion::identifier_list const& list)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
@@ -115,7 +115,7 @@ extractIdentifier(std::string& value, bool allowLeadingZeroes, std::string& inpu
|
||||
|
||||
bool
|
||||
extractIdentifiers(
|
||||
SemanticVersion::IdentifierList& identifiers,
|
||||
SemanticVersion::identifier_list& identifiers,
|
||||
bool allowLeadingZeroes,
|
||||
std::string& input)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,14 @@ namespace xrpl {
|
||||
|
||||
namespace directory {
|
||||
|
||||
struct Gap
|
||||
{
|
||||
uint64_t const page;
|
||||
SLE::pointer node;
|
||||
uint64_t const nextPage;
|
||||
SLE::pointer next;
|
||||
};
|
||||
|
||||
std::uint64_t
|
||||
createRoot(
|
||||
ApplyView& view,
|
||||
@@ -126,7 +134,9 @@ insertPage(
|
||||
if (page == 0)
|
||||
return std::nullopt;
|
||||
if (!view.rules().enabled(fixDirectoryLimit) && page >= kDirNodeMaxPages) // Old pages limit
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// We are about to create a new node; we'll link it to
|
||||
// the chain first:
|
||||
@@ -147,12 +157,8 @@ insertPage(
|
||||
// Save some space by not specifying the value 0 since it's the default.
|
||||
if (page != 1)
|
||||
node->setFieldU64(sfIndexPrevious, page - 1);
|
||||
XRPL_ASSERT_PARTS(!nextPage, "xrpl::directory::insertPage", "nextPage has default value");
|
||||
/* Reserved for future use when directory pages may be inserted in
|
||||
* between two other pages instead of only at the end of the chain.
|
||||
if (nextPage)
|
||||
node->setFieldU64(sfIndexNext, nextPage);
|
||||
*/
|
||||
describe(node);
|
||||
view.insert(node);
|
||||
|
||||
@@ -168,7 +174,7 @@ ApplyView::dirAdd(
|
||||
uint256 const& key,
|
||||
std::function<void(SLE::ref)> const& describe)
|
||||
{
|
||||
auto root = peek(directory);
|
||||
auto const root = peek(directory);
|
||||
|
||||
if (!root)
|
||||
{
|
||||
@@ -178,6 +184,43 @@ ApplyView::dirAdd(
|
||||
|
||||
auto [page, node, indexes] = directory::findPreviousPage(*this, directory, root);
|
||||
|
||||
if (rules().enabled(featureDefragDirectories))
|
||||
{
|
||||
// If there are more nodes than just the root, and there's no space in
|
||||
// the last one, walk backwards to find one with space, or to find one
|
||||
// missing.
|
||||
std::optional<directory::Gap> gapPages;
|
||||
while (page && indexes.size() >= kDIR_NODE_MAX_PAGES)
|
||||
{
|
||||
// Find a page with space, or a gap in pages.
|
||||
auto [prevPage, prevNode, prevIndexes] =
|
||||
directory::findPreviousPage(*this, directory, node);
|
||||
if (!gapPages && prevPage != page - 1)
|
||||
gapPages.emplace(prevPage, prevNode, page, node);
|
||||
page = prevPage;
|
||||
node = prevNode;
|
||||
indexes = prevIndexes;
|
||||
}
|
||||
// We looped through all the pages back to the root.
|
||||
if (!page)
|
||||
{
|
||||
// If we found a gap, use it.
|
||||
if (gapPages)
|
||||
{
|
||||
return directory::insertPage(
|
||||
*this,
|
||||
gapPages->page,
|
||||
gapPages->node,
|
||||
gapPages->nextPage,
|
||||
gapPages->next,
|
||||
key,
|
||||
directory,
|
||||
describe);
|
||||
}
|
||||
std::tie(page, node, indexes) = directory::findPreviousPage(*this, directory, root);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's space, we use it:
|
||||
if (indexes.size() < kDirNodeMaxEntries)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/VaultHelpers.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
@@ -131,127 +130,6 @@ isRounded(Asset const& asset, Number const& value, std::int32_t scale)
|
||||
roundToAsset(asset, value, scale, Number::RoundingMode::Upward);
|
||||
}
|
||||
|
||||
namespace Accrual {
|
||||
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(Number const& principalRequested, Number const& interestDue)
|
||||
{
|
||||
return {.assetsTotalDelta = interestDue, .debtTotalDelta = principalRequested + interestDue};
|
||||
}
|
||||
|
||||
bool
|
||||
loanOriginationExceedsVaultMaximum(
|
||||
Number const& vaultMaximum,
|
||||
Number const& vaultTotal,
|
||||
Number const& interestDue)
|
||||
{
|
||||
return vaultMaximum != 0 && interestDue > vaultMaximum - vaultTotal;
|
||||
}
|
||||
|
||||
/*
|
||||
XLS-66 section 3.2.3.2, defines the default amount as
|
||||
|
||||
DefaultAmount = (Loan.PrincipalOutstanding + Loan.InterestOutstanding)
|
||||
|
||||
Which is equivalent to (Loan.TotalValueOutstanding - Loan.ManagementFeeOutstanding)
|
||||
*/
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref loanSle)
|
||||
{
|
||||
return loanSle->at(sfTotalValueOutstanding) - loanSle->at(sfManagementFeeOutstanding);
|
||||
}
|
||||
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(LoanPaymentParts const& parts)
|
||||
{
|
||||
return {
|
||||
.assetsTotalDelta = parts.valueChange,
|
||||
.debtTotalDelta = (parts.principalPaid + parts.interestPaid) - parts.valueChange};
|
||||
}
|
||||
|
||||
} // namespace Accrual
|
||||
|
||||
namespace CashBasis {
|
||||
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(Number const& principalRequested)
|
||||
{
|
||||
return {.assetsTotalDelta = kNumZero, .debtTotalDelta = principalRequested};
|
||||
}
|
||||
|
||||
/*
|
||||
* Under CashBasis accounting, Loan default amount is:
|
||||
*
|
||||
* DefaultAmount = Loan.PrincipalOutstanding
|
||||
*/
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref loanSle)
|
||||
{
|
||||
return loanSle->at(sfPrincipalOutstanding);
|
||||
}
|
||||
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(LoanPaymentParts const& parts)
|
||||
{
|
||||
return {.assetsTotalDelta = parts.interestPaid, .debtTotalDelta = parts.principalPaid};
|
||||
}
|
||||
|
||||
} // namespace CashBasis
|
||||
|
||||
namespace {
|
||||
|
||||
// Cash-basis accounting applies only when featureLendingProtocolV1_1 is
|
||||
// enabled AND the specific Vault was created under it (LEVersion ==
|
||||
// VaultVersion::CashBasis). Vaults created before activation keep accrual-basis
|
||||
// accounting forever, even after the amendment later turns on.
|
||||
bool
|
||||
cashBasisEnabled(SLE::const_ref vaultSle)
|
||||
{
|
||||
return getVaultVersion(vaultSle) == VaultVersion::CashBasis;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AccountingDeltas
|
||||
loanOriginationDeltas(
|
||||
SLE::const_ref vaultSle,
|
||||
Number const& principalRequested,
|
||||
Number const& interestDue)
|
||||
{
|
||||
return cashBasisEnabled(vaultSle)
|
||||
? CashBasis::loanOriginationDeltas(principalRequested)
|
||||
: Accrual::loanOriginationDeltas(principalRequested, interestDue);
|
||||
}
|
||||
|
||||
bool
|
||||
loanOriginationExceedsVaultMaximum(
|
||||
SLE::const_ref vaultSle,
|
||||
Number const& vaultTotal,
|
||||
Number const& interestDue)
|
||||
{
|
||||
// Cash-basis origination doesn't recognize interest into AssetsTotal, so
|
||||
// interest due can never push the vault past AssetsMaximum at origination.
|
||||
if (cashBasisEnabled(vaultSle))
|
||||
return false;
|
||||
|
||||
auto const vaultMaximum = vaultSle->at(sfAssetsMaximum);
|
||||
return Accrual::loanOriginationExceedsVaultMaximum(vaultMaximum, vaultTotal, interestDue);
|
||||
}
|
||||
|
||||
Number
|
||||
loanVaultExposure(SLE::const_ref vaultSle, SLE::const_ref loanSle)
|
||||
{
|
||||
return cashBasisEnabled(vaultSle) ? CashBasis::loanVaultExposure(loanSle)
|
||||
: Accrual::loanVaultExposure(loanSle);
|
||||
}
|
||||
|
||||
AccountingDeltas
|
||||
loanPaymentDeltas(SLE::const_ref vaultSle, LoanPaymentParts const& parts)
|
||||
{
|
||||
return cashBasisEnabled(vaultSle) ? CashBasis::loanPaymentDeltas(parts)
|
||||
: Accrual::loanPaymentDeltas(parts);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
void
|
||||
|
||||
@@ -3,19 +3,14 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/Zero.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
|
||||
#include <xrpl/ledger/helpers/EscrowHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Concepts.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Rate.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
|
||||
@@ -23,19 +18,12 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
TER
|
||||
closeChannel(
|
||||
SLE::ref slep,
|
||||
ApplyViewContext ctx,
|
||||
uint256 const& key,
|
||||
AccountID const& txAccount,
|
||||
beast::Journal j)
|
||||
closeChannel(SLE::ref slep, ApplyView& view, uint256 const& key, beast::Journal j)
|
||||
{
|
||||
ApplyView& view = ctx.view;
|
||||
AccountID const src = (*slep)[sfAccount];
|
||||
// Remove PayChan from owner directory
|
||||
{
|
||||
@@ -50,9 +38,9 @@ closeChannel(
|
||||
}
|
||||
|
||||
// Remove PayChan from recipient's owner directory, if present.
|
||||
AccountID const dst = (*slep)[sfDestination];
|
||||
if (auto const page = (*slep)[~sfDestinationNode])
|
||||
{
|
||||
auto const dst = (*slep)[sfDestination];
|
||||
if (!view.dirRemove(keylet::ownerDir(dst), *page, key, true))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
@@ -69,63 +57,7 @@ closeChannel(
|
||||
|
||||
XRPL_ASSERT(
|
||||
(*slep)[sfAmount] >= (*slep)[sfBalance], "xrpl::closeChannel : minimum channel amount");
|
||||
|
||||
auto const reqDelta = (*slep)[sfAmount] - (*slep)[sfBalance];
|
||||
auto const& issuer = reqDelta.getIssuer();
|
||||
|
||||
// Only update the balance if there is a positive delta.
|
||||
if (reqDelta > beast::kZero)
|
||||
{
|
||||
if (isXRP(reqDelta))
|
||||
{
|
||||
(*sle)[sfBalance] = (*sle)[sfBalance] + reqDelta;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!view.rules().enabled(featureTokenPaychan))
|
||||
return temDISABLED;
|
||||
|
||||
if (auto const ret = std::visit(
|
||||
[&]<typename T>(T const&) {
|
||||
return escrowUnlockPreclaimHelper<T>(view, src, reqDelta, false);
|
||||
},
|
||||
reqDelta.asset().value());
|
||||
!isTesSuccess(ret))
|
||||
return ret;
|
||||
|
||||
bool const createAsset = src == txAccount;
|
||||
if (auto const ret = std::visit(
|
||||
[&]<typename T>(T const&) {
|
||||
return escrowUnlockApplyHelper<T>(
|
||||
ctx,
|
||||
kParityRate,
|
||||
sle,
|
||||
STAmount{(*sle)[sfBalance]}.xrp(),
|
||||
reqDelta,
|
||||
issuer,
|
||||
src,
|
||||
src,
|
||||
createAsset,
|
||||
j);
|
||||
},
|
||||
reqDelta.asset().value());
|
||||
!isTesSuccess(ret))
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove PayChan from issuer's owner directory, if present.
|
||||
if (auto const optPage = (*slep)[~sfIssuerNode])
|
||||
{
|
||||
if (!view.dirRemove(keylet::ownerDir(issuer), *optPage, key, true))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.fatal()) << "Could not remove paychan from issuer owner directory";
|
||||
return tefBAD_LEDGER;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance];
|
||||
decreaseOwnerCountForObject(view, sle, slep, 1, j);
|
||||
view.update(sle);
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
@@ -14,7 +13,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -139,22 +137,4 @@ isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref
|
||||
return sleToken->getFieldU64(sfMPTAmount) == outstanding;
|
||||
}
|
||||
|
||||
[[nodiscard]] VaultVersion
|
||||
getVaultVersion(SLE::const_ref vault)
|
||||
{
|
||||
XRPL_ASSERT(vault && vault->getType() == ltVAULT, "xrpl::getVaultVersion : valid Vault sle");
|
||||
if (!vault->isFieldPresent(sfLEVersion))
|
||||
return VaultVersion::Legacy;
|
||||
|
||||
auto const version = vault->at(sfLEVersion);
|
||||
if (version > std::to_underlying(VaultVersion::CashBasis))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("xrpl::getVaultVersion : invalid vault version");
|
||||
return VaultVersion::Legacy;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
return static_cast<VaultVersion>(version);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
BatchWriter::BatchWriter(Callback& callback, Scheduler& scheduler)
|
||||
: callback_(callback), scheduler_(scheduler)
|
||||
@@ -72,7 +72,7 @@ BatchWriter::writeBatch()
|
||||
|
||||
writeSet_.swap(set);
|
||||
XRPL_ASSERT(
|
||||
writeSet_.empty(), "xrpl::node_store::BatchWriter::writeBatch : writes not set");
|
||||
writeSet_.empty(), "xrpl::NodeStore::BatchWriter::writeBatch : writes not set");
|
||||
writeLoad_ = set.size();
|
||||
|
||||
if (set.empty())
|
||||
@@ -107,4 +107,4 @@ BatchWriter::waitForWriting()
|
||||
writeCondition_.wait(sl);
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
Database::Database(
|
||||
Scheduler& scheduler,
|
||||
@@ -43,7 +43,7 @@ Database::Database(
|
||||
, requestBundle_(get<int>(config, Keys::kRqBundle, 4))
|
||||
, readThreads_(std::max(1, readThreads))
|
||||
{
|
||||
XRPL_ASSERT(readThreads, "xrpl::node_store::Database::Database : nonzero threads input");
|
||||
XRPL_ASSERT(readThreads, "xrpl::NodeStore::Database::Database : nonzero threads input");
|
||||
|
||||
if (earliestLedgerSeq_ < 1)
|
||||
Throw<std::runtime_error>("Invalid earliest_seq");
|
||||
@@ -89,7 +89,7 @@ Database::Database(
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
!it->second.empty(),
|
||||
"xrpl::node_store::Database::Database : non-empty "
|
||||
"xrpl::NodeStore::Database::Database : non-empty "
|
||||
"data");
|
||||
|
||||
auto const& hash = it->first;
|
||||
@@ -164,7 +164,7 @@ Database::stop()
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
steady_clock::now() - start < 30s,
|
||||
"xrpl::node_store::Database::stop : maximum stop duration");
|
||||
"xrpl::NodeStore::Database::stop : maximum stop duration");
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ Database::importInternal(Backend& dstBackend, Database& srcDB)
|
||||
};
|
||||
|
||||
srcDB.forEach([&](std::shared_ptr<NodeObject> nodeObject) {
|
||||
XRPL_ASSERT(nodeObject, "xrpl::node_store::Database::importInternal : non-null node");
|
||||
XRPL_ASSERT(nodeObject, "xrpl::NodeStore::Database::importInternal : non-null node");
|
||||
if (!nodeObject) // This should never happen
|
||||
return;
|
||||
|
||||
@@ -257,7 +257,7 @@ Database::fetchNodeObject(
|
||||
void
|
||||
Database::getCountsJson(json::Value& obj)
|
||||
{
|
||||
XRPL_ASSERT(obj.isObject(), "xrpl::node_store::Database::getCountsJson : valid input type");
|
||||
XRPL_ASSERT(obj.isObject(), "xrpl::NodeStore::Database::getCountsJson : valid input type");
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> const lock(readLock_);
|
||||
@@ -276,4 +276,4 @@ Database::getCountsJson(json::Value& obj)
|
||||
obj[jss::node_reads_duration_us] = std::to_string(fetchDurationUs_);
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
void
|
||||
DatabaseNodeImp::store(NodeObjectType type, Blob&& data, uint256 const& hash, std::uint32_t)
|
||||
@@ -125,4 +125,4 @@ DatabaseNodeImp::fetchNodeObject(
|
||||
return nodeObject;
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
DatabaseRotatingImp::DatabaseRotatingImp(
|
||||
Scheduler& scheduler,
|
||||
@@ -43,7 +43,7 @@ DatabaseRotatingImp::DatabaseRotatingImp(
|
||||
|
||||
void
|
||||
DatabaseRotatingImp::rotate(
|
||||
std::unique_ptr<node_store::Backend>&& newBackend,
|
||||
std::unique_ptr<NodeStore::Backend>&& newBackend,
|
||||
std::function<void(std::string const& writableName, std::string const& archiveName)> const& f)
|
||||
{
|
||||
// Pass these two names to the callback function
|
||||
@@ -52,7 +52,7 @@ DatabaseRotatingImp::rotate(
|
||||
// Hold on to current archive backend pointer until after the
|
||||
// callback finishes. Only then will the archive directory be
|
||||
// deleted.
|
||||
std::shared_ptr<node_store::Backend> oldArchiveBackend;
|
||||
std::shared_ptr<NodeStore::Backend> oldArchiveBackend;
|
||||
std::uint64_t copyForwards = 0;
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
@@ -232,4 +232,4 @@ DatabaseRotatingImp::forEach(std::function<void(std::shared_ptr<NodeObject>)> f)
|
||||
archive->forEach(f);
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) : key_(key)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) : k
|
||||
std::shared_ptr<NodeObject>
|
||||
DecodedBlob::createObject()
|
||||
{
|
||||
XRPL_ASSERT(success_, "xrpl::node_store::DecodedBlob::createObject : valid object type");
|
||||
XRPL_ASSERT(success_, "xrpl::NodeStore::DecodedBlob::createObject : valid object type");
|
||||
|
||||
std::shared_ptr<NodeObject> object;
|
||||
|
||||
@@ -69,4 +69,4 @@ DecodedBlob::createObject()
|
||||
return object;
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <xrpl/nodestore/Scheduler.h>
|
||||
#include <xrpl/nodestore/Task.h>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
void
|
||||
DummyScheduler::scheduleTask(Task& task)
|
||||
@@ -22,4 +22,4 @@ DummyScheduler::onBatchWrite(BatchWriteReport const& report)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
ManagerImp&
|
||||
ManagerImp::instance()
|
||||
@@ -112,7 +112,7 @@ ManagerImp::erase(Factory& factory)
|
||||
std::scoped_lock const _(mutex_);
|
||||
auto const iter =
|
||||
std::ranges::find_if(list_, [&factory](Factory* other) { return other == &factory; });
|
||||
XRPL_ASSERT(iter != list_.end(), "xrpl::node_store::ManagerImp::erase : valid input");
|
||||
XRPL_ASSERT(iter != list_.end(), "xrpl::NodeStore::ManagerImp::erase : valid input");
|
||||
list_.erase(iter);
|
||||
}
|
||||
|
||||
@@ -135,4 +135,4 @@ Manager::instance()
|
||||
return ManagerImp::instance();
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
struct MemoryDB
|
||||
{
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
Status
|
||||
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pObject) override
|
||||
{
|
||||
XRPL_ASSERT(db_, "xrpl::node_store::MemoryBackend::fetch : non-null database");
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::fetch : non-null database");
|
||||
|
||||
std::scoped_lock const _(db_->mutex);
|
||||
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
void
|
||||
store(std::shared_ptr<NodeObject> const& object) override
|
||||
{
|
||||
XRPL_ASSERT(db_, "xrpl::node_store::MemoryBackend::store : non-null database");
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::store : non-null database");
|
||||
std::scoped_lock const _(db_->mutex);
|
||||
db_->table.emplace(object->getHash(), object);
|
||||
}
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
void
|
||||
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override
|
||||
{
|
||||
XRPL_ASSERT(db_, "xrpl::node_store::MemoryBackend::forEach : non-null database");
|
||||
XRPL_ASSERT(db_, "xrpl::NodeStore::MemoryBackend::forEach : non-null database");
|
||||
for (auto const& e : db_->table)
|
||||
f(e.second);
|
||||
}
|
||||
@@ -216,4 +216,4 @@ MemoryFactory::createInstance(
|
||||
return std::make_unique<MemoryBackend>(keyBytes, keyValues, journal);
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
class NuDBBackend : public Backend
|
||||
{
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"xrpl::node_store::NuDBBackend::open : database is already "
|
||||
"xrpl::NodeStore::NuDBBackend::open : database is already "
|
||||
"open");
|
||||
JLOG(j.error()) << "database is already open";
|
||||
return;
|
||||
@@ -441,4 +441,4 @@ registerNuDBFactory(Manager& manager)
|
||||
static NuDBFactory const kInstance{manager};
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace xrpl::node_store {
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
class NullBackend : public Backend
|
||||
{
|
||||
@@ -125,4 +125,4 @@ registerNullFactory(Manager& manager)
|
||||
static NullFactory const kInstance{manager};
|
||||
}
|
||||
|
||||
} // namespace xrpl::node_store
|
||||
} // namespace xrpl::NodeStore
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user