mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-22 11:37:07 +00:00
Compare commits
51
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7e4d52e38 | ||
|
|
4135d56aa0 | ||
|
|
865557024e | ||
|
|
91b96d6386 | ||
|
|
f1dbb20d7b | ||
|
|
2a2881ee53 | ||
|
|
ee2dff337d | ||
|
|
102a89f351 | ||
|
|
9add957962 | ||
|
|
0f1b607bb4 | ||
|
|
4425f84c1f | ||
|
|
8a6cc3ded8 | ||
|
|
3eec6ffcd7 | ||
|
|
6b56c805dd | ||
|
|
da0eff9c1b | ||
|
|
6e326e6c11 | ||
|
|
405575fd53 | ||
|
|
f38f299a86 | ||
|
|
8951419dbe | ||
|
|
a8b1a01d9e | ||
|
|
994b490db5 | ||
|
|
7c8b16797f | ||
|
|
9507d9c276 | ||
|
|
8ca21406e6 | ||
|
|
178f4248e4 | ||
|
|
e8069a40f2 | ||
|
|
5ebc29c481 | ||
|
|
224b055124 | ||
|
|
f99c1158d5 | ||
|
|
a2594b6fe0 | ||
|
|
12fb54c66e | ||
|
|
51917be96d | ||
|
|
97b8f5c4b3 | ||
|
|
a127314a89 | ||
|
|
0754cca98c | ||
|
|
eb66ae1bd4 | ||
|
|
5c3b44d1af | ||
|
|
e4b334faba | ||
|
|
adad20b862 | ||
|
|
9907fa07a9 | ||
|
|
d032bd681a | ||
|
|
b444457c19 | ||
|
|
4f076cb955 | ||
|
|
220ab26225 | ||
|
|
89d81655c6 | ||
|
|
7bc2d5cba4 | ||
|
|
a34b36e021 | ||
|
|
5b2ab905c0 | ||
|
|
5e43e91d4a | ||
|
|
5bac21c05b | ||
|
|
1643d22103 |
No files matched your search
@@ -10,10 +10,17 @@ inputs:
|
||||
build_type:
|
||||
description: 'The build type to use ("Debug", "Release").'
|
||||
required: true
|
||||
build_nproc:
|
||||
description: "The number of processors to use for building."
|
||||
required: true
|
||||
force_build:
|
||||
description: 'Force building of all dependencies ("true", "false").'
|
||||
required: false
|
||||
default: "false"
|
||||
log_verbosity:
|
||||
description: "The logging verbosity."
|
||||
required: false
|
||||
default: "verbose"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
@@ -22,16 +29,21 @@ runs:
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
BUILD_NPROC: ${{ inputs.build_nproc }}
|
||||
BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
LOG_VERBOSITY: ${{ inputs.log_verbosity }}
|
||||
run: |
|
||||
echo 'Installing dependencies.'
|
||||
mkdir -p '${{ env.BUILD_DIR }}'
|
||||
cd '${{ env.BUILD_DIR }}'
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
cd "${BUILD_DIR}"
|
||||
conan install \
|
||||
--output-folder . \
|
||||
--build=${{ env.BUILD_OPTION }} \
|
||||
--build="${BUILD_OPTION}" \
|
||||
--options:host='&:tests=True' \
|
||||
--options:host='&:xrpld=True' \
|
||||
--settings:all build_type='${{ env.BUILD_TYPE }}' \
|
||||
--settings:all build_type="${BUILD_TYPE}" \
|
||||
--conf:all tools.build:jobs=${BUILD_NPROC} \
|
||||
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
|
||||
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
|
||||
..
|
||||
@@ -39,8 +39,8 @@ runs:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
CONAN_REMOTE_URL: ${{ inputs.conan_remote_url }}
|
||||
run: |
|
||||
echo "Adding Conan remote '${{ env.CONAN_REMOTE_NAME }}' at '${{ env.CONAN_REMOTE_URL }}'."
|
||||
conan remote add --index 0 --force '${{ env.CONAN_REMOTE_NAME }}' '${{ env.CONAN_REMOTE_URL }}'
|
||||
echo "Adding Conan remote '${CONAN_REMOTE_NAME}' at '${CONAN_REMOTE_URL}'."
|
||||
conan remote add --index 0 --force "${CONAN_REMOTE_NAME}" "${CONAN_REMOTE_URL}"
|
||||
|
||||
echo 'Listing Conan remotes.'
|
||||
conan remote list
|
||||
@@ -138,6 +138,7 @@ test.toplevel > test.csf
|
||||
test.toplevel > xrpl.json
|
||||
test.unit_test > xrpl.basics
|
||||
tests.libxrpl > xrpl.basics
|
||||
tests.libxrpl > xrpl.json
|
||||
tests.libxrpl > xrpl.net
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
|
||||
@@ -74,14 +74,14 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# RHEL:
|
||||
# - 9.4 using GCC 12: Debug and Unity on linux/amd64.
|
||||
# - 9.6 using Clang: Release and no Unity on linux/amd64.
|
||||
# - 9 using GCC 12: Debug and Unity on linux/amd64.
|
||||
# - 10 using Clang: Release and no Unity on linux/amd64.
|
||||
if os['distro_name'] == 'rhel':
|
||||
skip = True
|
||||
if os['distro_version'] == '9.4':
|
||||
if os['distro_version'] == '9':
|
||||
if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-12' and build_type == 'Debug' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64':
|
||||
skip = False
|
||||
elif os['distro_version'] == '9.6':
|
||||
elif os['distro_version'] == '10':
|
||||
if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-any' and build_type == 'Release' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64':
|
||||
skip = False
|
||||
if skip:
|
||||
@@ -138,8 +138,6 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# Unity on linux/amd64
|
||||
if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-15' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64':
|
||||
cmake_args = f'-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0 {cmake_args}'
|
||||
cmake_target = 'coverage'
|
||||
build_only = True
|
||||
|
||||
# Generate a unique name for the configuration, e.g. macos-arm64-debug
|
||||
# or debian-bookworm-gcc-12-amd64-release-unity.
|
||||
|
||||
@@ -14,139 +14,169 @@
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12"
|
||||
"compiler_version": "12",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13"
|
||||
"compiler_version": "13",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14"
|
||||
"compiler_version": "14",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "15"
|
||||
"compiler_version": "15",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16"
|
||||
"compiler_version": "16",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17"
|
||||
"compiler_version": "17",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18"
|
||||
"compiler_version": "18",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19"
|
||||
"compiler_version": "19",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "20"
|
||||
"compiler_version": "20",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.4",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12"
|
||||
"compiler_version": "14",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.4",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.4",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.6",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.6",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.4",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any"
|
||||
"compiler_version": "any",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9.6",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any"
|
||||
"compiler_version": "any",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "jammy",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12"
|
||||
"compiler_version": "12",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13"
|
||||
"compiler_version": "13",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14"
|
||||
"compiler_version": "14",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16"
|
||||
"compiler_version": "16",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17"
|
||||
"compiler_version": "17",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18"
|
||||
"compiler_version": "18",
|
||||
"image_sha": "97ba375"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19"
|
||||
"compiler_version": "19",
|
||||
"image_sha": "97ba375"
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
"distro_name": "macos",
|
||||
"distro_version": "",
|
||||
"compiler_name": "",
|
||||
"compiler_version": ""
|
||||
"compiler_version": "",
|
||||
"image_sha": ""
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
"distro_name": "windows",
|
||||
"distro_version": "",
|
||||
"compiler_name": "",
|
||||
"compiler_version": ""
|
||||
"compiler_version": "",
|
||||
"image_sha": ""
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
|
||||
@@ -103,6 +103,7 @@ jobs:
|
||||
if: ${{ needs.should-run.outputs.go == 'true' }}
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [linux, macos, windows]
|
||||
with:
|
||||
|
||||
@@ -9,9 +9,9 @@ name: Trigger
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- release
|
||||
- master
|
||||
- "develop"
|
||||
- "release*"
|
||||
- "master"
|
||||
paths:
|
||||
# These paths are unique to `on-trigger.yml`.
|
||||
- ".github/workflows/reusable-check-missing-commits.yml"
|
||||
@@ -50,7 +50,12 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
# When a PR is merged into the develop branch it will be assigned a unique
|
||||
# group identifier, so execution will continue even if another PR is merged
|
||||
# while it is still running. In all other cases the group identifier is shared
|
||||
# per branch, so that any in-progress runs are cancelled when a new commit is
|
||||
# pushed.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' && github.sha || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
@@ -65,6 +70,7 @@ jobs:
|
||||
build-test:
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
strategy:
|
||||
fail-fast: ${{ github.event_name == 'merge_group' }}
|
||||
matrix:
|
||||
os: [linux, macos, windows]
|
||||
with:
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@af1b0f0d764cda2e5435f5ac97b240d4bd4d95d3
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@34790936fae4c6c751f62ec8c06696f9c1a5753a
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-d1496b8" }'
|
||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'
|
||||
@@ -23,16 +23,24 @@ defaults:
|
||||
|
||||
env:
|
||||
BUILD_DIR: .build
|
||||
NPROC_SUBTRACT: 2
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-d1496b8
|
||||
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-a8c7be1
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
||||
|
||||
- name: Check configuration
|
||||
run: |
|
||||
echo 'Checking path.'
|
||||
@@ -46,12 +54,16 @@ jobs:
|
||||
|
||||
echo 'Checking Doxygen version.'
|
||||
doxygen --version
|
||||
|
||||
- name: Build documentation
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
mkdir -p ${{ env.BUILD_DIR }}
|
||||
cd ${{ env.BUILD_DIR }}
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
cd "${BUILD_DIR}"
|
||||
cmake -Donly_docs=ON ..
|
||||
cmake --build . --target docs --parallel $(nproc)
|
||||
cmake --build . --target docs --parallel ${BUILD_NPROC}
|
||||
|
||||
- name: Publish documentation
|
||||
if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }}
|
||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||
|
||||
@@ -7,19 +7,23 @@ on:
|
||||
description: "The directory where to build."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
build_only:
|
||||
description: 'Whether to only build or to build and test the code ("true", "false").'
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
build_type:
|
||||
description: 'The build type to use ("Debug", "Release").'
|
||||
type: string
|
||||
required: true
|
||||
|
||||
cmake_args:
|
||||
description: "Additional arguments to pass to CMake."
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
cmake_target:
|
||||
description: "The CMake target to build."
|
||||
type: string
|
||||
@@ -29,6 +33,7 @@ on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
@@ -39,31 +44,170 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
nproc_subtract:
|
||||
description: "The number of processors to subtract when calculating parallelism."
|
||||
required: false
|
||||
type: number
|
||||
default: 2
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/reusable-build.yml
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
cmake_args: ${{ inputs.cmake_args }}
|
||||
cmake_target: ${{ inputs.cmake_target }}
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
image: ${{ inputs.image }}
|
||||
config_name: ${{ inputs.config_name }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
test:
|
||||
needs: build
|
||||
uses: ./.github/workflows/reusable-test.yml
|
||||
with:
|
||||
run_tests: ${{ !inputs.build_only }}
|
||||
verify_voidstar: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
runs_on: ${{ inputs.runs_on }}
|
||||
image: ${{ inputs.image }}
|
||||
config_name: ${{ inputs.config_name }}
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
ENABLED_VOIDSTAR: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
ENABLED_COVERAGE: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }}
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||
with:
|
||||
disable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ inputs.nproc_subtract }}
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
uses: ./.github/actions/build-deps
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||
${CMAKE_ARGS} \
|
||||
..
|
||||
|
||||
- name: Build the binary
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target "${CMAKE_TARGET}"
|
||||
|
||||
- name: Upload rippled artifact (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.build_dir }}
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
path: ${{ env.BUILD_DIR }}/rippled
|
||||
retention-days: 3
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Check linking (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
run: |
|
||||
ldd ./rippled
|
||||
if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
|
||||
echo 'The binary is statically linked.'
|
||||
else
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify presence of instrumentation (Linux)
|
||||
if: ${{ runner.os == 'Linux' && env.ENABLED_VOIDSTAR == 'true' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
run: |
|
||||
./rippled --version | grep libvoidstar
|
||||
|
||||
- name: Run the separate tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
# Windows locks some of the build files while running tests, and parallel jobs can collide
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
ctest \
|
||||
--output-on-failure \
|
||||
-C "${BUILD_TYPE}" \
|
||||
-j "${PARALLELISM}"
|
||||
|
||||
- name: Run the embedded tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', inputs.build_dir, inputs.build_type) || inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
run: |
|
||||
./rippled --unittest --unittest-jobs "${BUILD_NPROC}"
|
||||
|
||||
- name: Debug failure (Linux)
|
||||
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
|
||||
run: |
|
||||
echo "IPv4 local port range:"
|
||||
cat /proc/sys/net/ipv4/ip_local_port_range
|
||||
echo "Netstat:"
|
||||
netstat -an
|
||||
|
||||
- name: Prepare coverage report
|
||||
if: ${{ !inputs.build_only && env.ENABLED_COVERAGE == 'true' }}
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config "${BUILD_TYPE}" \
|
||||
--parallel "${BUILD_NPROC}" \
|
||||
--target coverage
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.ENABLED_COVERAGE == 'true' }}
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: ${{ inputs.build_dir }}/coverage.xml
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
- generate-matrix
|
||||
uses: ./.github/workflows/reusable-build-test-config.yml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
fail-fast: ${{ github.event_name == 'merge_group' }}
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
max-parallel: 10
|
||||
with:
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
cmake_args: ${{ matrix.cmake_args }}
|
||||
cmake_target: ${{ matrix.cmake_target }}
|
||||
runs_on: ${{ toJSON(matrix.architecture.runner) }}
|
||||
image: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-5dd7158', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version) || '' }}
|
||||
image: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || '' }}
|
||||
config_name: ${{ matrix.config_name }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -1,121 +0,0 @@
|
||||
name: Build rippled
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
build_dir:
|
||||
description: "The directory where to build."
|
||||
required: true
|
||||
type: string
|
||||
build_type:
|
||||
description: 'The build type to use ("Debug", "Release").'
|
||||
required: true
|
||||
type: string
|
||||
cmake_args:
|
||||
description: "Additional arguments to pass to CMake."
|
||||
required: true
|
||||
type: string
|
||||
cmake_target:
|
||||
description: "The CMake target to build."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
runs_on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
config_name:
|
||||
description: "The name of the configuration."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
required: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
||||
with:
|
||||
disable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
- name: Build dependencies
|
||||
uses: ./.github/actions/build-deps
|
||||
with:
|
||||
build_dir: ${{ inputs.build_dir }}
|
||||
build_type: ${{ inputs.build_type }}
|
||||
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
${{ env.CMAKE_ARGS }} \
|
||||
..
|
||||
|
||||
- name: Build the binary
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.build_dir }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
cmake \
|
||||
--build . \
|
||||
--config ${{ env.BUILD_TYPE }} \
|
||||
--parallel $(nproc) \
|
||||
--target ${{ env.CMAKE_TARGET }}
|
||||
|
||||
- name: Upload rippled artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
path: ${{ inputs.build_dir }}/${{ runner.os == 'Windows' && inputs.build_type || '' }}/rippled${{ runner.os == 'Windows' && '.exe' || '' }}
|
||||
retention-days: 3
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ inputs.cmake_target == 'coverage' }}
|
||||
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: ${{ inputs.build_dir }}/coverage.xml
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
run: |
|
||||
echo 'Generating user and channel.'
|
||||
echo "user=clio" >> "${GITHUB_OUTPUT}"
|
||||
echo "channel=pr_${{ env.PR_NUMBER }}" >> "${GITHUB_OUTPUT}"
|
||||
echo "channel=pr_${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
|
||||
echo 'Extracting version.'
|
||||
echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}"
|
||||
- name: Calculate conan reference
|
||||
@@ -64,13 +64,15 @@ jobs:
|
||||
conan_remote_name: ${{ inputs.conan_remote_name }}
|
||||
conan_remote_url: ${{ inputs.conan_remote_url }}
|
||||
- name: Log into Conan remote
|
||||
run: conan remote login ${{ inputs.conan_remote_name }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
|
||||
env:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
|
||||
- name: Upload package
|
||||
env:
|
||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
||||
run: |
|
||||
conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} .
|
||||
conan upload --confirm --check --remote=${{ env.CONAN_REMOTE_NAME }} xrpl/${{ steps.conan_ref.outputs.conan_ref }}
|
||||
conan upload --confirm --check --remote="${CONAN_REMOTE_NAME}" xrpl/${{ steps.conan_ref.outputs.conan_ref }}
|
||||
outputs:
|
||||
conan_ref: ${{ steps.conan_ref.outputs.conan_ref }}
|
||||
|
||||
@@ -86,4 +88,4 @@ jobs:
|
||||
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||
-F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \
|
||||
-F "client_payload[pr_url]=${{ env.PR_URL }}"
|
||||
-F "client_payload[pr_url]=${PR_URL}"
|
||||
@@ -18,6 +18,10 @@ on:
|
||||
description: "The generated strategy matrix."
|
||||
value: ${{ jobs.generate-matrix.outputs.matrix }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -38,4 +42,4 @@ jobs:
|
||||
env:
|
||||
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
|
||||
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
|
||||
run: ./generate.py ${{ env.GENERATE_OPTION }} ${{ env.GENERATE_CONFIG }} >> "${GITHUB_OUTPUT}"
|
||||
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"
|
||||
@@ -1,69 +0,0 @@
|
||||
name: Test rippled
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
verify_voidstar:
|
||||
description: "Whether to verify the presence of voidstar instrumentation."
|
||||
required: true
|
||||
type: boolean
|
||||
run_tests:
|
||||
description: "Whether to run unit tests"
|
||||
required: true
|
||||
type: boolean
|
||||
|
||||
runs_on:
|
||||
description: Runner to run the job on as a JSON string
|
||||
required: true
|
||||
type: string
|
||||
image:
|
||||
description: "The image to run in (leave empty to run natively)"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
config_name:
|
||||
description: "The name of the configuration."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test ${{ inputs.config_name }}
|
||||
runs-on: ${{ fromJSON(inputs.runs_on) }}
|
||||
container: ${{ inputs.image != '' && inputs.image || null }}
|
||||
steps:
|
||||
- name: Download rippled artifact
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
name: rippled-${{ inputs.config_name }}
|
||||
|
||||
- name: Make binary executable (Linux and macOS)
|
||||
shell: bash
|
||||
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
|
||||
run: |
|
||||
chmod +x ./rippled
|
||||
|
||||
- name: Check linking (Linux)
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
shell: bash
|
||||
run: |
|
||||
ldd ./rippled
|
||||
if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
|
||||
echo 'The binary is statically linked.'
|
||||
else
|
||||
echo 'The binary is dynamically linked.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verifying presence of instrumentation
|
||||
if: ${{ inputs.verify_voidstar }}
|
||||
shell: bash
|
||||
run: |
|
||||
./rippled --version | grep libvoidstar
|
||||
|
||||
- name: Test the binary
|
||||
if: ${{ inputs.run_tests }}
|
||||
shell: bash
|
||||
run: |
|
||||
./rippled --unittest --unittest-jobs $(nproc)
|
||||
ctest -j $(nproc) --output-on-failure
|
||||
@@ -34,17 +34,24 @@ on:
|
||||
env:
|
||||
CONAN_REMOTE_NAME: xrplf
|
||||
CONAN_REMOTE_URL: https://conan.ripplex.io
|
||||
NPROC_SUBTRACT: 2
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
# Generate the strategy matrix to be used by the following job.
|
||||
generate-matrix:
|
||||
uses: ./.github/workflows/reusable-strategy-matrix.yml
|
||||
with:
|
||||
strategy_matrix: ${{ github.event_name == 'pull_request' && 'minimal' || 'all' }}
|
||||
|
||||
# Build and upload the dependencies for each configuration.
|
||||
run-upload-conan-deps:
|
||||
needs:
|
||||
- generate-matrix
|
||||
@@ -53,19 +60,29 @@ jobs:
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
max-parallel: 10
|
||||
runs-on: ${{ matrix.architecture.runner }}
|
||||
container: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-5dd7158', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version) || null }}
|
||||
|
||||
container: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || null }}
|
||||
steps:
|
||||
- name: Cleanup workspace
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||
|
||||
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
||||
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||
with:
|
||||
disable_ccache: false
|
||||
|
||||
- name: Print build environment
|
||||
uses: ./.github/actions/print-env
|
||||
|
||||
- name: Get number of processors
|
||||
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
|
||||
id: nproc
|
||||
with:
|
||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
with:
|
||||
@@ -76,15 +93,19 @@ jobs:
|
||||
uses: ./.github/actions/build-deps
|
||||
with:
|
||||
build_dir: .build
|
||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
||||
build_type: ${{ matrix.build_type }}
|
||||
force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
|
||||
# Set the verbosity to "quiet" for Windows to avoid an excessive
|
||||
# amount of logs. For other OSes, the "verbose" logs are more useful.
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
|
||||
- name: Log into Conan remote
|
||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' }}
|
||||
run: conan remote login ${{ env.CONAN_REMOTE_NAME }} "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
|
||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
|
||||
|
||||
- name: Upload Conan packages
|
||||
if: ${{ github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule' }}
|
||||
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
env:
|
||||
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
||||
run: conan upload "*" --remote='${{ env.CONAN_REMOTE_NAME }}' --confirm ${{ env.FORCE_OPTION }}
|
||||
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
|
||||
@@ -39,17 +39,12 @@ found here](./docs/build/environment.md).
|
||||
|
||||
- [Python 3.11](https://www.python.org/downloads/), or higher
|
||||
- [Conan 2.17](https://conan.io/downloads.html)[^1], or higher
|
||||
- [CMake 3.22](https://cmake.org/download/)[^2], or higher
|
||||
- [CMake 3.22](https://cmake.org/download/), or higher
|
||||
|
||||
[^1]:
|
||||
It is possible to build with Conan 1.60+, but the instructions are
|
||||
significantly different, which is why we are not recommending it.
|
||||
|
||||
[^2]:
|
||||
CMake 4 is not yet supported by all dependencies required by this project.
|
||||
If you are affected by this issue, follow [conan workaround for cmake
|
||||
4](#workaround-for-cmake-4)
|
||||
|
||||
`rippled` is written in the C++20 dialect and includes the `<concepts>` header.
|
||||
The [minimum compiler versions][2] required are:
|
||||
|
||||
@@ -282,21 +277,6 @@ sed -i.bak -e 's|^arch=.*$|arch=x86_64|' $(conan config home)/profiles/default
|
||||
sed -i.bak -e 's|^compiler\.runtime=.*$|compiler.runtime=static|' $(conan config home)/profiles/default
|
||||
```
|
||||
|
||||
#### Workaround for CMake 4
|
||||
|
||||
If your system CMake is version 4 rather than 3, you may have to configure Conan
|
||||
profile to use CMake version 3 for dependencies, by adding the following two
|
||||
lines to your profile:
|
||||
|
||||
```text
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/[>=3 <4]
|
||||
```
|
||||
|
||||
This will force Conan to download and use a locally cached CMake 3 version, and
|
||||
is needed because some of the dependencies used by this project do not support
|
||||
CMake 4.
|
||||
|
||||
#### Clang workaround for grpc
|
||||
|
||||
If your compiler is clang, version 19 or later, or apple-clang, version 17 or
|
||||
@@ -515,18 +495,18 @@ A coverage report is created when the following steps are completed, in order:
|
||||
|
||||
1. `rippled` binary built with instrumentation data, enabled by the `coverage`
|
||||
option mentioned above
|
||||
2. completed run of unit tests, which populates coverage capture data
|
||||
2. completed one or more run of the unit tests, which populates coverage capture data
|
||||
3. completed run of the `gcovr` tool (which internally invokes either `gcov` or `llvm-cov`)
|
||||
to assemble both instrumentation data and the coverage capture data into a coverage report
|
||||
|
||||
The above steps are automated into a single target `coverage`. The instrumented
|
||||
The last step of the above is automated into a single target `coverage`. The instrumented
|
||||
`rippled` binary can also be used for regular development or testing work, at
|
||||
the cost of extra disk space utilization and a small performance hit
|
||||
(to store coverage capture). In case of a spurious failure of unit tests, it is
|
||||
possible to re-run the `coverage` target without rebuilding the `rippled` binary
|
||||
(since it is simply a dependency of the coverage report target). It is also possible
|
||||
to select only specific tests for the purpose of the coverage report, by setting
|
||||
the `coverage_test` variable in `cmake`
|
||||
(to store coverage capture data). Since `rippled` binary is simply a dependency of the
|
||||
coverage report target, it is possible to re-run the `coverage` target without
|
||||
rebuilding the `rippled` binary. Note, running of the unit tests before the `coverage`
|
||||
target is left to the developer. Each such run will append to the coverage data
|
||||
collected in the build directory.
|
||||
|
||||
The default coverage report format is `html-details`, but the user
|
||||
can override it to any of the formats listed in `Builds/CMake/CodeCoverage.cmake`
|
||||
@@ -535,11 +515,6 @@ to generate more than one format at a time by setting the `coverage_extra_args`
|
||||
variable in `cmake`. The specific command line used to run the `gcovr` tool will be
|
||||
displayed if the `CODE_COVERAGE_VERBOSE` variable is set.
|
||||
|
||||
By default, the code coverage tool runs parallel unit tests with `--unittest-jobs`
|
||||
set to the number of available CPU cores. This may cause spurious test
|
||||
errors on Apple. Developers can override the number of unit test jobs with
|
||||
the `coverage_test_parallelism` variable in `cmake`.
|
||||
|
||||
Example use with some cmake variables set:
|
||||
|
||||
```
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
macro(group_sources_in source_dir curdir)
|
||||
file(GLOB children RELATIVE ${source_dir}/${curdir}
|
||||
${source_dir}/${curdir}/*)
|
||||
foreach (child ${children})
|
||||
if (IS_DIRECTORY ${source_dir}/${curdir}/${child})
|
||||
group_sources_in(${source_dir} ${curdir}/${child})
|
||||
else()
|
||||
string(REPLACE "/" "\\" groupname ${curdir})
|
||||
source_group(${groupname} FILES
|
||||
${source_dir}/${curdir}/${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(group_sources curdir)
|
||||
group_sources_in(${PROJECT_SOURCE_DIR} ${curdir})
|
||||
endmacro()
|
||||
|
||||
macro (exclude_from_default target_)
|
||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||
|
||||
+20
-10
@@ -109,6 +109,9 @@
|
||||
# - add a new function add_code_coverage_to_target
|
||||
# - remove some unused code
|
||||
#
|
||||
# 2025-11-11, Bronek Kozicki
|
||||
# - make EXECUTABLE and EXECUTABLE_ARGS optional
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
@@ -317,6 +320,10 @@ function(setup_target_for_coverage_gcovr)
|
||||
set(Coverage_FORMAT xml)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED Coverage_EXECUTABLE AND DEFINED Coverage_EXECUTABLE_ARGS)
|
||||
message(FATAL_ERROR "EXECUTABLE_ARGS must not be set if EXECUTABLE is not set")
|
||||
endif()
|
||||
|
||||
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
||||
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
|
||||
else()
|
||||
@@ -398,17 +405,18 @@ function(setup_target_for_coverage_gcovr)
|
||||
endforeach()
|
||||
|
||||
# Set up commands which will be run to generate coverage data
|
||||
# Run tests
|
||||
set(GCOVR_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
# If EXECUTABLE is not set, the user is expected to run the tests manually
|
||||
# before running the coverage target NAME
|
||||
if(DEFINED Coverage_EXECUTABLE)
|
||||
set(GCOVR_EXEC_TESTS_CMD
|
||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create folder
|
||||
if(DEFINED GCOVR_CREATE_FOLDER)
|
||||
set(GCOVR_FOLDER_CMD
|
||||
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
|
||||
else()
|
||||
set(GCOVR_FOLDER_CMD echo) # dummy
|
||||
endif()
|
||||
|
||||
# Running gcovr
|
||||
@@ -425,11 +433,13 @@ function(setup_target_for_coverage_gcovr)
|
||||
if(CODE_COVERAGE_VERBOSE)
|
||||
message(STATUS "Executed command report")
|
||||
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||
if(NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
|
||||
message(STATUS "Command to run tests: ")
|
||||
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||
endif()
|
||||
|
||||
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
|
||||
if(NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
|
||||
message(STATUS "Command to create a folder: ")
|
||||
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
|
||||
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
||||
|
||||
@@ -12,7 +12,7 @@ if (static OR MSVC)
|
||||
else ()
|
||||
set (Boost_USE_STATIC_RUNTIME OFF)
|
||||
endif ()
|
||||
find_dependency (Boost 1.70
|
||||
find_dependency (Boost
|
||||
COMPONENTS
|
||||
chrono
|
||||
container
|
||||
@@ -52,5 +52,3 @@ if (TARGET ZLIB::ZLIB)
|
||||
set_target_properties(OpenSSL::Crypto PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
||||
endif ()
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/RippleTargets.cmake")
|
||||
@@ -72,10 +72,7 @@ include(target_link_modules)
|
||||
|
||||
# Level 01
|
||||
add_module(xrpl beast)
|
||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC
|
||||
xrpl.imports.main
|
||||
xrpl.libpb
|
||||
)
|
||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
|
||||
|
||||
# Level 02
|
||||
add_module(xrpl basics)
|
||||
|
||||
@@ -11,6 +11,9 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
|
||||
include(CodeCoverage)
|
||||
|
||||
# The instructions for these commands come from the `CodeCoverage` module,
|
||||
@@ -26,15 +29,13 @@ list(APPEND GCOVR_ADDITIONAL_ARGS
|
||||
--exclude-throw-branches
|
||||
--exclude-noncode-lines
|
||||
--exclude-unreachable-branches -s
|
||||
-j ${coverage_test_parallelism})
|
||||
-j ${PROCESSOR_COUNT})
|
||||
|
||||
setup_target_for_coverage_gcovr(
|
||||
NAME coverage
|
||||
FORMAT ${coverage_format}
|
||||
EXECUTABLE rippled
|
||||
EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
|
||||
EXCLUDE "src/test" "src/tests" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
||||
DEPENDENCIES rippled
|
||||
DEPENDENCIES rippled xrpl.tests
|
||||
)
|
||||
|
||||
add_code_coverage_to_target(opts INTERFACE)
|
||||
@@ -1,5 +1,5 @@
|
||||
#[===================================================================[
|
||||
convenience variables and sanity checks
|
||||
sanity checks
|
||||
#]===================================================================]
|
||||
|
||||
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
@@ -16,39 +16,19 @@ if (NOT is_multiconfig)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||
if (has_parent)
|
||||
set (is_root_project OFF)
|
||||
else ()
|
||||
set (is_root_project ON)
|
||||
endif ()
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
|
||||
set (is_clang TRUE)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
message (FATAL_ERROR "This project requires clang 8 or later")
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
|
||||
message (FATAL_ERROR "This project requires clang 16 or later")
|
||||
endif ()
|
||||
# TODO min AppleClang version check ?
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set (is_gcc TRUE)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
message (FATAL_ERROR "This project requires GCC 8 or later")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||
message (FATAL_ERROR "This project requires GCC 12 or later")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (is_linux TRUE)
|
||||
else ()
|
||||
set (is_linux FALSE)
|
||||
endif ()
|
||||
|
||||
if ("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
||||
set (is_ci TRUE)
|
||||
else ()
|
||||
set (is_ci FALSE)
|
||||
endif ()
|
||||
|
||||
# check for in-source build and fail
|
||||
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
message (FATAL_ERROR "Builds (in-source) are not allowed in "
|
||||
|
||||
+28
-24
@@ -1,10 +1,25 @@
|
||||
#[===================================================================[
|
||||
declare user options/settings
|
||||
declare options and variables
|
||||
#]===================================================================]
|
||||
|
||||
include(ProcessorCount)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (is_linux TRUE)
|
||||
else()
|
||||
set(is_linux FALSE)
|
||||
endif()
|
||||
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
||||
set(is_ci TRUE)
|
||||
else()
|
||||
set(is_ci FALSE)
|
||||
endif()
|
||||
|
||||
get_directory_property(has_parent PARENT_DIRECTORY)
|
||||
if(has_parent)
|
||||
set(is_root_project OFF)
|
||||
else()
|
||||
set(is_root_project ON)
|
||||
endif()
|
||||
|
||||
option(assert "Enables asserts, even in release builds" OFF)
|
||||
|
||||
@@ -25,29 +40,28 @@ if(unity)
|
||||
endif()
|
||||
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
|
||||
endif()
|
||||
|
||||
if(is_clang AND is_linux)
|
||||
option(voidstar "Enable Antithesis instrumentation." OFF)
|
||||
endif()
|
||||
|
||||
if(is_gcc OR is_clang)
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(PROCESSOR_COUNT)
|
||||
|
||||
option(coverage "Generates coverage info." OFF)
|
||||
option(profile "Add profiling flags" OFF)
|
||||
set(coverage_test_parallelism "${PROCESSOR_COUNT}" CACHE STRING
|
||||
"Unit tests parallelism for the purpose of coverage report.")
|
||||
set(coverage_format "html-details" CACHE STRING
|
||||
"Output format of the coverage report.")
|
||||
set(coverage_extra_args "" CACHE STRING
|
||||
"Additional arguments to pass to gcovr.")
|
||||
set(coverage_test "" CACHE STRING
|
||||
"On gcc & clang, the specific unit test(s) to run for coverage. Default is all tests.")
|
||||
if(coverage_test AND NOT coverage)
|
||||
set(coverage ON CACHE BOOL "gcc/clang only" FORCE)
|
||||
endif()
|
||||
option(wextra "compile with extra gcc/clang warnings enabled" ON)
|
||||
else()
|
||||
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||
set(coverage OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||
endif()
|
||||
|
||||
if(is_linux)
|
||||
option(BUILD_SHARED_LIBS "build shared ripple libraries" OFF)
|
||||
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
||||
@@ -64,11 +78,13 @@ else()
|
||||
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
|
||||
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
|
||||
endif()
|
||||
|
||||
if(is_clang)
|
||||
option(use_lld "enables detection of lld linker" ON)
|
||||
else()
|
||||
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
||||
endif()
|
||||
|
||||
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
||||
option(werr "treat warnings as errors" OFF)
|
||||
option(local_protobuf
|
||||
@@ -102,38 +118,26 @@ if(san)
|
||||
message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
|
||||
endif()
|
||||
endif()
|
||||
set(container_label "" CACHE STRING "tag to use for package building containers")
|
||||
option(packages_only
|
||||
"ONLY generate package building targets. This is special use-case and almost \
|
||||
certainly not what you want. Use with caution as you won't be able to build \
|
||||
any compiled targets locally." OFF)
|
||||
option(have_package_container
|
||||
"Sometimes you already have the tagged container you want to use for package \
|
||||
building and you don't want docker to rebuild it. This flag will detach the \
|
||||
dependency of the package build from the container build. It's an advanced \
|
||||
use case and most likely you should not be touching this flag." OFF)
|
||||
|
||||
# the remaining options are obscure and rarely used
|
||||
option(beast_no_unit_test_inline
|
||||
"Prevents unit test definitions from being inserted into global table"
|
||||
OFF)
|
||||
option(single_io_service_thread
|
||||
"Restricts the number of threads calling io_context::run to one. \
|
||||
"Restricts the number of threads calling io_service::run to one. \
|
||||
This can be useful when debugging."
|
||||
OFF)
|
||||
option(boost_show_deprecated
|
||||
"Allow boost to fail on deprecated usage. Only useful if you're trying\
|
||||
to find deprecated calls."
|
||||
OFF)
|
||||
option(beast_hashers
|
||||
"Use local implementations for sha/ripemd hashes (experimental, not recommended)"
|
||||
OFF)
|
||||
|
||||
if(WIN32)
|
||||
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
|
||||
else()
|
||||
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
|
||||
endif()
|
||||
|
||||
if(coverage)
|
||||
message(STATUS "coverage build requested - forcing Debug build")
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
||||
|
||||
@@ -24,7 +24,6 @@ target_link_libraries(ripple_boost
|
||||
Boost::date_time
|
||||
Boost::filesystem
|
||||
Boost::json
|
||||
Boost::process
|
||||
Boost::program_options
|
||||
Boost::regex
|
||||
Boost::system
|
||||
|
||||
@@ -7,7 +7,7 @@ function(xrpl_add_test name)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
|
||||
)
|
||||
add_executable(${target} EXCLUDE_FROM_ALL ${ARGN} ${sources})
|
||||
add_executable(${target} ${ARGN} ${sources})
|
||||
|
||||
isolate_headers(
|
||||
${target}
|
||||
@@ -22,20 +22,4 @@ function(xrpl_add_test name)
|
||||
UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
|
||||
|
||||
add_test(NAME ${target} COMMAND ${target})
|
||||
set_tests_properties(
|
||||
${target} PROPERTIES
|
||||
FIXTURES_REQUIRED ${target}_fixture
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME ${target}.build
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
--build ${CMAKE_BINARY_DIR}
|
||||
--config $<CONFIG>
|
||||
--target ${target}
|
||||
)
|
||||
set_tests_properties(${target}.build PROPERTIES
|
||||
FIXTURES_SETUP ${target}_fixture
|
||||
)
|
||||
endfunction()
|
||||
+2
-2
@@ -21,7 +21,7 @@
|
||||
"date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
|
||||
"c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
|
||||
"bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
|
||||
"boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326",
|
||||
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
|
||||
"abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
|
||||
],
|
||||
"build_requires": [
|
||||
@@ -46,7 +46,7 @@
|
||||
"lz4/1.10.0"
|
||||
],
|
||||
"boost/1.83.0": [
|
||||
"boost/1.88.0"
|
||||
"boost/1.83.0"
|
||||
],
|
||||
"sqlite3/3.44.2": [
|
||||
"sqlite3/3.49.1"
|
||||
|
||||
+1
-5
@@ -1,9 +1,5 @@
|
||||
# Global configuration for Conan. This is used to set the number of parallel
|
||||
# downloads, uploads, and build jobs. The verbosity is set to verbose to
|
||||
# provide more information during the build process.
|
||||
# downloads and uploads.
|
||||
core:non_interactive=True
|
||||
core.download:parallel={{ os.cpu_count() }}
|
||||
core.upload:parallel={{ os.cpu_count() }}
|
||||
tools.build:jobs={{ (os.cpu_count() * 4/5) | int }}
|
||||
tools.build:verbosity=verbose
|
||||
tools.compilation:verbosity=verbose
|
||||
@@ -21,14 +21,14 @@ compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
|
||||
|
||||
[conf]
|
||||
{% if compiler == "clang" and compiler_version >= 19 %}
|
||||
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "apple-clang" and compiler_version >= 17 %}
|
||||
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
||||
{% endif %}
|
||||
{% if compiler == "clang" and compiler_version == 16 %}
|
||||
tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS']
|
||||
{% endif %}
|
||||
{% if compiler == "gcc" and compiler_version < 13 %}
|
||||
tools.build:cxxflags=['-Wno-restrict']
|
||||
tools.build:cxxflags+=['-Wno-restrict']
|
||||
{% endif %}
|
||||
|
||||
[tool_requires]
|
||||
!cmake/*: cmake/[>=3 <4]
|
||||
+1
-4
@@ -100,13 +100,11 @@ class Xrpl(ConanFile):
|
||||
def configure(self):
|
||||
if self.settings.compiler == 'apple-clang':
|
||||
self.options['boost'].visibility = 'global'
|
||||
if self.settings.compiler in ['clang', 'gcc']:
|
||||
self.options['boost'].without_cobalt = True
|
||||
|
||||
def requirements(self):
|
||||
# Conan 2 requires transitive headers to be specified
|
||||
transitive_headers_opt = {'transitive_headers': True} if conan_version.split('.')[0] == '2' else {}
|
||||
self.requires('boost/1.88.0', force=True, **transitive_headers_opt)
|
||||
self.requires('boost/1.83.0', force=True, **transitive_headers_opt)
|
||||
self.requires('date/3.0.4', **transitive_headers_opt)
|
||||
self.requires('lz4/1.10.0', force=True)
|
||||
self.requires('protobuf/3.21.12', force=True)
|
||||
@@ -177,7 +175,6 @@ class Xrpl(ConanFile):
|
||||
'boost::filesystem',
|
||||
'boost::json',
|
||||
'boost::program_options',
|
||||
'boost::process',
|
||||
'boost::regex',
|
||||
'boost::system',
|
||||
'boost::thread',
|
||||
|
||||
@@ -654,12 +654,14 @@ SharedWeakUnion<T>::convertToWeak()
|
||||
break;
|
||||
case destroy:
|
||||
// We just added a weak ref. How could we destroy?
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
|
||||
"added ref");
|
||||
delete p;
|
||||
unsafeSetRawPtr(nullptr);
|
||||
return true; // Should never happen
|
||||
// LCOV_EXCL_STOP
|
||||
case partialDestroy:
|
||||
// This is a weird case. We just converted the last strong
|
||||
// pointer to a weak pointer.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <xrpl/basics/Resolver.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
explicit ResolverAsio() = default;
|
||||
|
||||
static std::unique_ptr<ResolverAsio>
|
||||
New(boost::asio::io_context&, beast::Journal);
|
||||
New(boost::asio::io_service&, beast::Journal);
|
||||
};
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
@@ -33,7 +32,7 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Measures handler latency on an io_context queue. */
|
||||
/** Measures handler latency on an io_service queue. */
|
||||
template <class Clock>
|
||||
class io_latency_probe
|
||||
{
|
||||
@@ -45,12 +44,12 @@ private:
|
||||
std::condition_variable_any m_cond;
|
||||
std::size_t m_count;
|
||||
duration const m_period;
|
||||
boost::asio::io_context& m_ios;
|
||||
boost::asio::io_service& m_ios;
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
|
||||
bool m_cancel;
|
||||
|
||||
public:
|
||||
io_latency_probe(duration const& period, boost::asio::io_context& ios)
|
||||
io_latency_probe(duration const& period, boost::asio::io_service& ios)
|
||||
: m_count(1)
|
||||
, m_period(period)
|
||||
, m_ios(ios)
|
||||
@@ -65,16 +64,16 @@ public:
|
||||
cancel(lock, true);
|
||||
}
|
||||
|
||||
/** Return the io_context associated with the latency probe. */
|
||||
/** Return the io_service associated with the latency probe. */
|
||||
/** @{ */
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return m_ios;
|
||||
}
|
||||
|
||||
boost::asio::io_context const&
|
||||
get_io_context() const
|
||||
boost::asio::io_service const&
|
||||
get_io_service() const
|
||||
{
|
||||
return m_ios;
|
||||
}
|
||||
@@ -110,10 +109,8 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
m_ios.post(sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
}
|
||||
|
||||
/** Initiate continuous i/o latency sampling.
|
||||
@@ -127,10 +124,8 @@ public:
|
||||
std::lock_guard lock(m_mutex);
|
||||
if (m_cancel)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
boost::asio::post(
|
||||
m_ios,
|
||||
sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
m_ios.post(sample_op<Handler>(
|
||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -241,13 +236,12 @@ private:
|
||||
// The latency is too high to maintain the desired
|
||||
// period so don't bother with a timer.
|
||||
//
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
m_probe->m_ios.post(
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_probe->m_timer.expires_after(when - now);
|
||||
m_probe->m_timer.expires_from_now(when - now);
|
||||
m_probe->m_timer.async_wait(
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
@@ -260,8 +254,7 @@ private:
|
||||
if (!m_probe)
|
||||
return;
|
||||
typename Clock::time_point const now(Clock::now());
|
||||
boost::asio::post(
|
||||
m_probe->m_ios,
|
||||
m_probe->m_ios.post(
|
||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,7 +94,11 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
|
||||
else if (addr.is_v6())
|
||||
hash_append(h, addr.to_v6().to_bytes());
|
||||
else
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("beast::hash_append : invalid address type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
} // namespace beast
|
||||
|
||||
|
||||
@@ -8,11 +8,9 @@
|
||||
#ifndef BEAST_TEST_YIELD_TO_HPP
|
||||
#define BEAST_TEST_YIELD_TO_HPP
|
||||
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
@@ -31,12 +29,10 @@ namespace test {
|
||||
class enable_yield_to
|
||||
{
|
||||
protected:
|
||||
boost::asio::io_context ios_;
|
||||
boost::asio::io_service ios_;
|
||||
|
||||
private:
|
||||
boost::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
work_;
|
||||
boost::optional<boost::asio::io_service::work> work_;
|
||||
std::vector<std::thread> threads_;
|
||||
std::mutex m_;
|
||||
std::condition_variable cv_;
|
||||
@@ -46,8 +42,7 @@ public:
|
||||
/// The type of yield context passed to functions.
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
explicit enable_yield_to(std::size_t concurrency = 1)
|
||||
: work_(boost::asio::make_work_guard(ios_))
|
||||
explicit enable_yield_to(std::size_t concurrency = 1) : work_(ios_)
|
||||
{
|
||||
threads_.reserve(concurrency);
|
||||
while (concurrency--)
|
||||
@@ -61,9 +56,9 @@ public:
|
||||
t.join();
|
||||
}
|
||||
|
||||
/// Return the `io_context` associated with the object
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
/// Return the `io_service` associated with the object
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return ios_;
|
||||
}
|
||||
@@ -116,18 +111,13 @@ enable_yield_to::spawn(F0&& f, FN&&... fn)
|
||||
{
|
||||
boost::asio::spawn(
|
||||
ios_,
|
||||
boost::allocator_arg,
|
||||
boost::context::fixedsize_stack(2 * 1024 * 1024),
|
||||
[&](yield_context yield) {
|
||||
f(yield);
|
||||
std::lock_guard lock{m_};
|
||||
if (--running_ == 0)
|
||||
cv_.notify_all();
|
||||
},
|
||||
[](std::exception_ptr e) {
|
||||
if (e)
|
||||
std::rethrow_exception(e);
|
||||
});
|
||||
boost::coroutines::attributes(2 * 1024 * 1024));
|
||||
spawn(fn...);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ Reader::parse(Value& root, BufferSequence const& bs)
|
||||
std::string s;
|
||||
s.reserve(buffer_size(bs));
|
||||
for (auto const& b : bs)
|
||||
s.append(static_cast<char const*>(b.data()), buffer_size(b));
|
||||
s.append(buffer_cast<char const*>(b), buffer_size(b));
|
||||
return parse(s, root);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
* without formatting (not human friendly).
|
||||
*
|
||||
* The JSON document is written in a single line. It is not intended for 'human'
|
||||
* consumption, but may be useful to support feature such as RPC where bandwith
|
||||
* consumption, but may be useful to support feature such as RPC where bandwidth
|
||||
* is limited. \sa Reader, Value
|
||||
*/
|
||||
|
||||
|
||||
@@ -284,12 +284,14 @@ public:
|
||||
{
|
||||
if (key.type != ltOFFER)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::ApplyView::dirAppend : only Offers are appended to "
|
||||
"book directories");
|
||||
// Only Offers are appended to book directories. Call dirInsert()
|
||||
// instead
|
||||
return std::nullopt;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
return dirAdd(true, directory, key.key, describe);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
public:
|
||||
AutoSocket(
|
||||
boost::asio::io_context& s,
|
||||
boost::asio::io_service& s,
|
||||
boost::asio::ssl::context& c,
|
||||
bool secureOnly,
|
||||
bool plainOnly)
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
mSocket = std::make_unique<ssl_socket>(s, c);
|
||||
}
|
||||
|
||||
AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c)
|
||||
AutoSocket(boost::asio::io_service& s, boost::asio::ssl::context& c)
|
||||
: AutoSocket(s, c, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
|
||||
#include <chrono>
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
static void
|
||||
get(bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::deque<std::string> deqSites,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
|
||||
static void
|
||||
get(bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
static void
|
||||
request(
|
||||
bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::function<
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
{
|
||||
strm.set_verify_callback(
|
||||
std::bind(
|
||||
&rfc6125_verify,
|
||||
&rfc2818_verify,
|
||||
host,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief callback invoked for name verification - just passes through
|
||||
* to the asio `host_name_verification` (rfc6125) implementation.
|
||||
* to the asio rfc2818 implementation.
|
||||
*
|
||||
* @param domain hostname expected
|
||||
* @param preverified passed by implementation
|
||||
@@ -175,13 +175,13 @@ public:
|
||||
* @param j journal for logging
|
||||
*/
|
||||
static bool
|
||||
rfc6125_verify(
|
||||
rfc2818_verify(
|
||||
std::string const& domain,
|
||||
bool preverified,
|
||||
boost::asio::ssl::verify_context& ctx,
|
||||
beast::Journal j)
|
||||
{
|
||||
if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
|
||||
if (boost::asio::ssl::rfc2818_verification(domain)(preverified, ctx))
|
||||
return true;
|
||||
|
||||
JLOG(j.warn()) << "Outbound SSL connection to " << domain
|
||||
|
||||
@@ -55,7 +55,10 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
|
||||
/** The maximum number of entries per directory page */
|
||||
std::size_t constexpr dirNodeMaxEntries = 32;
|
||||
|
||||
/** The maximum number of pages allowed in a directory */
|
||||
/** The maximum number of pages allowed in a directory
|
||||
|
||||
Made obsolete by fixDirectoryLimit amendment.
|
||||
*/
|
||||
std::uint64_t constexpr dirNodeMaxPages = 262144;
|
||||
|
||||
/** The maximum number of items in an NFT page */
|
||||
|
||||
@@ -129,10 +129,12 @@ inplace_bigint_div_rem(std::span<uint64_t> numerator, std::uint64_t divisor)
|
||||
{
|
||||
// should never happen, but if it does then it seems natural to define
|
||||
// the a null set of numbers to be zero, so the remainder is also zero.
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::b58_fast::detail::inplace_bigint_div_rem : empty "
|
||||
"numerator");
|
||||
return 0;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
auto to_u128 = [](std::uint64_t high,
|
||||
|
||||
@@ -29,15 +29,14 @@
|
||||
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
// If you add an amendment here, then do not forget to increment `numFeatures`
|
||||
// in include/xrpl/protocol/Feature.h.
|
||||
|
||||
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -457,7 +457,7 @@ LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
|
||||
{sfExpiration, soeOPTIONAL},
|
||||
{sfURI, soeOPTIONAL},
|
||||
{sfIssuerNode, soeREQUIRED},
|
||||
{sfSubjectNode, soeREQUIRED},
|
||||
{sfSubjectNode, soeOPTIONAL},
|
||||
{sfPreviousTxnID, soeREQUIRED},
|
||||
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
||||
}))
|
||||
|
||||
@@ -851,7 +851,7 @@ TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
|
||||
TRANSACTION(ttVAULT_CREATE, 65, VaultCreate,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
createPseudoAcct | createMPTIssuance,
|
||||
createPseudoAcct | createMPTIssuance | mustModifyVault,
|
||||
({
|
||||
{sfAsset, soeREQUIRED, soeMPTSupported},
|
||||
{sfAssetsMaximum, soeOPTIONAL},
|
||||
@@ -869,7 +869,7 @@ TRANSACTION(ttVAULT_CREATE, 65, VaultCreate,
|
||||
TRANSACTION(ttVAULT_SET, 66, VaultSet,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
noPriv,
|
||||
mustModifyVault,
|
||||
({
|
||||
{sfVaultID, soeREQUIRED},
|
||||
{sfAssetsMaximum, soeOPTIONAL},
|
||||
@@ -884,7 +884,7 @@ TRANSACTION(ttVAULT_SET, 66, VaultSet,
|
||||
TRANSACTION(ttVAULT_DELETE, 67, VaultDelete,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
mustDeleteAcct | destroyMPTIssuance,
|
||||
mustDeleteAcct | destroyMPTIssuance | mustModifyVault,
|
||||
({
|
||||
{sfVaultID, soeREQUIRED},
|
||||
}))
|
||||
@@ -896,7 +896,7 @@ TRANSACTION(ttVAULT_DELETE, 67, VaultDelete,
|
||||
TRANSACTION(ttVAULT_DEPOSIT, 68, VaultDeposit,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
mayAuthorizeMPT,
|
||||
mayAuthorizeMPT | mustModifyVault,
|
||||
({
|
||||
{sfVaultID, soeREQUIRED},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
@@ -909,7 +909,7 @@ TRANSACTION(ttVAULT_DEPOSIT, 68, VaultDeposit,
|
||||
TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
mayDeleteMPT,
|
||||
mayDeleteMPT | mayAuthorizeMPT | mustModifyVault,
|
||||
({
|
||||
{sfVaultID, soeREQUIRED},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
@@ -924,7 +924,7 @@ TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw,
|
||||
TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback,
|
||||
Delegation::delegatable,
|
||||
featureSingleAssetVault,
|
||||
mayDeleteMPT,
|
||||
mayDeleteMPT | mustModifyVault,
|
||||
({
|
||||
{sfVaultID, soeREQUIRED},
|
||||
{sfHolder, soeREQUIRED},
|
||||
|
||||
@@ -436,10 +436,12 @@ public:
|
||||
admin_.erase(admin_.iterator_to(entry));
|
||||
break;
|
||||
default:
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::Resource::Logic::release : invalid entry "
|
||||
"kind");
|
||||
break;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
inactive_.push_back(entry);
|
||||
entry.whenExpires = m_clock.now() + secondsUntilExpiration;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <xrpl/server/Port.h>
|
||||
#include <xrpl/server/detail/ServerImpl.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -34,10 +34,10 @@ template <class Handler>
|
||||
std::unique_ptr<Server>
|
||||
make_Server(
|
||||
Handler& handler,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
beast::Journal journal)
|
||||
{
|
||||
return std::make_unique<ServerImpl<Handler>>(handler, io_context, journal);
|
||||
return std::make_unique<ServerImpl<Handler>>(handler, io_service, journal);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -88,7 +88,9 @@ public:
|
||||
++iter)
|
||||
{
|
||||
typename BufferSequence::value_type const& buffer(*iter);
|
||||
write(buffer.data(), boost::asio::buffer_size(buffer));
|
||||
write(
|
||||
boost::asio::buffer_cast<void const*>(buffer),
|
||||
boost::asio::buffer_size(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +104,7 @@ public:
|
||||
|
||||
/** Detach the session.
|
||||
This holds the session open so that the response can be sent
|
||||
asynchronously. Calls to io_context::run made by the server
|
||||
asynchronously. Calls to io_service::run made by the server
|
||||
will not return until all detached sessions are closed.
|
||||
*/
|
||||
virtual std::shared_ptr<Session>
|
||||
|
||||
@@ -24,13 +24,11 @@
|
||||
#include <xrpl/beast/net/IPAddressConversion.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/server/Session.h>
|
||||
#include <xrpl/server/detail/Spawn.h>
|
||||
#include <xrpl/server/detail/io_list.h>
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/beast/http/dynamic_body.hpp>
|
||||
@@ -217,8 +215,8 @@ BaseHTTPPeer<Handler, Impl>::BaseHTTPPeer(
|
||||
ConstBufferSequence const& buffers)
|
||||
: port_(port)
|
||||
, handler_(handler)
|
||||
, work_(boost::asio::make_work_guard(executor))
|
||||
, strand_(boost::asio::make_strand(executor))
|
||||
, work_(executor)
|
||||
, strand_(executor)
|
||||
, remote_address_(remote_address)
|
||||
, journal_(journal)
|
||||
{
|
||||
@@ -358,7 +356,7 @@ BaseHTTPPeer<Handler, Impl>::on_write(
|
||||
return;
|
||||
if (graceful_)
|
||||
return do_close();
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
strand_,
|
||||
std::bind(
|
||||
&BaseHTTPPeer<Handler, Impl>::do_read,
|
||||
@@ -377,7 +375,7 @@ BaseHTTPPeer<Handler, Impl>::do_writer(
|
||||
{
|
||||
auto const p = impl().shared_from_this();
|
||||
resume = std::function<void(void)>([this, p, writer, keep_alive]() {
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
strand_,
|
||||
std::bind(
|
||||
&BaseHTTPPeer<Handler, Impl>::do_writer,
|
||||
@@ -408,7 +406,7 @@ BaseHTTPPeer<Handler, Impl>::do_writer(
|
||||
if (!keep_alive)
|
||||
return do_close();
|
||||
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
strand_,
|
||||
std::bind(
|
||||
&BaseHTTPPeer<Handler, Impl>::do_read,
|
||||
@@ -450,14 +448,14 @@ BaseHTTPPeer<Handler, Impl>::write(
|
||||
std::shared_ptr<Writer> const& writer,
|
||||
bool keep_alive)
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&BaseHTTPPeer<Handler, Impl>::do_writer,
|
||||
impl().shared_from_this(),
|
||||
writer,
|
||||
keep_alive,
|
||||
std::placeholders::_1));
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
@@ -492,12 +490,12 @@ BaseHTTPPeer<Handler, Impl>::complete()
|
||||
}
|
||||
|
||||
// keep-alive
|
||||
util::spawn(
|
||||
boost::asio::spawn(bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
&BaseHTTPPeer<Handler, Impl>::do_read,
|
||||
impl().shared_from_this(),
|
||||
std::placeholders::_1));
|
||||
std::placeholders::_1)));
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
|
||||
@@ -91,8 +91,8 @@ BasePeer<Handler, Impl>::BasePeer(
|
||||
return "##" + std::to_string(++id) + " ";
|
||||
}())
|
||||
, j_(sink_)
|
||||
, work_(boost::asio::make_work_guard(executor))
|
||||
, strand_(boost::asio::make_strand(executor))
|
||||
, work_(executor)
|
||||
, strand_(executor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <xrpl/server/detail/BasePeer.h>
|
||||
#include <xrpl/server/detail/LowestLayer.h>
|
||||
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/http/message.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
@@ -421,17 +420,11 @@ BaseWSPeer<Handler, Impl>::start_timer()
|
||||
// Max seconds without completing a message
|
||||
static constexpr std::chrono::seconds timeout{30};
|
||||
static constexpr std::chrono::seconds timeoutLocal{3};
|
||||
|
||||
try
|
||||
{
|
||||
timer_.expires_after(
|
||||
remote_endpoint().address().is_loopback() ? timeoutLocal : timeout);
|
||||
}
|
||||
catch (boost::system::system_error const& e)
|
||||
{
|
||||
return fail(e.code(), "start_timer");
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
timer_.expires_from_now(
|
||||
remote_endpoint().address().is_loopback() ? timeoutLocal : timeout, ec);
|
||||
if (ec)
|
||||
return fail(ec, "start_timer");
|
||||
timer_.async_wait(bind_executor(
|
||||
strand_,
|
||||
std::bind(
|
||||
@@ -445,14 +438,8 @@ template <class Handler, class Impl>
|
||||
void
|
||||
BaseWSPeer<Handler, Impl>::cancel_timer()
|
||||
{
|
||||
try
|
||||
{
|
||||
timer_.cancel();
|
||||
}
|
||||
catch (boost::system::system_error const&)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
error_code ec;
|
||||
timer_.cancel(ec);
|
||||
}
|
||||
|
||||
template <class Handler, class Impl>
|
||||
|
||||
@@ -30,29 +30,15 @@
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/beast/core/detect_ssl.hpp>
|
||||
#include <boost/beast/core/multi_buffer.hpp>
|
||||
#include <boost/beast/core/tcp_stream.hpp>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/predef.h>
|
||||
|
||||
#if !BOOST_OS_WINDOWS
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -83,7 +69,7 @@ private:
|
||||
stream_type stream_;
|
||||
socket_type& socket_;
|
||||
endpoint_type remote_address_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
boost::asio::io_context::strand strand_;
|
||||
beast::Journal const j_;
|
||||
|
||||
public:
|
||||
@@ -109,30 +95,13 @@ private:
|
||||
Handler& handler_;
|
||||
boost::asio::io_context& ioc_;
|
||||
acceptor_type acceptor_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
boost::asio::io_context::strand strand_;
|
||||
bool ssl_;
|
||||
bool plain_;
|
||||
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
|
||||
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
|
||||
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
|
||||
boost::asio::steady_timer backoff_timer_;
|
||||
static constexpr double FREE_FD_THRESHOLD = 0.70;
|
||||
|
||||
struct FDStats
|
||||
{
|
||||
std::uint64_t used{0};
|
||||
std::uint64_t limit{0};
|
||||
};
|
||||
|
||||
void
|
||||
reOpen();
|
||||
|
||||
std::optional<FDStats>
|
||||
query_fd_stats() const;
|
||||
|
||||
bool
|
||||
should_throttle_for_fds();
|
||||
|
||||
public:
|
||||
Door(
|
||||
Handler& handler,
|
||||
@@ -186,7 +155,7 @@ Door<Handler>::Detector::Detector(
|
||||
, stream_(std::move(stream))
|
||||
, socket_(stream_.socket())
|
||||
, remote_address_(remote_address)
|
||||
, strand_(boost::asio::make_strand(ioc_))
|
||||
, strand_(ioc_)
|
||||
, j_(j)
|
||||
{
|
||||
}
|
||||
@@ -195,7 +164,7 @@ template <class Handler>
|
||||
void
|
||||
Door<Handler>::Detector::run()
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
strand_,
|
||||
std::bind(
|
||||
&Detector::do_detect,
|
||||
@@ -300,7 +269,7 @@ Door<Handler>::reOpen()
|
||||
Throw<std::exception>();
|
||||
}
|
||||
|
||||
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
|
||||
if (ec)
|
||||
{
|
||||
JLOG(j_.error()) << "Listen on port '" << port_.name
|
||||
@@ -322,7 +291,7 @@ Door<Handler>::Door(
|
||||
, handler_(handler)
|
||||
, ioc_(io_context)
|
||||
, acceptor_(io_context)
|
||||
, strand_(boost::asio::make_strand(io_context))
|
||||
, strand_(io_context)
|
||||
, ssl_(
|
||||
port_.protocol.count("https") > 0 ||
|
||||
port_.protocol.count("wss") > 0 || port_.protocol.count("wss2") > 0 ||
|
||||
@@ -330,7 +299,6 @@ Door<Handler>::Door(
|
||||
, plain_(
|
||||
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
|
||||
port_.protocol.count("ws2"))
|
||||
, backoff_timer_(io_context)
|
||||
{
|
||||
reOpen();
|
||||
}
|
||||
@@ -339,7 +307,7 @@ template <class Handler>
|
||||
void
|
||||
Door<Handler>::run()
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
strand_,
|
||||
std::bind(
|
||||
&Door<Handler>::do_accept,
|
||||
@@ -352,10 +320,8 @@ void
|
||||
Door<Handler>::close()
|
||||
{
|
||||
if (!strand_.running_in_this_thread())
|
||||
return boost::asio::post(
|
||||
strand_,
|
||||
return strand_.post(
|
||||
std::bind(&Door<Handler>::close, this->shared_from_this()));
|
||||
backoff_timer_.cancel();
|
||||
error_code ec;
|
||||
acceptor_.close(ec);
|
||||
}
|
||||
@@ -401,17 +367,6 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
||||
{
|
||||
while (acceptor_.is_open())
|
||||
{
|
||||
if (should_throttle_for_fds())
|
||||
{
|
||||
backoff_timer_.expires_after(accept_delay_);
|
||||
boost::system::error_code tec;
|
||||
backoff_timer_.async_wait(do_yield[tec]);
|
||||
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
|
||||
JLOG(j_.warn()) << "Throttling do_accept for "
|
||||
<< accept_delay_.count() << "ms.";
|
||||
continue;
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
endpoint_type remote_address;
|
||||
stream_type stream(ioc_);
|
||||
@@ -421,28 +376,15 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
break;
|
||||
|
||||
if (ec == boost::asio::error::no_descriptors ||
|
||||
ec == boost::asio::error::no_buffer_space)
|
||||
JLOG(j_.error()) << "accept: " << ec.message();
|
||||
if (ec == boost::asio::error::no_descriptors)
|
||||
{
|
||||
JLOG(j_.warn()) << "accept: Too many open files. Pausing for "
|
||||
<< accept_delay_.count() << "ms.";
|
||||
|
||||
backoff_timer_.expires_after(accept_delay_);
|
||||
boost::system::error_code tec;
|
||||
backoff_timer_.async_wait(do_yield[tec]);
|
||||
|
||||
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
JLOG(j_.error()) << "accept error: " << ec.message();
|
||||
JLOG(j_.info()) << "re-opening acceptor";
|
||||
reOpen();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
accept_delay_ = INITIAL_ACCEPT_DELAY;
|
||||
|
||||
if (ssl_ && plain_)
|
||||
{
|
||||
if (auto sp = ios().template emplace<Detector>(
|
||||
@@ -465,60 +407,6 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
|
||||
}
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
std::optional<typename Door<Handler>::FDStats>
|
||||
Door<Handler>::query_fd_stats() const
|
||||
{
|
||||
#if BOOST_OS_WINDOWS
|
||||
return std::nullopt;
|
||||
#else
|
||||
FDStats s;
|
||||
struct rlimit rl;
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) != 0 || rl.rlim_cur == RLIM_INFINITY)
|
||||
return std::nullopt;
|
||||
s.limit = static_cast<std::uint64_t>(rl.rlim_cur);
|
||||
#if BOOST_OS_LINUX
|
||||
constexpr char const* kFdDir = "/proc/self/fd";
|
||||
#else
|
||||
constexpr char const* kFdDir = "/dev/fd";
|
||||
#endif
|
||||
if (DIR* d = ::opendir(kFdDir))
|
||||
{
|
||||
std::uint64_t cnt = 0;
|
||||
while (::readdir(d) != nullptr)
|
||||
++cnt;
|
||||
::closedir(d);
|
||||
// readdir counts '.', '..', and the DIR* itself shows in the list
|
||||
s.used = (cnt >= 3) ? (cnt - 3) : 0;
|
||||
return s;
|
||||
}
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
bool
|
||||
Door<Handler>::should_throttle_for_fds()
|
||||
{
|
||||
#if BOOST_OS_WINDOWS
|
||||
return false;
|
||||
#else
|
||||
auto const stats = query_fd_stats();
|
||||
if (!stats || stats->limit == 0)
|
||||
return false;
|
||||
|
||||
auto const& s = *stats;
|
||||
auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull;
|
||||
double const free_ratio =
|
||||
static_cast<double>(free) / static_cast<double>(s.limit);
|
||||
if (free_ratio < FREE_FD_THRESHOLD)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
@@ -105,7 +105,7 @@ PlainHTTPPeer<Handler>::run()
|
||||
{
|
||||
if (!this->handler_.onAccept(this->session(), this->remote_address_))
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
this->strand_,
|
||||
std::bind(&PlainHTTPPeer::do_close, this->shared_from_this()));
|
||||
return;
|
||||
@@ -114,7 +114,7 @@ PlainHTTPPeer<Handler>::run()
|
||||
if (!socket_.is_open())
|
||||
return;
|
||||
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
this->strand_,
|
||||
std::bind(
|
||||
&PlainHTTPPeer::do_read,
|
||||
|
||||
@@ -115,14 +115,14 @@ SSLHTTPPeer<Handler>::run()
|
||||
{
|
||||
if (!this->handler_.onAccept(this->session(), this->remote_address_))
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
this->strand_,
|
||||
std::bind(&SSLHTTPPeer::do_close, this->shared_from_this()));
|
||||
return;
|
||||
}
|
||||
if (!socket_.is_open())
|
||||
return;
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
this->strand_,
|
||||
std::bind(
|
||||
&SSLHTTPPeer::do_handshake,
|
||||
@@ -164,7 +164,7 @@ SSLHTTPPeer<Handler>::do_handshake(yield_context do_yield)
|
||||
this->port().protocol.count("https") > 0;
|
||||
if (http)
|
||||
{
|
||||
util::spawn(
|
||||
boost::asio::spawn(
|
||||
this->strand_,
|
||||
std::bind(
|
||||
&SSLHTTPPeer::do_read,
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include <xrpl/server/detail/io_list.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
@@ -87,11 +85,9 @@ private:
|
||||
|
||||
Handler& handler_;
|
||||
beast::Journal const j_;
|
||||
boost::asio::io_context& io_context_;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
|
||||
std::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
work_;
|
||||
boost::asio::io_service& io_service_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
std::optional<boost::asio::io_service::work> work_;
|
||||
|
||||
std::mutex m_;
|
||||
std::vector<Port> ports_;
|
||||
@@ -104,7 +100,7 @@ private:
|
||||
public:
|
||||
ServerImpl(
|
||||
Handler& handler,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
beast::Journal journal);
|
||||
|
||||
~ServerImpl();
|
||||
@@ -127,10 +123,10 @@ public:
|
||||
return ios_;
|
||||
}
|
||||
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return io_context_;
|
||||
return io_service_;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -144,13 +140,13 @@ private:
|
||||
template <class Handler>
|
||||
ServerImpl<Handler>::ServerImpl(
|
||||
Handler& handler,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
beast::Journal journal)
|
||||
: handler_(handler)
|
||||
, j_(journal)
|
||||
, io_context_(io_context)
|
||||
, strand_(boost::asio::make_strand(io_context_))
|
||||
, work_(std::in_place, boost::asio::make_work_guard(io_context_))
|
||||
, io_service_(io_service)
|
||||
, strand_(io_service_)
|
||||
, work_(io_service_)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -177,7 +173,7 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
|
||||
ports_.push_back(port);
|
||||
auto& internalPort = ports_.back();
|
||||
if (auto sp = ios_.emplace<Door<Handler>>(
|
||||
handler_, io_context_, internalPort, j_))
|
||||
handler_, io_service_, internalPort, j_))
|
||||
{
|
||||
list_.push_back(sp);
|
||||
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright(c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERVER_SPAWN_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SPAWN_H_INCLUDED
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple::util {
|
||||
namespace impl {
|
||||
|
||||
template <typename T>
|
||||
concept IsStrand = std::same_as<
|
||||
std::decay_t<T>,
|
||||
boost::asio::strand<typename std::decay_t<T>::inner_executor_type>>;
|
||||
|
||||
/**
|
||||
* @brief A completion handler that restores `boost::asio::spawn`'s behaviour
|
||||
* from Boost 1.83
|
||||
*
|
||||
* This is intended to be passed as the third argument to `boost::asio::spawn`
|
||||
* so that exceptions are not ignored but propagated to `io_context.run()` call
|
||||
* site.
|
||||
*
|
||||
* @param ePtr The exception that was caught on the coroutine
|
||||
*/
|
||||
inline constexpr auto kPROPAGATE_EXCEPTIONS = [](std::exception_ptr ePtr) {
|
||||
if (ePtr)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ePtr);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
JLOG(debugLog().warn()) << "Spawn exception: " << e.what();
|
||||
throw;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
JLOG(debugLog().warn()) << "Spawn exception: Unknown";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/**
|
||||
* @brief Spawns a coroutine using `boost::asio::spawn`
|
||||
*
|
||||
* @note This uses kPROPAGATE_EXCEPTIONS to force asio to propagate exceptions
|
||||
* through `io_context`
|
||||
* @note Since implicit strand was removed from boost::asio::spawn this helper
|
||||
* function adds the strand back
|
||||
*
|
||||
* @tparam Ctx The type of the context/strand
|
||||
* @tparam F The type of the function to execute
|
||||
* @param ctx The execution context
|
||||
* @param func The function to execute. Must return `void`
|
||||
*/
|
||||
template <typename Ctx, typename F>
|
||||
requires std::is_invocable_r_v<void, F, boost::asio::yield_context>
|
||||
void
|
||||
spawn(Ctx&& ctx, F&& func)
|
||||
{
|
||||
if constexpr (impl::IsStrand<Ctx>)
|
||||
{
|
||||
boost::asio::spawn(
|
||||
std::forward<Ctx>(ctx),
|
||||
std::forward<F>(func),
|
||||
impl::kPROPAGATE_EXCEPTIONS);
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::asio::spawn(
|
||||
boost::asio::make_strand(
|
||||
boost::asio::get_associated_executor(std::forward<Ctx>(ctx))),
|
||||
std::forward<F>(func),
|
||||
impl::kPROPAGATE_EXCEPTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ripple::util
|
||||
|
||||
#endif
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
May be called concurrently.
|
||||
|
||||
Preconditions:
|
||||
No call to io_context::run on any io_context
|
||||
No call to io_service::run on any io_service
|
||||
used by work objects associated with this io_list
|
||||
exists in the caller's call stack.
|
||||
*/
|
||||
|
||||
@@ -239,9 +239,11 @@ Logs::fromSeverity(beast::severities::Severity level)
|
||||
case kError:
|
||||
return lsERROR;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("ripple::Logs::fromSeverity : invalid severity");
|
||||
[[fallthrough]];
|
||||
// LCOV_EXCL_STOP
|
||||
case kFatal:
|
||||
break;
|
||||
}
|
||||
@@ -265,9 +267,11 @@ Logs::toSeverity(LogSeverity level)
|
||||
return kWarning;
|
||||
case lsERROR:
|
||||
return kError;
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("ripple::Logs::toSeverity : invalid severity");
|
||||
[[fallthrough]];
|
||||
// LCOV_EXCL_STOP
|
||||
case lsFATAL:
|
||||
break;
|
||||
}
|
||||
@@ -292,9 +296,11 @@ Logs::toString(LogSeverity s)
|
||||
return "Error";
|
||||
case lsFATAL:
|
||||
return "Fatal";
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("ripple::Logs::toString : invalid severity");
|
||||
return "Unknown";
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,9 +362,11 @@ Logs::format(
|
||||
case kError:
|
||||
output += "ERR ";
|
||||
break;
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("ripple::Logs::format : invalid severity");
|
||||
[[fallthrough]];
|
||||
// LCOV_EXCL_STOP
|
||||
case kFatal:
|
||||
output += "FTL ";
|
||||
break;
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/system/detail/error_code.hpp>
|
||||
|
||||
@@ -125,8 +124,8 @@ public:
|
||||
|
||||
beast::Journal m_journal;
|
||||
|
||||
boost::asio::io_context& m_io_context;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> m_strand;
|
||||
boost::asio::io_service& m_io_service;
|
||||
boost::asio::io_service::strand m_strand;
|
||||
boost::asio::ip::tcp::resolver m_resolver;
|
||||
|
||||
std::condition_variable m_cv;
|
||||
@@ -156,12 +155,12 @@ public:
|
||||
std::deque<Work> m_work;
|
||||
|
||||
ResolverAsioImpl(
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
beast::Journal journal)
|
||||
: m_journal(journal)
|
||||
, m_io_context(io_context)
|
||||
, m_strand(boost::asio::make_strand(io_context))
|
||||
, m_resolver(io_context)
|
||||
, m_io_service(io_service)
|
||||
, m_strand(io_service)
|
||||
, m_resolver(io_service)
|
||||
, m_asyncHandlersCompleted(true)
|
||||
, m_stop_called(false)
|
||||
, m_stopped(true)
|
||||
@@ -217,14 +216,8 @@ public:
|
||||
{
|
||||
if (m_stop_called.exchange(true) == false)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_stop,
|
||||
this,
|
||||
CompletionCounter(this))));
|
||||
m_io_service.dispatch(m_strand.wrap(std::bind(
|
||||
&ResolverAsioImpl::do_stop, this, CompletionCounter(this))));
|
||||
|
||||
JLOG(m_journal.debug()) << "Queued a stop request";
|
||||
}
|
||||
@@ -255,16 +248,12 @@ public:
|
||||
|
||||
// TODO NIKB use rvalue references to construct and move
|
||||
// reducing cost.
|
||||
boost::asio::dispatch(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_resolve,
|
||||
this,
|
||||
names,
|
||||
handler,
|
||||
CompletionCounter(this))));
|
||||
m_io_service.dispatch(m_strand.wrap(std::bind(
|
||||
&ResolverAsioImpl::do_resolve,
|
||||
this,
|
||||
names,
|
||||
handler,
|
||||
CompletionCounter(this))));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -290,20 +279,19 @@ public:
|
||||
std::string name,
|
||||
boost::system::error_code const& ec,
|
||||
HandlerType handler,
|
||||
boost::asio::ip::tcp::resolver::results_type results,
|
||||
boost::asio::ip::tcp::resolver::iterator iter,
|
||||
CompletionCounter)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
std::vector<beast::IP::Endpoint> addresses;
|
||||
auto iter = results.begin();
|
||||
|
||||
// If we get an error message back, we don't return any
|
||||
// results that we may have gotten.
|
||||
if (!ec)
|
||||
{
|
||||
while (iter != results.end())
|
||||
while (iter != boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
addresses.push_back(
|
||||
beast::IPAddressConversion::from_asio(*iter));
|
||||
@@ -313,14 +301,8 @@ public:
|
||||
|
||||
handler(name, addresses);
|
||||
|
||||
boost::asio::post(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_work,
|
||||
this,
|
||||
CompletionCounter(this))));
|
||||
m_io_service.post(m_strand.wrap(std::bind(
|
||||
&ResolverAsioImpl::do_work, this, CompletionCounter(this))));
|
||||
}
|
||||
|
||||
HostAndPort
|
||||
@@ -401,21 +383,16 @@ public:
|
||||
{
|
||||
JLOG(m_journal.error()) << "Unable to parse '" << name << "'";
|
||||
|
||||
boost::asio::post(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_work,
|
||||
this,
|
||||
CompletionCounter(this))));
|
||||
m_io_service.post(m_strand.wrap(std::bind(
|
||||
&ResolverAsioImpl::do_work, this, CompletionCounter(this))));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::resolver::query query(host, port);
|
||||
|
||||
m_resolver.async_resolve(
|
||||
host,
|
||||
port,
|
||||
query,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_finish,
|
||||
this,
|
||||
@@ -446,14 +423,10 @@ public:
|
||||
|
||||
if (m_work.size() > 0)
|
||||
{
|
||||
boost::asio::post(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&ResolverAsioImpl::do_work,
|
||||
this,
|
||||
CompletionCounter(this))));
|
||||
m_io_service.post(m_strand.wrap(std::bind(
|
||||
&ResolverAsioImpl::do_work,
|
||||
this,
|
||||
CompletionCounter(this))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -462,9 +435,9 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<ResolverAsio>
|
||||
ResolverAsio::New(boost::asio::io_context& io_context, beast::Journal journal)
|
||||
ResolverAsio::New(boost::asio::io_service& io_service, beast::Journal journal)
|
||||
{
|
||||
return std::make_unique<ResolverAsioImpl>(io_context, journal);
|
||||
return std::make_unique<ResolverAsioImpl>(io_service, journal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -36,6 +36,7 @@ LogThrow(std::string const& title)
|
||||
[[noreturn]] void
|
||||
LogicError(std::string const& s) noexcept
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(debugLog().fatal()) << s;
|
||||
std::cerr << "Logic error: " << s << std::endl;
|
||||
// Use a non-standard contract naming here (without namespace) because
|
||||
@@ -45,6 +46,7 @@ LogicError(std::string const& s) noexcept
|
||||
// For the above reasons, we want this contract to stand out.
|
||||
UNREACHABLE("LogicError", {{"message", s}});
|
||||
std::abort();
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
@@ -30,11 +30,9 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ip/udp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/system/detail/error_code.hpp>
|
||||
@@ -240,11 +238,9 @@ private:
|
||||
Journal m_journal;
|
||||
IP::Endpoint m_address;
|
||||
std::string m_prefix;
|
||||
boost::asio::io_context m_io_context;
|
||||
std::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
m_work;
|
||||
boost::asio::strand<boost::asio::io_context::executor_type> m_strand;
|
||||
boost::asio::io_service m_io_service;
|
||||
std::optional<boost::asio::io_service::work> m_work;
|
||||
boost::asio::io_service::strand m_strand;
|
||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
|
||||
boost::asio::ip::udp::socket m_socket;
|
||||
std::deque<std::string> m_data;
|
||||
@@ -268,24 +264,18 @@ public:
|
||||
: m_journal(journal)
|
||||
, m_address(address)
|
||||
, m_prefix(prefix)
|
||||
, m_work(boost::asio::make_work_guard(m_io_context))
|
||||
, m_strand(boost::asio::make_strand(m_io_context))
|
||||
, m_timer(m_io_context)
|
||||
, m_socket(m_io_context)
|
||||
, m_work(std::ref(m_io_service))
|
||||
, m_strand(m_io_service)
|
||||
, m_timer(m_io_service)
|
||||
, m_socket(m_io_service)
|
||||
, m_thread(&StatsDCollectorImp::run, this)
|
||||
{
|
||||
}
|
||||
|
||||
~StatsDCollectorImp() override
|
||||
{
|
||||
try
|
||||
{
|
||||
m_timer.cancel();
|
||||
}
|
||||
catch (boost::system::system_error const&)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
boost::system::error_code ec;
|
||||
m_timer.cancel(ec);
|
||||
|
||||
m_work.reset();
|
||||
m_thread.join();
|
||||
@@ -344,10 +334,10 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
boost::asio::io_context&
|
||||
get_io_context()
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return m_io_context;
|
||||
return m_io_service;
|
||||
}
|
||||
|
||||
std::string const&
|
||||
@@ -365,14 +355,8 @@ public:
|
||||
void
|
||||
post_buffer(std::string&& buffer)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_io_context,
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
std::bind(
|
||||
&StatsDCollectorImp::do_post_buffer,
|
||||
this,
|
||||
std::move(buffer))));
|
||||
m_io_service.dispatch(m_strand.wrap(std::bind(
|
||||
&StatsDCollectorImp::do_post_buffer, this, std::move(buffer))));
|
||||
}
|
||||
|
||||
// The keepAlive parameter makes sure the buffers sent to
|
||||
@@ -402,7 +386,8 @@ public:
|
||||
for (auto const& buffer : buffers)
|
||||
{
|
||||
std::string const s(
|
||||
buffer.data(), boost::asio::buffer_size(buffer));
|
||||
boost::asio::buffer_cast<char const*>(buffer),
|
||||
boost::asio::buffer_size(buffer));
|
||||
std::cerr << s;
|
||||
}
|
||||
std::cerr << '\n';
|
||||
@@ -471,7 +456,7 @@ public:
|
||||
set_timer()
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
m_timer.expires_after(1s);
|
||||
m_timer.expires_from_now(1s);
|
||||
m_timer.async_wait(std::bind(
|
||||
&StatsDCollectorImp::on_timer, this, std::placeholders::_1));
|
||||
}
|
||||
@@ -513,13 +498,13 @@ public:
|
||||
|
||||
set_timer();
|
||||
|
||||
m_io_context.run();
|
||||
m_io_service.run();
|
||||
|
||||
m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_send, ec);
|
||||
|
||||
m_socket.close();
|
||||
|
||||
m_io_context.poll();
|
||||
m_io_service.poll();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -562,12 +547,10 @@ StatsDCounterImpl::~StatsDCounterImpl()
|
||||
void
|
||||
StatsDCounterImpl::increment(CounterImpl::value_type amount)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_impl->get_io_context(),
|
||||
std::bind(
|
||||
&StatsDCounterImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDCounterImpl>(shared_from_this()),
|
||||
amount));
|
||||
m_impl->get_io_service().dispatch(std::bind(
|
||||
&StatsDCounterImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDCounterImpl>(shared_from_this()),
|
||||
amount));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -609,12 +592,10 @@ StatsDEventImpl::StatsDEventImpl(
|
||||
void
|
||||
StatsDEventImpl::notify(EventImpl::value_type const& value)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_impl->get_io_context(),
|
||||
std::bind(
|
||||
&StatsDEventImpl::do_notify,
|
||||
std::static_pointer_cast<StatsDEventImpl>(shared_from_this()),
|
||||
value));
|
||||
m_impl->get_io_service().dispatch(std::bind(
|
||||
&StatsDEventImpl::do_notify,
|
||||
std::static_pointer_cast<StatsDEventImpl>(shared_from_this()),
|
||||
value));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -644,23 +625,19 @@ StatsDGaugeImpl::~StatsDGaugeImpl()
|
||||
void
|
||||
StatsDGaugeImpl::set(GaugeImpl::value_type value)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_impl->get_io_context(),
|
||||
std::bind(
|
||||
&StatsDGaugeImpl::do_set,
|
||||
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
|
||||
value));
|
||||
m_impl->get_io_service().dispatch(std::bind(
|
||||
&StatsDGaugeImpl::do_set,
|
||||
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
|
||||
value));
|
||||
}
|
||||
|
||||
void
|
||||
StatsDGaugeImpl::increment(GaugeImpl::difference_type amount)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_impl->get_io_context(),
|
||||
std::bind(
|
||||
&StatsDGaugeImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
|
||||
amount));
|
||||
m_impl->get_io_service().dispatch(std::bind(
|
||||
&StatsDGaugeImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDGaugeImpl>(shared_from_this()),
|
||||
amount));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -736,12 +713,10 @@ StatsDMeterImpl::~StatsDMeterImpl()
|
||||
void
|
||||
StatsDMeterImpl::increment(MeterImpl::value_type amount)
|
||||
{
|
||||
boost::asio::dispatch(
|
||||
m_impl->get_io_context(),
|
||||
std::bind(
|
||||
&StatsDMeterImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDMeterImpl>(shared_from_this()),
|
||||
amount));
|
||||
m_impl->get_io_service().dispatch(std::bind(
|
||||
&StatsDMeterImpl::do_increment,
|
||||
std::static_pointer_cast<StatsDMeterImpl>(shared_from_this()),
|
||||
amount));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace IP {
|
||||
bool
|
||||
is_private(AddressV4 const& addr)
|
||||
{
|
||||
return ((addr.to_uint() & 0xff000000) ==
|
||||
return ((addr.to_ulong() & 0xff000000) ==
|
||||
0x0a000000) || // Prefix /8, 10. #.#.#
|
||||
((addr.to_uint() & 0xfff00000) ==
|
||||
((addr.to_ulong() & 0xfff00000) ==
|
||||
0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.#
|
||||
((addr.to_uint() & 0xffff0000) ==
|
||||
((addr.to_ulong() & 0xffff0000) ==
|
||||
0xc0a80000) || // Prefix /16 192.168.#.#
|
||||
addr.is_loopback();
|
||||
}
|
||||
@@ -44,7 +44,7 @@ char
|
||||
get_class(AddressV4 const& addr)
|
||||
{
|
||||
static char const* table = "AAAABBCD";
|
||||
return table[(addr.to_uint() & 0xE0000000) >> 29];
|
||||
return table[(addr.to_ulong() & 0xE0000000) >> 29];
|
||||
}
|
||||
|
||||
} // namespace IP
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
#include <xrpl/beast/net/IPAddressV4.h>
|
||||
#include <xrpl/beast/net/IPAddressV6.h>
|
||||
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace IP {
|
||||
|
||||
@@ -30,9 +28,7 @@ is_private(AddressV6 const& addr)
|
||||
{
|
||||
return (
|
||||
(addr.to_bytes()[0] & 0xfd) || // TODO fc00::/8 too ?
|
||||
(addr.is_v4_mapped() &&
|
||||
is_private(boost::asio::ip::make_address_v4(
|
||||
boost::asio::ip::v4_mapped, addr))));
|
||||
(addr.is_v4_mapped() && is_private(addr.to_v4())));
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
#include <boost/system/detail/error_code.hpp>
|
||||
|
||||
#include <cctype>
|
||||
@@ -169,7 +167,7 @@ operator>>(std::istream& is, Endpoint& endpoint)
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
auto addr = boost::asio::ip::make_address(addrStr, ec);
|
||||
auto addr = Address::from_string(addrStr, ec);
|
||||
if (ec)
|
||||
{
|
||||
is.setstate(std::ios_base::failbit);
|
||||
|
||||
@@ -174,7 +174,7 @@ Array::append(Json::Value const& v)
|
||||
return;
|
||||
}
|
||||
}
|
||||
UNREACHABLE("Json::Array::append : invalid type");
|
||||
UNREACHABLE("Json::Array::append : invalid type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
void
|
||||
@@ -209,7 +209,7 @@ Object::set(std::string const& k, Json::Value const& v)
|
||||
return;
|
||||
}
|
||||
}
|
||||
UNREACHABLE("Json::Object::set : invalid type");
|
||||
UNREACHABLE("Json::Object::set : invalid type"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -213,8 +213,10 @@ Value::Value(ValueType type) : type_(type), allocated_(0)
|
||||
value_.bool_ = false;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::Value(ValueType) : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,8 +292,10 @@ Value::Value(Value const& other) : type_(other.type_)
|
||||
value_.map_ = new ObjectValues(*other.value_.map_);
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::Value(Value const&) : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,8 +322,10 @@ Value::~Value()
|
||||
delete value_.map_;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::~Value : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,8 +425,10 @@ operator<(Value const& x, Value const& y)
|
||||
return *x.value_.map_ < *y.value_.map_;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::operator<(Value, Value) : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable
|
||||
@@ -465,8 +473,10 @@ operator==(Value const& x, Value const& y)
|
||||
return x.value_.map_->size() == y.value_.map_->size() &&
|
||||
*x.value_.map_ == *y.value_.map_;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::operator==(Value, Value) : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable
|
||||
@@ -506,8 +516,10 @@ Value::asString() const
|
||||
case objectValue:
|
||||
JSON_ASSERT_MESSAGE(false, "Type is not convertible to string");
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asString : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return ""; // unreachable
|
||||
@@ -548,8 +560,10 @@ Value::asInt() const
|
||||
case objectValue:
|
||||
JSON_ASSERT_MESSAGE(false, "Type is not convertible to int");
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asInt : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable;
|
||||
@@ -590,8 +604,10 @@ Value::asUInt() const
|
||||
case objectValue:
|
||||
JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint");
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asUInt : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable;
|
||||
@@ -622,8 +638,10 @@ Value::asDouble() const
|
||||
case objectValue:
|
||||
JSON_ASSERT_MESSAGE(false, "Type is not convertible to double");
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asDouble : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable;
|
||||
@@ -654,8 +672,10 @@ Value::asBool() const
|
||||
case objectValue:
|
||||
return value_.map_->size() != 0;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::asBool : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return false; // unreachable;
|
||||
@@ -710,8 +730,10 @@ Value::isConvertibleTo(ValueType other) const
|
||||
return other == objectValue ||
|
||||
(other == nullValue && value_.map_->size() == 0);
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::isConvertible : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return false; // unreachable;
|
||||
@@ -744,8 +766,10 @@ Value::size() const
|
||||
case objectValue:
|
||||
return Int(value_.map_->size());
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
UNREACHABLE("Json::Value::size : invalid type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return 0; // unreachable;
|
||||
|
||||
@@ -259,9 +259,11 @@ ApplyStateTable::apply(
|
||||
}
|
||||
else
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::detail::ApplyStateTable::apply : unsupported "
|
||||
"operation type");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
std::optional<std::uint64_t>
|
||||
@@ -91,8 +94,21 @@ ApplyView::dirAdd(
|
||||
return page;
|
||||
}
|
||||
|
||||
// We rely on modulo arithmetic of unsigned integers (guaranteed in
|
||||
// [basic.fundamental] paragraph 2) to detect page representation overflow.
|
||||
// For signed integers this would be UB, hence static_assert here.
|
||||
static_assert(std::is_unsigned_v<decltype(page)>);
|
||||
// Defensive check against breaking changes in compiler.
|
||||
static_assert([]<typename T>(std::type_identity<T>) constexpr -> T {
|
||||
T tmp = std::numeric_limits<T>::max();
|
||||
return ++tmp;
|
||||
}(std::type_identity<decltype(page)>{}) == 0);
|
||||
++page;
|
||||
// Check whether we're out of pages.
|
||||
if (++page >= dirNodeMaxPages)
|
||||
if (page == 0)
|
||||
return std::nullopt;
|
||||
if (!rules().enabled(fixDirectoryLimit) &&
|
||||
page >= dirNodeMaxPages) // Old pages limit
|
||||
return std::nullopt;
|
||||
|
||||
// We are about to create a new node; we'll link it to
|
||||
@@ -133,8 +149,10 @@ ApplyView::emptyDirDelete(Keylet const& directory)
|
||||
if (directory.type != ltDIR_NODE ||
|
||||
node->getFieldH256(sfRootIndex) != directory.key)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::ApplyView::emptyDirDelete : invalid node type");
|
||||
return false;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
// The directory still contains entries and so it cannot be removed
|
||||
|
||||
@@ -36,7 +36,9 @@ BookDirs::BookDirs(ReadView const& view, Book const& book)
|
||||
{
|
||||
if (!cdirFirst(*view_, key_, sle_, entry_, index_))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::BookDirs::BookDirs : directory is empty");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,9 +112,11 @@ BookDirs::const_iterator::operator++()
|
||||
}
|
||||
else if (!cdirFirst(*view_, cur_key_, sle_, entry_, index_))
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"ripple::BookDirs::const_iterator::operator++ : directory is "
|
||||
"empty");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,19 +77,23 @@ deleteSLE(
|
||||
AccountID const& account, SField const& node, bool isOwner) -> TER {
|
||||
auto const sleAccount = view.peek(keylet::account(account));
|
||||
if (!sleAccount)
|
||||
{ // LCOV_EXCL_START
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.fatal()) << "Internal error: can't retrieve Owner account.";
|
||||
return tecINTERNAL;
|
||||
} // LCOV_EXCL_STOP
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
// Remove object from owner directory
|
||||
std::uint64_t const page = sleCredential->getFieldU64(node);
|
||||
if (!view.dirRemove(
|
||||
keylet::ownerDir(account), page, sleCredential->key(), false))
|
||||
{ // LCOV_EXCL_START
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.fatal()) << "Unable to delete Credential from owner.";
|
||||
return tefBAD_LEDGER;
|
||||
} // LCOV_EXCL_STOP
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
if (isOwner)
|
||||
adjustOwnerCount(view, sleAccount, -1, j);
|
||||
|
||||
+59
-32
@@ -324,10 +324,12 @@ isVaultPseudoAccountFrozen(
|
||||
auto const issuer = mptIssuance->getAccountID(sfIssuer);
|
||||
auto const mptIssuer = view.read(keylet::account(issuer));
|
||||
if (mptIssuer == nullptr)
|
||||
{ // LCOV_EXCL_START
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::isVaultPseudoAccountFrozen : null MPToken issuer");
|
||||
return false;
|
||||
} // LCOV_EXCL_STOP
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
if (!mptIssuer->isFieldPresent(sfVaultID))
|
||||
return false; // not a Vault pseudo-account, common case
|
||||
@@ -338,7 +340,8 @@ isVaultPseudoAccountFrozen(
|
||||
{ // LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::isVaultPseudoAccountFrozen : null vault");
|
||||
return false;
|
||||
} // LCOV_EXCL_STOP
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
|
||||
}
|
||||
@@ -1131,7 +1134,7 @@ createPseudoAccount(
|
||||
uint256 const& pseudoOwnerKey,
|
||||
SField const& ownerField)
|
||||
{
|
||||
auto const& fields = getPseudoAccountFields();
|
||||
[[maybe_unused]] auto const& fields = getPseudoAccountFields();
|
||||
XRPL_ASSERT(
|
||||
std::count_if(
|
||||
fields.begin(),
|
||||
@@ -1239,6 +1242,12 @@ addEmptyHolding(
|
||||
// If the line already exists, don't create it again.
|
||||
if (view.read(index))
|
||||
return tecDUPLICATE;
|
||||
|
||||
// Can the account cover the trust line reserve ?
|
||||
std::uint32_t const ownerCount = sleDst->at(sfOwnerCount);
|
||||
if (priorBalance < view.fees().accountReserve(ownerCount + 1))
|
||||
return tecNO_LINE_INSUF_RESERVE;
|
||||
|
||||
return trustCreate(
|
||||
view,
|
||||
high,
|
||||
@@ -1289,7 +1298,7 @@ authorizeMPToken(
|
||||
{
|
||||
auto const sleAcct = view.peek(keylet::account(account));
|
||||
if (!sleAcct)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
// If the account that submitted the tx is a holder
|
||||
// Note: `account_` is holder's account
|
||||
@@ -1354,17 +1363,17 @@ authorizeMPToken(
|
||||
|
||||
auto const sleMptIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
|
||||
if (!sleMptIssuance)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
// If the account that submitted this tx is the issuer of the MPT
|
||||
// Note: `account_` is issuer's account
|
||||
// `holderID` is holder's account
|
||||
if (account != (*sleMptIssuance)[sfIssuer])
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const sleMpt = view.peek(keylet::mptoken(mptIssuanceID, *holderID));
|
||||
if (!sleMpt)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
std::uint32_t const flagsIn = sleMpt->getFieldU32(sfFlags);
|
||||
std::uint32_t flagsOut = flagsIn;
|
||||
@@ -1421,7 +1430,7 @@ trustCreate(
|
||||
describeOwnerDir(uLowAccountID));
|
||||
|
||||
if (!lowNode)
|
||||
return tecDIR_FULL;
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
auto highNode = view.dirInsert(
|
||||
keylet::ownerDir(uHighAccountID),
|
||||
@@ -1429,14 +1438,14 @@ trustCreate(
|
||||
describeOwnerDir(uHighAccountID));
|
||||
|
||||
if (!highNode)
|
||||
return tecDIR_FULL;
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
bool const bSetDst = saLimit.getIssuer() == uDstAccountID;
|
||||
bool const bSetHigh = bSrcHigh ^ bSetDst;
|
||||
|
||||
XRPL_ASSERT(sleAccount, "ripple::trustCreate : non-null SLE");
|
||||
if (!sleAccount)
|
||||
return tefINTERNAL;
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
XRPL_ASSERT(
|
||||
sleAccount->getAccountID(sfAccount) ==
|
||||
@@ -1515,10 +1524,12 @@ removeEmptyHolding(
|
||||
{
|
||||
auto const sle = view.read(keylet::account(accountID));
|
||||
if (!sle)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const balance = sle->getFieldAmount(sfBalance);
|
||||
if (balance.xrp() != 0)
|
||||
return tecHAS_OBLIGATIONS;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -1536,7 +1547,8 @@ removeEmptyHolding(
|
||||
auto sleLowAccount =
|
||||
view.peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
|
||||
if (!sleLowAccount)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
adjustOwnerCount(view, sleLowAccount, -1, journal);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
@@ -1550,7 +1562,8 @@ removeEmptyHolding(
|
||||
auto sleHighAccount =
|
||||
view.peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
|
||||
if (!sleHighAccount)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
adjustOwnerCount(view, sleHighAccount, -1, journal);
|
||||
// It's not really necessary to clear the reserve flag, since the line
|
||||
// is about to be deleted, but this will make the metadata reflect an
|
||||
@@ -1610,7 +1623,7 @@ trustDelete(
|
||||
sleRippleState->key(),
|
||||
false))
|
||||
{
|
||||
return tefBAD_LEDGER;
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: high";
|
||||
@@ -1621,7 +1634,7 @@ trustDelete(
|
||||
sleRippleState->key(),
|
||||
false))
|
||||
{
|
||||
return tefBAD_LEDGER;
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
JLOG(j.trace()) << "trustDelete: Deleting ripple line: state";
|
||||
@@ -1647,7 +1660,7 @@ offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j)
|
||||
offerIndex,
|
||||
false))
|
||||
{
|
||||
return tefBAD_LEDGER;
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
if (!view.dirRemove(
|
||||
@@ -1656,7 +1669,7 @@ offerDelete(ApplyView& view, std::shared_ptr<SLE> const& sle, beast::Journal j)
|
||||
offerIndex,
|
||||
false))
|
||||
{
|
||||
return tefBAD_LEDGER;
|
||||
return tefBAD_LEDGER; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
if (sle->isFieldPresent(sfAdditionalBooks))
|
||||
@@ -1820,7 +1833,7 @@ rippleCreditIOU(
|
||||
|
||||
auto const sleAccount = view.peek(keylet::account(uReceiverID));
|
||||
if (!sleAccount)
|
||||
return tefINTERNAL;
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
bool const noRipple = (sleAccount->getFlags() & lsfDefaultRipple) == 0;
|
||||
|
||||
@@ -1910,14 +1923,16 @@ accountSendIOU(
|
||||
{
|
||||
if (saAmount < beast::zero || saAmount.holds<MPTIssue>())
|
||||
{
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
XRPL_ASSERT(
|
||||
saAmount >= beast::zero && !saAmount.holds<MPTIssue>(),
|
||||
"ripple::accountSendIOU : minimum amount and not MPT");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
/* If we aren't sending anything or if the sender is the same as the
|
||||
@@ -1974,8 +1989,10 @@ accountSendIOU(
|
||||
{
|
||||
// VFALCO Its laborious to have to mutate the
|
||||
// TER based on params everywhere
|
||||
// LCOV_EXCL_START
|
||||
terResult = view.open() ? TER{telFAILED_PROCESSING}
|
||||
: TER{tecFAILED_PROCESSING};
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2062,7 +2079,7 @@ rippleCreditMPT(
|
||||
view.update(sleIssuance);
|
||||
}
|
||||
else
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2322,7 +2339,7 @@ issueIOU(
|
||||
|
||||
auto const receiverAccount = view.peek(keylet::account(account));
|
||||
if (!receiverAccount)
|
||||
return tefINTERNAL;
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
bool noRipple = (receiverAccount->getFlags() & lsfDefaultRipple) == 0;
|
||||
|
||||
@@ -2410,11 +2427,13 @@ redeemIOU(
|
||||
// In order to hold an IOU, a trust line *MUST* exist to track the
|
||||
// balance. If it doesn't, then something is very wrong. Don't try
|
||||
// to continue.
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.fatal()) << "redeemIOU: " << to_string(account)
|
||||
<< " attempts to redeem " << amount.getFullText()
|
||||
<< " but no trust line exists!";
|
||||
|
||||
return tefINTERNAL;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
TER
|
||||
@@ -2434,7 +2453,7 @@ transferXRP(
|
||||
SLE::pointer const sender = view.peek(keylet::account(from));
|
||||
SLE::pointer const receiver = view.peek(keylet::account(to));
|
||||
if (!sender || !receiver)
|
||||
return tefINTERNAL;
|
||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
JLOG(j.trace()) << "transferXRP: " << to_string(from) << " -> "
|
||||
<< to_string(to) << ") : " << amount.getFullText();
|
||||
@@ -2444,8 +2463,10 @@ transferXRP(
|
||||
// VFALCO Its unfortunate we have to keep
|
||||
// mutating these TER everywhere
|
||||
// FIXME: this logic should be moved to callers maybe?
|
||||
// LCOV_EXCL_START
|
||||
return view.open() ? TER{telFAILED_PROCESSING}
|
||||
: TER{tecFAILED_PROCESSING};
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
// Decrement XRP balance.
|
||||
@@ -2676,7 +2697,8 @@ enforceMPTokenAuthorization(
|
||||
UNREACHABLE(
|
||||
"ripple::enforceMPTokenAuthorization : condition list is incomplete");
|
||||
return tefINTERNAL;
|
||||
} // LCOV_EXCL_STOP
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
TER
|
||||
canTransfer(
|
||||
@@ -2725,11 +2747,13 @@ cleanupOnAccountDelete(
|
||||
if (!sleItem)
|
||||
{
|
||||
// Directory node has an invalid index. Bail out.
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.fatal())
|
||||
<< "DeleteAccount: Directory node in ledger " << view.seq()
|
||||
<< " has index to object that is missing: "
|
||||
<< to_string(dirEntry);
|
||||
return tefBAD_LEDGER;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
LedgerEntryType const nodeType{safe_cast<LedgerEntryType>(
|
||||
@@ -2762,9 +2786,11 @@ cleanupOnAccountDelete(
|
||||
"ripple::cleanupOnAccountDelete : minimum dir entries");
|
||||
if (uDirEntry == 0)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j.error())
|
||||
<< "DeleteAccount iterator re-validation failed.";
|
||||
return tefBAD_LEDGER;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
if (skipEntry == SkipEntry::No)
|
||||
uDirEntry--;
|
||||
@@ -2784,7 +2810,7 @@ deleteAMMTrustLine(
|
||||
beast::Journal j)
|
||||
{
|
||||
if (!sleState || sleState->getType() != ltRIPPLE_STATE)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const& [low, high] = std::minmax(
|
||||
sleState->getFieldAmount(sfLowLimit).getIssuer(),
|
||||
@@ -2792,13 +2818,14 @@ deleteAMMTrustLine(
|
||||
auto sleLow = view.peek(keylet::account(low));
|
||||
auto sleHigh = view.peek(keylet::account(high));
|
||||
if (!sleLow || !sleHigh)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
bool const ammLow = sleLow->isFieldPresent(sfAMMID);
|
||||
bool const ammHigh = sleHigh->isFieldPresent(sfAMMID);
|
||||
|
||||
// can't both be AMM
|
||||
if (ammLow && ammHigh)
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
// at least one must be
|
||||
if (!ammLow && !ammHigh)
|
||||
@@ -2818,7 +2845,7 @@ deleteAMMTrustLine(
|
||||
|
||||
auto const uFlags = !ammLow ? lsfLowReserve : lsfHighReserve;
|
||||
if (!(sleState->getFlags() & uFlags))
|
||||
return tecINTERNAL;
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
adjustOwnerCount(view, !ammLow ? sleLow : sleHigh, -1, j);
|
||||
|
||||
@@ -2877,7 +2904,7 @@ assetsToSharesDeposit(
|
||||
.truncate()};
|
||||
|
||||
Number const shareTotal = issuance->at(sfOutstandingAmount);
|
||||
shares = (shareTotal * (assets / assetTotal)).truncate();
|
||||
shares = ((shareTotal * assets) / assetTotal).truncate();
|
||||
return shares;
|
||||
}
|
||||
|
||||
@@ -2906,7 +2933,7 @@ sharesToAssetsDeposit(
|
||||
false};
|
||||
|
||||
Number const shareTotal = issuance->at(sfOutstandingAmount);
|
||||
assets = assetTotal * (shares / shareTotal);
|
||||
assets = (assetTotal * shares) / shareTotal;
|
||||
return assets;
|
||||
}
|
||||
|
||||
@@ -2932,7 +2959,7 @@ assetsToSharesWithdraw(
|
||||
if (assetTotal == 0)
|
||||
return shares;
|
||||
Number const shareTotal = issuance->at(sfOutstandingAmount);
|
||||
Number result = shareTotal * (assets / assetTotal);
|
||||
Number result = (shareTotal * assets) / assetTotal;
|
||||
if (truncate == TruncateShares::yes)
|
||||
result = result.truncate();
|
||||
shares = result;
|
||||
@@ -2960,7 +2987,7 @@ sharesToAssetsWithdraw(
|
||||
if (assetTotal == 0)
|
||||
return assets;
|
||||
Number const shareTotal = issuance->at(sfOutstandingAmount);
|
||||
assets = assetTotal * (shares / shareTotal);
|
||||
assets = (assetTotal * shares) / shareTotal;
|
||||
return assets;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <xrpl/net/HTTPClientSSLContext.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/resolver_query_base.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
@@ -56,16 +55,16 @@ class HTTPClientImp : public std::enable_shared_from_this<HTTPClientImp>,
|
||||
{
|
||||
public:
|
||||
HTTPClientImp(
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
unsigned short const port,
|
||||
std::size_t maxResponseSize,
|
||||
beast::Journal& j)
|
||||
: mSocket(io_context, httpClientSSLContext->context())
|
||||
, mResolver(io_context)
|
||||
: mSocket(io_service, httpClientSSLContext->context())
|
||||
, mResolver(io_service)
|
||||
, mHeader(maxClientHeaderBytes)
|
||||
, mPort(port)
|
||||
, maxResponseSize_(maxResponseSize)
|
||||
, mDeadline(io_context)
|
||||
, mDeadline(io_service)
|
||||
, j_(j)
|
||||
{
|
||||
}
|
||||
@@ -147,21 +146,18 @@ public:
|
||||
{
|
||||
JLOG(j_.trace()) << "Fetch: " << mDeqSites[0];
|
||||
|
||||
auto query = std::make_shared<Query>(
|
||||
auto query = std::make_shared<boost::asio::ip::tcp::resolver::query>(
|
||||
mDeqSites[0],
|
||||
std::to_string(mPort),
|
||||
boost::asio::ip::resolver_query_base::numeric_service);
|
||||
mQuery = query;
|
||||
|
||||
try
|
||||
{
|
||||
mDeadline.expires_after(mTimeout);
|
||||
}
|
||||
catch (boost::system::system_error const& e)
|
||||
{
|
||||
mShutdown = e.code();
|
||||
mDeadline.expires_from_now(mTimeout, mShutdown);
|
||||
|
||||
JLOG(j_.trace()) << "expires_after: " << mShutdown.message();
|
||||
JLOG(j_.trace()) << "expires_from_now: " << mShutdown.message();
|
||||
|
||||
if (!mShutdown)
|
||||
{
|
||||
mDeadline.async_wait(std::bind(
|
||||
&HTTPClientImp::handleDeadline,
|
||||
shared_from_this(),
|
||||
@@ -173,9 +169,7 @@ public:
|
||||
JLOG(j_.trace()) << "Resolving: " << mDeqSites[0];
|
||||
|
||||
mResolver.async_resolve(
|
||||
mQuery->host,
|
||||
mQuery->port,
|
||||
mQuery->flags,
|
||||
*mQuery,
|
||||
std::bind(
|
||||
&HTTPClientImp::handleResolve,
|
||||
shared_from_this(),
|
||||
@@ -239,7 +233,7 @@ public:
|
||||
void
|
||||
handleResolve(
|
||||
boost::system::error_code const& ecResult,
|
||||
boost::asio::ip::tcp::resolver::results_type result)
|
||||
boost::asio::ip::tcp::resolver::iterator itrEndpoint)
|
||||
{
|
||||
if (!mShutdown)
|
||||
{
|
||||
@@ -261,7 +255,7 @@ public:
|
||||
|
||||
boost::asio::async_connect(
|
||||
mSocket.lowest_layer(),
|
||||
result,
|
||||
itrEndpoint,
|
||||
std::bind(
|
||||
&HTTPClientImp::handleConnect,
|
||||
shared_from_this(),
|
||||
@@ -481,15 +475,13 @@ public:
|
||||
std::string const& strData = "")
|
||||
{
|
||||
boost::system::error_code ecCancel;
|
||||
try
|
||||
|
||||
(void)mDeadline.cancel(ecCancel);
|
||||
|
||||
if (ecCancel)
|
||||
{
|
||||
mDeadline.cancel();
|
||||
}
|
||||
catch (boost::system::system_error const& e)
|
||||
{
|
||||
JLOG(j_.trace())
|
||||
<< "invokeComplete: Deadline cancel error: " << e.what();
|
||||
ecCancel = e.code();
|
||||
JLOG(j_.trace()) << "invokeComplete: Deadline cancel error: "
|
||||
<< ecCancel.message();
|
||||
}
|
||||
|
||||
JLOG(j_.debug()) << "invokeComplete: Deadline popping: "
|
||||
@@ -523,15 +515,7 @@ private:
|
||||
bool mSSL;
|
||||
AutoSocket mSocket;
|
||||
boost::asio::ip::tcp::resolver mResolver;
|
||||
|
||||
struct Query
|
||||
{
|
||||
std::string host;
|
||||
std::string port;
|
||||
boost::asio::ip::resolver_query_base::flags flags;
|
||||
};
|
||||
std::shared_ptr<Query> mQuery;
|
||||
|
||||
std::shared_ptr<boost::asio::ip::tcp::resolver::query> mQuery;
|
||||
boost::asio::streambuf mRequest;
|
||||
boost::asio::streambuf mHeader;
|
||||
boost::asio::streambuf mResponse;
|
||||
@@ -562,7 +546,7 @@ private:
|
||||
void
|
||||
HTTPClient::get(
|
||||
bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::deque<std::string> deqSites,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
@@ -575,14 +559,14 @@ HTTPClient::get(
|
||||
beast::Journal& j)
|
||||
{
|
||||
auto client =
|
||||
std::make_shared<HTTPClientImp>(io_context, port, responseMax, j);
|
||||
std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
|
||||
client->get(bSSL, deqSites, strPath, timeout, complete);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPClient::get(
|
||||
bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::string const& strPath,
|
||||
@@ -597,14 +581,14 @@ HTTPClient::get(
|
||||
std::deque<std::string> deqSites(1, strSite);
|
||||
|
||||
auto client =
|
||||
std::make_shared<HTTPClientImp>(io_context, port, responseMax, j);
|
||||
std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
|
||||
client->get(bSSL, deqSites, strPath, timeout, complete);
|
||||
}
|
||||
|
||||
void
|
||||
HTTPClient::request(
|
||||
bool bSSL,
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::io_service& io_service,
|
||||
std::string strSite,
|
||||
unsigned short const port,
|
||||
std::function<void(boost::asio::streambuf& sb, std::string const& strHost)>
|
||||
@@ -620,7 +604,7 @@ HTTPClient::request(
|
||||
std::deque<std::string> deqSites(1, strSite);
|
||||
|
||||
auto client =
|
||||
std::make_shared<HTTPClientImp>(io_context, port, responseMax, j);
|
||||
std::make_shared<HTTPClientImp>(io_service, port, responseMax, j);
|
||||
client->request(bSSL, deqSites, setRequest, timeout, complete);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace BuildInfo {
|
||||
// and follow the format described at http://semver.org/
|
||||
//------------------------------------------------------------------------------
|
||||
// clang-format off
|
||||
char const* const versionString = "3.0.0-b1"
|
||||
char const* const versionString = "3.0.0-rc1"
|
||||
// clang-format on
|
||||
|
||||
#if defined(DEBUG) || defined(SANITIZER)
|
||||
|
||||
@@ -112,7 +112,9 @@ void
|
||||
STBase::add(Serializer& s) const
|
||||
{
|
||||
// Should never be called
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::STBase::add : not implemented");
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -238,9 +238,11 @@ TxMeta::getAffectedNode(uint256 const& node)
|
||||
if (n.getFieldH256(sfLedgerIndex) == node)
|
||||
return n;
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
|
||||
Throw<std::runtime_error>("Affected node not found");
|
||||
return *(mNodes.begin()); // Silence compiler warning.
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
STObject
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <exception>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -220,7 +219,7 @@ parse_Port(ParsedPort& port, Section const& section, std::ostream& log)
|
||||
{
|
||||
try
|
||||
{
|
||||
port.ip = boost::asio::ip::make_address(*optResult);
|
||||
port.ip = boost::asio::ip::address::from_string(*optResult);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
|
||||
@@ -3666,7 +3666,7 @@ private:
|
||||
auto const settleDelay = 100s;
|
||||
NetClock::time_point const cancelAfter =
|
||||
env.current()->info().parentCloseTime + 200s;
|
||||
env(create(
|
||||
env(paychan::create(
|
||||
carol,
|
||||
ammAlice.ammAccount(),
|
||||
XRP(1'000),
|
||||
|
||||
@@ -558,6 +558,39 @@ struct Credentials_test : public beast::unit_test::suite
|
||||
jle[jss::result][jss::node]["CredentialType"] ==
|
||||
strHex(std::string_view(credType)));
|
||||
}
|
||||
|
||||
{
|
||||
testcase("Credentials fail, directory full");
|
||||
std::uint32_t const issuerSeq{env.seq(issuer) + 1};
|
||||
env(ticket::create(issuer, 63));
|
||||
env.close();
|
||||
|
||||
// Everything below can only be tested on open ledger.
|
||||
auto const res1 = directory::bumpLastPage(
|
||||
env,
|
||||
directory::maximumPageIndex(env),
|
||||
keylet::ownerDir(issuer.id()),
|
||||
directory::adjustOwnerNode);
|
||||
BEAST_EXPECT(res1);
|
||||
|
||||
auto const jv = credentials::create(issuer, subject, credType);
|
||||
env(jv, ter(tecDIR_FULL));
|
||||
// Free one directory entry by using a ticket
|
||||
env(noop(issuer), ticket::use(issuerSeq + 40));
|
||||
|
||||
// Fill subject directory
|
||||
env(ticket::create(subject, 63));
|
||||
auto const res2 = directory::bumpLastPage(
|
||||
env,
|
||||
directory::maximumPageIndex(env),
|
||||
keylet::ownerDir(subject.id()),
|
||||
directory::adjustOwnerNode);
|
||||
BEAST_EXPECT(res2);
|
||||
env(jv, ter(tecDIR_FULL));
|
||||
|
||||
// End test
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1084,6 +1117,7 @@ struct Credentials_test : public beast::unit_test::suite
|
||||
testSuccessful(all);
|
||||
testCredentialsDelete(all);
|
||||
testCreateFailed(all);
|
||||
testCreateFailed(all - fixDirectoryLimit);
|
||||
testAcceptFailed(all);
|
||||
testDeleteFailed(all);
|
||||
testFeatureFailed(all - featureCredentials);
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
pUrl_.domain,
|
||||
pUrl_.path,
|
||||
port_,
|
||||
env_.app().getIOContext(),
|
||||
env_.app().getIOService(),
|
||||
env_.journal,
|
||||
env_.app().config(),
|
||||
lastEndpoint,
|
||||
@@ -80,11 +80,10 @@ public:
|
||||
isMultipleEndpoints()
|
||||
{
|
||||
using boost::asio::ip::tcp;
|
||||
tcp::resolver resolver(env_.app().getIOContext());
|
||||
tcp::resolver resolver(env_.app().getIOService());
|
||||
std::string port = pUrl_.port ? std::to_string(*pUrl_.port) : "443";
|
||||
auto results = resolver.resolve(pUrl_.domain, port);
|
||||
auto it = results.begin();
|
||||
auto end = results.end();
|
||||
tcp::resolver::iterator it = resolver.resolve(pUrl_.domain, port);
|
||||
tcp::resolver::iterator end;
|
||||
int n = 0;
|
||||
for (; it != end; ++it)
|
||||
++n;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1107,7 +1107,7 @@ struct LedgerReplayer_test : public beast::unit_test::suite
|
||||
return false;
|
||||
|
||||
beast::IP::Address addr =
|
||||
boost::asio::ip::make_address("172.1.1.100");
|
||||
boost::asio::ip::address::from_string("172.1.1.100");
|
||||
jtx::Env serverEnv(*this);
|
||||
serverEnv.app().config().LEDGER_REPLAY = server;
|
||||
auto http_resp = ripple::makeResponse(
|
||||
|
||||
@@ -88,10 +88,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
|
||||
jvParams[jss::ledger_index] = "current";
|
||||
jvParams[jss::binary] = false;
|
||||
{
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
|
||||
// Iterate the state and print all NFTokenPages.
|
||||
if (!jrr.isMember(jss::result) ||
|
||||
@@ -413,10 +411,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
|
||||
jvParams[jss::ledger_index] = "current";
|
||||
jvParams[jss::binary] = false;
|
||||
{
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
|
||||
Json::Value& state = jrr[jss::result][jss::state];
|
||||
|
||||
@@ -460,10 +456,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
|
||||
jvParams[jss::ledger_index] = "current";
|
||||
jvParams[jss::binary] = false;
|
||||
{
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
|
||||
Json::Value& state = jrr[jss::result][jss::state];
|
||||
|
||||
@@ -1235,10 +1229,8 @@ class NFTokenBurnBaseUtil_test : public beast::unit_test::suite
|
||||
jvParams[jss::ledger_index] = "current";
|
||||
jvParams[jss::binary] = false;
|
||||
{
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
|
||||
Json::Value& state = jrr[jss::result][jss::state];
|
||||
|
||||
|
||||
@@ -47,10 +47,8 @@ class NFTokenDir_test : public beast::unit_test::suite
|
||||
jvParams[jss::ledger_index] = "current";
|
||||
jvParams[jss::binary] = false;
|
||||
{
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
|
||||
// Iterate the state and print all NFTokenPages.
|
||||
if (!jrr.isMember(jss::result) ||
|
||||
|
||||
@@ -592,10 +592,8 @@ private:
|
||||
jvParams[field] = value;
|
||||
jvParams[jss::binary] = false;
|
||||
jvParams[jss::type] = jss::oracle;
|
||||
Json::Value jrr = env.rpc(
|
||||
"json",
|
||||
"ledger_data",
|
||||
boost::lexical_cast<std::string>(jvParams));
|
||||
Json::Value jrr =
|
||||
env.rpc("json", "ledger_data", to_string(jvParams));
|
||||
BEAST_EXPECT(jrr[jss::result][jss::state].size() == 2);
|
||||
};
|
||||
verifyLedgerData(jss::ledger_index, index);
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
using namespace jtx::paychan;
|
||||
|
||||
struct PayChan_test : public beast::unit_test::suite
|
||||
{
|
||||
FeatureBitset const disallowIncoming{featureDisallowIncoming};
|
||||
|
||||
@@ -37,10 +37,8 @@ struct Transaction_ordering_test : public beast::unit_test::suite
|
||||
auto const aliceSequence = env.seq(alice);
|
||||
|
||||
auto const tx1 = env.jt(noop(alice), seq(aliceSequence));
|
||||
auto const tx2 = env.jt(
|
||||
noop(alice),
|
||||
seq(aliceSequence + 1),
|
||||
json(R"({"LastLedgerSequence":7})"));
|
||||
auto const tx2 =
|
||||
env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7));
|
||||
|
||||
env(tx1);
|
||||
env.close();
|
||||
@@ -83,10 +81,8 @@ struct Transaction_ordering_test : public beast::unit_test::suite
|
||||
auto const aliceSequence = env.seq(alice);
|
||||
|
||||
auto const tx1 = env.jt(noop(alice), seq(aliceSequence));
|
||||
auto const tx2 = env.jt(
|
||||
noop(alice),
|
||||
seq(aliceSequence + 1),
|
||||
json(R"({"LastLedgerSequence":7})"));
|
||||
auto const tx2 =
|
||||
env.jt(noop(alice), seq(aliceSequence + 1), last_ledger_seq(7));
|
||||
|
||||
env(tx2, ter(terPRE_SEQ));
|
||||
BEAST_EXPECT(env.seq(alice) == aliceSequence);
|
||||
@@ -131,9 +127,7 @@ struct Transaction_ordering_test : public beast::unit_test::suite
|
||||
for (auto i = 0; i < 5; ++i)
|
||||
{
|
||||
tx.emplace_back(env.jt(
|
||||
noop(alice),
|
||||
seq(aliceSequence + i),
|
||||
json(R"({"LastLedgerSequence":7})")));
|
||||
noop(alice), seq(aliceSequence + i), last_ledger_seq(7)));
|
||||
}
|
||||
|
||||
for (auto i = 1; i < 5; ++i)
|
||||
|
||||
+43
-38
@@ -747,11 +747,9 @@ public:
|
||||
|
||||
BEAST_EXPECT(env.current()->info().seq == 6);
|
||||
// Fail to queue an item with a low LastLedgerSeq
|
||||
env(noop(alice),
|
||||
json(R"({"LastLedgerSequence":7})"),
|
||||
ter(telCAN_NOT_QUEUE));
|
||||
env(noop(alice), last_ledger_seq(7), ter(telCAN_NOT_QUEUE));
|
||||
// Queue an item with a sufficient LastLedgerSeq.
|
||||
env(noop(alice), json(R"({"LastLedgerSequence":8})"), queued);
|
||||
env(noop(alice), last_ledger_seq(8), queued);
|
||||
|
||||
constexpr auto largeFeeMultiplier = 700;
|
||||
auto const largeFee = baseFee * largeFeeMultiplier;
|
||||
@@ -2705,21 +2703,15 @@ public:
|
||||
|
||||
auto const aliceSeq = env.seq(alice);
|
||||
BEAST_EXPECT(env.current()->info().seq == 3);
|
||||
env(noop(alice),
|
||||
seq(aliceSeq),
|
||||
json(R"({"LastLedgerSequence":5})"),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 1),
|
||||
json(R"({"LastLedgerSequence":5})"),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice), seq(aliceSeq), last_ledger_seq(5), ter(terQUEUED));
|
||||
env(noop(alice), seq(aliceSeq + 1), last_ledger_seq(5), ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 2),
|
||||
json(R"({"LastLedgerSequence":10})"),
|
||||
last_ledger_seq(10),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 3),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
checkMetrics(*this, env, 4, std::nullopt, 2, 1);
|
||||
auto const bobSeq = env.seq(bob);
|
||||
@@ -2816,39 +2808,39 @@ public:
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 11),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 12),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 13),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 14),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 15),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 16),
|
||||
json(R"({"LastLedgerSequence": 5})"),
|
||||
last_ledger_seq(5),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 17),
|
||||
json(R"({"LastLedgerSequence": 5})"),
|
||||
last_ledger_seq(5),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 18),
|
||||
json(R"({"LastLedgerSequence": 5})"),
|
||||
last_ledger_seq(5),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice),
|
||||
seq(aliceSeq + 19),
|
||||
json(R"({"LastLedgerSequence":11})"),
|
||||
last_ledger_seq(11),
|
||||
ter(terQUEUED));
|
||||
checkMetrics(*this, env, 10, std::nullopt, 2, 1);
|
||||
|
||||
@@ -3089,16 +3081,23 @@ public:
|
||||
env.fund(XRP(1000000), alice);
|
||||
env.close();
|
||||
|
||||
auto const withQueue =
|
||||
R"({ "account": ")" + alice.human() + R"(", "queue": true })";
|
||||
auto const withoutQueue = R"({ "account": ")" + alice.human() + R"("})";
|
||||
auto const prevLedgerWithQueue = R"({ "account": ")" + alice.human() +
|
||||
R"(", "queue": true, "ledger_index": 3 })";
|
||||
Json::Value withQueue;
|
||||
withQueue[jss::account] = alice.human();
|
||||
withQueue[jss::queue] = true;
|
||||
|
||||
Json::Value withoutQueue;
|
||||
withoutQueue[jss::account] = alice.human();
|
||||
|
||||
Json::Value prevLedgerWithQueue;
|
||||
prevLedgerWithQueue[jss::account] = alice.human();
|
||||
prevLedgerWithQueue[jss::queue] = true;
|
||||
prevLedgerWithQueue[jss::ledger_index] = 3;
|
||||
BEAST_EXPECT(env.current()->info().seq > 3);
|
||||
|
||||
{
|
||||
// account_info without the "queue" argument.
|
||||
auto const info = env.rpc("json", "account_info", withoutQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withoutQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3106,7 +3105,8 @@ public:
|
||||
}
|
||||
{
|
||||
// account_info with the "queue" argument.
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3128,7 +3128,8 @@ public:
|
||||
checkMetrics(*this, env, 0, 6, 4, 3);
|
||||
|
||||
{
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3157,7 +3158,8 @@ public:
|
||||
checkMetrics(*this, env, 4, 6, 4, 3);
|
||||
|
||||
{
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3220,7 +3222,8 @@ public:
|
||||
checkMetrics(*this, env, 1, 8, 5, 4);
|
||||
|
||||
{
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3284,7 +3287,8 @@ public:
|
||||
checkMetrics(*this, env, 1, 8, 5, 4);
|
||||
|
||||
{
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -3352,7 +3356,7 @@ public:
|
||||
|
||||
{
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", prevLedgerWithQueue);
|
||||
env.rpc("json", "account_info", to_string(prevLedgerWithQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
RPC::contains_error(info[jss::result]));
|
||||
@@ -3364,7 +3368,8 @@ public:
|
||||
checkMetrics(*this, env, 0, 10, 0, 5);
|
||||
|
||||
{
|
||||
auto const info = env.rpc("json", "account_info", withQueue);
|
||||
auto const info =
|
||||
env.rpc("json", "account_info", to_string(withQueue));
|
||||
BEAST_EXPECT(
|
||||
info.isMember(jss::result) &&
|
||||
info[jss::result].isMember(jss::account_data));
|
||||
@@ -4575,7 +4580,7 @@ public:
|
||||
env(noop(alice),
|
||||
seq(seqAlice++),
|
||||
fee(--feeDrops),
|
||||
json(R"({"LastLedgerSequence": 7})"),
|
||||
last_ledger_seq(7),
|
||||
ter(terQUEUED));
|
||||
env(noop(alice), seq(seqAlice++), fee(--feeDrops), ter(terQUEUED));
|
||||
env(noop(alice), seq(seqAlice++), fee(--feeDrops), ter(terQUEUED));
|
||||
@@ -4585,7 +4590,7 @@ public:
|
||||
// The drop penalty works a little differently with tickets.
|
||||
env(noop(bob),
|
||||
ticket::use(bobTicketSeq + 0),
|
||||
json(R"({"LastLedgerSequence": 7})"),
|
||||
last_ledger_seq(7),
|
||||
ter(terQUEUED));
|
||||
env(noop(bob),
|
||||
ticket::use(bobTicketSeq + 1),
|
||||
|
||||
@@ -205,7 +205,7 @@ private:
|
||||
NetClock::time_point const expires2 =
|
||||
effective2 + cfg.expiresFromNow;
|
||||
item.server = make_TrustedPublisherServer(
|
||||
env.app().getIOContext(),
|
||||
env.app().getIOService(),
|
||||
item.list,
|
||||
expires,
|
||||
{{effective2, expires2}},
|
||||
|
||||
+722
-174
File diff suppressed because it is too large.
Load diff
@@ -45,13 +45,13 @@ public:
|
||||
std::string const& normal = "")
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
Address const result{boost::asio::ip::make_address(s, ec)};
|
||||
Address const result{Address::from_string(s, ec)};
|
||||
if (!BEAST_EXPECTS(!ec, ec.message()))
|
||||
return;
|
||||
if (!BEAST_EXPECTS(result.is_v4(), s + " not v4"))
|
||||
return;
|
||||
if (!BEAST_EXPECTS(
|
||||
result.to_v4().to_uint() == value, s + " value mismatch"))
|
||||
result.to_v4().to_ulong() == value, s + " value mismatch"))
|
||||
return;
|
||||
BEAST_EXPECTS(
|
||||
result.to_string() == (normal.empty() ? s : normal),
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
failParseAddr(std::string const& s)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
auto a = boost::asio::ip::make_address(s, ec);
|
||||
auto a = Address::from_string(s, ec);
|
||||
BEAST_EXPECTS(ec, s + " parses as " + a.to_string());
|
||||
}
|
||||
|
||||
@@ -71,24 +71,24 @@ public:
|
||||
{
|
||||
testcase("AddressV4");
|
||||
|
||||
BEAST_EXPECT(AddressV4{}.to_uint() == 0);
|
||||
BEAST_EXPECT(AddressV4{}.to_ulong() == 0);
|
||||
BEAST_EXPECT(is_unspecified(AddressV4{}));
|
||||
BEAST_EXPECT(AddressV4{0x01020304}.to_uint() == 0x01020304);
|
||||
BEAST_EXPECT(AddressV4{0x01020304}.to_ulong() == 0x01020304);
|
||||
|
||||
{
|
||||
AddressV4::bytes_type d = {{1, 2, 3, 4}};
|
||||
BEAST_EXPECT(AddressV4{d}.to_uint() == 0x01020304);
|
||||
BEAST_EXPECT(AddressV4{d}.to_ulong() == 0x01020304);
|
||||
|
||||
unexpected(is_unspecified(AddressV4{d}));
|
||||
}
|
||||
|
||||
AddressV4 const v1{1};
|
||||
BEAST_EXPECT(AddressV4{v1}.to_uint() == 1);
|
||||
BEAST_EXPECT(AddressV4{v1}.to_ulong() == 1);
|
||||
|
||||
{
|
||||
AddressV4 v;
|
||||
v = v1;
|
||||
BEAST_EXPECT(v.to_uint() == v1.to_uint());
|
||||
BEAST_EXPECT(v.to_ulong() == v1.to_ulong());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
d[2] = 3;
|
||||
d[3] = 4;
|
||||
v = AddressV4{d};
|
||||
BEAST_EXPECT(v.to_uint() == 0x01020304);
|
||||
BEAST_EXPECT(v.to_ulong() == 0x01020304);
|
||||
}
|
||||
|
||||
BEAST_EXPECT(AddressV4(0x01020304).to_string() == "1.2.3.4");
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
testcase("Address");
|
||||
|
||||
boost::system::error_code ec;
|
||||
Address result{boost::asio::ip::make_address("1.2.3.4", ec)};
|
||||
Address result{Address::from_string("1.2.3.4", ec)};
|
||||
AddressV4::bytes_type d = {{1, 2, 3, 4}};
|
||||
BEAST_EXPECT(!ec);
|
||||
BEAST_EXPECT(result.is_v4() && result.to_v4() == AddressV4{d});
|
||||
@@ -263,10 +263,7 @@ public:
|
||||
BEAST_EXPECT(is_loopback(ep));
|
||||
BEAST_EXPECT(to_string(ep) == "127.0.0.1:80");
|
||||
// same address as v4 mapped in ipv6
|
||||
ep = Endpoint(
|
||||
boost::asio::ip::make_address_v6(
|
||||
boost::asio::ip::v4_mapped, AddressV4{d}),
|
||||
80);
|
||||
ep = Endpoint(AddressV6::v4_mapped(AddressV4{d}), 80);
|
||||
BEAST_EXPECT(!is_unspecified(ep));
|
||||
BEAST_EXPECT(!is_public(ep));
|
||||
BEAST_EXPECT(is_private(ep));
|
||||
@@ -284,11 +281,8 @@ public:
|
||||
BEAST_EXPECT(!is_loopback(ep));
|
||||
BEAST_EXPECT(to_string(ep) == "10.0.0.1");
|
||||
// same address as v4 mapped in ipv6
|
||||
ep = Endpoint(boost::asio::ip::make_address_v6(
|
||||
boost::asio::ip::v4_mapped, AddressV4{d}));
|
||||
BEAST_EXPECT(
|
||||
get_class(boost::asio::ip::make_address_v4(
|
||||
boost::asio::ip::v4_mapped, ep.to_v6())) == 'A');
|
||||
ep = Endpoint(AddressV6::v4_mapped(AddressV4{d}));
|
||||
BEAST_EXPECT(get_class(ep.to_v6().to_v4()) == 'A');
|
||||
BEAST_EXPECT(!is_unspecified(ep));
|
||||
BEAST_EXPECT(!is_public(ep));
|
||||
BEAST_EXPECT(is_private(ep));
|
||||
@@ -305,8 +299,7 @@ public:
|
||||
BEAST_EXPECT(!is_loopback(ep));
|
||||
BEAST_EXPECT(to_string(ep) == "166.78.151.147");
|
||||
// same address as v4 mapped in ipv6
|
||||
ep = Endpoint(boost::asio::ip::make_address_v6(
|
||||
boost::asio::ip::v4_mapped, AddressV4{d}));
|
||||
ep = Endpoint(AddressV6::v4_mapped(AddressV4{d}));
|
||||
BEAST_EXPECT(!is_unspecified(ep));
|
||||
BEAST_EXPECT(is_public(ep));
|
||||
BEAST_EXPECT(!is_private(ep));
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/executor_work_guard.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
@@ -61,10 +60,8 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
measure_asio_timers(duration interval = 100ms, size_t num_samples = 50)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
boost::asio::io_context ios;
|
||||
std::optional<boost::asio::executor_work_guard<
|
||||
boost::asio::io_context::executor_type>>
|
||||
work{boost::asio::make_work_guard(ios)};
|
||||
boost::asio::io_service ios;
|
||||
std::optional<boost::asio::io_service::work> work{ios};
|
||||
std::thread worker{[&] { ios.run(); }};
|
||||
boost::asio::basic_waitable_timer<Clock> timer{ios};
|
||||
elapsed_times_.reserve(num_samples);
|
||||
@@ -138,7 +135,7 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
|
||||
test_sampler(
|
||||
std::chrono::milliseconds interval,
|
||||
boost::asio::io_context& ios)
|
||||
boost::asio::io_service& ios)
|
||||
: probe_(interval, ios)
|
||||
{
|
||||
}
|
||||
@@ -167,9 +164,9 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
{
|
||||
testcase << "sample one";
|
||||
boost::system::error_code ec;
|
||||
test_sampler io_probe{100ms, get_io_context()};
|
||||
test_sampler io_probe{100ms, get_io_service()};
|
||||
io_probe.start_one();
|
||||
MyTimer timer{get_io_context(), 1s};
|
||||
MyTimer timer{get_io_service(), 1s};
|
||||
timer.async_wait(yield[ec]);
|
||||
if (!BEAST_EXPECTS(!ec, ec.message()))
|
||||
return;
|
||||
@@ -201,9 +198,9 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
duration_cast<milliseconds>(probe_duration).count()) /
|
||||
static_cast<size_t>(tt.getMean<milliseconds>());
|
||||
#endif
|
||||
test_sampler io_probe{interval, get_io_context()};
|
||||
test_sampler io_probe{interval, get_io_service()};
|
||||
io_probe.start();
|
||||
MyTimer timer{get_io_context(), probe_duration};
|
||||
MyTimer timer{get_io_service(), probe_duration};
|
||||
timer.async_wait(yield[ec]);
|
||||
if (!BEAST_EXPECTS(!ec, ec.message()))
|
||||
return;
|
||||
@@ -215,7 +212,7 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
io_probe.probe_.cancel_async();
|
||||
// wait again in order to flush the remaining
|
||||
// probes from the work queue
|
||||
timer.expires_after(1s);
|
||||
timer.expires_from_now(1s);
|
||||
timer.async_wait(yield[ec]);
|
||||
}
|
||||
|
||||
@@ -223,7 +220,7 @@ class io_latency_probe_test : public beast::unit_test::suite,
|
||||
testCanceled(boost::asio::yield_context& yield)
|
||||
{
|
||||
testcase << "canceled";
|
||||
test_sampler io_probe{100ms, get_io_context()};
|
||||
test_sampler io_probe{100ms, get_io_service()};
|
||||
io_probe.probe_.cancel_async();
|
||||
except<std::logic_error>([&io_probe]() { io_probe.start_one(); });
|
||||
except<std::logic_error>([&io_probe]() { io_probe.start(); });
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <test/json/TestOutputSuite.h>
|
||||
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/json/Writer.h>
|
||||
|
||||
namespace Json {
|
||||
|
||||
class JsonWriter_test : public ripple::test::TestOutputSuite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testTrivial()
|
||||
{
|
||||
setup("trivial");
|
||||
BEAST_EXPECT(output_.empty());
|
||||
expectResult("");
|
||||
}
|
||||
|
||||
void
|
||||
testNearTrivial()
|
||||
{
|
||||
setup("near trivial");
|
||||
BEAST_EXPECT(output_.empty());
|
||||
writer_->output(0);
|
||||
expectResult("0");
|
||||
}
|
||||
|
||||
void
|
||||
testPrimitives()
|
||||
{
|
||||
setup("true");
|
||||
writer_->output(true);
|
||||
expectResult("true");
|
||||
|
||||
setup("false");
|
||||
writer_->output(false);
|
||||
expectResult("false");
|
||||
|
||||
setup("23");
|
||||
writer_->output(23);
|
||||
expectResult("23");
|
||||
|
||||
setup("23.0");
|
||||
writer_->output(23.0);
|
||||
expectResult("23.0");
|
||||
|
||||
setup("23.5");
|
||||
writer_->output(23.5);
|
||||
expectResult("23.5");
|
||||
|
||||
setup("a string");
|
||||
writer_->output("a string");
|
||||
expectResult("\"a string\"");
|
||||
|
||||
setup("nullptr");
|
||||
writer_->output(nullptr);
|
||||
expectResult("null");
|
||||
}
|
||||
|
||||
void
|
||||
testEmpty()
|
||||
{
|
||||
setup("empty array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->finish();
|
||||
expectResult("[]");
|
||||
|
||||
setup("empty object");
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->finish();
|
||||
expectResult("{}");
|
||||
}
|
||||
|
||||
void
|
||||
testEscaping()
|
||||
{
|
||||
setup("backslash");
|
||||
writer_->output("\\");
|
||||
expectResult("\"\\\\\"");
|
||||
|
||||
setup("quote");
|
||||
writer_->output("\"");
|
||||
expectResult("\"\\\"\"");
|
||||
|
||||
setup("backslash and quote");
|
||||
writer_->output("\\\"");
|
||||
expectResult("\"\\\\\\\"\"");
|
||||
|
||||
setup("escape embedded");
|
||||
writer_->output("this contains a \\ in the middle of it.");
|
||||
expectResult("\"this contains a \\\\ in the middle of it.\"");
|
||||
|
||||
setup("remaining escapes");
|
||||
writer_->output("\b\f\n\r\t");
|
||||
expectResult("\"\\b\\f\\n\\r\\t\"");
|
||||
}
|
||||
|
||||
void
|
||||
testArray()
|
||||
{
|
||||
setup("empty array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->append(12);
|
||||
writer_->finish();
|
||||
expectResult("[12]");
|
||||
}
|
||||
|
||||
void
|
||||
testLongArray()
|
||||
{
|
||||
setup("long array");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->append(12);
|
||||
writer_->append(true);
|
||||
writer_->append("hello");
|
||||
writer_->finish();
|
||||
expectResult("[12,true,\"hello\"]");
|
||||
}
|
||||
|
||||
void
|
||||
testEmbeddedArraySimple()
|
||||
{
|
||||
setup("embedded array simple");
|
||||
writer_->startRoot(Writer::array);
|
||||
writer_->startAppend(Writer::array);
|
||||
writer_->finish();
|
||||
writer_->finish();
|
||||
expectResult("[[]]");
|
||||
}
|
||||
|
||||
void
|
||||
testObject()
|
||||
{
|
||||
setup("object");
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->set("hello", "world");
|
||||
writer_->finish();
|
||||
|
||||
expectResult("{\"hello\":\"world\"}");
|
||||
}
|
||||
|
||||
void
|
||||
testComplexObject()
|
||||
{
|
||||
setup("complex object");
|
||||
writer_->startRoot(Writer::object);
|
||||
|
||||
writer_->set("hello", "world");
|
||||
writer_->startSet(Writer::array, "array");
|
||||
|
||||
writer_->append(true);
|
||||
writer_->append(12);
|
||||
writer_->startAppend(Writer::array);
|
||||
writer_->startAppend(Writer::object);
|
||||
writer_->set("goodbye", "cruel world.");
|
||||
writer_->startSet(Writer::array, "subarray");
|
||||
writer_->append(23.5);
|
||||
writer_->finishAll();
|
||||
|
||||
expectResult(
|
||||
"{\"hello\":\"world\",\"array\":[true,12,"
|
||||
"[{\"goodbye\":\"cruel world.\","
|
||||
"\"subarray\":[23.5]}]]}");
|
||||
}
|
||||
|
||||
void
|
||||
testJson()
|
||||
{
|
||||
setup("object");
|
||||
Json::Value value(Json::objectValue);
|
||||
value["foo"] = 23;
|
||||
writer_->startRoot(Writer::object);
|
||||
writer_->set("hello", value);
|
||||
writer_->finish();
|
||||
|
||||
expectResult("{\"hello\":{\"foo\":23}}");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testTrivial();
|
||||
testNearTrivial();
|
||||
testPrimitives();
|
||||
testEmpty();
|
||||
testEscaping();
|
||||
testArray();
|
||||
testLongArray();
|
||||
testEmbeddedArraySimple();
|
||||
testObject();
|
||||
testComplexObject();
|
||||
testJson();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(JsonWriter, json, ripple);
|
||||
|
||||
} // namespace Json
|
||||
File diff suppressed because it is too large.
Load diff
@@ -39,6 +39,7 @@
|
||||
#include <test/jtx/delivermin.h>
|
||||
#include <test/jtx/deposit.h>
|
||||
#include <test/jtx/did.h>
|
||||
#include <test/jtx/directory.h>
|
||||
#include <test/jtx/domain.h>
|
||||
#include <test/jtx/escrow.h>
|
||||
#include <test/jtx/fee.h>
|
||||
|
||||
@@ -502,6 +502,7 @@ expectLedgerEntryRoot(
|
||||
|
||||
/* Payment Channel */
|
||||
/******************************************************************************/
|
||||
namespace paychan {
|
||||
|
||||
Json::Value
|
||||
create(
|
||||
@@ -561,6 +562,8 @@ channelBalance(ReadView const& view, uint256 const& chan);
|
||||
bool
|
||||
channelExists(ReadView const& view, uint256 const& chan);
|
||||
|
||||
} // namespace paychan
|
||||
|
||||
/* Crossing Limits */
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ public:
|
||||
bool immediateStart = true,
|
||||
int sequence = 1)
|
||||
: sock_{ioc}
|
||||
, ep_{boost::asio::ip::make_address(
|
||||
, ep_{beast::IP::Address::from_string(
|
||||
ripple::test::getEnvLocalhostAddr()),
|
||||
// 0 means let OS pick the port based on what's available
|
||||
0}
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
acceptor_.set_option(
|
||||
boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
|
||||
acceptor_.bind(ep_);
|
||||
acceptor_.listen(boost::asio::socket_base::max_listen_connections);
|
||||
acceptor_.listen(boost::asio::socket_base::max_connections);
|
||||
acceptor_.async_accept(
|
||||
sock_,
|
||||
[wp = std::weak_ptr<TrustedPublisherServer>{shared_from_this()}](
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2025 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TEST_JTX_DIRECTORY_H_INCLUDED
|
||||
#define RIPPLE_TEST_JTX_DIRECTORY_H_INCLUDED
|
||||
|
||||
#include <test/jtx/Env.h>
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace ripple::test::jtx {
|
||||
|
||||
/** Directory operations. */
|
||||
namespace directory {
|
||||
|
||||
enum Error {
|
||||
DirectoryRootNotFound,
|
||||
DirectoryTooSmall,
|
||||
DirectoryPageDuplicate,
|
||||
DirectoryPageNotFound,
|
||||
InvalidLastPage,
|
||||
AdjustmentError
|
||||
};
|
||||
|
||||
/// Move the position of the last page in the user's directory on open ledger to
|
||||
/// newLastPage. Requirements:
|
||||
/// - directory must have at least two pages (root and one more)
|
||||
/// - adjust should be used to update owner nodes of the objects affected
|
||||
/// - newLastPage must be greater than index of the last page in the directory
|
||||
///
|
||||
/// Use this to test tecDIR_FULL errors in open ledger.
|
||||
/// NOTE: effects will be DISCARDED on env.close()
|
||||
auto
|
||||
bumpLastPage(
|
||||
Env& env,
|
||||
std::uint64_t newLastPage,
|
||||
Keylet directory,
|
||||
std::function<bool(ApplyView&, uint256, std::uint64_t)> adjust)
|
||||
-> Expected<void, Error>;
|
||||
|
||||
/// Implementation of adjust for the most common ledger entry, i.e. one where
|
||||
/// page index is stored in sfOwnerNode (and only there). Pass this function
|
||||
/// to bumpLastPage if the last page of directory has only objects
|
||||
/// of this kind (e.g. ticket, DID, offer, deposit preauth, MPToken etc.)
|
||||
bool
|
||||
adjustOwnerNode(ApplyView& view, uint256 key, std::uint64_t page);
|
||||
|
||||
inline auto
|
||||
maximumPageIndex(Env const& env) -> std::uint64_t
|
||||
{
|
||||
if (env.enabled(fixDirectoryLimit))
|
||||
return std::numeric_limits<std::uint64_t>::max();
|
||||
return dirNodeMaxPages - 1;
|
||||
}
|
||||
|
||||
} // namespace directory
|
||||
|
||||
} // namespace ripple::test::jtx
|
||||
|
||||
#endif
|
||||
Loaded 100 of 235 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user